|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
smashlck.c
Abstract:
This function smashes lock prefixes replacing them with NOPs
Author:
Mark Lucovsky (markl) 30-Apr-1993
Revision History:
Ted Miller (tedm) 7-Dec-1993 -- copied from imagehlp, modified for setup.
--*/
#include "spprecmp.h"
#pragma hdrstop
#define OPCODE_LOCK_PREFIX ((UCHAR)0xf0)
#define OPCODE_NO_OP ((UCHAR)0x90)
typedef struct _LOADED_IMAGE { HANDLE hFile; HANDLE hSection; PUCHAR MappedAddress; ULONG FileSize; ULONG Characteristics; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER LastRvaSection; ULONG NumberOfSections; PIMAGE_SECTION_HEADER Sections; } LOADED_IMAGE, *PLOADED_IMAGE;
PVOID RvaToVa( PVOID Rva, PLOADED_IMAGE Image ) {
PIMAGE_SECTION_HEADER Section; ULONG i; PVOID Va;
Rva = (PVOID)((PUCHAR)Rva-(PUCHAR)Image->NtHeader->OptionalHeader.ImageBase); Va = NULL; Section = Image->LastRvaSection; if ( (ULONG)Rva >= Section->VirtualAddress && (ULONG)Rva < Section->VirtualAddress + Section->SizeOfRawData ) { Va = (PVOID)((ULONG)Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress); } else { for(Section = Image->Sections,i=0; i<Image->NumberOfSections; i++,Section++) { if ( (ULONG)Rva >= Section->VirtualAddress && (ULONG)Rva < Section->VirtualAddress + Section->SizeOfRawData ) { Va = (PVOID)((ULONG)Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress); Image->LastRvaSection = Section; break; } } } if ( !Va ) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: RvaToVa %lx failed\n",Rva)); } return Va; }
BOOLEAN pSpLoadForSmash( IN PWSTR ImageName, OPTIONAL IN HANDLE FileHandle, OPTIONAL OUT PLOADED_IMAGE LoadedImage ) { NTSTATUS Status; PIMAGE_NT_HEADERS NtHeader;
//
// open and map the file.
// then fill in the loaded image descriptor
//
if(FileHandle) {
LoadedImage->hFile = FileHandle;
Status = SpGetFileSize(FileHandle,&LoadedImage->FileSize); if(NT_SUCCESS(Status)) { Status = SpMapEntireFile( FileHandle, &LoadedImage->hSection, &LoadedImage->MappedAddress, TRUE ); }
} else {
ASSERT(ImageName);
Status = SpOpenAndMapFile( ImageName, &LoadedImage->hFile, &LoadedImage->hSection, &LoadedImage->MappedAddress, &LoadedImage->FileSize, TRUE ); }
if(!NT_SUCCESS(Status)) {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: pSpLoadForSmash: open/map %ws failed (%lx)\n", ImageName ? ImageName : L"(by handle)", Status ));
return FALSE; }
//
// Check the image and find nt image headers
//
if((NtHeader = RtlImageNtHeader(LoadedImage->MappedAddress)) && NtHeader->FileHeader.SizeOfOptionalHeader) { LoadedImage->Characteristics = NtHeader->FileHeader.Characteristics; LoadedImage->NumberOfSections = NtHeader->FileHeader.NumberOfSections; LoadedImage->Sections = (PIMAGE_SECTION_HEADER)((PUCHAR)NtHeader + sizeof(IMAGE_NT_HEADERS)); LoadedImage->LastRvaSection = LoadedImage->Sections;
LoadedImage->NtHeader = NtHeader;
} else {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: pSpLoadForSmash: %ws is not an NT image\n", ImageName ? ImageName : L"(by handle)" ));
SpUnmapFile(LoadedImage->hSection,LoadedImage->MappedAddress); ZwClose(LoadedImage->hFile); }
return (BOOLEAN)(NtHeader != NULL); }
VOID SpMashemSmashem( IN HANDLE FileHandle, OPTIONAL IN PWSTR Name1, OPTIONAL IN PWSTR Name2, OPTIONAL IN PWSTR Name3 OPTIONAL ) { PWSTR FullFilename; LOADED_IMAGE LoadedImage; ULONG whocares; PIMAGE_LOAD_CONFIG_DIRECTORY ConfigInfo; ULONG CheckSum; ULONG HeaderSum; BOOLEAN LocksSmashed; BOOLEAN b;
//
// Determine whether we really need to smash locks.
// We need to do this if we are installing for a UP machine.
//
if(SpInstallingMp()) { return; }
//
// Form the full name of the file if a file handle is not specified.
//
if(FileHandle) {
FullFilename = NULL;
} else {
ASSERT(Name1);
wcscpy((PWSTR)TemporaryBuffer,Name1); if(Name2) { SpConcatenatePaths((PWSTR)TemporaryBuffer,Name2); } if(Name3) { SpConcatenatePaths((PWSTR)TemporaryBuffer,Name3); } FullFilename = SpDupStringW((PWSTR)TemporaryBuffer); }
//
// Attempt to load and map the image for smashing.
//
try {
b = pSpLoadForSmash(FullFilename,FileHandle,&LoadedImage);
} except(EXCEPTION_EXECUTE_HANDLER) {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Warning: exception while loading %ws for smash\n", FullFilename ? FullFilename : L"(by handle)" ));
b = FALSE; }
if(b) {
//
// make sure the image has correct configuration information,
// and that the LockPrefixTable is set up properly
//
// Put exception handling around this since we haven't yet verified the file
// and it may be corrupted.
//
try {
ConfigInfo = (PIMAGE_LOAD_CONFIG_DIRECTORY)RtlImageDirectoryEntryToData( LoadedImage.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &whocares );
if(ConfigInfo && ConfigInfo->LockPrefixTable) {
//
// Walk through the lock prefix table
//
PUCHAR *LockPrefixs; PUCHAR LockPrefix;
LockPrefixs = (PUCHAR *)RvaToVa((PVOID)ConfigInfo->LockPrefixTable,&LoadedImage);
while(LockPrefixs && *LockPrefixs) {
LockPrefix = RvaToVa(*LockPrefixs,&LoadedImage); if(LockPrefix && (*LockPrefix == OPCODE_LOCK_PREFIX)) {
LocksSmashed = TRUE; *LockPrefix = OPCODE_NO_OP; }
LockPrefixs++; }
if(LocksSmashed) {
//
// recompute the checksum.
//
LoadedImage.NtHeader->OptionalHeader.CheckSum = 0;
SpChecksumMappedFile( LoadedImage.MappedAddress, LoadedImage.FileSize, &HeaderSum, &CheckSum );
LoadedImage.NtHeader->OptionalHeader.CheckSum = CheckSum;
//
// Flush changes.
//
SpFlushVirtualMemory(LoadedImage.MappedAddress,0); } }
} except(EXCEPTION_EXECUTE_HANDLER) {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Warning: exception while smashing locks for %ws\n", FullFilename ? FullFilename : L"(by handle)" ));
}
SpUnmapFile(LoadedImage.hSection,LoadedImage.MappedAddress); if(!FileHandle) { ZwClose(LoadedImage.hFile); }
} else { //
// This is not really a fatal problem
// but we probably ought to alert the user.
//
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Failed to smash a lock.\n"));
}
if(FullFilename) { SpMemFree(FullFilename); } }
|