Merging r37048, r37051, r37052, r37055 from the-real-msvc branch
[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 /* Now, copy the first physical page into the first virtual page */
124 _SEH_TRY
125 {
126 RtlMoveMemory(NullAddress, BaseAddress, ViewSize);
127 }
128 _SEH_HANDLE
129 {
130 /* Get the status */
131 Status = _SEH_GetExceptionCode();
132 }
133 _SEH_END;
134
135 if (!NT_SUCCESS(Status))
136 {
137 DPRINT1("Couldn't copy first page (%x)\n", Status);
138 ZwClose(PhysMemHandle);
139 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
140 return Status;
141 }
142
143 /* Close physical memory section handle */
144 ZwClose(PhysMemHandle);
145
146 /* Unmap the section */
147 Status = ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
148
149 if (!NT_SUCCESS(Status))
150 {
151 DPRINT1("Couldn't unmap the section (%x)\n", Status);
152 return Status;
153 }
154
155 return STATUS_SUCCESS;
156 }
157
158 /* PUBLIC FUNCTIONS **********************************************************/
159
160 /*
161 * @implemented
162 */
163 NTSTATUS
164 NTAPI
165 NtVdmControl(IN ULONG ControlCode,
166 IN PVOID ControlData)
167 {
168 NTSTATUS Status;
169 PAGED_CODE();
170
171 /* Check which control code this is */
172 switch (ControlCode)
173 {
174 /* VDM Execution start */
175 case VdmStartExecution:
176
177 /* Call the sub-function */
178 Status = VdmpStartExecution();
179 break;
180
181 case VdmInitialize:
182
183 /* Call the init sub-function */
184 Status = VdmpInitialize(ControlData);
185 break;
186
187 default:
188
189 /* Unsupported */
190 DPRINT1("Unknown VDM call: %lx\n", ControlCode);
191 Status = STATUS_INVALID_PARAMETER;
192 }
193
194 /* Return the status */
195 return Status;
196 }