随笔 - 0, 文章 - 2, 评论 - 0, 引用 - 0
数据加载中……

测试代码


#include 
"iop.h"
#include 
"ntddft.h"
#include 
<inbv.h>
#include 
<windef.h>

//
// Processor specific macros.
//

#if defined (i386)

#define PROGRAM_COUNTER(_context)   ((_context)->Eip)
#define STACK_POINTER(_context)     ((_context)->Esp)
#define CURRENT_IMAGE_TYPE()        IMAGE_FILE_MACHINE_I386
#define PaeEnabled() X86PaeEnabled()

#elif defined (ALPHA)

#define PROGRAM_COUNTER(_context)   ((_context)->Fir)
#define STACK_POINTER(_context)     ((_context)->IntSp)
#define CURRENT_IMAGE_TYPE()        IMAGE_FILE_MACHINE_ALPHA
#define PaeEnabled() (FALSE)

#elif defined (_IA64_)

#define PROGRAM_COUNTER(_context)   ((_context)->StIIP)
#define STACK_POINTER(_context)     ((_context)->IntSp)
#define CURRENT_IMAGE_TYPE()        IMAGE_FILE_MACHINE_IA64
#define PaeEnabled() (FALSE)

#else

#error ("unknown processor type")

#endif

//
// min3(_a,_b,_c)
//
// Same as min() but takes 3 parameters.
//

#define min3(_a,_b,_c) ( min ( min ((_a), (_b)), min ((_a), (_c))) )


//
// Global variables
//

extern PVOID MmPfnDatabase;
extern PFN_NUMBER MmHighestPossiblePhysicalPage;

NTSTATUS IopFinalCrashDumpStatus         
= -1;
ULONG    IopCrashDumpStateChange         
=  0;
BOOLEAN  IopDumpFileContainsNewDump      
= FALSE;

//
// Max dump transfer sizes
//

#define IO_DUMP_MAXIMUM_TRANSFER_SIZE   ( 1024 * 64 )
#define IO_DUMP_MINIMUM_TRANSFER_SIZE   ( 1024 * 32 )
#define IO_DUMP_MINIMUM_FILE_SIZE       ( PAGE_SIZE * 256 )
#define MAX_UNICODE_LENGTH              ( 512 )

#define DEFAULT_DRIVER_PATH             L"\\SystemRoot\\System32\\Drivers\\"
#define DEFAULT_DUMP_DRIVER             L"\\SystemRoot\\System32\\Drivers\\diskdump.sys"
#define SCSIPORT_DRIVER_NAME            L"scsiport.sys"
#define MAX_TRIAGE_STACK_SIZE           ( 16 * 1024 )
#define DEFAULT_TRIAGE_DUMP_FLAGS (0xFFFFFFFF)


//
// Function prototypes
//


NTSTATUS
IopWriteTriageDump(
    IN ULONG FieldsToWrite,
    IN PDUMP_DRIVER_WRITE WriteRoutine,
    IN OUT PLARGE_INTEGER Mcb,
    IN OUT PMDL Mdl,
    IN ULONG DiverTransferSize,
    IN PCONTEXT Context,
    IN LPBYTE Buffer,
    IN ULONG BufferSize,
    IN ULONG ServicePackBuild,
    IN ULONG TriageOptions
    );

NTSTATUS
IopWriteSummaryDump(
    IN PRTL_BITMAP PageMap,
    IN PDUMP_DRIVER_WRITE WriteRoutine,
    IN PANSI_STRING ProgressMessage,
    IN PUCHAR MessageBuffer,
    IN OUT PLARGE_INTEGER Mcb,
    IN ULONG DiverTransferSize
    );

NTSTATUS
IopWriteToDisk(
    IN PVOID Buffer,
    IN ULONG WriteLength,
    IN PDUMP_DRIVER_WRITE DriverWriteRoutine,
    IN OUT PLARGE_INTEGER 
* Mcb,
    IN OUT PMDL Mdl,
    IN ULONG DriverTransferSize
    );
    
VOID
IopMapPhysicalMemory(
    IN OUT PMDL Mdl,
    IN ULONG_PTR MemoryAddress,
    IN PPHYSICAL_MEMORY_RUN PhysicalMemoryRun,
    IN ULONG Length
    );

NTSTATUS
IopLoadDumpDriver (
    IN OUT PDUMP_STACK_CONTEXT  DumpStack,
    IN PWCHAR DriverNameString,
    IN PWCHAR NewBaseNameString
    );

NTSTATUS
IoSetCrashDumpState(
    IN SYSTEM_CRASH_STATE_INFORMATION 
*pDumpState
    );

PSUMMARY_DUMP_HEADER
IopInitializeSummaryDump(
    IN PDUMP_CONTROL_BLOCK pDcb
    );

NTSTATUS
IopWriteSummaryHeader(
    IN PSUMMARY_DUMP_HEADER    pSummaryHeader,
    IN PDUMP_DRIVER_WRITE      pfWrite,
    IN OUT PLARGE_INTEGER 
*    pMcbBuffer,
    IN OUT PMDL                pMdl,
    IN ULONG                   dwWriteSize,
    IN ULONG                   dwLength
    );

VOID
IopMapVirtualToPhysicalMdl(
    IN OUT PMDL pMdl,
    IN ULONG_PTR dwMemoryAddress,
    IN ULONG    dwLength
    );

ULONG
IopCreateSummaryDump (
    IN PSUMMARY_DUMP_HEADER pHeader
    );

VOID
IopDeleteNonExistentMemory(
    PSUMMARY_DUMP_HEADER        pHeader,
    PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
    );


NTSTATUS
IopGetDumpStack (
    IN PWCHAR                         ModulePrefix,
    OUT PDUMP_STACK_CONTEXT           
*pDumpStack,
    IN PUNICODE_STRING                pUniDeviceName,
    IN PWSTR                          pDumpDriverName,
    IN DEVICE_USAGE_NOTIFICATION_TYPE UsageType,
    IN ULONG                          IgnoreDeviceUsageFailure
    );

BOOLEAN
IopInitializeDCB(
    );

LARGE_INTEGER
IopCalculateRequiredDumpSpace(
    IN ULONG            dwDmpFlags,
    IN ULONG            dwHeaderSize,
    IN PFN_NUMBER       dwMaxPages,
    IN PFN_NUMBER       dwMaxSummaryPages
    );

NTSTATUS
IopCompleteDumpInitialization(
    IN HANDLE     FileHandle
    );

#if DBG

VOID
IopDebugPrint(
    ULONG  DebugPrintLevel,
    PCCHAR DebugMessage,
    
    );

#define IoDebugPrint(X) IopDebugPrint X

#else

#define IoDebugPrint(X)

#endif //DBG


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,IoGetDumpStack)
#pragma alloc_text(PAGE,IopLoadDumpDriver)
#pragma alloc_text(PAGE,IoFreeDumpStack)
#pragma alloc_text(PAGE,IoGetCrashDumpInformation)
#pragma alloc_text(PAGE,IoGetCrashDumpStateInformation)
#pragma alloc_text(PAGE,IoSetCrashDumpState)
#endif


#if defined (i386)

//
// Functions 
//


BOOL
X86PaeEnabled(
    )

/*++

Routine Description:

    Is PAE currently enabled?
    
Return Values:

    Return TRUE if PAE is enabled in the CR4 register, FALSE otherwise.

--
*/

    
{
    ULONG Reg_Cr4;
    
    _asm 
{
        _emit 0Fh
        _emit 20h
        _emit 0E0h  ;; mov eax, cr4
        mov Reg_Cr4, eax
    }


    
return (Reg_Cr4 & CR4_PAE ? TRUE : FALSE);
}


#endif

        

BOOLEAN
IopIsAddressRangeValid(
    IN PVOID VirtualAddress,
    IN SIZE_T Length
    )

/*++

Routine Description:

    Validate a range of addresses.

Arguments:

    Virtual Address - Beginning of of memory block to validate.

    Length - Length of memory block to validate.

Return Value:

    TRUE - Address range is valid.

    FALSE - Address range is not valid.

--
*/


{
    UINT_PTR Va;
    ULONG Pages;

    Va 
= (UINT_PTR) PAGE_ALIGN (VirtualAddress);
    Pages 
= COMPUTE_PAGES_SPANNED (VirtualAddress, Length);

    
while (Pages) {

        
if (!MmIsAddressValid ( (LPVOID) Va)) {
            
return FALSE;
        }


        Va 
+= PAGE_SIZE;
        Pages
--;
    }


    
return TRUE;
}

    


NTSTATUS
IoGetDumpStack (
    IN PWCHAR                          ModulePrefix,
    OUT PDUMP_STACK_CONTEXT          
* pDumpStack,
    IN  DEVICE_USAGE_NOTIFICATION_TYPE UsageType,
    IN  ULONG                          IgnoreDeviceUsageFailure
    )
/*++

Routine Description:

    This routine loads a dump stack instance and returns an allocated
    context structure to track the loaded dumps stack.

Arguments:

    ModePrefix      - The prefix to prepent to BaseName during the load
                      operation.  This allows loading the same drivers
                      multiple times with different virtual names and
                      linkages.

    pDumpStack      - The returned dump stack context structure

    UsageType       - The Device Notification Usage Type for this file, that
                      this routine will send as to the device object once the
                      file has been successfully created and initialized.

    IgnoreDeviceUsageFailure - If the Device Usage Notification Irp fails, allow
                      this to succeed anyway.

Return Value:

    Status

--
*/

{

    PAGED_CODE();
    
return IopGetDumpStack(ModulePrefix,
                           pDumpStack,
                           
&IoArcBootDeviceName,
                           DEFAULT_DUMP_DRIVER,
                           UsageType,
                           IgnoreDeviceUsageFailure
                           );
}




NTSTATUS
IopGetDumpStack (
    IN PWCHAR                         ModulePrefix,
    OUT PDUMP_STACK_CONTEXT         
* pDumpStack,
    IN PUNICODE_STRING                pUniDeviceName,
    IN PWCHAR                         pDumpDriverName,
    IN DEVICE_USAGE_NOTIFICATION_TYPE UsageType,
    IN ULONG                          IgnoreDeviceUsageFailure
    )
/*++

Routine Description:

    This routine loads a dump stack instance and returns an allocated
    context structure to track the loaded dumps stack.

Arguments:

    ModePrefix      - The prefix to prepent to BaseName during the load
                      operation.  This allows loading the same drivers
                      multiple times with different virtual names and
                      linkages.

    pDumpStack      - The returned dump stack context structure

    pDeviceName     - The name of the target dump device

    pDumpDriverName - The name of the target dump driver

    UsageType       - The Device Notification Usage Type for this file, that
                      this routine will send as to the device object once the
                      file has been successfully created and initialized.

    IgnoreDeviceUsageFailure - If the Device Usage Notification Irp fails, allow
                      this to succeed anyway.

Return Value:

    Status

--
*/

{
    PDUMP_STACK_CONTEXT         DumpStack;
    PUCHAR                      Buffer;
    PUCHAR                      PartitionName;
    ANSI_STRING                 AnsiString;
    UNICODE_STRING              TempName;
    OBJECT_ATTRIBUTES           ObjectAttributes;
    NTSTATUS                    Status;
    HANDLE                      DeviceHandle;
    SCSI_ADDRESS                ScsiAddress;
    BOOLEAN                     ScsiDump;
    PARTITION_INFORMATION       PartitionInfo;
    PFILE_OBJECT                FileObject;
    PDEVICE_OBJECT              DeviceObject;
    PINITIALIZATION_CONTEXT     DumpInit;
    PDUMP_POINTERS              DumpPointers;
    UNICODE_STRING              DriverName;
    PDRIVER_OBJECT              DriverObject;
    PIRP                        Irp;
    PIO_STACK_LOCATION          IrpSp;
    IO_STATUS_BLOCK             IoStatus;
    PWCHAR                      DumpName, NameOffset;
    KEVENT                      Event;
    PVOID                       p1;
    PHYSICAL_ADDRESS            pa;
    ULONG                       i;
    IO_STACK_LOCATION           irpSp;
    ULONG                       information;

    IoDebugPrint((
2,"IopGetDumpStack: Prefix:%ws stk: %x device:%ws driver:%ws\n",
                ModulePrefix, pDumpStack, pUniDeviceName
->Buffer,pDumpDriverName));

    ASSERT (DeviceUsageTypeUndefined 
!= UsageType);

    DumpStack 
= ExAllocatePoolWithTag (
                    NonPagedPool,
                    
sizeof (DUMP_STACK_CONTEXT) + sizeof (DUMP_POINTERS),
                    
'pmuD'
                    );

    
if (!DumpStack) {
        
return STATUS_INSUFFICIENT_RESOURCES;
    }


    RtlZeroMemory(DumpStack, 
sizeof(DUMP_STACK_CONTEXT)+sizeof(DUMP_POINTERS));
    DumpInit 
= &DumpStack->Init;
    DumpPointers 
= (PDUMP_POINTERS) (DumpStack + 1);
    DumpStack
->DumpPointers = DumpPointers;
    InitializeListHead (
&DumpStack->DriverList);
    DumpName 
= NULL;

    
//
    
// Allocate scratch buffer
    
//

    Buffer 
= ExAllocatePoolWithTag (PagedPool, PAGE_SIZE, 'pmuD');
    
if (!Buffer) {
        ExFreePool (DumpStack);
        
return STATUS_INSUFFICIENT_RESOURCES;
    }


    
if (!KeGetBugMessageText(BUGCODE_PSS_CRASH_INIT, &DumpStack->InitMsg) ||
        
!KeGetBugMessageText(BUGCODE_PSS_CRASH_PROGRESS, &DumpStack->ProgMsg) ||
        
!KeGetBugMessageText(BUGCODE_PSS_CRASH_DONE, &DumpStack->DoneMsg)) {
            Status 
= STATUS_UNSUCCESSFUL;
            
goto Done;
    }


    InitializeObjectAttributes(
        
&ObjectAttributes,
        pUniDeviceName,
        
0,
        NULL,
        NULL
        );

    Status 
= ZwOpenFile(
              
&DeviceHandle,
              FILE_READ_DATA 
| SYNCHRONIZE,
              
&ObjectAttributes,
              
&IoStatus,
              FILE_SHARE_READ 
| FILE_SHARE_WRITE,
              FILE_NON_DIRECTORY_FILE
              );

    
if (!NT_SUCCESS(Status)) {
        IoDebugPrint ((
0,
                       
"IODUMP: Could not open boot device partition, %s\n",
                       Buffer
                       ));
        
goto Done;
    }


    
//
    
// Check to see whether or not the system was booted from a SCSI device.
    
//

    Status 
= ZwDeviceIoControlFile (
                    DeviceHandle,
                    NULL,
                    NULL,
                    NULL,
                    
&IoStatus,
                    IOCTL_SCSI_GET_ADDRESS,
                    NULL,
                    
0,
                    
&ScsiAddress,
                    
sizeof( SCSI_ADDRESS )
                    );

    
if (Status == STATUS_PENDING) {
        ZwWaitForSingleObject (
            DeviceHandle,
            FALSE,
            NULL
            );

        Status 
= IoStatus.Status;
    }


    ScsiDump 
= (BOOLEAN) (NT_SUCCESS(Status));

    
//
    
// If SCSI then allocate storage to contain the target address information.
    
//

    DumpInit
->TargetAddress = NULL;

    
if (ScsiDump) {

        DumpInit
->TargetAddress = ExAllocatePoolWithTag (
                                    NonPagedPool,
                                    
sizeof (SCSI_ADDRESS),
                                    
'pmuD'
                                    );
        
//
        
// It is ok If the allocation fails. The scsi dump driver will scan
        
// all devices if the targetaddress information does not exist
        
//

        
if (DumpInit->TargetAddress) {
            RtlCopyMemory(DumpInit
->TargetAddress,&ScsiAddress,sizeof(SCSI_ADDRESS));
        }

    }


    
//
    
// Determine the disk signature for the device from which the system was
    
// booted and get the partition offset.
    
//

    Status 
= ZwDeviceIoControlFile(
                    DeviceHandle,
                    NULL,
                    NULL,
                    NULL,
                    
&IoStatus,
                    IOCTL_DISK_GET_PARTITION_INFO,
                    NULL,
                    
0,
                    
&PartitionInfo,
                    
sizeof( PARTITION_INFORMATION )
                    );

    
if (Status == STATUS_PENDING) {
        ZwWaitForSingleObject (
            DeviceHandle,
            FALSE,
            NULL
            );

        Status 
= IoStatus.Status;
    }


    IoDebugPrint((
2,"Partition Type = %x\n",PartitionInfo.PartitionType));
    IoDebugPrint((
2,"Boot Indicator = %x\n",PartitionInfo.BootIndicator));

    Status 
= ZwDeviceIoControlFile(
                    DeviceHandle,
                    NULL,
                    NULL,
                    NULL,
                    
&IoStatus,
                    IOCTL_DISK_GET_DRIVE_LAYOUT,
                    NULL,
                    
0,
                    Buffer,
                    PAGE_SIZE
                    );

    
if (Status == STATUS_PENDING) {
        ZwWaitForSingleObject (
            DeviceHandle,
            FALSE,
            NULL
            );

        Status 
= IoStatus.Status;
    }


    DumpInit
->DiskSignature = ((PDRIVE_LAYOUT_INFORMATION) Buffer)->Signature;

    
//
    
// Get the adapter object and base mapping registers for the disk from
    
// the disk driver.  These will be used to call the HAL once the system
    
// system has crashed, since it is not possible at that point to recreate
    
// them from scratch.
    
//

    ObReferenceObjectByHandle (
            DeviceHandle,
            
0,
            IoFileObjectType,
            KernelMode,
            (PVOID 
*&FileObject,
            NULL
            );


    DeviceObject 
= IoGetRelatedDeviceObject (FileObject);

    KeInitializeEvent( 
&Event, NotificationEvent, FALSE );

    Irp 
= IoBuildDeviceIoControlRequest(
                IOCTL_SCSI_GET_DUMP_POINTERS,
                DeviceObject,
                NULL,
                
0,
                DumpPointers,
                
sizeof (DUMP_POINTERS),
                FALSE,
                
&Event,
                
&IoStatus
                );

    
if (!Irp) {
        ObDereferenceObject (FileObject);
        ZwClose (DeviceHandle);
        Status 
= STATUS_INSUFFICIENT_RESOURCES;
        
goto Done;
    }


    IrpSp 
= IoGetNextIrpStackLocation (Irp);

    IrpSp
->FileObject = FileObject;

    Status 
= IoCallDriver( DeviceObject, Irp );

    
if (Status == STATUS_PENDING) {
        KeWaitForSingleObject(
&Event, Executive, KernelMode, FALSE, NULL);
        Status 
= IoStatus.Status;
    }


    
if (!NT_SUCCESS(Status)  ||  IoStatus.Information < FIELD_OFFSET(DUMP_POINTERS, DeviceObject)) {

        IoDebugPrint ((
0,
                       
"IODUMP: Could not get dump pointers; error = %x, length %x\n",
                        Status,
                        IoStatus.Information
                        ));
        ObDereferenceObject (FileObject);
//      NtClose (DeviceHandle);
        ZwClose (DeviceHandle);
        
goto Done;
    }

    DumpStack
->PointersLength = (ULONG) IoStatus.Information;

    
//
    
// If the driver returned a pointer to a device object, that is the
    
// object for the dump driver  (non-scsi case)
    
//

    DeviceObject 
= (PDEVICE_OBJECT) DumpPointers->DeviceObject;
    
if (DeviceObject) {
        DriverObject 
= DeviceObject->DriverObject;

        
//
        
// Loop through the name of the driver looking for the end of the name,
        
// which is the name of the dump image.
        
//

        DumpName 
= DriverObject->DriverName.Buffer;
        
while ( NameOffset = wcsstr( DumpName, L"\\" )) {
            DumpName 
= ++NameOffset;
        }


        ScsiDump 
= FALSE;
    }


    
//
    
// Release the handle, but keep the reference to the file object as it
    
// will be needed at free dump dump driver time
    
//

    DumpStack
->FileObject = FileObject;
    ZwClose (DeviceHandle);

    
//
    
// Fill in some DumpInit results
    
//

    DumpInit
->Length             = sizeof (INITIALIZATION_CONTEXT);
    DumpInit
->StallRoutine       = &KeStallExecutionProcessor;
    DumpInit
->AdapterObject      = DumpPointers->AdapterObject;
    DumpInit
->MappedRegisterBase = DumpPointers->MappedRegisterBase;
    DumpInit
->PortConfiguration  = DumpPointers->DumpData;

    DumpStack
->ModulePrefix      = ModulePrefix;
    DumpStack
->PartitionOffset   = PartitionInfo.StartingOffset;
    DumpStack
->UsageType         = DeviceUsageTypeUndefined;

    
//
    
// The minimum common buffer size is IO_DUMP_COMMON_BUFFER_SIZE (compatability)
    
// This is used by the dump driver for SRB extension, CachedExtension, and sense buffer
    
//
    if (DumpPointers->CommonBufferSize < IO_DUMP_COMMON_BUFFER_SIZE) {
        DumpPointers
->CommonBufferSize = IO_DUMP_COMMON_BUFFER_SIZE;
    }

    DumpInit
->CommonBufferSize    = DumpPointers->CommonBufferSize;

    
//
    
// Allocate the required common buffers
    
//

    
if (DumpPointers->AllocateCommonBuffers) {
        pa.QuadPart 
= 0x1000000 - 1;
        
for (i=0; i < 2; i++{
            
if (DumpInit->AdapterObject) {

#if !defined(NO_LEGACY_DRIVERS)
                p1 
= HalAllocateCommonBuffer(
                    DumpInit
->AdapterObject,
                    DumpPointers
->CommonBufferSize,
                    
&pa,
                    FALSE
                    );
                
#else
                p1 
= (*((PDMA_ADAPTER)DumpInit->AdapterObject)->DmaOperations->
                      AllocateCommonBuffer)(
                          (PDMA_ADAPTER)DumpInit
->AdapterObject,
                          DumpPointers
->CommonBufferSize,
                          
&pa,
                          FALSE
                          );
                
#endif // NO_LEGACY_DRIVERS
                        
            }
 else {
                p1 
= MmAllocateContiguousMemory (
                        DumpPointers
->CommonBufferSize,
                        pa
                        );

                
if (!p1) {
                    p1 
= MmAllocateNonCachedMemory (DumpPointers->CommonBufferSize);
                }

                pa 
= MmGetPhysicalAddress(p1);
            }


            
if (!p1) {
                IoDebugPrint ((
0"IODUMP: Could not allocate common buffers for dump\n"));
                Status 
= STATUS_INSUFFICIENT_RESOURCES;
                
goto Done;
            }


            DumpInit
->CommonBuffer[i] = p1;
            DumpInit
->PhysicalAddress[i] = pa;
        }

    }


    
//
    
// Determine whether or not the system booted from SCSI.
    
//

    
if (ScsiDump) {

        
//
        
// Load the boot disk and port driver to be used by the various
        
// miniports for writing memory to the disk.
        
//

        Status 
= IopLoadDumpDriver (
                        DumpStack,
                        pDumpDriverName,
                        SCSIPORT_DRIVER_NAME
                        );

        
if (!NT_SUCCESS(Status)) {

            IopLogErrorEvent(
0,9,STATUS_SUCCESS,IO_DUMP_DRIVER_LOAD_FAILURE,0,NULL,0,NULL);
            
goto Done;
        }


        
//
        
// The disk and port dump driver has been loaded.  Load the appropriate
        
// miniport driver as well so that the boot device can be accessed.
        
//

        DriverName.Length 
= 0;
        DriverName.Buffer 
= (PVOID) Buffer;
        DriverName.MaximumLength 
= PAGE_SIZE;


        
//
        
// The system was booted from SCSI. Get the name of the appropriate
        
// miniport driver and load it.
        
//

        sprintf(Buffer, 
"\\Device\\ScsiPort%d", ScsiAddress.PortNumber );
        RtlInitAnsiString( 
&AnsiString, Buffer );
        RtlAnsiStringToUnicodeString( 
&TempName, &AnsiString, TRUE );
        InitializeObjectAttributes(
                    
&ObjectAttributes,
                    
&TempName,
                    
0,
                    NULL,
                    NULL
                    );

        Status 
= ZwOpenFile(
                    
&DeviceHandle,
                    FILE_READ_ATTRIBUTES,
                    
&ObjectAttributes,
                    
&IoStatus,
                    FILE_SHARE_READ 
| FILE_SHARE_WRITE,
                    FILE_NON_DIRECTORY_FILE
                    );

        RtlFreeUnicodeString( 
&TempName );
        
if (!NT_SUCCESS( Status )) {
            IoDebugPrint ((
0,
                           
"IODUMP: Could not open SCSI port %d, error = %x\n",
                           ScsiAddress.PortNumber,
                           Status
                           ));
            
goto Done;
        }


        
//
        
// Convert the file handle into a pointer to the device object, and
        
// get the name of the driver from its driver object.
        
//

        ObReferenceObjectByHandle(
                    DeviceHandle,
                    
0,
                    IoFileObjectType,
                    KernelMode,
                    (PVOID 
*&FileObject,
                    NULL
                    );

        DriverObject 
= FileObject->DeviceObject->DriverObject;
        ObDereferenceObject( FileObject );
        ZwClose( DeviceHandle );
        
//
        
// Loop through the name of the driver looking for the end of the name,
        
// which is the name of the miniport image.
        
//

        DumpName 
= DriverObject->DriverName.Buffer;
        
while ( NameOffset = wcsstr( DumpName, L"\\" )) {
            DumpName 
= ++NameOffset;
        }

    }


    
//
    
// Load the dump driver
    
//

    
if (!DumpName) {
        Status 
= STATUS_NOT_SUPPORTED;
        
goto Done;
    }


    swprintf ((PWCHAR) Buffer, L
"\\SystemRoot\\System32\\Drivers\\%s.sys", DumpName);
    Status 
= IopLoadDumpDriver (
                    DumpStack,
                    (PWCHAR) Buffer,
                    NULL
                    );
    
if (!NT_SUCCESS(Status)) {

        IopLogErrorEvent(
0,10,STATUS_SUCCESS,IO_DUMP_DRIVER_LOAD_FAILURE,0,NULL,0,NULL);
        
goto Done;
    }


    
//
    
// Claim the file as part of specific device usage path.
    
//

    FileObject 
= DumpStack->FileObject;
    DeviceObject 
= IoGetRelatedDeviceObject (FileObject);

    RtlZeroMemory (
&irpSp, sizeof (IO_STACK_LOCATION));

    irpSp.MajorFunction 
= IRP_MJ_PNP;
    irpSp.MinorFunction 
= IRP_MN_DEVICE_USAGE_NOTIFICATION;
    irpSp.Parameters.UsageNotification.Type 
= UsageType;
    irpSp.Parameters.UsageNotification.InPath 
= TRUE;
    irpSp.FileObject 
= FileObject;

    Status 
= IopSynchronousCall (DeviceObject, &irpSp, (VOID **&information);
    ASSERT (
0 == information);

    
if (!NT_SUCCESS(Status) && IgnoreDeviceUsageFailure) {
        IoDebugPrint ((
0,
                       
"IopGetDumpStack: DEVICE_USAGE_NOTIFICATION "
                       
"Error ignored (%x)\n",
                       Status));
        Status 
= STATUS_SUCCESS;
    }


    
if (NT_SUCCESS(Status)) {
        DumpStack
->UsageType         = UsageType;
    }


Done:
    
if (NT_SUCCESS(Status)) {
        
*pDumpStack = DumpStack;
    }
 else {
        IoFreeDumpStack (DumpStack);
    }

    ExFreePool (Buffer);
    
return Status;
}




NTSTATUS
IopLoadDumpDriver (
    IN OUT PDUMP_STACK_CONTEXT  DumpStack,
    IN PWCHAR DriverNameString,
    IN PWCHAR NewBaseNameString OPTIONAL
    )
/*++

Routine Description:

    Worker function for IoGetDumpStack to load a particular driver into
    the current DumpStack being created

Arguments:

    DumpStack           - Dump driver stack being built

    DriverNameString    - The string name of the driver to load

    NewBaseNameString   - The modified basename of the driver once loaded

Return Value:

    Status

--
*/

{
    NTSTATUS                Status;
    PDUMP_STACK_IMAGE       DumpImage;
    PLDR_DATA_TABLE_ENTRY   ImageLdrInfo;
    UNICODE_STRING          DriverName;
    UNICODE_STRING          BaseName;
    UNICODE_STRING          Prefix;
    PUNICODE_STRING         LoadBaseName;

    
//
    
// Allocate space to track this dump driver
    
//

    DumpImage 
= ExAllocatePoolWithTag (
                        NonPagedPool,
                        
sizeof (DUMP_STACK_IMAGE),
                        
'pmuD'
                        );

    
if (!DumpImage) {
        
return STATUS_INSUFFICIENT_RESOURCES;
    }


    
//
    
// Load the system image
    
//

    RtlInitUnicodeString (
&DriverName, DriverNameString);
    RtlInitUnicodeString (
&Prefix, DumpStack->ModulePrefix);
    LoadBaseName 
= NULL;
    
if (NewBaseNameString) {
        LoadBaseName 
= &BaseName;
        RtlInitUnicodeString (
&BaseName, NewBaseNameString);
        BaseName.MaximumLength 
= Prefix.Length + BaseName.Length;
        BaseName.Buffer 
= ExAllocatePoolWithTag (
                            NonPagedPool,
                            BaseName.MaximumLength,
                            
'pmuD'
                            );


        
if (!BaseName.Buffer) {
            ExFreePool (DumpImage);
            
return STATUS_INSUFFICIENT_RESOURCES;
        }


        BaseName.Length 
= 0;
        RtlAppendUnicodeStringToString (
&BaseName, &Prefix);
        RtlAppendUnicodeToString (
&BaseName, NewBaseNameString);
    }


    Status 
= MmLoadAndLockSystemImage(
                
&DriverName,
                
&Prefix,
                LoadBaseName,
                
&DumpImage->Image,
                
&DumpImage->ImageBase
                );

    
if (NewBaseNameString) {
        ExFreePool (BaseName.Buffer);
    }


    
if (!NT_SUCCESS (Status)) {
        IoDebugPrint ((
0,
                       
"IODUMP: Could not load %wZ; error = %x\n",
                       
&DriverName,
                       Status));
        ExFreePool (DumpImage);
        
return Status;
    }


    
//
    
// Put this driver on the list of drivers to be processed at crash time
    
//

    DumpImage
->SizeOfImage = DumpImage->Image->SizeOfImage;
    InsertTailList (
&DumpStack->DriverList, &DumpImage->Link);
    
return STATUS_SUCCESS;
}



ULONG
IopGetDumpControlBlockCheck (
    IN PDUMP_CONTROL_BLOCK  Dcb
    )
/*++

Routine Description:

    Return the current checksum total for the Dcb

Arguments:

    DumpStack           - Dump driver stack to checksum

Return Value:

    Checksum value

--
*/

{
    ULONG                   Check;
    PLIST_ENTRY             Link;
    PDUMP_STACK_IMAGE       DumpImage;
    PMAPPED_ADDRESS         MappedAddress;
    PDUMP_STACK_CONTEXT     DumpStack;


    
//
    
// Check the DCB, memory descriptor array, and the FileDescriptorArray
    
//

    Check 
= PoSimpleCheck(0, Dcb, sizeof(DUMP_CONTROL_BLOCK));
    Check 
= PoSimpleCheck(
                Check,
                Dcb
->MemoryDescriptor,
                Dcb
->MemoryDescriptorLength
                );

    Check 
= PoSimpleCheck(Check, Dcb->FileDescriptorArray, Dcb->FileDescriptorSize);

    DumpStack 
= Dcb->DumpStack;
    
if (DumpStack) {

        
//
        
// Include the dump stack context structure, and dump driver images
        
//

        Check 
= PoSimpleCheck(Check, DumpStack, sizeof(DUMP_STACK_CONTEXT));
        Check 
= PoSimpleCheck(Check, DumpStack->DumpPointers, DumpStack->PointersLength);

        
for (Link = DumpStack->DriverList.Flink;
             Link 
!= &DumpStack->DriverList;
             Link 
= Link->Flink) {

            DumpImage 
= CONTAINING_RECORD(Link, DUMP_STACK_IMAGE, Link);
            Check 
= PoSimpleCheck(Check, DumpImage, sizeof(DUMP_STACK_IMAGE));
            Check 
= PoSimpleCheck(Check, DumpImage->ImageBase, DumpImage->SizeOfImage);
        }


        
//
        
// Include the mapped addresses
        
//
        
// If this is non-null it is treated as a PMAPPED_ADDRESS * (see scsiport and atdisk)
        
//
        if (DumpStack->Init.MappedRegisterBase != NULL) {
            MappedAddress 
= *(PMAPPED_ADDRESS *)DumpStack->Init.MappedRegisterBase;
        }
 else {
            MappedAddress 
= NULL;
        }


        
while (MappedAddress) {
            Check 
= PoSimpleCheck (Check, MappedAddress, sizeof(MAPPED_ADDRESS));
            MappedAddress 
= MappedAddress->NextMappedAddress;
        }

    }


    
return Check;
}

posted on 2008-11-29 14:25 郝大个儿 阅读(491) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航:   博客园   博客园最新博文   博问   管理