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.

2288 lines
68 KiB

  1. PAGE ,132
  2. TITLE DXBOOT.ASM -- Dos Extender Startup Code
  3. ; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
  4. ;****************************************************************
  5. ;* *
  6. ;* DXBOOT.ASM - Dos Extender Startup Code *
  7. ;* *
  8. ;****************************************************************
  9. ;* *
  10. ;* Module Description: *
  11. ;* *
  12. ;* This module contains real mode initialization code that *
  13. ;* initializes the dos extender itself. This includes *
  14. ;* allocating and initializing the descriptor tables, and *
  15. ;* relocating the dos extender for protected mode operation. *
  16. ;* *
  17. ;****************************************************************
  18. ;* Revision History: *
  19. ;* *
  20. ;* 01/29/92 mattfe Build for MIPS *
  21. ;* 12/19/90 amitc NetHeapSize default made 4k from 8k *
  22. ;* 12/03/90 amitc Added support for 'Win30CommDriver' switch *
  23. ; in system.ini *
  24. ;* 10/09/90 earleh split LDT from GDT and reduced XMS handles *
  25. ;* needed to boot program to 1 *
  26. ;* 08/08/90 earleh DOSX and client privilege ring determined *
  27. ;* by equate in pmdefs.inc *
  28. ;* 05/07/90 jimmat Started VCPI related changes. *
  29. ;* 04/09/90 jimmat Detect if on 286 & 287 installed. *
  30. ;* 04/02/90 jimmat Added PM Int 70h handler. *
  31. ;* 09/27/89 jimmat Changes to use FindFile to locate child *
  32. ;* program. *
  33. ;* 08/29/89 jimmat Now hooks real mode Int 2Fh chain. *
  34. ;* 08/20/89 jimmat Removed A20 code since HIMEM version 2.07 *
  35. ;* now works properly across processor resets. *
  36. ;* 07/28/89 jimmat Int PM Int 30h & 41h to be ignored, not *
  37. ;* reflected to real mode. *
  38. ;* 07/14/89 jimmat Added call to EMMDisable *
  39. ;* 06/16/89 jimmat Ifdef'd combined DOSX/child .EXE code *
  40. ;* 05/22/89 jimmat Added Int 13h/25h/26h/67h hooks. *
  41. ;* 05/18/89 jimmat Added setting of real mode Int 30h hook. *
  42. ;* 03/31/89 jimmat Added Priv Level to selectors during *
  43. ;* relocation and removed some dead code. *
  44. ;* 03/15/89 jimmat Added INT 31h hook *
  45. ;* 03/11/89 jimmat Added support for TSS & LDT & ring 1 *
  46. ;* 03/07/89 jimmat Converted to use WDEB386 debugger *
  47. ;* 02/25/89 (GeneA): added support for combined exe file where *
  48. ;* the Dos Extender and the child reside in the same exe *
  49. ;* file. *
  50. ;* 02/17/89 (GeneA): fixed error handling code during init. *
  51. ;* 02/14/89 (GeneA): added initialization of INT15h vector, *
  52. ;* and changed segment limit of BIOS_CODE segment to *
  53. ;* 64k. *
  54. ;* 02/14/89 (GeneA): added code to copy protected mode code *
  55. ;* segment up into extended memory. Also code to allocate *
  56. ;* and copy GDT and IDT in extended memory. *
  57. ;* 01/31/89 (GeneA): reorganization of code. This module now *
  58. ;* contains only code for initializing the Dos Extender *
  59. ;* itself. *
  60. ;* 01/25/89 (GeneA): moved code for loading and relocating *
  61. ;* the child program here from dxinit.asm *
  62. ;* 01/24/89 (Genea): removed routines for hooking into real *
  63. ;* mode int 2Fh. (part of removing real mode int 2Fh *
  64. ;* interface from the dos extender). *
  65. ;* 12/13/88 (GeneA): created by moving code from DXINIT.ASM *
  66. ;* *
  67. ;****************************************************************
  68. .286p
  69. .287
  70. ; -------------------------------------------------------
  71. ; INCLUDE FILE DEFINITIONS
  72. ; -------------------------------------------------------
  73. .xlist
  74. .sall
  75. include segdefs.inc
  76. include gendefs.inc
  77. include pmdefs.inc
  78. include dpmi.inc
  79. ifdef WOW_x86
  80. include vdmtib.inc
  81. endif
  82. include intmac.inc
  83. include dbgsvc.inc
  84. .list
  85. ; -------------------------------------------------------
  86. ; GENERAL SYMBOL DEFINITIONS
  87. ; -------------------------------------------------------
  88. ;
  89. ; This structure defines the format of the EXE file header.
  90. EXEHDR struc
  91. idExeFile dw ? ;magic number to identify EXE file
  92. cbLastPage dw ? ;number of bytes in last page of the file
  93. crgbFileLen dw ? ;number of 512 byte pages in the file
  94. clpRelocLen dw ? ;number of relocation entries in the table
  95. cparHdrSize dw ? ;number of 16 byte paragraphs in header
  96. cparMinAlloc dw ?
  97. cparMaxAlloc dw ?
  98. segStackInit dw ? ;initial stack segment
  99. offStackInit dw ? ;initial stack pointer
  100. wCheckSum dw ?
  101. offCodeInit dw ? ;initial program counter
  102. segCodeInit dw ? ;initial code segment
  103. wRelocOffset dw ? ;byte offset of relocation table
  104. idOverlay dw ? ;overlay number
  105. EXEHDR ends
  106. ;
  107. ; This structure defines the parameter block to the XMS driver block
  108. ; move function.
  109. XMSMOVE struc
  110. cbxmsLen dd ? ;length of memory block
  111. hxmsSource dw ? ;XMS source block handle
  112. oxmsSource dd ? ;source offset
  113. hxmsDest dw ? ;XMS destination block handle
  114. oxmsDest dd ? ;destination offset
  115. XMSMOVE ends
  116. NOP_OPCODE equ 090h ; NO-OP opcode
  117. IRET_OPCODE equ 0CFh ; IRET opcode
  118. FAR_JMP_OPCODE equ 0EAh ; JMP FAR opcode
  119. SHORT_JMP_OPCODE equ 0EBh ; JMP SHORT opcode
  120. ; -------------------------------------------------------
  121. ; EXTERNAL SYMBOL DEFINITIONS
  122. ; -------------------------------------------------------
  123. extrn PMIntr31:NEAR
  124. extrn PMIntr13:NEAR
  125. extrn PMIntr19:NEAR
  126. extrn PMIntr28:NEAR
  127. extrn PMIntr25:NEAR
  128. extrn PMIntr26:NEAR
  129. extrn PMIntr4B:NEAR
  130. extrn PMIntrDos:NEAR
  131. extrn PMIntrMisc:NEAR
  132. extrn PMIntrVideo:NEAR
  133. extrn PMIntrMouse:NEAR
  134. extrn PMIntrIgnore:NEAR
  135. extrn PMIntrEntryVector:NEAR
  136. extrn PMFaultEntryVector:NEAR
  137. extrn ReadINIFile:NEAR
  138. ifdef NEC_98 ;
  139. extrn PMIntrSound:NEAR ; for Sound Bios
  140. extrn PMIntrExDos:NEAR ; for Extend Dos Function
  141. extrn PMIntr11dummy:NEAR
  142. extrn PMIntrPrinter:NEAR
  143. extrn PMIntrCalTi:NEAR
  144. extrn PMIntrGraph:NEAR
  145. endif ;NEC_98 ;
  146. extrn EMMDisable:NEAR
  147. extrn FindFIle:NEAR
  148. ifdef WOW_x86
  149. extrn NpxExceptionHandler:near
  150. extrn EndNpxExceptionHandler:near
  151. endif
  152. extrn RmUnsimulateProc:FAR
  153. extrn PmUnsimulateProc:FAR
  154. extrn PMFaultHandlerIRET:NEAR
  155. extrn PMFaultHandlerIRETD:NEAR
  156. extrn PMIntHandlerIRET:NEAR
  157. extrn PMIntHandlerIRETD:NEAR
  158. extrn PMDosxIret:NEAR
  159. extrn PMDosxIretd:NEAR
  160. extrn RMCallBackBop:FAR
  161. extrn RMtoPMReflector:FAR
  162. extrn RmSaveRestoreState:far
  163. extrn PmSaveRestoreState:far
  164. extrn RmRawModeSwitch:far
  165. extrn PmRawModeSwitch:far
  166. extrn DPMI_MsDos_API:far
  167. extrn VCD_PM_Svc_Call:far
  168. extrn XmsControl:far
  169. extrn HungAppExit:far
  170. DXPMCODE segment
  171. extrn CodeEndPM:NEAR
  172. externFP NSetSegmentDscr
  173. DXPMCODE ends
  174. ; -------------------------------------------------------
  175. ; DATA SEGMENT DEFINITIONS
  176. ; -------------------------------------------------------
  177. DXDATA segment
  178. extrn selGDT:WORD
  179. extrn segGDT:WORD
  180. extrn selIDT:WORD
  181. extrn segIDT:WORD
  182. extrn bpGDT:FWORD
  183. extrn bpIDT:FWORD
  184. extrn sysTSS:WORD
  185. extrn segPSP:WORD
  186. extrn selPSP:WORD
  187. extrn hmemDOSX:WORD
  188. extrn f286_287:BYTE
  189. extrn bpRmIVT:FWORD
  190. extrn fhExeFile:WORD
  191. extrn idCpuType:WORD
  192. extrn cdscGDTMax:WORD
  193. extrn rgbXfrBuf0:BYTE
  194. extrn rgbXfrBuf1:BYTE
  195. extrn clpRelocItem:WORD
  196. extrn plpRelocItem:WORD
  197. extrn lpfnXMSFunc:DWORD
  198. ifdef NEC_98 ;
  199. extrn fPCH98:BYTE ; PC-H98 flag
  200. extrn fNHmode:BYTE ; NHmode flag
  201. endif ;NEC_98 ;
  202. extrn lpfnUserMouseHandler:DWORD
  203. extrn fUsingHMA:BYTE
  204. ifdef WOW_x86
  205. extrn rgwWowStack:word
  206. extrn FastBop:fword
  207. endif
  208. extrn pbHwIntrStack:word
  209. IFNDEF WOW_x86
  210. extrn IretBopTable:BYTE
  211. ENDIF
  212. public fDebug
  213. fDebug db 0
  214. szModName db 'DOSX',0 ;Our module name for use by WDEB386
  215. if DEBUG
  216. public lpchFileName
  217. lpchFileName dd ?
  218. endif
  219. INIFileName db 'SYSTEM.INI',0 ;.INI file to read
  220. public NetHeapSize, Int28Filter
  221. INIKeywords label byte
  222. db '[standard]',0
  223. db 'netheapsize',0
  224. NetHeapSize dw 4 ;default is 8k
  225. db 'int28filter',0
  226. Int28Filter dw 10 ;default is every 10th
  227. if DEBUG ;------------------------------------------------------------
  228. public fTraceDOS
  229. db 'tracedos',0
  230. fTraceDOS dw 0
  231. public fTraceFault
  232. db 'tracefault',0
  233. fTraceFault dw 0
  234. public fTraceA20
  235. db 'tracea20',0
  236. fTraceA20 dw 1
  237. public TrapDOS
  238. db 'trapdos',0
  239. TrapDOS dw 0
  240. db 'tableslow',0
  241. fTablesLow dw 0
  242. public fTraceReflect
  243. db 'tracereflect',0
  244. fTraceReflect dw 0
  245. public fTraceMode
  246. db 'tracemode',0
  247. fTraceMode dw 0
  248. endif ;DEBUG --------------------------------------------------------
  249. db 0
  250. szExeExtension db '.exe',0
  251. ; The following set of variables are used when copying our Pmode data
  252. ; structures into a HIMEM-allocated block.
  253. public lmaIDT,lmaGDT,lmaDXPMCODE
  254. CBIDTOFF = 0
  255. CBGDTOFF = CDSCIDTDEFAULT * 8
  256. IFNDEF WOW_x86
  257. CBDXPMCODEOFF = CBGDTOFF + GDT_SIZE
  258. ELSE
  259. ;
  260. ; Since we have no GDT for wow, we do not need space for it.
  261. ;
  262. CBDXPMCODEOFF = CBGDTOFF
  263. ENDIF
  264. CBTABLESIZE = CBDXPMCODEOFF
  265. .errnz CBIDTOFF and 0fh
  266. .errnz CBGDTOFF and 0fh
  267. .errnz CBDXPMCODEOFF and 0fh
  268. lmaIDT dd CBIDTOFF
  269. lmaGDT dd CBGDTOFF
  270. lmaDXPMCODE dd CBDXPMCODEOFF
  271. lmaLDT dd CBDXPMCODEOFF
  272. extrn rgwStack:WORD
  273. DXDATA ends
  274. DXSTACK segment
  275. extrn ResetStack:WORD
  276. DXSTACK ends
  277. ; -------------------------------------------------------
  278. page
  279. ; -------------------------------------------------------
  280. ; CODE SEGMENT VARIABLES
  281. ; -------------------------------------------------------
  282. DXCODE segment
  283. ;************************************************************************
  284. ;
  285. ; REMEMBER... any code segment variables defined in this file
  286. ; will be discarded after initialization.
  287. ;
  288. ;************************************************************************
  289. extrn CodeEnd:NEAR
  290. extrn segDXCode:WORD
  291. extrn segDXData:WORD
  292. extrn selDgroup:WORD
  293. ErrMsg MACRO name
  294. extrn ER_&name:BYTE
  295. ERC_&name equ offset ER_&name
  296. ENDM
  297. ErrMsg CPUTYPE
  298. ErrMsg DXINIT
  299. ErrMsg PROTMODE
  300. ErrMsg NOHIMEM
  301. ErrMsg EXTMEM
  302. ErrMsg NOEXE
  303. extrn RMInt2FHandler:NEAR
  304. extrn PrevInt2FHandler:DWORD
  305. lpfnPrevXMS dd 0
  306. DXCODE ends
  307. DXPMCODE segment
  308. extrn selDgroupPM:WORD
  309. extrn segDXCodePM:WORD
  310. extrn segDXDataPM:WORD
  311. DXPMCODE ends
  312. ; -------------------------------------------------------
  313. page
  314. DXCODE segment
  315. assume cs:DXCODE
  316. ; -------------------------------------------------------
  317. ; MAIN INITIALIZATION ROUTINES
  318. ; -------------------------------------------------------
  319. ; InitDosExtender -- This routine is the executive
  320. ; for initializing the dos extender.
  321. ;
  322. ; Input: none
  323. ; Output: various global tables and variables initialized.
  324. ; Dos Extender relocated for protected mode execution
  325. ; and moved into extended memory.
  326. ; Errors: returns CY set if error occurs, pointer to error message
  327. ; in DX
  328. ; Uses:
  329. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  330. public InitDosExtender
  331. InitDosExtender:
  332. ; Init the key code & data segment variables.
  333. mov ax,cs
  334. mov segDXCode,ax
  335. mov ax,ds
  336. mov segDXData,ax
  337. mov selDgroup,ax
  338. push es
  339. mov ax,seg DXPMCODE
  340. mov es,ax
  341. assume es:DXPMCODE
  342. mov selDgroupPM,SEL_DXDATA or STD_RING
  343. mov segDXCodePM,cs
  344. mov segDXDataPM,ds
  345. pop es
  346. assume es:DGROUP
  347. ; Do an initial shrink of our program memory. This assumes that DXPMCODE
  348. ; is the last segment in program.
  349. mov bx,(offset DXPMCODE:CodeEndPM) + 10h
  350. shr bx,4
  351. add bx,seg DXPMCODE
  352. sub bx,segPSP
  353. mov es,segPSP
  354. dossvc 4Ah
  355. push ds
  356. pop es
  357. ; Determine the type of CPU we are running on and make sure it is
  358. ; at least an 80286.
  359. call CheckCPUType
  360. cmp ax,2
  361. jae indx14
  362. mov ax,ERC_CPUTYPE
  363. jmp indx80
  364. indx14:
  365. ; If running on a 286, see if there is a 287 coprocessor installed
  366. ifdef NEC_98 ;
  367. ;------------------- 90/08/15 --------------------
  368. ;check N/H at system area BIOS_FLAG(0:501h)
  369. ;if H mode, fNHmode bit on.
  370. push es
  371. push ax
  372. mov ax,0
  373. mov es,ax
  374. test byte ptr es:[501h],8h ;if Hmode
  375. jz not_Hmode
  376. mov fNHmode,0FFh ;Now! Running on Hmode!!! 90/07/07
  377. not_Hmode:
  378. pop ax
  379. pop es
  380. ;------------------- 90/08/15 --------------------
  381. ; If running on a 286, see if there is a 287 coprocessor installed
  382. cmp al,2 ;286 processor?
  383. jnz EMM_Disable
  384. test fNHmode,0FFh
  385. jz Copro_Nmode
  386. ;----- 90/07/04 in -----
  387. ; check co-processor exist at memory-switch
  388. ;----------------- Hmode -----------------
  389. push ds
  390. push bx
  391. ;;;;;;;; mov bx,0Eh
  392. mov bx,0E000h ;90/10/04 bug
  393. mov ds,bx
  394. mov bx,3FEAh
  395. mov al,byte ptr ds:[bx]
  396. pop bx
  397. pop ds
  398. test al,08h ;0=none,1=exists
  399. jmp Coprocessor
  400. Copro_Nmode:
  401. ;----------------- Nmode -----------------
  402. push ds
  403. push bx
  404. ;;;;;;;; mov bx,0Ah
  405. mov bx,0A000h ;90/10/04 bug
  406. mov ds,bx
  407. mov bx,3FEAh
  408. mov al,byte ptr ds:[bx]
  409. pop bx
  410. pop ds
  411. test al,08h ;0=none,1=exists
  412. Coprocessor:
  413. jz EMM_Disable
  414. inc f286_287 ; yup, 286 & 287
  415. EMM_Disable:
  416. else ;NEC_98 ;
  417. cmp al,2 ;286 processor?
  418. jnz @f
  419. int 11h ;math coprocessor installed?
  420. test al,2
  421. jz @f
  422. ifndef WOW_x86
  423. inc f286_287 ; yup, 286 & 287
  424. endif
  425. @@:
  426. endif ;NEC_98 ;
  427. ; If on a 386 or greater, try to disable the EMM drivers we know about
  428. call EMMDisable
  429. ; Check if the machine is already running in protected mode. If so, we
  430. ; can't run.
  431. ifndef WOW_x86
  432. smsw ax
  433. test ax,1 ;check the protected mode bit
  434. jz @f
  435. mov ax,ERC_PROTMODE
  436. jmp indx80
  437. endif
  438. @@:
  439. ; Get the full pathname of our EXE file, it's needed in a couple of places
  440. call GetExeName
  441. jnc @F
  442. mov ax,ERC_DXINIT
  443. jmp indx80
  444. @@:
  445. ; Determine if the real mode Int 28h vector points anywhere. If it doesn't
  446. ; then we don't need to reflect Int 28h calls from protected to real mode.
  447. ; The user can still override this by putting a Int28Filter= entry in
  448. ; SYSTEM.INI.
  449. push es
  450. mov ax,3528h
  451. int 21h
  452. assume es:NOTHING
  453. cmp byte ptr es:[bx],IRET_OPCODE ;Int 28h -> IRET?
  454. jne @f
  455. mov Int28Filter,0 ; yes, don't need to reflect
  456. @@:
  457. pop es
  458. assume es:DGROUP
  459. ; Read SYSTEM.INI for any parameter overrides - NOTE: requires GetExeName
  460. ; having been run first!
  461. mov bx,offset INIKeywords
  462. mov dx,offset INIFileName
  463. call ReadINIFile
  464. ; Check that the HIMEM.SYS driver is installed so that we can use it
  465. ; for extended memory management.
  466. call SetupHimemDriver
  467. jnc @F ; Himem is OK.
  468. mov ax,ERC_NOHIMEM
  469. jmp indx80
  470. @@:
  471. ifdef NEC_98 ;
  472. push es
  473. xor ax, ax
  474. mov es, ax
  475. test byte ptr es:[458h], 80h ; if NESA
  476. jz not_MC
  477. mov fPCH98, 0FFh ; it's a NPC NESA
  478. not_MC:
  479. pop es
  480. assume es:DGROUP
  481. endif ;NEC_98 ;
  482. ; Hook the real mode int vectors
  483. mov ax,352Fh ;get previous Int 2Fh vector
  484. int 21h
  485. assume es:NOTHING
  486. mov word ptr [PrevInt2FHandler],bx
  487. mov word ptr [PrevInt2FHandler+2],es
  488. push ds
  489. pop es
  490. assume es:DGROUP
  491. mov ax,cs ;point to our rMode Int 2Fh
  492. mov ds,ax
  493. assume ds:NOTHING
  494. mov dx,offset DXCODE:RMInt2FHandler
  495. mov ax,252Fh
  496. int 21h
  497. push es
  498. pop ds
  499. assume ds:DGROUP
  500. ; Allocate and initialize the descriptor tables and TSS.
  501. cCall AllocateExtMem
  502. jnc indx20
  503. mov ax,ERC_EXTMEM
  504. jmp indx80
  505. indx20:
  506. push es
  507. push bx
  508. push dx
  509. push di
  510. push si
  511. ;
  512. ; Bop to initialize 32 bit support.
  513. ;
  514. mov di, sp ;original stack offset
  515. push SEL_DXPMCODE OR STD_RING
  516. push offset DXPMCODE:HungAppExit
  517. push SEL_DXPMCODE OR STD_RING
  518. push offset DXPMCODE:XmsControl
  519. push SEL_DXPMCODE OR STD_RING
  520. push offset DXPMCODE:DPMI_MsDos_API
  521. push SEL_DXPMCODE OR STD_RING
  522. push offset DXPMCODE:VCD_PM_Svc_Call
  523. push SEL_DXPMCODE OR STD_RING
  524. push offset DXPMCODE:PmRawModeSwitch
  525. push segDXCode
  526. push offset DXCODE:RmRawModeSwitch
  527. push SEL_DXPMCODE OR STD_RING
  528. push offset DXPMCODE:PmSaveRestoreState
  529. push segDXCode
  530. push offset DXCODE:RmSaveRestoreState
  531. mov bx,cdscGDTMax
  532. shl bx,3
  533. dec bx
  534. push bx ;Initial LDT size
  535. push selGDT
  536. push SEL_DXPMCODE OR STD_RING ;pm reflector seg
  537. push segDXCode
  538. push offset DXCODE:RMtoPMReflector
  539. push segDXCode
  540. push offset DXCODE:RMCallBackBop
  541. push SEL_DXPMCODE OR STD_RING
  542. push offset DXPMCODE:PMDosxIretd
  543. push SEL_DXPMCODE OR STD_RING
  544. push offset DXPMCODE:PMDosxIret
  545. push SEL_DXPMCODE OR STD_RING
  546. push offset DXPMCODE:PMIntHandlerIRETD
  547. push SEL_DXPMCODE OR STD_RING
  548. push offset DXPMCODE:PMIntHandlerIRET
  549. push SEL_DXPMCODE OR STD_RING
  550. push offset DXPMCODE:PMFaultHandlerIRETD
  551. push SEL_DXPMCODE OR STD_RING
  552. push offset DXPMCODE:PMFaultHandlerIRET
  553. push SEL_DXCODE OR STD_RING
  554. push segDXCode
  555. push SEL_DXPMCODE OR STD_RING
  556. push offset DXPMCODE:PmUnsimulateProc
  557. push segDXCode
  558. push offset DXCODE:RmUnsimulateProc
  559. push word ptr CB_STKFRAME
  560. push segDXData
  561. mov si,sp ;pass stack offset
  562. DPMIBOP InitDosxRM
  563. mov sp, di ;restore stack
  564. ifdef WOW_x86
  565. mov word ptr [FastBop],bx
  566. mov word ptr [FastBop + 2],dx
  567. mov word ptr [FastBop + 4],es
  568. endif
  569. pop si
  570. pop di
  571. pop dx
  572. pop bx
  573. pop es
  574. call InitGlobalDscrTable ;set up the GDT
  575. call SendDbgNotification ;tell NTSD about our segments
  576. call InitIntrDscrTable ;set up the IDT
  577. ifndef WOW_x86 ;bugbug
  578. call InitTaskStateSeg ;set up the TSS
  579. endif
  580. if DEBUG
  581. ; DOSX is written such that it does not require any segment fix ups for
  582. ; protected mode operation. This wasn't always the case, and it's easy
  583. ; to make create dependencies so the routine CheckDOSXFixUps exists in
  584. ; the debug version to check for segment fix ups in non-initialization
  585. ; code.
  586. call CheckDOSXFixUps
  587. jnc @F
  588. mov ax,ERC_DXINIT
  589. jmp short indx80
  590. @@:
  591. endif ;DEBUG
  592. ; Move the Extended memory segment up into extended memory.
  593. mov dx,seg DXPMCODE
  594. call MoveDosExtender
  595. jc indx80
  596. ; Move the GDT and IDT up into extended memory.
  597. call MoveDscrTables
  598. ; Parse the command line, and locate the child exe file
  599. call ParseCommandLine
  600. ; Initialized okay!
  601. clc
  602. jmp short indx90
  603. ; Error occured. Free any extended memory blocks allocated and then
  604. ; return the error code.
  605. indx80: push ax ;save the error code
  606. ;
  607. ; If we have allocated an extended memory block, then free it.
  608. ; If we have allocated the HMA, then free it.
  609. ;
  610. mov dx,hmemDOSX
  611. or dx,dx
  612. jz @F
  613. xmssvc 0Dh
  614. xmssvc 0Ah
  615. @@:
  616. cmp fUsingHMA,0
  617. je @F
  618. xmssvc 2
  619. @@:
  620. indxEXIT:
  621. pop ax ;restore the error code
  622. stc ;set error flag
  623. indx90: ret
  624. ; -------------------------------------------------------
  625. ; AllocateExtMem -- Allocates memory used by DOSX for
  626. ; system tables and protected mode
  627. ; code.
  628. ; Allocates a temporary buffer in
  629. ; DOS memory for building the
  630. ; IDT and GDT.
  631. ; Input: none
  632. ; Output: none
  633. ; Uses: Flags
  634. ; Error: Carry set if cannot allocate memory.
  635. ;
  636. ; History:
  637. ; 10/05/90 - earleh wrote it
  638. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  639. cProc AllocateExtMem,<PUBLIC,NEAR>,<ax,bx,dx>
  640. cBegin
  641. ; If there is sufficient XMS memory, increase the size of the GDT/LDT
  642. ; up to the max of 8k selectors.
  643. add word ptr lmaLDT,offset DXPMCODE:CodeEndPM
  644. adc word ptr lmaLDT+2,0
  645. add word ptr lmaLDT,0Fh ;make sure LDT is para aligned
  646. adc word ptr lmaLDT+2,0
  647. and word ptr lmaLDT,0FFF0h
  648. @@:
  649. xmssvc 08h ;Query Free Extended memory
  650. cmp dx,1024 ;is there more than 1 meg available?
  651. jb @f
  652. mov cdscGDTMax,CDSCMAXLDT ; yes, max out the GDT size
  653. @@:
  654. mov ax,cdscGDTMax
  655. xor dx,dx
  656. shl ax,3
  657. adc dx,0
  658. add ax,word ptr lmaLDT
  659. adc dx,word ptr lmaLDT+2
  660. add ax,1023d
  661. adc dx,0 ; DX:AX = total extended memory needed
  662. shl dx,6
  663. shr ax,10d
  664. or dx,ax ; DX = kbytes needed
  665. mov si,dx ; SI = kbytes needed
  666. xmssvc 09h ; allocate the XMS block
  667. or ax,ax
  668. jz axm_error
  669. mov hmemDOSX,dx
  670. xmssvc 0Ch ; lock it, DX:BX = address
  671. or ax,ax
  672. jz axm_error
  673. axm_address:
  674. add word ptr lmaIDT,bx ; relocate tables & Pmode code
  675. adc word ptr lmaIDT+2,dx
  676. add word ptr lmaGDT,bx
  677. adc word ptr lmaGDT+2,dx
  678. add word ptr lmaDXPMCODE,bx
  679. adc word ptr lmaDXPMCODE+2,dx
  680. add word ptr lmaLDT,bx
  681. adc word ptr lmaLDT+2,dx
  682. mov bx,(CDSCIDTDEFAULT + GDT_SELECTORS + 1) shr 1
  683. dossvc 48h ; get a DOS block for building tables
  684. jc axm_error ; abort if error
  685. mov segIDT,ax
  686. mov selIDT,ax
  687. add ax,CDSCIDTDEFAULT shr 1
  688. mov segGDT,ax
  689. mov selGDT,ax
  690. clc
  691. jmp axm_exit
  692. axm_error:
  693. stc
  694. axm_exit:
  695. cEnd
  696. ; -------------------------------------------------------
  697. ; SetupHimemDriver -- This routine checks that an XMS driver
  698. ; is installed and sets up for calling it.
  699. ;
  700. ; Input: none
  701. ; Output: none
  702. ; Errors: returns CY set if no driver available
  703. ; Uses: AX, all other registers preserved
  704. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  705. public SetupHimemDriver
  706. SetupHimemDriver proc near
  707. push bx
  708. push es
  709. ; Check to see if there is an XMS driver resident.
  710. mov ax,4300h
  711. int 2Fh
  712. cmp al,80h
  713. jnz sthd80
  714. ; There is an XMS driver resident, so init for calling it.
  715. mov ax,4310h
  716. int 2Fh
  717. mov word ptr [lpfnXMSFunc],bx
  718. mov word ptr [lpfnXMSFunc+2],es
  719. ; Make sure this is the proper XMS/driver version
  720. xmssvc 0 ;returns XMS vers in ax, driver vers in bx
  721. cmp ax,300h ;assume okay if XMS 3.0 or above
  722. jae @f
  723. cmp ax,200h ;require at least XMS 2.00
  724. jb sthd80
  725. cmp bx,21Ch ;if XMS 2.x, require driver version 2.28+
  726. jb sthd80 ; (himem used to have minor vers in decimal)
  727. @@:
  728. ; Verify that the XMS driver's A20 functions work
  729. xmssvc 5 ;local enable
  730. or ax,ax
  731. jz sthd80
  732. xmssvc 7 ;query A20
  733. push ax
  734. xmssvc 6 ;local disable
  735. or ax,ax
  736. pop ax ;recover query status
  737. jz sthd80
  738. or ax,ax ;should be NZ, (A20 enabled status)
  739. jz sthd80
  740. ; Looks good to me...
  741. clc
  742. jmp short sthd90
  743. ; No XMS driver resident or wrong version or we couldn't enable A20.
  744. sthd80: stc
  745. sthd90: pop es
  746. pop bx
  747. ret
  748. SetupHimemDriver endp
  749. ; -------------------------------------------------------
  750. ; MoveDosExtender -- This routine will move the Dos Extender
  751. ; protected mode segment up into extended memory.
  752. ; The himem driver function for moving memory blocks is used.
  753. ; The parameter block for this function is built in rgbXfrBuf0.
  754. ;
  755. ; Input: DX - real mode segment address of the segment to move
  756. ; Output: none
  757. ; Errors: returns CY set if error, Error code in AX
  758. ; Uses: AX used, all else preserved
  759. ; modifies rgbXfrBuf0
  760. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  761. public MoveDosExtender
  762. MoveDosExtender proc near
  763. push bx
  764. push cx
  765. push dx
  766. push si
  767. cmp fUsingHMA,0
  768. je mvdx40
  769. ;
  770. ; Our extended memory block is actually the HMA. Enable A20 and do
  771. ; the move ourselves.
  772. ;
  773. xmssvc 5 ;local enable
  774. push di
  775. push ds
  776. push es
  777. mov cx,offset DXPMCODE:CodeEndPM
  778. inc cx
  779. and cx,0FFFEh
  780. mov di,CBDXPMCODEOFF+10h
  781. xor si,si
  782. dec si
  783. mov es,si
  784. inc si
  785. mov ds,dx
  786. assume ds:NOTHING
  787. ;
  788. ; DS:SI = segIDT:0
  789. ; ES:DI = 0FFFF:CBDXPMCODEOFF+10h
  790. ; CX = code size
  791. ;
  792. cld
  793. rep movsb
  794. pop es
  795. assume ds:DGROUP
  796. pop ds
  797. pop di
  798. xmssvc 6 ;local disable
  799. jmp mvdx65
  800. mvdx40:
  801. ; Move the data up into extended memory using the XMS driver's function.
  802. mov si,offset DGROUP:rgbXfrBuf0
  803. mov cx,offset DXPMCODE:CodeEndPM
  804. inc cx
  805. and cx,0FFFEh
  806. mov word ptr [si].cbxmsLen,cx
  807. mov word ptr [si].oxmsSource+2,dx ;real mode code segment address
  808. mov ax,hmemDOSX
  809. mov word ptr [si].hxmsDest,ax
  810. xor ax,ax
  811. mov word ptr [si].cbxmsLen+2,ax
  812. mov [si].hxmsSource,ax
  813. mov word ptr [si].oxmsSource,ax
  814. mov word ptr [si].oxmsDest,CBDXPMCODEOFF
  815. mov word ptr [si].oxmsDest+2,ax
  816. xmssvc 0Bh
  817. mvdx65:
  818. clc
  819. jmp short mvdx90
  820. ; Error occured
  821. mvdx80: stc
  822. mvdx90: pop si
  823. pop dx
  824. pop cx
  825. pop bx
  826. ret
  827. MoveDosExtender endp
  828. ; -------------------------------------------------------
  829. ; MoveDscrTables -- This routine will move the GDT
  830. ; and IDT up into extended memory. The himem driver
  831. ; function for moving memory blocks is used. The parameter
  832. ; block for this function is built in rgbXfrBuf0.
  833. ;
  834. ; Input: none
  835. ; Output: none
  836. ; Errors: returns CY set if error occurs. Error code in AX
  837. ; Uses: AX, all else preserved
  838. ; modifies rgbXfrBuf0
  839. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  840. public MoveDscrTables
  841. MoveDscrTables proc near
  842. push bx
  843. push si
  844. push es
  845. cmp fUsingHMA,0
  846. je @F
  847. ;
  848. ; Our extended memory block is actually the HMA. Enable A20 and do
  849. ; the move ourselves.
  850. ;
  851. xmssvc 5 ;local enable
  852. push ds
  853. push di
  854. push cx
  855. mov cx,CBTABLESIZE
  856. mov di,10h
  857. xor si,si
  858. dec si
  859. mov es,si
  860. inc si
  861. mov ds,segIDT
  862. assume ds:NOTHING
  863. ;
  864. ; DS:SI = segIDT:0
  865. ; ES:DI = 0FFFF:10
  866. ; CX = tables size
  867. ;
  868. cld
  869. rep movsb
  870. pop cx
  871. pop di
  872. pop ds
  873. assume ds:DGROUP
  874. xmssvc 6 ;local disable
  875. clc
  876. jmp mvdt_ret
  877. @@:
  878. ; Move the GDT and IDT together.
  879. mov si,offset DGROUP:rgbXfrBuf0
  880. mov word ptr [si].cbxmsLen,CBTABLESIZE
  881. mov word ptr [si].cbxmsLen+2,0
  882. mov ax,segIDT
  883. mov word ptr [si].oxmsSource+2,ax
  884. mov ax,hmemDOSX
  885. mov word ptr [si].hxmsDest,ax
  886. xor ax,ax
  887. mov [si].hxmsSource,ax
  888. mov word ptr [si].oxmsSource,ax
  889. mov word ptr [si].oxmsDest,ax
  890. mov word ptr [si].oxmsDest+2,ax
  891. xmssvc 0Bh
  892. IFDEF WOW
  893. ;
  894. ; Move the initialized selectors from the gdt to the ldt
  895. ;
  896. mov word ptr [si].cbxmsLen,GDT_SIZE
  897. mov word ptr [si].cbxmsLen+2,0
  898. mov ax,segGDT
  899. mov word ptr [si].oxmsSource+2,ax
  900. mov ax,hmemDOSX
  901. mov word ptr [si].hxmsDest,ax
  902. xor ax,ax
  903. mov word ptr [si].hxmsSource,ax
  904. mov word ptr [si].oxmsSource,ax
  905. mov word ptr [si].oxmsDest+2,ax
  906. mov word ptr [si].oxmsDest,CBTABLESIZE + offset DXPMCODE:CodeEndPM
  907. xmssvc 0Bh
  908. ENDIF
  909. mvdt_ret:
  910. mov es,segIDT ;free the low memory copy
  911. dossvc 49h
  912. pop es
  913. pop si
  914. pop bx
  915. ret
  916. MoveDscrTables endp
  917. ; -------------------------------------------------------
  918. ; Send Debugger Notification
  919. SendDbgNotification proc near
  920. IFDEF WOW
  921. ;
  922. ; Send load notification to the debugger for DXDATA
  923. ;
  924. push 1 ; data
  925. push ds ; exe name
  926. push offset EXEC_DXNAME
  927. push ds ; module name
  928. push offset szModName
  929. push 0
  930. push SEL_DXDATA OR STD_RING
  931. push DBG_SEGLOAD
  932. BOP BOP_DEBUGGER
  933. add sp,16
  934. ;
  935. ; Send load notification to the debugger for DXCODE
  936. ;
  937. push 0 ; code
  938. push ds ; exe name
  939. push offset EXEC_DXNAME
  940. push ds ; module name
  941. push offset szModName
  942. push 1
  943. push SEL_DXCODE OR STD_RING
  944. push DBG_SEGLOAD
  945. BOP BOP_DEBUGGER
  946. add sp,16
  947. ;
  948. ; Send load notification to the debugger
  949. ;
  950. push 0 ; code
  951. push ds ; exe name
  952. push offset EXEC_DXNAME
  953. push ds ; module name
  954. push offset szModName
  955. push 2
  956. push SEL_DXPMCODE OR STD_RING
  957. push DBG_SEGLOAD
  958. BOP BOP_DEBUGGER
  959. add sp,16
  960. ENDIF
  961. ret
  962. SendDbgNotification endp
  963. ; -------------------------------------------------------
  964. ; InitGlobalDscrTable -- This function will allocate a memory
  965. ; buffer from DOS and then initialize it as a global
  966. ; descriptor table. It will also initialize all global
  967. ; variables associated with GDT management.
  968. ; Descriptors in the range 0 - SEL_USER are given statically
  969. ; defined meanings. Descriptors from SEL_USER up are defined
  970. ; dynamically when a program is loaded or when dynamic memory
  971. ; management calls occur.
  972. ;
  973. ; NOTE: This routine works in real mode. The buffer where
  974. ; the GDT is built is in low memory.
  975. ;
  976. ; Input: AX - number of descriptors to initialize
  977. ; Output: none
  978. ; Errors: CY set if unable to obtain memory for the GDT
  979. ; Uses: AX used, all other registers preserved
  980. ; bpGDT initialized.
  981. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  982. public InitGlobalDscrTable
  983. InitGlobalDscrTable proc near
  984. push bx
  985. push cx
  986. push dx
  987. push di
  988. push es
  989. mov word ptr [bpGDT+0],GDT_SIZE - 1
  990. mov ax,word ptr lmaGDT
  991. mov word ptr [bpGDT+2],ax
  992. mov ax,word ptr lmaGDT+2
  993. mov word ptr [bpGDT+4],ax
  994. ;
  995. ; Start by initializing the GDT to 0.
  996. ;
  997. mov cx,GDT_SIZE shr 1
  998. mov es,segGDT
  999. assume es:NOTHING
  1000. xor ax,ax
  1001. mov di,ax
  1002. rep stosw
  1003. ; Next, initialize the statically defined descriptors.
  1004. ;
  1005. ; Set up a descriptor for our protected mode code.
  1006. xor ax,ax ;AX = 0
  1007. mov dx,cs ;our code segment paragraph address
  1008. call B_ParaToLinear ;convert to linear byte address
  1009. mov cx,offset CodeEnd
  1010. cCall NSetSegmentDscr,<SEL_DXCODE,bx,dx,ax,cx,STD_CODE>
  1011. ; Set up another one, but ring 0 this time. Limit should be 0FFFFh
  1012. ; or 386 reset to real mode will not work properly.
  1013. mov cx,0FFFFh
  1014. cCall NSetSegmentDscr,<SEL_DXCODE0,bx,dx,ax,cx,ARB_CODE0>
  1015. ;
  1016. ; Set up one for the other segment, and a Ring 0 alias.
  1017. ;
  1018. mov cx,offset CodeEndPM
  1019. mov bx,word ptr lmaDXPMCODE
  1020. mov dx,word ptr lmaDXPMCODE+2
  1021. cCall NSetSegmentDscr,<SEL_DXPMCODE,dx,bx,0,cx,STD_CODE>
  1022. cCall NSetSegmentDscr,<SEL_NBPMCODE,dx,bx,0,cx,STD_CODE>
  1023. ifndef WOW_x86
  1024. cCall NSetSegmentDscr,<SEL_EH,dx,bx,0,cx,EH_CODE>
  1025. else
  1026. cCall NSetSegmentDscr,<SEL_EH,dx,bx,0,cx,STD_CODE>
  1027. endif
  1028. mov cx,0FFFFh
  1029. ; Set up a descriptor for our protected mode data and stack area.
  1030. mov dx,ds ;our data segment paragraph address
  1031. call B_ParaToLinear ;convert to linear byte address
  1032. cCall NSetSegmentDscr,<SEL_DXDATA,bx,dx,ax,cx,STD_DATA>
  1033. IFNDEF WOW_x86
  1034. ; Set up descriptor for IRET HOOKS
  1035. push dx
  1036. push bx
  1037. add dx,offset IretBopTable
  1038. adc bx,0
  1039. cCall NSetSegmentDscr,<SEL_IRETHOOK,bx,dx,ax,cx,STD_CODE>
  1040. pop bx
  1041. pop dx
  1042. ELSE
  1043. ; Set up descriptor for IRET HOOKS
  1044. push dx
  1045. push bx
  1046. add dx,offset FastBop
  1047. adc bx,0
  1048. cCall NSetSegmentDscr,<SEL_IRETHOOK,bx,dx,ax,cx,STD_CODE>
  1049. pop bx
  1050. pop dx
  1051. ENDIF
  1052. IFNDEF WOW_x86
  1053. ; And another one of those for ring 0
  1054. cCall NSetSegmentDscr,<SEL_DXDATA0,bx,dx,ax,cx,ARB_DATA0>
  1055. ENDIF
  1056. ;
  1057. ; Set up descriptors pointing to our PSP and environment.
  1058. mov dx,segPSP ;segment address of the PSP
  1059. call B_ParaToLinear ;convert to linear byte address
  1060. cCall NSetSegmentDscr,<SEL_PSP,bx,dx,ax,cx,STD_DATA>
  1061. mov selPSP,SEL_PSP
  1062. ;
  1063. push es
  1064. mov es,segPSP
  1065. assume es:PSPSEG
  1066. mov dx,segEnviron
  1067. call B_ParaToLinear
  1068. cCall NSetSegmentDscr,<SEL_ENVIRON,bx,dx,ax,7FFFH,STD_DATA>
  1069. pop es
  1070. assume es:nothing
  1071. ; Set up a descriptor that points to the GDT.
  1072. mov dx,word ptr [bpGDT+2] ;get the GDT linear byte address
  1073. mov bx,word ptr [bpGDT+4]
  1074. mov cx,word ptr [bpGDT+0] ;get the GDT segment size
  1075. cCall NSetSegmentDscr,<SEL_GDT,bx,dx,ax,cx,STD_DATA>
  1076. ; Set up a descriptor for the LDT and an LDT data alias.
  1077. mov cx,cdscGDTMax ;get count of descriptors
  1078. shl cx,3
  1079. dec cx
  1080. mov dx,word ptr lmaLDT
  1081. mov bx,word ptr lmaLDT+2
  1082. IFNDEF WOW_x86
  1083. cCall NSetSegmentDscr,<SEL_LDT,bx,dx,ax,cx,STD_LDT>
  1084. ENDIF
  1085. cCall NSetSegmentDscr,<SEL_LDT_ALIAS,bx,dx,ax,cx,STD_DATA>
  1086. ; set up a readonly selector to the LDT for the wow kernel
  1087. cCall NSetSegmentDscr,<SEL_WOW_LDT,bx,dx,ax,cx,STD_DATA>
  1088. ; Set up descriptors pointing to the BIOS code and data areas
  1089. mov cx,0FFFFH ; CX = 0FFFFH
  1090. cCall NSetSegmentDscr,<SEL_BIOSCODE,000fh,ax,ax,cx,STD_CODE>
  1091. mov dx,40h*16
  1092. cCall NSetSegmentDscr,<SEL_BIOSDATA,ax,dx,ax,cx,STD_DATA>
  1093. ; Set up a descriptor pointing to the real mode interrupt vector table.
  1094. cCall NSetSegmentDscr,<SEL_RMIVT,ax,ax,ax,cx,STD_DATA>
  1095. IFNDEF WOW_x86
  1096. ; Setup a selector and data alias for the TSS
  1097. mov dx,ds ;get base address of TSS
  1098. call B_ParaToLinear ; (it may not be para aligned)
  1099. add dx,offset DGROUP:sysTSS
  1100. adc bx,ax
  1101. mov cx,(TYPE TSS286) - 1
  1102. cCall NSetSegmentDscr,<SEL_TSS,bx,dx,ax,cx,STD_TSS>
  1103. cCall NSetSegmentDscr,<SEL_TSS_ALIAS,bx,dx,ax,cx,STD_DATA>
  1104. ENDIF
  1105. ;
  1106. ; Pass address of HwIntr stack, and form pointer to lockcount in
  1107. ; VdmTib. This enables us to coordinate stack switching with
  1108. ; the nt kernel and the monitor. These components will switch
  1109. ; the stack on Hw Interrupt reflection, dosx will switch it
  1110. ; back at iret.
  1111. ;
  1112. push es
  1113. mov ax,SEL_DXDATA or STD_RING
  1114. mov es, ax
  1115. mov bx, pbHwIntrStack
  1116. DPMIBOP InitPmStackInfo
  1117. pop es
  1118. IFDEF WOW_x86
  1119. ;
  1120. ; Create a code selector for the NPX emulation exception handler
  1121. ;
  1122. mov ax,offset EndNpxExceptionHandler
  1123. sub ax,offset NpxExceptionHandler
  1124. mov bx,offset DXPMCODE:NpxExceptionHandler
  1125. add bx,word ptr lmaDXPMCODE
  1126. mov dx,word ptr lmaDXPMCODE + 2
  1127. cCall NSetSegmentDscr,<SEL_NPXHDLR,dx,bx,0,ax,STD_CODE>
  1128. ENDIF
  1129. clc ;worked! make sure CY is clear
  1130. ; All done
  1131. igdt90: pop es
  1132. pop di
  1133. pop dx
  1134. pop cx
  1135. pop bx
  1136. ret
  1137. InitGlobalDscrTable endp
  1138. ; -------------------------------------------------------
  1139. ; InitIntrDscrTable -- This function will initialize the
  1140. ; specified memory buffer as an Interrupt Descriptor Table,
  1141. ; and set up all of the control variables associated with
  1142. ; the IDT.
  1143. ;
  1144. ; NOTE: This routine works in real mode. The buffer where
  1145. ; the IDT is built is in low memory.
  1146. ; NOTE: The InitGlobalDscrTable function must be called before
  1147. ; this function can be called.
  1148. ;
  1149. ; Input: AX - number of descriptors to initialize
  1150. ; Output: none
  1151. ; Errors: CY set if unable to obtain the memory required
  1152. ; Uses: AX, all other registers preserved
  1153. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1154. public InitIntrDscrTable
  1155. InitIntrDscrTable proc near
  1156. push bx
  1157. push cx
  1158. push dx
  1159. push si
  1160. push di
  1161. push es
  1162. ifndef WOW_x86
  1163. ; Save the current pointer to the real mode interrupt vector table.
  1164. sidt fword ptr bpRmIVT
  1165. endif
  1166. mov es,selIDT
  1167. assume es:NOTHING
  1168. mov cx,256 ;number of descriptors in table
  1169. shl cx,3 ;convert to count of bytes
  1170. dec cx ;compute segment size limit
  1171. mov word ptr [bpIDT+0],cx
  1172. mov dx,word ptr lmaIDT
  1173. mov word ptr [bpIDT+2],dx
  1174. mov bx,word ptr lmaIDT+2
  1175. mov word ptr [bpIDT+4],bx
  1176. cCall NSetSegmentDscr,<SEL_IDT,bx,dx,0,cx,STD_DATA>
  1177. ; Fill the IDT with interrupt gates that point to the fault handler and
  1178. ; interrupt reflector entry vector.
  1179. xor di,di
  1180. mov dx,offset DXPMCODE:PmIntrEntryVector
  1181. mov cx,256
  1182. iidt23: mov es:[di].offDest,dx
  1183. mov es:[di].selDest,SEL_DXPMCODE or STD_RING
  1184. mov es:[di].cwParam,0
  1185. mov es:[di].arbGate,STD_TRAP ; BUGBUG- int gates not set up
  1186. mov es:[di].rsvdGate,0
  1187. add dx,5
  1188. add di,8
  1189. loop iidt23
  1190. ; Now, fix up the ones that don't point to the interrupt reflector.
  1191. ; BUGBUG In dxstrt.asm, these are x86 ONLY.
  1192. mov es:[1h*8].offDest,offset PMIntrIgnore
  1193. mov es:[3h*8].offDest,offset PMIntrIgnore
  1194. ifdef NEC_98 ;
  1195. mov es:[11h*8].offDest,offset PMIntr11dummy
  1196. mov es:[18h*8].offDest,offset PMIntrVideo
  1197. mov es:[1ah*8].offDest,offset PMIntrPrinter
  1198. mov es:[1bh*8].offDest,offset PMIntr13
  1199. mov es:[1ch*8].offDest,offset PMIntrCalTi
  1200. mov es:[1dh*8].offDest,offset PMIntrGraph
  1201. mov es:[1fh*8].offDest,offset PMIntrMisc
  1202. else ;NEC_98 ;
  1203. mov es:[10h*8].offDest,offset PMIntrVideo
  1204. mov es:[13h*8].offDest,offset PMIntr13
  1205. mov es:[15h*8].offDest,offset PMIntrMisc
  1206. mov es:[19h*8].offDest,offset PMIntr19
  1207. endif ;NEC_98 ;
  1208. mov es:[21h*8].offDest,offset DXPMCODE:PMIntrDos
  1209. mov es:[25h*8].offDest,offset DXPMCODE:PMIntr25
  1210. mov es:[26h*8].offDest,offset DXPMCODE:PMIntr26
  1211. mov es:[28h*8].offDest,offset DXPMCODE:PMIntr28
  1212. mov es:[30h*8].offDest,offset DXPMCODE:PMIntrIgnore
  1213. mov es:[31h*8].offDest,offset DXPMCODE:PMIntr31
  1214. mov es:[33h*8].offDest,offset DXPMCODE:PMIntrMouse
  1215. mov es:[41h*8].offDest,offset DXPMCODE:PMIntrIgnore
  1216. ifndef WOW_x86
  1217. mov es:[4Bh*8].offDest,offset DXPMCODE:PMIntr4B
  1218. ifdef NEC_98 ;
  1219. ; Sound BIOS Int D2h handler
  1220. mov es:[0D2h*8].offDest,offset DXPMCODE:PMIntrSound
  1221. ; Extended DOS Int DCh handler (KANA/KANJI)
  1222. mov es:[0DCh*8].offDest,offset DXPMCODE:PMIntrExDos
  1223. endif ;NEC_98 ;
  1224. endif
  1225. ;
  1226. ; Set up the IDT, and dpmi32 state
  1227. ;
  1228. mov ax,es ; Idt selector
  1229. mov bx,VDM_INT_16
  1230. DPMIBOP InitIDT
  1231. mov ax,5 ; handler increment
  1232. mov cx,SEL_DXPMCODE OR STD_RING
  1233. mov dx,offset DXPMCODE:PmFaultEntryVector
  1234. DPMIBOP InitExceptionHandlers
  1235. .286p
  1236. ; All done
  1237. iidt90: pop es
  1238. pop di
  1239. pop si
  1240. pop dx
  1241. pop cx
  1242. pop bx
  1243. ret
  1244. InitIntrDscrTable endp
  1245. ; -------------------------------------------------------
  1246. ;
  1247. ; InitTaskStateSeg -- This function initializes the
  1248. ; TSS for the DOS Extender.
  1249. ;
  1250. ; Input: none
  1251. ; Output: none
  1252. ; Errors: returns CY if unable to allocate memory
  1253. ; Uses: all registers preserved
  1254. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1255. public InitTaskStateSeg
  1256. InitTaskStateSeg proc near
  1257. push ax
  1258. push cx
  1259. push di
  1260. ; As a start, zero out the TSS
  1261. xor al,al
  1262. mov cx,type TSS286
  1263. mov di,offset DGROUP:sysTSS
  1264. rep stosb
  1265. ; Set the LDT selector
  1266. mov sysTSS.tss_ldt,SEL_LDT
  1267. ; Set the ring 0 stack seg/pointer, we don't bother to set the others
  1268. ; since nothing runs below DOSX's ring. Currently very little code runs
  1269. ; ring 0 - just when switching between real/proteted modes.
  1270. mov sysTSS.tss_ss0,SEL_DXDATA0
  1271. mov sysTSS.tss_sp0,offset DGROUP:ResetStack
  1272. ; That's all it takes
  1273. pop di
  1274. pop cx
  1275. pop ax
  1276. clc
  1277. ret
  1278. InitTaskStateSeg endp
  1279. ; -------------------------------------------------------
  1280. ; MISC. STARTUP ROUTINES
  1281. ; -------------------------------------------------------
  1282. ; *** CheckCPUType - Set global variable for CPU type
  1283. ;
  1284. ; This routine relies on Intel-approved code that takes advantage
  1285. ; of the documented behavior of the high nibble of the flag word
  1286. ; in the REAL MODE of the various processors. The MSB (bit 15)
  1287. ; is always a one on the 8086 and 8088 and a zero on the 286 and
  1288. ; 386. Bit 14 (NT flag) and bits 13/12 (IOPL bit field) are
  1289. ; always zero on the 286, but can be set on the 386.
  1290. ;
  1291. ; For future compatibility of this test, it is strongly recommended
  1292. ; that this specific instruction sequence be used. The exit codes
  1293. ; can of course be changed to fit a particular need.
  1294. ;
  1295. ; CALLABLE FROM REAL MODE ONLY
  1296. ;
  1297. ; ENTRY: NONE
  1298. ;
  1299. ; EXIT: AX holds CPU type ( 0=8086,80186; 2=80286; 3=80386; 4=80486 )
  1300. ;
  1301. ; USES: AX, DS must point to DX data segment
  1302. ; idCpuType initialized
  1303. ;
  1304. ; Modified: 07-31-90 Earleh added code from Kernel, originally
  1305. ; supplied by Intel, to check for 80486. Added check
  1306. ; for V86 mode just in case a Limulator or something
  1307. ; is active.
  1308. ;
  1309. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1310. public CheckCPUType
  1311. CheckCPUType proc near
  1312. .8086
  1313. pushf ; save flags during cpu test
  1314. pushf
  1315. pop ax ; flags to ax
  1316. and ax, 0fffh ; clear bits 12-15
  1317. push ax ; push immediate is bad op-code on 8086
  1318. npopf ; try to put that in the flags
  1319. pushf
  1320. pop ax ; look at what really went into flags
  1321. and ah,0f0h ; mask off high flag bits
  1322. cmp ah,0f0h ; Q: was high nibble all ones ?
  1323. mov ax, 0
  1324. jz cidx ; Y: 8086
  1325. .286p
  1326. smsw ax
  1327. test ax,1 ; Protected mode?
  1328. jnz cid386 ; V86! Gotta be at least a 386.
  1329. push 0f000h ; N: try to set the high bits
  1330. npopf ; ... in the flags
  1331. pushf
  1332. pop ax ; look at actual flags
  1333. and ah,0f0h ; Q: any high bits set ?
  1334. mov ax, 2 ; at least 286
  1335. jz cidx ; N: 80286 - exit w/ Z flag set
  1336. ; Y: 80386 - Z flag reset
  1337. ; 386 or 486? See if we can set the AC (Alignment check) bit in Eflags
  1338. ; Need to insure stack is DWORD aligned for this to work properly
  1339. .386
  1340. cid386:
  1341. mov ax, 3
  1342. push cx
  1343. push ebx
  1344. mov cx,sp ; Assume stack aligned
  1345. and cx,0011b ; set "pop" count
  1346. sub sp,cx ; Move to DWORD aligned
  1347. pushfd ; save entry flags (DWORD)
  1348. push dword ptr 40000h ; AC bit
  1349. popfd
  1350. pushfd
  1351. pop ebx
  1352. popfd ; Recover entry flags (DWORD)
  1353. add sp,cx ; pop off alignment bytes
  1354. test ebx,40000h ; Did AC bit set?
  1355. pop ebx
  1356. pop cx
  1357. jz short cidx ; No, 386
  1358. .286p
  1359. inc ax ; At least 80486...
  1360. cidx:
  1361. mov idCpuType,ax ;store CPU type in global
  1362. npopf ; restore flags after cpu test
  1363. CheckCPUType endp
  1364. ; -------------------------------------------------------
  1365. ; B_ParaToLinear
  1366. ;
  1367. ; This function will convert a paragraph address in the lower
  1368. ; megabyte of memory space into a linear address for use in
  1369. ; a descriptor table. This is a local duplicate of the function
  1370. ; ParaToLinear in DXUTIL.ASM. This is duplicated here to avoid
  1371. ; having to make far calls to it during the initialization.
  1372. ;
  1373. ; Input: DX - paragraph address
  1374. ; Output: DX - lower word of linear address
  1375. ; BX - high word of linear address
  1376. ; Errors: none
  1377. ; Uses: DX, BX used, all else preserved
  1378. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1379. B_ParaToLinear proc near
  1380. xor bh,bh
  1381. mov bl,dh
  1382. shr bl,4
  1383. shl dx,4
  1384. ret
  1385. B_ParaToLinear endp
  1386. if DEBUG ;-------------------------------------------------------
  1387. ; -------------------------------------------------------
  1388. ; CheckDOSXFixUps -- This routine will check for segment fix ups
  1389. ; in non-initialization code that need to be converted from
  1390. ; a segment to selector.
  1391. ;
  1392. ; This routine works by opening the EXE file that we were
  1393. ; loaded from and examining the relocation table.
  1394. ;
  1395. ; 10-09-90 Earleh modified so that references in initialization
  1396. ; code are not edited.
  1397. ;
  1398. ; 11-12-90 JimMat renamed from RelocateDosExtender and it now
  1399. ; only checks for fix ups in DEBUG version since all fix ups
  1400. ; in post-initialization code have been removed.
  1401. ;
  1402. ; Input: none
  1403. ; Output: none
  1404. ; Errors: returns CY set if error occurs
  1405. ; Uses: AX, all else preserved
  1406. ; modifies lpchFileName
  1407. assume ds:DGROUP,es:NOTHING,ss:DGROUP
  1408. public CheckDOSXFixUps
  1409. CheckDOSXFixUps proc near
  1410. push bp
  1411. mov bp,sp
  1412. push bx
  1413. push dx
  1414. push si
  1415. push di
  1416. push es
  1417. ; Find the path to our exe fie.
  1418. mov word ptr [lpchFileName],offset EXEC_DXNAME
  1419. mov word ptr [lpchFileName+2],ds
  1420. ; Set up for reading the relocation table from the exe file.
  1421. call B_InitRelocBuffer
  1422. jc rldx90 ;get out if error
  1423. ; Go down through the relocation table and for each fixup item,
  1424. ; patch in our selector.
  1425. mov bx,segPSP
  1426. add bx,10h ;the relocation table items are relative
  1427. ; to the initial load address of our program
  1428. ; image which is immediately after the PSP
  1429. rldx40: call B_GetRelocationItem ;get next relocation table entry
  1430. jz rldx60 ;if end of table, get out
  1431. mov di,ax ;offset of relocation item
  1432. add dx,bx ;adjust relocation item segment for our load
  1433. ; address
  1434. mov es,dx ;
  1435. ;
  1436. ; Do not fixup instructions in initialization code.
  1437. ;
  1438. cmp dx,seg DXCODE
  1439. jne rldx41
  1440. cmp di,offset DXCODE:CodeEnd
  1441. jnc rldx40
  1442. rldx41:
  1443. cmp dx,seg DXPMCODE
  1444. jne rldx42
  1445. cmp di,offset DXPMCODE:CodeEndPM
  1446. jnc rldx40
  1447. rldx42:
  1448. mov ax,es:[di] ;get the current fixup contents
  1449. cmp ax,seg DXCODE ;is it the mixed mode segment?
  1450. jnz rldx44
  1451. extrn lCodeSegLoc:WORD
  1452. cmp di,offset DXCODE:lCodeSegLoc ;special far jmp to flush
  1453. jz rldx40 ; pre-fetch queue? ok if so.
  1454. ; Shouldn't get here--tell developer he messed something up!
  1455. int 3 ;****************************************
  1456. mov word ptr es:[di],SEL_DXCODE or STD_RING
  1457. jmp short rldx40
  1458. rldx44: cmp ax,seg DXPMCODE ;is it the protected mode only segment
  1459. jnz rldx40
  1460. ; Shouldn't get here--tell developer he messed something up!
  1461. int 3 ;****************************************
  1462. mov word ptr es:[di],SEL_DXPMCODE or STD_RING
  1463. jmp rldx40 ;and repeat for the next one
  1464. ; We have gone through the entire relocation table, so close up the exe file
  1465. rldx60: mov bx,fhExeFile
  1466. dossvc 3Eh
  1467. ;
  1468. clc
  1469. jmp short rldx90
  1470. ;
  1471. ; Error occured
  1472. rldx80: stc
  1473. ;
  1474. ; All done
  1475. rldx90: pop es
  1476. pop di
  1477. pop si
  1478. pop dx
  1479. pop bx
  1480. mov sp,bp
  1481. pop bp
  1482. ret
  1483. CheckDOSXFixUps endp
  1484. ; -------------------------------------------------------
  1485. ; B_InitRelocBuffer -- This routine will open the EXE
  1486. ; file and initialize for reading the relocation table
  1487. ; as part of relocating the program for protected mode
  1488. ; execution.
  1489. ;
  1490. ; Input: lpchFileName - pointer to exe file name
  1491. ; Output: none
  1492. ; Errors: returns CY set if error occurs
  1493. ; Uses: AX modified, all other registers preserved
  1494. ; sets up static variables:
  1495. ; clpRelocItem, plpRelocItem, fhExeFile
  1496. ; modifies rgbXfrBuf1 at offset RELOC_BUFFER
  1497. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1498. public B_InitRelocBuffer
  1499. B_InitRelocBuffer proc near
  1500. push bx
  1501. push cx
  1502. push dx
  1503. push si
  1504. ;
  1505. ; Open the EXE file.
  1506. push ds
  1507. lds dx,lpchFileName
  1508. mov al,0
  1509. dossvc 3Dh ;attempt to open the exe file
  1510. pop ds
  1511. jc inrl80 ;get out if error occurs
  1512. ;
  1513. mov fhExeFile,ax ;store the file handle
  1514. mov bx,ax ;file handle to BX also
  1515. ; Read the EXE file header, so that we can get information about
  1516. ; the relocation table.
  1517. mov dx,offset RELOC_BUFFER
  1518. mov si,dx
  1519. mov cx,32
  1520. dossvc 3Fh
  1521. jc inrl80 ;get out if error
  1522. cmp ax,32
  1523. jnz inrl80
  1524. ;
  1525. ; Get the important values from the exe file header.
  1526. cmp [si].idExeFile,5A4Dh ;make sure it is an EXE file
  1527. jnz inrl80
  1528. mov ax,[si].clpRelocLen ;number of relocation items
  1529. mov clpRelocItem,ax
  1530. mov plpRelocItem,0FFFFh ;init the pointer to the first one
  1531. ; to a bogus value to force the initial
  1532. ; buffer to be loaded
  1533. ;
  1534. ; Get the location of the relocation table, and move the file pointer
  1535. ; to its start.
  1536. xor cx,cx
  1537. mov dx,[si].wRelocOffset
  1538. mov al,cl
  1539. dossvc 42h
  1540. jnc inrl90
  1541. ;
  1542. ; Error occured
  1543. inrl80: stc
  1544. ;
  1545. ; All done
  1546. inrl90: pop si
  1547. pop dx
  1548. pop cx
  1549. pop bx
  1550. ret
  1551. B_InitRelocBuffer endp
  1552. ; -------------------------------------------------------
  1553. ; B_GetRelocationItem -- This routine will return the next
  1554. ; relocation table entry from the exe file being relocated.
  1555. ;
  1556. ; Input: none
  1557. ; Output: AX - offset of relocation item pointer
  1558. ; DX - segment of relocation item pointer
  1559. ; Errors: returns ZR true if end of table and no more items
  1560. ; Uses: AX, DX modified, all other registers preserved
  1561. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1562. public B_GetRelocationItem
  1563. B_GetRelocationItem proc near
  1564. push si
  1565. ;
  1566. cmp clpRelocItem,0 ;are there any relocation items left?
  1567. jz gtrl90 ;get out if not
  1568. ;
  1569. ; Check if the buffer is empty. The buffer for the relocation table is
  1570. ; at offset RELOC_BUFFER in the buffer rgbXfrBuf1, and is 512 bytes long.
  1571. cmp plpRelocItem,offset RELOC_BUFFER + 512
  1572. jc gtrl40
  1573. ;
  1574. ; The buffer is empty, so we need to read the next part of it in.
  1575. push cx
  1576. push bx
  1577. push dx
  1578. mov ax,clpRelocItem ;number of items left in file
  1579. shl ax,2 ;multiply by size of relocation item
  1580. jc gtrl22 ;check for overflow
  1581. cmp ax,512 ;check if bigger than the buffer
  1582. jc gtrl24
  1583. gtrl22: mov ax,512 ;use buffer size as size of transfer
  1584. gtrl24: mov cx,ax
  1585. mov dx,offset RELOC_BUFFER
  1586. mov plpRelocItem,dx ;pointer to next reloc item to return
  1587. mov bx,fhExeFile
  1588. dossvc 3Fh
  1589. pop dx
  1590. pop bx
  1591. jc gtrl28 ;if error occured
  1592. cmp ax,cx ;or, if we didn't get as much as we asked
  1593. jnz gtrl28 ; for, we have an error
  1594. pop cx
  1595. jmp short gtrl40
  1596. ;
  1597. gtrl28: pop cx
  1598. stc
  1599. jmp short gtrl90
  1600. ;
  1601. ; Get the next relocation item from the buffer.
  1602. gtrl40: mov si,plpRelocItem
  1603. lods word ptr [si] ;get the offset part of the reloc item
  1604. mov dx,ax
  1605. lods word ptr [si] ;get the segment part of the reloc item
  1606. xchg dx,ax ;put offset in AX, and segment in DX
  1607. mov plpRelocItem,si ;store the updated pointer
  1608. dec clpRelocItem ;and bump the count down by 1
  1609. or si,si ;clear the zero flag
  1610. ;
  1611. ; All done.
  1612. gtrl90: pop si
  1613. ret
  1614. B_GetRelocationItem endp
  1615. endif ;DEBUG --------------------------------------------------------
  1616. ; -------------------------------------------------------
  1617. ; GetExeName -- This routine will put a copy of the complete
  1618. ; path name to the dos extender's exe file. In a name
  1619. ; buffer in rgbXfrBuf1.
  1620. ;
  1621. ; Input: none
  1622. ; Output: EXEC_DXNAME buffer updated with complete pathname.
  1623. ; Errors: returns CY set if environment not correctly built.
  1624. ; Uses: all preserved
  1625. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1626. public GetExeName
  1627. GetExeName proc near
  1628. push ax
  1629. push si
  1630. push di
  1631. push ds
  1632. ; The name of the current program is stored at the end of the environment
  1633. ; table. There are two bytes of 0 to indicate end of table, a byte
  1634. ; with a 1 in it followed by another byte of 0 and then the null terminated
  1635. ; string with the current program name.
  1636. gtxe20: mov ds,segPSP
  1637. assume ds:PSPSEG
  1638. mov ds,segEnviron
  1639. assume ds:NOTHING
  1640. xor si,si
  1641. gtxe22: lods byte ptr [si] ;get next byte from environment
  1642. or al,al ;test if 0
  1643. jnz gtxe22 ;if not, keep looking
  1644. lods byte ptr [si] ;get next byte
  1645. or al,al ;see if it is 0 also
  1646. jnz gtxe22
  1647. ; We have found the double 0 at the end of the environment. So
  1648. ; we can now get the name. At the end of the environment is an
  1649. ; argc, argv construct. (i.e. a word giving the count of strings
  1650. ; followed by an array of strings). Under DOS, argc is always 1,
  1651. ; so check that there is a word of 1 here. If not, this environment
  1652. ; wasn't built correctly and we don't know what is here.
  1653. lods word ptr [si]
  1654. cmp ax,1
  1655. jnz gtxe80
  1656. ; We have the pointer to the name, now copy it.
  1657. mov di,offset EXEC_DXNAME
  1658. call strcpy
  1659. clc
  1660. jmp short gtxe90
  1661. ; We have an error.
  1662. gtxe80: stc ;set error condition flag
  1663. gtxe90: pop ds
  1664. pop di
  1665. pop si
  1666. pop ax
  1667. ret
  1668. GetExeName endp
  1669. ; -------------------------------------------------------
  1670. ; COMMAND LINE PARSING ROUTINES
  1671. ; -------------------------------------------------------
  1672. ; ParseCommandLine -- This function will examine the dos
  1673. ; command line that caused the Dos Extender to be exec'd
  1674. ; and determine what the user wants done. It will set
  1675. ; up the various buffers required for the child program
  1676. ; to be loaded.
  1677. ;
  1678. ; NOTE: the child exe file name read from the command line
  1679. ; is placed in RELOC_BUFFER in the case where the child
  1680. ; name is specified on the command line. This buffer is
  1681. ; used later when reading the relocation table while
  1682. ; performing the fixups on the child.
  1683. ;
  1684. ; Input: none
  1685. ; Output: AL - 0 if empty command line, else non-zero
  1686. ; parse buffers in rgbXfrBuf1 set up.
  1687. ; Errors: none
  1688. ; Uses: AX, all else preserved
  1689. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1690. public ParseCommandLine
  1691. ParseCommandLine proc near
  1692. push si
  1693. push di
  1694. push ds
  1695. mov ds,segPSP
  1696. assume ds:PSPSEG
  1697. mov si,81h ;pointer to command line in PSP
  1698. ; Skip any white space in front of the child program name.
  1699. prsc12: lods byte ptr [si]
  1700. cmp al,' '
  1701. jz prsc12
  1702. dec si
  1703. ; Copy the command line tail following the program name to the command
  1704. ; line buffer for use when we load the child.
  1705. prsc40: push si ;save current point in parse
  1706. mov di,offset EXEC_CMNDLINE + 1
  1707. xor dl,dl ;count characters in command line tail
  1708. prsc42: lods byte ptr [si] ;get the next character
  1709. stos byte ptr [di] ;store it into the output buffer
  1710. cmp al,0Dh ;is it the end of the line?
  1711. jz prsc44
  1712. inc dl ;count the character
  1713. jmp prsc42
  1714. prsc44: mov es:[EXEC_CMNDLINE],dl ;store the character count
  1715. pop si ;restore the buffer pointer
  1716. ; Now we want to set up the two default FCB's by letting DOS parse the
  1717. ; first two parameters on the command line.
  1718. mov di,offset EXEC_FCB0
  1719. mov al,1
  1720. dossvc 29h
  1721. mov di,offset EXEC_FCB1
  1722. mov al,1
  1723. dossvc 29h
  1724. prsc90:
  1725. pop ds
  1726. pop di
  1727. pop si
  1728. ret
  1729. ParseCommandLine endp
  1730. ; -------------------------------------------------------
  1731. ; strcpy -- copy a null terminated string.
  1732. ;
  1733. ; Input: DS:SI - pointer to source string
  1734. ; ES:DI - pointer to destination buffer
  1735. ; Output: ES:DI - pointer to end of destination string
  1736. ; Errors: none
  1737. ; Uses: DI modified, all else preserved
  1738. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1739. public strcpy
  1740. strcpy proc near
  1741. push ax
  1742. push si
  1743. stcp10: lods byte ptr [si]
  1744. stos byte ptr [di]
  1745. or al,al
  1746. jnz stcp10
  1747. dec di
  1748. pop si
  1749. pop ax
  1750. ret
  1751. strcpy endp
  1752. ; -------------------------------------------------------
  1753. ; strcmpi -- This function will perform a case insensitive
  1754. ; comparison of two null terminated strings.
  1755. ;
  1756. ; Input: DS:SI - string 1
  1757. ; ES:DI - string 2
  1758. ; Output: ZR if the strings match, else NZ
  1759. ; CY set if string 1 less than string 2
  1760. ; Errors: none
  1761. ; Uses: all registers preserved
  1762. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1763. public strcmpi
  1764. strcmpi proc near
  1765. push si
  1766. push di
  1767. stcm20: mov al,byte ptr ds:[si]
  1768. call toupper
  1769. mov ah,al
  1770. mov al,byte ptr es:[di]
  1771. call toupper
  1772. cmp ah,al
  1773. jnz stcm90
  1774. or al,ah
  1775. jz stcm90
  1776. inc si
  1777. inc di
  1778. jmp stcm20
  1779. stcm90: pop di
  1780. pop si
  1781. ret
  1782. strcmpi endp
  1783. ; -------------------------------------------------------
  1784. ; IsFileNameChar -- This function will examine the
  1785. ; character in AL and determine if it is a legal character
  1786. ; in an MS-DOS file name.
  1787. ;
  1788. ; Input: AL - character to test
  1789. ; Output: ZR true if character is legal in a file name
  1790. ; Errors: none
  1791. ; Uses: all registers preserved
  1792. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1793. IsFileNameChar proc near
  1794. push ax
  1795. cmp al,20h ;is it a control character
  1796. jbe isfc80 ;if so, it isn't valid
  1797. cmp al,':'
  1798. jz isfc80
  1799. cmp al,';'
  1800. jz isfc80
  1801. cmp al,','
  1802. jz isfc80
  1803. cmp al,'='
  1804. jz isfc80
  1805. cmp al,'+'
  1806. jz isfc80
  1807. cmp al,'<'
  1808. jz isfc80
  1809. cmp al,'>'
  1810. jz isfc80
  1811. cmp al,'|'
  1812. jz isfc80
  1813. cmp al,'/'
  1814. jz isfc80
  1815. cmp al,'"'
  1816. jz isfc80
  1817. cmp al,'['
  1818. jz isfc80
  1819. cmp al,']'
  1820. jz isfc80
  1821. xor al,al
  1822. jmp short isfc90
  1823. ; Not a valid file name character
  1824. isfc80: or al,0FFh
  1825. isfc90: pop ax
  1826. ret
  1827. IsFileNameChar endp
  1828. ; -------------------------------------------------------
  1829. ; toupper -- This function will convert the character
  1830. ; in AL into upper case.
  1831. ;
  1832. ; Input: AL - character to convert
  1833. ; Output: AL - upper case character
  1834. ; Errors: none
  1835. ; Uses: AL modified, all else preserved
  1836. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1837. public toupper
  1838. toupper proc near
  1839. cmp al,'a'
  1840. jb toup90
  1841. cmp al,'z'
  1842. ja toup90
  1843. sub al,'a'-'A'
  1844. toup90:
  1845. ret
  1846. toupper endp
  1847. ; -------------------------------------------------------
  1848. DXCODE ends
  1849. ;
  1850. ;****************************************************************
  1851. end