[NDK][NTOS] Add global definition of INIT_FUNCTION/INIT_SECTION (#779)
[reactos.git] / 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 /* PRIVATE FUNCTIONS *********************************************************/
19
20 INIT_FUNCTION
21 VOID
22 NTAPI
23 Ki386VdmEnablePentiumExtentions(IN BOOLEAN Enable)
24 {
25 ULONG EFlags, Cr4;
26
27 /* Save interrupt state and disable them */
28 EFlags = __readeflags();
29 _disable();
30
31 /* Enable or disable VME as required */
32 Cr4 = __readcr4();
33 __writecr4(Enable ? Cr4 | CR4_VME : Cr4 & ~CR4_VME);
34
35 /* Restore interrupt state */
36 __writeeflags(EFlags);
37 }
38
39 INIT_FUNCTION
40 VOID
41 NTAPI
42 KeI386VdmInitialize(VOID)
43 {
44 NTSTATUS Status;
45 OBJECT_ATTRIBUTES ObjectAttributes;
46 HANDLE RegHandle;
47 UNICODE_STRING Name;
48 UCHAR KeyValueInfo[sizeof(KEY_VALUE_BASIC_INFORMATION) + 30];
49 ULONG ReturnLength;
50
51 /* Make sure that there is a WOW key */
52 RtlInitUnicodeString(&Name,
53 L"\\Registry\\Machine\\System\\CurrentControlSet\\"
54 L"Control\\Wow");
55 InitializeObjectAttributes(&ObjectAttributes,
56 &Name,
57 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
58 NULL,
59 NULL);
60 Status = ZwOpenKey(&RegHandle, KEY_READ, &ObjectAttributes);
61 if (!NT_SUCCESS(Status)) return;
62
63 /* Check if VME is enabled */
64 RtlInitUnicodeString(&Name, L"DisableVme");
65 Status = ZwQueryValueKey(RegHandle,
66 &Name,
67 KeyValueBasicInformation,
68 &KeyValueInfo,
69 sizeof(KeyValueInfo),
70 &ReturnLength);
71 if (!NT_SUCCESS(Status))
72 {
73 /* Not present, so check if the CPU supports VME */
74 if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS)
75 {
76 /* Enable them. FIXME: Use IPI */
77 Ki386VdmEnablePentiumExtentions(TRUE);
78 KeI386VirtualIntExtensions = TRUE;
79 }
80 }
81
82 /* Close the key */
83 ZwClose(RegHandle);
84 }
85
86 NTSTATUS
87 NTAPI
88 VdmpInitialize(PVOID ControlData)
89 {
90 OBJECT_ATTRIBUTES ObjectAttributes;
91 UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
92 NTSTATUS Status;
93 HANDLE PhysMemHandle;
94 PVOID BaseAddress;
95 volatile PVOID NullAddress = NULL;
96 LARGE_INTEGER Offset;
97 ULONG ViewSize;
98
99 /* Open the physical memory section */
100 InitializeObjectAttributes(&ObjectAttributes,
101 &PhysMemName,
102 OBJ_KERNEL_HANDLE,
103 NULL,
104 NULL);
105 Status = ZwOpenSection(&PhysMemHandle,
106 SECTION_ALL_ACCESS,
107 &ObjectAttributes);
108 if (!NT_SUCCESS(Status))
109 {
110 DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
111 return Status;
112 }
113
114 /* Map the BIOS and device registers into the address space */
115 Offset.QuadPart = 0;
116 ViewSize = PAGE_SIZE;
117 BaseAddress = 0;
118 Status = ZwMapViewOfSection(PhysMemHandle,
119 NtCurrentProcess(),
120 &BaseAddress,
121 0,
122 ViewSize,
123 &Offset,
124 &ViewSize,
125 ViewUnmap,
126 0,
127 PAGE_READWRITE);
128 if (!NT_SUCCESS(Status))
129 {
130 DPRINT1("Couldn't map physical memory (%x)\n", Status);
131 ZwClose(PhysMemHandle);
132 return Status;
133 }
134
135 /* Enter SEH */
136 _SEH2_TRY
137 {
138 /* Copy the first physical page into the first virtual page */
139 RtlMoveMemory(NullAddress, BaseAddress, ViewSize);
140 }
141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
142 {
143 /* Fail */
144 DPRINT1("Couldn't copy first page (%x)\n", Status);
145 ZwClose(PhysMemHandle);
146 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
147 _SEH2_YIELD(return _SEH2_GetExceptionCode());
148 }
149 _SEH2_END;
150
151 /* Close physical memory section handle */
152 ZwClose(PhysMemHandle);
153
154 /* Unmap the section */
155 Status = ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
156
157 if (!NT_SUCCESS(Status))
158 {
159 DPRINT1("Couldn't unmap the section (%x)\n", Status);
160 return Status;
161 }
162
163 return STATUS_SUCCESS;
164 }
165
166 /* PUBLIC FUNCTIONS **********************************************************/
167
168 /*
169 * @implemented
170 */
171 NTSTATUS
172 NTAPI
173 NtVdmControl(IN ULONG ControlCode,
174 IN PVOID ControlData)
175 {
176 NTSTATUS Status;
177 PAGED_CODE();
178
179 /* Check which control code this is */
180 switch (ControlCode)
181 {
182 /* VDM Execution start */
183 case VdmStartExecution:
184
185 /* Call the sub-function */
186 Status = VdmpStartExecution();
187 break;
188
189 case VdmInitialize:
190
191 /* Call the init sub-function */
192 Status = VdmpInitialize(ControlData);
193 break;
194
195 default:
196
197 /* Unsupported */
198 DPRINT1("Unknown VDM call: %lx\n", ControlCode);
199 Status = STATUS_INVALID_PARAMETER;
200 }
201
202 /* Return the status */
203 return Status;
204 }