#define NDEBUG
#include <debug.h>
+#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
+
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
-LdrVerifyMappedImageMatchesChecksum(IN PVOID BaseAddress,
- IN ULONG NumberOfBytes,
- IN ULONG FileLength)
+LdrVerifyMappedImageMatchesChecksum(
+ IN PVOID BaseAddress,
+ 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);
}
/*
* @implemented
*/
-PIMAGE_NT_HEADERS NTAPI
-RtlImageNtHeader (IN PVOID BaseAddress)
+PIMAGE_NT_HEADERS
+NTAPI
+RtlImageNtHeader(IN PVOID BaseAddress)
{
- PIMAGE_NT_HEADERS NtHeader;
- PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
+ PIMAGE_NT_HEADERS NtHeader;
+ PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
- if (DosHeader && DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ if (DosHeader && SWAPW(DosHeader->e_magic) != IMAGE_DOS_SIGNATURE)
{
- DPRINT1("DosHeader->e_magic %x\n", DosHeader->e_magic);
- DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR)BaseAddress + DosHeader->e_lfanew));
+ DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader->e_magic));
+ DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR)BaseAddress + SWAPD(DosHeader->e_lfanew)));
}
-
- if (DosHeader && DosHeader->e_magic == IMAGE_DOS_SIGNATURE)
+ else
{
- NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)BaseAddress + DosHeader->e_lfanew);
- if (NtHeader->Signature == IMAGE_NT_SIGNATURE)
- return NtHeader;
+ NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)BaseAddress + SWAPD(DosHeader->e_lfanew));
+ if (SWAPD(NtHeader->Signature) == IMAGE_NT_SIGNATURE)
+ return NtHeader;
}
- return NULL;
+ return NULL;
}
*/
PVOID
NTAPI
-RtlImageDirectoryEntryToData(PVOID BaseAddress,
- BOOLEAN MappedAsImage,
- USHORT Directory,
- PULONG Size)
+RtlImageDirectoryEntryToData(
+ PVOID BaseAddress,
+ BOOLEAN MappedAsImage,
+ USHORT Directory,
+ PULONG Size)
{
- PIMAGE_NT_HEADERS NtHeader;
- ULONG Va;
-
- /* Magic flag for non-mapped images. */
- if ((ULONG_PTR)BaseAddress & 1)
- {
- BaseAddress = (PVOID)((ULONG_PTR)BaseAddress & ~1);
- MappedAsImage = FALSE;
- }
+ PIMAGE_NT_HEADERS NtHeader;
+ ULONG Va;
+
+ /* Magic flag for non-mapped images. */
+ if ((ULONG_PTR)BaseAddress & 1)
+ {
+ BaseAddress = (PVOID)((ULONG_PTR)BaseAddress & ~1);
+ MappedAsImage = FALSE;
+ }
- NtHeader = RtlImageNtHeader (BaseAddress);
- if (NtHeader == NULL)
- return NULL;
+ NtHeader = RtlImageNtHeader (BaseAddress);
+ if (NtHeader == NULL)
+ return NULL;
- if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
- return NULL;
+ if (Directory >= SWAPD(NtHeader->OptionalHeader.NumberOfRvaAndSizes))
+ return NULL;
- Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
- if (Va == 0)
- return NULL;
+ Va = SWAPD(NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress);
+ if (Va == 0)
+ return NULL;
- *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
+ *Size = SWAPD(NtHeader->OptionalHeader.DataDirectory[Directory].Size);
- if (MappedAsImage || Va < NtHeader->OptionalHeader.SizeOfHeaders)
- return (PVOID)((ULONG_PTR)BaseAddress + Va);
+ if (MappedAsImage || Va < SWAPD(NtHeader->OptionalHeader.SizeOfHeaders))
+ return (PVOID)((ULONG_PTR)BaseAddress + Va);
- /* image mapped as ordinary file, we must find raw pointer */
- return RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
+ /* image mapped as ordinary file, we must find raw pointer */
+ return RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
}
*/
PIMAGE_SECTION_HEADER
NTAPI
-RtlImageRvaToSection (
- PIMAGE_NT_HEADERS NtHeader,
- PVOID BaseAddress,
- ULONG Rva
- )
+RtlImageRvaToSection(
+ PIMAGE_NT_HEADERS NtHeader,
+ PVOID BaseAddress,
+ ULONG Rva)
{
- PIMAGE_SECTION_HEADER Section;
- ULONG Va;
- ULONG Count;
-
- Count = NtHeader->FileHeader.NumberOfSections;
- Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
- NtHeader->FileHeader.SizeOfOptionalHeader);
- while (Count)
- {
- Va = Section->VirtualAddress;
- if ((Va <= Rva) &&
- (Rva < Va + Section->SizeOfRawData))
- return Section;
- Section++;
- }
- return NULL;
+ PIMAGE_SECTION_HEADER Section;
+ ULONG Va;
+ ULONG Count;
+
+ Count = SWAPW(NtHeader->FileHeader.NumberOfSections);
+ Section = IMAGE_FIRST_SECTION(NtHeader);
+
+ while (Count--)
+ {
+ Va = SWAPD(Section->VirtualAddress);
+ if ((Va <= Rva) &&
+ (Rva < Va + SWAPD(Section->Misc.VirtualSize)))
+ return Section;
+ Section++;
+ }
+ return NULL;
}
*/
PVOID
NTAPI
-RtlImageRvaToVa (
- PIMAGE_NT_HEADERS NtHeader,
- PVOID BaseAddress,
- ULONG Rva,
- PIMAGE_SECTION_HEADER *SectionHeader
- )
+RtlImageRvaToVa(
+ PIMAGE_NT_HEADERS NtHeader,
+ PVOID BaseAddress,
+ ULONG Rva,
+ PIMAGE_SECTION_HEADER *SectionHeader)
{
- PIMAGE_SECTION_HEADER Section = NULL;
-
- if (SectionHeader)
- Section = *SectionHeader;
-
- if (Section == NULL ||
- Rva < Section->VirtualAddress ||
- Rva >= Section->VirtualAddress + Section->SizeOfRawData)
- {
- Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
- if (Section == NULL)
- return 0;
-
- if (SectionHeader)
- *SectionHeader = Section;
- }
-
- return (PVOID)((ULONG_PTR)BaseAddress +
- Rva +
- Section->PointerToRawData -
- (ULONG_PTR)Section->VirtualAddress);
+ PIMAGE_SECTION_HEADER Section = NULL;
+
+ if (SectionHeader)
+ Section = *SectionHeader;
+
+ if (Section == NULL ||
+ Rva < SWAPD(Section->VirtualAddress) ||
+ Rva >= SWAPD(Section->VirtualAddress) + SWAPD(Section->Misc.VirtualSize))
+ {
+ Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
+ if (Section == NULL)
+ return 0;
+
+ if (SectionHeader)
+ *SectionHeader = Section;
+ }
+
+ return (PVOID)((ULONG_PTR)BaseAddress +
+ Rva +
+ SWAPD(Section->PointerToRawData) -
+ (ULONG_PTR)SWAPD(Section->VirtualAddress));
}
PIMAGE_BASE_RELOCATION
IN ULONG_PTR Address,
IN ULONG Count,
IN PUSHORT TypeOffset,
- IN LONGLONG Delta
- )
+ IN LONGLONG Delta)
{
SHORT Offset;
USHORT Type;
USHORT i;
PUSHORT ShortPtr;
PULONG LongPtr;
+ PULONGLONG LongLongPtr;
for (i = 0; i < Count; i++)
{
- Offset = *TypeOffset & 0xFFF;
- Type = *TypeOffset >> 12;
+ Offset = SWAPW(*TypeOffset) & 0xFFF;
+ Type = SWAPW(*TypeOffset) >> 12;
ShortPtr = (PUSHORT)(RVA(Address, Offset));
/*
{*/
switch (Type)
{
- /* case IMAGE_REL_BASED_SECTION : */
- /* case IMAGE_REL_BASED_REL32 : */
+ /* case IMAGE_REL_BASED_SECTION : */
+ /* case IMAGE_REL_BASED_REL32 : */
case IMAGE_REL_BASED_ABSOLUTE:
break;
break;
case IMAGE_REL_BASED_LOW:
- *ShortPtr += LOWORD(Delta);
+ *ShortPtr = SWAPW(*ShortPtr) + LOWORD(Delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
LongPtr = (PULONG)RVA(Address, Offset);
- *LongPtr += (ULONG)Delta;
+ *LongPtr = SWAPD(*LongPtr) + (ULONG)Delta;
+ break;
+
+ case IMAGE_REL_BASED_DIR64:
+ LongLongPtr = (PUINT64)RVA(Address, Offset);
+ *LongLongPtr = SWAPQ(*LongLongPtr) + Delta;
break;
case IMAGE_REL_BASED_HIGHADJ:
case IMAGE_REL_BASED_MIPS_JMPADDR:
default:
DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
- DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
+ DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, SWAPW(*TypeOffset));
return (PIMAGE_BASE_RELOCATION)NULL;
}
IN PCCH LoaderName,
IN ULONG Success,
IN ULONG Conflict,
- IN ULONG Invalid
- )
+ IN ULONG Invalid)
{
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_DATA_DIRECTORY RelocationDDir;
if (NtHeaders == NULL)
return Invalid;
- if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+ if (SWAPW(NtHeaders->FileHeader.Characteristics) & IMAGE_FILE_RELOCS_STRIPPED)
{
return Conflict;
}
RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
- if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
+ if (SWAPD(RelocationDDir->VirtualAddress) == 0 || SWAPD(RelocationDDir->Size) == 0)
{
return Success;
}
- Delta = (ULONG_PTR)BaseAddress - NtHeaders->OptionalHeader.ImageBase + AdditionalBias;
- RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + RelocationDDir->VirtualAddress);
- RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
+ Delta = (ULONG_PTR)BaseAddress - SWAPD(NtHeaders->OptionalHeader.ImageBase) + AdditionalBias;
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + SWAPD(RelocationDDir->VirtualAddress));
+ RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + SWAPD(RelocationDDir->Size));
while (RelocationDir < RelocationEnd &&
- RelocationDir->SizeOfBlock > 0)
+ SWAPW(RelocationDir->SizeOfBlock) > 0)
{
- Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
- Address = (ULONG_PTR)RVA(BaseAddress, RelocationDir->VirtualAddress);
+ Count = (SWAPW(RelocationDir->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
+ Address = (ULONG_PTR)RVA(BaseAddress, SWAPD(RelocationDir->VirtualAddress));
TypeOffset = (PUSHORT)(RelocationDir + 1);
RelocationDir = LdrProcessRelocationBlockLongLong(Address,
- Count,
- TypeOffset,
- Delta);
+ Count,
+ TypeOffset,
+ Delta);
if (RelocationDir == NULL)
{
return Success;
}
+
/* EOF */