3dcf145a45b4193418edacf5f2f8e8ec9ae0b047
[reactos.git] / reactos / ntoskrnl / vdm / vdmmain.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/vdm/vdmmain.c
5 * PURPOSE: VDM Support Services
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Aleksey Bragin (aleksey@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18
19 /* PRIVATE FUNCTIONS *********************************************************/
20
21 VOID
22 NTAPI
23 Ki386VdmEnablePentiumExtentions(VOID)
24 {
25 DPRINT1("VME detected but not yet supported\n");
26 }
27
28 VOID
29 NTAPI
30 KeI386VdmInitialize(VOID)
31 {
32 NTSTATUS Status;
33 OBJECT_ATTRIBUTES ObjectAttributes;
34 HANDLE RegHandle;
35 UNICODE_STRING Name;
36 UCHAR KeyValueInfo[sizeof(KEY_VALUE_BASIC_INFORMATION) + 30];
37 ULONG ReturnLength;
38
39 /* Make sure that there is a WOW key */
40 RtlInitUnicodeString(&Name,
41 L"\\Registry\\Machine\\System\\CurrentControlSet\\"
42 L"Control\\Wow");
43 InitializeObjectAttributes(&ObjectAttributes,
44 &Name,
45 OBJ_CASE_INSENSITIVE,
46 NULL,
47 NULL);
48 Status = ZwOpenKey(&RegHandle, KEY_READ, &ObjectAttributes);
49 if (!NT_SUCCESS(Status)) return;
50
51 /* Check if VME is enabled */
52 RtlInitUnicodeString(&Name, L"DisableVme");
53 Status = ZwQueryValueKey(RegHandle,
54 &Name,
55 KeyValueBasicInformation,
56 &KeyValueInfo,
57 sizeof(KeyValueInfo),
58 &ReturnLength);
59 if (!NT_SUCCESS(Status))
60 {
61 /* Not present, so check if the CPU supports VME */
62 if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS)
63 {
64 /* Enable them. FIXME: Use IPI */
65 Ki386VdmEnablePentiumExtentions();
66 KeI386VirtualIntExtensions = TRUE;
67 }
68 }
69
70 /* Close the key */
71 ZwClose(RegHandle);
72 }
73
74 NTSTATUS
75 NTAPI
76 VdmpInitialize(PVOID ControlData)
77 {
78 OBJECT_ATTRIBUTES ObjectAttributes;
79 UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
80 NTSTATUS Status;
81 HANDLE PhysMemHandle;
82 PVOID BaseAddress;
83 PVOID NullAddress = NULL;
84 LARGE_INTEGER Offset;
85 ULONG ViewSize;
86
87 /* Open the physical memory section */
88 InitializeObjectAttributes(&ObjectAttributes,
89 &PhysMemName,
90 0,
91 NULL,
92 NULL);
93 Status = ZwOpenSection(&PhysMemHandle,
94 SECTION_ALL_ACCESS,
95 &ObjectAttributes);
96 if (!NT_SUCCESS(Status))
97 {
98 DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
99 return Status;
100 }
101
102 /* Map the BIOS and device registers into the address space */
103 Offset.QuadPart = 0;
104 ViewSize = PAGE_SIZE;
105 BaseAddress = 0;
106 Status = ZwMapViewOfSection(PhysMemHandle,
107 NtCurrentProcess(),
108 &BaseAddress,
109 0,
110 ViewSize,
111 &Offset,
112 &ViewSize,
113 ViewUnmap,
114 0,
115 PAGE_READWRITE);
116 if (!NT_SUCCESS(Status))
117 {
118 DPRINT1("Couldn't map physical memory (%x)\n", Status);
119 ZwClose(PhysMemHandle);
120 return Status;
121 }
122
123 /* Enter SEH */
124 _SEH2_TRY
125 {
126 /* Copy the first physical page into the first virtual page */
127 RtlMoveMemory(NullAddress, BaseAddress, ViewSize);
128 }
129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
130 {
131 /* Fail */
132 DPRINT1("Couldn't copy first page (%x)\n", Status);
133 ZwClose(PhysMemHandle);
134 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
135 _SEH2_YIELD(return _SEH2_GetExceptionCode());
136 }
137 _SEH2_END;
138
139 /* Close physical memory section handle */
140 ZwClose(PhysMemHandle);
141
142 /* Unmap the section */
143 Status = ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
144
145 if (!NT_SUCCESS(Status))
146 {
147 DPRINT1("Couldn't unmap the section (%x)\n", Status);
148 return Status;
149 }
150
151 return STATUS_SUCCESS;
152 }
153
154 /* PUBLIC FUNCTIONS **********************************************************/
155
156 /*
157 * @implemented
158 */
159 NTSTATUS
160 NTAPI
161 NtVdmControl(IN ULONG ControlCode,
162 IN PVOID ControlData)
163 {
164 NTSTATUS Status;
165 PAGED_CODE();
166
167 /* Check which control code this is */
168 switch (ControlCode)
169 {
170 /* VDM Execution start */
171 case VdmStartExecution:
172
173 /* Call the sub-function */
174 Status = VdmpStartExecution();
175 break;
176
177 case VdmInitialize:
178
179 /* Call the init sub-function */
180 Status = VdmpInitialize(ControlData);
181 break;
182
183 default:
184
185 /* Unsupported */
186 DPRINT1("Unknown VDM call: %lx\n", ControlCode);
187 Status = STATUS_INVALID_PARAMETER;
188 }
189
190 /* Return the status */
191 return Status;
192 }