MiQueryVirtualMemory(): created because ZwQueryVirtualMemory() didn't work for me...
[reactos.git] / reactos / ntoskrnl / mm / virtual.c
index 44c966c..3970987 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: virtual.c,v 1.77 2004/07/09 20:14:49 navaraf Exp $
+/* $Id: virtual.c,v 1.86 2004/12/22 05:17:44 royce Exp $
  *
  * PROJECT:     ReactOS kernel
  * FILE:        ntoskrnl/mm/virtual.c
 
 /* INCLUDE *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/mm.h>
-#include <internal/ob.h>
-#include <internal/io.h>
-#include <internal/ps.h>
-#include <internal/pool.h>
-#include <internal/safe.h>
+#include <ntoskrnl.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -47,112 +41,123 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
 /*
  * FUNCTION: Flushes virtual memory to file
  * ARGUMENTS:
- *        ProcessHandle = Points to the process that allocated the virtual 
+ *        ProcessHandle = Points to the process that allocated the virtual
  *                        memory
  *        BaseAddress = Points to the memory address
  *        NumberOfBytesToFlush = Limits the range to flush,
  *        NumberOfBytesFlushed = Actual number of bytes flushed
- * RETURNS: Status 
+ * RETURNS: Status
  */
 {
    UNIMPLEMENTED;
    return(STATUS_NOT_IMPLEMENTED);
 }
 
-/* (tMk 2004.II.4)
- * FUNCTION: Locks range of process virtual memory.
- * Called from VirtualLock (lib\kernel32\mem\virtual.c)
- *
- * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
- */
+
 NTSTATUS STDCALL
-NtLockVirtualMemory(HANDLE ProcessHandle,
-                    PVOID BaseAddress,
-                    ULONG NumberOfBytesToLock,
-                    PULONG NumberOfBytesLocked)   // ULONG LockOption?
+MiLockVirtualMemory(HANDLE ProcessHandle,
+  PVOID BaseAddress,
+  ULONG NumberOfBytesToLock,
+  PULONG NumberOfBytesLocked,
+  PObReferenceObjectByHandle pObReferenceObjectByHandle,
+  PMmCreateMdl pMmCreateMdl,
+  PObDereferenceObject pObDereferenceObject,
+  PMmProbeAndLockPages pMmProbeAndLockPages,
+  PExFreePool pExFreePool)
 {
-   // AG [08-20-03] : I have *no* idea if this is correct, I just used the
-   // other functions as a template and made a few intelligent guesses...
+  PEPROCESS Process;
+  NTSTATUS Status;
+  PMDL Mdl;
+
+  Status = pObReferenceObjectByHandle(ProcessHandle,
+    PROCESS_VM_WRITE,
+    NULL,
+    UserMode,
+    (PVOID*)(&Process),
+    NULL);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  Mdl = pMmCreateMdl(NULL,
+    BaseAddress,
+    NumberOfBytesToLock);
+  if (Mdl == NULL)
+    {
+      pObDereferenceObject(Process);
+      return(STATUS_NO_MEMORY);
+    }
 
-   NTSTATUS Status;
-   PMDL Mdl;
-   PEPROCESS Process;
+  pMmProbeAndLockPages(Mdl,
+    UserMode,
+    IoWriteAccess);
 
-   DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
-          "NumberOfBytesToLock %d), NumberOfBytesLocked %x\n",ProcessHandle,BaseAddress,
-          NumberOfBytesToLock, NumberOfBytesLocked);
+  pExFreePool(Mdl);
 
-   Status = ObReferenceObjectByHandle(ProcessHandle,
-                                      PROCESS_VM_WRITE,
-                                      NULL,
-                                      UserMode,
-                                      (PVOID*)(&Process),
-                                      NULL);
-   if (!NT_SUCCESS(Status))
-   {
-      return(Status);
-   }
-
-   Mdl = MmCreateMdl(NULL,
-                     BaseAddress,
-                     NumberOfBytesToLock);
-   if(Mdl == NULL) 
-   {
-      ObDereferenceObject(Process);
-      return(STATUS_NO_MEMORY);
-   }
-   MmProbeAndLockPages(Mdl,
-                       UserMode,
-                       IoWriteAccess);
+  pObDereferenceObject(Process);
 
-   ExFreePool(Mdl);  // Are we supposed to do this here?
+  *NumberOfBytesLocked = NumberOfBytesToLock;
+  return(STATUS_SUCCESS);
+}
 
-   ObDereferenceObject(Process);
 
-   *NumberOfBytesLocked = NumberOfBytesToLock;
-   return(STATUS_SUCCESS);
+NTSTATUS STDCALL
+NtLockVirtualMemory(HANDLE ProcessHandle,
+  PVOID BaseAddress,
+  ULONG NumberOfBytesToLock,
+  PULONG NumberOfBytesLocked)
+{
+  DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
+    "NumberOfBytesToLock %d, NumberOfBytesLocked %x)\n",
+    ProcessHandle,
+    BaseAddress,
+    NumberOfBytesToLock,
+    NumberOfBytesLocked);
+
+  return MiLockVirtualMemory(ProcessHandle,
+    BaseAddress,
+    NumberOfBytesToLock,
+    NumberOfBytesLocked,
+    ObReferenceObjectByHandle,
+    MmCreateMdl,
+    ObfDereferenceObject,
+    MmProbeAndLockPages,
+    ExFreePool);
 }
 
 
-/* (tMk 2004.II.4)
- * FUNCTION: 
- * Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
- *
- */
-NTSTATUS STDCALL 
-NtQueryVirtualMemory (IN HANDLE ProcessHandle,
+NTSTATUS FASTCALL
+MiQueryVirtualMemory (IN HANDLE ProcessHandle,
                       IN PVOID Address,
                       IN CINT VirtualMemoryInformationClass,
                       OUT PVOID VirtualMemoryInformation,
                       IN ULONG Length,
-                      OUT PULONG UnsafeResultLength)
+                      OUT PULONG ResultLength)
 {
    NTSTATUS Status;
    PEPROCESS Process;
    MEMORY_AREA* MemoryArea;
-   ULONG ResultLength = 0;
    PMADDRESS_SPACE AddressSpace;
 
-   DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
-          "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
-          "Length %lu ResultLength %x)\n",ProcessHandle,Address,
-          VirtualMemoryInformationClass,VirtualMemoryInformation,
-          Length,ResultLength);
-
-   Status = ObReferenceObjectByHandle(ProcessHandle,
-                                      PROCESS_QUERY_INFORMATION,
-                                      NULL,
-                                      UserMode,
-                                      (PVOID*)(&Process),
-                                      NULL);
-
-   if (!NT_SUCCESS(Status))
+   if (Address < (PVOID)KERNEL_BASE)
    {
-      DPRINT("NtQueryVirtualMemory() = %x\n",Status);
-      return(Status);
+      Status = ObReferenceObjectByHandle(ProcessHandle,
+                                         PROCESS_QUERY_INFORMATION,
+                                         NULL,
+                                         UserMode,
+                                         (PVOID*)(&Process),
+                                         NULL);
+
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT("NtQueryVirtualMemory() = %x\n",Status);
+         return(Status);
+      }
+      AddressSpace = &Process->AddressSpace;
+   }
+   else
+   {
+      AddressSpace = MmGetKernelAddressSpace();
    }
-
-   AddressSpace = &Process->AddressSpace;
    MmLockAddressSpace(AddressSpace);
    MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
                                           Address);
@@ -160,9 +165,8 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
    {
       case MemoryBasicInformation:
          {
-            PMEMORY_BASIC_INFORMATION Info =
-               (PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
-
+           PMEMORY_BASIC_INFORMATION Info =
+               (PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
             if (Length != sizeof(MEMORY_BASIC_INFORMATION))
             {
                MmUnlockAddressSpace(AddressSpace);
@@ -172,48 +176,168 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
 
             if (MemoryArea == NULL)
             {
+              Info->Type = 0;
                Info->State = MEM_FREE;
+              Info->Protect = PAGE_NOACCESS;
+              Info->AllocationProtect = 0;
                Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
-               Info->AllocationBase = 0;
-               Info->AllocationProtect = 0;
-               /* TODO: Find the next memory area and set RegionSize! */
-               /* Since programs might depend on RegionSize for
-                * iteration, we for now just make up a value.
-                */
-               Info->RegionSize = (Address > (PVOID)0x80000000) ? 0 : 0x10000;
-               Info->Protect = PAGE_NOACCESS;
-               Info->Type = 0;
+              Info->AllocationBase = NULL;
+              Info->RegionSize = MmFindGapAtAddress(AddressSpace, Info->BaseAddress);
                Status = STATUS_SUCCESS;
-               ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
-            }
-            else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
-            {
-               Status = MmQueryAnonMem(MemoryArea, Address, Info,
-                                       &ResultLength);
-            }
-            else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
-            {
-               Status = MmQuerySectionView(MemoryArea, Address, Info,
-                                           &ResultLength);
-            }
+               *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
+           }
             else
-            {
-               Status = STATUS_UNSUCCESSFUL;
-               ResultLength = 0;
-            }
+           {
+              switch(MemoryArea->Type)
+              {
+                 case MEMORY_AREA_VIRTUAL_MEMORY:
+                     Status = MmQueryAnonMem(MemoryArea, Address, Info,
+                                             ResultLength);
+                    break;
+                 case MEMORY_AREA_SECTION_VIEW:
+                     Status = MmQuerySectionView(MemoryArea, Address, Info,
+                                                 ResultLength);
+                     break;
+                 case MEMORY_AREA_NO_ACCESS:
+                    Info->Type = 0;
+                     Info->State = MEM_FREE;
+                    Info->Protect = MemoryArea->Attributes;
+                    Info->AllocationProtect = MemoryArea->Attributes;
+                     Info->BaseAddress = MemoryArea->BaseAddress;
+                    Info->AllocationBase = MemoryArea->BaseAddress;
+                    Info->RegionSize = MemoryArea->Length;
+                     Status = STATUS_SUCCESS;
+                     *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
+                    break;
+                 case MEMORY_AREA_SHARED_DATA:
+                    Info->Type = 0;
+                     Info->State = MEM_COMMIT;
+                    Info->Protect = MemoryArea->Attributes;
+                    Info->AllocationProtect = MemoryArea->Attributes;
+                     Info->BaseAddress = MemoryArea->BaseAddress;
+                    Info->AllocationBase = MemoryArea->BaseAddress;
+                    Info->RegionSize = MemoryArea->Length;
+                     Status = STATUS_SUCCESS;
+                     *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
+                    break;
+                 case MEMORY_AREA_SYSTEM:
+                    {
+                       static int warned = 0;
+                       if ( !warned )
+                       {
+                         DPRINT1("FIXME: MEMORY_AREA_SYSTEM case incomplete (or possibly wrong) for NtQueryVirtualMemory()\n");
+                         warned = 1;
+                       }
+                    }
+                    /* FIXME - don't have a clue if this is right, but it's better than nothing */
+                    Info->Type = 0;
+                     Info->State = MEM_COMMIT;
+                    Info->Protect = MemoryArea->Attributes;
+                    Info->AllocationProtect = MemoryArea->Attributes;
+                     Info->BaseAddress = MemoryArea->BaseAddress;
+                    Info->AllocationBase = MemoryArea->BaseAddress;
+                    Info->RegionSize = MemoryArea->Length;
+                     Status = STATUS_SUCCESS;
+                     *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
+                    break;
+                 case MEMORY_AREA_KERNEL_STACK:
+                    {
+                       static int warned = 0;
+                       if ( !warned )
+                       {
+                         DPRINT1("FIXME: MEMORY_AREA_KERNEL_STACK case incomplete (or possibly wrong) for NtQueryVirtualMemory()\n");
+                         warned = 1;
+                       }
+                    }
+                    /* FIXME - don't have a clue if this is right, but it's better than nothing */
+                    Info->Type = 0;
+                     Info->State = MEM_COMMIT;
+                    Info->Protect = MemoryArea->Attributes;
+                    Info->AllocationProtect = MemoryArea->Attributes;
+                     Info->BaseAddress = MemoryArea->BaseAddress;
+                    Info->AllocationBase = MemoryArea->BaseAddress;
+                    Info->RegionSize = MemoryArea->Length;
+                     Status = STATUS_SUCCESS;
+                     *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
+                    break;
+                 default:
+                    DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea->Type);
+                    Status = STATUS_UNSUCCESSFUL;
+                     *ResultLength = 0;
+              }
+           }
             break;
          }
 
       default:
          {
             Status = STATUS_INVALID_INFO_CLASS;
-            ResultLength = 0;
+            *ResultLength = 0;
             break;
          }
    }
 
    MmUnlockAddressSpace(AddressSpace);
-   ObDereferenceObject(Process);
+   if (Address < (PVOID)KERNEL_BASE)
+   {
+      ObDereferenceObject(Process);
+   }
+
+   return Status;
+}
+
+/* (tMk 2004.II.4)
+ * FUNCTION:
+ * Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
+ *
+ */
+NTSTATUS STDCALL
+NtQueryVirtualMemory (IN HANDLE ProcessHandle,
+                      IN PVOID Address,
+                      IN CINT VirtualMemoryInformationClass,
+                      OUT PVOID VirtualMemoryInformation,
+                      IN ULONG Length,
+                      OUT PULONG UnsafeResultLength)
+{
+   NTSTATUS Status;
+   ULONG ResultLength = 0;
+   KPROCESSOR_MODE PrevMode;
+   union
+   {
+      MEMORY_BASIC_INFORMATION BasicInfo;
+   }
+   VirtualMemoryInfo;
+
+   DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
+          "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
+          "Length %lu ResultLength %x)\n",ProcessHandle,Address,
+          VirtualMemoryInformationClass,VirtualMemoryInformation,
+          Length,ResultLength);
+
+   PrevMode =  ExGetPreviousMode();
+
+   if (PrevMode == UserMode && Address >= (PVOID)KERNEL_BASE)
+   {
+      DPRINT1("Invalid parameter\n");
+      return STATUS_INVALID_PARAMETER;
+   }
+
+   Status = MiQueryVirtualMemory ( ProcessHandle,
+       Address,
+       VirtualMemoryInformationClass,
+       &VirtualMemoryInfo,
+       Length,
+       &ResultLength );
+
+   if (NT_SUCCESS(Status) && ResultLength > 0)
+   {
+      Status = MmCopyToCaller(VirtualMemoryInformation, &VirtualMemoryInfo, ResultLength);
+      if (!NT_SUCCESS(Status))
+      {
+         ResultLength = 0;
+      }
+   }
+
    if (UnsafeResultLength != NULL)
    {
       MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
@@ -223,7 +347,7 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
 
 
 /* (tMk 2004.II.5)
- * FUNCTION: 
+ * FUNCTION:
  * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
  *
  */
@@ -249,13 +373,13 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
    if (!NT_SUCCESS(Status))
       return Status;
 
-   // (tMk 2004.II.5) in Microsoft SDK I read: 
+   // (tMk 2004.II.5) in Microsoft SDK I read:
    // 'if this parameter is NULL or does not point to a valid variable, the function fails'
-   if(UnsafeOldAccessProtection == NULL) 
+   if(UnsafeOldAccessProtection == NULL)
    {
       return(STATUS_INVALID_PARAMETER);
    }
-   
+
    NumberOfBytesToProtect =
       PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
       PAGE_ROUND_DOWN(BaseAddress);
@@ -311,7 +435,7 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
 
 
 /* (tMk 2004.II.05)
- * FUNCTION: 
+ * FUNCTION:
  * Called from ReadProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
  *
  * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
@@ -326,7 +450,8 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
    NTSTATUS Status;
    PMDL Mdl;
    PVOID SystemAddress;
-   PEPROCESS Process;
+   PEPROCESS Process, CurrentProcess;
+
 
    DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
           "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
@@ -343,31 +468,40 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
       return(Status);
    }
 
-   Mdl = MmCreateMdl(NULL,
-                     Buffer,
-                     NumberOfBytesToRead);
-   if(Mdl == NULL) 
+   CurrentProcess = PsGetCurrentProcess();
+
+   if (Process == CurrentProcess)
    {
-      ObDereferenceObject(Process);
-      return(STATUS_NO_MEMORY);
+      memcpy(Buffer, BaseAddress, NumberOfBytesToRead);
    }
-   MmProbeAndLockPages(Mdl,
-                       UserMode,
-                       IoWriteAccess);
-
-   KeAttachProcess(Process);
-
-   SystemAddress = MmGetSystemAddressForMdl(Mdl);
-   memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
-
-   KeDetachProcess();
-
-   if (Mdl->MappedSystemVa != NULL)
+   else
    {
-      MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+      Mdl = MmCreateMdl(NULL,
+                        Buffer,
+                        NumberOfBytesToRead);
+      if(Mdl == NULL)
+      {
+         ObDereferenceObject(Process);
+         return(STATUS_NO_MEMORY);
+      }
+      MmProbeAndLockPages(Mdl,
+                          UserMode,
+                          IoWriteAccess);
+
+      KeAttachProcess(&Process->Pcb);
+
+      SystemAddress = MmGetSystemAddressForMdl(Mdl);
+      memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
+
+      KeDetachProcess();
+
+      if (Mdl->MappedSystemVa != NULL)
+      {
+         MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+      }
+      MmUnlockPages(Mdl);
+      ExFreePool(Mdl);
    }
-   MmUnlockPages(Mdl);
-   ExFreePool(Mdl);
 
    ObDereferenceObject(Process);
 
@@ -411,7 +545,7 @@ NtUnlockVirtualMemory(HANDLE ProcessHandle,
    Mdl = MmCreateMdl(NULL,
                      BaseAddress,
                      NumberOfBytesToUnlock);
-   if(Mdl == NULL) 
+   if(Mdl == NULL)
    {
       ObDereferenceObject(Process);
       return(STATUS_NO_MEMORY);
@@ -435,7 +569,7 @@ NtUnlockVirtualMemory(HANDLE ProcessHandle,
 /* (tMk 2004.II.05)
  * FUNCTION:
  * Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
- * 
+ *
  * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
  */
 NTSTATUS STDCALL
@@ -465,38 +599,59 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
       return(Status);
    }
 
-   Mdl = MmCreateMdl(NULL,
-                     Buffer,
-                     NumberOfBytesToWrite);
-   MmProbeAndLockPages(Mdl,
-                       UserMode,
-                       IoReadAccess);
-   if(Mdl == NULL)
+   if (Process == PsGetCurrentProcess())
    {
-      ObDereferenceObject(Process);
-      return(STATUS_NO_MEMORY);
+      memcpy(BaseAddress, Buffer, NumberOfBytesToWrite);
    }
-   KeAttachProcess(Process);
-
-   SystemAddress = MmGetSystemAddressForMdl(Mdl);
-   memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
-
-   KeDetachProcess();
-
-   ObDereferenceObject(Process);
-
-   if (Mdl->MappedSystemVa != NULL)
+   else
    {
-      MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+      Mdl = MmCreateMdl(NULL,
+                        Buffer,
+                        NumberOfBytesToWrite);
+      MmProbeAndLockPages(Mdl,
+                          UserMode,
+                          IoReadAccess);
+      if(Mdl == NULL)
+      {
+         ObDereferenceObject(Process);
+         return(STATUS_NO_MEMORY);
+      }
+      KeAttachProcess(&Process->Pcb);
+
+      SystemAddress = MmGetSystemAddressForMdl(Mdl);
+      memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
+
+      KeDetachProcess();
+
+      if (Mdl->MappedSystemVa != NULL)
+      {
+         MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+      }
+      MmUnlockPages(Mdl);
+      ExFreePool(Mdl);
    }
-   MmUnlockPages(Mdl);
-   ExFreePool(Mdl);
+
+   ObDereferenceObject(Process);
 
    *NumberOfBytesWritten = NumberOfBytesToWrite;
 
    return(STATUS_SUCCESS);
 }
 
+/*
+ * @unimplemented
+ */
+
+PVOID
+STDCALL
+MmGetVirtualForPhysical (
+    IN PHYSICAL_ADDRESS PhysicalAddress
+    )
+{
+       UNIMPLEMENTED;
+       return 0;
+}
+
 /* FUNCTION:
  * Called from EngSecureMem (subsys\win32k\eng\mem.c)
  * @unimplemented
@@ -542,7 +697,7 @@ ProbeForRead (IN PVOID Address,
               IN ULONG Length,
               IN ULONG Alignment)
 {
-   assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
+   ASSERT(Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
 
    if (Length == 0)
       return;
@@ -571,7 +726,7 @@ ProbeForWrite (IN PVOID Address,
    ULONG x;
    ULONG i;
 
-   assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
+   ASSERT(Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
 
    if (Length == 0)
       return;