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.

306 lines
6.7 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dpmi386.c
  5. Abstract:
  6. This file contains support for 386/486 only dpmi bops
  7. Author:
  8. Dave Hastings (daveh) 27-Jun-1991
  9. Revision History:
  10. Matt Felton (mattfe) Dec 6 1992 removed unwanted verification
  11. Dave Hastings (daveh) 24-Nov-1992 Moved to mvdm\dpmi32
  12. Matt Felton (mattfe) 8 Feb 1992 optimize getvdmpointer for regular protect mode path.
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <softpc.h>
  17. #include <memory.h>
  18. #include <malloc.h>
  19. #include <nt_vdd.h>
  20. BOOL
  21. DpmiSetX86Descriptor(
  22. USHORT SelStart,
  23. USHORT SelCount
  24. )
  25. /*++
  26. Routine Description:
  27. This function puts descriptors into the real LDT. It uses the client's
  28. LDT as a source for the descriptor data.
  29. Arguments:
  30. SelStart - The first selector in the block of selectors to set
  31. SelCount - The number of selectors to set
  32. Return Value:
  33. This function returns TRUE if successful, FALSE otherwise
  34. --*/
  35. {
  36. LDT_ENTRY UNALIGNED *Descriptors = &Ldt[SelStart>>3];
  37. PPROCESS_LDT_INFORMATION LdtInformation = NULL;
  38. NTSTATUS Status;
  39. ULONG ulLdtEntrySize;
  40. ULONG Selector0,Selector1;
  41. ulLdtEntrySize = SelCount * sizeof(LDT_ENTRY);
  42. //
  43. // If there are only 2 descriptors, set them the fast way
  44. //
  45. Selector0 = (ULONG)SelStart;
  46. if ((SelCount <= 2) && (Selector0 != 0)) {
  47. VDMSET_LDT_ENTRIES_DATA ServiceData;
  48. if (SelCount == 2) {
  49. Selector1 = SelStart + sizeof(LDT_ENTRY);
  50. } else {
  51. Selector1 = 0;
  52. }
  53. ServiceData.Selector0 = Selector0;
  54. ServiceData.Entry0Low = *((PULONG)(&Descriptors[0]));
  55. ServiceData.Entry0Hi = *((PULONG)(&Descriptors[0]) + 1);
  56. ServiceData.Selector1 = Selector1;
  57. ServiceData.Entry1Low = *((PULONG)(&Descriptors[1]));
  58. ServiceData.Entry1Hi = *((PULONG)(&Descriptors[1]) + 1);
  59. Status = NtVdmControl(VdmSetLdtEntries, &ServiceData);
  60. if (NT_SUCCESS(Status)) {
  61. return TRUE;
  62. }
  63. return FALSE;
  64. }
  65. LdtInformation = malloc(sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize);
  66. if (!LdtInformation ) {
  67. return FALSE;
  68. } else {
  69. VDMSET_PROCESS_LDT_INFO_DATA ServiceData;
  70. LdtInformation->Start = SelStart;
  71. LdtInformation->Length = ulLdtEntrySize;
  72. CopyMemory(
  73. &(LdtInformation->LdtEntries),
  74. Descriptors,
  75. ulLdtEntrySize
  76. );
  77. ServiceData.LdtInformation = LdtInformation;
  78. ServiceData.LdtInformationLength = sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize;
  79. Status = NtVdmControl(VdmSetProcessLdtInfo, &ServiceData);
  80. if (!NT_SUCCESS(Status)) {
  81. VDprint(
  82. VDP_LEVEL_ERROR,
  83. ("DPMI: Failed to set selectors %lx\n", Status)
  84. );
  85. free(LdtInformation);
  86. return FALSE;
  87. }
  88. free(LdtInformation);
  89. return TRUE;
  90. }
  91. }
  92. UCHAR *
  93. Sim32pGetVDMPointer(
  94. ULONG Address,
  95. UCHAR ProtectedMode
  96. )
  97. /*++
  98. Routine Description:
  99. This routine converts a 16/16 address to a linear address.
  100. WARNIGN NOTE - This routine has been optimized so protect mode LDT lookup
  101. falls stright through. This routine is call ALL the time by WOW, if you
  102. need to modify it please re optimize the path - mattfe feb 8 92
  103. Arguments:
  104. Address -- specifies the address in seg:offset format
  105. Size -- specifies the size of the region to be accessed.
  106. ProtectedMode -- true if the address is a protected mode address
  107. Return Value:
  108. The pointer.
  109. --*/
  110. {
  111. ULONG Selector;
  112. PUCHAR ReturnPointer;
  113. if (ProtectedMode) {
  114. Selector = (Address & 0xFFFF0000) >> 16;
  115. if (Selector != 40) {
  116. Selector &= ~7;
  117. ReturnPointer = (PUCHAR)FlatAddress[Selector >> 3];
  118. ReturnPointer += (Address & 0xFFFF);
  119. return ReturnPointer;
  120. // Selector 40
  121. } else {
  122. ReturnPointer = (PUCHAR)0x400 + (Address & 0xFFFF);
  123. }
  124. // Real Mode
  125. } else {
  126. ReturnPointer = (PUCHAR)(((Address & 0xFFFF0000) >> 12) + (Address & 0xFFFF));
  127. }
  128. return ReturnPointer;
  129. }
  130. PUCHAR
  131. ExpSim32GetVDMPointer(
  132. ULONG Address,
  133. ULONG Size,
  134. UCHAR ProtectedMode
  135. )
  136. /*++
  137. See Sim32pGetVDMPointer, above
  138. This call must be maintaned as is because it is exported for VDD's
  139. in product 1.0.
  140. --*/
  141. {
  142. return Sim32pGetVDMPointer(Address,(UCHAR)ProtectedMode);
  143. }
  144. PVOID
  145. VdmMapFlat(
  146. WORD selector,
  147. ULONG offset,
  148. VDM_MODE mode
  149. )
  150. /*++
  151. Routine Description:
  152. This routine converts a 16/16 address to a linear address.
  153. WARNIGN NOTE - This routine has been optimized so protect mode LDT lookup
  154. falls stright through. This routine is call ALL the time by WOW, if you
  155. need to modify it please re optimize the path - mattfe feb 8 92
  156. Arguments:
  157. Address -- specifies the address in seg:offset format
  158. Size -- specifies the size of the region to be accessed.
  159. ProtectedMode -- true if the address is a protected mode address
  160. Return Value:
  161. The pointer.
  162. --*/
  163. {
  164. PUCHAR ReturnPointer;
  165. if (mode == VDM_PM) {
  166. if (selector != 40) {
  167. selector &= ~7;
  168. ReturnPointer = (PUCHAR)FlatAddress[selector >> 3] + offset;
  169. return ReturnPointer;
  170. // Selector 40
  171. } else {
  172. ReturnPointer = (PUCHAR)0x400 + (offset & 0xFFFF);
  173. }
  174. // Real Mode
  175. } else {
  176. ReturnPointer = (PUCHAR)((((ULONG)selector) << 4) + (offset & 0xFFFF));
  177. }
  178. return ReturnPointer;
  179. }
  180. BOOL
  181. DpmiSetDebugRegisters(
  182. PULONG RegisterPointer
  183. )
  184. /*++
  185. Routine Description:
  186. This routine is called by dpmi when an app has issued DPMI debug commands.
  187. The six doubleword pointed to by the input parameter are the desired values
  188. for the real x86 hardware debug registers. This routine lets
  189. ThreadSetDebugContext() do all the work.
  190. Arguments:
  191. None
  192. Return Value:
  193. None.
  194. --*/
  195. {
  196. BOOL bReturn = TRUE;
  197. if (!ThreadSetDebugContext(RegisterPointer))
  198. {
  199. ULONG ClearDebugRegisters[6] = {0, 0, 0, 0, 0, 0};
  200. //
  201. // an error occurred. Reset everything to zero
  202. //
  203. ThreadSetDebugContext (&ClearDebugRegisters[0]);
  204. bReturn = FALSE;
  205. }
  206. return bReturn;
  207. }
  208. BOOL
  209. DpmiGetDebugRegisters(
  210. PULONG RegisterPointer
  211. )
  212. /*++
  213. Routine Description:
  214. This routine is called by DOSX when an app has issued DPMI debug commands.
  215. The six doubleword pointed to by the input parameter are the desired values
  216. for the real x86 hardware debug registers. This routine lets
  217. ThreadGetDebugContext() do all the work.
  218. Arguments:
  219. None
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. return (ThreadGetDebugContext(RegisterPointer));
  225. }