test: dumpctl.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# dumpctl.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     dumpctl.c
    00008
    00009 Abstract:
    00010
    00011     This module contains the code to dump memory to disk after a crash.
    00012
    00013 Author:
    00014
    00015     Darryl E. Havens (darrylh) 17-dec-1993
    00016
    00017 Environment:
    00018
    00019     Kernel mode
    00020
    00021 Revision History:
    00022
    00023
    00024 --*/
    00025
    00026 #include "iop.h"
    00027 #include "ntddft.h"
    00028 #include <inbv.h>
    00029 #include <windef.h>
    00030
    00031 //
    00032 // Processor specific macros.
    00033 //
    00034
    00035 #if defined (i386)
    00036
    00037 #define PROGRAM_COUNTER(_context)   ((_context)->Eip)
    00038 #define STACK_POINTER(_context)     ((_context)->Esp)
    00039 #define CURRENT_IMAGE_TYPE()        IMAGE_FILE_MACHINE_I386
    00040 #define PaeEnabled() X86PaeEnabled()
    00041
    00042 #elif defined (ALPHA)
    00043
    00044 #define PROGRAM_COUNTER(_context)   ((_context)->Fir)
    00045 #define STACK_POINTER(_context)     ((_context)->IntSp)
    00046 #define CURRENT_IMAGE_TYPE()        IMAGE_FILE_MACHINE_ALPHA
    00047 #define PaeEnabled() (FALSE)
    00048
    00049 #elif defined (_IA64_)
    00050
    00051 #define PROGRAM_COUNTER(_context)   ((_context)->StIIP)
    00052 #define STACK_POINTER(_context)     ((_context)->IntSp)
    00053 #define CURRENT_IMAGE_TYPE()        IMAGE_FILE_MACHINE_IA64
    00054 #define PaeEnabled() (FALSE)
    00055
    00056 #else
    00057
    00058 #error ("unknown processor type")
    00059
    00060 #endif
    00061
    00062 //
    00063 // min3(_a,_b,_c)
    00064 //
    00065 // Same as min() but takes 3 parameters.
    00066 //
    00067
    00068 #define min3(_a,_b,_c) ( min ( min ((_a), (_b)), min ((_a), (_c))) )
    00069
    00070
    00071 //
    00072 // Global variables
    00073 //
    00074
    00075 extern PVOID MmPfnDatabase;
    00076 extern PFN_NUMBER MmHighestPossiblePhysicalPage;
    00077
    00078 NTSTATUS IopFinalCrashDumpStatus         = -1;
    00079 ULONG    IopCrashDumpStateChange         =  0;
    00080 BOOLEAN  IopDumpFileContainsNewDump      = FALSE;
    00081
    00082 //
    00083 // Max dump transfer sizes
    00084 //
    00085
    00086 #define IO_DUMP_MAXIMUM_TRANSFER_SIZE   ( 1024 * 64 )
    00087 #define IO_DUMP_MINIMUM_TRANSFER_SIZE   ( 1024 * 32 )
    00088 #define IO_DUMP_MINIMUM_FILE_SIZE       ( PAGE_SIZE * 256 )
    00089 #define MAX_UNICODE_LENGTH              ( 512 )
    00090
    00091 #define DEFAULT_DRIVER_PATH             L"\\SystemRoot\\System32\\Drivers\\"
    00092 #define DEFAULT_DUMP_DRIVER             L"\\SystemRoot\\System32\\Drivers\\diskdump.sys"
    00093 #define SCSIPORT_DRIVER_NAME            L"scsiport.sys"
    00094 #define MAX_TRIAGE_STACK_SIZE           ( 16 * 1024 )
    00095 #define DEFAULT_TRIAGE_DUMP_FLAGS (0xFFFFFFFF)
    00096
    00097
    00098 //
    00099 // Function prototypes
    00100 //
    00101
    00102
    00103 NTSTATUS
    00104 IopWriteTriageDump(
    00105     IN ULONG FieldsToWrite,
    00106     IN PDUMP_DRIVER_WRITE WriteRoutine,
    00107     IN OUT PLARGE_INTEGER Mcb,
    00108     IN OUT PMDL Mdl,
    00109     IN ULONG DiverTransferSize,
    00110     IN PCONTEXT Context,
    00111     IN LPBYTE Buffer,
    00112     IN ULONG BufferSize,
    00113     IN ULONG ServicePackBuild,
    00114     IN ULONG TriageOptions
    00115     );
    00116
    00117 NTSTATUS
    00118 IopWriteSummaryDump(
    00119     IN PRTL_BITMAP PageMap,
    00120     IN PDUMP_DRIVER_WRITE WriteRoutine,
    00121     IN PANSI_STRING ProgressMessage,
    00122     IN PUCHAR MessageBuffer,
    00123     IN OUT PLARGE_INTEGER Mcb,
    00124     IN ULONG DiverTransferSize
    00125     );
    00126
    00127 NTSTATUS
    00128 IopWriteToDisk(
    00129     IN PVOID Buffer,
    00130     IN ULONG WriteLength,
    00131     IN PDUMP_DRIVER_WRITE DriverWriteRoutine,
    00132     IN OUT PLARGE_INTEGER * Mcb,
    00133     IN OUT PMDL Mdl,
    00134     IN ULONG DriverTransferSize
    00135     );
    00136
    00137 VOID
    00138 IopMapPhysicalMemory(
    00139     IN OUT PMDL Mdl,
    00140     IN ULONG_PTR MemoryAddress,
    00141     IN PPHYSICAL_MEMORY_RUN PhysicalMemoryRun,
    00142     IN ULONG Length
    00143     );
    00144
    00145 NTSTATUS
    00146 IopLoadDumpDriver (
    00147     IN OUT PDUMP_STACK_CONTEXT  DumpStack,
    00148     IN PWCHAR DriverNameString,
    00149     IN PWCHAR NewBaseNameString
    00150     );
    00151
    00152 NTSTATUS
    00153 IoSetCrashDumpState(
    00154     IN SYSTEM_CRASH_STATE_INFORMATION *pDumpState
    00155     );
    00156
    00157 PSUMMARY_DUMP_HEADER
    00158 IopInitializeSummaryDump(
    00159     IN PDUMP_CONTROL_BLOCK pDcb
    00160     );
    00161
    00162 NTSTATUS
    00163 IopWriteSummaryHeader(
    00164     IN PSUMMARY_DUMP_HEADER    pSummaryHeader,
    00165     IN PDUMP_DRIVER_WRITE      pfWrite,
    00166     IN OUT PLARGE_INTEGER *    pMcbBuffer,
    00167     IN OUT PMDL                pMdl,
    00168     IN ULONG                   dwWriteSize,
    00169     IN ULONG                   dwLength
    00170     );
    00171
    00172 VOID
    00173 IopMapVirtualToPhysicalMdl(
    00174     IN OUT PMDL pMdl,
    00175     IN ULONG_PTR dwMemoryAddress,
    00176     IN ULONG    dwLength
    00177     );
    00178
    00179 ULONG
    00180 IopCreateSummaryDump (
    00181     IN PSUMMARY_DUMP_HEADER pHeader
    00182     );
    00183
    00184 VOID
    00185 IopDeleteNonExistentMemory(
    00186     PSUMMARY_DUMP_HEADER        pHeader,
    00187     PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
    00188     );
    00189
    00190
    00191 NTSTATUS
    00192 IopGetDumpStack (
    00193     IN PWCHAR                         ModulePrefix,
    00194     OUT PDUMP_STACK_CONTEXT           *pDumpStack,
    00195     IN PUNICODE_STRING                pUniDeviceName,
    00196     IN PWSTR                          pDumpDriverName,
    00197     IN DEVICE_USAGE_NOTIFICATION_TYPE UsageType,
    00198     IN ULONG                          IgnoreDeviceUsageFailure
    00199     );
    00200
    00201 BOOLEAN
    00202 IopInitializeDCB(
    00203     );
    00204
    00205 LARGE_INTEGER
    00206 IopCalculateRequiredDumpSpace(
    00207     IN ULONG            dwDmpFlags,
    00208     IN ULONG            dwHeaderSize,
    00209     IN PFN_NUMBER       dwMaxPages,
    00210     IN PFN_NUMBER       dwMaxSummaryPages
    00211     );
    00212
    00213 NTSTATUS
    00214 IopCompleteDumpInitialization(
    00215     IN HANDLE     FileHandle
    00216     );
    00217
    00218 #if DBG
    00219
    00220 VOID
    00221 IopDebugPrint(
    00222     ULONG  DebugPrintLevel,
    00223     PCCHAR DebugMessage,
    00224     ...
    00225     );
    00226
    00227 #define IoDebugPrint(X) IopDebugPrint X
    00228
    00229 #else
    00230
    00231 #define IoDebugPrint(X)
    00232
    00233 #endif //DBG
    00234
    00235
    00236 #ifdef ALLOC_PRAGMA
    00237 #pragma alloc_text(PAGE,IoGetDumpStack)
    00238 #pragma alloc_text(PAGE,IopLoadDumpDriver)
    00239 #pragma alloc_text(PAGE,IoFreeDumpStack)
    00240 #pragma alloc_text(PAGE,IoGetCrashDumpInformation)
    00241 #pragma alloc_text(PAGE,IoGetCrashDumpStateInformation)
    00242 #pragma alloc_text(PAGE,IoSetCrashDumpState)
    00243 #endif
    00244
    00245
    00246 #if defined (i386)
    00247
    00248 //
    00249 // Functions
    00250 //
    00251
    00252
    00253 BOOL
    00254 X86PaeEnabled(
    00255     )
    00256
    00257 /*++
    00258
    00259 Routine Description:
    00260
    00261     Is PAE currently enabled?
    00262
    00263 Return Values:
    00264
    00265     Return TRUE if PAE is enabled in the CR4 register, FALSE otherwise.
    00266
    00267 --*/
    00268
    00269 {
    00270     ULONG Reg_Cr4;
    00271
    00272     _asm {
    00273         _emit 0Fh
    00274         _emit 20h
    00275         _emit 0E0h  ;; mov eax, cr4
    00276         mov Reg_Cr4, eax
    00277     }
    00278
    00279     return (Reg_Cr4 & CR4_PAE ? TRUE : FALSE);
    00280 }
    00281
    00282 #endif
    00283
    00284
    00285
    00286 BOOLEAN
    00287 IopIsAddressRangeValid(
    00288     IN PVOID VirtualAddress,
    00289     IN SIZE_T Length
    00290     )
    00291
    00292 /*++
    00293
    00294 Routine Description:
    00295
    00296     Validate a range of addresses.
    00297
    00298 Arguments:
    00299
    00300     Virtual Address - Beginning of of memory block to validate.
    00301
    00302     Length - Length of memory block to validate.
    00303
    00304 Return Value:
    00305
    00306     TRUE - Address range is valid.
    00307
    00308     FALSE - Address range is not valid.
    00309
    00310 --*/
    00311
    00312 {
    00313     UINT_PTR Va;
    00314     ULONG Pages;
    00315
    00316     Va = (UINT_PTR) PAGE_ALIGN (VirtualAddress);
    00317     Pages = COMPUTE_PAGES_SPANNED (VirtualAddress, Length);
    00318
    00319     while (Pages) {
    00320
    00321         if (!MmIsAddressValid ( (LPVOID) Va)) {
    00322             return FALSE;
    00323         }
    00324
    00325         Va += PAGE_SIZE;
    00326         Pages--;
    00327     }
    00328
    00329     return TRUE;
    00330 }
    00331
    00332
    00333
    00334 NTSTATUS
    00335 IoGetDumpStack (
    00336     IN PWCHAR                          ModulePrefix,
    00337     OUT PDUMP_STACK_CONTEXT          * pDumpStack,
    00338     IN  DEVICE_USAGE_NOTIFICATION_TYPE UsageType,
    00339     IN  ULONG                          IgnoreDeviceUsageFailure
    00340     )
    00341 /*++
    00342
    00343 Routine Description:
    00344
    00345     This routine loads a dump stack instance and returns an allocated
    00346     context structure to track the loaded dumps stack.
    00347
    00348 Arguments:
    00349
    00350     ModePrefix      - The prefix to prepent to BaseName during the load
    00351                       operation.  This allows loading the same drivers
    00352                       multiple times with different virtual names and
    00353                       linkages.
    00354
    00355     pDumpStack      - The returned dump stack context structure
    00356
    00357     UsageType       - The Device Notification Usage Type for this file, that
    00358                       this routine will send as to the device object once the
    00359                       file has been successfully created and initialized.
    00360
    00361     IgnoreDeviceUsageFailure - If the Device Usage Notification Irp fails, allow
    00362                       this to succeed anyway.
    00363
    00364 Return Value:
    00365
    00366     Status
    00367
    00368 --*/
    00369 {
    00370
    00371     PAGED_CODE();
    00372     return IopGetDumpStack(ModulePrefix,
    00373                            pDumpStack,
    00374                            &IoArcBootDeviceName,
    00375                            DEFAULT_DUMP_DRIVER,
    00376                            UsageType,
    00377                            IgnoreDeviceUsageFailure
    00378                            );
    00379 }
    00380
    00381
    00382
    00383 NTSTATUS
    00384 IopGetDumpStack (
    00385     IN PWCHAR                         ModulePrefix,
    00386     OUT PDUMP_STACK_CONTEXT         * pDumpStack,
    00387     IN PUNICODE_STRING                pUniDeviceName,
    00388     IN PWCHAR                         pDumpDriverName,
    00389     IN DEVICE_USAGE_NOTIFICATION_TYPE UsageType,
    00390     IN ULONG                          IgnoreDeviceUsageFailure
    00391     )
    00392 /*++
    00393
    00394 Routine Description:
    00395
    00396     This routine loads a dump stack instance and returns an allocated
    00397     context structure to track the loaded dumps stack.
    00398
    00399 Arguments:
    00400
    00401     ModePrefix      - The prefix to prepent to BaseName during the load
    00402                       operation.  This allows loading the same drivers
    00403                       multiple times with different virtual names and
    00404                       linkages.
    00405
    00406     pDumpStack      - The returned dump stack context structure
    00407
    00408     pDeviceName     - The name of the target dump device
    00409
    00410     pDumpDriverName - The name of the target dump driver
    00411
    00412     UsageType       - The Device Notification Usage Type for this file, that
    00413                       this routine will send as to the device object once the
    00414                       file has been successfully created and initialized.
    00415
    00416     IgnoreDeviceUsageFailure - If the Device Usage Notification Irp fails, allow
    00417                       this to succeed anyway.
    00418
    00419 Return Value:
    00420
    00421     Status
    00422
    00423 --*/
    00424 {
    00425     PDUMP_STACK_CONTEXT         DumpStack;
    00426     PUCHAR                      Buffer;
    00427     PUCHAR                      PartitionName;
    00428     ANSI_STRING                 AnsiString;
    00429     UNICODE_STRING              TempName;
    00430     OBJECT_ATTRIBUTES           ObjectAttributes;
    00431     NTSTATUS                    Status;
    00432     HANDLE                      DeviceHandle;
    00433     SCSI_ADDRESS                ScsiAddress;
    00434     BOOLEAN                     ScsiDump;
    00435     PARTITION_INFORMATION       PartitionInfo;
    00436     PFILE_OBJECT                FileObject;
    00437     PDEVICE_OBJECT              DeviceObject;
    00438     PINITIALIZATION_CONTEXT     DumpInit;
    00439     PDUMP_POINTERS              DumpPointers;
    00440     UNICODE_STRING              DriverName;
    00441     PDRIVER_OBJECT              DriverObject;
    00442     PIRP                        Irp;
    00443     PIO_STACK_LOCATION          IrpSp;
    00444     IO_STATUS_BLOCK             IoStatus;
    00445     PWCHAR                      DumpName, NameOffset;
    00446     KEVENT                      Event;
    00447     PVOID                       p1;
    00448     PHYSICAL_ADDRESS            pa;
    00449     ULONG                       i;
    00450     IO_STACK_LOCATION           irpSp;
    00451     ULONG                       information;
    00452
    00453     IoDebugPrint((2,"IopGetDumpStack: Prefix:%ws stk: %x device:%ws driver:%ws\n",
    00454                 ModulePrefix, pDumpStack, pUniDeviceName->Buffer,pDumpDriverName));
    00455
    00456     ASSERT (DeviceUsageTypeUndefined != UsageType);
    00457
    00458     DumpStack = ExAllocatePoolWithTag (
    00459                     NonPagedPool,
    00460                     sizeof (DUMP_STACK_CONTEXT) + sizeof (DUMP_POINTERS),
    00461                     'pmuD'
    00462                     );
    00463
    00464     if (!DumpStack) {
    00465         return STATUS_INSUFFICIENT_RESOURCES;
    00466     }
    00467
    00468     RtlZeroMemory(DumpStack, sizeof(DUMP_STACK_CONTEXT)+sizeof(DUMP_POINTERS));
    00469     DumpInit = &DumpStack->Init;
    00470     DumpPointers = (PDUMP_POINTERS) (DumpStack + 1);
    00471     DumpStack->DumpPointers = DumpPointers;
    00472     InitializeListHead (&DumpStack->DriverList);
    00473     DumpName = NULL;
    00474
    00475     //
    00476     // Allocate scratch buffer
    00477     //
    00478
    00479     Buffer = ExAllocatePoolWithTag (PagedPool, PAGE_SIZE, 'pmuD');
    00480     if (!Buffer) {
    00481         ExFreePool (DumpStack);
    00482         return STATUS_INSUFFICIENT_RESOURCES;
    00483     }
    00484
    00485     if (!KeGetBugMessageText(BUGCODE_PSS_CRASH_INIT, &DumpStack->InitMsg) ||
    00486         !KeGetBugMessageText(BUGCODE_PSS_CRASH_PROGRESS, &DumpStack->ProgMsg) ||
    00487         !KeGetBugMessageText(BUGCODE_PSS_CRASH_DONE, &DumpStack->DoneMsg)) {
    00488             Status = STATUS_UNSUCCESSFUL;
    00489             goto Done;
    00490     }
    00491
    00492     InitializeObjectAttributes(
    00493         &ObjectAttributes,
    00494         pUniDeviceName,
    00495         0,
    00496         NULL,
    00497         NULL
    00498         );
    00499
    00500     Status = ZwOpenFile(
    00501               &DeviceHandle,
    00502               FILE_READ_DATA | SYNCHRONIZE,
    00503               &ObjectAttributes,
    00504               &IoStatus,
    00505               FILE_SHARE_READ | FILE_SHARE_WRITE,
    00506               FILE_NON_DIRECTORY_FILE
    00507               );
    00508
    00509     if (!NT_SUCCESS(Status)) {
    00510         IoDebugPrint ((0,
    00511                        "IODUMP: Could not open boot device partition, %s\n",
    00512                        Buffer
    00513                        ));
    00514         goto Done;
    00515     }
    00516
    00517     //
    00518     // Check to see whether or not the system was booted from a SCSI device.
    00519     //
    00520
    00521     Status = ZwDeviceIoControlFile (
    00522                     DeviceHandle,
    00523                     NULL,
    00524                     NULL,
    00525                     NULL,
    00526                     &IoStatus,
    00527                     IOCTL_SCSI_GET_ADDRESS,
    00528                     NULL,
    00529                     0,
    00530                     &ScsiAddress,
    00531                     sizeof( SCSI_ADDRESS )
    00532                     );
    00533
    00534     if (Status == STATUS_PENDING) {
    00535         ZwWaitForSingleObject (
    00536             DeviceHandle,
    00537             FALSE,
    00538             NULL
    00539             );
    00540
    00541         Status = IoStatus.Status;
    00542     }
    00543
    00544     ScsiDump = (BOOLEAN) (NT_SUCCESS(Status));
    00545
    00546     //
    00547     // If SCSI then allocate storage to contain the target address information.
    00548     //
    00549
    00550     DumpInit->TargetAddress = NULL;
    00551
    00552     if (ScsiDump) {
    00553
    00554         DumpInit->TargetAddress = ExAllocatePoolWithTag (
    00555                                     NonPagedPool,
    00556                                     sizeof (SCSI_ADDRESS),
    00557                                     'pmuD'
    00558                                     );
    00559         //
    00560         // It is ok If the allocation fails. The scsi dump driver will scan
    00561         // all devices if the targetaddress information does not exist
    00562         //
    00563
    00564         if (DumpInit->TargetAddress) {
    00565             RtlCopyMemory(DumpInit->TargetAddress,&ScsiAddress,sizeof(SCSI_ADDRESS));
    00566         }
    00567     }
    00568
    00569     //
    00570     // Determine the disk signature for the device from which the system was
    00571     // booted and get the partition offset.
    00572     //
    00573
    00574     Status = ZwDeviceIoControlFile(
    00575                     DeviceHandle,
    00576                     NULL,
    00577                     NULL,
    00578                     NULL,
    00579                     &IoStatus,
    00580                     IOCTL_DISK_GET_PARTITION_INFO,
    00581                     NULL,
    00582                     0,
    00583                     &PartitionInfo,
    00584                     sizeof( PARTITION_INFORMATION )
    00585                     );
    00586
    00587     if (Status == STATUS_PENDING) {
    00588         ZwWaitForSingleObject (
    00589             DeviceHandle,
    00590             FALSE,
    00591             NULL
    00592             );
    00593
    00594         Status = IoStatus.Status;
    00595     }
    00596
    00597     IoDebugPrint((2,"Partition Type = %x\n",PartitionInfo.PartitionType));
    00598     IoDebugPrint((2,"Boot Indicator = %x\n",PartitionInfo.BootIndicator));
    00599
    00600     Status = ZwDeviceIoControlFile(
    00601                     DeviceHandle,
    00602                     NULL,
    00603                     NULL,
    00604                     NULL,
    00605                     &IoStatus,
    00606                     IOCTL_DISK_GET_DRIVE_LAYOUT,
    00607                     NULL,
    00608                     0,
    00609                     Buffer,
    00610                     PAGE_SIZE
    00611                     );
    00612
    00613     if (Status == STATUS_PENDING) {
    00614         ZwWaitForSingleObject (
    00615             DeviceHandle,
    00616             FALSE,
    00617             NULL
    00618             );
    00619
    00620         Status = IoStatus.Status;
    00621     }
    00622
    00623     DumpInit->DiskSignature = ((PDRIVE_LAYOUT_INFORMATION) Buffer)->Signature;
    00624
    00625     //
    00626     // Get the adapter object and base mapping registers for the disk from
    00627     // the disk driver.  These will be used to call the HAL once the system
    00628     // system has crashed, since it is not possible at that point to recreate
    00629     // them from scratch.
    00630     //
    00631
    00632     ObReferenceObjectByHandle (
    00633             DeviceHandle,
    00634             0,
    00635             IoFileObjectType,
    00636             KernelMode,
    00637             (PVOID *) &FileObject,
    00638             NULL
    00639             );
    00640
    00641
    00642     DeviceObject = IoGetRelatedDeviceObject (FileObject);
    00643
    00644     KeInitializeEvent( &Event, NotificationEvent, FALSE );
    00645
    00646     Irp = IoBuildDeviceIoControlRequest(
    00647                 IOCTL_SCSI_GET_DUMP_POINTERS,
    00648                 DeviceObject,
    00649                 NULL,
    00650                 0,
    00651                 DumpPointers,
    00652                 sizeof (DUMP_POINTERS),
    00653                 FALSE,
    00654                 &Event,
    00655                 &IoStatus
    00656                 );
    00657
    00658     if (!Irp) {
    00659         ObDereferenceObject (FileObject);
    00660         ZwClose (DeviceHandle);
    00661         Status = STATUS_INSUFFICIENT_RESOURCES;
    00662         goto Done;
    00663     }
    00664
    00665     IrpSp = IoGetNextIrpStackLocation (Irp);
    00666
    00667     IrpSp->FileObject = FileObject;
    00668
    00669     Status = IoCallDriver( DeviceObject, Irp );
    00670
    00671     if (Status == STATUS_PENDING) {
    00672         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
    00673         Status = IoStatus.Status;
    00674     }
    00675
    00676     if (!NT_SUCCESS(Status)  ||  IoStatus.Information < FIELD_OFFSET(DUMP_POINTERS, DeviceObject)) {
    00677
    00678         IoDebugPrint ((0,
    00679                        "IODUMP: Could not get dump pointers; error = %x, length %x\n",
    00680                         Status,
    00681                         IoStatus.Information
    00682                         ));
    00683         ObDereferenceObject (FileObject);
    00684 //      NtClose (DeviceHandle);
    00685         ZwClose (DeviceHandle);
    00686         goto Done;
    00687     }
    00688     DumpStack->PointersLength = (ULONG) IoStatus.Information;
    00689
    00690     //
    00691     // If the driver returned a pointer to a device object, that is the
    00692     // object for the dump driver  (non-scsi case)
    00693     //
    00694
    00695     DeviceObject = (PDEVICE_OBJECT) DumpPointers->DeviceObject;
    00696     if (DeviceObject) {
    00697         DriverObject = DeviceObject->DriverObject;
    00698
    00699         //
    00700         // Loop through the name of the driver looking for the end of the name,
    00701         // which is the name of the dump image.
    00702         //
    00703
    00704         DumpName = DriverObject->DriverName.Buffer;
    00705         while ( NameOffset = wcsstr( DumpName, L"\\" )) {
    00706             DumpName = ++NameOffset;
    00707         }
    00708
    00709         ScsiDump = FALSE;
    00710     }
    00711
    00712     //
    00713     // Release the handle, but keep the reference to the file object as it
    00714     // will be needed at free dump dump driver time
    00715     //
    00716
    00717     DumpStack->FileObject = FileObject;
    00718     ZwClose (DeviceHandle);
    00719
    00720     //
    00721     // Fill in some DumpInit results
    00722     //
    00723
    00724     DumpInit->Length             = sizeof (INITIALIZATION_CONTEXT);
    00725     DumpInit->StallRoutine       = &KeStallExecutionProcessor;
    00726     DumpInit->AdapterObject      = DumpPointers->AdapterObject;
    00727     DumpInit->MappedRegisterBase = DumpPointers->MappedRegisterBase;
    00728     DumpInit->PortConfiguration  = DumpPointers->DumpData;
    00729
    00730     DumpStack->ModulePrefix      = ModulePrefix;
    00731     DumpStack->PartitionOffset   = PartitionInfo.StartingOffset;
    00732     DumpStack->UsageType         = DeviceUsageTypeUndefined;
    00733
    00734     //
    00735     // The minimum common buffer size is IO_DUMP_COMMON_BUFFER_SIZE (compatability)
    00736     // This is used by the dump driver for SRB extension, CachedExtension, and sense buffer
    00737     //
    00738     if (DumpPointers->CommonBufferSize < IO_DUMP_COMMON_BUFFER_SIZE) {
    00739         DumpPointers->CommonBufferSize = IO_DUMP_COMMON_BUFFER_SIZE;
    00740     }
    00741     DumpInit->CommonBufferSize    = DumpPointers->CommonBufferSize;
    00742
    00743     //
    00744     // Allocate the required common buffers
    00745     //
    00746
    00747     if (DumpPointers->AllocateCommonBuffers) {
    00748         pa.QuadPart = 0x1000000 - 1;
    00749         for (i=0; i < 2; i++) {
    00750             if (DumpInit->AdapterObject) {
    00751
    00752 #if !defined(NO_LEGACY_DRIVERS)
    00753                 p1 = HalAllocateCommonBuffer(
    00754                     DumpInit->AdapterObject,
    00755                     DumpPointers->CommonBufferSize,
    00756                     &pa,
    00757                     FALSE
    00758                     );
    00759
    00760 #else
    00761                 p1 = (*((PDMA_ADAPTER)DumpInit->AdapterObject)->DmaOperations->
    00762                       AllocateCommonBuffer)(
    00763                           (PDMA_ADAPTER)DumpInit->AdapterObject,
    00764                           DumpPointers->CommonBufferSize,
    00765                           &pa,
    00766                           FALSE
    00767                           );
    00768
    00769 #endif // NO_LEGACY_DRIVERS
    00770
    00771             } else {
    00772                 p1 = MmAllocateContiguousMemory (
    00773                         DumpPointers->CommonBufferSize,
    00774                         pa
    00775                         );
    00776
    00777                 if (!p1) {
    00778                     p1 = MmAllocateNonCachedMemory (DumpPointers->CommonBufferSize);
    00779                 }
    00780                 pa = MmGetPhysicalAddress(p1);
    00781             }
    00782
    00783             if (!p1) {
    00784                 IoDebugPrint ((0, "IODUMP: Could not allocate common buffers for dump\n"));
    00785                 Status = STATUS_INSUFFICIENT_RESOURCES;
    00786                 goto Done;
    00787             }
    00788
    00789             DumpInit->CommonBuffer[i] = p1;
    00790             DumpInit->PhysicalAddress[i] = pa;
    00791         }
    00792     }
    00793
    00794     //
    00795     // Determine whether or not the system booted from SCSI.
    00796     //
    00797
    00798     if (ScsiDump) {
    00799
    00800         //
    00801         // Load the boot disk and port driver to be used by the various
    00802         // miniports for writing memory to the disk.
    00803         //
    00804
    00805         Status = IopLoadDumpDriver (
    00806                         DumpStack,
    00807                         pDumpDriverName,
    00808                         SCSIPORT_DRIVER_NAME
    00809                         );
    00810
    00811         if (!NT_SUCCESS(Status)) {
    00812
    00813             IopLogErrorEvent(0,9,STATUS_SUCCESS,IO_DUMP_DRIVER_LOAD_FAILURE,0,NULL,0,NULL);
    00814             goto Done;
    00815         }
    00816
    00817         //
    00818         // The disk and port dump driver has been loaded.  Load the appropriate
    00819         // miniport driver as well so that the boot device can be accessed.
    00820         //
    00821
    00822         DriverName.Length = 0;
    00823         DriverName.Buffer = (PVOID) Buffer;
    00824         DriverName.MaximumLength = PAGE_SIZE;
    00825
    00826
    00827         //
    00828         // The system was booted from SCSI. Get the name of the appropriate
    00829         // miniport driver and load it.
    00830         //
    00831
    00832         sprintf(Buffer, "\\Device\\ScsiPort%d", ScsiAddress.PortNumber );
    00833         RtlInitAnsiString( &AnsiString, Buffer );
    00834         RtlAnsiStringToUnicodeString( &TempName, &AnsiString, TRUE );
    00835         InitializeObjectAttributes(
    00836                     &ObjectAttributes,
    00837                     &TempName,
    00838                     0,
    00839                     NULL,
    00840                     NULL
    00841                     );
    00842
    00843         Status = ZwOpenFile(
    00844                     &DeviceHandle,
    00845                     FILE_READ_ATTRIBUTES,
    00846                     &ObjectAttributes,
    00847                     &IoStatus,
    00848                     FILE_SHARE_READ | FILE_SHARE_WRITE,
    00849                     FILE_NON_DIRECTORY_FILE
    00850                     );
    00851
    00852         RtlFreeUnicodeString( &TempName );
    00853         if (!NT_SUCCESS( Status )) {
    00854             IoDebugPrint ((0,
    00855                            "IODUMP: Could not open SCSI port %d, error = %x\n",
    00856                            ScsiAddress.PortNumber,
    00857                            Status
    00858                            ));
    00859             goto Done;
    00860         }
    00861
    00862         //
    00863         // Convert the file handle into a pointer to the device object, and
    00864         // get the name of the driver from its driver object.
    00865         //
    00866
    00867         ObReferenceObjectByHandle(
    00868                     DeviceHandle,
    00869                     0,
    00870                     IoFileObjectType,
    00871                     KernelMode,
    00872                     (PVOID *) &FileObject,
    00873                     NULL
    00874                     );
    00875
    00876         DriverObject = FileObject->DeviceObject->DriverObject;
    00877         ObDereferenceObject( FileObject );
    00878         ZwClose( DeviceHandle );
    00879         //
    00880         // Loop through the name of the driver looking for the end of the name,
    00881         // which is the name of the miniport image.
    00882         //
    00883
    00884         DumpName = DriverObject->DriverName.Buffer;
    00885         while ( NameOffset = wcsstr( DumpName, L"\\" )) {
    00886             DumpName = ++NameOffset;
    00887         }
    00888     }
    00889
    00890     //
    00891     // Load the dump driver
    00892     //
    00893
    00894     if (!DumpName) {
    00895         Status = STATUS_NOT_SUPPORTED;
    00896         goto Done;
    00897     }
    00898
    00899     swprintf ((PWCHAR) Buffer, L"\\SystemRoot\\System32\\Drivers\\%s.sys", DumpName);
    00900     Status = IopLoadDumpDriver (
    00901                     DumpStack,
    00902                     (PWCHAR) Buffer,
    00903                     NULL
    00904                     );
    00905     if (!NT_SUCCESS(Status)) {
    00906
    00907         IopLogErrorEvent(0,10,STATUS_SUCCESS,IO_DUMP_DRIVER_LOAD_FAILURE,0,NULL,0,NULL);
    00908         goto Done;
    00909     }
    00910
    00911     //
    00912     // Claim the file as part of specific device usage path.
    00913     //
    00914
    00915     FileObject = DumpStack->FileObject;
    00916     DeviceObject = IoGetRelatedDeviceObject (FileObject);
    00917
    00918     RtlZeroMemory (&irpSp, sizeof (IO_STACK_LOCATION));
    00919
    00920     irpSp.MajorFunction = IRP_MJ_PNP;
    00921     irpSp.MinorFunction = IRP_MN_DEVICE_USAGE_NOTIFICATION;
    00922     irpSp.Parameters.UsageNotification.Type = UsageType;
    00923     irpSp.Parameters.UsageNotification.InPath = TRUE;
    00924     irpSp.FileObject = FileObject;
    00925
    00926     Status = IopSynchronousCall (DeviceObject, &irpSp, (VOID **) &information);
    00927     ASSERT (0 == information);
    00928
    00929     if (!NT_SUCCESS(Status) && IgnoreDeviceUsageFailure) {
    00930         IoDebugPrint ((0,
    00931                        "IopGetDumpStack: DEVICE_USAGE_NOTIFICATION "
    00932                        "Error ignored (%x)\n",
    00933                        Status));
    00934         Status = STATUS_SUCCESS;
    00935     }
    00936
    00937     if (NT_SUCCESS(Status)) {
    00938         DumpStack->UsageType         = UsageType;
    00939     }
    00940
    00941 Done:
    00942     if (NT_SUCCESS(Status)) {
    00943         *pDumpStack = DumpStack;
    00944     } else {
    00945         IoFreeDumpStack (DumpStack);
    00946     }
    00947     ExFreePool (Buffer);
    00948     return Status;
    00949 }
    00950
    00951
    00952
    00953 NTSTATUS
    00954 IopLoadDumpDriver (
    00955     IN OUT PDUMP_STACK_CONTEXT  DumpStack,
    00956     IN PWCHAR DriverNameString,
    00957     IN PWCHAR NewBaseNameString OPTIONAL
    00958     )
    00959 /*++
    00960
    00961 Routine Description:
    00962
    00963     Worker function for IoGetDumpStack to load a particular driver into
    00964     the current DumpStack being created
    00965
    00966 Arguments:
    00967
    00968     DumpStack           - Dump driver stack being built
    00969
    00970     DriverNameString    - The string name of the driver to load
    00971
    00972     NewBaseNameString   - The modified basename of the driver once loaded
    00973
    00974 Return Value:
    00975
    00976     Status
    00977
    00978 --*/
    00979 {
    00980     NTSTATUS                Status;
    00981     PDUMP_STACK_IMAGE       DumpImage;
    00982     PLDR_DATA_TABLE_ENTRY   ImageLdrInfo;
    00983     UNICODE_STRING          DriverName;
    00984     UNICODE_STRING          BaseName;
    00985     UNICODE_STRING          Prefix;
    00986     PUNICODE_STRING         LoadBaseName;
    00987
    00988     //
    00989     // Allocate space to track this dump driver
    00990     //
    00991
    00992     DumpImage = ExAllocatePoolWithTag (
    00993                         NonPagedPool,
    00994                         sizeof (DUMP_STACK_IMAGE),
    00995                         'pmuD'
    00996                         );
    00997
    00998     if (!DumpImage) {
    00999         return STATUS_INSUFFICIENT_RESOURCES;
    01000     }
    01001
    01002     //
    01003     // Load the system image
    01004     //
    01005
    01006     RtlInitUnicodeString (&DriverName, DriverNameString);
    01007     RtlInitUnicodeString (&Prefix, DumpStack->ModulePrefix);
    01008     LoadBaseName = NULL;
    01009     if (NewBaseNameString) {
    01010         LoadBaseName = &BaseName;
    01011         RtlInitUnicodeString (&BaseName, NewBaseNameString);
    01012         BaseName.MaximumLength = Prefix.Length + BaseName.Length;
    01013         BaseName.Buffer = ExAllocatePoolWithTag (
    01014                             NonPagedPool,
    01015                             BaseName.MaximumLength,
    01016                             'pmuD'
    01017                             );
    01018
    01019
    01020         if (!BaseName.Buffer) {
    01021             ExFreePool (DumpImage);
    01022             return STATUS_INSUFFICIENT_RESOURCES;
    01023         }
    01024
    01025         BaseName.Length = 0;
    01026         RtlAppendUnicodeStringToString (&BaseName, &Prefix);
    01027         RtlAppendUnicodeToString (&BaseName, NewBaseNameString);
    01028     }
    01029
    01030     Status = MmLoadAndLockSystemImage(
    01031                 &DriverName,
    01032                 &Prefix,
    01033                 LoadBaseName,
    01034                 &DumpImage->Image,
    01035                 &DumpImage->ImageBase
    01036                 );
    01037
    01038     if (NewBaseNameString) {
    01039         ExFreePool (BaseName.Buffer);
    01040     }
    01041
    01042     if (!NT_SUCCESS (Status)) {
    01043         IoDebugPrint ((0,
    01044                        "IODUMP: Could not load %wZ; error = %x\n",
    01045                        &DriverName,
    01046                        Status));
    01047         ExFreePool (DumpImage);
    01048         return Status;
    01049     }
    01050
    01051     //
    01052     // Put this driver on the list of drivers to be processed at crash time
    01053     //
    01054
    01055     DumpImage->SizeOfImage = DumpImage->Image->SizeOfImage;
    01056     InsertTailList (&DumpStack->DriverList, &DumpImage->Link);
    01057     return STATUS_SUCCESS;
    01058 }
    01059
    01060
    01061 ULONG
    01062 IopGetDumpControlBlockCheck (
    01063     IN PDUMP_CONTROL_BLOCK  Dcb
    01064     )
    01065 /*++
    01066
    01067 Routine Description:
    01068
    01069     Return the current checksum total for the Dcb
    01070
    01071 Arguments:
    01072
    01073     DumpStack           - Dump driver stack to checksum
    01074
    01075 Return Value:
    01076
    01077     Checksum value
    01078
    01079 --*/
    01080 {
    01081     ULONG                   Check;
    01082     PLIST_ENTRY             Link;
    01083     PDUMP_STACK_IMAGE       DumpImage;
    01084     PMAPPED_ADDRESS         MappedAddress;
    01085     PDUMP_STACK_CONTEXT     DumpStack;
    01086
    01087
    01088     //
    01089     // Check the DCB, memory descriptor array, and the FileDescriptorArray
    01090     //
    01091
    01092     Check = PoSimpleCheck(0, Dcb, sizeof(DUMP_CONTROL_BLOCK));
    01093     Check = PoSimpleCheck(
    01094                 Check,
    01095                 Dcb->MemoryDescriptor,
    01096                 Dcb->MemoryDescriptorLength
    01097                 );
    01098
    01099     Check = PoSimpleCheck(Check, Dcb->FileDescriptorArray, Dcb->FileDescriptorSize);
    01100
    01101     DumpStack = Dcb->DumpStack;
    01102     if (DumpStack) {
    01103
    01104         //
    01105         // Include the dump stack context structure, and dump driver images
    01106         //
    01107
    01108         Check = PoSimpleCheck(Check, DumpStack, sizeof(DUMP_STACK_CONTEXT));
    01109         Check = PoSimpleCheck(Check, DumpStack->DumpPointers, DumpStack->PointersLength);
    01110
    01111         for (Link = DumpStack->DriverList.Flink;
    01112              Link != &DumpStack->DriverList;
    01113              Link = Link->Flink) {
    01114
    01115             DumpImage = CONTAINING_RECORD(Link, DUMP_STACK_IMAGE, Link);
    01116             Check = PoSimpleCheck(Check, DumpImage, sizeof(DUMP_STACK_IMAGE));
    01117             Check = PoSimpleCheck(Check, DumpImage->ImageBase, DumpImage->SizeOfImage);
    01118         }
    01119
    01120         //
    01121         // Include the mapped addresses
    01122         //
    01123         // If this is non-null it is treated as a PMAPPED_ADDRESS * (see scsiport and atdisk)
    01124         //
    01125         if (DumpStack->Init.MappedRegisterBase != NULL) {
    01126             MappedAddress = *(PMAPPED_ADDRESS *)DumpStack->Init.MappedRegisterBase;
    01127         } else {
    01128             MappedAddress = NULL;
    01129         }
    01130
    01131         while (MappedAddress) {
    01132             Check = PoSimpleCheck (Check, MappedAddress, sizeof(MAPPED_ADDRESS));
    01133             MappedAddress = MappedAddress->NextMappedAddress;
    01134         }
    01135     }
    01136
    01137     return Check;
    01138 }
    01139
    01140
    01141 NTSTATUS
    01142 IoInitializeDumpStack (
    01143     IN PDUMP_STACK_CONTEXT  DumpStack,
    01144     IN PUCHAR               MessageBuffer OPTIONAL
    01145     )
    01146 /*++
    01147
    01148 Routine Description:
    01149
    01150     Initialize the dump driver stack referenced by DumpStack to perform IO.
    01151
    01152 Arguments:
    01153
    01154     DumpStack   - Dump driver stack being initialized
    01155
    01156 Return Value:
    01157
    01158     Status
    01159
    01160 --*/
    01161 {
    01162
    01163     PINITIALIZATION_CONTEXT     DumpInit;
    01164     PLIST_ENTRY                 Link;
    01165     ULONG                       Check;
    01166     NTSTATUS                    Status;
    01167     PDRIVER_INITIALIZE          DriverInit;
    01168     PDUMP_STACK_IMAGE           DumpImage;
    01169
    01170
    01171     DumpInit = &DumpStack->Init;
    01172
    01173     //
    01174     // Verify checksum on DumpStack structure
    01175     //
    01176
    01177     // BUGBUG: later
    01178
    01179     //
    01180     // Initializes the dump drivers
    01181     //
    01182
    01183     for (Link = DumpStack->DriverList.Flink;
    01184          Link != &DumpStack->DriverList;
    01185          Link = Link->Flink) {
    01186
    01187         DumpImage = CONTAINING_RECORD(Link, DUMP_STACK_IMAGE, Link);
    01188
    01189         //
    01190         // Call this driver's driver init.  Only the first driver gets the
    01191         // dump initialization context
    01192         //
    01193
    01194         DriverInit = DumpImage->Image->EntryPoint;
    01195         Status = DriverInit (NULL, (PUNICODE_STRING) DumpInit);
    01196         DumpInit = NULL;
    01197
    01198         if (!NT_SUCCESS(Status)) {
    01199             IoDebugPrint ((0,
    01200                            "IODUMP: Unable to initialize driver; error = %x\n",
    01201                            Status
    01202                            ));
    01203             return Status;
    01204         }
    01205     }
    01206
    01207     DumpInit = &DumpStack->Init;
    01208
    01209     //
    01210     // Display string we are starting
    01211     //
    01212
    01213     if (MessageBuffer) {
    01214         InbvDisplayString (MessageBuffer);
    01215     }
    01216
    01217     //
    01218     // Open the partition from which the system was booted.
    01219     // This returns TRUE if the disk w/the appropriate signature was found,
    01220     // otherwise a NULL, in which case there is no way to continue.
    01221     //
    01222
    01223     if (!DumpInit->OpenRoutine (DumpStack->PartitionOffset)) {
    01224         IoDebugPrint (( 0, "IODUMP: Could not find/open partition offset\n" ));
    01225         return STATUS_UNSUCCESSFUL;
    01226     }
    01227
    01228     return STATUS_SUCCESS;
    01229 }
    01230
    01231
    01232 VOID
    01233 IoGetDumpHiberRanges (
    01234     IN PVOID                    HiberContext,
    01235     IN PDUMP_STACK_CONTEXT      DumpStack
    01236     )
    01237 /*++
    01238
    01239 Routine Description:
    01240
    01241     Adds the dump driver stack storage to the hibernate range list,
    01242     to inform the hibernate procedure which pages need cloned,
    01243     discarded or not checksumed as they are in use by the dump
    01244     stack.
    01245
    01246 Arguments:
    01247
    01248     HiberContext        - Pointer to the hiber context structure
    01249
    01250     DumpStack           - Dump driver stack being initialized
    01251
    01252 Return Value:
    01253
    01254     None
    01255
    01256 --*/
    01257 {
    01258     PDUMP_POINTERS              DumpPointers;
    01259     PDUMP_STACK_IMAGE           DumpImage;
    01260     PLIST_ENTRY                 Link;
    01261
    01262     DumpPointers = DumpStack->DumpPointers;
    01263
    01264     //
    01265     // Report the common buffer
    01266     //
    01267
    01268     if (DumpPointers->CommonBufferVa) {
    01269         PoSetHiberRange (
    01270             HiberContext,
    01271             PO_MEM_CL_OR_NCHK,
    01272             DumpPointers->CommonBufferVa,
    01273             DumpPointers->CommonBufferSize,
    01274             'fubc'
    01275             );
    01276     }
    01277
    01278     //
    01279     // Dump the entire image of the dump drivers
    01280     //
    01281
    01282     for (Link = DumpStack->DriverList.Flink;
    01283          Link != &DumpStack->DriverList;
    01284          Link = Link->Flink) {
    01285
    01286         DumpImage = CONTAINING_RECORD(Link, DUMP_STACK_IMAGE, Link);
    01287
    01288         PoSetHiberRange (
    01289             HiberContext,
    01290             PO_MEM_CL_OR_NCHK,
    01291             DumpImage->ImageBase,
    01292             DumpImage->SizeOfImage,
    01293             'gmID'
    01294             );
    01295     }
    01296 }
    01297
    01298
    01299 VOID
    01300 IoFreeDumpStack (
    01301     IN PDUMP_STACK_CONTEXT     DumpStack
    01302     )
    01303 /*++
    01304
    01305 Routine Description:
    01306
    01307     Free the dump driver stack referenced by DumpStack
    01308
    01309 Arguments:
    01310
    01311     DumpStack           - Dump driver stack being initialized
    01312
    01313 Return Value:
    01314
    01315     None
    01316
    01317 --*/
    01318 {
    01319     PINITIALIZATION_CONTEXT     DumpInit;
    01320     PDUMP_STACK_IMAGE           DumpImage;
    01321     PDEVICE_OBJECT              DeviceObject;
    01322     PIO_STACK_LOCATION          IrpSp;
    01323     IO_STATUS_BLOCK             IoStatus;
    01324     PIRP                        Irp;
    01325     KEVENT                      Event;
    01326     NTSTATUS                    Status;
    01327     ULONG                       i;
    01328     PFILE_OBJECT                FileObject;
    01329     IO_STACK_LOCATION           irpSp;
    01330     ULONG                       information;
    01331
    01332     PAGED_CODE();
    01333     DumpInit = &DumpStack->Init;
    01334
    01335     //
    01336     // Release the claim to this file as a specific device usage path.
    01337     //
    01338
    01339     FileObject = DumpStack->FileObject;
    01340     if (FileObject) {
    01341         DeviceObject = IoGetRelatedDeviceObject (FileObject);
    01342
    01343         RtlZeroMemory (&irpSp, sizeof (IO_STACK_LOCATION));
    01344
    01345         irpSp.MajorFunction = IRP_MJ_PNP;
    01346         irpSp.MinorFunction = IRP_MN_DEVICE_USAGE_NOTIFICATION;
    01347         irpSp.Parameters.UsageNotification.Type = DumpStack->UsageType;
    01348         irpSp.Parameters.UsageNotification.InPath = FALSE;
    01349         irpSp.FileObject = FileObject;
    01350
    01351         if (DeviceUsageTypeUndefined != DumpStack->UsageType) {
    01352             Status = IopSynchronousCall (DeviceObject, &irpSp, (VOID **) &information);
    01353             ASSERT (0 == information);
    01354         } else {
    01355             Status = STATUS_SUCCESS;
    01356         }
    01357     }
    01358
    01359     //
    01360     // Free any common buffers which where allocated
    01361     //
    01362
    01363     for (i=0; i < 2; i++) {
    01364         if (DumpInit->CommonBuffer[i]) {
    01365             if (DumpInit->AdapterObject) {
    01366
    01367 #if !defined(NO_LEGACY_DRIVERS)
    01368                 HalFreeCommonBuffer (
    01369                     DumpInit->AdapterObject,
    01370                     ((PDUMP_POINTERS)DumpStack->DumpPointers)->CommonBufferSize,
    01371                     DumpInit->PhysicalAddress[i],
    01372                     DumpInit->CommonBuffer[i],
    01373                     FALSE
    01374                     );
    01375 #else
    01376                 (*((PDMA_ADAPTER)DumpInit->AdapterObject)->DmaOperations->
    01377                  FreeCommonBuffer )(
    01378                      (PDMA_ADAPTER)DumpInit->AdapterObject,
    01379                      ((PDUMP_POINTERS)DumpStack->DumpPointers)->CommonBufferSize,
    01380                      DumpInit->PhysicalAddress[i],
    01381                      DumpInit->CommonBuffer[i],
    01382                      FALSE
    01383                      );
    01384
    01385 #endif // NO_LEGACY_DRIVERS
    01386
    01387
    01388             } else {
    01389                 MmFreeContiguousMemory (DumpInit->CommonBuffer[i]);
    01390             }
    01391         }
    01392         DumpInit->CommonBuffer[i] = NULL;
    01393     }
    01394
    01395     //
    01396     // Unload the dump drivers
    01397     //
    01398
    01399     while (!IsListEmpty(&DumpStack->DriverList)) {
    01400         DumpImage = CONTAINING_RECORD(DumpStack->DriverList.Blink, DUMP_STACK_IMAGE, Link);
    01401         RemoveEntryList (&DumpImage->Link);
    01402         MmUnloadSystemImage (DumpImage->Image);
    01403         ExFreePool (DumpImage);
    01404     }
    01405
    01406     //
    01407     // Inform the driver stack that the dump registartion is over
    01408     //
    01409
    01410     if (DumpStack->FileObject) {
    01411         DeviceObject = IoGetRelatedDeviceObject ((PFILE_OBJECT) DumpStack->FileObject);
    01412
    01413         KeInitializeEvent( &Event, NotificationEvent, FALSE );
    01414         Irp = IoBuildDeviceIoControlRequest(
    01415                     IOCTL_SCSI_FREE_DUMP_POINTERS,
    01416                     DeviceObject,
    01417                     DumpStack->DumpPointers,
    01418                     sizeof (DUMP_POINTERS),
    01419                     NULL,
    01420                     0,
    01421                     FALSE,
    01422                     &Event,
    01423                     &IoStatus
    01424                     );
    01425
    01426         IrpSp = IoGetNextIrpStackLocation (Irp);
    01427         IrpSp->FileObject = DumpStack->FileObject;
    01428
    01429         Status = IoCallDriver( DeviceObject, Irp );
    01430
    01431         if (Status == STATUS_PENDING) {
    01432             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
    01433             Status = IoStatus.Status;
    01434         }
    01435         ObDereferenceObject( DumpStack->FileObject );
    01436     }
    01437     //
    01438     // Free the target address if it exists
    01439     //
    01440     if (DumpStack->Init.TargetAddress) {
    01441         ExFreePool( DumpStack->Init.TargetAddress);
    01442     }
    01443     //
    01444     // Free the dump stack context
    01445     //
    01446
    01447     ExFreePool (DumpStack);
    01448 }
    01449
    01450
    01451 NTSTATUS
    01452 IopInitializeDumpSpaceAndType(
    01453     IN PDUMP_CONTROL_BLOCK dcb,
    01454     IN OUT PULONG block,
    01455     IN PSUMMARY_DUMP_HEADER pSummaryHeader
    01456     )
    01457 {
    01458     LARGE_INTEGER Space;
    01459
    01460     Space.QuadPart = 0;
    01461
    01462     if (dcb->Flags & DCB_TRIAGE_DUMP_ENABLED) {
    01463
    01464         //
    01465         // Fixed size dump for triage-dumps.
    01466         //
    01467
    01468         block [ DH_DUMP_TYPE ] = DUMP_TYPE_TRIAGE;
    01469         Space.QuadPart = TRIAGE_DUMP_SIZE;
    01470
    01471
    01472     } else if (dcb->Flags & DCB_SUMMARY_DUMP_ENABLED) {
    01473
    01474         block [ DH_DUMP_TYPE ] = DUMP_TYPE_SUMMARY;
    01475
    01476         Space = IopCalculateRequiredDumpSpace(
    01477                                 dcb->Flags,
    01478                                 dcb->HeaderSize,
    01479                                 dcb->MemoryDescriptor->NumberOfPages,
    01480                                 pSummaryHeader->Pages
    01481                                 );
    01482     } else {
    01483
    01484         if (dcb->Flags & DCB_DUMP_HEADER_ENABLED) {
    01485             block [ DH_DUMP_TYPE ] = DUMP_TYPE_HEADER;
    01486         }
    01487
    01488         Space = IopCalculateRequiredDumpSpace(
    01489                                 dcb->Flags,
    01490                                 dcb->HeaderSize,
    01491                                 dcb->MemoryDescriptor->NumberOfPages,
    01492                                 dcb->MemoryDescriptor->NumberOfPages
    01493                                 );
    01494     }
    01495
    01496     //
    01497     // If the calculated size is larger than the pagefile, truncate it to
    01498     // the pagefile size.
    01499     //
    01500
    01501     if (Space.QuadPart > dcb->DumpFileSize.QuadPart) {
    01502         Space.QuadPart = dcb->DumpFileSize.QuadPart;
    01503     }
    01504
    01505     block [ DH_REQUIRED_DUMP_SPACE ] = Space.LowPart;
    01506     block [ DH_REQUIRED_DUMP_SPACE + 1 ] = Space.HighPart;
    01507
    01508     IoDebugPrint((2,"IODUMP: dcb File Size %x Block Size %x\n",
    01509                     block [DH_REQUIRED_DUMP_SPACE],
    01510                     (ULONG)dcb->DumpFileSize.LowPart
    01511                     ));
    01512
    01513     return STATUS_SUCCESS;
    01514 }
    01515
    01516
    01517
    01518 BOOLEAN
    01519 IoWriteCrashDump(
    01520     IN ULONG BugCheckCode,
    01521     IN ULONG_PTR BugCheckParameter1,
    01522     IN ULONG_PTR BugCheckParameter2,
    01523     IN ULONG_PTR BugCheckParameter3,
    01524     IN ULONG_PTR BugCheckParameter4,
    01525     IN PVOID ContextSave
    01526     )
    01527
    01528 /*++
    01529
    01530 Routine Description:
    01531
    01532     This routine checks to see whether or not crash dumps are enabled and, if
    01533     so, writes all of physical memory to the system disk's paging file.
    01534
    01535 Arguments:
    01536
    01537     BugCheckCode/ParameterN - Code and parameters w/which BugCheck was called.
    01538
    01539 Return Value:
    01540
    01541     None.
    01542
    01543 --*/
    01544
    01545 {
    01546     PDUMP_CONTROL_BLOCK dcb;
    01547     PDUMP_STACK_CONTEXT dumpStack;
    01548     PDUMP_DRIVER_WRITE write;
    01549     PDUMP_DRIVER_FINISH finishUp;
    01550     PDUMP_HEADER header;
    01551     EXCEPTION_RECORD exception;
    01552     PCONTEXT context = ContextSave;
    01553     PULONG block;
    01554     LARGE_INTEGER diskByteOffset;
    01555     PPFN_NUMBER page;
    01556     PFN_NUMBER localMdl[(sizeof( MDL )/sizeof(PFN_NUMBER)) + 17];
    01557     PMDL mdl;
    01558     PLARGE_INTEGER mcb;
    01559     ULONG_PTR memoryAddress;
    01560     ULONG byteOffset;
    01561     ULONG byteCount;
    01562     ULONG bytesRemaining;
    01563     NTSTATUS status;
    01564     UCHAR messageBuffer[128];
    01565     PFN_NUMBER ActualPages;
    01566     PSUMMARY_DUMP_HEADER pSummaryHeader;
    01567     ULONG dwTransferSize;
    01568     LARGE_INTEGER requiredDumpSpace;
    01569     ULONG_PTR DirBasePage;
    01570
    01571     //
    01572     // Begin by determining whether or not crash dumps are enabled.  If not,
    01573     // check to see whether or not auto-rebooting is enabled.  If not, return
    01574     // immediately since there is nothing to do.
    01575     //
    01576
    01577     dcb = IopDumpControlBlock;
    01578     if (!dcb) {
    01579         return FALSE;
    01580     }
    01581
    01582     if (dcb->Flags & DCB_DUMP_ENABLED || dcb->Flags & DCB_SUMMARY_ENABLED) {
    01583
    01584         IopFinalCrashDumpStatus = STATUS_PENDING;
    01585
    01586         //
    01587         // A dump is to be written to the paging file.  Ensure that all of the
    01588         // descriptor data for what needs to be done is valid, otherwise it
    01589         // could be that part of the reason for the bugcheck is that this data
    01590         // was corrupted.  Or, it could be that no paging file was found yet,
    01591         // or any number of other situations.
    01592         //
    01593
    01594         if (IopGetDumpControlBlockCheck(dcb) != IopDumpControlBlockChecksum) {
    01595             IoDebugPrint (( 0,
    01596                            "CRASHDUMP: Disk dump routine returning due to DCB integrity error\n"
    01597                            "           No dump will be created\n" ));
    01598             IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    01599             return FALSE;
    01600         }
    01601
    01602         //
    01603         // Message  that we are starting the crashdump
    01604         //
    01605
    01606         dumpStack = dcb->DumpStack;
    01607         sprintf( messageBuffer, "%Z\n", &dumpStack->InitMsg );
    01608
    01609         //
    01610         // Initialize the dump stack
    01611         //
    01612
    01613         status = IoInitializeDumpStack (dumpStack, messageBuffer);
    01614         if (!NT_SUCCESS( status )) {
    01615             IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    01616             return FALSE;
    01617         }
    01618
    01619         //
    01620         // Record the dump driver's entry points.
    01621         //
    01622
    01623         write = dumpStack->Init.WriteRoutine;
    01624         finishUp = dumpStack->Init.FinishRoutine;
    01625
    01626
    01627         dwTransferSize = dumpStack->Init.MaximumTransferSize;
    01628
    01629         if ( ( !dwTransferSize ) || ( dwTransferSize > IO_DUMP_MAXIMUM_TRANSFER_SIZE ) ) {
    01630             dwTransferSize = IO_DUMP_MINIMUM_TRANSFER_SIZE;
    01631         }
    01632
    01633         IoDebugPrint((2,"CRASHDUMP: Maximum Transfer Size = %x\n",dwTransferSize));
    01634
    01635
    01636         //
    01637         // The boot partition was found, so put together a dump file header
    01638         // and write it to the disk.
    01639         //
    01640
    01641         block = dcb->HeaderPage;
    01642         header = (PDUMP_HEADER) block;
    01643
    01644         RtlFillMemoryUlong( header, PAGE_SIZE, 'EGAP' );
    01645         header->ValidDump = 'PMUD';
    01646         header->BugCheckCode = BugCheckCode;
    01647         header->BugCheckParameter1 = BugCheckParameter1;
    01648         header->BugCheckParameter2 = BugCheckParameter2;
    01649         header->BugCheckParameter3 = BugCheckParameter3;
    01650         header->BugCheckParameter4 = BugCheckParameter4;
    01651 #if defined (i386)
    01652         //
    01653         // Add the current page directory table page - don't use the directory
    01654         // table base for the crashing process as we have switched cr3 on
    01655         // stack overflow crashes, etc.
    01656         //
    01657
    01658         _asm {
    01659             mov     eax, cr3
    01660             mov     DirBasePage, eax
    01661         }
    01662         header->DirectoryTableBase = DirBasePage;
    01663 #else
    01664         header->DirectoryTableBase = KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
    01665 #endif
    01666         header->PfnDataBase = MmPfnDatabase;
    01667         header->PsLoadedModuleList = &PsLoadedModuleList;
    01668         header->PsActiveProcessHead = &PsActiveProcessHead;
    01669         header->NumberProcessors = dcb->NumberProcessors;
    01670         header->MajorVersion = dcb->MajorVersion;
    01671         header->MinorVersion = dcb->MinorVersion;
    01672         header->KdDebuggerDataBlock = KdGetDataBlock();
    01673         header->PaeEnabled = PaeEnabled ();
    01674
    01675         header->MachineImageType = CURRENT_IMAGE_TYPE ();
    01676
    01677         if (!(dcb->Flags & DCB_DUMP_ENABLED)) {
    01678             dcb->MemoryDescriptor->NumberOfPages = 1;
    01679         }
    01680
    01681         strcpy( header->VersionUser, dcb->VersionUser );
    01682
    01683         RtlCopyMemory( &block[DH_PHYSICAL_MEMORY_BLOCK],
    01684                        dcb->MemoryDescriptor,
    01685                        sizeof( PHYSICAL_MEMORY_DESCRIPTOR ) +
    01686                        ((dcb->MemoryDescriptor->NumberOfRuns - 1) *
    01687                        sizeof( PHYSICAL_MEMORY_RUN )) );
    01688
    01689         RtlCopyMemory( &block[DH_CONTEXT_RECORD],
    01690                        context,
    01691                        sizeof( CONTEXT ) );
    01692
    01693         exception.ExceptionCode = STATUS_BREAKPOINT;
    01694         exception.ExceptionRecord = (PEXCEPTION_RECORD) NULL;
    01695         exception.NumberParameters = 0;
    01696         exception.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
    01697         exception.ExceptionAddress = (PVOID) PROGRAM_COUNTER (context);
    01698
    01699         RtlCopyMemory( &block[DH_EXCEPTION_RECORD],
    01700                        &exception,
    01701                        sizeof( EXCEPTION_RECORD ) );
    01702
    01703         //
    01704         // Init dump type to FULL
    01705         //
    01706
    01707         block[DH_DUMP_TYPE] = DUMP_TYPE_FULL;
    01708
    01709         //
    01710         // Set the timestamp
    01711         //
    01712 #ifdef _WIN64
    01713         RtlCopyMemory( &block[DH_CRASH_DUMP_TIMESTAMP],
    01714                        (PCHAR)( &SharedUserData->SystemLowTime),
    01715                        sizeof( LARGE_INTEGER) );
    01716 #else
    01717         RtlCopyMemory( &block[DH_CRASH_DUMP_TIMESTAMP],
    01718                        (PCHAR)( &SharedUserData->SystemTime),
    01719                        sizeof( LARGE_INTEGER) );
    01720 #endif
    01721
    01722         //
    01723         // Set the Required dump size in the dump header. In the case of
    01724         // a summary dump the file allocation size can be significantly larger
    01725         // then the amount of used space.
    01726         //
    01727
    01728         RtlZeroMemory( &block[DH_REQUIRED_DUMP_SPACE], sizeof(LARGE_INTEGER));
    01729
    01730         if (dcb->Flags & DCB_DUMP_ENABLED) {
    01731
    01732             //
    01733             // If summary dump try to create the dump header
    01734             //
    01735
    01736             if ( (dcb->Flags & DCB_SUMMARY_DUMP_ENABLED) ) {
    01737
    01738                 //
    01739                 // Initialize the summary dump
    01740                 //
    01741
    01742                 pSummaryHeader = IopInitializeSummaryDump(dcb);
    01743
    01744                 if ( !pSummaryHeader ) {
    01745
    01746                     //
    01747                     // No summary dump header so return.
    01748                     //
    01749
    01750                     IoDebugPrint((1,"IoWriteCrashDump: Error Null summary dump header\n"));
    01751
    01752                     IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    01753
    01754                     return FALSE;
    01755                 }
    01756             }
    01757
    01758             IopInitializeDumpSpaceAndType (dcb, block, pSummaryHeader);
    01759         }
    01760
    01761         //
    01762         // All of the pieces of the header file have been generated.  Before
    01763         // mapping or writing anything to the disk, the I- & D-stream caches
    01764         // must be flushed so that page color coherency is kept.  Sweep both
    01765         // caches now.
    01766         //
    01767
    01768         KeSweepCurrentDcache();
    01769         KeSweepCurrentIcache();
    01770
    01771         //
    01772         // Create MDL for dump.
    01773         //
    01774
    01775         mdl = (PMDL) &localMdl[0];
    01776         MmCreateMdl( mdl, NULL, PAGE_SIZE );
    01777         mdl->MdlFlags |= MDL_PAGES_LOCKED;
    01778
    01779         mcb = dcb->FileDescriptorArray;
    01780
    01781         page = MmGetMdlPfnArray(mdl);
    01782         *page = dcb->HeaderPfn;
    01783         mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
    01784
    01785         bytesRemaining = PAGE_SIZE;
    01786         memoryAddress = (ULONG_PTR) dcb->HeaderPage;
    01787
    01788         //
    01789         // All of the pieces of the header file have been generated.  Write
    01790         // the header page to the paging file, using the appropriate drivers,
    01791         // etc.
    01792         //
    01793
    01794         IoDebugPrint((2,"IoWriteCrashDump: Writing dump header to disk\n"));
    01795
    01796         while (bytesRemaining) {
    01797
    01798             if (mcb[0].QuadPart <= bytesRemaining) {
    01799                 byteCount = mcb[0].LowPart;
    01800             } else {
    01801                 byteCount = bytesRemaining;
    01802             }
    01803
    01804             mdl->ByteCount = byteCount;
    01805             mdl->ByteOffset = (ULONG)(memoryAddress & (PAGE_SIZE - 1));
    01806             mdl->MappedSystemVa = (PVOID) memoryAddress;
    01807             mdl->StartVa = PAGE_ALIGN ((PVOID)memoryAddress);
    01808
    01809             //
    01810             // Write to disk.
    01811             //
    01812
    01813             if (!NT_SUCCESS( write( &mcb[1], mdl ) )) {
    01814                 IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    01815                 return FALSE;
    01816             }
    01817
    01818             //
    01819             // Adjust bytes remaining.
    01820             //
    01821
    01822             bytesRemaining -= byteCount;
    01823             memoryAddress += byteCount;
    01824             mcb[0].QuadPart = mcb[0].QuadPart - byteCount;
    01825             mcb[1].QuadPart = mcb[1].QuadPart + byteCount;
    01826
    01827             if (!mcb[0].QuadPart) {
    01828                 mcb += 2;
    01829             }
    01830         }
    01831
    01832         IoDebugPrint((2,"IoWriteCrashDump: Header Page written\n"));
    01833
    01834
    01835         //
    01836         // If only requesting a header dump, we are now done.
    01837         //
    01838
    01839         if (dcb->Flags & DCB_DUMP_HEADER_ENABLED) {
    01840             IoDebugPrint((2,"IoWriteCrashDump: Only Dumping Dump Header\n"));
    01841             goto FinishDump;
    01842         }
    01843
    01844         //
    01845         // The header page has been written. If this is a triage-dump, write
    01846         // the dump information and bail. Otherwise, fall through and do the
    01847         // full or summary dump.
    01848         //
    01849
    01850         if (dcb->Flags & DCB_TRIAGE_DUMP_ENABLED) {
    01851             status = IopWriteTriageDump (dcb->TriageDumpFlags,
    01852                                        write,
    01853                                        mcb,
    01854                                        mdl,
    01855                                        dwTransferSize,
    01856                                        context,
    01857                                        dcb->TriageDumpBuffer,
    01858                                        dcb->TriageDumpBufferSize - PAGE_SIZE,
    01859                                        dcb->BuildNumber,
    01860                                        dcb->Flags
    01861                                        );
    01862
    01863             if (!NT_SUCCESS (status)) {
    01864                 IoDebugPrint((1, "IoWriteCrashDump: Failed to write triage-dump\n"));
    01865                 IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    01866                 return FALSE;
    01867             }
    01868
    01869             IoDebugPrint((1, "IoWriteCrashDump: Successfully wrote triage-dump\n"));
    01870             goto FinishDump;
    01871         }
    01872
    01873         //
    01874         // The header page has been written to the paging file.  If a full dump
    01875         // of all of physical memory is to be written, write it now.
    01876         //
    01877
    01878         if (dcb->Flags & DCB_DUMP_ENABLED) {
    01879
    01880             PFN_NUMBER pagesDoneSoFar = 0;
    01881             ULONG currentPercentage = 0;
    01882             ULONG maximumPercentage = 0;
    01883
    01884
    01885             //
    01886             // Actual Pages is the number of pages to dump.
    01887             //
    01888
    01889             ActualPages = dcb->MemoryDescriptor->NumberOfPages;
    01890
    01891             if (dcb->Flags & DCB_SUMMARY_DUMP_ENABLED) {
    01892
    01893                 PRTL_BITMAP PageMap;
    01894
    01895                 ASSERT ( pSummaryHeader != NULL );
    01896
    01897                 PageMap = (PRTL_BITMAP)(pSummaryHeader + 1);
    01898                 ASSERT (PageMap != NULL);
    01899
    01900                 //
    01901                 // At this point the dump header header has been sucessfully
    01902                 // written. Write the summary dump header.
    01903                 //
    01904
    01905                 status = IopWriteSummaryHeader(
    01906                                      pSummaryHeader,
    01907                                      write,
    01908                                      &mcb,
    01909                                      mdl,
    01910                                      dwTransferSize,
    01911                                      (dcb->HeaderSize - PAGE_SIZE)
    01912                                      );
    01913
    01914                 if (!NT_SUCCESS (status)) {
    01915                     IoDebugPrint((1,"IoWriteCrashDump: Error writing summary dump header\n"));
    01916                     IopFinalCrashDumpStatus = status;
    01917                     return FALSE;
    01918                 }
    01919
    01920                 IoDebugPrint((2,"IoWriteCrashDump: Sucessfully wrote summary dump header\n"));
    01921
    01922                 ActualPages = pSummaryHeader->Pages;
    01923
    01924             }
    01925
    01926             IoDebugPrint((2,"IoWriteCrashDump: Writing Memory Dump\n"));
    01927
    01928             //
    01929             // Set the virtual file offset and initialize loop variables and
    01930             // constants.
    01931             //
    01932
    01933             memoryAddress = (ULONG_PTR)dcb->MemoryDescriptor->Run[0].BasePage * PAGE_SIZE;
    01934
    01935             if ( dcb->Flags & DCB_SUMMARY_DUMP_ENABLED ) {
    01936
    01937                 PRTL_BITMAP BitMap;
    01938
    01939                 BitMap = (PRTL_BITMAP)(pSummaryHeader+1);
    01940
    01941                 status = IopWriteSummaryDump (
    01942                                         BitMap,
    01943                                         write,
    01944                                         &dumpStack->ProgMsg,
    01945                                         messageBuffer,
    01946                                         mcb,
    01947                                         dwTransferSize
    01948                                         );
    01949
    01950                 if (!NT_SUCCESS (status)) {
    01951                     IoDebugPrint((1, "IoWriteCrashDump: Failed to write triage-dump\n"));
    01952                     IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    01953                     return FALSE;
    01954                 }
    01955
    01956                 IoDebugPrint((1, "IoWriteCrashDump: Successfully wrote triage-dump\n"));
    01957                 goto FinishDump;
    01958             }
    01959
    01960             //
    01961             // Now loop, writing all of physical memory to the paging file.
    01962             //
    01963
    01964             while (mcb[0].QuadPart) {
    01965
    01966                 diskByteOffset = mcb[1];
    01967
    01968                 //
    01969                 // Calculate byte offset;
    01970                 //
    01971
    01972                 byteOffset = (ULONG)(memoryAddress & (PAGE_SIZE - 1));
    01973
    01974                 if (dwTransferSize <= mcb[0].QuadPart) {
    01975                     byteCount = dwTransferSize - byteOffset;
    01976                 } else {
    01977                     byteCount = mcb[0].LowPart;
    01978                 }
    01979                 pagesDoneSoFar += byteCount / PAGE_SIZE;
    01980
    01981                 currentPercentage = (ULONG)((pagesDoneSoFar * 100) /
    01982                                     ActualPages);
    01983
    01984                 if (currentPercentage > maximumPercentage) {
    01985
    01986                     maximumPercentage = currentPercentage;
    01987                     //
    01988                     // Update message on screen.
    01989                     //
    01990
    01991                     sprintf( messageBuffer, "%Z: %3d\r", &dumpStack->ProgMsg, maximumPercentage );
    01992                     InbvDisplayString( messageBuffer );
    01993
    01994                 }
    01995
    01996                 //
    01997                 // Map the physical memory and write it to the
    01998                 // current segment of the file.
    01999                 //
    02000
    02001                 IopMapPhysicalMemory( mdl,
    02002                                    memoryAddress,
    02003                                    &dcb->MemoryDescriptor->Run[0],
    02004                                    byteCount
    02005                                    );
    02006
    02007
    02008                 //
    02009                 // Write the next segment.
    02010                 //
    02011
    02012                 if (!NT_SUCCESS( write( &diskByteOffset, mdl ) )) {
    02013                     IopFinalCrashDumpStatus = STATUS_UNSUCCESSFUL;
    02014                     return FALSE;
    02015                 }
    02016
    02017                 //
    02018                 // Adjust pointers for next part.
    02019                 //
    02020
    02021                 memoryAddress += byteCount;
    02022                 mcb[0].QuadPart = mcb[0].QuadPart - byteCount;
    02023                 mcb[1].QuadPart = mcb[1].QuadPart + byteCount;
    02024
    02025                 if (!mcb[0].QuadPart) {
    02026                     mcb += 2;
    02027                 }
    02028
    02029                 if (pagesDoneSoFar >= ActualPages) {
    02030                     break;
    02031
    02032                 }
    02033
    02034             }
    02035
    02036             IoDebugPrint((2,"IoWriteCrashDump: memory dump written\n"));
    02037         }
    02038
    02039 FinishDump:
    02040
    02041         sprintf( messageBuffer, "%Z", &dumpStack->DoneMsg );
    02042         InbvDisplayString( messageBuffer );
    02043
    02044         //
    02045         // Sweep the cache so the debugger will work.
    02046         //
    02047
    02048         KeSweepCurrentDcache();
    02049         KeSweepCurrentIcache();
    02050
    02051         //
    02052         // Have the dump flush the adapter and disk caches.
    02053         //
    02054
    02055         finishUp();
    02056
    02057         //
    02058         // Indicate to the debugger that the dump has been successfully
    02059         // written.
    02060         //
    02061
    02062         IopFinalCrashDumpStatus = STATUS_SUCCESS;
    02063     }
    02064
    02065     //
    02066     // Check to see whether or not auto-reboots are enabled and, if so,
    02067     // reboot now.
    02068     //
    02069
    02070     if (dcb->Flags & DCB_AUTO_REBOOT) {
    02071         IoDebugPrint (( 0,  "IODUMP: Autorebooting\n" ));
    02072         KeReturnToFirmware( HalRebootRoutine );
    02073     }
    02074
    02075     return TRUE;
    02076 }
    02077
    02078
    02079
    02080 VOID
    02081 IopMapPhysicalMemory(
    02082     IN OUT PMDL Mdl,
    02083     IN ULONG_PTR MemoryAddress,
    02084     IN PPHYSICAL_MEMORY_RUN PhysicalMemoryRun,
    02085     IN ULONG Length
    02086     )
    02087
    02088 /*++
    02089
    02090 Routine Description:
    02091
    02092     This routine is invoked to fill in the specified MDL (Memory Descriptor
    02093     List) w/the appropriate information to map the specified memory address
    02094     range.
    02095
    02096 Arguments:
    02097
    02098     Mdl - Address of the MDL to be filled in.
    02099
    02100     MemoryAddress - Pseudo-virtual address being mapped.
    02101
    02102     PhysicalMemoryRun - Base address of the physical memory run list.
    02103
    02104     Length - Length of transfer to be mapped.
    02105
    02106 Return Value:
    02107
    02108     None.
    02109
    02110 --*/
    02111
    02112 {
    02113     PPHYSICAL_MEMORY_RUN pmr = PhysicalMemoryRun;
    02114     PPFN_NUMBER page;
    02115     PFN_NUMBER pages;
    02116     PFN_NUMBER base;
    02117     PFN_NUMBER currentBase;
    02118
    02119     //
    02120     // Begin by determining the base physical page of the start of the address
    02121     // range and filling in the MDL appropriately.
    02122     //
    02123     Mdl->StartVa = PAGE_ALIGN( (PVOID) (MemoryAddress) );
    02124     Mdl->ByteOffset = (ULONG)(MemoryAddress & (PAGE_SIZE - 1));
    02125     Mdl->ByteCount = Length;
    02126
    02127     //
    02128     // Get the page frame index for the base address.
    02129     //
    02130
    02131     base = (PFN_NUMBER) ((ULONG_PTR)(Mdl->StartVa) >> PAGE_SHIFT);
    02132     pages = COMPUTE_PAGES_SPANNED(MemoryAddress, Length);
    02133     currentBase = pmr->BasePage;
    02134     page = MmGetMdlPfnArray(Mdl);
    02135
    02136     //
    02137     // Map all of the pages for this transfer until there are no more remaining
    02138     // to be mapped.
    02139     //
    02140
    02141     while (pages) {
    02142
    02143         //
    02144         // Find the memory run that maps the beginning of this transfer.
    02145         //
    02146
    02147         while (currentBase + pmr->PageCount <= base) {
    02148             currentBase += pmr->PageCount;
    02149             pmr++;
    02150         }
    02151
    02152         //
    02153         // The current memory run maps the start of this transfer.  Capture
    02154         // the base page for the start of the transfer.
    02155         //
    02156
    02157         *page++ = pmr->BasePage + (PFN_NUMBER)(base++ - currentBase);
    02158         pages--;
    02159     }
    02160
    02161     //
    02162     // All of the PFNs for the address range have been filled in so map the
    02163     // physical memory into virtual address space.
    02164     //
    02165
    02166     MmMapMemoryDumpMdl( Mdl );
    02167 }
    02168
    02169
    02170
    02171 VOID
    02172 IopAddPageToPageMap(
    02173     IN ULONG dwMaxPage,
    02174     IN PRTL_BITMAP pBitMapHeader,
    02175     IN ULONG dwPageFrameIndex,
    02176     IN ULONG dwNumberOfPages
    02177     )
    02178 {
    02179     //
    02180     // Sometimes we get PFNs that are out of range. Just ignore them.
    02181     //
    02182
    02183     if (dwPageFrameIndex >= dwMaxPage) {
    02184         return;
    02185     }
    02186
    02187     RtlSetBits (pBitMapHeader, dwPageFrameIndex, dwNumberOfPages);
    02188 }
    02189
    02190
    02191
    02192 VOID
    02193 IopRemovePageFromPageMap(
    02194     IN ULONG dwMaxPage,
    02195     IN PRTL_BITMAP pBitMapHeader,
    02196     IN ULONG dwPageFrameIndex,
    02197     IN ULONG dwNumberOfPages
    02198     )
    02199 {
    02200     //
    02201     // Sometimes we get PFNs that are out of range. Just ignore them.
    02202     //
    02203
    02204     if (dwPageFrameIndex >= dwMaxPage) {
    02205         return;
    02206     }
    02207
    02208     IoDebugPrint( (6, "RtlClearBits max:%x pfn:%x, pages:%x\n",(dwMaxPage), (dwPageFrameIndex), (dwNumberOfPages) )); \
    02209     RtlClearBits (pBitMapHeader, dwPageFrameIndex, dwNumberOfPages);
    02210
    02211 }
    02212
    02213
    02214
    02215 NTKERNELAPI
    02216 NTSTATUS
    02217 IoGetCrashDumpInformation(
    02218     OUT PSYSTEM_CRASH_DUMP_INFORMATION pCrashDumpInfo
    02219     )
    02220
    02221 /*++
    02222
    02223 Routine Description:
    02224
    02225     This function checks to see if an open crash dump section exists and
    02226     if so creates a handle to the section and returns that value
    02227     in the CrashDumpInformation structure.
    02228
    02229
    02230 Arguments:
    02231
    02232     CrashInfo - Supplies a pointer to the crash dump information
    02233                 structure.
    02234
    02235 Return Value:
    02236
    02237     Status of the operation.  A handle value of zero indicates no
    02238     crash dump was located.
    02239
    02240 --*/
    02241 {
    02242
    02243     if (!IopDumpControlBlock) {
    02244         return STATUS_NOT_FOUND;
    02245     }
    02246
    02247     //
    02248     // NB: The section object is for direct dump support, which has been
    02249     // removed.
    02250     //
    02251
    02252     pCrashDumpInfo->hDumpSection = NULL;
    02253     return STATUS_SUCCESS;
    02254 }
    02255
    02256
    02257
    02258 NTKERNELAPI
    02259 NTSTATUS
    02260 IoGetCrashDumpStateInformation(
    02261     OUT PSYSTEM_CRASH_STATE_INFORMATION pCrashDumpState
    02262     )
    02263
    02264 /*++
    02265
    02266 Routine Description:
    02267
    02268     This routine returns sets the state variable for direct dump (fast dump)
    02269
    02270
    02271 Arguments:
    02272
    02273     CrashInfo - Supplies a pointer to the crash dump state information
    02274                 structure.
    02275
    02276 Return Value:
    02277
    02278     Status of the operation.  A handle value of zero indicates no
    02279     crash dump was located.
    02280
    02281 --*/
    02282
    02283 {
    02284     pCrashDumpState->ValidDirectDump = FALSE;
    02285
    02286     return STATUS_SUCCESS;
    02287 }
    02288
    02289
    02290 NTSTATUS
    02291 IoSetDumpRange(
    02292     IN PVOID   DumpContext,
    02293     IN PVOID   StartVa,
    02294     IN ULONG_PTR Pages,
    02295     IN BOOLEAN IsPhysicalAddress
    02296     )
    02297
    02298 /*++
    02299
    02300 Routine Description:
    02301
    02302     This routine includes this range of memory in the dump
    02303
    02304 Arguments:
    02305
    02306     DumpContext - dump context
    02307
    02308     StartVa - Starting VA
    02309
    02310     Pages - The number of pages to include
    02311
    02312     IsPhysicalAddress - true if direct physical address translation
    02313
    02314 Return Value:
    02315
    02316     STATUS_SUCCESS - On success.
    02317
    02318     NTSTATUS - Error.
    02319
    02320 --*/
    02321 {
    02322     PCHAR                   Va;
    02323     PRTL_BITMAP             pBitMapHeader;
    02324     PHYSICAL_ADDRESS        phyAddr;
    02325     PSUMMARY_DUMP_HEADER    pHeader;
    02326     BOOLEAN                 AllPagesSet;
    02327
    02328
    02329     Va = StartVa;
    02330     pHeader = (PSUMMARY_DUMP_HEADER) DumpContext;
    02331     pBitMapHeader = (PRTL_BITMAP)(pHeader + 1);
    02332     AllPagesSet = TRUE;
    02333
    02334     //
    02335     // Win64 can have really large page addresses.  This dump code does
    02336     // not handle that yet.  Note that before this assert is removed
    02337     // the casts of Pages to ULONG must be removed.
    02338     //
    02339
    02340     ASSERT(Pages <= MAXULONG);
    02341
    02342     //
    02343     // IsPhysicalAddress indicates that the va is virtually / physically
    02344     // contiguous.
    02345     //
    02346
    02347     if (IsPhysicalAddress) {
    02348
    02349         phyAddr = MmGetPhysicalAddress (Va);
    02350         IopAddPageToPageMap (pHeader->BitmapSize,
    02351                              pBitMapHeader,
    02352                              (ULONG)(phyAddr.QuadPart >> PAGE_SHIFT),
    02353                              (ULONG) Pages
    02354                              );
    02355
    02356     } else {
    02357
    02358         //
    02359         // Not physically contiguous.
    02360         //
    02361
    02362         while (Pages) {
    02363
    02364             //
    02365             // Only do a translation for valid pages.
    02366             //
    02367
    02368             if ( MmIsAddressValid(Va) ) {
    02369
    02370                 //
    02371                 // Get the physical mapping. Note: this does not require a lock
    02372                 //
    02373
    02374                 phyAddr = MmGetPhysicalAddress (Va);
    02375
    02376                 IopAddPageToPageMap (pHeader->BitmapSize,
    02377                                      pBitMapHeader,
    02378                                      (ULONG)(phyAddr.QuadPart >> PAGE_SHIFT),
    02379                                      1);
    02380
    02381                 if (phyAddr.QuadPart >> PAGE_SHIFT > pHeader->BitmapSize) {
    02382                     AllPagesSet = FALSE;
    02383                 }
    02384             }
    02385
    02386             Va +=  PAGE_SIZE;
    02387             Pages--;
    02388         }
    02389     }
    02390
    02391     if (AllPagesSet) {
    02392         return STATUS_SUCCESS;
    02393     }
    02394
    02395     return STATUS_INVALID_ADDRESS;
    02396 }
    02397
    02398
    02399 NTSTATUS
    02400 IoFreeDumpRange(
    02401     IN PVOID   DumpContext,
    02402     IN PVOID   StartVa,
    02403     IN ULONG_PTR Pages,
    02404     IN BOOLEAN IsPhysicalAddress
    02405     )
    02406 /*++
    02407
    02408 Routine Description:
    02409
    02410     This routine excludes this range of memory in the dump.
    02411
    02412 Arguments:
    02413
    02414     DumpContext - dump context
    02415
    02416     StartVa - Starting VA
    02417
    02418     Pages - The number of pages to include
    02419
    02420     IsPhysicalAddress - true if direct physical address translation
    02421
    02422 Return Value:
    02423
    02424     STATUS_SUCCESS - On success.
    02425
    02426     NTSTATUS - Error.
    02427
    02428 --*/
    02429 {
    02430     PCHAR                   Va;
    02431     PRTL_BITMAP             pBitMapHeader;
    02432     PHYSICAL_ADDRESS        phyAddr;
    02433     PSUMMARY_DUMP_HEADER    pHeader;
    02434
    02435     //
    02436     // Round to page size.
    02437     //
    02438
    02439     Va = StartVa;
    02440     pHeader = (PSUMMARY_DUMP_HEADER)DumpContext;
    02441     pBitMapHeader = (PRTL_BITMAP)(pHeader + 1);
    02442
    02443     //
    02444     // Win64 can have really large page addresses.  This dump code does
    02445     // not handle that yet.  Note that before this assert is removed
    02446     // the casts of Pages to ULONG must be removed.
    02447     //
    02448
    02449     ASSERT (Pages <= MAXULONG);
    02450
    02451     if (IsPhysicalAddress) {
    02452
    02453         phyAddr = MmGetPhysicalAddress(Va);
    02454
    02455         IopRemovePageFromPageMap (pHeader->BitmapSize,
    02456                                   pBitMapHeader,
    02457                                   (ULONG)(phyAddr.QuadPart >> PAGE_SHIFT),
    02458                                   (ULONG) Pages
    02459                                   );
    02460     } else {
    02461
    02462         while (Pages) {
    02463
    02464             //
    02465             // Only do a translation for valid pages.
    02466             //
    02467
    02468             if ( MmIsAddressValid (Va) ) {
    02469                 phyAddr = MmGetPhysicalAddress (Va);
    02470
    02471                 IoDebugPrint((3,"IoFreeDumpRange:Va: %x Pages: %x IsPhysical: %x phyAddr %I64x\n",
    02472                     StartVa,Pages,IsPhysicalAddress, phyAddr.QuadPart));
    02473
    02474                 IopRemovePageFromPageMap (pHeader->BitmapSize,
    02475                                           pBitMapHeader,
    02476                                           (ULONG)(phyAddr.QuadPart >> PAGE_SHIFT),
    02477                                           1);
    02478
    02479             }
    02480
    02481             Va += PAGE_SIZE;
    02482             Pages--;
    02483         }
    02484     }
    02485
    02486     return STATUS_SUCCESS;
    02487 }
    02488
    02489
    02490
    02491 LARGE_INTEGER
    02492 IopCalculateRequiredDumpSpace(
    02493     IN ULONG   dwDmpFlags,
    02494     IN ULONG   dwHeaderSize,
    02495     IN PFN_NUMBER   dwMaxPages,
    02496     IN PFN_NUMBER   dwMaxSummaryPages
    02497     )
    02498
    02499 /*++
    02500
    02501 Routine Description:
    02502
    02503     This routine is used to calcuate required dump space
    02504
    02505         1. Crash dump summary must be at least 1 page in length.
    02506
    02507         2. Summary dump must be large enough for kernel memory plus header,
    02508            plus summary header.
    02509
    02510         3. Full dump must be large enough for header plus all physical memory.
    02511
    02512 Arguments:
    02513
    02514     dwDmpFlags - Dump Control Block (DCB) flags.
    02515
    02516     dwHeaderSize - The size of the dump header.
    02517
    02518     dwMaxPages - All physical memory.
    02519
    02520     dwMaxSummaryPages - Maximum pages in summary dump.
    02521
    02522 Return Value:
    02523
    02524     Size of the dump file
    02525
    02526 --*/
    02527 {
    02528     LARGE_INTEGER maxMemorySize;
    02529
    02530     //
    02531     // Dump header or dump summary.
    02532     //
    02533
    02534     if ( (dwDmpFlags & DCB_DUMP_HEADER_ENABLED) ||
    02535          ( !( dwDmpFlags & DCB_DUMP_ENABLED ) &&
    02536          ( dwDmpFlags & DCB_SUMMARY_ENABLED ) ) ) {
    02537
    02538         maxMemorySize.QuadPart = IO_DUMP_MINIMUM_FILE_SIZE;
    02539         return maxMemorySize;
    02540     }
    02541
    02542     if (dwDmpFlags & DCB_TRIAGE_DUMP_ENABLED) {
    02543
    02544         maxMemorySize.QuadPart = TRIAGE_DUMP_SIZE;
    02545         return maxMemorySize;
    02546     }
    02547
    02548     if (dwDmpFlags & DCB_SUMMARY_DUMP_ENABLED) {
    02549         ULONG summaryHeaderSize;
    02550         ULONG dwGB;
    02551
    02552         maxMemorySize.QuadPart  = (dwMaxSummaryPages) * PAGE_SIZE;
    02553
    02554         //
    02555         // If biased then max kernel memory is 1GB otherwise it is 2GB
    02556         //
    02557
    02558         dwGB = 1024 * 1024 * 1024;
    02559
    02560         if (maxMemorySize.QuadPart >  (2 * dwGB) ) {
    02561             if (MmVirtualBias) {
    02562                 maxMemorySize.QuadPart = dwGB;
    02563             } else {
    02564                 maxMemorySize.QuadPart = (2 * dwGB);
    02565             }
    02566         }
    02567
    02568         //
    02569         // Calculate the summary header size. Includes the header plus bitmap
    02570         //
    02571         summaryHeaderSize = (ULONG) ROUND_TO_PAGES(
    02572                                 sizeof(SUMMARY_DUMP_HEADER) +
    02573                                 sizeof(RTL_BITMAP) +
    02574                                 ( ( (maxMemorySize.QuadPart >> PAGE_SHIFT ) >> 5 ) << 2 ) +
    02575                                 dwHeaderSize
    02576                                 );
    02577
    02578         maxMemorySize.QuadPart+= summaryHeaderSize;
    02579
    02580         return maxMemorySize;
    02581
    02582     }
    02583
    02584     //
    02585     // Full memory dump is #pages * pagesize plus 1 page for the dump header.
    02586     //
    02587
    02588     maxMemorySize.QuadPart = (dwMaxPages * PAGE_SIZE) + dwHeaderSize;
    02589
    02590     return maxMemorySize;
    02591
    02592 }
    02593
    02594
    02595
    02596 //
    02597 // Triage-dump support routines.
    02598 //
    02599
    02600
    02601 NTSTATUS
    02602 IopGetLoadedDriverInfo(
    02603     OUT ULONG * lpDriverCount,
    02604     OUT ULONG * lpSizeOfStringData
    02605     )
    02606
    02607 /*++
    02608
    02609 Routine Description:
    02610
    02611     Get information about all loaded drivers.
    02612
    02613 Arguments:
    02614
    02615     lpDriverCount - Buffer to return the count of all the drivers that are
    02616                     currently loaded in the system.
    02617
    02618     lpSizeOfStringData - Buffer to return the sum of the sizes of all driver
    02619                     name strings (FullDllName). This does not include the size
    02620                     of the UNICODE_STRING structure or a trailing NULL byte.
    02621
    02622 Return Values:
    02623
    02624     NTSTATUS
    02625
    02626 --*/
    02627
    02628 {
    02629     ULONG DriverCount = 0;
    02630     ULONG SizeOfStringData = 0;
    02631     PLIST_ENTRY NextEntry;
    02632     PLDR_DATA_TABLE_ENTRY DriverEntry;
    02633
    02634
    02635     NextEntry = PsLoadedModuleList.Flink;
    02636     while (NextEntry != &PsLoadedModuleList) {
    02637
    02638         DriverEntry = CONTAINING_RECORD (NextEntry,
    02639                                          LDR_DATA_TABLE_ENTRY,
    02640                                          InLoadOrderLinks
    02641                                          );
    02642
    02643         if (!IopIsAddressRangeValid (DriverEntry, sizeof (*DriverEntry)) ||
    02644             !IopIsAddressRangeValid (DriverEntry->BaseDllName.Buffer,
    02645                                      DriverEntry->BaseDllName.Length)) {
    02646
    02647             return STATUS_UNSUCCESSFUL;
    02648         }
    02649
    02650         DriverCount++;
    02651         SizeOfStringData += DriverEntry->FullDllName.Length;
    02652         NextEntry = NextEntry->Flink;
    02653     }
    02654
    02655     *lpDriverCount = DriverCount;
    02656     *lpSizeOfStringData = SizeOfStringData;
    02657
    02658     return STATUS_SUCCESS;
    02659 }
    02660
    02661 #define DmpPoolStringSize(DumpString)\
    02662         (sizeof (DUMP_STRING) + sizeof (WCHAR) * ( DumpString->Length + 1 ))
    02663
    02664 #define DmpNextPoolString(DumpString)                                       \
    02665         (PDUMP_STRING) (                                                    \
    02666             ALIGN_UP_POINTER(                                               \
    02667                 ((LPBYTE) DumpString) + DmpPoolStringSize (DumpString),     \
    02668                 ULONGLONG                                                   \
    02669                 )                                                           \
    02670             )
    02671
    02672 #define ALIGN_8(_x) ALIGN_UP(_x, DWORDLONG)
    02673
    02674
    02675 #ifndef IndexByByte
    02676 #define IndexByByte(Pointer, Index) (&(((BYTE*) (Pointer)) [Index]))
    02677 #endif
    02678
    02679
    02680 NTSTATUS
    02681 IopWriteDriverList(
    02682     IN ULONG_PTR BufferAddress,
    02683     IN ULONG BufferSize,
    02684     IN ULONG DriverListOffset,
    02685     IN ULONG StringPoolOffset
    02686     )
    02687
    02688 /*++
    02689
    02690 Routine Description:
    02691
    02692     Write the triage dump driver list to the buffer.
    02693
    02694 Arguments:
    02695
    02696     BufferAddress - The address of the buffer.
    02697
    02698     BufferSize - The size of the buffer.
    02699
    02700     DriverListOffset - The offset within the buffer where the driver list
    02701         should be written.
    02702
    02703     StringPoolOffset - The offset within the buffer where the driver list's
    02704         string pool should start. If there are no other strings for the triage
    02705         dump other than driver name strings, this will be the string pool
    02706         offset.
    02707
    02708 Return Value:
    02709
    02710     NTSTATUS
    02711
    02712 --*/
    02713
    02714 {
    02715     ULONG i = 0;
    02716     PLIST_ENTRY NextEntry;
    02717     PLDR_DATA_TABLE_ENTRY DriverEntry;
    02718     PDUMP_DRIVER_ENTRY DumpImageArray;
    02719     PDUMP_STRING DumpStringName = NULL;
    02720     PIMAGE_NT_HEADERS NtHeaders;
    02721
    02722     ASSERT (DriverListOffset != 0);
    02723     ASSERT (StringPoolOffset != 0);
    02724
    02725
    02726     DumpImageArray = (PDUMP_DRIVER_ENTRY) (BufferAddress + DriverListOffset);
    02727     DumpStringName = (PDUMP_STRING) (BufferAddress + StringPoolOffset);
    02728
    02729     NextEntry = PsLoadedModuleList.Flink;
    02730
    02731     while (NextEntry != &PsLoadedModuleList) {
    02732
    02733         DriverEntry = CONTAINING_RECORD (NextEntry,
    02734                                         LDR_DATA_TABLE_ENTRY,
    02735                                         InLoadOrderLinks);
    02736
    02737         //
    02738         // Verify the memory is valid before reading anything from it.
    02739         //
    02740
    02741         if (!IopIsAddressRangeValid (DriverEntry, sizeof (*DriverEntry)) ||
    02742             !IopIsAddressRangeValid (DriverEntry->BaseDllName.Buffer,
    02743                                      DriverEntry->BaseDllName.Length)) {
    02744
    02745             return STATUS_UNSUCCESSFUL;
    02746         }
    02747
    02748         //
    02749         // Build the entry in the string pool. We guarantee all strings are
    02750         // NULL terminated as well as length prefixed.
    02751         //
    02752
    02753         DumpStringName->Length = DriverEntry->BaseDllName.Length / 2;
    02754         RtlCopyMemory (DumpStringName->Buffer,
    02755                        DriverEntry->BaseDllName.Buffer,
    02756                        DumpStringName->Length * sizeof (WCHAR)
    02757                        );
    02758
    02759         DumpStringName->Buffer[ DumpStringName->Length ] = '\000';
    02760
    02761         RtlCopyMemory (&DumpImageArray [i].LdrEntry,
    02762                        DriverEntry,
    02763                        sizeof (DumpImageArray [i].LdrEntry)
    02764                        );
    02765
    02766         //
    02767         // Add the time/date stamp.
    02768         //
    02769
    02770         DumpImageArray[i].LdrEntry.TimeDateStamp = 0;
    02771         DumpImageArray[i].LdrEntry.SizeOfImage = 0;
    02772
    02773         if ( MmDbgReadCheck (DriverEntry->DllBase ) != NULL ) {
    02774
    02775             NtHeaders = RtlImageNtHeader (DriverEntry->DllBase);
    02776             ASSERT ( NtHeaders );
    02777             DumpImageArray[i].LdrEntry.TimeDateStamp = NtHeaders->FileHeader.TimeDateStamp;
    02778             DumpImageArray[i].LdrEntry.SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
    02779         }
    02780
    02781         DumpImageArray [i].DriverNameOffset =
    02782                 (ULONG)((ULONG_PTR) DumpStringName - BufferAddress);
    02783
    02784         i++;
    02785         DumpStringName = DmpNextPoolString (DumpStringName);
    02786         NextEntry = NextEntry->Flink;
    02787     }
    02788
    02789     return STATUS_SUCCESS;
    02790 }
    02791
    02792
    02793
    02794 NTSTATUS
    02795 IopWriteTriageDump(
    02796     IN ULONG Fields,
    02797     IN PDUMP_DRIVER_WRITE DriverWriteRoutine,
    02798     IN OUT PLARGE_INTEGER Mcb,
    02799     IN OUT PMDL Mdl,
    02800     IN ULONG DriverTransferSize,
    02801     IN PCONTEXT Context,
    02802     IN BYTE* Buffer,
    02803     IN ULONG BufferSize,
    02804     IN ULONG ServicePackBuild,
    02805     IN ULONG TriageOptions
    02806     )
    02807
    02808 /*++
    02809
    02810 Routine Description:
    02811
    02812     Write the Triage-Dump to the MCB.
    02813
    02814 Arguments:
    02815
    02816     Fields - The set of fields that should be written.
    02817
    02818     DriverWriteRoutine - The write routine for the driver.
    02819
    02820     Mcb - Message Control Block where the data is to be written.
    02821
    02822     Mdl - A MDL descrbing the data to be written (??).
    02823
    02824     DriverTransferSize - The maximum transfer size for the driver.
    02825
    02826     Context - The context.
    02827
    02828     Buffer - The buffer to use as a scratch buffer.
    02829
    02830     BufferSize - The size of the buffer.
    02831
    02832     ServicePackBuild - Service Pack BuildNumber.
    02833
    02834     TriageOptions - Triage Options.
    02835
    02836 Return Values:
    02837
    02838     STATUS_SUCCESS - On success.
    02839
    02840     NTSTATUS - Otherwise.
    02841
    02842 Comments:
    02843
    02844     This function assumes that exactly one header page was written.
    02845
    02846 --*/
    02847
    02848 {
    02849     ULONG SizeOfSection;
    02850     ULONG SizeOfStringData;
    02851     ULONG DriverCount = 0;
    02852     LPVOID Address = NULL;
    02853     ULONG BytesToWrite = 0;
    02854     ULONG_PTR BufferAddress = 0;
    02855     NTSTATUS Status;
    02856     ULONG_PTR Offset;
    02857     ULONG_PTR StartOfStackRegion = 0;
    02858     PTRIAGE_DUMP_HEADER TriageDumpHeader = NULL;
    02859     PLDR_DATA_TABLE_ENTRY DriverEntry = NULL;
    02860     PDUMP_DRIVER_ENTRY DumpImageArray = NULL;
    02861     PDUMP_STRING DumpStringName = NULL;
    02862     PETHREAD Thread = NULL;
    02863
    02864     IoDebugPrint ((0, "[IopWriteTriageDump] BufferSize = %#x ServicePackBuild = %d\n",
    02865                    BufferSize,
    02866                    ServicePackBuild));
    02867
    02868     //
    02869     // Setup the triage-dump header.
    02870     //
    02871
    02872     if (BufferSize < sizeof (TRIAGE_DUMP_HEADER) + sizeof (DWORD)) {
    02873         return STATUS_NO_MEMORY;
    02874     }
    02875
    02876     TriageDumpHeader = (PTRIAGE_DUMP_HEADER) Buffer;
    02877     RtlZeroMemory (TriageDumpHeader, sizeof (*TriageDumpHeader));
    02878
    02879     //
    02880     // The normal dump header is of size PAGE_SIZE.
    02881     //
    02882
    02883     TriageDumpHeader->SizeOfDump = BufferSize + PAGE_SIZE;
    02884
    02885     //
    02886     // Adjust the BufferSize so we can write the final status DWORD at the
    02887     // end.
    02888     //
    02889
    02890     BufferSize -= sizeof (DWORD);
    02891     RtlZeroMemory (IndexByByte (Buffer, BufferSize), sizeof (DWORD));
    02892
    02893     TriageDumpHeader->ValidOffset = ( TriageDumpHeader->SizeOfDump - sizeof (ULONG) );
    02894     TriageDumpHeader->ContextOffset = DH_CONTEXT_RECORD * sizeof (ULONG);
    02895     TriageDumpHeader->ExceptionOffset = DH_EXCEPTION_RECORD * sizeof (ULONG);
    02896     TriageDumpHeader->BrokenDriverOffset = 0;
    02897     TriageDumpHeader->ServicePackBuild = ServicePackBuild;
    02898     TriageDumpHeader->TriageOptions = TriageOptions;
    02899
    02900     Offset = ALIGN_8 (PAGE_SIZE + sizeof (TRIAGE_DUMP_HEADER));
    02901
    02902     //
    02903     // Set the Mm Offset, if necessary.
    02904     //
    02905
    02906     SizeOfSection = ALIGN_8 (MmSizeOfTriageInformation());
    02907
    02908     if (Offset + SizeOfSection < BufferSize) {
    02909         TriageDumpHeader->MmOffset = (ULONG)Offset;
    02910         Offset += SizeOfSection;
    02911     }
    02912
    02913     //
    02914     // Set the Unloaded Drivers Offset, if necessary.
    02915     //
    02916
    02917     SizeOfSection = ALIGN_8 (MmSizeOfUnloadedDriverInformation());
    02918
    02919     if (Offset + SizeOfSection < BufferSize) {
    02920         TriageDumpHeader->UnloadedDriversOffset = (ULONG)Offset;
    02921         Offset += SizeOfSection;
    02922     }
    02923
    02924     //
    02925     // Set the Prcb Offset, if necessary.
    02926     //
    02927
    02928     if (Fields & TRIAGE_DUMP_PRCB) {
    02929         SizeOfSection = ALIGN_8 (sizeof (KPRCB));
    02930
    02931         if (Offset + SizeOfSection < BufferSize) {
    02932             TriageDumpHeader->PrcbOffset = (ULONG)Offset;
    02933             Offset += SizeOfSection;
    02934         }
    02935     }
    02936
    02937     //
    02938     // Set the Process Offset, if necessary.
    02939     //
    02940
    02941     if (Fields & TRIAGE_DUMP_PROCESS) {
    02942         SizeOfSection = ALIGN_8 (sizeof (EPROCESS));
    02943
    02944         if (Offset + SizeOfSection < BufferSize) {
    02945             TriageDumpHeader->ProcessOffset = (ULONG)Offset;
    02946             Offset += SizeOfSection;
    02947         }
    02948     }
    02949
    02950     //
    02951     // Set the Thread Offset, if necessary.
    02952     //
    02953
    02954     if (Fields & TRIAGE_DUMP_THREAD) {
    02955         SizeOfSection = ALIGN_8 (sizeof (ETHREAD));
    02956
    02957         if (Offset + SizeOfSection < BufferSize) {
    02958             TriageDumpHeader->ThreadOffset = (ULONG)Offset;
    02959             Offset += SizeOfSection;
    02960         }
    02961     }
    02962
    02963     //
    02964     // Set the CallStack Offset, if necessary.
    02965     //
    02966
    02967     Thread = PsGetCurrentThread ();
    02968
    02969     if (Fields & TRIAGE_DUMP_STACK) {
    02970
    02971         //
    02972         // If there is a stack, calculate its size.
    02973         //
    02974
    02975         if (Thread->Tcb.KernelStackResident) {
    02976
    02977             ULONG_PTR StackBase;
    02978
    02979             StackBase = (ULONG_PTR) Thread->Tcb.InitialStack;
    02980
    02981             ASSERT ( StackBase > STACK_POINTER (Context));
    02982
    02983             //
    02984             // There is a valid stack. Note that we limit the size of
    02985             // the triage dump stack to MAX_TRIAGE_STACK_SIZE (currently
    02986             // 16 KB).
    02987             //
    02988
    02989             StartOfStackRegion = (ULONG_PTR) STACK_POINTER (Context);
    02990             SizeOfSection = (ULONG) min ( StackBase -  (ULONG_PTR) STACK_POINTER (Context),
    02991                                   MAX_TRIAGE_STACK_SIZE
    02992                                   );
    02993
    02994             ASSERT ( StartOfStackRegion + SizeOfSection <= StackBase);
    02995
    02996         } else {
    02997
    02998             //
    02999             // There is not a valid stack.
    03000             //
    03001
    03002             SizeOfSection = 0;
    03003         }
    03004
    03005         if (SizeOfSection && Offset + SizeOfSection < BufferSize) {
    03006             TriageDumpHeader->CallStackOffset = (ULONG)Offset;
    03007             TriageDumpHeader->SizeOfCallStack = SizeOfSection;
    03008             TriageDumpHeader->BaseOfStack = (ULONG) StartOfStackRegion;
    03009             Offset += SizeOfSection;
    03010         }
    03011     }
    03012
    03013     //
    03014     // Set the Driver List Offset, if necessary.
    03015     //
    03016
    03017     Status = IopGetLoadedDriverInfo (&DriverCount, &SizeOfStringData);
    03018
    03019     if (NT_SUCCESS (Status) && Fields & TRIAGE_DUMP_DRIVER_LIST) {
    03020         SizeOfSection = ALIGN_8 (DriverCount * sizeof (DUMP_DRIVER_ENTRY));
    03021
    03022         if (SizeOfSection && (Offset + SizeOfSection < BufferSize)) {
    03023             TriageDumpHeader->DriverListOffset = (ULONG)Offset;
    03024             TriageDumpHeader->DriverCount = DriverCount;
    03025             Offset += SizeOfSection;
    03026         }
    03027
    03028     } else {
    03029
    03030         SizeOfSection = 0;
    03031         SizeOfStringData = 0;
    03032     }
    03033
    03034     //
    03035     // Set the String Pool offset.
    03036     //
    03037
    03038     SizeOfSection = ALIGN_8 (SizeOfStringData +
    03039                         DriverCount * (sizeof (WCHAR) + sizeof (DUMP_STRING)));
    03040
    03041     if (SizeOfSection && (Offset + SizeOfSection < BufferSize)) {
    03042         TriageDumpHeader->StringPoolOffset = (ULONG)Offset;
    03043         TriageDumpHeader->StringPoolSize = SizeOfSection;
    03044         Offset += SizeOfSection;
    03045     }
    03046
    03047
    03048     BytesToWrite = (ULONG)Offset;
    03049     BufferAddress = ((ULONG_PTR) Buffer) - PAGE_SIZE ;
    03050
    03051     //
    03052     // Write the Mm information.
    03053     //
    03054
    03055     if (TriageDumpHeader->MmOffset) {
    03056
    03057         Address = (LPVOID) (BufferAddress + TriageDumpHeader->MmOffset);
    03058         MmWriteTriageInformation (Address);
    03059     }
    03060
    03061     if (TriageDumpHeader->UnloadedDriversOffset) {
    03062
    03063         Address = (LPVOID) (BufferAddress + TriageDumpHeader->UnloadedDriversOffset);
    03064         MmWriteUnloadedDriverInformation (Address);
    03065     }
    03066
    03067     //
    03068     // Write the PRCB.
    03069     //
    03070
    03071     if (TriageDumpHeader->PrcbOffset) {
    03072
    03073         Address = (LPVOID) (BufferAddress + TriageDumpHeader->PrcbOffset);
    03074         RtlCopyMemory (Address,
    03075                        KeGetCurrentPrcb (),
    03076                        sizeof (KPRCB)
    03077                        );
    03078     }
    03079
    03080     //
    03081     // Write the EPROCESS.
    03082     //
    03083
    03084     if (TriageDumpHeader->ProcessOffset) {
    03085
    03086         Address = (LPVOID) (BufferAddress + TriageDumpHeader->ProcessOffset);
    03087         RtlCopyMemory (Address,
    03088                        PsGetCurrentProcess (),
    03089                        sizeof (EPROCESS)
    03090                        );
    03091     }
    03092
    03093     //
    03094     // Write the ETHREAD.
    03095     //
    03096
    03097     if (TriageDumpHeader->ThreadOffset) {
    03098
    03099         Address = (LPVOID) (BufferAddress + TriageDumpHeader->ThreadOffset);
    03100         RtlCopyMemory (Address,
    03101                        KeGetCurrentThread (),
    03102                        sizeof (ETHREAD)
    03103                        );
    03104     }
    03105
    03106     //
    03107     // Write the Call Stack.
    03108     //
    03109
    03110     if (TriageDumpHeader->CallStackOffset) {
    03111
    03112         ASSERT (Thread);
    03113         ASSERT (TriageDumpHeader->SizeOfCallStack != 0);
    03114
    03115         Address = (LPVOID) (BufferAddress + TriageDumpHeader->CallStackOffset);
    03116         RtlCopyMemory (Address,
    03117                        (PVOID) StartOfStackRegion,
    03118                        TriageDumpHeader->SizeOfCallStack
    03119                        );
    03120     }
    03121
    03122     //
    03123     // Write the Driver List.
    03124     //
    03125
    03126     if (TriageDumpHeader->DriverListOffset &&
    03127         TriageDumpHeader->StringPoolOffset) {
    03128
    03129         Status = IopWriteDriverList (BufferAddress,
    03130                                      BufferSize,
    03131                                      TriageDumpHeader->DriverListOffset,
    03132                                      TriageDumpHeader->StringPoolOffset
    03133                                      );
    03134
    03135         if (!NT_SUCCESS (Status)) {
    03136             TriageDumpHeader->DriverListOffset = 0;
    03137         }
    03138     }
    03139
    03140     ASSERT (BytesToWrite < BufferSize);
    03141     ASSERT (ALIGN_UP (BytesToWrite, PAGE_SIZE) < BufferSize);
    03142
    03143     IoDebugPrint ((3, "TRIAGEDUMP: Calling IopWriteToDisk with:\n"
    03144                    "\tBytesToWrite = %#x\n"
    03145                    "\tBytesToWrite (Aligned) = %#x\n"
    03146                    "\tBufferSize = %#x\n",
    03147                     BytesToWrite,
    03148                     ALIGN_UP (BytesToWrite, PAGE_SIZE),
    03149                     BufferSize));
    03150
    03151
    03152     //
    03153     // Write the valid status to the end of the dump.
    03154     //
    03155
    03156     *((ULONG *)IndexByByte (Buffer, BufferSize)) = TRIAGE_DUMP_VALID ;
    03157
    03158     //
    03159     // Re-adjust the buffer size.
    03160     //
    03161
    03162     BufferSize += sizeof (DWORD);
    03163
    03164     //
    03165     // NOTE: This routine writes the entire buffer, even if it is not
    03166     // all required.
    03167     //
    03168
    03169     Status = IopWriteToDisk (Buffer,
    03170                              BufferSize,
    03171                              DriverWriteRoutine,
    03172                              &Mcb,
    03173                              Mdl,
    03174                              DriverTransferSize
    03175                              );
    03176
    03177     return Status;
    03178 }
    03179
    03180
    03181
    03182 NTSTATUS
    03183 IopWritePageToDisk(
    03184     IN PDUMP_DRIVER_WRITE DriverWrite,
    03185     IN OUT PLARGE_INTEGER * McbBuffer,
    03186     IN OUT ULONG DriverTransferSize,
    03187     IN PFN_NUMBER PageFrameIndex
    03188     )
    03189
    03190 /*++
    03191
    03192 Routine Description:
    03193
    03194     Write the page described by PageFrameIndex to the disk/file (DriverWrite,
    03195     McbBuffer) and update the MCB buffer to reflect the new position in the
    03196     file.
    03197
    03198 Arguments:
    03199
    03200     DriverWrite - The driver write routine.
    03201
    03202     McbBuffer - A pointer to the MCB array. This array is terminated by
    03203             a zero-length MCB entry. On success, this pointer is updated
    03204             to reflect the new position in the MCB array.
    03205
    03206             NB: MCB[0] is the size and MCB[1] is the offset.
    03207
    03208     DriverTransferSize - The maximum transfer size for this driver.
    03209
    03210     PageFrameIndex - The page to be written.
    03211
    03212 Return Values:
    03213
    03214     NTSTATUS code.
    03215
    03216 --*/
    03217
    03218 {
    03219     NTSTATUS Status;
    03220     PFN_NUMBER MdlHack [ (sizeof (MDL) / sizeof (PFN_NUMBER)) + 1];
    03221     PPFN_NUMBER PfnArray;
    03222     PLARGE_INTEGER Mcb;
    03223     ULONG ByteCount;
    03224     ULONG ByteOffset;
    03225     ULONG BytesToWrite;
    03226     PMDL TempMdl;
    03227
    03228
    03229     ASSERT ( DriverWrite );
    03230     ASSERT ( McbBuffer );
    03231     ASSERT ( DriverTransferSize && DriverTransferSize >= PAGE_SIZE );
    03232
    03233     //
    03234     // Initialization
    03235     //
    03236
    03237     TempMdl = (PMDL) &MdlHack;
    03238     Mcb = *McbBuffer;
    03239     BytesToWrite = PAGE_SIZE;
    03240
    03241
    03242     //
    03243     // Initialze the MDL to point to this page.
    03244     //
    03245
    03246     MmInitializeMdl (TempMdl, NULL, PAGE_SIZE);
    03247
    03248     PfnArray = MmGetMdlPfnArray ( TempMdl );
    03249     PfnArray[0] = PageFrameIndex;
    03250
    03251
    03252     //
    03253     // We loop for the cases when the space remaining in this block (Mcb [0])
    03254     // is less than one page. Generally the Mcb will be large enough to hold
    03255     // the entire page and this loop will only be executed once. When Mcb[0]
    03256     // is less than a page, we will write the first part of the page to this
    03257     // Mcb then increment the Mcb and write the remaining part to the next
    03258     // page.
    03259     //
    03260
    03261     ByteOffset = 0;
    03262
    03263     while ( BytesToWrite ) {
    03264
    03265         ASSERT ( Mcb[0].QuadPart != 0 );
    03266
    03267         ByteCount = (ULONG) min3 ((LONGLONG) BytesToWrite,
    03268                                   (LONGLONG) DriverTransferSize,
    03269                                   Mcb[0].QuadPart
    03270                                   );
    03271
    03272         ASSERT ( ByteCount != 0 );
    03273
    03274         //
    03275         // Update the MDL byte count and byte offset.
    03276         //
    03277
    03278         TempMdl->ByteCount = ByteCount;
    03279         TempMdl->ByteOffset = ByteOffset;
    03280
    03281         //
    03282         // Map the MDL. The flags are updated to show that MappedSsytemVa is
    03283         // valid, which should probably be done in MmMapMemoryDumpMdl.
    03284         //
    03285
    03286         MmMapMemoryDumpMdl ( TempMdl );
    03287         TempMdl->MdlFlags |= ( MDL_PAGES_LOCKED | MDL_MAPPED_TO_SYSTEM_VA );
    03288         TempMdl->StartVa = PAGE_ALIGN (TempMdl->MappedSystemVa);
    03289
    03290         Status = DriverWrite ( &Mcb[1], TempMdl );
    03291
    03292
    03293         if (!NT_SUCCESS (Status)) {
    03294             return Status;
    03295         }
    03296
    03297         BytesToWrite -= ByteCount;
    03298         ByteOffset += ByteCount;
    03299
    03300         Mcb[0].QuadPart -= ByteCount;
    03301         Mcb[1].QuadPart += ByteCount;
    03302
    03303
    03304         //
    03305         // If there is no more room for this MCB, go to the next one.
    03306         //
    03307
    03308         if ( Mcb[0].QuadPart == 0 ) {
    03309
    03310             Mcb += 2;
    03311
    03312             //
    03313             // We have filled up all the space in the paging file.
    03314             //
    03315
    03316             if ( Mcb[0].QuadPart == 0) {
    03317                 return STATUS_END_OF_FILE;
    03318             }
    03319         }
    03320     }
    03321
    03322     *McbBuffer = Mcb;
    03323
    03324     return Status;
    03325 }
    03326
    03327
    03328 NTSTATUS
    03329 IopWriteSummaryDump(
    03330     IN PRTL_BITMAP PageMap,
    03331     IN PDUMP_DRIVER_WRITE DriverWriteRoutine,
    03332     IN PANSI_STRING ProgressMessage,
    03333     IN PUCHAR MessageBuffer,
    03334     IN OUT PLARGE_INTEGER Mcb,
    03335     IN OUT ULONG DriverTransferSize
    03336     )
    03337
    03338 /*++
    03339
    03340 Routine Description:
    03341
    03342     Write a summary dump to the disk.
    03343
    03344 Arguments:
    03345
    03346
    03347     PageMap - A bitmap of the pages that need to be written.
    03348
    03349     DriverWriteRoutine - The driver's write routine.
    03350
    03351     ProgressMessage - The "Percent Complete" message.
    03352
    03353     MessageBuffer - A message buffer we can use to update percentage complete
    03354             status.
    03355
    03356     Mcb - Message Control Block where the data is to be written.
    03357
    03358     DriverTransferSize - The maximum transfer size for the driver.
    03359
    03360 Return Values:
    03361
    03362     NTSTATUS code.
    03363
    03364 --*/
    03365
    03366 {
    03367     PVOID Va;
    03368     PFN_NUMBER PageFrameIndex;
    03369     PHYSICAL_ADDRESS PhysicalAddress;
    03370     NTSTATUS Status;
    03371
    03372     ULONG WriteCount;
    03373     ULONG MaxWriteCount;
    03374     ULONG Step;
    03375
    03376
    03377     ASSERT ( DriverWriteRoutine != NULL );
    03378     ASSERT ( Mcb != NULL );
    03379     ASSERT ( DriverTransferSize != 0 );
    03380
    03381
    03382     MaxWriteCount = RtlNumberOfSetBits ( PageMap );
    03383     Step = MaxWriteCount / 100;
    03384
    03385     IoDebugPrint ((1, "IODUMP: Summary Dump\n"
    03386                      "  Writing %x pages to disk from a total of %x\n",
    03387                   MaxWriteCount,
    03388                   PageMap->SizeOfBitMap));
    03389
    03390     //
    03391     // Loop over all pages in the system and write those that are set
    03392     // in the bitmap.
    03393     //
    03394
    03395     WriteCount = 0;
    03396     for ( PageFrameIndex = 0;
    03397           PageFrameIndex < PageMap->SizeOfBitMap;
    03398           PageFrameIndex++) {
    03399
    03400
    03401         //
    03402         // If this page needs to be included in the dump file.
    03403         //
    03404
    03405         if ( RtlCheckBit (PageMap, PageFrameIndex) ) {
    03406
    03407             if (++WriteCount % Step == 0) {
    03408
    03409                 sprintf (MessageBuffer,
    03410                          "%Z: %3d\r",
    03411                          ProgressMessage,
    03412                          (WriteCount * 100) / MaxWriteCount);
    03413
    03414                 InbvDisplayString ( MessageBuffer );
    03415             }
    03416
    03417             ASSERT ( WriteCount <= MaxWriteCount );
    03418
    03419             //
    03420             // Write the page to disk.
    03421             //
    03422
    03423             Status = IopWritePageToDisk (
    03424                             DriverWriteRoutine,
    03425                             &Mcb,
    03426                             DriverTransferSize,
    03427                             PageFrameIndex
    03428                             );
    03429
    03430             if (!NT_SUCCESS (Status)) {
    03431
    03432                 return STATUS_UNSUCCESSFUL;
    03433             }
    03434         }
    03435     }
    03436
    03437     return STATUS_SUCCESS;
    03438 }
    03439
    03440
    03441 PSUMMARY_DUMP_HEADER
    03442 IopInitializeSummaryDump(
    03443     IN PDUMP_CONTROL_BLOCK pDcb
    03444     )
    03445 /*++
    03446
    03447 Routine Description:
    03448
    03449     This routine creates a summary dump header. In particular it initializes
    03450     a bitmap that contains a map of kernel memory.
    03451
    03452 Arguments:
    03453
    03454     PDUMP_CONTROL_BLOCK - A pointer to the dump control block.
    03455
    03456 Return Value:
    03457
    03458     Non-NULL - A pointer to the summary dump header
    03459
    03460     NULL - Error
    03461
    03462 --*/
    03463 {
    03464     PULONG                  pdwBlock;
    03465     PSUMMARY_DUMP_HEADER    pSummaryHeader;
    03466     ULONG                   dwActualPages;
    03467
    03468     //
    03469     // Get the dump header page.
    03470     //
    03471
    03472     pdwBlock = pDcb->HeaderPage;
    03473
    03474     //
    03475     // The summary dump starts 1 page after the header.
    03476     //
    03477
    03478     pSummaryHeader = (PSUMMARY_DUMP_HEADER)&pdwBlock[ DH_SUMMARY_DUMP_RECORD ];
    03479
    03480     //
    03481     // Fill the header with signatures.
    03482     //
    03483     RtlFillMemoryUlong( pSummaryHeader,
    03484                         sizeof(SUMMARY_DUMP_HEADER),
    03485                         'PMDS' );
    03486
    03487     //
    03488     // Set the size and valid signature.
    03489     //
    03490
    03491     pSummaryHeader->BitmapSize = (ULONG)( MmPhysicalMemoryBlock->Run[MmPhysicalMemoryBlock->NumberOfRuns-1].BasePage  +
    03492                                       MmPhysicalMemoryBlock->Run[MmPhysicalMemoryBlock->NumberOfRuns-1].PageCount );
    03493     pSummaryHeader->ValidDump = 'PMUD';
    03494
    03495     //
    03496     // Construct the kernel memory bitmap.
    03497     //
    03498
    03499     dwActualPages = IopCreateSummaryDump(pSummaryHeader);
    03500
    03501     IoDebugPrint((2,"[IopInitializeSummaryDump]: Kernel Pages = %x\n",dwActualPages));
    03502
    03503     if (!dwActualPages) {
    03504         return NULL;
    03505     }
    03506
    03507     //
    03508     // Set the actual number of physical pages in the summary dump
    03509     //
    03510
    03511     pSummaryHeader->Pages = dwActualPages;
    03512     pSummaryHeader->HeaderSize = pDcb->HeaderSize;
    03513
    03514     return pSummaryHeader;
    03515 }
    03516
    03517
    03518
    03519 NTSTATUS
    03520 IopWriteSummaryHeader(
    03521     IN PSUMMARY_DUMP_HEADER    pSummaryHeader,
    03522     IN PDUMP_DRIVER_WRITE      pfWrite,
    03523     IN OUT PLARGE_INTEGER *    McbBuffer,
    03524     IN OUT PMDL                pMdl,
    03525     IN ULONG                   dwWriteSize,
    03526     IN ULONG                   dwLength
    03527     )
    03528 /*++
    03529
    03530 Routine Description:
    03531
    03532     Write the summary dump header to the dump file.
    03533
    03534 Arguments:
    03535
    03536     pSummaryHeader - pointer to the summary dump bitmap
    03537
    03538     pfWrite - dump driver write function
    03539
    03540     McbBuffer - pointer to the MCB array.
    03541
    03542     pMdl - Pointer to an MDL
    03543
    03544     dwWriteSize - the max transfer size for the dump driver
    03545
    03546     dwLength - the length of this transfer
    03547
    03548 Return Value:
    03549
    03550     Updated MCB
    03551
    03552 --*/
    03553 {
    03554     NTSTATUS Status;
    03555     ULONG       dwBytesRemaining;
    03556     ULONG_PTR   dwMemoryAddress;
    03557     ULONG       dwByteOffset;
    03558     ULONG       dwByteCount;
    03559     PLARGE_INTEGER pMcb;
    03560
    03561     dwBytesRemaining = dwLength;
    03562     dwMemoryAddress = (ULONG_PTR) pSummaryHeader;
    03563     pMcb = *McbBuffer;
    03564
    03565     IoDebugPrint (( 0, "IoWriteCrashDump: Writing SUMMARY dump header to disk\n" ));
    03566
    03567     while (dwBytesRemaining) {
    03568
    03569         // Calculate byte offset
    03570         dwByteOffset = (ULONG)(dwMemoryAddress & (PAGE_SIZE - 1));
    03571
    03572         //
    03573         // See if the number of bytes to write is greator than the crash
    03574         // drives max transfer.
    03575         //
    03576
    03577         if (dwBytesRemaining <= dwWriteSize) {
    03578             dwByteCount = dwBytesRemaining;
    03579         } else {
    03580             dwByteCount = dwWriteSize;
    03581         }
    03582
    03583         //
    03584         // If the byteCount is greater than the remaining mcb then correct it.
    03585         //
    03586
    03587         if (dwByteCount > pMcb[0].QuadPart) {
    03588             dwByteCount = pMcb[0].LowPart;
    03589         }
    03590
    03591         pMdl->ByteCount      = dwByteCount;
    03592         pMdl->ByteOffset     = dwByteOffset;
    03593         pMdl->MappedSystemVa = (PVOID) dwMemoryAddress;
    03594
    03595         //
    03596         // Get the actual physical frame and create an mdl.
    03597         //
    03598
    03599         IopMapVirtualToPhysicalMdl(pMdl, dwMemoryAddress, dwByteCount);
    03600
    03601         //
    03602         // Write to disk.
    03603         //
    03604         Status = pfWrite( &pMcb[1], pMdl );
    03605
    03606         if ( !NT_SUCCESS (Status) ) {
    03607             return Status;
    03608         }
    03609
    03610         //
    03611         // Adjust bytes remaining.
    03612         //
    03613
    03614         dwBytesRemaining -= dwByteCount;
    03615         dwMemoryAddress  += dwByteCount;
    03616
    03617         pMcb[0].QuadPart = pMcb[0].QuadPart - dwByteCount;
    03618         pMcb[1].QuadPart = pMcb[1].QuadPart + dwByteCount;
    03619
    03620         if (pMcb[0].QuadPart == 0) {
    03621             pMcb += 2;
    03622         }
    03623
    03624         if (pMcb[0].QuadPart == 0) {
    03625             return STATUS_END_OF_FILE;
    03626         }
    03627     }
    03628
    03629     IoDebugPrint((2, "IoWriteCrashDump: Writing SUMMARY dump header to disk\n" ));
    03630
    03631     *McbBuffer = pMcb;
    03632     return STATUS_SUCCESS;
    03633 }
    03634
    03635
    03636
    03637 NTSTATUS
    03638 IopWriteToDisk(
    03639     IN PVOID Buffer,
    03640     IN ULONG WriteLength,
    03641     IN PDUMP_DRIVER_WRITE DriverWriteRoutine,
    03642     IN OUT PLARGE_INTEGER * McbBuffer,
    03643     IN OUT PMDL Mdl,
    03644     IN ULONG DriverTransferSize
    03645     )
    03646 /*++
    03647
    03648 Routine Description:
    03649
    03650     Write the summary dump header to the dump file.
    03651
    03652 Arguments:
    03653
    03654     Buffer - Pointer to the buffer to write.
    03655
    03656     WriteLength - The length of this transfer.
    03657
    03658     DriverWriteRoutine - Dump driver write function.
    03659
    03660     McbBuffer - Pointer to the dump file Mapped Control Block.
    03661
    03662     Mdl - Pointer to an MDL.
    03663
    03664     DriverTransferSize - The max transfer size for the dump driver.
    03665
    03666
    03667 Return Value:
    03668
    03669
    03670 --*/
    03671 {
    03672     ULONG dwBytesRemaining;
    03673     ULONG_PTR dwMemoryAddress;
    03674     ULONG dwByteOffset;
    03675     ULONG dwByteCount;
    03676     PLARGE_INTEGER Mcb;
    03677
    03678     ASSERT (Buffer);
    03679     ASSERT (WriteLength);
    03680     ASSERT (DriverWriteRoutine);
    03681     ASSERT (McbBuffer && *McbBuffer);
    03682     ASSERT (Mdl);
    03683     ASSERT (DriverTransferSize >= IO_DUMP_MINIMUM_TRANSFER_SIZE &&
    03684             DriverTransferSize <= IO_DUMP_MAXIMUM_TRANSFER_SIZE);
    03685
    03686
    03687     Mcb = *McbBuffer;
    03688     dwBytesRemaining = WriteLength;
    03689     dwMemoryAddress = (ULONG_PTR) Buffer;
    03690
    03691     IoDebugPrint(( 2, "IoWriteToDisk: Writing %d bytes to disk.\n", WriteLength ));
    03692
    03693     while (dwBytesRemaining) {
    03694
    03695         ASSERT (Mcb [0].QuadPart != 0);
    03696         ASSERT (IopDumpControlBlock->FileDescriptorArray <= Mcb &&
    03697                 (LPBYTE) Mcb < (LPBYTE) IopDumpControlBlock->FileDescriptorArray +
    03698                                IopDumpControlBlock->FileDescriptorSize
    03699                 );
    03700
    03701         dwByteOffset = BYTE_OFFSET (dwMemoryAddress);
    03702
    03703         //
    03704         // See if the number of bytes to write is greator than the crash
    03705         // drives max transfer.
    03706         //
    03707
    03708         dwByteCount = min ( dwBytesRemaining, DriverTransferSize );
    03709
    03710         //
    03711         // If the byteCount is greater than the remaining mcb then correct it.
    03712         //
    03713
    03714         if (dwByteCount > Mcb[0].QuadPart) {
    03715             dwByteCount = Mcb[0].LowPart;
    03716         }
    03717
    03718         Mdl->ByteCount = dwByteCount;
    03719         Mdl->ByteOffset = dwByteOffset;
    03720         Mdl->MappedSystemVa = (PVOID) dwMemoryAddress;
    03721
    03722         //
    03723         // Get the actual physical frame and create an mdl.
    03724         //
    03725
    03726         IopMapVirtualToPhysicalMdl(Mdl, dwMemoryAddress, dwByteCount);
    03727
    03728         if (!NT_SUCCESS( DriverWriteRoutine ( &Mcb[1], Mdl ) )) {
    03729             IoDebugPrint ((1, "IopWriteToDisk: Failed write.\n"));
    03730             return STATUS_UNSUCCESSFUL;
    03731         }
    03732
    03733         //
    03734         // Adjust bytes remaining.
    03735         //
    03736
    03737         ASSERT (dwBytesRemaining >= dwByteCount);
    03738         ASSERT (dwByteCount != 0);
    03739
    03740         dwBytesRemaining -= dwByteCount;
    03741         dwMemoryAddress  += dwByteCount;
    03742
    03743         Mcb[0].QuadPart -= dwByteCount;
    03744         Mcb[1].QuadPart += dwByteCount;
    03745
    03746         if (Mcb[0].QuadPart == 0) {
    03747             Mcb += 2;
    03748         }
    03749     }
    03750
    03751     IoDebugPrint ((2, "IopWriteToDisk: Successfully wrote %d bytes.\n", WriteLength));
    03752
    03753     *McbBuffer = Mcb;
    03754     return STATUS_SUCCESS;
    03755 }
    03756
    03757
    03758 VOID
    03759 IopMapVirtualToPhysicalMdl(
    03760     IN OUT PMDL pMdl,
    03761     IN ULONG_PTR dwMemoryAddress,
    03762     IN ULONG    dwLength
    03763     )
    03764 {
    03765     PPFN_NUMBER  pdwPage;
    03766     ULONG   dwPages;
    03767     ULONG   dwBase;
    03768     ULONG   dwCurrentBase;
    03769     ULONG_PTR dwBaseVa;
    03770     PHYSICAL_ADDRESS PhysicalAddress;
    03771
    03772     //
    03773     // Begin by determining the base physical page of the start of the address
    03774     // range and filling in the MDL appropriately.
    03775     //
    03776
    03777     pMdl->StartVa = PAGE_ALIGN((PVOID)dwMemoryAddress);
    03778     pMdl->ByteOffset= (ULONG)(dwMemoryAddress & (PAGE_SIZE - 1));
    03779     pMdl->ByteCount = dwLength;
    03780     dwBaseVa = dwMemoryAddress & ~(PAGE_SIZE -1);
    03781     pMdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
    03782
    03783     //
    03784     // Compute the number of pages spanned
    03785     //
    03786
    03787     dwPages = COMPUTE_PAGES_SPANNED( dwMemoryAddress, dwLength );
    03788     pdwPage = MmGetMdlPfnArray(pMdl);
    03789
    03790     //
    03791     // Map all of the pages for this transfer until there are no more remaining
    03792     // to be mapped.
    03793     //
    03794     IoDebugPrint((3,"MapVirtualToPhysical: VA: %08x off: %08x Len:%08x base: %08x \n",pMdl->StartVa,pMdl->ByteOffset,pMdl->ByteCount,dwBaseVa));
    03795
    03796     while (dwPages) {
    03797         PhysicalAddress = MmGetPhysicalAddress( (PVOID)dwBaseVa );
    03798         IoDebugPrint( (3,"Physical Frame: %08x Adr: %08x\n",( PhysicalAddress.QuadPart >> PAGE_SHIFT),dwBaseVa ) );
    03799         *pdwPage++  = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
    03800         dwBaseVa    +=PAGE_SIZE;
    03801         dwPages--;
    03802     }
    03803
    03804     //
    03805     // All of the PFNs for the address range have been filled in so map the
    03806     // physical memory into virtual address space using crash dump PTE.
    03807     //
    03808
    03809 //    MmMapMemoryDumpMdl( pMdl );
    03810 }
    03811
    03812
    03813
    03814 ULONG
    03815 IopCreateSummaryDump (
    03816     IN PSUMMARY_DUMP_HEADER pHeader
    03817     )
    03818 /*++
    03819
    03820 Routine Description:
    03821
    03822     This routine determines the kernel memory and data structures to include
    03823     in the summary memory dump.
    03824
    03825     NOTE: This function uses MmGetPhysicalAddress. MmGetPhysicalAddress does
    03826     not acquire any locks. It uses a set of macros for translation.
    03827
    03828
    03829 Arguments:
    03830
    03831     pHeader - Pointer to the dump header
    03832
    03833     pDcb - Dump control block
    03834
    03835 Return Value:
    03836
    03837     Status
    03838
    03839 --*/
    03840 {
    03841     PRTL_BITMAP             pBitMapHeader = (PRTL_BITMAP)(pHeader+1);
    03842     ULONG                   Pages;
    03843     PCHAR                   VA;
    03844     ULONG                   UserPages;
    03845     PHYSICAL_ADDRESS        PhyAddr;
    03846     ULONG                   i;
    03847     PULONG                  pBitMapBuffer;
    03848     PUCHAR                  pBitMapBytes;
    03849     LARGE_INTEGER           dumpFileSize;
    03850     PULONG                  block;
    03851     ULONG                   numDumpPages;
    03852
    03853     //
    03854     // The bitmap is the last structure in the header. The
    03855     // buffer is allocated directly after the bitmap header.
    03856     //
    03857     // Initialize Bit Map, set the size and buffer address.
    03858     //
    03859
    03860     pBitMapHeader->SizeOfBitMap = pHeader->BitmapSize;
    03861     pBitMapBuffer = (PULONG)( pBitMapHeader + 1);
    03862     pBitMapHeader->Buffer = pBitMapBuffer;
    03863     pBitMapBytes = (PUCHAR)pBitMapBuffer;
    03864
    03865     //
    03866     // Clear all bits
    03867     //
    03868
    03869     RtlClearAllBits (pBitMapHeader);
    03870
    03871     //
    03872     // Have MM initialize the kernel memory to dump
    03873     //
    03874
    03875     MmSetKernelDumpRange(pHeader);
    03876
    03877     //
    03878     // Exclude non-existent memory
    03879     //
    03880
    03881     IopDeleteNonExistentMemory(pHeader, MmPhysicalMemoryBlock);
    03882
    03883
    03884     Pages = RtlNumberOfSetBits ( pBitMapHeader );
    03885     IoDebugPrint((2,"IopLocalSetBits =       %x\n",Pages));
    03886
    03887     //
    03888     // See If we have room to Include user va for the current process
    03889     //
    03890
    03891     block = IopDumpControlBlock->HeaderPage;
    03892     dumpFileSize.LowPart= block [DH_REQUIRED_DUMP_SPACE];
    03893     dumpFileSize.HighPart= block [DH_REQUIRED_DUMP_SPACE + 1];
    03894
    03895     dumpFileSize.QuadPart -= IopDumpControlBlock->HeaderSize;
    03896
    03897     //
    03898     // Total physical pages will not exceed 2<<32 for sometime
    03899     //
    03900
    03901     numDumpPages= (ULONG)(dumpFileSize.QuadPart >> PAGE_SHIFT);
    03902     IoDebugPrint ((2,"IopCreateSummaryDump: numDumpPages: %x Pages : %x\n", numDumpPages,Pages));
    03903
    03904     //
    03905     // Only copy user virtual if there is enough room in the dump file.
    03906     //
    03907
    03908     UserPages = 0;
    03909
    03910     if (Pages < numDumpPages ) {
    03911
    03912         //
    03913         // Stride through user VA and include all valid pages
    03914         //
    03915
    03916         for (VA = 0; VA < (PCHAR)MmHighestUserAddress; VA+=PAGE_SIZE ) {
    03917
    03918             if ( MmIsAddressValid( VA ) ) {
    03919
    03920                 if ( NT_SUCCESS(IoSetDumpRange(pHeader,VA, 1, FALSE ) ) ) {
    03921
    03922                     UserPages++;
    03923
    03924                     //
    03925                     // Break if there is no more room in the dump file
    03926                     //
    03927
    03928                     if (UserPages+Pages >= numDumpPages ) {
    03929                         break;
    03930                     }
    03931                 }
    03932             }
    03933         }
    03934
    03935     }
    03936
    03937     Pages+= UserPages;
    03938
    03939     IoDebugPrint((2,"IopCreateSummaryDump number of user mode pages = %x\n",UserPages));
    03940
    03941     IoDebugPrint((2, "SummaryDump: Dump SummaryDumpHeader\n"));
    03942     IoDebugPrint((2, "SdBitmapSize      =%x\n", pHeader->BitmapSize));
    03943     IoDebugPrint((2, "SdAllBits         =%x\n", Pages));
    03944     IoDebugPrint((2, "&SdBitmapBuffer[0]=%x\n", pBitMapHeader->Buffer));
    03945
    03946
    03947     return Pages;
    03948
    03949 }
    03950
    03951
    03952 VOID
    03953 IopDeleteNonExistentMemory(
    03954     PSUMMARY_DUMP_HEADER pHeader,
    03955     PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
    03956     )
    03957 /*++
    03958
    03959 Routine Description:
    03960
    03961     This deletes non existent memory. Non existent memory is defined as the
    03962     unassigned memory between memory runs. For example, memory between
    03963     (run[0].base + size) and run[1].base.
    03964
    03965 Arguments:
    03966
    03967     pHeader - This is a pointer to the summary dump header.
    03968
    03969     dwStartingIndex - The starting bit index in the bitmap (starting page).
    03970
    03971     dwMemoryAddress - Pseudo-virtual address being mapped.
    03972
    03973     dwByteCount - The number of bytes to copy.
    03974
    03975     dwMaxBitmapBit - The limit or the highest possible valid bit in the bitmap.
    03976
    03977     pMdl - The MDL to create.
    03978
    03979 Return Value:
    03980
    03981     (none)
    03982
    03983 --*/
    03984 {
    03985     PPHYSICAL_MEMORY_RUN    Run;
    03986     ULONG                   NumberOfRuns;
    03987     ULONG                   i;
    03988     PFN_NUMBER              CurrentPageFrame, NextPageFrame;
    03989     PRTL_BITMAP             pBitMapHeader;
    03990
    03991     NumberOfRuns            = MmPhysicalMemoryBlock->NumberOfRuns;
    03992
    03993     Run = &MmPhysicalMemoryBlock->Run[0];
    03994
    03995     pBitMapHeader = (PRTL_BITMAP)(pHeader + 1);
    03996     i = 0;
    03997
    03998     CurrentPageFrame = 1;
    03999
    04000     NextPageFrame = Run->BasePage;
    04001
    04002     //
    04003     // Remove the gap from 0 till the first run.
    04004     //
    04005
    04006     if (NextPageFrame > CurrentPageFrame) {
    04007
    04008         IoDebugPrint( (2,"DeleteNonExistentMemory: %x - %x\n",
    04009             CurrentPageFrame,
    04010             (NextPageFrame - CurrentPageFrame) ) );
    04011
    04012         //
    04013         // FIXFIX - handle page frame numbers greater than 32 bits.
    04014         //
    04015
    04016         IopRemovePageFromPageMap (pHeader->BitmapSize,
    04017                                   pBitMapHeader,
    04018                                   (ULONG)CurrentPageFrame,
    04019                                   (ULONG)(NextPageFrame-CurrentPageFrame)
    04020                                   );
    04021
    04022     }
    04023
    04024     //
    04025     // Remove the gaps between runs.
    04026     //
    04027
    04028     while (i < NumberOfRuns - 1) {
    04029
    04030         CurrentPageFrame = Run->BasePage + Run->PageCount;
    04031         IoDebugPrint((2, "Run[%x]: Base=%x, Pages=%x\n", i, Run->BasePage, Run->PageCount));
    04032
    04033         i++;
    04034         Run++;
    04035
    04036         //
    04037         // Get the next starting BasePage.
    04038         //
    04039
    04040         NextPageFrame = Run->BasePage;
    04041
    04042         if (NextPageFrame != CurrentPageFrame) {
    04043
    04044             IoDebugPrint((2, "DeleteNonExistentMemory: %x - %x\n", NextPageFrame, CurrentPageFrame));
    04045
    04046             //
    04047             // FIXFIX - handle page frame numbers greater than 32 bits.
    04048             //
    04049
    04050             IopRemovePageFromPageMap (pHeader->BitmapSize,
    04051                                       pBitMapHeader,
    04052                                       (ULONG)CurrentPageFrame,
    04053                                       (ULONG)(NextPageFrame - CurrentPageFrame)
    04054                                       );
    04055         }
    04056     }
    04057 }
    04058
    04059
    04060 NTSTATUS
    04061 IopCompleteDumpInitialization(
    04062     IN HANDLE     FileHandle
    04063     )
    04064
    04065 /*++
    04066
    04067 Routine Description:
    04068
    04069     This routine is invoked after the dump file is created.
    04070
    04071     The purpose is to obtain the retrieval pointers so that they can then be
    04072     used later to write the dump. The last step is to checksum the
    04073     IopDumpControlBlock.
    04074
    04075     Fields in the IopDumpControlBlock are updated if necessary and the
    04076     IopDumpControlBlockChecksum is initialized.
    04077
    04078     This is the final step in dump initialization.
    04079
    04080 Arguments:
    04081
    04082     FileHandle - Handle to the dump file just created.
    04083
    04084 Return Value:
    04085
    04086     STATUS_SUCCESS - Indicates success.
    04087
    04088     Other NTSTATUS - Failure.
    04089
    04090 --*/
    04091
    04092 {
    04093     NTSTATUS Status;
    04094     NTSTATUS ErrorToLog;
    04095     ULONG i;
    04096     LARGE_INTEGER RequestedFileSize;
    04097     PLARGE_INTEGER mcb;
    04098     PFILE_OBJECT FileObject;
    04099     PDEVICE_OBJECT DeviceObject;
    04100     IO_STATUS_BLOCK IoStatusBlock;
    04101     FILE_STANDARD_INFORMATION StandardFileInfo;
    04102
    04103     Status = STATUS_UNSUCCESSFUL;
    04104     ErrorToLog = STATUS_SUCCESS;    // No error
    04105     FileObject = NULL;
    04106     DeviceObject = NULL;
    04107
    04108     Status = ObReferenceObjectByHandle( FileHandle,
    04109                                         0,
    04110                                         IoFileObjectType,
    04111                                         KernelMode,
    04112                                         (PVOID *) &FileObject,
    04113                                         NULL
    04114                                         );
    04115
    04116     if ( !NT_SUCCESS (Status) ) {
    04117         ASSERT (FALSE);
    04118         goto Cleanup;
    04119     }
    04120
    04121
    04122     DeviceObject = FileObject->DeviceObject;
    04123
    04124     //
    04125     // If this device object represents the boot partition then query
    04126     // the retrieval pointers for the file.
    04127     //
    04128
    04129     if ( !(DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION) ) {
    04130
    04131         KdPrint (("IODUMP: Cannot dump to pagefile on non-system partition.\n"));
    04132         goto Cleanup;
    04133     }
    04134
    04135     Status = ZwQueryInformationFile(
    04136                                 FileHandle,
    04137                                 &IoStatusBlock,
    04138                                 &StandardFileInfo,
    04139                                 sizeof (StandardFileInfo),
    04140                                 FileStandardInformation
    04141                                 );
    04142
    04143     if (Status == STATUS_PENDING) {
    04144         Status = KeWaitForSingleObject( &FileObject->Event,
    04145                                         Executive,
    04146                                         KernelMode,
    04147                                         FALSE,
    04148                                         NULL
    04149                                         );
    04150         Status = IoStatusBlock.Status;
    04151     }
    04152
    04153     if ( !NT_SUCCESS (Status) ) {
    04154         KdPrint (("CRASHDUMP: Failed ZwQueryInformationFile\n"));
    04155         goto Cleanup;
    04156     }
    04157
    04158     //
    04159     // Do not ask for more space than is in the pagefile.
    04160     //
    04161
    04162     RequestedFileSize = IopDumpControlBlock->DumpFileSize;
    04163
    04164     if (RequestedFileSize.QuadPart > StandardFileInfo.EndOfFile.QuadPart) {
    04165         RequestedFileSize = StandardFileInfo.EndOfFile;
    04166     }
    04167
    04168     Status = ZwFsControlFile(
    04169                         FileHandle,
    04170                         NULL,
    04171                         NULL,
    04172                         NULL,
    04173                         &IoStatusBlock,
    04174                         FSCTL_QUERY_RETRIEVAL_POINTERS,
    04175                         &RequestedFileSize,
    04176                         sizeof( LARGE_INTEGER ),
    04177                         &mcb,
    04178                         sizeof( PVOID )
    04179                         );
    04180
    04181     if (Status == STATUS_PENDING) {
    04182         Status = KeWaitForSingleObject( &FileObject->Event,
    04183                                         Executive,
    04184                                         KernelMode,
    04185                                         FALSE,
    04186                                         NULL );
    04187         Status = IoStatusBlock.Status;
    04188     }
    04189
    04190
    04191     //
    04192     // NOTE: If you fail here, put a BP on ntfs!NtfsQueryRetrievalPointers
    04193     // or FatQueryRetrievalPointers and see why you failed.
    04194     //
    04195
    04196     if ( !NT_SUCCESS (Status) ) {
    04197         KdPrint (("CRASHDUMP: ZwFsControlFile returnd %d\n", Status));
    04198         ErrorToLog = IO_DUMP_POINTER_FAILURE;
    04199         goto Cleanup;
    04200     }
    04201
    04202     //
    04203     // This paging file is on the system boot partition, and
    04204     // the retrieval pointers for the file were just successfully
    04205     // queried.  Walk the MCB to size it, and then checksum it.
    04206     //
    04207
    04208     for (i = 0; mcb [i].QuadPart; i++) {
    04209         NOTHING;
    04210     }
    04211
    04212     //
    04213     // Write back fields of the IopDumpControlBlock.
    04214     //
    04215
    04216     IopDumpControlBlock->FileDescriptorArray = mcb;
    04217     IopDumpControlBlock->FileDescriptorSize = (i + 1) * sizeof (LARGE_INTEGER);
    04218     IopDumpControlBlock->DumpFileSize = RequestedFileSize;
    04219     IopDumpControlBlockChecksum = IopGetDumpControlBlockCheck ( IopDumpControlBlock );
    04220
    04221     Status = STATUS_SUCCESS;
    04222
    04223 Cleanup:
    04224
    04225     if (Status != STATUS_SUCCESS &&
    04226         ErrorToLog != STATUS_SUCCESS ) {
    04227
    04228         IopLogErrorEvent (0,
    04229                           4,
    04230                           STATUS_SUCCESS,
    04231                           ErrorToLog,
    04232                           0,
    04233                           NULL,
    04234                           0,
    04235                           NULL
    04236                           );
    04237     }
    04238
    04239     DeviceObject = NULL;
    04240
    04241     if ( FileObject ) {
    04242         ObDereferenceObject( FileObject );
    04243         FileObject = NULL;
    04244     }
    04245
    04246     return Status;
    04247
    04248 }
    04249
    04250
    04251 VOID
    04252 IopFreeDCB(
    04253     BOOLEAN FreeDCB
    04254     )
    04255
    04256 /*++
    04257
    04258 Routine Description:
    04259
    04260     Free dump control block storage.
    04261
    04262 Arguments:
    04263
    04264     FreeDCB - Implictly free storage for the dump control block.
    04265
    04266 Return Value:
    04267
    04268     None
    04269
    04270 --*/
    04271 {
    04272     PDUMP_CONTROL_BLOCK dcb;
    04273     NTSTATUS            dwStatus;
    04274     BOOLEAN             ShouldFreeDCB;
    04275
    04276     dcb = IopDumpControlBlock;
    04277
    04278
    04279     if (dcb) {
    04280
    04281         if (dcb->MemoryDescriptor) {
    04282              ExFreePool (dcb->MemoryDescriptor);
    04283              dcb->MemoryDescriptor      = NULL;
    04284         }
    04285
    04286         if (dcb->HeaderPage) {
    04287             ExFreePool (dcb->HeaderPage);
    04288             dcb->HeaderPage             = NULL;
    04289         }
    04290
    04291         if (dcb->FileDescriptorArray) {
    04292             ExFreePool (dcb->FileDescriptorArray);
    04293             dcb->FileDescriptorArray    = NULL;
    04294         }
    04295
    04296         if (dcb->DumpStack) {
    04297             IoFreeDumpStack (dcb->DumpStack);
    04298             dcb->DumpStack              = NULL;
    04299         }
    04300
    04301         ShouldFreeDCB = FreeDCB | !( dcb->Flags & DCB_AUTO_REBOOT);
    04302
    04303         //
    04304         // Disable all options that require dump file access
    04305         //
    04306
    04307         dcb->Flags = dcb->Flags & DCB_AUTO_REBOOT;
    04308
    04309         IoDebugPrint((2,"[IopFreeDCB] Should Free DCB = %s\n",(ShouldFreeDCB ? "TRUE" : "FALSE")));
    04310
    04311         if (ShouldFreeDCB) {
    04312             IopDumpControlBlock = NULL;
    04313             ExFreePool( dcb );
    04314             IoDebugPrint((2,"[IopFreeDCB]: Freeing Dump Control Block\n"));
    04315         }
    04316     }
    04317
    04318     IoDebugPrint((2,"[IopFreeDCB]: CRASH DUMP DISABLED\n"));
    04319
    04320 }
    04321
    04322
    04323
    04324 NTSTATUS
    04325 IoSetCrashDumpState(
    04326     IN SYSTEM_CRASH_STATE_INFORMATION *pDumpState
    04327     )
    04328
    04329 /*++
    04330
    04331 Routine Description:
    04332
    04333     Disable the current crash dump. Optionally, configure a new crash dump.
    04334
    04335 Arguments:
    04336
    04337     pDumpState - If ValidDirectDump = TRUE  enable a new dump
    04338                                       FALSE Disable crash dump
    04339
    04340 Return Value:
    04341
    04342     STATUS_SUCCESS - The operation was successful
    04343
    04344     W32ERROR - Otherwise
    04345
    04346 --*/
    04347 {
    04348     NTSTATUS    Status;
    04349     ULONG       crashConfigurationInProgress;
    04350
    04351     //
    04352     // Check the sentinal
    04353     //
    04354
    04355     crashConfigurationInProgress = InterlockedExchange(&IopCrashDumpStateChange,1);
    04356
    04357     if (crashConfigurationInProgress) {
    04358         return STATUS_SUCCESS;
    04359     }
    04360
    04361     //
    04362     // If crash dumps disabled return success
    04363     //
    04364
    04365     if (!pDumpState->ValidDirectDump) {
    04366         IopFreeDCB(FALSE);
    04367         Status = STATUS_SUCCESS;
    04368     } else {
    04369         Status = STATUS_INVALID_DEVICE_REQUEST;
    04370     }
    04371
    04372     InterlockedExchange(&IopCrashDumpStateChange,0);
    04373
    04374     return Status;
    04375 }
    04376
    04377
    04378 VOID
    04379 IopReadDumpRegistry(
    04380     OUT PULONG dumpControl,
    04381     OUT PULONG numberOfHeaderPages,
    04382     OUT PULONG autoReboot,
    04383     OUT PULONG dumpFileSize
    04384     )
    04385 /*++
    04386
    04387 Routine Description:
    04388
    04389     This routine reads the dump parameters from the registry.
    04390
    04391 Arguments:
    04392
    04393     dumpControl - Supplies a pointer to the dumpControl flags to set.
    04394
    04395 Return Value:
    04396
    04397     None.
    04398
    04399 --*/
    04400
    04401 {
    04402     HANDLE                      keyHandle;
    04403     HANDLE                      crashHandle;
    04404     LOGICAL                     crashHandleOpened;
    04405     UNICODE_STRING              keyName;
    04406     NTSTATUS                    status;
    04407     PKEY_VALUE_FULL_INFORMATION keyValueInformation;
    04408     PDUMP_CONTROL_BLOCK         dcb;
    04409     ULONG                       handleValue;
    04410
    04411     *dumpControl = 0;
    04412     *autoReboot = 0;
    04413     *dumpFileSize = 0;
    04414
    04415     *numberOfHeaderPages = 1;       // Dump header
    04416
    04417     //
    04418     // Begin by opening the path to the control for dumping memory.  Note
    04419     // that if it does not exist, then no dumps will occur.
    04420     //
    04421
    04422     crashHandleOpened = FALSE;
    04423
    04424     RtlInitUnicodeString( &keyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control" );
    04425
    04426     status = IopOpenRegistryKey( &keyHandle,
    04427                                  (HANDLE) NULL,
    04428                                  &keyName,
    04429                                  KEY_READ,
    04430                                  FALSE );
    04431
    04432     if (!NT_SUCCESS( status )) {
    04433         return;
    04434     }
    04435
    04436     RtlInitUnicodeString( &keyName, L"CrashControl" );
    04437     status = IopOpenRegistryKey( &crashHandle,
    04438                                  keyHandle,
    04439                                  &keyName,
    04440                                  KEY_READ,
    04441                                  FALSE );
    04442
    04443     NtClose( keyHandle );
    04444
    04445     if (!NT_SUCCESS( status )) {
    04446         return;
    04447     }
    04448
    04449     crashHandleOpened = TRUE;
    04450
    04451     //
    04452     // Now get the value of the crash control to determine whether or not
    04453     // dumping is enabled.
    04454     //
    04455
    04456     status = IopGetRegistryValue( crashHandle,
    04457                                   L"CrashDumpEnabled",
    04458                                   &keyValueInformation );
    04459
    04460     if (NT_SUCCESS (status)) {
    04461
    04462         if (keyValueInformation->DataLength) {
    04463
    04464             handleValue = * ((PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset));
    04465             ExFreePool( keyValueInformation );
    04466
    04467             if (handleValue) {
    04468
    04469                 *dumpControl |= DCB_DUMP_ENABLED;
    04470
    04471                 //
    04472                 // If handleValue equals summary dump or the amount of physical
    04473                 // memory is greater than 2GB, then enable summary dump
    04474                 //
    04475
    04476                 if ( handleValue == 3 ) {
    04477
    04478                     *dumpControl |= DCB_TRIAGE_DUMP_ENABLED;
    04479
    04480                 } else if ( handleValue == 4 ) {
    04481
    04482                     *dumpControl |= ( DCB_TRIAGE_DUMP_ENABLED | DCB_TRIAGE_DUMP_ACT_UPON_ENABLED );
    04483
    04484                 } else if ( ( handleValue == 2 ) ||
    04485                      ( MmPhysicalMemoryBlock->NumberOfPages >= ( 0x80000000 >> PAGE_SHIFT ) ) ) {
    04486
    04487                     *dumpControl |= DCB_SUMMARY_DUMP_ENABLED;
    04488
    04489                     IoDebugPrint((2,"IopInitializeDCB: SUMMARY DUMP ENABLED \n"));
    04490
    04491                     //
    04492                     // Allocate enough storage for the dump header, summary
    04493                     // dump header and bitmap.
    04494                     //
    04495
    04496                     *numberOfHeaderPages = BYTES_TO_PAGES(
    04497                                             PAGE_SIZE +
    04498                                             ( ( MmPhysicalMemoryBlock->NumberOfPages >> 5) << 2 ) +
    04499                                             sizeof(SUMMARY_DUMP_HEADER)
    04500                                             );
    04501
    04502                     IoDebugPrint((2,"IopInitializeDCB: NumberOfHeader Pages = %x\n",numberOfHeaderPages));
    04503
    04504                 }
    04505             }
    04506         }
    04507     }
    04508
    04509     status = IopGetRegistryValue( crashHandle,
    04510                                   L"LogEvent",
    04511                                   &keyValueInformation );
    04512
    04513     if (NT_SUCCESS( status )) {
    04514          if (keyValueInformation->DataLength) {
    04515             handleValue = * ((PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset));
    04516             ExFreePool( keyValueInformation);
    04517             if (handleValue) {
    04518                 *dumpControl |= DCB_SUMMARY_ENABLED;
    04519             }
    04520         }
    04521     }
    04522
    04523     status = IopGetRegistryValue( crashHandle,
    04524                                   L"SendAlert",
    04525                                   &keyValueInformation );
    04526
    04527     if (NT_SUCCESS( status )) {
    04528          if (keyValueInformation->DataLength) {
    04529             handleValue = * ((PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset));
    04530             ExFreePool( keyValueInformation);
    04531             if (handleValue) {
    04532                 *dumpControl |= DCB_SUMMARY_ENABLED;
    04533             }
    04534         }
    04535     }
    04536
    04537     //
    04538     // Now determine whether or not automatic reboot is enabled.
    04539     //
    04540
    04541     status = IopGetRegistryValue( crashHandle,
    04542                                   L"AutoReboot",
    04543                                   &keyValueInformation );
    04544
    04545
    04546     if (NT_SUCCESS( status )) {
    04547         if (keyValueInformation->DataLength) {
    04548             *autoReboot = * ((PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset));
    04549         }
    04550         ExFreePool( keyValueInformation );
    04551     }
    04552
    04553     //
    04554     // If we aren't auto rebooting or crashing then return now.
    04555     //
    04556
    04557     if (*dumpControl == 0 && *autoReboot == 0) {
    04558         if (crashHandleOpened == TRUE) {
    04559             NtClose( crashHandle );
    04560         }
    04561         return;
    04562     }
    04563
    04564     status = IopGetRegistryValue( crashHandle,
    04565                                   L"DumpFileSize",
    04566                                   &keyValueInformation );
    04567
    04568     if (NT_SUCCESS( status )) {
    04569         if (keyValueInformation->DataLength) {
    04570             *dumpFileSize = * ((PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset));
    04571         }
    04572
    04573         ExFreePool( keyValueInformation );
    04574     }
    04575     return;
    04576 }
    04577
    04578
    04579 BOOLEAN
    04580 IopInitializeDCB(
    04581     )
    04582 /*++
    04583
    04584 Routine Description:
    04585
    04586     This routine initializes the Dump Control Block (DCB). It allocates the
    04587     DCB and reads the crashdump parameters from the registry.
    04588
    04589 Arguments:
    04590
    04591
    04592 Return Value:
    04593
    04594     The final function value is TRUE if everything worked, else FALSE.
    04595
    04596 --*/
    04597
    04598 {
    04599     HANDLE                      keyHandle;
    04600     HANDLE                      crashHandle;
    04601     LOGICAL                     crashHandleOpened;
    04602     UNICODE_STRING              keyName;
    04603     NTSTATUS                    status;
    04604     PKEY_VALUE_FULL_INFORMATION keyValueInformation;
    04605     PDUMP_CONTROL_BLOCK         dcb;
    04606     ULONG                       dumpControl;
    04607     ULONG                       handleValue;
    04608     ULONG                       autoReboot;
    04609     PCHAR                       partitionName;
    04610     ULONG                       dcbSize;
    04611     LARGE_INTEGER               page;
    04612     ULONG                       numberOfHeaderPages;
    04613     ULONG                       dumpFileSize;
    04614
    04615     //
    04616     // Read all the registry default values first.
    04617     //
    04618
    04619     IopReadDumpRegistry ( &dumpControl,
    04620                           &numberOfHeaderPages,
    04621                           &autoReboot,
    04622                           &dumpFileSize);
    04623
    04624     //
    04625     // If we aren't crashing or auto rebooting then return now.
    04626     //
    04627
    04628     if (dumpControl == 0 && autoReboot == 0) {
    04629
    04630         //
    04631         // At some point, we will conditionally on system size, type, etc,
    04632         // set dump defaults like the below and skip over the return.
    04633         //
    04634         //    *dumpControl = (DCB_DUMP_ENABLED | DCB_TRIAGE_DUMP_ENABLED);
    04635         //    *autoReboot = 1;
    04636         //    *dumpFileSize = ?
    04637         //
    04638
    04639         return TRUE;
    04640     }
    04641
    04642     if (dumpControl & DCB_TRIAGE_DUMP_ENABLED) {
    04643         dumpControl &= ~DCB_SUMMARY_ENABLED;
    04644         dumpFileSize = TRIAGE_DUMP_SIZE;
    04645     }
    04646
    04647     //
    04648     // Allocate and initialize the structures necessary to describe and control
    04649     // the post-bugcheck code.
    04650     //
    04651
    04652     dcbSize = sizeof( DUMP_CONTROL_BLOCK ) + sizeof( MINIPORT_NODE );
    04653     dcb = ExAllocatePoolWithTag( NonPagedPool, dcbSize, 'pmuD' );
    04654     if (!dcb) {
    04655         IoDebugPrint((1, "IopInitializeDCB: Not enough pool to allocate DCB0\n" ));
    04656         IopLogErrorEvent(0,1,STATUS_SUCCESS,IO_DUMP_INITIALIZATION_FAILURE,0,NULL,0,NULL);
    04657         return FALSE;
    04658     }
    04659
    04660     RtlZeroMemory( dcb, dcbSize );
    04661     dcb->Type = IO_TYPE_DCB;
    04662     dcb->Size = (USHORT) dcbSize;
    04663     dcb->Flags = (UCHAR) (dumpControl | (autoReboot ? DCB_AUTO_REBOOT : 0));
    04664     dcb->NumberProcessors = KeNumberProcessors;
    04665     dcb->ProcessorArchitecture = KeProcessorArchitecture;
    04666     dcb->MinorVersion = (USHORT) NtBuildNumber;
    04667     dcb->MajorVersion = (USHORT) ((NtBuildNumber >> 28) & 0xfffffff);
    04668     dcb->BuildNumber = CmNtCSDVersion;
    04669     dcb->TriageDumpFlags = DEFAULT_TRIAGE_DUMP_FLAGS;
    04670
    04671     dcb->DumpFileSize.QuadPart = dumpFileSize;
    04672
    04673     //
    04674     // Allocate memory descriptors.
    04675     //
    04676
    04677     dcb->MemoryDescriptorLength = sizeof( PHYSICAL_MEMORY_DESCRIPTOR ) - sizeof( PHYSICAL_MEMORY_RUN ) +
    04678                                   (MmPhysicalMemoryBlock->NumberOfRuns * sizeof( PHYSICAL_MEMORY_RUN ));
    04679     dcb->MemoryDescriptor = ExAllocatePoolWithTag (
    04680                                     NonPagedPool,
    04681                                     dcb->MemoryDescriptorLength,
    04682                                     'pmuD'
    04683                                     );
    04684     if (!dcb->MemoryDescriptor) {
    04685         ExFreePool (dcb);
    04686
    04687         IoDebugPrint((1, "IopInitializeDCB: Not enough pool to allocate DCB1\n" ));
    04688         IopLogErrorEvent(0,1,STATUS_SUCCESS,IO_DUMP_INITIALIZATION_FAILURE,0,NULL,0,NULL);
    04689         return FALSE;
    04690     }
    04691
    04692     RtlCopyMemory (
    04693         dcb->MemoryDescriptor,
    04694         MmPhysicalMemoryBlock,
    04695         dcb->MemoryDescriptorLength
    04696         );
    04697
    04698     //
    04699     // Allocate header page.
    04700     //
    04701
    04702     dcb->HeaderSize = numberOfHeaderPages * PAGE_SIZE;
    04703     dcb->HeaderPage = ExAllocatePoolWithTag( NonPagedPool, dcb->HeaderSize, 'pmuD' );
    04704
    04705     if (!dcb->HeaderPage) {
    04706         ExFreePool (dcb->MemoryDescriptor);
    04707         ExFreePool (dcb);
    04708         IoDebugPrint((1, "IopInitializeDCB: Not enough pool to allocate DCB2\n" ));
    04709         IopLogErrorEvent(0,1,STATUS_SUCCESS,IO_DUMP_INITIALIZATION_FAILURE,0,NULL,0,NULL);
    04710         return FALSE;
    04711     }
    04712     page = MmGetPhysicalAddress( dcb->HeaderPage );
    04713     dcb->HeaderPfn = (ULONG)(page.QuadPart >> PAGE_SHIFT);
    04714
    04715
    04716     //
    04717     // Allocate the triage-dump buffer.
    04718     //
    04719
    04720     if (dumpControl & DCB_TRIAGE_DUMP_ENABLED) {
    04721
    04722         dcb->TriageDumpBuffer = ExAllocatePoolWithTag ( NonPagedPool,
    04723                                                       dumpFileSize,
    04724                                                       'pmuD'
    04725                                                       );
    04726
    04727         if (!dcb->TriageDumpBuffer) {
    04728             ExFreePool (dcb->HeaderPage);
    04729             ExFreePool (dcb->MemoryDescriptor);
    04730             ExFreePool (dcb);
    04731             IoDebugPrint((1, "IopInitializeDCB: Not enough pool to allocate DCB3\n" ));
    04732             IopLogErrorEvent(0,1,STATUS_SUCCESS,IO_DUMP_INITIALIZATION_FAILURE,0,NULL,0,NULL);
    04733             return FALSE;
    04734         }
    04735
    04736         dcb->TriageDumpBufferSize = dumpFileSize;
    04737     }
    04738
    04739     IopDumpControlBlock = dcb;
    04740
    04741     return TRUE;
    04742 }
    04743
    04744
    04745 BOOLEAN
    04746 IopConfigureCrashDump(
    04747     IN HANDLE hPageFile
    04748     )
    04749 /*++
    04750
    04751 Routine Description:
    04752
    04753     This routine configures the system for crash dump. The following things
    04754     are done:
    04755
    04756         1. Initialize the dump control block and init registry crashdump
    04757            parameters.
    04758
    04759         2. Configure either page or fast dump.
    04760
    04761         3. Complete dump file initialization.
    04762
    04763     This routine is called as each page file is created. A return value of
    04764     TRUE tells the caller (i.e., NtCreatePagingFiles, IoPageFileCreated)
    04765     that crash dump has been configured.
    04766
    04767
    04768 Arguments:
    04769
    04770        hPageFile - Handle to the paging file
    04771
    04772 Return Value:
    04773
    04774     TRUE - Configuration complete (or crash dump not enabled).
    04775
    04776     FALSE - Error, retry PageFile is not on boot partition.
    04777
    04778 --*/
    04779 {
    04780     ULONG           dwStatus;
    04781     PFILE_OBJECT    fileObject;
    04782     PDEVICE_OBJECT  deviceObject;
    04783
    04784     //
    04785     // Only Init DCB Once.
    04786     //
    04787
    04788     if (!IopDumpControlBlock) {
    04789         if (!IopInitializeDCB()) {
    04790             return TRUE;
    04791         }
    04792     }
    04793
    04794     //
    04795     // Return crash dump not enabled
    04796     //
    04797     if (!IopDumpControlBlock){
    04798         return TRUE;
    04799     }
    04800
    04801     //
    04802     //  Only autoreboot?
    04803     //
    04804
    04805     if ( !( IopDumpControlBlock->Flags & (DCB_DUMP_ENABLED | DCB_SUMMARY_ENABLED) ) ) {
    04806         return TRUE;
    04807     }
    04808
    04809     //
    04810     // Configure the paging file for crash dump.
    04811     //
    04812
    04813     IoDebugPrint((2,"[IoPageFileCreated]: Page file dump\n"));
    04814
    04815
    04816     dwStatus = ObReferenceObjectByHandle(
    04817                                         hPageFile,
    04818                                         0,
    04819                                         IoFileObjectType,
    04820                                         KernelMode,
    04821                                         (PVOID *) &fileObject,
    04822                                         NULL
    04823                                         );
    04824
    04825     if (!NT_SUCCESS( dwStatus )) {
    04826         IoDebugPrint((1,"[IoPageFileCreated]: ObReferenceObjectByHandle for Paging file failed status = %x\n",dwStatus));
    04827         goto error_return;
    04828     }
    04829
    04830     //
    04831     // Get a pointer to the device object for this file.  Note that it
    04832     // cannot go away, since there is an open handle to it, so it is
    04833     // OK to dereference it and then use it.
    04834     //
    04835
    04836     deviceObject = fileObject->DeviceObject;
    04837
    04838     ObDereferenceObject( fileObject );
    04839
    04840     //
    04841     // If this device object does not represents the boot partition return
    04842     // FALSE so MM will try again.
    04843     //
    04844
    04845     if ( ! (deviceObject->Flags & DO_SYSTEM_BOOT_PARTITION) ) {
    04846         return FALSE;
    04847     }
    04848
    04849     //
    04850     // Load paging file dump stack
    04851     //
    04852
    04853     dwStatus = IoGetDumpStack (L"dump_",
    04854                                &IopDumpControlBlock->DumpStack,
    04855                                DeviceUsageTypeDumpFile,
    04856                                FALSE);
    04857
    04858     if (!NT_SUCCESS(dwStatus)) {
    04859         IoDebugPrint((1, "IoPageFileCreated: Could not load dump stack status = %x\n",dwStatus) );
    04860         goto error_return;
    04861     }
    04862
    04863     IopDumpControlBlock->DumpStack->Init.CrashDump = TRUE;
    04864
    04865     IopDumpControlBlock->DumpStack->Init.MemoryBlock = ExAllocatePoolWithTag (
    04866                                                 NonPagedPool,
    04867                                                 IO_DUMP_MEMORY_BLOCK_PAGES * PAGE_SIZE,
    04868                                                 'pmuD'
    04869                                                 );
    04870
    04871     if (!IopDumpControlBlock->DumpStack->Init.MemoryBlock) {
    04872         dwStatus = STATUS_NO_MEMORY;
    04873         goto error_return;
    04874     }
    04875
    04876
    04877     //
    04878     // Calculate the amount of space required for the dump
    04879     //
    04880     IopDumpControlBlock->DumpFileSize =IopCalculateRequiredDumpSpace(
    04881                                                     IopDumpControlBlock->Flags,
    04882                                                     IopDumpControlBlock->HeaderSize,
    04883                                                     IopDumpControlBlock->MemoryDescriptor->NumberOfPages,
    04884                                                     IopDumpControlBlock->MemoryDescriptor->NumberOfPages
    04885                                                     );
    04886
    04887
    04888     //
    04889     // Complete dump initialization
    04890     //
    04891
    04892     dwStatus = IopCompleteDumpInitialization(hPageFile);
    04893
    04894 error_return:
    04895
    04896     //
    04897     // The BOOT partition paging file could not be configured.
    04898     //   1. Log an error message
    04899     //   2. Return TRUE so that MM does not try again
    04900     //
    04901
    04902     if (!NT_SUCCESS(dwStatus)) {
    04903         IoDebugPrint((1,"IopPageFileCreated: Page File dump init FAILED status = %x\n",dwStatus));
    04904
    04905         IopLogErrorEvent(0,3,STATUS_SUCCESS,IO_DUMP_PAGE_CONFIG_FAILED,0,NULL,0,NULL);
    04906
    04907         IopFreeDCB(FALSE);
    04908
    04909     }
    04910
    04911     return TRUE;
    04912 }
    04913
    04914
    04915 //
    04916 // Debugging routines.
    04917 //
    04918
    04919 #if DBG
    04920
    04921 ULONG IopDebugLevel = 0;
    04922 UCHAR IopBuffer[128];
    04923
    04924
    04925 VOID
    04926 IopDebugPrint(
    04927     ULONG Level,
    04928     PCHAR Format,
    04929     ...
    04930     )
    04931 {
    04932     va_list ap;
    04933
    04934     va_start(ap, Format);
    04935
    04936     if (IopDebugLevel >= Level) {
    04937         vsprintf(IopBuffer, Format, ap);
    04938         DbgPrint(IopBuffer);
    04939     }
    04940
    04941     va_end(ap);
    04942 }
    04943
    04944 #endif //DBG