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.

2992 lines
57 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Int21Map.c
  5. Abstract:
  6. This module performs int 21 API translation for dpmi
  7. Author:
  8. Dave Hastings (daveh) 23-Nov-1992
  9. Revision History:
  10. Neil Sandlin (neilsa) 31-Jul-1995 - Updates for the 486 emulator
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "int21map.h"
  15. #include "softpc.h"
  16. #include "xlathlp.h"
  17. //
  18. // Local constants
  19. //
  20. //#define Verbose 1
  21. #define MAX_SUPPORTED_DOS_CALL 0x6d
  22. #define DosxTranslated NULL
  23. typedef VOID (*APIXLATFUNCTION)(VOID);
  24. APIXLATFUNCTION ApiXlatTable[MAX_SUPPORTED_DOS_CALL] = {
  25. DosxTranslated , // 00h - Terminate process
  26. NoTranslation , // 01h - Char input with echo
  27. NoTranslation , // 02h - Character output
  28. NoTranslation , // 03h - Auxiliary input
  29. NoTranslation , // 04h - Auxiliary output
  30. NoTranslation , // 05h - Print character
  31. NoTranslation , // 06h - Direct console I/O
  32. NoTranslation , // 07h - Unfiltered char input
  33. NoTranslation , // 08h - Char input w/o echo
  34. DisplayString , // 09h - Display "$" term string
  35. BufferedKeyboardInput , // 0Ah - Buffered keyboard input
  36. NoTranslation , // 0Bh - Check keyboard status
  37. FlushBuffReadKbd , // 0Ch - Flush buff, Read kbd
  38. NoTranslation , // 0Dh - Disk reset
  39. NoTranslation , // 0Eh - Select disk
  40. NotSupportedFCB , // 0Fh * Open file with FCB
  41. NotSupportedFCB , // 10h * Close file with FCB
  42. FindFileFCB , // 11h - Find First File
  43. FindFileFCB , // 12h - Find Next File
  44. MapFCB , // 13h - Delete File
  45. NotSupportedFCB , // 14h * Sequential Read
  46. NotSupportedFCB , // 15h * Sequential Write
  47. NotSupportedFCB , // 16h * Create File With FCB
  48. RenameFCB , // 17h - Rename File With FCB
  49. NoTranslation , // 18h - UNUSED
  50. NoTranslation , // 19h - Get Current Disk
  51. SetDTA , // 1Ah - Set DTA Address
  52. GetDriveData , // 1Bh - Get Default Drive Data
  53. GetDriveData , // 1Ch - Get Drive Data
  54. NoTranslation , // 1Dh - UNUSED
  55. NoTranslation , // 1Eh - UNUSED
  56. GetDriveData , // 1Fh - Get Drive Parameter Blk
  57. NoTranslation , // 20h - UNUSED
  58. NotSupportedFCB , // 21h * Random Read
  59. NotSupportedFCB , // 22h * Random Write
  60. NotSupportedFCB , // 23h * Get File Size
  61. NotSupportedFCB , // 24h * Set Relative Record
  62. SetVector , // 25h - Set interrupt vector
  63. CreatePSP , // 26h - Create PSP
  64. NotSupportedFCB , // 27h * Random block read
  65. NotSupportedFCB , // 28h * Random block write
  66. ParseFilename , // 29h - Parse filename
  67. GetDate , // 2Ah - Get date
  68. NoTranslation , // 2Bh - Set date
  69. NoTranslation , // 2Ch - Get time
  70. NoTranslation , // 2Dh - Set time
  71. NoTranslation , // 2Eh - Set/Reset verify flag
  72. GetDTA , // 2Fh - Get DTA address
  73. NoTranslation , // 30h - Get DOS version
  74. TSR , // 31h - Terminate and Stay Res
  75. GetDevParamBlock , // 32h - Get device parameter blk
  76. NoTranslation , // 33h - Get/Set Control-C Flag
  77. ReturnESBX , // 34h - Get Address of InDOS
  78. GetVector , // 35h - Get Interrupt Vector
  79. NoTranslation , // 36h - Get Disk Free Space
  80. NoTranslation , // 37h - Char Oper
  81. GetSetCountry , // 38h - Get/Set Current Country
  82. MapASCIIZDSDX , // 39h - Create Directory
  83. MapASCIIZDSDX , // 3Ah - Remove Directory
  84. MapASCIIZDSDX , // 3Bh - Change Current Directory
  85. MapASCIIZDSDX , // 3Ch - Create File with Handle
  86. MapASCIIZDSDX , // 3Dh - Open File with Handle
  87. NoTranslation , // 3Eh - Close File with Handle
  88. ReadWriteFile , // 3Fh - Read File or Device
  89. ReadWriteFile , // 40h - Write File or Device
  90. MapASCIIZDSDX , // 41h - Delete File
  91. NoTranslation , // 42h - Move file pointer
  92. MapASCIIZDSDX , // 43h - Get/Set File Attributes
  93. IOCTL , // 44h - IOCTL
  94. NoTranslation , // 45h - Duplicate File Handle
  95. NoTranslation , // 46h - Force Duplicate Handle
  96. GetCurDir , // 47h - Get Current Directory
  97. AllocateMemoryBlock , // 48h - Allocate Memory Block
  98. FreeMemoryBlock , // 49h - Free Memory Block
  99. ResizeMemoryBlock , // 4Ah - Resize Memory Block
  100. LoadExec , // 4Bh - Load and Exec Program
  101. DosxTranslated , // 4Ch - Terminate with Ret Code
  102. NoTranslation , // 4Dh - Get Ret Code Child Proc
  103. FindFirstFileHandle , // 4Eh - Find First File
  104. FindNextFileHandle , // 4Fh - Find Next File
  105. SetPSP , // 50h - Set PSP Segment
  106. GetPSP , // 51h - Get PSP Segment
  107. ReturnESBX , // 52h - Get List of Lists (invars)
  108. TranslateBPB , // 53h - Translate BPB
  109. NoTranslation , // 54h - Get Verify Flag
  110. CreatePSP , // 55h - Create PSP
  111. RenameFile , // 56h - Rename File
  112. NoTranslation , // 57h - Get/Set Date/Time File
  113. NoTranslation , // 58h - Get/Set Alloc Strategy
  114. NoTranslation , // 59h - Get Extended Error Info
  115. CreateTempFile , // 5Ah - Create Temporary File
  116. MapASCIIZDSDX , // 5Bh - Create New File
  117. NoTranslation , // 5Ch - Lock/Unlock File Region
  118. Func5Dh , // 5Dh - Server DOS call
  119. Func5Eh , // 5Eh - Net Name/Printer Setup
  120. Func5Fh , // 5Fh - Network redir stuff
  121. NotSupportedBad , // 60h - NameTrans
  122. NoTranslation , // 61h - UNUSED
  123. GetPSP , // 62h - Get PSP Address
  124. #ifdef DBCS
  125. ReturnDSSI , // 63h - Get DBCS Vector
  126. #else
  127. NotSupportedBetter , // 63h - Hangool call
  128. #endif
  129. NotSupportedBad , // 64h - Set Prn Flag
  130. GetExtendedCountryInfo , // 65h - Get Extended Country Info
  131. NoTranslation , // 66h - Get/Set Global Code Page
  132. NoTranslation , // 67h - Set Handle Count
  133. NoTranslation , // 68h - Commit File
  134. NoTranslation , // 69h -
  135. NoTranslation , // 6Ah -
  136. NoTranslation , // 6Bh -
  137. MapASCIIZDSSI // 6Ch - Extended open
  138. };
  139. VOID
  140. DpmiXlatInt21Call(
  141. VOID
  142. )
  143. /*++
  144. Routine Description:
  145. This routine dispatches to the appropriate routine to perform the
  146. actual translation of the api
  147. Arguments:
  148. None
  149. Return Value:
  150. None.
  151. --*/
  152. {
  153. DECLARE_LocalVdmContext;
  154. ULONG DosMajorCode;
  155. PUCHAR StackPointer;
  156. //
  157. // Pop ds from stack
  158. //
  159. StackPointer = Sim32GetVDMPointer(
  160. ((ULONG)getSS() << 16),
  161. 1,
  162. TRUE
  163. );
  164. StackPointer += (*GetSPRegister)();
  165. setDS(*(PWORD16)StackPointer);
  166. (*SetSPRegister)((*GetSPRegister)() + 2);
  167. DosMajorCode = getAH();
  168. if (DosMajorCode >= MAX_SUPPORTED_DOS_CALL) {
  169. return; //bugbug find out what win31 does.
  170. }
  171. if (ApiXlatTable[DosMajorCode]) {
  172. ULONG Eip, Esp;
  173. USHORT Cs, Ss;
  174. Eip = getEIP();
  175. Esp = getESP();
  176. Cs = getCS();
  177. Ss = getSS();
  178. (*ApiXlatTable[DosMajorCode])();
  179. setEIP(Eip);
  180. setESP(Esp);
  181. setCS(Cs);
  182. setSS(Ss);
  183. SimulateIret(PASS_CARRY_FLAG_16);
  184. }
  185. // put this back in after beta 2.5
  186. DpmiFreeAllBuffers();
  187. }
  188. VOID
  189. NoTranslation(
  190. VOID
  191. )
  192. /*++
  193. Routine Description:
  194. This routine handles int 21 functions which don't need any translation.
  195. It simply executes the int 21 in real/v86 mode
  196. Arguments:
  197. None
  198. Return Value:
  199. None.
  200. --*/
  201. {
  202. DECLARE_LocalVdmContext;
  203. DpmiSwitchToRealMode();
  204. DPMI_EXEC_INT(0x21);
  205. DpmiSwitchToProtectedMode();
  206. }
  207. VOID
  208. DisplayString(
  209. VOID
  210. )
  211. /*++
  212. Routine Description:
  213. This routine translates the int 21 display string function.
  214. N.B. Win 3.1 does this by calling int 21 function 2 repeatedly.
  215. We do it this way because Win 3.1 does. If this function is
  216. frequently used, we should actually buffer the string and
  217. call the dos display string function.
  218. Arguments:
  219. None
  220. Return Value:
  221. None.
  222. --*/
  223. { PUCHAR String;
  224. DECLARE_LocalVdmContext;
  225. USHORT ClientAX, ClientDX;
  226. USHORT ClientDS = getDS();
  227. DpmiSwitchToRealMode();
  228. String = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  229. + (*GetDXRegister)();
  230. //
  231. // Repeatedly call int 21 function 2 to display the characters
  232. //
  233. ClientAX = getAX();
  234. ClientDX = getDX();
  235. setAH(2);
  236. while (*(String) != '$') {
  237. setDL(*(String));
  238. DPMI_EXEC_INT(0x21);
  239. String++;
  240. }
  241. setAX(ClientAX);
  242. setDX(ClientDX);
  243. DpmiSwitchToProtectedMode();
  244. }
  245. VOID
  246. BufferedKeyboardInput(
  247. VOID
  248. )
  249. /*++
  250. Routine Description:
  251. This routine performs the tranlation for the int 21 function Ah
  252. Arguments:
  253. None.
  254. Return Value:
  255. None.
  256. --*/
  257. {
  258. DECLARE_LocalVdmContext;
  259. PUCHAR PmInputBuffer, RmInputBuffer;
  260. USHORT BufferSeg, BufferOff, BufferLen;
  261. USHORT ClientDX;
  262. USHORT ClientDS = getDS();
  263. DpmiSwitchToRealMode();
  264. ClientDX = getDX();
  265. //
  266. // Get a pointer to the PM buffer
  267. //
  268. PmInputBuffer = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  269. + (*GetDXRegister)();
  270. //
  271. // Get the buffer length (there are two bytes in addition to the
  272. // buffer)
  273. //
  274. BufferLen = *PmInputBuffer + 2;
  275. //
  276. // Move the buffer to low memory
  277. //
  278. RmInputBuffer = DpmiMapAndCopyBuffer(PmInputBuffer, BufferLen);
  279. //
  280. // Set up the registers for the int 21 call
  281. //
  282. DPMI_FLAT_TO_SEGMENTED(RmInputBuffer, &BufferSeg, &BufferOff);
  283. setDS(BufferSeg);
  284. setDX(BufferOff);
  285. DPMI_EXEC_INT(0x21);
  286. //
  287. // Copy the data back
  288. //
  289. DpmiUnmapAndCopyBuffer(PmInputBuffer, RmInputBuffer, BufferLen);
  290. setDX(ClientDX);
  291. DpmiSwitchToProtectedMode();
  292. setDS(ClientDS);
  293. }
  294. VOID
  295. FlushBuffReadKbd(
  296. VOID
  297. )
  298. /*++
  299. Routine Description:
  300. This routine performs translation for the flush keyboard routines.
  301. It calls the appropriate xlat routine.
  302. Arguments:
  303. None.
  304. Return Value:
  305. None.
  306. --*/
  307. {
  308. DECLARE_LocalVdmContext;
  309. if (getAL() == 0x0a) {
  310. BufferedKeyboardInput();
  311. } else {
  312. NoTranslation();
  313. }
  314. }
  315. VOID
  316. NotSupportedFCB(
  317. VOID
  318. )
  319. /*++
  320. Routine Description:
  321. This routine does not do any translation. It prints a warning to
  322. the debugger
  323. Arguments:
  324. None.
  325. Return Value:
  326. None.
  327. --*/
  328. {
  329. #if DBG
  330. DECLARE_LocalVdmContext;
  331. DbgPrint(
  332. "WARNING: DOS INT 21 call AH = %x will not be translated.\n", getAH());
  333. DbgPrint(
  334. " Protected mode applications should not be using\n");
  335. DbgPrint(
  336. " this type of FCB call. Convert this application\n");
  337. DbgPrint(
  338. " to use the handle calls.\n"
  339. );
  340. #endif
  341. NoTranslation();
  342. }
  343. VOID
  344. FindFileFCB(
  345. VOID
  346. )
  347. /*++
  348. Routine Description:
  349. This function translates the find first/find next FCB calls.
  350. Arguments:
  351. None.
  352. Return Value:
  353. None.
  354. --*/
  355. {
  356. DECLARE_LocalVdmContext;
  357. PUCHAR FcbAddress, FcbBufferedAddress;
  358. USHORT FcbSegment, FcbOffset;
  359. USHORT ClientDX;
  360. USHORT FcbLength;
  361. USHORT ClientDS = getDS();
  362. DpmiSwitchToRealMode();
  363. SetDTAPointers();
  364. ClientDX = getDX();
  365. FcbAddress = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  366. + (*GetDXRegister)();
  367. //
  368. // Calculate the size of the FCB
  369. //
  370. FcbLength = DpmiCalcFcbLength(FcbAddress);
  371. //
  372. // Buffer the FCB
  373. //
  374. FcbBufferedAddress = DpmiMapAndCopyBuffer(FcbAddress, FcbLength);
  375. //
  376. // Check to see if we need to set the real dta
  377. //
  378. if (CurrentDosDta != CurrentDta)
  379. SetDosDTA();
  380. //
  381. // Make the int 21 call
  382. //
  383. DPMI_FLAT_TO_SEGMENTED(FcbBufferedAddress, &FcbSegment, &FcbOffset);
  384. setDS(FcbSegment);
  385. setDX(FcbOffset);
  386. DPMI_EXEC_INT(0x21);
  387. //
  388. // If the call was successful and the PM dta is in high memory
  389. // copy the dta to high memory
  390. //
  391. if ((getAL() == 0) && (CurrentPmDtaAddress != CurrentDta)) {
  392. MoveMemory(CurrentPmDtaAddress, CurrentDta, FcbLength);
  393. DpmiUnmapAndCopyBuffer(FcbAddress, FcbBufferedAddress, FcbLength);
  394. } else {
  395. DpmiUnmapBuffer(FcbBufferedAddress, FcbLength);
  396. }
  397. setDX(ClientDX);
  398. DpmiSwitchToProtectedMode();
  399. setDS(ClientDS);
  400. }
  401. VOID
  402. MapFCB(
  403. VOID
  404. )
  405. /*++
  406. Routine Description:
  407. This routine translates the delete file fcb int 21 call
  408. Arguments:
  409. None.
  410. Return Value:
  411. None.
  412. --*/
  413. {
  414. DECLARE_LocalVdmContext;
  415. USHORT FcbLength, FcbSegment, FcbOffset;
  416. PUCHAR FcbAddress, FcbBufferedAddress;
  417. USHORT ClientDX;
  418. USHORT ClientDS = getDS();
  419. DpmiSwitchToRealMode();
  420. ClientDX = getDX();
  421. FcbAddress = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  422. + (*GetDXRegister)();
  423. //
  424. // Get the length of the FCB
  425. //
  426. FcbLength = DpmiCalcFcbLength(FcbAddress);
  427. //
  428. // Copy the FCB
  429. //
  430. FcbBufferedAddress = DpmiMapAndCopyBuffer(FcbAddress, FcbLength);
  431. //
  432. // Make the int 21 call
  433. //
  434. DPMI_FLAT_TO_SEGMENTED(FcbBufferedAddress, &FcbSegment, &FcbOffset);
  435. setDS(FcbSegment);
  436. setDX(FcbOffset);
  437. DPMI_EXEC_INT(0x21);
  438. //
  439. // Copy the FCB back
  440. //
  441. DpmiUnmapAndCopyBuffer(FcbAddress, FcbBufferedAddress, FcbLength);
  442. //
  443. // Clean up
  444. //
  445. setDX(ClientDX);
  446. DpmiSwitchToProtectedMode();
  447. setDS(ClientDS);
  448. }
  449. VOID
  450. RenameFCB(
  451. VOID
  452. )
  453. /*++
  454. Routine Description:
  455. This routine translates the rename fcb int 21 function
  456. Arguments:
  457. None.
  458. Return Value:
  459. None.
  460. --*/
  461. {
  462. DECLARE_LocalVdmContext;
  463. USHORT FcbSegment, FcbOffset;
  464. PUCHAR FcbAddress, FcbBufferedAddress;
  465. USHORT ClientDX;
  466. USHORT ClientDS = getDS();
  467. DpmiSwitchToRealMode();
  468. ClientDX = getDX();
  469. FcbAddress = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  470. + (*GetDXRegister)();
  471. //
  472. // Copy the FCB (The fcb for rename is a special format, fixed size)
  473. //
  474. FcbBufferedAddress = DpmiMapAndCopyBuffer(FcbAddress, 0x25);
  475. //
  476. // Make the int 21 call
  477. //
  478. DPMI_FLAT_TO_SEGMENTED(FcbBufferedAddress, &FcbSegment, &FcbOffset);
  479. setDS(FcbSegment);
  480. setDX(FcbOffset);
  481. DPMI_EXEC_INT(0x21);
  482. //
  483. // Copy the FCB back
  484. //
  485. DpmiUnmapAndCopyBuffer(FcbAddress, FcbAddress, 0x25);
  486. //
  487. // Clean up
  488. //
  489. setDX(ClientDX);
  490. DpmiSwitchToProtectedMode();
  491. setDS(ClientDS);
  492. }
  493. VOID
  494. GetDriveData(
  495. VOID
  496. )
  497. /*++
  498. Routine Description:
  499. Translates the drive data int 21 calls
  500. Arguments:
  501. None.
  502. Return Value:
  503. None.
  504. --*/
  505. {
  506. DECLARE_LocalVdmContext;
  507. USHORT Selector;
  508. DpmiSwitchToRealMode();
  509. DPMI_EXEC_INT(0x21);
  510. Selector = getDS();
  511. DpmiSwitchToProtectedMode();
  512. setDS(SegmentToSelector(Selector, STD_DATA));
  513. (*SetBXRegister)((ULONG)getBX());
  514. }
  515. VOID
  516. SetVector(
  517. VOID
  518. )
  519. /*++
  520. Routine Description:
  521. This function translates int 21 function 25
  522. Arguments:
  523. None.
  524. Return Value:
  525. None.
  526. --*/
  527. {
  528. DECLARE_LocalVdmContext;
  529. SetProtectedModeInterrupt(getAL(), getDS(), (*GetDXRegister)(),
  530. (USHORT)(Frame32 ? VDM_INT_32 : VDM_INT_16));
  531. }
  532. VOID
  533. CreatePSP(
  534. VOID
  535. )
  536. /*++
  537. Routine Description:
  538. This routine translates the selector to a segment and reflects the
  539. calls
  540. Arguments:
  541. None.
  542. Return Value:
  543. None.
  544. --*/
  545. {
  546. DECLARE_LocalVdmContext;
  547. ULONG Segment;
  548. USHORT ClientDX;
  549. DpmiSwitchToRealMode();
  550. ClientDX = getDX();
  551. Segment = SELECTOR_TO_INTEL_LINEAR_ADDRESS(ClientDX);
  552. if (Segment > ONE_MB) {
  553. //
  554. // Create PSP doesn't do anything on error
  555. //
  556. } else {
  557. setDX((USHORT) (Segment >> 4));
  558. DPMI_EXEC_INT(0x21);
  559. }
  560. setDX(ClientDX);
  561. DpmiSwitchToProtectedMode();
  562. }
  563. VOID
  564. ParseFilename(
  565. VOID
  566. )
  567. /*++
  568. Routine Description:
  569. This routine translates the int 21 parse filename api
  570. Arguments:
  571. None.
  572. Return Value:
  573. None.
  574. --*/
  575. {
  576. DECLARE_LocalVdmContext;
  577. USHORT ClientSI, ClientDI, FcbLength, StringOff, Seg, Off;
  578. PUCHAR Fcb, BufferedFcb, String, BufferedString;
  579. USHORT ClientDS = getDS();
  580. USHORT ClientES = getES();
  581. DpmiSwitchToRealMode();
  582. ClientSI = getSI();
  583. ClientDI = getDI();
  584. Fcb = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE)
  585. + (*GetDIRegister)();
  586. FcbLength = DpmiCalcFcbLength(Fcb);
  587. BufferedFcb = DpmiMapAndCopyBuffer(Fcb, FcbLength);
  588. String = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  589. + (*GetSIRegister)();
  590. BufferedString = DpmiMapAndCopyBuffer(String, 20);
  591. DPMI_FLAT_TO_SEGMENTED(BufferedFcb, &Seg, &Off);
  592. setES(Seg);
  593. setDI(Off);
  594. DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &StringOff);
  595. setDS(Seg);
  596. setSI(StringOff);
  597. DPMI_EXEC_INT(0x21);
  598. DpmiUnmapAndCopyBuffer(Fcb, BufferedFcb, FcbLength);
  599. DpmiUnmapAndCopyBuffer(String, BufferedString, 20);
  600. setDI(ClientDI);
  601. setSI(ClientSI + (getSI() - StringOff));
  602. DpmiSwitchToProtectedMode();
  603. setDS(ClientDS);
  604. setES(ClientES);
  605. }
  606. VOID
  607. GetDTA(
  608. VOID
  609. )
  610. /*++
  611. Routine Description:
  612. This routine returns the current DTA.
  613. Arguments:
  614. None.
  615. Return Value:
  616. None.
  617. --*/
  618. {
  619. DECLARE_LocalVdmContext;
  620. //
  621. // Win31 compatibility:
  622. //
  623. // Some hosebag programs set the DTA to a selector that they later free!
  624. // This test makes sure that this does not cause us to crash.
  625. //
  626. if (!SEGMENT_IS_WRITABLE(CurrentDtaSelector)) {
  627. CurrentDtaSelector = 0;
  628. CurrentDtaOffset = 0;
  629. }
  630. setES(CurrentDtaSelector);
  631. setBX(CurrentDtaOffset);
  632. setCF(0);
  633. }
  634. VOID
  635. SetDTA(
  636. VOID
  637. )
  638. /*++
  639. Routine Description:
  640. This routine sets the PM dta address. If the buffer is usable directly,
  641. CurrentDta is set to the translated address. Otherwise, it is set to
  642. the dosx dta.
  643. N.B. The Set Dta call is not actually reflected to Dos until a function
  644. call is made that actually uses the Dta, e.g. the Find First/Next
  645. functions. This techique was implemented to match what is done in
  646. Win 3.1.
  647. Arguments:
  648. None.
  649. Return Value:
  650. None.
  651. --*/
  652. {
  653. DECLARE_LocalVdmContext;
  654. USHORT ClientDX;
  655. ClientDX = getDX();
  656. CurrentDtaOffset = ClientDX;
  657. CurrentDtaSelector = getDS();
  658. //
  659. // Make sure real DTA is updated later
  660. //
  661. CurrentDosDta = (PUCHAR) NULL;
  662. }
  663. VOID
  664. SetDTAPointers(
  665. VOID
  666. )
  667. /*++
  668. Routine Description:
  669. This routine sets up the flat address values used elsewhere to
  670. reference the current DTA.
  671. N.B. This must be done on every entry to handle function calls because
  672. the PM dta may have been GlobalRealloc'd. This may change the base
  673. address of the PM selector (which invalidates the flat addresses),
  674. but not the selector/offset itself.
  675. Arguments:
  676. None.
  677. Return Value:
  678. None.
  679. --*/
  680. {
  681. PUCHAR NewDta;
  682. NewDta = Sim32GetVDMPointer(
  683. (CurrentDtaSelector << 16),
  684. 1,
  685. TRUE
  686. );
  687. NewDta += CurrentDtaOffset;
  688. CurrentPmDtaAddress = NewDta;
  689. //
  690. // If the new dta is not accessible in v86 mode, use the one
  691. // supplied by Dosx
  692. //
  693. if ((ULONG)(NewDta + 128 - IntelBase) > MAX_V86_ADDRESS) {
  694. NewDta = DosxDtaBuffer;
  695. }
  696. //
  697. // Update Current DTA information
  698. //
  699. CurrentDta = NewDta;
  700. }
  701. VOID
  702. SetDosDTA(
  703. VOID
  704. )
  705. /*++
  706. Routine Description:
  707. This routine is called internally by other functions in this module
  708. to reflect a Set Dta call to Dos.
  709. WARNING: The client must be in REAL mode
  710. Arguments:
  711. None.
  712. Return Value:
  713. None.
  714. --*/
  715. {
  716. DECLARE_LocalVdmContext;
  717. USHORT ClientAX, ClientDX, ClientDS, NewDtaSegment, NewDtaOffset;
  718. ASSERT((getMSW() & MSW_PE) == 0);
  719. ClientAX = getAX();
  720. ClientDX = getDX();
  721. ClientDS = getDS();
  722. DPMI_FLAT_TO_SEGMENTED(CurrentDta, &NewDtaSegment, &NewDtaOffset);
  723. setDS(NewDtaSegment);
  724. setDX(NewDtaOffset);
  725. setAH(0x1a);
  726. DPMI_EXEC_INT(0x21);
  727. setAX(ClientAX);
  728. setDX(ClientDX);
  729. setDS(ClientDS);
  730. CurrentDosDta = CurrentDta;
  731. }
  732. VOID
  733. TSR(
  734. VOID
  735. )
  736. /*++
  737. Routine Description:
  738. This function translates int 21h tsr. Win 3.1 does some
  739. magic here. We didn't before and it worked fine. Maybe
  740. we will later.
  741. Arguments:
  742. None.
  743. Return Value:
  744. None.
  745. --*/
  746. {
  747. NoTranslation();
  748. }
  749. VOID
  750. GetDevParamBlock(
  751. VOID
  752. )
  753. /*++
  754. Routine Description:
  755. This routine translates the Device Parameter Block apis
  756. Arguments:
  757. None.
  758. Return Value:
  759. None.
  760. --*/
  761. {
  762. DECLARE_LocalVdmContext;
  763. USHORT Selector;
  764. DpmiSwitchToRealMode();
  765. DPMI_EXEC_INT(0x21);
  766. Selector = getDS();
  767. DpmiSwitchToProtectedMode();
  768. setDS(SegmentToSelector(Selector, STD_DATA));
  769. (*SetBXRegister)((ULONG)getBX());
  770. }
  771. VOID
  772. ReturnESBX(
  773. VOID
  774. )
  775. /*++
  776. Routine Description:
  777. This function translates api that return information in es:bx
  778. Arguments:
  779. None.
  780. Return Value:
  781. None.
  782. --*/
  783. {
  784. DECLARE_LocalVdmContext;
  785. USHORT Selector;
  786. DpmiSwitchToRealMode();
  787. DPMI_EXEC_INT(0x21);
  788. Selector = getES();
  789. DpmiSwitchToProtectedMode();
  790. (*SetBXRegister)((ULONG)getBX());
  791. setES(SegmentToSelector(Selector, STD_DATA));
  792. }
  793. VOID
  794. GetVector(
  795. VOID
  796. )
  797. /*++
  798. Routine Description:
  799. This function translates int 21 function 35
  800. Arguments:
  801. None.
  802. Return Value:
  803. None.
  804. --*/
  805. {
  806. DECLARE_LocalVdmContext;
  807. PVDM_INTERRUPTHANDLER Handlers = DpmiInterruptHandlers;
  808. USHORT IntNumber = getAL();
  809. setES(Handlers[IntNumber].CsSelector);
  810. (*SetBXRegister)(Handlers[IntNumber].Eip);
  811. }
  812. VOID
  813. GetSetCountry(
  814. VOID
  815. )
  816. /*++
  817. Routine Description:
  818. This function translates int 21 function 38
  819. Arguments:
  820. None.
  821. Return Value:
  822. None.
  823. --*/
  824. {
  825. DECLARE_LocalVdmContext;
  826. if (getDX() == 0xFFFF) {
  827. NoTranslation();
  828. } else {
  829. USHORT ClientDX, Seg, Off;
  830. PUCHAR Country, BufferedCountry;
  831. USHORT ClientDS = getDS();
  832. DpmiSwitchToRealMode();
  833. ClientDX = getDX();
  834. Country = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  835. + (*GetDXRegister)();
  836. BufferedCountry = DpmiMapAndCopyBuffer(Country, 34);
  837. DPMI_FLAT_TO_SEGMENTED(BufferedCountry, &Seg, &Off);
  838. setDS(Seg);
  839. setDX(Off);
  840. DPMI_EXEC_INT(0x21);
  841. DpmiSwitchToProtectedMode();
  842. DpmiUnmapAndCopyBuffer(Country, BufferedCountry, 34);
  843. setDX(ClientDX);
  844. setDS(ClientDS);
  845. }
  846. }
  847. VOID
  848. MapASCIIZDSDX(
  849. VOID
  850. )
  851. /*++
  852. Routine Description:
  853. This routine maps the int 21 functions that pass file names in
  854. ds:dx
  855. Arguments:
  856. None.
  857. Return Value:
  858. None.
  859. --*/
  860. {
  861. DECLARE_LocalVdmContext;
  862. PUCHAR BufferedString;
  863. USHORT ClientDX, StringSeg, StringOff, Length;
  864. USHORT ClientDS = getDS();
  865. DpmiSwitchToRealMode();
  866. ClientDX = getDX();
  867. BufferedString = DpmiMapString(ClientDS, (GetDXRegister)(), &Length);
  868. DPMI_FLAT_TO_SEGMENTED(BufferedString, &StringSeg, &StringOff);
  869. setDS(StringSeg);
  870. setDX(StringOff);
  871. DPMI_EXEC_INT(0x21);
  872. DpmiSwitchToProtectedMode();
  873. DpmiUnmapString(BufferedString, Length);
  874. setDX(ClientDX);
  875. setDS(ClientDS);
  876. }
  877. VOID
  878. ReadWriteFile(
  879. VOID
  880. )
  881. /*++
  882. Routine Description:
  883. This routine translates the read/write file int 21 calls. Large reads
  884. are broken down into 4k chunks.
  885. Arguments:
  886. None.
  887. Return Value:
  888. None.
  889. --*/
  890. {
  891. DECLARE_LocalVdmContext;
  892. USHORT ClientCX, ClientDX, ClientAX, Function, DataSeg, DataOff, BytesToRead;
  893. ULONG BytesRead, TotalBytesToRead;
  894. PUCHAR ReadWriteData, BufferedData;
  895. USHORT ClientDS = getDS();
  896. DpmiSwitchToRealMode();
  897. ClientCX = getCX();
  898. ClientDX = getDX();
  899. Function = getAH();
  900. ClientAX = getAX();
  901. TotalBytesToRead = (*GetCXRegister)();
  902. BytesRead = 0;
  903. ReadWriteData = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  904. + (*GetDXRegister)();
  905. // while (TotalBytesToRead != BytesRead) {
  906. do {
  907. if ((TotalBytesToRead - BytesRead) > 1024 * 4) {
  908. BytesToRead = 4 * 1024;
  909. } else {
  910. BytesToRead = (USHORT)(TotalBytesToRead - BytesRead);
  911. }
  912. BufferedData = DpmiMapAndCopyBuffer(ReadWriteData, BytesToRead);
  913. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  914. setDS(DataSeg);
  915. setDX(DataOff);
  916. setCX(BytesToRead);
  917. setAX(ClientAX);
  918. DPMI_EXEC_INT(0x21);
  919. if (getCF()) {
  920. DpmiUnmapBuffer(BufferedData, BytesToRead);
  921. break;
  922. }
  923. if (getAX() == 0) {
  924. DpmiUnmapBuffer(BufferedData, BytesToRead);
  925. break;
  926. } else if (getAX() < BytesToRead) {
  927. CopyMemory(ReadWriteData, BufferedData, getAX());
  928. DpmiUnmapBuffer(BufferedData, BytesToRead);
  929. BytesRead += getAX();
  930. break;
  931. } else {
  932. DpmiUnmapAndCopyBuffer(
  933. ReadWriteData,
  934. BufferedData,
  935. BytesToRead
  936. );
  937. }
  938. ReadWriteData += getAX();
  939. BytesRead += getAX();
  940. // }
  941. } while (TotalBytesToRead != BytesRead);
  942. setDX(ClientDX);
  943. setCX(ClientCX);
  944. if (!getCF()) {
  945. (*SetAXRegister)(BytesRead);
  946. }
  947. DpmiSwitchToProtectedMode();
  948. setDS(ClientDS);
  949. }
  950. #define MAX_SUPPORTED_DOS_IOCTL_CALL 0x10
  951. //
  952. // Note: The translations here differ from those in the windows dpmi vxd,
  953. // because we do not have to lock memory, and we don't support block
  954. // device drivers.
  955. //
  956. APIXLATFUNCTION IOCTLXlatTable[MAX_SUPPORTED_DOS_IOCTL_CALL] = {
  957. NoTranslation , // 00 - Get Device Data
  958. NoTranslation , // 01 - Set Device Data
  959. MapDSDXLenCX , // 02 - Receive Ctrl Chr Data
  960. MapDSDXLenCX , // 03 - Send Ctrl Chr Data
  961. MapDSDXLenCX , // 04 - Receive Ctrl Block Data
  962. MapDSDXLenCX , // 05 - Send Ctrl Block Data
  963. NoTranslation , // 06 - Check Input Status
  964. NoTranslation , // 07 - Check Output Status
  965. NoTranslation , // 08 - Check Block Dev Removable
  966. NoTranslation , // 09 - Check Block Dev Remote
  967. NoTranslation , // 0A - Check if Handle Remote
  968. NoTranslation , // 0B - Change sharing retry cnt
  969. IOCTLMap2Bytes , // 0C - MAP DS:DX LENGTH 2!
  970. IOCTLBlockDevs , // 0D - Generic IOCTL to blk dev
  971. NoTranslation , // 0E - Get Logical Drive Map
  972. NoTranslation // 0F - Set Logical Drive Map
  973. };
  974. VOID
  975. IOCTL(
  976. VOID
  977. )
  978. /*++
  979. Routine Description:
  980. This function translates the int 21 ioctl function.
  981. Arguments:
  982. None.
  983. Return Value:
  984. None.
  985. --*/
  986. {
  987. DECLARE_LocalVdmContext;
  988. USHORT IoctlMinor;
  989. IoctlMinor = getAL();
  990. if (IoctlMinor >= MAX_SUPPORTED_DOS_IOCTL_CALL) {
  991. #if DBG
  992. OutputDebugString("DPMI: IOCTL DOS CALL NOT SUPPORTED\n");
  993. #endif
  994. NoTranslation();
  995. return;
  996. }
  997. (*IOCTLXlatTable[IoctlMinor])();
  998. }
  999. VOID
  1000. GetCurDir(
  1001. VOID
  1002. )
  1003. /*++
  1004. Routine Description:
  1005. This routine translates the get current directory call
  1006. Arguments:
  1007. None.
  1008. Return Value:
  1009. None.
  1010. --*/
  1011. {
  1012. DECLARE_LocalVdmContext;
  1013. PUCHAR DirInfo, BufferedDirInfo;
  1014. USHORT ClientSI, Seg, Off;
  1015. USHORT ClientDS = getDS();
  1016. DpmiSwitchToRealMode();
  1017. ClientSI = getSI();
  1018. DirInfo = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  1019. + (*GetSIRegister)();
  1020. BufferedDirInfo = DpmiMapAndCopyBuffer(DirInfo, 64);
  1021. DPMI_FLAT_TO_SEGMENTED(BufferedDirInfo, &Seg, &Off);
  1022. setDS(Seg);
  1023. setSI(Off);
  1024. DPMI_EXEC_INT(0x21);
  1025. DpmiSwitchToProtectedMode();
  1026. DpmiUnmapAndCopyBuffer(DirInfo, BufferedDirInfo, 64);
  1027. setSI(ClientSI);
  1028. setDS(ClientDS);
  1029. }
  1030. VOID
  1031. AllocateMemoryBlock(
  1032. VOID
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. This routine translates the AllocateMemory Int 21 api
  1037. Arguments:
  1038. None.
  1039. Return Value:
  1040. None.
  1041. --*/
  1042. {
  1043. DECLARE_LocalVdmContext;
  1044. PMEM_DPMI pMem;
  1045. ULONG MemSize = ((ULONG)getBX()) << 4;
  1046. pMem = DpmiAllocateXmem(MemSize);
  1047. if (pMem) {
  1048. pMem->SelCount = (USHORT) ((MemSize>>16) + 1);
  1049. pMem->Sel = ALLOCATE_SELECTORS(pMem->SelCount);
  1050. if (!pMem->Sel) {
  1051. pMem->SelCount = 0;
  1052. DpmiFreeXmem(pMem);
  1053. pMem = NULL;
  1054. } else {
  1055. SetDescriptorArray(pMem->Sel, (ULONG)pMem->Address, MemSize);
  1056. }
  1057. }
  1058. if (!pMem) {
  1059. setCF(1);
  1060. setAX(8);
  1061. setBX(0);
  1062. } else {
  1063. setCF(0);
  1064. setAX(pMem->Sel);
  1065. }
  1066. }
  1067. VOID
  1068. FreeMemoryBlock(
  1069. VOID
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. This routine translates the ResizeMemory Int 21 api
  1074. Arguments:
  1075. None.
  1076. Return Value:
  1077. None.
  1078. --*/
  1079. {
  1080. DECLARE_LocalVdmContext;
  1081. PMEM_DPMI pMem;
  1082. USHORT Sel = getES();
  1083. if (pMem = DpmiFindXmem(Sel)) {
  1084. while(pMem->SelCount--) {
  1085. FreeSelector(Sel);
  1086. Sel+=8;
  1087. }
  1088. DpmiFreeXmem(pMem);
  1089. setCF(0);
  1090. } else {
  1091. setCF(1);
  1092. setAX(9);
  1093. }
  1094. }
  1095. VOID
  1096. ResizeMemoryBlock(
  1097. VOID
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. This routine translates the ResizeMemory int 21 api
  1102. Arguments:
  1103. None.
  1104. Return Value:
  1105. None.
  1106. --*/
  1107. {
  1108. DECLARE_LocalVdmContext;
  1109. PMEM_DPMI pMem;
  1110. ULONG MemSize = ((ULONG)getBX()) << 4;
  1111. USHORT Sel = getES();
  1112. if (pMem = DpmiFindXmem(Sel)) {
  1113. if (DpmiReallocateXmem(pMem, MemSize)) {
  1114. SetDescriptorArray(pMem->Sel, (ULONG)pMem->Address, MemSize);
  1115. setCF(0);
  1116. } else {
  1117. // not enough memory
  1118. setCF(1);
  1119. setAX(8);
  1120. }
  1121. } else {
  1122. // invalid block
  1123. setCF(1);
  1124. setAX(9);
  1125. }
  1126. }
  1127. VOID
  1128. LoadExec(
  1129. VOID
  1130. )
  1131. /*++
  1132. Routine Description:
  1133. This function translates the int 21 load exec function. Load overlay
  1134. is not supported.
  1135. The child always inherits the environment, and the fcbs in the parameter
  1136. block are ignored. (win 3.1 does this)
  1137. Arguments:
  1138. None.
  1139. Return Value:
  1140. None.
  1141. --*/
  1142. {
  1143. DECLARE_LocalVdmContext;
  1144. PUCHAR CommandTail, BufferedString, Environment;
  1145. USHORT ClientDX, ClientBX, Seg, Off, Length, i, EnvironmentSel;
  1146. USHORT ClientDS = getDS();
  1147. USHORT ClientES = getES();
  1148. DpmiSwitchToRealMode();
  1149. ClientDX = getDX();
  1150. ClientBX = getBX();
  1151. if (getAL() == 3) {
  1152. setCF(1);
  1153. setAX(1);
  1154. } else {
  1155. //
  1156. // Make sure real DTA is updated later
  1157. //
  1158. CurrentDosDta = (PUCHAR) NULL;
  1159. //
  1160. // Map the command string
  1161. //
  1162. BufferedString = DpmiMapString(ClientDS, (*GetDXRegister)(), &Length);
  1163. //
  1164. // Set up the Parameter block
  1165. //
  1166. // We use the large xlat buffer. The parameter block comes
  1167. // first, and we fill in the command tail after
  1168. //
  1169. ZeroMemory(LargeXlatBuffer, 512);
  1170. //
  1171. // The environment segment address is now set
  1172. //
  1173. //
  1174. // Set the command tail address, and copy the command tail (all
  1175. // 128 bytes
  1176. //
  1177. DPMI_FLAT_TO_SEGMENTED((LargeXlatBuffer + 0x10), &Seg, &Off)
  1178. *(PWORD16)(LargeXlatBuffer + 2) = Off;
  1179. *(PWORD16)(LargeXlatBuffer + 4) = Seg;
  1180. //
  1181. // CommandTail = FLAT(es:bx)
  1182. //
  1183. CommandTail = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE)
  1184. + (*GetBXRegister)();
  1185. if (CurrentAppFlags & DPMI_32BIT) {
  1186. //
  1187. // CommandTail -> string
  1188. //
  1189. CommandTail = Sim32GetVDMPointer((*(PWORD16)(CommandTail + 4)) << 16, 1, TRUE)
  1190. + *(PDWORD16)(CommandTail);
  1191. } else {
  1192. //
  1193. // CommandTail -> string
  1194. //
  1195. CommandTail = Sim32GetVDMPointer(*(PDWORD16)(CommandTail + 2), 1, TRUE);
  1196. }
  1197. CopyMemory((LargeXlatBuffer + 0x10), CommandTail, 128);
  1198. //
  1199. // Set FCB pointers and put spaces in the file names
  1200. //
  1201. DPMI_FLAT_TO_SEGMENTED((LargeXlatBuffer + 144), &Seg, &Off)
  1202. *(PWORD16)(LargeXlatBuffer + 6) = Off;
  1203. *(PWORD16)(LargeXlatBuffer + 8) = Seg;
  1204. for (i = 0; i < 11; i++) {
  1205. (LargeXlatBuffer + 144 + 1)[i] = ' ';
  1206. }
  1207. DPMI_FLAT_TO_SEGMENTED((LargeXlatBuffer + 188), &Seg, &Off)
  1208. *(PWORD16)(LargeXlatBuffer + 0xA) = Off;
  1209. *(PWORD16)(LargeXlatBuffer + 0xC) = Seg;
  1210. for (i = 0; i < 11; i++) {
  1211. (LargeXlatBuffer + 188 + 1)[i] = ' ';
  1212. }
  1213. //
  1214. // Save the environment selector, and make it a segment
  1215. //
  1216. Environment = Sim32GetVDMPointer(((ULONG)CurrentPSPSelector << 16) | 0x2C, 1, TRUE);
  1217. EnvironmentSel = *(PWORD16)Environment;
  1218. *(PWORD16)Environment =
  1219. (USHORT)(SELECTOR_TO_INTEL_LINEAR_ADDRESS(EnvironmentSel) >> 4);
  1220. //
  1221. // Set up registers for the exec
  1222. //
  1223. DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &Off);
  1224. setDS(Seg);
  1225. setDX(Off);
  1226. DPMI_FLAT_TO_SEGMENTED(LargeXlatBuffer, &Seg, &Off);
  1227. setES(Seg);
  1228. setBX(Off);
  1229. DPMI_EXEC_INT(0x21);
  1230. //
  1231. // Restore the environment selector
  1232. //
  1233. Environment = Sim32GetVDMPointer(((ULONG)CurrentPSPSelector << 16) | 0x2C, 1, TRUE);
  1234. *(PWORD16)Environment = EnvironmentSel;
  1235. //
  1236. // Free translation buffer
  1237. //
  1238. DpmiUnmapString(BufferedString, Length);
  1239. }
  1240. setDX(ClientDX);
  1241. setBX(ClientBX);
  1242. DpmiSwitchToProtectedMode();
  1243. setES(ClientES);
  1244. setDS(ClientDS);
  1245. }
  1246. VOID
  1247. Terminate(
  1248. VOID
  1249. )
  1250. /*++
  1251. Routine Description:
  1252. description-of-function.
  1253. Arguments:
  1254. argument-name - Supplies | Returns description of argument.
  1255. .
  1256. .
  1257. Return Value:
  1258. return-value - Description of conditions needed to return value. - or -
  1259. None.
  1260. --*/
  1261. {
  1262. // bugbug We're currently mapping this one in the dos extender
  1263. }
  1264. VOID
  1265. FindFirstFileHandle(
  1266. VOID
  1267. )
  1268. /*++
  1269. Routine Description:
  1270. This routine translates the find first api.
  1271. Arguments:
  1272. None.
  1273. Return Value:
  1274. None.
  1275. --*/
  1276. {
  1277. DECLARE_LocalVdmContext;
  1278. USHORT ClientDX, Seg, Off, StringLength;
  1279. PUCHAR BufferedString;
  1280. USHORT ClientDS = getDS();
  1281. DpmiSwitchToRealMode();
  1282. SetDTAPointers();
  1283. ClientDX = getDX();
  1284. //
  1285. // Copy the DTA (if necessary)
  1286. //
  1287. if (CurrentDta != CurrentPmDtaAddress) {
  1288. CopyMemory(CurrentDta, CurrentPmDtaAddress, 43);
  1289. }
  1290. //
  1291. // Check to see if we need to set the real dta
  1292. //
  1293. if (CurrentDosDta != CurrentDta)
  1294. SetDosDTA();
  1295. //
  1296. // map the string
  1297. //
  1298. BufferedString = DpmiMapString(ClientDS, (GetDXRegister)(), &StringLength);
  1299. DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &Off);
  1300. setDS(Seg);
  1301. setDX(Off);
  1302. DPMI_EXEC_INT(0x21);
  1303. DpmiSwitchToProtectedMode();
  1304. setDS(ClientDS);
  1305. DpmiUnmapString(BufferedString, StringLength);
  1306. //
  1307. // Copy the DTA back (if necessary)
  1308. //
  1309. if (CurrentDta != CurrentPmDtaAddress) {
  1310. CopyMemory(CurrentPmDtaAddress, CurrentDta, 43);
  1311. }
  1312. setDX(ClientDX);
  1313. }
  1314. VOID
  1315. FindNextFileHandle(
  1316. VOID
  1317. )
  1318. /*++
  1319. Routine Description:
  1320. This routine translates the find next api
  1321. Arguments:
  1322. None.
  1323. Return Value:
  1324. None.
  1325. --*/
  1326. {
  1327. DECLARE_LocalVdmContext;
  1328. DpmiSwitchToRealMode();
  1329. SetDTAPointers();
  1330. //
  1331. // Copy the DTA (if necessary)
  1332. //
  1333. if (CurrentDta != CurrentPmDtaAddress) {
  1334. CopyMemory(CurrentDta, CurrentPmDtaAddress, 43);
  1335. }
  1336. //
  1337. // Check to see if we need to set the real dta
  1338. //
  1339. if (CurrentDosDta != CurrentDta)
  1340. SetDosDTA();
  1341. DPMI_EXEC_INT(0x21);
  1342. DpmiSwitchToProtectedMode();
  1343. //
  1344. // Copy the DTA back (if necessary)
  1345. //
  1346. if (CurrentDta != CurrentPmDtaAddress) {
  1347. CopyMemory(CurrentPmDtaAddress, CurrentDta, 43);
  1348. }
  1349. }
  1350. VOID
  1351. SetPSP(
  1352. VOID
  1353. )
  1354. /*++
  1355. Routine Description:
  1356. This routine translates the set psp api. This is substantially the
  1357. same as CreatePSP, except that this can fail (and return carry). It
  1358. also remembers the PSP selector, so we can return it on request.
  1359. Arguments:
  1360. None.
  1361. Return Value:
  1362. None.
  1363. --*/
  1364. {
  1365. DECLARE_LocalVdmContext;
  1366. ULONG Segment;
  1367. USHORT ClientBX;
  1368. DpmiSwitchToRealMode();
  1369. ClientBX = getBX();
  1370. if (ClientBX == 0) {
  1371. CurrentPSPSelector = ClientBX;
  1372. } else {
  1373. Segment = SELECTOR_TO_INTEL_LINEAR_ADDRESS(ClientBX);
  1374. if (Segment > ONE_MB) {
  1375. setCF(1);
  1376. } else {
  1377. setBX((USHORT) (Segment >> 4));
  1378. DPMI_EXEC_INT(0x21);
  1379. CurrentPSPSelector = ClientBX;
  1380. }
  1381. }
  1382. setBX(ClientBX);
  1383. DpmiSwitchToProtectedMode();
  1384. }
  1385. VOID
  1386. GetPSP(
  1387. VOID
  1388. )
  1389. /*++
  1390. Routine Description:
  1391. This routine returns the current PSP selector
  1392. Arguments:
  1393. None.
  1394. Return Value:
  1395. None.
  1396. --*/
  1397. {
  1398. DECLARE_LocalVdmContext;
  1399. DpmiSwitchToRealMode();
  1400. //
  1401. // Get the current psp segment to see if it changed
  1402. //
  1403. DPMI_EXEC_INT(0x21);
  1404. DpmiSwitchToProtectedMode();
  1405. //
  1406. // If it changed get a new selector for the psp
  1407. //
  1408. if (getBX() !=
  1409. (USHORT)(SELECTOR_TO_INTEL_LINEAR_ADDRESS(CurrentPSPSelector) >> 4)
  1410. ){
  1411. CurrentPSPSelector = SegmentToSelector(getBX(), STD_DATA);
  1412. }
  1413. setBX(CurrentPSPSelector);
  1414. setCF(0);
  1415. }
  1416. VOID
  1417. TranslateBPB(
  1418. VOID
  1419. )
  1420. /*++
  1421. Routine Description:
  1422. This function fails and returns. On NT we do not support this dos
  1423. call.
  1424. Arguments:
  1425. None.
  1426. Return Value:
  1427. None.
  1428. --*/
  1429. {
  1430. DECLARE_LocalVdmContext;
  1431. #if DBG
  1432. OutputDebugString("DPMI: Int 21 function 53 is not supported\n");
  1433. #endif
  1434. setCF(1);
  1435. }
  1436. VOID
  1437. RenameFile(
  1438. VOID
  1439. )
  1440. /*++
  1441. Routine Description:
  1442. This routine translates the rename int 21 api
  1443. Arguments:
  1444. None.
  1445. Return Value:
  1446. None.
  1447. --*/
  1448. {
  1449. DECLARE_LocalVdmContext;
  1450. PUCHAR SourceString, DestinationString;
  1451. USHORT ClientDX, ClientDI, Seg, Off, SourceLength, DestinationLength;
  1452. USHORT ClientDS = getDS();
  1453. USHORT ClientES = getES();
  1454. DpmiSwitchToRealMode();
  1455. ClientDX = getDX();
  1456. ClientDI = getDI();
  1457. SourceString = DpmiMapString(ClientDS, (*GetDXRegister)(), &SourceLength);
  1458. DestinationString = DpmiMapString(ClientES, (*GetDIRegister)(), &DestinationLength);
  1459. DPMI_FLAT_TO_SEGMENTED(SourceString, &Seg, &Off);
  1460. setDX(Off);
  1461. setDS(Seg);
  1462. DPMI_FLAT_TO_SEGMENTED(DestinationString, &Seg, &Off);
  1463. setDI(Off);
  1464. setES(Seg);
  1465. DPMI_EXEC_INT(0x21);
  1466. setDX(ClientDX);
  1467. setDI(ClientDI);
  1468. DpmiSwitchToProtectedMode();
  1469. setDS(ClientDS);
  1470. setES(ClientES);
  1471. }
  1472. VOID
  1473. CreateTempFile(
  1474. VOID
  1475. )
  1476. /*++
  1477. Routine Description:
  1478. This function maps the int 21 create temp file api
  1479. Arguments:
  1480. None.
  1481. Return Value:
  1482. None.
  1483. --*/
  1484. {
  1485. DECLARE_LocalVdmContext;
  1486. PUCHAR String, BufferedString;
  1487. USHORT ClientDX, Seg, Off, Length;
  1488. USHORT ClientDS = getDS();
  1489. DpmiSwitchToRealMode();
  1490. ClientDX = getDX();
  1491. String = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  1492. + (*GetDXRegister)();
  1493. Length = 0;
  1494. while (String[Length] != '\0') {
  1495. Length++;
  1496. }
  1497. Length += 13;
  1498. BufferedString = DpmiMapAndCopyBuffer(String, Length);
  1499. DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &Off);
  1500. setDS(Seg);
  1501. setDX(Off);
  1502. DPMI_EXEC_INT(0x21);
  1503. DpmiSwitchToProtectedMode();
  1504. DpmiUnmapAndCopyBuffer(String, BufferedString, Length);
  1505. setDX(ClientDX);
  1506. setDS(ClientDS);
  1507. }
  1508. #define MAX_SUPPORTED_DOS_5D_CALL 12
  1509. APIXLATFUNCTION Func5DXlatTable[MAX_SUPPORTED_DOS_5D_CALL] = {
  1510. NotSupportedBad , // 0
  1511. MapDPL , // 1
  1512. NotSupportedBad , // 2
  1513. MapDPL , // 3
  1514. MapDPL , // 4
  1515. NotSupportedBad , // 5
  1516. NotSupportedBad , // 6
  1517. NoTranslation , // 7
  1518. NoTranslation , // 8
  1519. NoTranslation , // 9
  1520. MapDPL , // 10
  1521. NotSupportedBad // 11
  1522. };
  1523. VOID
  1524. Func5Dh(
  1525. VOID
  1526. )
  1527. /*++
  1528. Routine Description:
  1529. This function translates dos call 5d
  1530. Arguments:
  1531. None.
  1532. Return Value:
  1533. None.
  1534. --*/
  1535. {
  1536. DECLARE_LocalVdmContext;
  1537. USHORT Func5DhMinor;
  1538. Func5DhMinor = getAL();
  1539. if (Func5DhMinor >= MAX_SUPPORTED_DOS_5D_CALL) {
  1540. #if DBG
  1541. OutputDebugString("DPMI: DOS FUNCTION 5D UNSUPPORTED\n");
  1542. #endif
  1543. NoTranslation();
  1544. return;
  1545. }
  1546. (*Func5DXlatTable[Func5DhMinor])();
  1547. }
  1548. #define MAX_SUPPORTED_DOS_5E_CALL 4
  1549. APIXLATFUNCTION Func5EXlatTable[MAX_SUPPORTED_DOS_5E_CALL] = {
  1550. GetMachineName,
  1551. MapASCIIZDSDX,
  1552. GetPrinterSetup,
  1553. SetPrinterSetup
  1554. };
  1555. VOID
  1556. Func5Eh(
  1557. VOID
  1558. )
  1559. /*++
  1560. Routine Description:
  1561. description-of-function.
  1562. Arguments:
  1563. argument-name - Supplies | Returns description of argument.
  1564. .
  1565. .
  1566. Return Value:
  1567. return-value - Description of conditions needed to return value. - or -
  1568. None.
  1569. --*/
  1570. {
  1571. DECLARE_LocalVdmContext;
  1572. USHORT Func5EhMinor;
  1573. Func5EhMinor = getAL();
  1574. if (Func5EhMinor >= MAX_SUPPORTED_DOS_5E_CALL) {
  1575. #if DBG
  1576. OutputDebugString("DPMI: DOS FUNCTION 5E UNSUPPORTED\n");
  1577. #endif
  1578. NoTranslation();
  1579. return;
  1580. }
  1581. (*Func5EXlatTable[Func5EhMinor])();
  1582. }
  1583. VOID
  1584. Func5Fh(
  1585. VOID
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. description-of-function.
  1590. Arguments:
  1591. argument-name - Supplies | Returns description of argument.
  1592. .
  1593. .
  1594. Return Value:
  1595. return-value - Description of conditions needed to return value. - or -
  1596. None.
  1597. --*/
  1598. {
  1599. DECLARE_LocalVdmContext;
  1600. USHORT Func5FMinor;
  1601. Func5FMinor = getAL();
  1602. if (Func5FMinor == 4) {
  1603. MapASCIIZDSSI();
  1604. return;
  1605. } else if ((Func5FMinor == 2) || (Func5FMinor == 3) ||
  1606. (Func5FMinor == 5)
  1607. ){
  1608. USHORT ClientSI, ClientDI, DataOff, DataSeg;
  1609. PUCHAR Data16, BufferedData16, Data128, BufferedData128;
  1610. USHORT ClientDS = getDS();
  1611. USHORT ClientES = getES();
  1612. DpmiSwitchToRealMode();
  1613. ClientDI = getDI();
  1614. ClientSI = getSI();
  1615. Data16 = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  1616. + (*GetSIRegister)();
  1617. BufferedData16 = DpmiMapAndCopyBuffer(Data16, 16);
  1618. Data128 = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE)
  1619. + (*GetDIRegister)();
  1620. BufferedData128 = DpmiMapAndCopyBuffer(Data128, 128);
  1621. DPMI_FLAT_TO_SEGMENTED(BufferedData16, &DataSeg, &DataOff);
  1622. setDS(DataSeg);
  1623. setSI(DataOff);
  1624. DPMI_FLAT_TO_SEGMENTED(BufferedData128, &DataSeg, &DataOff);
  1625. setES(DataSeg);
  1626. setDI(DataOff);
  1627. DPMI_EXEC_INT(0x21);
  1628. DpmiSwitchToProtectedMode();
  1629. DpmiUnmapAndCopyBuffer(Data16, BufferedData16, 16);
  1630. DpmiUnmapAndCopyBuffer(Data128, BufferedData128, 128);
  1631. setDS(ClientDS);
  1632. setES(ClientES);
  1633. setSI(ClientSI);
  1634. setDI(ClientDI);
  1635. } else {
  1636. #if DBG
  1637. OutputDebugString("DPMI: UNSUPPORTED INT 21 FUNCTION 5F\n");
  1638. #endif
  1639. NoTranslation();
  1640. }
  1641. }
  1642. VOID
  1643. NotSupportedBad(
  1644. VOID
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. description-of-function.
  1649. Arguments:
  1650. argument-name - Supplies | Returns description of argument.
  1651. .
  1652. .
  1653. Return Value:
  1654. return-value - Description of conditions needed to return value. - or -
  1655. None.
  1656. --*/
  1657. {
  1658. #if DBG
  1659. DECLARE_LocalVdmContext;
  1660. DbgPrint("WARNING: DOS INT 21 call AX= %x will not be translated.\n", getAH());
  1661. DbgPrint(" Use of this call is not supported from Prot\n");
  1662. DbgPrint(" mode applications.\n");
  1663. #endif
  1664. NoTranslation();
  1665. }
  1666. VOID
  1667. ReturnDSSI(
  1668. VOID
  1669. )
  1670. /*++
  1671. Routine Description:
  1672. This function translates api that return information in ds:si
  1673. Arguments:
  1674. None.
  1675. Return Value:
  1676. None.
  1677. --*/
  1678. {
  1679. DECLARE_LocalVdmContext;
  1680. USHORT Selector;
  1681. DpmiSwitchToRealMode();
  1682. DPMI_EXEC_INT(0x21);
  1683. Selector = getDS();
  1684. DpmiSwitchToProtectedMode();
  1685. (*SetSIRegister)((ULONG)getSI());
  1686. setDS(SegmentToSelector(Selector, STD_DATA));
  1687. }
  1688. VOID
  1689. NotSupportedBetter(
  1690. VOID
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. description-of-function.
  1695. Arguments:
  1696. argument-name - Supplies | Returns description of argument.
  1697. .
  1698. .
  1699. Return Value:
  1700. return-value - Description of conditions needed to return value. - or -
  1701. None.
  1702. --*/
  1703. {
  1704. #if DBG
  1705. DECLARE_LocalVdmContext;
  1706. DbgPrint("WARNING: DOS INT 21 call AX= %x will not be translated.", getAH());
  1707. DbgPrint(" Use of this call by a Prot Mode app is not");
  1708. DbgPrint(" appropriate. There is a better INT 21 call, or a");
  1709. DbgPrint(" Windows call which should be used instead of this.");
  1710. #endif
  1711. NoTranslation();
  1712. }
  1713. VOID
  1714. GetExtendedCountryInfo(
  1715. VOID
  1716. )
  1717. /*++
  1718. Routine Description:
  1719. This routine translates the get extended country info int 21 api
  1720. Arguments:
  1721. None.
  1722. Return Value:
  1723. None.
  1724. --*/
  1725. {
  1726. DECLARE_LocalVdmContext;
  1727. PUCHAR Country, BufferedCountry;
  1728. USHORT ClientDI, Seg, Off, Length;
  1729. USHORT ClientES = getES();
  1730. DpmiSwitchToRealMode();
  1731. ClientDI = getDI();
  1732. Length = getCX();
  1733. Country = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE)
  1734. + (*GetDIRegister)();
  1735. BufferedCountry = DpmiMapAndCopyBuffer(Country, Length);
  1736. DPMI_FLAT_TO_SEGMENTED(BufferedCountry, &Seg, &Off);
  1737. setES(Seg);
  1738. setDI(Off);
  1739. DPMI_EXEC_INT(0x21);
  1740. DpmiSwitchToProtectedMode();
  1741. setES(ClientES);
  1742. DpmiUnmapAndCopyBuffer(Country, BufferedCountry, Length);
  1743. setDI(ClientDI);
  1744. }
  1745. VOID
  1746. MapASCIIZDSSI(
  1747. VOID
  1748. )
  1749. /*++
  1750. Routine Description:
  1751. This function translates the int 21 extended open call
  1752. Arguments:
  1753. None.
  1754. Return Value:
  1755. None.
  1756. --*/
  1757. {
  1758. DECLARE_LocalVdmContext;
  1759. PUCHAR BufferedString;
  1760. USHORT ClientSI, StringSeg, StringOff, Length;
  1761. USHORT ClientDS = getDS();
  1762. DpmiSwitchToRealMode();
  1763. ClientSI = getSI();
  1764. BufferedString = DpmiMapString(ClientDS, (*GetSIRegister)(), &Length);
  1765. DPMI_FLAT_TO_SEGMENTED(BufferedString, &StringSeg, &StringOff);
  1766. setDS(StringSeg);
  1767. setSI(StringOff);
  1768. DPMI_EXEC_INT(0x21);
  1769. DpmiSwitchToProtectedMode();
  1770. DpmiUnmapString(BufferedString, Length);
  1771. setSI(ClientSI);
  1772. setDS(ClientDS);
  1773. }
  1774. VOID
  1775. MapDSDXLenCX(
  1776. VOID
  1777. )
  1778. /*++
  1779. Routine Description:
  1780. This function maps the ioctl calls that pass data in DS:DX, with
  1781. length in cx
  1782. Arguments:
  1783. None.
  1784. Return Value:
  1785. None.
  1786. --*/
  1787. {
  1788. DECLARE_LocalVdmContext;
  1789. USHORT ClientDX, ClientCX, DataSeg, DataOff;
  1790. PUCHAR Data, BufferedData;
  1791. USHORT ClientDS = getDS();
  1792. DpmiSwitchToRealMode();
  1793. ClientDX = getDX();
  1794. ClientCX = getCX();
  1795. Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  1796. + (*GetDXRegister)();
  1797. BufferedData = DpmiMapAndCopyBuffer(Data, ClientCX);
  1798. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  1799. setDS(DataSeg);
  1800. setDX(DataOff);
  1801. DPMI_EXEC_INT(0x21);
  1802. DpmiSwitchToProtectedMode();
  1803. DpmiUnmapAndCopyBuffer(Data, BufferedData, ClientCX);
  1804. setDS(ClientDS);
  1805. setDX(ClientDX);
  1806. }
  1807. VOID
  1808. IOCTLMap2Bytes(
  1809. VOID
  1810. )
  1811. /*++
  1812. Routine Description:
  1813. description-of-function.
  1814. Arguments:
  1815. argument-name - Supplies | Returns description of argument.
  1816. .
  1817. .
  1818. Return Value:
  1819. return-value - Description of conditions needed to return value. - or -
  1820. None.
  1821. --*/
  1822. {
  1823. DECLARE_LocalVdmContext;
  1824. USHORT ClientDX, DataSeg, DataOff;
  1825. PUCHAR Data, BufferedData;
  1826. USHORT ClientDS = getDS();
  1827. DpmiSwitchToRealMode();
  1828. ClientDX = getDX();
  1829. Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE);
  1830. BufferedData = DpmiMapAndCopyBuffer(Data, 2);
  1831. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  1832. setDS(DataSeg);
  1833. setDX(DataOff);
  1834. DPMI_EXEC_INT(0x21);
  1835. DpmiSwitchToProtectedMode();
  1836. DpmiUnmapAndCopyBuffer(Data, BufferedData, 2);
  1837. setDS(ClientDS);
  1838. setDX(ClientDX);
  1839. }
  1840. VOID
  1841. IOCTLBlockDevs(
  1842. VOID
  1843. )
  1844. /*++
  1845. Routine Description:
  1846. This function fails the block device ioctls
  1847. Arguments:
  1848. None.
  1849. Return Value:
  1850. None.
  1851. --*/
  1852. {
  1853. DECLARE_LocalVdmContext;
  1854. USHORT IoctlSubFunction, Seg, Off, ClientDX;
  1855. PUCHAR Data, BufferedData;
  1856. USHORT Length;
  1857. USHORT ClientDS = getDS();
  1858. IoctlSubFunction = getCL();
  1859. if ((IoctlSubFunction < 0x40) || (IoctlSubFunction > 0x42) &&
  1860. (IoctlSubFunction < 0x60) || (IoctlSubFunction > 0x62) &&
  1861. (IoctlSubFunction != 0x68)
  1862. ) {
  1863. #if DBG
  1864. OutputDebugString("DPMI: IOCTL DOS CALL NOT SUPPORTED\n");
  1865. #endif
  1866. NoTranslation();
  1867. return;
  1868. }
  1869. //
  1870. // Read and write track are special (and a pain)
  1871. //
  1872. if ((IoctlSubFunction == 0x41) || (IoctlSubFunction == 0x61)) {
  1873. IoctlReadWriteTrack();
  1874. return;
  1875. }
  1876. DpmiSwitchToRealMode();
  1877. ClientDX = getDX();
  1878. Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  1879. + (*GetDXRegister)();
  1880. switch (IoctlSubFunction) {
  1881. case 0x40:
  1882. //
  1883. // Map set device params
  1884. //
  1885. Length = (*(PWORD16)(Data + 0x26));
  1886. Length <<= 2;
  1887. Length += 0x28;
  1888. break;
  1889. case 0x60:
  1890. //
  1891. // Map get device params
  1892. //
  1893. Length = 38;
  1894. break;
  1895. case 0x62:
  1896. //
  1897. // Map format verify
  1898. //
  1899. Length = 5;
  1900. break;
  1901. case 0x68:
  1902. //
  1903. // Map Media sense
  1904. //
  1905. Length = 4;
  1906. break;
  1907. }
  1908. BufferedData = DpmiMapAndCopyBuffer(Data, Length);
  1909. DPMI_FLAT_TO_SEGMENTED(BufferedData, &Seg, &Off);
  1910. setDS(Seg);
  1911. setDX(Off);
  1912. DPMI_EXEC_INT(0x21);
  1913. DpmiSwitchToProtectedMode();
  1914. DpmiUnmapAndCopyBuffer(Data, BufferedData, Length);
  1915. setDS(ClientDS);
  1916. setDX(ClientDX);
  1917. }
  1918. VOID
  1919. IoctlReadWriteTrack(
  1920. VOID
  1921. )
  1922. /*++
  1923. Routine Description:
  1924. This routine maps the read/write track ioctl.
  1925. Arguments:
  1926. None.
  1927. Return Value:
  1928. None.
  1929. --*/
  1930. {
  1931. DECLARE_LocalVdmContext;
  1932. USHORT ClientDX, ClientDS, ClientCX, ClientAX;
  1933. USHORT Seg, Off, NumberOfSectors, BytesPerSector;
  1934. USHORT SectorsRead, SectorsToRead;
  1935. PUCHAR ParameterBlock, BufferedPBlock, Data, BufferedData;
  1936. ClientAX = getAX();
  1937. ClientDX = getDX();
  1938. ClientCX = getCX();
  1939. ClientDS = getDS();
  1940. DpmiSwitchToRealMode();
  1941. //
  1942. // Find out how many bytes/sector
  1943. //
  1944. BufferedData = DpmiAllocateBuffer(0x40);
  1945. DPMI_FLAT_TO_SEGMENTED(BufferedData, &Seg, &Off);
  1946. setDS(Seg);
  1947. setDX(Off);
  1948. setAX(0x440D);
  1949. setCX(0x860);
  1950. DPMI_EXEC_INT(0x21);
  1951. if (getCF()) {
  1952. //
  1953. // Failed, we don't know how much data to buffer,
  1954. // so fail read/write track
  1955. //
  1956. DpmiFreeBuffer(BufferedData, 0x40);
  1957. setDX(ClientDX);
  1958. setCX(ClientCX);
  1959. DpmiSwitchToProtectedMode();
  1960. setDS(ClientDS);
  1961. return;
  1962. }
  1963. //
  1964. // Get the number of bytes/sector
  1965. //
  1966. BytesPerSector = *(PWORD16)(BufferedData + 0x7);
  1967. DpmiFreeBuffer(BufferedData, 0x40);
  1968. setDX(ClientDX);
  1969. //
  1970. // First map the parameter block
  1971. //
  1972. ParameterBlock = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  1973. + (*GetDXRegister)();
  1974. BufferedPBlock = DpmiMapAndCopyBuffer(ParameterBlock, 13);
  1975. //
  1976. // Get the segment and offset of the parameter block
  1977. //
  1978. DPMI_FLAT_TO_SEGMENTED(BufferedPBlock, &Seg, &Off);
  1979. setDS(Seg);
  1980. setDX(Off);
  1981. if (CurrentAppFlags & DPMI_32BIT) {
  1982. Data = Sim32GetVDMPointer(
  1983. (*((PWORD16)(BufferedPBlock + 0xd)) << 16),
  1984. 1,
  1985. TRUE
  1986. );
  1987. Data += *((PDWORD16)(BufferedPBlock + 0x9));
  1988. } else {
  1989. Data = Sim32GetVDMPointer(
  1990. (*((PWORD16)(BufferedPBlock + 0xb)) << 16),
  1991. 1,
  1992. TRUE
  1993. );
  1994. Data += *((PWORD16)(BufferedPBlock + 0x9));
  1995. }
  1996. NumberOfSectors = *((PWORD16)(BufferedPBlock + 7));
  1997. SectorsRead = 0;
  1998. while (NumberOfSectors != SectorsRead) {
  1999. if ((NumberOfSectors - SectorsRead) * BytesPerSector > 1024 * 4) {
  2000. SectorsToRead = 4 * 1024 / BytesPerSector;
  2001. } else {
  2002. SectorsToRead = (USHORT)(NumberOfSectors - SectorsRead);
  2003. }
  2004. BufferedData = DpmiMapAndCopyBuffer(
  2005. Data,
  2006. (USHORT) (SectorsToRead * BytesPerSector)
  2007. );
  2008. DPMI_FLAT_TO_SEGMENTED(BufferedData, &Seg, &Off);
  2009. *((PWORD16)(BufferedPBlock + 9)) = Off;
  2010. *((PWORD16)(BufferedPBlock + 11)) = Seg;
  2011. *((PWORD16)(BufferedPBlock + 7)) = SectorsToRead;
  2012. setAX(ClientAX);
  2013. setCX(ClientCX);
  2014. DPMI_EXEC_INT(0x21);
  2015. if (getCF()) {
  2016. DpmiUnmapBuffer(
  2017. BufferedData,
  2018. (USHORT) (SectorsToRead * BytesPerSector)
  2019. );
  2020. break;
  2021. }
  2022. DpmiUnmapAndCopyBuffer(
  2023. Data,
  2024. BufferedData,
  2025. (USHORT) (SectorsToRead * BytesPerSector)
  2026. );
  2027. Data += SectorsToRead * BytesPerSector;
  2028. *((PWORD16)(BufferedPBlock + 5)) += SectorsToRead;
  2029. SectorsRead += SectorsToRead;
  2030. }
  2031. DpmiUnmapBuffer(BufferedPBlock,13);
  2032. setDX(ClientDX);
  2033. DpmiSwitchToProtectedMode();
  2034. setDS(ClientDS);
  2035. }
  2036. VOID
  2037. MapDPL(
  2038. VOID
  2039. )
  2040. /*++
  2041. Routine Description:
  2042. This routine maps a DPL for the server call
  2043. Arguments:
  2044. None.
  2045. Return Value:
  2046. None.
  2047. --*/
  2048. {
  2049. DECLARE_LocalVdmContext;
  2050. USHORT ClientDX, DataSeg, DataOff;
  2051. PUCHAR Data, BufferedData;
  2052. USHORT ClientDS = getDS();
  2053. DpmiSwitchToRealMode();
  2054. ClientDX = getDX();
  2055. Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  2056. + (*GetDXRegister)();
  2057. BufferedData = DpmiMapAndCopyBuffer(Data, 22);
  2058. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  2059. setDS(DataSeg);
  2060. setDX(DataOff);
  2061. DPMI_EXEC_INT(0x21);
  2062. DpmiSwitchToProtectedMode();
  2063. DpmiUnmapAndCopyBuffer(Data, BufferedData, 22);
  2064. setDX(ClientDX);
  2065. setDS(ClientDS);
  2066. }
  2067. VOID
  2068. GetMachineName(
  2069. VOID
  2070. )
  2071. /*++
  2072. Routine Description:
  2073. This routine maps a machine name for int 21 function 5e
  2074. Arguments:
  2075. None.
  2076. Return Value:
  2077. None.
  2078. --*/
  2079. {
  2080. DECLARE_LocalVdmContext;
  2081. USHORT ClientDX, DataSeg, DataOff;
  2082. PUCHAR Data, BufferedData;
  2083. USHORT ClientDS = getDS();
  2084. DpmiSwitchToRealMode();
  2085. ClientDX = getDX();
  2086. Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  2087. + (*GetDXRegister)();
  2088. BufferedData = DpmiMapAndCopyBuffer(Data, 16);
  2089. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  2090. setDS(DataSeg);
  2091. setDX(DataOff);
  2092. DPMI_EXEC_INT(0x21);
  2093. DpmiSwitchToProtectedMode();
  2094. DpmiUnmapAndCopyBuffer(Data, BufferedData, 16);
  2095. setDX(ClientDX);
  2096. setDS(ClientDS);
  2097. }
  2098. VOID
  2099. GetPrinterSetup(
  2100. VOID
  2101. )
  2102. /*++
  2103. Routine Description:
  2104. This routine maps printer setup data for int 21 function 5e
  2105. Arguments:
  2106. None.
  2107. Return Value:
  2108. None.
  2109. --*/
  2110. {
  2111. DECLARE_LocalVdmContext;
  2112. USHORT ClientSI, ClientCX, DataSeg, DataOff;
  2113. PUCHAR Data, BufferedData;
  2114. USHORT ClientDS = getDS();
  2115. DpmiSwitchToRealMode();
  2116. ClientSI = getSI();
  2117. ClientCX = getCX();
  2118. Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE)
  2119. + (*GetSIRegister)();
  2120. BufferedData = DpmiMapAndCopyBuffer(Data, ClientCX);
  2121. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  2122. setDS(DataSeg);
  2123. setSI(DataOff);
  2124. DPMI_EXEC_INT(0x21);
  2125. DpmiSwitchToProtectedMode();
  2126. DpmiUnmapAndCopyBuffer(Data, BufferedData, ClientCX);
  2127. setSI(ClientSI);
  2128. setDS(ClientDS);
  2129. }
  2130. VOID
  2131. SetPrinterSetup(
  2132. VOID
  2133. )
  2134. /*++
  2135. Routine Description:
  2136. This routine maps printer setup data for int 21 function 5e
  2137. Arguments:
  2138. None.
  2139. Return Value:
  2140. None.
  2141. --*/
  2142. {
  2143. DECLARE_LocalVdmContext;
  2144. USHORT ClientDI, DataSeg, DataOff;
  2145. PUCHAR Data, BufferedData;
  2146. USHORT ClientES = getES();
  2147. DpmiSwitchToRealMode();
  2148. ClientDI = getDI();
  2149. Data = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE)
  2150. + (*GetDIRegister)();
  2151. BufferedData = DpmiMapAndCopyBuffer(Data, 64);
  2152. DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
  2153. setES(DataSeg);
  2154. setDI(DataOff);
  2155. DPMI_EXEC_INT(0x21);
  2156. DpmiSwitchToProtectedMode();
  2157. setES(ClientES);
  2158. DpmiUnmapAndCopyBuffer(Data, BufferedData, 64);
  2159. setDI(ClientDI);
  2160. }
  2161. VOID
  2162. GetDate(
  2163. VOID
  2164. )
  2165. /*++
  2166. Routine Description:
  2167. This routine maps int21 func 2A GetDate
  2168. Arguments:
  2169. None.
  2170. Return Value:
  2171. Client (DH) - month
  2172. Client (DL) - Day
  2173. Client (CX) - Year
  2174. Client (AL) - WeekDay
  2175. --*/
  2176. {
  2177. DECLARE_LocalVdmContext;
  2178. SYSTEMTIME TimeDate;
  2179. GetLocalTime(&TimeDate);
  2180. setDH((UCHAR)TimeDate.wMonth);
  2181. setDL((UCHAR)TimeDate.wDay);
  2182. setCX(TimeDate.wYear);
  2183. setAL((UCHAR)TimeDate.wDayOfWeek);
  2184. }