test: hiveload.c File Reference

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

# hiveload.c File Reference

`#include "cmp.h"`

Go to the source code of this file.

## Defines

#define | IO_BUFFER_SIZE 0x10000

## Typedefs

typedef enum _RESULT | RESULT

## Enumerations

enum | _RESULT { NotHive, Fail, NoMemory, HiveSuccess, RecoverHeader, RecoverData }

## Functions

RESULT | HvpGetHiveHeader (PHHIVE Hive, PHBASE_BLOCK *BaseBlock, PLARGE_INTEGER TimeStamp)
RESULT | HvpGetLogHeader (PHHIVE Hive, PHBASE_BLOCK *BaseBlock, PLARGE_INTEGER TimeStamp)
RESULT | HvpRecoverData (PHHIVE Hive, BOOLEAN ReadOnly, PHCELL_INDEX TailDisplay OPTIONAL)
NTSTATUS | HvpReadFileImageAndBuildMap (PHHIVE Hive, ULONG Length, PHCELL_INDEX TailDisplay OPTIONAL)
VOID | HvpDelistBinFreeCells (PHHIVE Hive, PHBIN Bin, HSTORAGE_TYPE Type, PHCELL_INDEX TailDisplay OPTIONAL)
NTSTATUS | HvLoadHive (PHHIVE Hive, PHCELL_INDEX TailDisplay OPTIONAL)

## Variables

struct {
PHHIVE Hive
ULONG Status
ULONG Space
HCELL_INDEX MapPoint
PHBIN BinPoint
} | HvCheckHiveDebug

## Define Documentation

#define IO_BUFFER_SIZE 0x10000

| Definition at line 34 of file hiveload.c. Referenced by HvpReadFileImageAndBuildMap().

## Typedef Documentation

typedef enum _RESULT RESULT

## Enumeration Type Documentation

enum _RESULT

Enumeration values:

  NotHive |
  Fail |
  NoMemory |
  HiveSuccess |
  RecoverHeader |
  RecoverData |

Definition at line 36 of file hiveload.c.

    00036                      {
    00037     NotHive,
    00038     Fail,
    00039     NoMemory,
    00040     HiveSuccess,
    00041     RecoverHeader,
    00042     RecoverData
    00043 } RESULT;

## Function Documentation

NTSTATUS HvLoadHive | ( | PHHIVE | Hive,
|  | PHCELL_INDEX TailDisplay | OPTIONAL
| ) |

Definition at line 100 of file hiveload.c.

References ASSERT, _HHIVE::BaseBlock, _HHIVE::DirtyCount, Fail, FALSE, _HHIVE::Free, HFILE_TYPE_PRIMARY, HHIVE_SIGNATURE, Hive, HvpCleanMap(), HvpFreeAllocatedBins(), HvpGetHiveHeader(), HvpGetLogHeader(), HvpReadFileImageAndBuildMap(), HvpRecoverData(), _HBASE_BLOCK::Length, _HHIVE::Log, _HBASE_BLOCK::Minor, NoMemory, NotHive, NT_SUCCESS, NTSTATUS(), NULL, _HHIVE::ReadOnly, RecoverData, RecoverHeader, _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, _HHIVE::Signature, TRUE, _HBASE_BLOCK::Type, and _HHIVE::Version.

Referenced by HvInitializeHive().

    00106                    :
    00107
    00108     Hive must be fully initialized, in particular, file handles
    00109     must be set up.  This routine is not intended for loading hives
    00110     from images already in memory.
    00111
    00112     This routine will apply whatever fixes are available for errors
    00113     in the hive image.  In particular, if a log exists, and is applicable,
    00114     this routine will automatically apply it.
    00115
    00116     ALGORITHM:
    00117
    00118         call HvpGetHiveHeader()
    00119
    00120         if (NoMemory or NoHive)
    00121             return failure
    00122
    00123         if (RecoverData or RecoverHeader) and (no log)
    00124             return falure
    00125
    00126         if (RecoverHeader)
    00127             call HvpGetLogHeader
    00128             if (fail)
    00129                 return failure
    00130             fix up baseblock
    00131
    00132         Read Data
    00133
    00134         if (RecoverData or RecoverHeader)
    00135             HvpRecoverData
    00136             return STATUS_REGISTRY_RECOVERED
    00137
    00138         clean up sequence numbers
    00139
    00140         return success OR STATUS_REGISTRY_RECOVERED
    00141
    00142     If STATUS_REGISTRY_RECOVERED is returned, then
    00143
    00144         If (Log) was used, DirtyVector and DirtyCount are set,
    00145             caller is expected to flush the changes (using a
    00146             NEW log file)
    00147
    00148 Arguments:
    00149
    00150     Hive - supplies a pointer to the hive control structure for the
    00151             hive of interest
    00152
    00153     TailDisplay - array containing the tail ends of the free cell lists - optional
    00154
    00155 Return Value:
    00156
    00157     STATUS:
    00158
    00159         STATUS_INSUFFICIENT_RESOURCES   - memory alloc failure, etc
    00160         STATUS_NOT_REGISTRY_FILE        - bad signatures and the like
    00161         STATUS_REGISTRY_CORRUPT         - bad signatures in the log,
    00162                                           bad stuff in both in alternate,
    00163                                           inconsistent log
    00164
    00165         STATUS_REGISTRY_IO_FAILED       - data read failed
    00166
    00167         STATUS_RECOVERED                - successfully recovered the hive,
    00168                                           a semi-flush of logged data
    00169                                           is necessary.
    00170
    00171         STATUS_SUCCESS                  - it worked, no recovery needed
    00172
    00173 --*/
    00174 {
    00175     PHBASE_BLOCK    BaseBlock;
    00176     ULONG           result1;
    00177     ULONG           result2;
    00178     NTSTATUS        status;
    00179     LARGE_INTEGER   TimeStamp;
    00180     ULONG           FileOffset;
    00181     PHBIN           pbin;
    00182     BOOLEAN         ReadOnlyFlagCopy;
    00183
    00184     ASSERT(Hive->Signature == HHIVE_SIGNATURE);
    00185
    00186     BaseBlock = NULL;
    00187     result1 = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp);
    00188
    00189     //
    00190     // bomb out for total errors
    00191     //
    00192     if (result1 == NoMemory) {
    00193         status = STATUS_INSUFFICIENT_RESOURCES;
    00194         goto Exit1;
    00195     }
    00196     if (result1 == NotHive) {
    00197         status = STATUS_NOT_REGISTRY_FILE;
    00198         goto Exit1;
    00199     }
    00200
    00201
    00202     ReadOnlyFlagCopy = Hive->ReadOnly;
    00203     //
    00204     // if recovery needed, and no log, bomb out
    00205     //
    00206     if ( ((result1 == RecoverData) ||
    00207           (result1 == RecoverHeader)) )
    00208     {
    00209         //
    00210         // recovery needed
    00211         //
    00212         if(Hive->Log == FALSE)
    00213         {
    00214             //
    00215             // no log ==> bomb out
    00216             //
    00217             status = STATUS_REGISTRY_CORRUPT;
    00218             goto Exit1;
    00219         } else {
    00220             //
    00221             // TRICK: simulate hive as read-only; Free cells will not
    00222             // be enlisted in HvpReadFileImageAndBuildMap; Instead, they
    00223             // will be enlisted in HvpRecoverData, when we are sure we have
    00224             // the right info loaded up into memory
    00225             //
    00226             Hive->ReadOnly = TRUE;
    00227         }
    00228     }
    00229
    00230     //
    00231     // need to recover header using log, so try to get it from log
    00232     //
    00233     if (result1 == RecoverHeader) {
    00234         result2 = HvpGetLogHeader(Hive, &BaseBlock, &TimeStamp);
    00235         if (result2 == NoMemory) {
    00236             status =  STATUS_INSUFFICIENT_RESOURCES;
    00237             goto Exit1;
    00238         }
    00239         if (result2 == Fail) {
    00240             status = STATUS_REGISTRY_CORRUPT;
    00241             goto Exit1;
    00242         }
    00243         BaseBlock->Type = HFILE_TYPE_PRIMARY;
    00244     }
    00245     Hive->BaseBlock = BaseBlock;
    00246     Hive->Version = Hive->BaseBlock->Minor;
    00247
    00248     //
    00249     // at this point, we have a sane baseblock.  we may or may not still
    00250     // need to apply data recovery
    00251     //
    00252     status = HvpReadFileImageAndBuildMap(Hive,BaseBlock->Length,TailDisplay);
    00253
    00254
    00255     //
    00256     // if STATUS_REGISTRY_CORRUPT and RecoverData don't bail out, keep recovering
    00257     //
    00258     if( !NT_SUCCESS(status) && ((status != STATUS_REGISTRY_CORRUPT) || (result1 != RecoverData)) ) {
    00259         goto Exit2;
    00260     }
    00261
    00262     //
    00263     // apply data recovery if we need it
    00264     //
    00265     status = STATUS_SUCCESS;
    00266     if ( (result1 == RecoverHeader) ||      // -> implies recover data
    00267          (result1 == RecoverData) )
    00268     {
    00269         //
    00270         // recover data will enllist the free cells as well and
    00271         // will restore the original read-only state of the hive
    00272         //
    00273         result2 = HvpRecoverData(Hive,ReadOnlyFlagCopy,TailDisplay);
    00274         if (result2 == NoMemory) {
    00275             status = STATUS_INSUFFICIENT_RESOURCES;
    00276             goto Exit2;
    00277         }
    00278         if (result2 == Fail) {
    00279             status = STATUS_REGISTRY_CORRUPT;
    00280             goto Exit2;
    00281         }
    00282         status = STATUS_REGISTRY_RECOVERED;
    00283     }
    00284
    00285     BaseBlock->Sequence2 = BaseBlock->Sequence1;
    00286     return status;
    00287
    00288
    00289 Exit2:
    00290     //
    00291     // Clean up the bins already allocated
    00292     //
    00293     HvpFreeAllocatedBins( Hive );
    00294
    00295     //
    00296     // Clean up the directory table
    00297     //
    00298     HvpCleanMap( Hive );
    00299
    00300 Exit1:
    00301     if (BaseBlock != NULL) {
    00302         (Hive->Free)(BaseBlock, sizeof(HBASE_BLOCK));
    00303     }
    00304
    00305     Hive->BaseBlock = NULL;
    00306     Hive->DirtyCount = 0;
    00307     return status;
    00308 }

VOID HvpDelistBinFreeCells | ( | PHHIVE | Hive,
|  | PHBIN | Bin,
|  | HSTORAGE_TYPE | Type,
|  | PHCELL_INDEX TailDisplay | OPTIONAL
| ) |

RESULT HvpGetHiveHeader | ( | PHHIVE | Hive,
|  | PHBASE_BLOCK * | BaseBlock,
|  | PLARGE_INTEGER | TimeStamp
| ) |

Definition at line 592 of file hiveload.c.

References _HHIVE::Allocate, ASSERT, _HHIVE::Cluster, FALSE, _HHIVE::FileRead, _HHIVE::Free, HBASE_BLOCK, HBASE_BLOCK_SIGNATURE, HBASE_FORMAT_MEMORY, HBIN_SIGNATURE, HBLOCK_SIZE, HFILE_TYPE_PRIMARY, Hive, HiveSuccess, HSECTOR_SIZE, HSYS_MAJOR, HSYS_MINOR, HvpHeaderCheckSum(), NoMemory, NotHive, NULL, PAGE_SIZE, RecoverData, RecoverHeader, _HBASE_BLOCK::TimeStamp, and TRUE.

Referenced by HvLoadHive().

    00599                    :
    00600
    00601     Examine the base block sector and possibly the first sector of
    00602     the first bin, and decide what (if any) recovery needs to be applied
    00603     based on what we find there.
    00604
    00605     ALGORITHM:
    00606
    00607         read BaseBlock from offset 0
    00608         if ( (I/O error)    OR
    00609              (checksum wrong) )
    00610         {
    00611             read bin block from offset HBLOCK_SIZE (4k)
    00612             if (2nd I/O error)
    00613                 return NotHive
    00614             }
    00615             check bin sign., offset.
    00616             if (OK)
    00617                 return RecoverHeader, TimeStamp=from Link field
    00618             } else {
    00619                 return NotHive
    00620             }
    00621         }
    00622
    00623         if (wrong type or signature or version or format)
    00624             return NotHive
    00625         }
    00626
    00627         if (seq1 != seq2) {
    00628             return RecoverData, TimeStamp=BaseBlock->TimeStamp, valid BaseBlock
    00629         }
    00630
    00631         return ReadData, valid BaseBlock
    00632
    00633 Arguments:
    00634
    00635     Hive - supplies a pointer to the hive control structure for the
    00636             hive of interest
    00637
    00638     FileType - HFILE_TYPE_PRIMARY or HFILE_TYPE_ALTERNATE - which copy
    00639             of the hive to read from.
    00640
    00641     BaseBlock - supplies pointer to variable to receive pointer to
    00642             HBASE_BLOCK, if we can successfully read one.
    00643
    00644     TimeStamp - pointer to variable to receive time stamp (serial number)
    00645             of hive, be it from the baseblock or from the Link field
    00646             of the first bin.
    00647
    00648 Return Value:
    00649
    00650     RESULT code
    00651
    00652 --*/
    00653 {
    00654     PHBASE_BLOCK    buffer;
    00655     BOOLEAN         rc;
    00656     ULONG           FileOffset;
    00657     ULONG           Alignment;
    00658
    00659     ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
    00660
    00661     //
    00662     // allocate buffer to hold base block
    00663     //
    00664     *BaseBlock = NULL;
    00665     buffer = (PHBASE_BLOCK)((Hive->Allocate)(sizeof(HBASE_BLOCK), TRUE));
    00666     if (buffer == NULL) {
    00667         return NoMemory;
    00668     }
    00669     //
    00670     // Make sure the buffer we got back is cluster-aligned. If not, try
    00671     // harder to get an aligned buffer.
    00672     //
    00673     Alignment = Hive->Cluster * HSECTOR_SIZE - 1;
    00674     if (((ULONG_PTR)buffer & Alignment) != 0) {
    00675         (Hive->Free)(buffer, sizeof(HBASE_BLOCK));
    00676         buffer = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE));
    00677         if (buffer == NULL) {
    00678             return NoMemory;
    00679         }
    00680     }
    00681     RtlZeroMemory((PVOID)buffer, sizeof(HBASE_BLOCK));
    00682
    00683     //
    00684     // attempt to read base block
    00685     //
    00686     FileOffset = 0;
    00687     rc = (Hive->FileRead)(Hive,
    00688                           HFILE_TYPE_PRIMARY,
    00689                           &FileOffset,
    00690                           (PVOID)buffer,
    00691                           HSECTOR_SIZE * Hive->Cluster);
    00692
    00693     if ( (rc == FALSE)  ||
    00694          (HvpHeaderCheckSum(buffer) != buffer->CheckSum)) {
    00695         //
    00696         // base block is toast, try the first block in the first bin
    00697         //
    00698         FileOffset = HBLOCK_SIZE;
    00699         rc = (Hive->FileRead)(Hive,
    00700                               HFILE_TYPE_PRIMARY,
    00701                               &FileOffset,
    00702                               (PVOID)buffer,
    00703                               HSECTOR_SIZE * Hive->Cluster);
    00704
    00705         if ( (rc == FALSE) ||
    00706              ( ((PHBIN)buffer)->Signature != HBIN_SIGNATURE)           ||
    00707              ( ((PHBIN)buffer)->FileOffset != 0)
    00708            )
    00709         {
    00710             //
    00711             // the bin is toast too, punt
    00712             //
    00713             (Hive->Free)(buffer, sizeof(HBASE_BLOCK));
    00714             return NotHive;
    00715         }
    00716
    00717         //
    00718         // base block is bogus, but bin is OK, so tell caller
    00719         // to look for a log file and apply recovery
    00720         //
    00721         *TimeStamp = ((PHBIN)buffer)->TimeStamp;
    00722         (Hive->Free)(buffer, sizeof(HBASE_BLOCK));
    00723         return RecoverHeader;
    00724     }
    00725
    00726     //
    00727     // base block read OK, but is it valid?
    00728     //
    00729     if ( (buffer->Signature != HBASE_BLOCK_SIGNATURE)   ||
    00730          (buffer->Type != HFILE_TYPE_PRIMARY)           ||
    00731          (buffer->Major != HSYS_MAJOR)                  ||
    00732          (buffer->Minor > HSYS_MINOR)                   ||
    00733          ((buffer->Major == 1) && (buffer->Minor == 0)) ||
    00734          (buffer->Format != HBASE_FORMAT_MEMORY)
    00735        )
    00736     {
    00737         //
    00738         // file is simply not a valid hive
    00739         //
    00740         (Hive->Free)(buffer, sizeof(HBASE_BLOCK));
    00741         return NotHive;
    00742     }
    00743
    00744     //
    00745     // see if recovery is necessary
    00746     //
    00747     *BaseBlock = buffer;
    00748     *TimeStamp = buffer->TimeStamp;
    00749     if ( (buffer->Sequence1 != buffer->Sequence2) ) {
    00750         return RecoverData;
    00751     }
    00752
    00753     return HiveSuccess;
    00754 }

RESULT HvpGetLogHeader | ( | PHHIVE | Hive,
|  | PHBASE_BLOCK * | BaseBlock,
|  | PLARGE_INTEGER | TimeStamp
| ) |

Definition at line 758 of file hiveload.c.

References _HHIVE::Allocate, ASSERT, _HHIVE::Cluster, Fail, FALSE, _HHIVE::FileRead, _HHIVE::Free, HBASE_BLOCK, HBASE_BLOCK_SIGNATURE, HBLOCK_SIZE, HFILE_TYPE_LOG, Hive, HiveSuccess, HSECTOR_SIZE, HvpHeaderCheckSum(), NoMemory, NULL, and TRUE.

Referenced by HvLoadHive().

    00765                    :
    00766
    00767     Read and validate log file header.  Return it if it's valid.
    00768
    00769     ALGORITHM:
    00770
    00771         read header
    00772         if ( (I/O error) or
    00773            (wrong signature,
    00774             wrong type,
    00775             seq mismatch
    00776             wrong checksum,
    00777             wrong timestamp
    00778            )
    00779             return Fail
    00780         }
    00781         return baseblock, OK
    00782
    00783 Arguments:
    00784
    00785     Hive - supplies a pointer to the hive control structure for the
    00786             hive of interest
    00787
    00788     BaseBlock - supplies pointer to variable to receive pointer to
    00789             HBASE_BLOCK, if we can successfully read one.
    00790
    00791     TimeStamp - pointer to variable holding TimeStamp, which must
    00792             match the one in the log file.
    00793
    00794 Return Value:
    00795
    00796     RESULT
    00797
    00798 --*/
    00799 {
    00800     PHBASE_BLOCK    buffer;
    00801     BOOLEAN         rc;
    00802     ULONG           FileOffset;
    00803
    00804     ASSERT(sizeof(HBASE_BLOCK) == HBLOCK_SIZE);
    00805     ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
    00806
    00807     //
    00808     // allocate buffer to hold base block
    00809     //
    00810     *BaseBlock = NULL;
    00811     buffer = (PHBASE_BLOCK)((Hive->Allocate)(sizeof(HBASE_BLOCK), TRUE));
    00812     if (buffer == NULL) {
    00813         return NoMemory;
    00814     }
    00815     RtlZeroMemory((PVOID)buffer, HSECTOR_SIZE);
    00816
    00817     //
    00818     // attempt to read base block
    00819     //
    00820     FileOffset = 0;
    00821     rc = (Hive->FileRead)(Hive,
    00822                           HFILE_TYPE_LOG,
    00823                           &FileOffset,
    00824                           (PVOID)buffer,
    00825                           HSECTOR_SIZE * Hive->Cluster);
    00826
    00827     if ( (rc == FALSE)                                              ||
    00828          (buffer->Signature != HBASE_BLOCK_SIGNATURE)               ||
    00829          (buffer->Type != HFILE_TYPE_LOG)                           ||
    00830          (buffer->Sequence1 != buffer->Sequence2)                   ||
    00831          (HvpHeaderCheckSum(buffer) != buffer->CheckSum)            ||
    00832          (TimeStamp->LowPart != buffer->TimeStamp.LowPart)          ||
    00833          (TimeStamp->HighPart != buffer->TimeStamp.HighPart)) {
    00834         //
    00835         // Log is unreadable, invalid, or doesn't apply the right hive
    00836         //
    00837         (Hive->Free)(buffer, sizeof(HBASE_BLOCK));
    00838         return Fail;
    00839     }
    00840
    00841     *BaseBlock = buffer;
    00842     return HiveSuccess;
    00843 }

NTSTATUS HvpReadFileImageAndBuildMap | ( | PHHIVE | Hive,
|  | ULONG | Length,
|  | PHCELL_INDEX TailDisplay | OPTIONAL
| ) |

Definition at line 311 of file hiveload.c.

References _HHIVE::Allocate, ASSERT, Bin, ErrorExit(), ExAllocatePool, ExFreePool(), _HBIN::FileOffset, _HHIVE::FileRead, HBIN_SIGNATURE, HBLOCK_SIZE, HFILE_TYPE_PRIMARY, Hive, HvCheckHiveDebug, HvpCleanMap(), HvpEnlistBinInMap(), HvpInitMap(), IO_BUFFER_SIZE, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, _HBIN::Signature, _HBIN::Size, Status, and TRUE.

Referenced by HvLoadHive().

    00319                    :
    00320
    00321     Read the hive from the file and allocate storage for the hive
    00322     image in chunks of HBINs. Build the hive map "on the fly".
    00323         Optimized to read chunks of 64K from the file.
    00324
    00325 Arguments:
    00326
    00327     Hive - supplies a pointer to the hive control structure for the
    00328             hive of interest
    00329
    00330     Length - the length of the hive, in bytes
    00331
    00332     TailDisplay - array containing the tail ends of the free cell lists - optional
    00333
    00334 Return Value:
    00335
    00336     STATUS:
    00337
    00338         STATUS_INSUFFICIENT_RESOURCES   - memory alloc failure, etc
    00339
    00340         STATUS_REGISTRY_IO_FAILED       - data read failed
    00341
    00342         STATUS_REGISTRY_CORRUPT         - base block is corrupt
    00343
    00344         STATUS_SUCCESS                  - it worked
    00345
    00346 --*/
    00347 {
    00348     ULONG           FileOffset;
    00349     NTSTATUS        Status = STATUS_SUCCESS;
    00350     PHBIN           Bin;                        // current bin
    00351     ULONG           BinSize;            // size of the current bin
    00352     ULONG           BinOffset;          // current offset inside current bin
    00353     ULONG           BinFileOffset;  // physical offset of the bin in the file (used for consistency checking)
    00354     ULONG           BinDataInBuffer;// the amount of data needed to be copied in the current bin available in the buffer
    00355     ULONG           BinDataNeeded;  //
    00356     PUCHAR                      IOBuffer;
    00357     ULONG           IOBufferSize;       // valid data in IOBuffer (only at the end of the file this is different than IO_BUFFER_SIZE)
    00358     ULONG           IOBufferOffset;     // current offset inside IOBuffer
    00359
    00360     //
    00361     // Init the map
    00362     //
    00363     Status = HvpInitMap(Hive);
    00364
    00365     if( !NT_SUCCESS(Status) ) {
    00366         //
    00367         // return failure
    00368         //
    00369         return Status;
    00370     }
    00371
    00372     //
    00373     // Allocate a IO_BUFFER_SIZE for I/O operations from paged pool.
    00374         // It will be freed at the end of the function.
    00375     //
    00376     IOBuffer = (PUCHAR)ExAllocatePool(PagedPool, IO_BUFFER_SIZE);
    00377     if (IOBuffer == NULL) {
    00378         Status = STATUS_INSUFFICIENT_RESOURCES;
    00379         HvpCleanMap( Hive );
    00380         return Status;
    00381     }
    00382
    00383     //
    00384     // Start right after the hive header
    00385     //
    00386     FileOffset = HBLOCK_SIZE;
    00387     BinFileOffset = FileOffset;
    00388     Bin = NULL;
    00389
    00390     //
    00391         // outer loop : reads IO_BUFFER_SIZE chunks from the file
    00392         //
    00393         while( FileOffset < (Length + HBLOCK_SIZE) ) {
    00394                 //
    00395                 // we are at the begining of the IO buffer
    00396         //
    00397         IOBufferOffset = 0;
    00398
    00399         //
    00400         // the buffer size will be either IO_BufferSize, or the amount
    00401         // uread from the file (when this is smaller than IO_BUFFER_SIZE)
    00402         //
    00403         IOBufferSize = Length + HBLOCK_SIZE - FileOffset;
    00404         IOBufferSize = ( IOBufferSize > IO_BUFFER_SIZE ) ? IO_BUFFER_SIZE : IOBufferSize;
    00405
    00406         ASSERT( (IOBufferSize % HBLOCK_SIZE) == 0 );
    00407
    00408         //
    00409         // read data from the file
    00410         //
    00411         if ( ! (Hive->FileRead)(
    00412                         Hive,
    00413                         HFILE_TYPE_PRIMARY,
    00414                         &FileOffset,
    00415                         (PVOID)IOBuffer,
    00416                         IOBufferSize
    00417                         )
    00418            )
    00419         {
    00420             Status = STATUS_REGISTRY_IO_FAILED;
    00421             goto ErrorExit;
    00422         }
    00423
    00424         //
    00425         // inner loop: breaks the buffer into bins
    00426         //
    00427         while( IOBufferOffset < IOBufferSize ) {
    00428
    00429             if( Bin == NULL ) {
    00430                 //
    00431                 // this is the beginning of a new bin
    00432                 // perform bin validation and allocate the bin
    00433                 //
    00434                 // temporary bin points to the current location inside the buffer
    00435                 Bin = (PHBIN)(IOBuffer + IOBufferOffset);
    00436                 //
    00437                 // Check the validity of the bin header
    00438                 //
    00439                 BinSize = Bin->Size;
    00440                 if ( (BinSize > Length)                         ||
    00441                      (BinSize < HBLOCK_SIZE)                    ||
    00442                      (Bin->Signature != HBIN_SIGNATURE)         ||
    00443                      (Bin->FileOffset != (BinFileOffset - HBLOCK_SIZE) )) {
    00444                     //
    00445                     // Bin is bogus
    00446                     //
    00447                     Bin = (PHBIN)(Hive->Allocate)(HBLOCK_SIZE, TRUE);
    00448                     if (Bin == NULL) {
    00449                         Status = STATUS_INSUFFICIENT_RESOURCES;
    00450                         goto ErrorExit;
    00451                     }
    00452                     //
    00453                     // copy the data already read in the first HBLOCK of the bin
    00454                     //
    00455                     RtlCopyMemory(Bin,(IOBuffer + IOBufferOffset), HBLOCK_SIZE);
    00456
    00457                     Status = STATUS_REGISTRY_CORRUPT;
    00458                     HvCheckHiveDebug.Hive = Hive;
    00459                     HvCheckHiveDebug.Status = 0xA001;
    00460                     HvCheckHiveDebug.Space = Length;
    00461                     HvCheckHiveDebug.MapPoint = BinFileOffset;
    00462                     HvCheckHiveDebug.BinPoint = Bin;
    00463
    00464                     //goto ErrorExit;
    00465                     //
    00466                     // DO NOT EXIT; Fix this bin header and go on. RecoverData should fix it.
    00467                     // If not, CmCheckRegistry called later will prevent loading of an invalid hive
    00468                     //
    00469                     // NOTE: Still, mess the signature, to make sure that if this particular bin doesn't get recovered,
    00470                     //       we'll fail the hive loading request.
    00471                     //
    00472                     Bin->Signature = 0; //TRICK!!!!
    00473                     BinSize = Bin->Size = HBLOCK_SIZE;
    00474                     Bin->FileOffset = BinFileOffset - HBLOCK_SIZE;
    00475
    00476                     //
    00477                     // simulate as the entire bin is a used cell
    00478                     //
    00479                     ((PHCELL)((PUCHAR)Bin + sizeof(HBIN)))->Size = sizeof(HBIN) - BinSize; //TRICK!!!!
    00480                     //
    00481                     // Now that we have the entire bin in memory, Enlist It!
    00482                     //
    00483                     Status = HvpEnlistBinInMap(Hive, Length, Bin, BinFileOffset - HBLOCK_SIZE, TailDisplay);
    00484
    00485                     if( !NT_SUCCESS(Status) ) {
    00486                         goto ErrorExit;
    00487                     }
    00488
    00489                     //
    00490                     // Adjust the offsets
    00491                     //
    00492                     BinFileOffset += Bin->Size;
    00493                     IOBufferOffset += Bin->Size;
    00494
    00495                     //
    00496                     // another bin is on his way
    00497                     //
    00498                     Bin = NULL;
    00499                 } else {
    00500                     //
    00501                     // bin is valid; allocate a pool chunk of the right size
    00502                     //
    00503                     Bin = (PHBIN)(Hive->Allocate)(BinSize, TRUE);
    00504                     if (Bin == NULL) {
    00505                         Status = STATUS_INSUFFICIENT_RESOURCES;
    00506                         goto ErrorExit;
    00507                     }
    00508
    00509                     //
    00510                     // the chunk is allocated; set the offset inside the bin and continue
    00511                     // the next iteration of the inner loop will start by copying data in this bin
    00512                     //
    00513                     BinOffset = 0;
    00514                 }
    00515             } else {
    00516                 //
    00517                 // if we are here, the bin is allocated, the BinSize and BinOffset are set
    00518                 // We have to calculate how much for this bin is available in the buffer,
    00519                 // and copy it. If we finished with this bin, enlist it and mark the begining of a new one
    00520                 //
    00521                 ASSERT( Bin != NULL );
    00522                 BinDataInBuffer = (IOBufferSize - IOBufferOffset);
    00523                 BinDataNeeded = (BinSize - BinOffset);
    00524
    00525                 if( BinDataInBuffer >= BinDataNeeded ) {
    00526                     //
    00527                     // we have available more than what we need; Finish the bin
    00528                     //
    00529                     RtlCopyMemory(((PUCHAR)Bin + BinOffset),(IOBuffer + IOBufferOffset), BinDataNeeded);
    00530                     //
    00531                     // enlist it
    00532                     //
    00533                     Status = HvpEnlistBinInMap(Hive, Length, Bin, BinFileOffset - HBLOCK_SIZE, TailDisplay);
    00534
    00535                     if( !NT_SUCCESS(Status) ) {
    00536                         goto ErrorExit;
    00537                     }
    00538                     //
    00539                     // Adjust the offsets
    00540                     //
    00541                     BinFileOffset += BinSize;
    00542                     IOBufferOffset += BinDataNeeded;
    00543                     //
    00544                     // mark the begining of a new bin
    00545                     //
    00546                     Bin = NULL;
    00547                 } else {
    00548                     //
    00549                     // we do not have all bin data in the buffer
    00550                     // copy what we can
    00551                     //
    00552                     RtlCopyMemory(((PUCHAR)Bin + BinOffset),(IOBuffer + IOBufferOffset), BinDataInBuffer);
    00553
    00554                     //
    00555                     // adjust the offsets; this should be the last iteration of the inner loop
    00556                     //
    00557                     BinOffset += BinDataInBuffer;
    00558                     IOBufferOffset += BinDataInBuffer;
    00559
    00560                     //
    00561                     // if we are here, the buffer must have beed exausted
    00562                     //
    00563                     ASSERT( IOBufferOffset == IOBufferSize );
    00564                 }
    00565             }
    00566         }
    00567         }
    00568
    00569     //
    00570     // if we got here, we shouldn't have a bin under construction
    00571     //
    00572     ASSERT( Bin == NULL );
    00573
    00574         //
    00575         // Free the buffer used for I/O operations
    00576         //
    00577         ExFreePool(IOBuffer);
    00578
    00579     return Status;
    00580
    00581 ErrorExit:
    00582     //
    00583     // Free the buffer used for I/O operations
    00584     //
    00585     ExFreePool(IOBuffer);
    00586
    00587     return Status;
    00588 }

RESULT HvpRecoverData | ( | PHHIVE | Hive,
|  | BOOLEAN | ReadOnly,
|  | PHCELL_INDEX TailDisplay | OPTIONAL
| ) |

Definition at line 847 of file hiveload.c.

References _HHIVE::Allocate, ASSERT, _HHIVE::BaseBlock, Bin, _HMAP_ENTRY::BinAddress, BitMap, _HMAP_ENTRY::BlockAddress, _HHIVE::Cluster, _HHIVE::DirtyAlloc, _HHIVE::DirtyCount, _HHIVE::DirtyVector, End, ErrorExit(), ExAllocatePoolWithTag, ExFreePool(), Fail, FALSE, _HBIN::FileOffset, _HHIVE::FileRead, _HHIVE::Free, HBIN_SIGNATURE, HFILE_TYPE_LOG, Hive, HiveSuccess, HLOG_DV_SIGNATURE, HMAP_BASE, HMAP_NEWALLOC, HSECTOR_SIZE, HvCheckHiveDebug, HvMarkDirty(), HvpEnlistBinInMap(), HvpEnlistFreeCells(), HvpGetCellMap(), _HBASE_BLOCK::Length, NoMemory, NT_SUCCESS, NULL, PagedPool, _HHIVE::ReadOnly, ROUND_UP, RtlInitializeBitMap(), RtlNumberOfSetBits(), _HBIN::Signature, Size, _HBIN::Size, Start, TRUE, and VALIDATE_CELL_MAP.

Referenced by HvLoadHive().

    00854                    :
    00855
    00856     Apply the corrections in the log file to the hive memory image.
    00857
    00858     ALGORITHM:
    00859
    00860         compute size of dirty vector
    00861         read in dirty vector
    00862         if (i/o error)
    00863             return Fail
    00864
    00865         skip first cluster of data (already processed as log)
    00866         sweep vector, looking for runs of bits
    00867             address of first bit is used to compute memory offset
    00868             length of run is length of block to read
    00869             assert always a cluster multiple
    00870             file offset kept by running counter
    00871             read
    00872             if (i/o error)
    00873                 return fail
    00874
    00875         return success
    00876
    00877     NOTE:   It is assumed that the data part of the Hive has been
    00878             read into a single contiguous block, at Image.
    00879
    00880 Arguments:
    00881
    00882     Hive - supplies a pointer to the hive control structure for the
    00883             hive of interest
    00884
    00885     ReadOnly - by the time this function is called, the hive is forced to the
    00886             ready-only state. At the end, if recovery goes OK, we restore the
    00887             hive at it's original state, and enlist all free cells.
    00888
    00889     TailDisplay - array containing the tail ends of the free cell lists - optional
    00890
    00891 Return Value:
    00892
    00893     RESULT
    00894
    00895 --*/
    00896 {
    00897     ULONG       Cluster;
    00898     ULONG       ClusterSize;
    00899     ULONG       VectorSize;
    00900     PULONG      Vector;
    00901     ULONG       FileOffset;
    00902     BOOLEAN     rc;
    00903     ULONG       Current;
    00904     ULONG       Start;
    00905     ULONG       End;
    00906     ULONG       Address;
    00907     PUCHAR      MemoryBlock;
    00908     RTL_BITMAP  BitMap;
    00909     ULONG       Length;
    00910     ULONG       DirtyVectorSignature = 0;
    00911     ULONG       i;
    00912     PHMAP_ENTRY Me;
    00913     PHBIN       Bin;
    00914     PHBIN       NewBin;
    00915     PUCHAR      SectorImage;
    00916     PUCHAR      Source;
    00917     PHBIN       SourceBin;
    00918     ULONG       SectorOffsetInBin;
    00919     ULONG       SectorOffsetInBlock;
    00920     ULONG       BlockOffsetInBin;
    00921     ULONG       NumberOfSectors;
    00922
    00923     //
    00924     // compute size of dirty vector, read and check signature, read vector
    00925     //
    00926     Cluster = Hive->Cluster;
    00927     ClusterSize = Cluster * HSECTOR_SIZE;
    00928     Length = Hive->BaseBlock->Length;
    00929     VectorSize = (Length / HSECTOR_SIZE) / 8;       // VectorSize == Bytes
    00930     FileOffset = ClusterSize;
    00931
    00932     //
    00933     // get and check signature
    00934     //
    00935     rc = (Hive->FileRead)(
    00936             Hive,
    00937             HFILE_TYPE_LOG,
    00938             &FileOffset,
    00939             (PVOID)&DirtyVectorSignature,
    00940             sizeof(DirtyVectorSignature)
    00941             );
    00942     if (rc == FALSE) {
    00943         return Fail;
    00944     }
    00945
    00946     if (DirtyVectorSignature != HLOG_DV_SIGNATURE) {
    00947         return Fail;
    00948     }
    00949
    00950     //
    00951     // get the actual vector
    00952     //
    00953     Vector = (PULONG)((Hive->Allocate)(ROUND_UP(VectorSize,sizeof(ULONG)), TRUE));
    00954     if (Vector == NULL) {
    00955         return NoMemory;
    00956     }
    00957     rc = (Hive->FileRead)(
    00958             Hive,
    00959             HFILE_TYPE_LOG,
    00960             &FileOffset,            // dirty vector right after header
    00961             (PVOID)Vector,
    00962             VectorSize
    00963             );
    00964     if (rc == FALSE) {
    00965         (Hive->Free)(Vector, VectorSize);
    00966         return Fail;
    00967     }
    00968     FileOffset = ROUND_UP(FileOffset, ClusterSize);
    00969
    00970
    00971     //
    00972     // step through the diry map, reading in the corresponding file bytes
    00973     //
    00974     Current = 0;
    00975     VectorSize = VectorSize * 8;        // VectorSize == bits
    00976
    00977     RtlInitializeBitMap(&BitMap, Vector, VectorSize);
    00978
    00979     while (Current < VectorSize) {
    00980
    00981         //
    00982         // find next contiguous block of entries to read in
    00983         //
    00984         for (i = Current; i < VectorSize; i++) {
    00985             if (RtlCheckBit(&BitMap, i) == 1) {
    00986                 break;
    00987             }
    00988         }
    00989         Start = i;
    00990
    00991         for ( ; i < VectorSize; i++) {
    00992             if (RtlCheckBit(&BitMap, i) == 0) {
    00993                 break;
    00994             }
    00995         }
    00996         End = i;
    00997         Current = End;
    00998
    00999         //
    01000         // Start == number of 1st sector, End == number of Last sector + 1
    01001         //
    01002         Length = (End - Start) * HSECTOR_SIZE;
    01003
    01004         if( 0 == Length ) {
    01005             // no more dirty blocks.
    01006             break;
    01007         }
    01008         //
    01009         // allocate a buffer to read the whole run from the file; This is a temporary
    01010         // block that'll be freed immediately, so don't charge quota for it.
    01011         //
    01012         MemoryBlock = (PUCHAR)ExAllocatePoolWithTag(PagedPool, Length, CM_POOL_TAG);
    01013         if( MemoryBlock == NULL ) {
    01014             goto ErrorExit;
    01015         }
    01016
    01017         rc = (Hive->FileRead)(
    01018                 Hive,
    01019                 HFILE_TYPE_LOG,
    01020                 &FileOffset,
    01021                 (PVOID)MemoryBlock,
    01022                 Length
    01023                 );
    01024
    01025         ASSERT((FileOffset % ClusterSize) == 0);
    01026         if (rc == FALSE) {
    01027             ExFreePool(MemoryBlock);
    01028             goto ErrorExit;
    01029         }
    01030
    01031         Source = MemoryBlock;
    01032         //
    01033         // copy recovered data in the right locations inside the in-memory bins
    01034         //
    01035         while( Start < End ) {
    01036             Address = Start * HSECTOR_SIZE;
    01037
    01038             Me = HvpGetCellMap(Hive, Address);
    01039             VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address);
    01040
    01041             Bin = (PHBIN)(Me->BinAddress & HMAP_BASE);
    01042             //
    01043             // compute the memory address where data should be copied
    01044             //
    01045             SectorOffsetInBin = Address - Bin->FileOffset;
    01046
    01047             if( ( SectorOffsetInBin == 0 ) && ( ((PHBIN)Source)->Size > Bin->Size ) ){
    01048                 //
    01049                 // Bin in the log file is bigger than the one in memory;
    01050                 // two or more bins must have been coalesced
    01051                 //
    01052                 ASSERT( Me->BinAddress & HMAP_NEWALLOC );
    01053
    01054                 SourceBin = (PHBIN)Source;
    01055
    01056                 //
    01057                 // new bin must have the right offset
    01058                 //
    01059                 ASSERT( Address == SourceBin->FileOffset );
    01060                 ASSERT( SourceBin->Signature == HBIN_SIGNATURE );
    01061                 //
    01062                 // entire bin should be dirty
    01063                 //
    01064                 ASSERT( (SourceBin->FileOffset + SourceBin->Size) <= End * HSECTOR_SIZE );
    01065
    01066                 //
    01067                 // Allocate the right size for the new bin
    01068                 //
    01069                 NewBin = (PHBIN)(Hive->Allocate)(SourceBin->Size, TRUE);
    01070                 if (NewBin == NULL) {
    01071                     goto ErrorExit;
    01072                 }
    01073
    01074                 //
    01075                 // Copy the old data into the new bin and free old bins
    01076                 //
    01077                 while(Bin->FileOffset < (Address + SourceBin->Size)) {
    01078
    01079                     RtlCopyMemory((PUCHAR)NewBin + (Bin->FileOffset - Address),Bin, Bin->Size);
    01080
    01081                     //
    01082                     // Do not delist as we didn't enlisted  (when hive needs recovery)
    01083                     //
    01084                     //HvpDelistBinFreeCells(Hive,Bin,Stable,TailDisplay);
    01085
    01086                     //
    01087                     // Advance to the new bin
    01088                     //
    01089                     if( (Bin->FileOffset + Bin->Size) < Hive->BaseBlock->Length ) {
    01090                         Me = HvpGetCellMap(Hive, Bin->FileOffset + Bin->Size);
    01091                         VALIDATE_CELL_MAP(__LINE__,Me,Hive,Bin->FileOffset + Bin->Size);
    01092
    01093                         //
    01094                         // Free the old bin
    01095                         //
    01096                         (Hive->Free)(Bin, Bin->Size);
    01097
    01098                         //
    01099                         // the new address must be the begining of a new allocation
    01100                         //
    01101                         ASSERT( Me->BinAddress & HMAP_NEWALLOC );
    01102
    01103                         Bin = (PHBIN)(Me->BinAddress & HMAP_BASE);
    01104                     } else {
    01105                         //
    01106                         // we are at the end of the hive here; just break out of the loop
    01107                         //
    01108                         ASSERT( (Address + SourceBin->Size) == Hive->BaseBlock->Length );
    01109                         ASSERT( (Bin->FileOffset + Bin->Size) == Hive->BaseBlock->Length );
    01110
    01111                         //
    01112                         // Free the old bin
    01113                         //
    01114                         (Hive->Free)(Bin, Bin->Size);
    01115
    01116                         //
    01117                         // debug purposes only
    01118                         //
    01119                         ASSERT( (Bin = NULL) == NULL );
    01120
    01121                         // bail out of while loop
    01122                         break;
    01123                     }
    01124
    01125                 }
    01126
    01127 #if DBG
    01128                 //
    01129                 // validation: bin size increase must come from coalescing of former bins
    01130                 // (i.e. bins are never split!!!)
    01131                 //
    01132                 if( Bin != NULL ) {
    01133                     ASSERT( Bin->FileOffset == (Address + SourceBin->Size));
    01134                 }
    01135 #endif
    01136
    01137                 //
    01138                 // Now overwrite the modified data !
    01139                 //
    01140
    01141                 while( (Address < (SourceBin->FileOffset + SourceBin->Size)) && (Start < End) ) {
    01142                     RtlCopyMemory((PUCHAR)NewBin + (Address - SourceBin->FileOffset),Source, HSECTOR_SIZE);
    01143
    01144                     //
    01145                     // skip to the next sector
    01146                     //
    01147                     Start++;
    01148                     Source += HSECTOR_SIZE;
    01149                     Address += HSECTOR_SIZE;
    01150                 }
    01151
    01152                 //
    01153                 // first sector of the new bin is always restaured from the log file!
    01154                 //
    01155                 ASSERT(NewBin->FileOffset == SourceBin->FileOffset);
    01156                 ASSERT(NewBin->Size == SourceBin->Size);
    01157
    01158             } else {
    01159                 //
    01160                 // Normal case: sector recovery somewhere in the middle of the bin
    01161                 //
    01162
    01163
    01164                 //
    01165                 // Do not delist as we didn't enlisted  (when hive needs recovery)
    01166                 //
    01167                 //HvpDelistBinFreeCells(Hive,Bin,Stable,TailDisplay);
    01168
    01169                 //
    01170                 // Offset should fall within bin memory layout
    01171                 //
    01172                 ASSERT( SectorOffsetInBin < Bin->Size );
    01173
    01174                 BlockOffsetInBin = (ULONG)((PUCHAR)Me->BlockAddress - (PUCHAR)Bin);
    01175                 SectorOffsetInBlock = SectorOffsetInBin - BlockOffsetInBin;
    01176
    01177                 //
    01178                 // sanity check; address should  be the same relative to eigther begining of the bin or begining of the block
    01179                 //
    01180                 ASSERT(((PUCHAR)Me->BlockAddress + SectorOffsetInBlock) == ((PUCHAR)Bin + SectorOffsetInBin));
    01181
    01182                 SectorImage = (PUCHAR)((PUCHAR)Me->BlockAddress + SectorOffsetInBlock);
    01183
    01184                 //
    01185                 // both source and destination should be valid at this point
    01186                 //
    01187                 ASSERT( SectorImage < ((PUCHAR)Bin + Bin->Size) );
    01188                 ASSERT( Source < (MemoryBlock + Length) );
    01189
    01190                 NumberOfSectors = 0;
    01191                 while( ( (SectorImage + (NumberOfSectors * HSECTOR_SIZE)) < (PUCHAR)((PUCHAR)Bin + Bin->Size) ) &&
    01192                         ( (Start + NumberOfSectors ) < End )    ) {
    01193                     //
    01194                     // we are still inside the same bin;
    01195                     // deal with all sectors inside the same bin at once
    01196                     //
    01197                     NumberOfSectors++;
    01198                 }
    01199
    01200                 //
    01201                 // finally, copy the memory
    01202                 //
    01203                 RtlCopyMemory(SectorImage,Source, NumberOfSectors * HSECTOR_SIZE);
    01204
    01205                 NewBin = Bin;
    01206
    01207                 //
    01208                 // skip to the next sector
    01209                 //
    01210                 Start += NumberOfSectors;
    01211                 Source += NumberOfSectors * HSECTOR_SIZE;
    01212
    01213             }
    01214
    01215             //
    01216             // rebuild the map anyway
    01217             //
    01218             if( !NT_SUCCESS(HvpEnlistBinInMap(Hive, Length, NewBin, NewBin->FileOffset, TailDisplay)) ) {
    01219                 goto ErrorExit;
    01220             }
    01221         }
    01222
    01223         //
    01224         // get rid of the temporary pool
    01225         //
    01226         ExFreePool(MemoryBlock);
    01227     }
    01228
    01229     //
    01230     // now, after we have successfully recovered, enlist all free cells
    01231     // and restore the hive to it's original state
    01232     //
    01233     Hive->ReadOnly = ReadOnly;
    01234
    01235     if( ReadOnly == FALSE ) {
    01236         //
    01237         // no point going through this loop if the hive is read-only
    01238         //
    01239         Address = 0;
    01240         while( Address < Hive->BaseBlock->Length ) {
    01241             Me = HvpGetCellMap(Hive, Address);
    01242             VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address);
    01243             Bin = (PHBIN)(Me->BinAddress & HMAP_BASE);
    01244
    01245             ASSERT( Bin->FileOffset == Address );
    01246             ASSERT( Bin->Signature == HBIN_SIGNATURE );
    01247
    01248             //
    01249             // add free cells in the bin to the appropriate free lists
    01250             //
    01251             if ( ! HvpEnlistFreeCells(Hive, Bin, Address,TailDisplay)) {
    01252                 HvCheckHiveDebug.Hive = Hive;
    01253                 HvCheckHiveDebug.Status = 0xA004;
    01254                 HvCheckHiveDebug.Space = Bin->Size;
    01255                 HvCheckHiveDebug.MapPoint = Address;
    01256                 HvCheckHiveDebug.BinPoint = Bin;
    01257                 goto ErrorExit;
    01258             }
    01259
    01260             Address += Bin->Size;
    01261         }
    01262     }
    01263
    01264     //
    01265     // put correct dirty vector in Hive so that recovered data
    01266     // can be correctly flushed
    01267     //
    01268     RtlInitializeBitMap(&(Hive->DirtyVector), Vector, VectorSize);
    01269     Hive->DirtyCount = RtlNumberOfSetBits(&Hive->DirtyVector);
    01270     Hive->DirtyAlloc = VectorSize * 8;
    01271     HvMarkDirty(Hive, 0, sizeof(HBIN));  // force header of 1st bin dirty
    01272     return HiveSuccess;
    01273
    01274 ErrorExit:
    01275     //
    01276     // free the dirty vector and return failure
    01277     //
    01278     (Hive->Free)(Vector, VectorSize);
    01279     return Fail;
    01280 }

## Variable Documentation

PHBIN BinPoint

| Definition at line 95 of file hiveload.c.

PHHIVE Hive

| Definition at line 91 of file hiveload.c.

struct { ... } HvCheckHiveDebug

HCELL_INDEX MapPoint

| Definition at line 94 of file hiveload.c.

ULONG Space

| Definition at line 93 of file hiveload.c.

ULONG Status

| Definition at line 92 of file hiveload.c.