Index: /trunk/src/VBox/Runtime/r0drv/nt/memuserkernel-r0drv-nt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/nt/memuserkernel-r0drv-nt.cpp	(revision 91674)
+++ /trunk/src/VBox/Runtime/r0drv/nt/memuserkernel-r0drv-nt.cpp	(revision 91675)
@@ -97,12 +97,48 @@
 RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb)
 {
-    __try
-    {
-        memcpy(pvDst, pvSrc, cb);
-    }
-    __except(EXCEPTION_EXECUTE_HANDLER)
-    {
-        return VERR_ACCESS_DENIED;
-    }
+    if (!RTR0MemKernelIsValidAddr((void *)pvSrc))
+        return VERR_ACCESS_DENIED;
+
+    uint8_t       *pbDst = (uint8_t *)pvDst;
+    uint8_t const *pbSrc = (uint8_t const *)pvSrc;
+
+#if 0
+    /*
+     * The try+except stuff does not work for kernel addresses.
+     */
+    __try
+    {
+        while (cb-- > 0)
+            *pbDst++ = *pbSrc++;
+    }
+    __except(EXCEPTION_EXECUTE_HANDLER)
+    {
+        return VERR_ACCESS_DENIED;
+    }
+#else
+    /*
+     * This is the best I can come up with for now: Work page-by-page using MmIsAddressValid.
+     */
+    while (cb > 0)
+    {
+        if (!MmIsAddressValid((PVOID)pbSrc))
+            return VERR_ACCESS_DENIED;
+
+        size_t cbToCopy = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
+        if (cbToCopy > cb)
+            cbToCopy = cb;
+        cb -= cbToCopy;
+
+        __try /* doesn't work, but can't hurt, right? */
+        {
+            while (cbToCopy-- > 0)
+                *pbDst++ = *pbSrc++;
+        }
+        __except(EXCEPTION_EXECUTE_HANDLER)
+        {
+            return VERR_ACCESS_DENIED;
+        }
+    }
+#endif
     return VINF_SUCCESS;
 }
@@ -111,13 +147,54 @@
 RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb)
 {
-    __try
-    {
-        memcpy(pvDst, pvSrc, cb);
-    }
-    __except(EXCEPTION_EXECUTE_HANDLER)
-    {
-        return VERR_ACCESS_DENIED;
-    }
-    return VINF_SUCCESS;
-}
-
+    if (!RTR0MemKernelIsValidAddr(pvDst))
+        return VERR_ACCESS_DENIED;
+#if 0
+    uint8_t       *pbDst = (uint8_t *)pvDst;
+    uint8_t const *pbSrc = (uint8_t const *)pvSrc;
+# if 0
+    /*
+     * The try+except stuff does not work for kernel addresses.
+     */
+    __try
+    {
+        while (cb-- > 0)
+            *pbDst++ = *pbSrc++;
+    }
+    __except(EXCEPTION_EXECUTE_HANDLER)
+    {
+        return VERR_ACCESS_DENIED;
+    }
+
+# else
+    /*
+     * This is the best I can come up with for now: Work page-by-page using MmIsAddressValid.
+     * Note! MmIsAddressValid does not indicate that it's writable, so we're a bit buggered if it isn't...
+     */
+    while (cb > 0)
+    {
+        if (!MmIsAddressValid((PVOID)pbSrc))
+            return VERR_ACCESS_DENIED;
+
+        size_t cbToCopy = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
+        if (cbToCopy > cb)
+            cbToCopy = cb;
+        cb -= cbToCopy;
+
+        __try /* doesn't work, but can't hurt, right? */
+        {
+            while (cbToCopy-- > 0)
+                *pbDst++ = *pbSrc++;
+        }
+        __except(EXCEPTION_EXECUTE_HANDLER)
+        {
+            return VERR_ACCESS_DENIED;
+        }
+    }
+# endif
+    return VINF_SUCCESS;
+#else
+    RT_NOREF(pvDst, pvSrc, cb);
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
