[RTL]
authorAleksey Bragin <aleksey@reactos.org>
Wed, 16 Mar 2011 09:49:07 +0000 (09:49 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Wed, 16 Mar 2011 09:49:07 +0000 (09:49 +0000)
- Implement LdrVerifyMappedImageChecksum (copied from ntdll/ldr/utils.c).

svn path=/trunk/; revision=51059

reactos/lib/rtl/image.c

index 3886fb5..479319f 100644 (file)
@@ -24,11 +24,78 @@ BOOLEAN
 NTAPI
 LdrVerifyMappedImageMatchesChecksum(
     IN PVOID BaseAddress,
-    IN ULONG NumberOfBytes,
+    IN ULONG ImageSize,
     IN ULONG FileLength)
 {
-    /* FIXME: TODO */
-    return TRUE;
+    PIMAGE_NT_HEADERS Header;
+    PUSHORT Ptr;
+    ULONG Sum;
+    ULONG CalcSum;
+    ULONG HeaderSum;
+    ULONG i;
+
+    /* Get NT header to check if it's an image at all */
+    Header = RtlImageNtHeader (BaseAddress);
+    if (!Header) return FALSE;
+
+    /* Get checksum to match */
+    HeaderSum = Header->OptionalHeader.CheckSum;
+
+    /* Zero checksum seems to be accepted */
+    if (HeaderSum == 0) return TRUE;
+
+    /* Calculate the checksum */
+    Sum = 0;
+    Ptr = (PUSHORT) BaseAddress;
+    for (i = 0; i < ImageSize / sizeof (USHORT); i++)
+    {
+        Sum += (ULONG)*Ptr;
+        if (HIWORD(Sum) != 0)
+        {
+            Sum = LOWORD(Sum) + HIWORD(Sum);
+        }
+        Ptr++;
+    }
+
+    if (ImageSize & 1)
+    {
+        Sum += (ULONG)*((PUCHAR)Ptr);
+        if (HIWORD(Sum) != 0)
+        {
+            Sum = LOWORD(Sum) + HIWORD(Sum);
+        }
+    }
+
+    CalcSum = (USHORT)(LOWORD(Sum) + HIWORD(Sum));
+
+    /* Subtract image checksum from calculated checksum. */
+    /* fix low word of checksum */
+    if (LOWORD(CalcSum) >= LOWORD(HeaderSum))
+    {
+        CalcSum -= LOWORD(HeaderSum);
+    }
+    else
+    {
+        CalcSum = ((LOWORD(CalcSum) - LOWORD(HeaderSum)) & 0xFFFF) - 1;
+    }
+
+    /* Fix high word of checksum */
+    if (LOWORD(CalcSum) >= HIWORD(HeaderSum))
+    {
+        CalcSum -= HIWORD(HeaderSum);
+    }
+    else
+    {
+        CalcSum = ((LOWORD(CalcSum) - HIWORD(HeaderSum)) & 0xFFFF) - 1;
+    }
+
+    /* Add file length */
+    CalcSum += ImageSize;
+
+    if (CalcSum != HeaderSum)
+        DPRINT1("Image %p checksum mismatches! 0x%x != 0x%x\n", BaseAddress, CalcSum, HeaderSum);
+
+    return (BOOLEAN)(CalcSum == HeaderSum);
 }
 
 /*