- Use _SEH2_YIELD when returning from an exception instead of returning outside the...
[reactos.git] / reactos / ntoskrnl / vdm / vdmmain.c
index 8f6a28b..3dcf145 100644 (file)
-/*\r
- * PROJECT:         ReactOS Kernel\r
- * LICENSE:         GPL - See COPYING in the top level directory\r
- * FILE:            ntoskrnl/vdm/vdmmain.c\r
- * PURPOSE:         VDM Support Services\r
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* GLOBALS *******************************************************************/\r
-\r
-static UCHAR OrigIVT[1024];\r
-static UCHAR OrigBDA[256];\r
-\r
-/* PRIVATE FUNCTIONS *********************************************************/\r
-\r
-VOID\r
-INIT_FUNCTION\r
-NtEarlyInitVdm(VOID)\r
-{\r
-    /* GCC 3.4 hack */\r
-    PVOID start = (PVOID)0x0;\r
-\r
-    /*\r
-     * Save various BIOS data tables. At this point the lower 4MB memory\r
-     * map is still active so we can just copy the data from low memory.\r
-     * HACK HACK HACK: We should just map Physical Memory!!!\r
-     */\r
-    memcpy(OrigIVT, start, 1024);\r
-    memcpy(OrigBDA, (PVOID)0x400, 256);\r
-}\r
-\r
-VOID\r
-NTAPI\r
-Ki386VdmEnablePentiumExtentions(VOID)\r
-{\r
-    DPRINT1("VME detected but not yet supported\n");\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KeI386VdmInitialize(VOID)\r
-{\r
-    NTSTATUS Status;\r
-    OBJECT_ATTRIBUTES ObjectAttributes;\r
-    HANDLE RegHandle;\r
-    UNICODE_STRING Name;\r
-    UCHAR KeyValueInfo[sizeof(KEY_VALUE_BASIC_INFORMATION) + 30];\r
-    ULONG ReturnLength;\r
-\r
-    /* Make sure that there is a WOW key */\r
-    RtlInitUnicodeString(&Name,\r
-                         L"\\Registry\\Machine\\System\\CurrentControlSet\\"\r
-                         L"Control\\Wow");\r
-    InitializeObjectAttributes(&ObjectAttributes,\r
-                               &Name,\r
-                               OBJ_CASE_INSENSITIVE,\r
-                               NULL,\r
-                               NULL);\r
-    Status = ZwOpenKey(&RegHandle, KEY_READ, &ObjectAttributes);\r
-    if (!NT_SUCCESS(Status)) return;\r
-\r
-    /* Check if VME is enabled */\r
-    RtlInitUnicodeString(&Name, L"DisableVme");\r
-    Status = ZwQueryValueKey(RegHandle,\r
-                             &Name,\r
-                             KeyValueBasicInformation,\r
-                             &KeyValueInfo,\r
-                             sizeof(KeyValueInfo),\r
-                             &ReturnLength);\r
-    if (!NT_SUCCESS(Status))\r
-    {\r
-        /* Not present, so check if the CPU supports VME */\r
-        if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS)\r
-        {\r
-            /* Enable them. FIXME: Use IPI */\r
-            Ki386VdmEnablePentiumExtentions();\r
-            KeI386VirtualIntExtensions = TRUE;\r
-        }\r
-    }\r
-\r
-    /* Close the key */\r
-    ZwClose(RegHandle);\r
-}\r
-\r
-/* PUBLIC FUNCTIONS **********************************************************/\r
-\r
-/*\r
- * @implemented\r
- */\r
-NTSTATUS\r
-NTAPI\r
-NtVdmControl(IN ULONG ControlCode,\r
-             IN PVOID ControlData)\r
-{\r
-    NTSTATUS Status;\r
-    PAGED_CODE();\r
-\r
-    /* Check which control code this is */\r
-    switch (ControlCode)\r
-    {\r
-        /* VDM Execution start */\r
-        case VdmStartExecution:\r
-\r
-            /* Call the sub-function */\r
-            Status = VdmpStartExecution();\r
-            break;\r
-\r
-        case VdmInitialize:\r
-\r
-            /* Pretty much a hack, since a lot more needs to happen */\r
-            memcpy(ControlData, OrigIVT, 1024);\r
-            memcpy((PVOID)((ULONG_PTR)ControlData + 1024), OrigBDA, 256);\r
-            Status = STATUS_SUCCESS;\r
-            break;\r
-\r
-        default:\r
-\r
-            /* Unsupported */\r
-            DPRINT1("Unknown VDM call: %lx\n", ControlCode);\r
-            Status = STATUS_INVALID_PARAMETER;\r
-    }\r
-\r
-    /* Return the status */\r
-    return Status;\r
-}\r
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/vdm/vdmmain.c
+ * PURPOSE:         VDM Support Services
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Aleksey Bragin (aleksey@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+Ki386VdmEnablePentiumExtentions(VOID)
+{
+    DPRINT1("VME detected but not yet supported\n");
+}
+
+VOID
+NTAPI
+KeI386VdmInitialize(VOID)
+{
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE RegHandle;
+    UNICODE_STRING Name;
+    UCHAR KeyValueInfo[sizeof(KEY_VALUE_BASIC_INFORMATION) + 30];
+    ULONG ReturnLength;
+
+    /* Make sure that there is a WOW key */
+    RtlInitUnicodeString(&Name,
+                         L"\\Registry\\Machine\\System\\CurrentControlSet\\"
+                         L"Control\\Wow");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &Name,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = ZwOpenKey(&RegHandle, KEY_READ, &ObjectAttributes);
+    if (!NT_SUCCESS(Status)) return;
+
+    /* Check if VME is enabled */
+    RtlInitUnicodeString(&Name, L"DisableVme");
+    Status = ZwQueryValueKey(RegHandle,
+                             &Name,
+                             KeyValueBasicInformation,
+                             &KeyValueInfo,
+                             sizeof(KeyValueInfo),
+                             &ReturnLength);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Not present, so check if the CPU supports VME */
+        if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS)
+        {
+            /* Enable them. FIXME: Use IPI */
+            Ki386VdmEnablePentiumExtentions();
+            KeI386VirtualIntExtensions = TRUE;
+        }
+    }
+
+    /* Close the key */
+    ZwClose(RegHandle);
+}
+
+NTSTATUS
+NTAPI
+VdmpInitialize(PVOID ControlData)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
+    NTSTATUS Status;
+    HANDLE PhysMemHandle;
+    PVOID BaseAddress;
+    PVOID NullAddress = NULL;
+    LARGE_INTEGER Offset;
+    ULONG ViewSize;
+
+    /* Open the physical memory section */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &PhysMemName,
+                               0,
+                               NULL,
+                               NULL);
+    Status = ZwOpenSection(&PhysMemHandle,
+                           SECTION_ALL_ACCESS,
+                           &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
+        return Status;
+    }
+
+    /* Map the BIOS and device registers into the address space */
+    Offset.QuadPart = 0;
+    ViewSize = PAGE_SIZE;
+    BaseAddress = 0;
+    Status = ZwMapViewOfSection(PhysMemHandle,
+                                NtCurrentProcess(),
+                                &BaseAddress,
+                                0,
+                                ViewSize,
+                                &Offset,
+                                &ViewSize,
+                                ViewUnmap,
+                                0,
+                                PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Couldn't map physical memory (%x)\n", Status);
+        ZwClose(PhysMemHandle);
+        return Status;
+    }
+
+    /* Enter SEH */
+    _SEH2_TRY
+    {
+        /* Copy the first physical page into the first virtual page */
+        RtlMoveMemory(NullAddress, BaseAddress, ViewSize);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Fail */
+        DPRINT1("Couldn't copy first page (%x)\n", Status);
+        ZwClose(PhysMemHandle);
+        ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
+        _SEH2_YIELD(return _SEH2_GetExceptionCode());
+    }
+    _SEH2_END;
+
+    /* Close physical memory section handle */
+    ZwClose(PhysMemHandle);
+
+    /* Unmap the section */
+    Status = ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Couldn't unmap the section (%x)\n", Status);
+        return Status;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtVdmControl(IN ULONG ControlCode,
+             IN PVOID ControlData)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Check which control code this is */
+    switch (ControlCode)
+    {
+        /* VDM Execution start */
+        case VdmStartExecution:
+
+            /* Call the sub-function */
+            Status = VdmpStartExecution();
+            break;
+
+        case VdmInitialize:
+
+            /* Call the init sub-function */
+            Status = VdmpInitialize(ControlData);
+            break;
+
+        default:
+
+            /* Unsupported */
+            DPRINT1("Unknown VDM call: %lx\n", ControlCode);
+            Status = STATUS_INVALID_PARAMETER;
+    }
+
+    /* Return the status */
+    return Status;
+}