test: cmtrecpy.c File Reference

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

# cmtrecpy.c File Reference

`#include "cmp.h"`

Go to the source code of this file.

## Classes

struct | CMP_COPY_STACK_ENTRY

## Defines

#define | DEBUG_TREE_SYNC FALSE
#define | CMP_INITIAL_STACK_SIZE 1024

## Typedefs

typedef * | PCMP_COPY_STACK_ENTRY

## Functions

BOOLEAN | CmpCopySyncTree2 (PCMP_COPY_STACK_ENTRY CmpCopyStack, ULONG CmpCopyStackSize, ULONG CmpCopyStackTop, PHHIVE CmpSourceHive, PHHIVE CmpTargetHive, BOOLEAN CopyVolatile, CMP_COPY_TYPE CopyType)
BOOLEAN | CmpFreeKeyValues (PHHIVE Hive, HCELL_INDEX Cell, PCM_KEY_NODE Node)
BOOLEAN | CmpSyncKeyValues (PHHIVE SourceHive, HCELL_INDEX SourceKeyCell, PCM_KEY_NODE SourceKeyNode, PHHIVE TargetHive, HCELL_INDEX TargetKeyCell, PCM_KEY_NODE TargetKeyNode)
BOOLEAN | CmpMergeKeyValues (PHHIVE SourceHive, HCELL_INDEX SourceKeyCell, PCM_KEY_NODE SourceKeyNode, PHHIVE TargetHive, HCELL_INDEX TargetKeyCell, PCM_KEY_NODE TargetKeyNode)
BOOLEAN | CmpSyncSubKeysAfterDelete (PHHIVE SourceHive, PCM_KEY_NODE SourceCell, PHHIVE TargetHive, PCM_KEY_NODE TargetCell, WCHAR *NameBuffer)
BOOLEAN | CmpMarkKeyValuesDirty (PHHIVE Hive, HCELL_INDEX Cell, PCM_KEY_NODE Node)
BOOLEAN | CmpMarkKeyParentDirty (PHHIVE Hive, HCELL_INDEX Cell)
BOOLEAN | CmpCopySyncTree (PHHIVE SourceHive, HCELL_INDEX SourceCell, PHHIVE TargetHive, HCELL_INDEX TargetCell, BOOLEAN CopyVolatile, CMP_COPY_TYPE CopyType)
HCELL_INDEX | CmpCopyKeyPartial (PHHIVE SourceHive, HCELL_INDEX SourceKeyCell, PHHIVE TargetHive, HCELL_INDEX Parent, BOOLEAN CopyValues)
HCELL_INDEX | CmpCopyValue (PHHIVE SourceHive, HCELL_INDEX SourceValueCell, PHHIVE TargetHive, HSTORAGE_TYPE Type)
HCELL_INDEX | CmpCopyCell (PHHIVE SourceHive, HCELL_INDEX SourceCell, PHHIVE TargetHive, HSTORAGE_TYPE Type)
VOID | CmpInitializeKeyNameString (PCM_KEY_NODE Cell, PUNICODE_STRING KeyName, WCHAR *NameBuffer)
VOID | CmpInitializeValueNameString (PCM_KEY_VALUE Cell, PUNICODE_STRING ValueName, WCHAR *NameBuffer)

## Define Documentation

#define CMP_INITIAL_STACK_SIZE 1024

| Definition at line 38 of file cmtrecpy.c. Referenced by CmpCopySyncTree().

#define DEBUG_TREE_SYNC FALSE

| Definition at line 31 of file cmtrecpy.c.

## Typedef Documentation

typedef * PCMP_COPY_STACK_ENTRY

| Referenced by CmpCopySyncTree(), and CmpCopySyncTree2().

## Function Documentation

HCELL_INDEX CmpCopyCell | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceCell,
|  | PHHIVE | TargetHive,
|  | HSTORAGE_TYPE | Type
| ) |

Definition at line 1009 of file cmtrecpy.c.

References CML_MINOR, CMLOG, CMS_SAVRES, HCELL_INDEX, HCELL_NIL, HvAllocateCell(), HvGetCell, and HvGetCellSize().

Referenced by CmpCopyKeyPartial(), CmpCopyValue(), and CmpSyncKeyValues().

    01017                    :
    01018
    01019     Copy SourceHive.SourceCell to TargetHive.TargetCell.
    01020
    01021 Arguments:
    01022
    01023     SourceHive - pointer to hive control structure for source
    01024
    01025     SourceCell - index of cell to copy from
    01026
    01027     TargetHive - pointer to hive control structure for target
    01028
    01029     Type - storage type (stable or volatile) of new cell
    01030
    01031 Return Value:
    01032
    01033     HCELL_INDEX of new cell, or HCELL_NIL if failure.
    01034
    01035 --*/
    01036 {
    01037     PVOID   psource;
    01038     PVOID   ptarget;
    01039     ULONG   size;
    01040     HCELL_INDEX newcell;
    01041
    01042     CMLOG(CML_MINOR, CMS_SAVRES) {
    01043         KdPrint(("CmpCopyCell:\n"));
    01044         KdPrint(("\tSourceHive=%08lx SourceCell=%08lx\n",SourceHive,SourceCell));
    01045         KdPrint(("\tTargetHive=%08lx\n",TargetHive));
    01046     }
    01047
    01048     psource = HvGetCell(SourceHive, SourceCell);
    01049     size = HvGetCellSize(SourceHive, psource);
    01050
    01051     newcell = HvAllocateCell(TargetHive, size, Type);
    01052     if (newcell == HCELL_NIL) {
    01053         return HCELL_NIL;
    01054     }
    01055
    01056     ptarget = HvGetCell(TargetHive, newcell);
    01057
    01058     RtlCopyMemory(ptarget, psource, size);
    01059
    01060     return newcell;
    01061 }

HCELL_INDEX CmpCopyKeyPartial | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceKeyCell,
|  | PHHIVE | TargetHive,
|  | HCELL_INDEX | Parent,
|  | BOOLEAN | CopyValues
| ) |

Definition at line 686 of file cmtrecpy.c.

References _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, CML_MINOR, CMLOG, CmpAssignSecurityDescriptor(), CmpCopyCell(), CmpCopyValue(), CMS_SAVRES, _CHILD_LIST::Count, _CM_KEY_SECURITY::Descriptor, FALSE, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, KEY_COMP_NAME, KEY_HIVE_ENTRY, KEY_NO_DELETE, _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyNode, _CELL_DATA::_u::KeySecurity, _CHILD_LIST::List, NT_SUCCESS, NTSTATUS(), _CM_KEY_NODE::Parent, _CM_KEY_NODE::Security, Stable, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and Volatile.

Referenced by CmpCopySyncTree2(), CmpLoadHiveVolatile(), CmRestoreKey(), CmSaveKey(), and CmSaveMergedKeys().

    00695                    :
    00696
    00697     Copy a key body and all of its values, but NOT its subkeylist or
    00698     subkey entries.  SubKeyList.Count will be set to 0.
    00699
    00700 Arguments:
    00701
    00702     SourceHive - pointer to hive control structure for source
    00703
    00704     SourceKeyCell - value entry being copied
    00705
    00706     TargetHive - pointer to hive control structure for target
    00707
    00708     Parent - parent value to set into newly created key body
    00709
    00710     CopyValues - if FALSE value entries will not be copied, if TRUE, they will
    00711
    00712 Return Value:
    00713
    00714     HCELL_INDEX - Cell of body of new key entry, or HCELL_NIL
    00715         if some error.
    00716
    00717 --*/
    00718 {
    00719     NTSTATUS    status;
    00720     HCELL_INDEX newkey = HCELL_NIL;
    00721     HCELL_INDEX newclass = HCELL_NIL;
    00722     HCELL_INDEX newsecurity = HCELL_NIL;
    00723     HCELL_INDEX newlist = HCELL_NIL;
    00724     HCELL_INDEX newvalue;
    00725     BOOLEAN success = FALSE;
    00726     ULONG   i;
    00727     PCELL_DATA psrckey;
    00728     PCM_KEY_NODE ptarkey;
    00729     PCELL_DATA psrclist;
    00730     PCELL_DATA ptarlist;
    00731     PCELL_DATA psrcsecurity;
    00732     HCELL_INDEX security;
    00733     HCELL_INDEX class;
    00734     ULONG   classlength;
    00735     ULONG   count;
    00736     ULONG   Type;
    00737
    00738     CMLOG(CML_MINOR, CMS_SAVRES) {
    00739         KdPrint(("CmpCopyKeyPartial:\n"));
    00740         KdPrint(("\tSHive=%08lx SCell=%08lx\n",SourceHive,SourceKeyCell));
    00741         KdPrint(("\tTHive=%08lx\n",TargetHive));
    00742     }
    00743
    00744
    00745     //
    00746     // get description of source
    00747     //
    00748     if (Parent == HCELL_NIL) {
    00749         //
    00750         // This is a root node we are creating, so don't make it volatile.
    00751         //
    00752         Type = Stable;
    00753     } else {
    00754         Type = HvGetCellType(Parent);
    00755     }
    00756     psrckey = HvGetCell(SourceHive, SourceKeyCell);
    00757     security = psrckey->u.KeyNode.Security;
    00758     class = psrckey->u.KeyNode.Class;
    00759     classlength = psrckey->u.KeyNode.ClassLength;
    00760
    00761     //
    00762     // Allocate and copy the body
    00763     //
    00764     newkey = CmpCopyCell(SourceHive, SourceKeyCell, TargetHive, Type);
    00765     if (newkey == HCELL_NIL) {
    00766         goto DoFinally;
    00767     }
    00768
    00769     //
    00770     // Allocate and copy class
    00771     //
    00772     if (classlength > 0) {
    00773         newclass = CmpCopyCell(SourceHive, class, TargetHive, Type);
    00774         if (newclass == HCELL_NIL) {
    00775             goto DoFinally;
    00776         }
    00777     }
    00778
    00779     //
    00780     // Fill in the target body
    00781     //
    00782     ptarkey = (PCM_KEY_NODE)HvGetCell(TargetHive, newkey);
    00783
    00784     ptarkey->Class = newclass;
    00785     ptarkey->Security = HCELL_NIL;
    00786     ptarkey->SubKeyLists[Stable] = HCELL_NIL;
    00787     ptarkey->SubKeyLists[Volatile] = HCELL_NIL;
    00788     ptarkey->SubKeyCounts[Stable] = 0;
    00789     ptarkey->SubKeyCounts[Volatile] = 0;
    00790     ptarkey->Parent = Parent;
    00791
    00792     ptarkey->Flags = (psrckey->u.KeyNode.Flags & KEY_COMP_NAME);
    00793     if (Parent == HCELL_NIL) {
    00794         ptarkey->Flags |= KEY_HIVE_ENTRY + KEY_NO_DELETE;
    00795     }
    00796
    00797     //
    00798     // Allocate and copy security
    00799     //
    00800     psrcsecurity = HvGetCell(SourceHive, security);
    00801
    00802     status = CmpAssignSecurityDescriptor(TargetHive,
    00803                                          newkey,
    00804                                          ptarkey,
    00805                                          &(psrcsecurity->u.KeySecurity.Descriptor));
    00806     if (!NT_SUCCESS(status)) {
    00807         goto DoFinally;
    00808     }
    00809
    00810
    00811     //
    00812     // Set up the value list
    00813     //
    00814     count = psrckey->u.KeyNode.ValueList.Count;
    00815
    00816     if ((count == 0) || (CopyValues == FALSE)) {
    00817         ptarkey->ValueList.List = HCELL_NIL;
    00818         ptarkey->ValueList.Count = 0;
    00819         success = TRUE;
    00820     } else {
    00821
    00822         psrclist = HvGetCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
    00823
    00824         newlist = HvAllocateCell(
    00825                     TargetHive,
    00826                     count * sizeof(HCELL_INDEX),
    00827                     Type
    00828                     );
    00829         if (newlist == HCELL_NIL) {
    00830             goto DoFinally;
    00831         }
    00832         ptarkey->ValueList.List = newlist;
    00833         ptarlist = HvGetCell(TargetHive, newlist);
    00834
    00835
    00836         //
    00837         // Copy the values
    00838         //
    00839         for (i = 0; i < count; i++) {
    00840
    00841             newvalue = CmpCopyValue(
    00842                             SourceHive,
    00843                             psrclist->u.KeyList[i],
    00844                             TargetHive,
    00845                             Type
    00846                             );
    00847
    00848             if (newvalue != HCELL_NIL) {
    00849
    00850                 ptarlist->u.KeyList[i] = newvalue;
    00851
    00852             } else {
    00853
    00854                 for (; i > 0; i--) {
    00855                     HvFreeCell(
    00856                         TargetHive,
    00857                         ptarlist->u.KeyList[i - 1]
    00858                         );
    00859                 }
    00860                 goto DoFinally;
    00861             }
    00862         }
    00863         success = TRUE;
    00864     }
    00865
    00866 DoFinally:
    00867     if (success == FALSE) {
    00868
    00869         if (newlist != HCELL_NIL) {
    00870             HvFreeCell(TargetHive, newlist);
    00871         }
    00872
    00873         if (newsecurity != HCELL_NIL) {
    00874             HvFreeCell(TargetHive, newsecurity);
    00875         }
    00876
    00877         if (newclass != HCELL_NIL) {
    00878             HvFreeCell(TargetHive, newclass);
    00879         }
    00880
    00881         if (newkey != HCELL_NIL) {
    00882             HvFreeCell(TargetHive, newkey);
    00883         }
    00884
    00885         return HCELL_NIL;
    00886
    00887     } else {
    00888
    00889         return newkey;
    00890     }
    00891 }

BOOLEAN CmpCopySyncTree | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceCell,
|  | PHHIVE | TargetHive,
|  | HCELL_INDEX | TargetCell,
|  | BOOLEAN | CopyVolatile,
|  | CMP_COPY_TYPE | CopyType
| ) |

Definition at line 127 of file cmtrecpy.c.

References CML_MAJOR, CMLOG, CMP_INITIAL_STACK_SIZE, CmpCopySyncTree2(), CMS_SAVRES, ExAllocatePool, ExFreePool(), FALSE, NULL, PagedPool, and PCMP_COPY_STACK_ENTRY.

    00137                    :
    00138
    00139     This routine can perform two distinct (yet similar) tasks:
    00140     a tree copy or a tree synchronization (sync). Which task
    00141     is performed is determined by the TreeSync parameter.
    00142
    00143     For both operations:
    00144     --------------------
    00145
    00146     The source root key and target root key must exist in advance.
    00147     These root nodes and their value entries will NOT be copied/synced.
    00148
    00149     NOTE:   Volatile keys are only copied/synced if the CopyVolatile
    00150             parameter is set to true.
    00151
    00152
    00153     For a tree copy:
    00154     ----------------
    00155
    00156     A tree is copied from source to destination. The subkeys
    00157     of the source root key and the full trees under those
    00158     subkeys will be copied to a new tree at target root key.
    00159
    00160     NOTE:   If this call fails part way through, it will NOT undo
    00161             any successfully completed key copies, thus a partial
    00162             tree copy CAN occur.
    00163
    00164     For a tree sync:
    00165     ----------------
    00166
    00167     The target tree is synchronized with the source tree. It is
    00168     assumed that for a certain period of the time the target tree
    00169     has remained unmodified while modifications may have been made
    00170     to the source tree. During a sync, any such modifications
    00171     to the source tree are made to the target tree. Thus, at the
    00172     end of a successful sync, the target tree is identical to the
    00173     source tree.
    00174
    00175     Since only things that have changed in the source tree
    00176     are modified in the target tree, a sync operation is far
    00177     more efficient than the delete/copy operations necessary
    00178     to accomplish the same results.
    00179
    00180     NOTE: It is assumed that no open handles are held
    00181           on any target tree keys. Registry in-memory data
    00182           structures may be corrupted if this is not true.
    00183
    00184 Arguments:
    00185
    00186     SourceHive - pointer to hive control structure for source
    00187
    00188     SourceCell - index of cell at root of tree to copy/sync
    00189
    00190     TargetHive - pointer to hive control structure for target
    00191
    00192     TargetCell - pointer to cell at root of target tree
    00193
    00194     CopyVolatile - indicates whether volatile keys should be
    00195                    copied/synced.
    00196
    00197     CopyType - indicates the type of the copy operation:
    00198                 Copy  - A copy is requested
    00199                 Sync  - A sync is requested
    00200                 Merge - A merge is requested i.e.:
    00201                     1. the target nodes that are not present on the source tree are not
    00202                     deleted.
    00203                     2. the target nodes that are present in the source tree gets overrided
    00204                     no matter what the LastWriteTime value is.
    00205 Return Value:
    00206
    00207     BOOLEAN - Result code from call, among the following:
    00208         TRUE - it worked
    00209         FALSE - the tree copy/sync was not completed (though more than 0
    00210                 keys may have been copied/synced)
    00211
    00212 --*/
    00213 {
    00214     BOOLEAN result;
    00215     PCMP_COPY_STACK_ENTRY   CmpCopyStack;
    00216
    00217     CMLOG(CML_MAJOR, CMS_SAVRES) {
    00218         KdPrint(("CmpCopyTree:\n"));
    00219     }
    00220
    00221     CmpCopyStack = ExAllocatePool(
    00222                         PagedPool,
    00223                         sizeof(CMP_COPY_STACK_ENTRY)*CMP_INITIAL_STACK_SIZE
    00224                         );
    00225     if (CmpCopyStack == NULL) {
    00226         return FALSE;
    00227     }
    00228     CmpCopyStack[0].SourceCell = SourceCell;
    00229     CmpCopyStack[0].TargetCell = TargetCell;
    00230
    00231     result = CmpCopySyncTree2(
    00232                 CmpCopyStack,
    00233                 CMP_INITIAL_STACK_SIZE,
    00234                 0,
    00235                 SourceHive,
    00236                 TargetHive,
    00237                 CopyVolatile,
    00238                 CopyType
    00239                 );
    00240
    00241     ExFreePool(CmpCopyStack);
    00242     return result;
    00243 }

BOOLEAN CmpCopySyncTree2 | ( | PCMP_COPY_STACK_ENTRY | CmpCopyStack,
|  | ULONG | CmpCopyStackSize,
|  | ULONG | CmpCopyStackTop,
|  | PHHIVE | CmpSourceHive,
|  | PHHIVE | CmpTargetHive,
|  | BOOLEAN | CopyVolatile,
|  | CMP_COPY_TYPE | CopyType
| ) |

Definition at line 251 of file cmtrecpy.c.

References CML_MINOR, CMLOG, CmpAddSubKey(), CmpCopyKeyPartial(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpInitializeKeyNameString(), CmpMarkKeyParentDirty(), CmpMergeKeyValues(), CmpSyncKeyValues(), CmpSyncSubKeysAfterDelete(), CMS_SAVRES, ExAllocatePool, ExFreePool(), FALSE, HCELL_INDEX, HCELL_NIL, HvGetCell, HvGetCellType, KeyName, _CM_KEY_NODE::LastWriteTime, MAX_KEY_NAME_LENGTH, Merge, NULL, PagedPool, PCMP_COPY_STACK_ENTRY, Stable, _CM_KEY_NODE::SubKeyCounts, Sync, TRUE, and Volatile.

Referenced by CmpCopySyncTree().

    00262                    :
    00263
    00264    This is a helper routine for CmpCopySyncTree. It accomplishes
    00265    the functionality described by that routine in a "virtually"
    00266    recursive manner which frees this routine from the limitations
    00267    of the Kernel stack.
    00268
    00269    This routine should not be called directly. Use CmpCopySyncTree!.
    00270
    00271 Arguments:
    00272
    00273     (All of these are "virtual globals")
    00274
    00275     CmpCopyStack - "global" pointer to stack for frames
    00276
    00277     CmpCopyStackSize - alloced size of stack
    00278
    00279     CmpCopyStackTop - current top
    00280
    00281     CmpSourceHive, CmpTargetHive - source and target hives
    00282
    00283     CopyVolatile, CopyType - same as CmpCopySyncTree.
    00284
    00285
    00286 Return Value:
    00287
    00288     BOOLEAN - Result code from call, among the following:
    00289         TRUE - it worked
    00290         FALSE - the tree copy/sync was not completed (though more than 0
    00291                 keys may have been copied/synced)
    00292
    00293 --*/
    00294 {
    00295     PCMP_COPY_STACK_ENTRY   Frame;
    00296     HCELL_INDEX             SourceChild;
    00297     HCELL_INDEX             NewSubKey;
    00298
    00299     BOOLEAN                 Ret = FALSE, SyncNeedsTreeCopy = FALSE;
    00300     UNICODE_STRING          KeyName;
    00301     PCM_KEY_NODE            SourceChildCell, TargetChildCell;
    00302     PCM_KEY_NODE            SourceCell, TargetCell;
    00303     ULONG                   SyncTreeCopyStackStart;
    00304     WCHAR                   *NameBuffer = NULL;
    00305
    00306     // A merge is a particular case of a sync !!!
    00307     BOOLEAN                 TreeSync = (CopyType == Sync || CopyType == Merge)?TRUE:FALSE;
    00308
    00309     CMLOG(CML_MINOR, CMS_SAVRES) {
    00310         KdPrint(("CmpCopyTree2:\n"));
    00311     }
    00312
    00313     if (TreeSync) {
    00314
    00315        //
    00316        // The sync operation involves some work with key names,
    00317        // so we must allocate a buffer used for key name decompression.
    00318        //
    00319
    00320        NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_NAME_LENGTH);
    00321        if(!NameBuffer) return FALSE;
    00322
    00323     }
    00324
    00325     //
    00326     // outer loop, apply to entire tree, emulate recursion here
    00327     // jump to here is a virtual call
    00328     //
    00329     Outer: while (TRUE) {
    00330
    00331         Frame = &(CmpCopyStack[CmpCopyStackTop]);
    00332
    00333         Frame->i = 0;
    00334
    00335     //
    00336     // inner loop, applies to one key
    00337     // jump to here is a virtual return
    00338     //
    00339         Inner: while (TRUE) {
    00340
    00341             SourceCell = (PCM_KEY_NODE)HvGetCell(CmpSourceHive, Frame->SourceCell);
    00342
    00343             SourceChild = CmpFindSubKeyByNumber(CmpSourceHive,
    00344                                                 SourceCell,
    00345                                                 Frame->i);
    00346             (Frame->i)++;
    00347
    00348             if ((SourceChild == HCELL_NIL) || (!CopyVolatile &&
    00349                                                (HvGetCellType(SourceChild) == Volatile))) {
    00350
    00351                 //
    00352                 // we've stepped through all the children (or we are only
    00353                 // interested in stable children and have just stepped through
    00354                 // the stable children and into the volatile ones)
    00355                 //
    00356
    00357                 if(TreeSync && (CopyType != Merge))
    00358                 {
    00359                    //
    00360                    // If we are here during a sync, that means most of sync operations
    00361                    // applied to the current SourceCell have been completed.
    00362                    // That is, we have:
    00363                    //   1) Synchronized SourceCell's values with its counterpart in the
    00364                    //      target tree.
    00365                    //   2) Synchronized any new SourceCell subkeys (subkeys present
    00366                    //      in SourceCell but not its counterpart) by creating
    00367                    //      and copying them to the proper place in the target tree.
    00368                    //
    00369                    // What this means is that SourceCell's counterpart in the target tree
    00370                    // (TargetCell) now has at least as many subkeys as SourceCell.
    00371                    //
    00372                    // This implies that if TargetCell now has more subkeys that SourceCell
    00373                    // than some subkeys of TargetCell are not present in the source tree
    00374                    // (probably because those keys were deleted from the source tree
    00375                    //  during the period between the previous sync and now).
    00376                    //
    00377                    // If such keys exist, then they must be delete them from TargetCell
    00378                    // in order to complete the sync. We do this below.
    00379                    //
    00380
    00381                    TargetCell = (PCM_KEY_NODE)HvGetCell(CmpTargetHive, Frame->TargetCell);
    00382
    00383                    //
    00384                    // Does TargetCell have more subkeys than SourceCell?
    00385                    //
    00386
    00387                    if((TargetCell->SubKeyCounts[Stable] +
    00388                        TargetCell->SubKeyCounts[Volatile]) >
    00389                       (SourceCell->SubKeyCounts[Stable] +
    00390
    00391                        // We only count the volatile keys if we are actually
    00392                        // syncing them. Note, however, that we always use
    00393                        // the volatile counts in TargetCell since we may
    00394                        // be syncing to a volatile tree where all keys are volatile.
    00395
    00396                        (CopyVolatile ? SourceCell->SubKeyCounts[Volatile] : 0)))
    00397
    00398                    {
    00399 #if DEBUG_TREE_SYNC
    00400                       KdPrint(("CONFIG: SubKey Deletion from Source Cell #%lu.\n",
    00401                                Frame->SourceCell));
    00402 #endif
    00403
    00404                       //
    00405                       // Delete what should be deleted from TargetCell
    00406                       //
    00407
    00408                       CmpSyncSubKeysAfterDelete(CmpSourceHive,
    00409                                                 SourceCell,
    00410                                                 CmpTargetHive,
    00411                                                 TargetCell,
    00412                                                 NameBuffer);
    00413                    }
    00414                 }
    00415
    00416                 break;
    00417             }
    00418
    00419             if (TreeSync) {
    00420
    00421                //
    00422                // For a sync, we want to check if the current child (subkey)
    00423                // of SourceCell is also a child of TargetCell - i.e. if
    00424                // the subkey in question has a counterpart in the target tree.
    00425                //
    00426                // There is no guarantee that the counterpart's index number
    00427                // will be the same so we must perform this check using
    00428                // the subkey name.
    00429                //
    00430
    00431                //
    00432                // Get the name of the current child
    00433                //
    00434
    00435                SourceChildCell = (PCM_KEY_NODE)HvGetCell(CmpSourceHive,
    00436                                                          SourceChild);
    00437
    00438                CmpInitializeKeyNameString(SourceChildCell,
    00439                                           &KeyName,
    00440                                           NameBuffer);
    00441
    00442                //
    00443                // Try to find the current child's counterpart in
    00444                // in the target tree using the child's name.
    00445                //
    00446
    00447                NewSubKey = CmpFindSubKeyByName(CmpTargetHive,
    00448                                                (PCM_KEY_NODE)HvGetCell(CmpTargetHive,
    00449                                                                        Frame->TargetCell),
    00450                                                &KeyName);
    00451
    00452
    00453                if (NewSubKey != HCELL_NIL) {
    00454
    00455                   //
    00456                   // Found it, the current child (subkey) has a counterpart
    00457                   // in the target tree. Thus, we just need to check if
    00458                   // the counterpart's values are out of date and should
    00459                   // be updated.
    00460                   //
    00461
    00462                   TargetChildCell = (PCM_KEY_NODE)HvGetCell(CmpTargetHive,
    00463                                                             NewSubKey);
    00464
    00465                   //
    00466                   // Check if the current subkey has been modified
    00467                   // more recently than its target tree counterpart.
    00468                   // When we are doing a tree merge, always override the target.
    00469                   //
    00470
    00471                   if ( (CopyType == Merge) ||
    00472                       ((TargetChildCell->LastWriteTime.QuadPart) <
    00473                       (SourceChildCell->LastWriteTime.QuadPart))) {
    00474
    00475                      //
    00476                      // The counterpart is out of date. Its values
    00477                      // must be synchornized with the current subkey.
    00478                      //
    00479 #if DEBUG_TREE_SYNC
    00480                      KdPrint(("CONFIG: Target Refresh.\n"));
    00481                      KdPrint(("CONFIG: Source Cell %lu = %.*S\n",
    00482                               SourceChild,
    00483                               KeyName.Length / sizeof(WCHAR),
    00484                               KeyName.Buffer));
    00485 #endif
    00486
    00487                      //
    00488                      // Sync up the key's values, sd, & class
    00489                      //
    00490
    00491                      if(CopyType == Merge) {
    00492                          if(!CmpMergeKeyValues(CmpSourceHive, SourceChild, SourceChildCell,
    00493                                               CmpTargetHive, NewSubKey, TargetChildCell)) {
    00494                             goto CopyEnd;
    00495                          }
    00496                      } else {
    00497                          if(!CmpSyncKeyValues(CmpSourceHive, SourceChild, SourceChildCell,
    00498                                               CmpTargetHive, NewSubKey, TargetChildCell)) {
    00499                             goto CopyEnd;
    00500                         }
    00501                      }
    00502
    00503                      //
    00504                      // Sync the timestamps so that we don't do this again.
    00505                      //
    00506
    00507                      TargetChildCell->LastWriteTime.QuadPart =
    00508                         SourceChildCell->LastWriteTime.QuadPart;
    00509
    00510                   }
    00511
    00512                   //
    00513                   // If we are here, then the current subkey's target
    00514                   // tree counterpart has been synchronized (or did not need
    00515                   // to be). Transfer control to the code that will apply
    00516                   // this function "recursively" to the current subkey in order
    00517                   // to continue the sync.
    00518                   //
    00519
    00520                   goto NewKeyCreated;
    00521
    00522                }
    00523
    00524                //
    00525                // If we are here, it means that the current child (subkey)
    00526                // does not have a counterpart in the target tree. This means
    00527                // we have encountered a new subkey in the source tree and must
    00528                // create it in the target tree.
    00529                //
    00530                // The standard copy code below will create this subkey. However,
    00531                // we must also make sure that the tree under this subkey is properly
    00532                // copied from source to target. The most efficient way of doing
    00533                // this is to temporarily forget that we are in a sync operation
    00534                // and merely perform a copy until the desired result is achieved.
    00535                //
    00536
    00537 #if DEBUG_TREE_SYNC
    00538                KdPrint(("CONFIG: New SubKey.\n"));
    00539                KdPrint(("CONFIG: Source Cell %lu = %.*S\n",
    00540                         SourceChild,
    00541                         KeyName.Length / sizeof(WCHAR),
    00542                         KeyName.Buffer));
    00543 #endif
    00544
    00545                //
    00546                // Indicate that we will just copy and not sync for a while
    00547                //
    00548
    00549                SyncNeedsTreeCopy = TRUE;
    00550
    00551             }
    00552
    00553             NewSubKey = CmpCopyKeyPartial(
    00554                                           CmpSourceHive,
    00555                                           SourceChild,
    00556                                           CmpTargetHive,
    00557                                           Frame->TargetCell,
    00558                                           TRUE
    00559                                           );
    00560
    00561
    00562             if (NewSubKey == HCELL_NIL) {
    00563
    00564                goto CopyEnd;
    00565             }
    00566
    00567             if ( !  CmpAddSubKey(
    00568                                  CmpTargetHive,
    00569                                  Frame->TargetCell,
    00570                                  NewSubKey
    00571                                  )
    00572                  ) {
    00573
    00574                goto CopyEnd;
    00575             }
    00576
    00577             //
    00578             // Check if the sync operation determined that this
    00579             // subtree should be copied
    00580             //
    00581
    00582             if(TreeSync && SyncNeedsTreeCopy) {
    00583
    00584                //
    00585                // We have just created a new key in the target tree
    00586                // with the above code. However, since this is a sync,
    00587                // the parent of that new key has not been created by our
    00588                // code and thus may not have been modified at all before
    00589                // the creation of the new key. But this parent now
    00590                // has a new child, and must therefore be marked as dirty.
    00591                //
    00592
    00593                if (! CmpMarkKeyParentDirty(CmpTargetHive, NewSubKey)) {
    00594
    00595                   goto CopyEnd;
    00596                }
    00597
    00598                //
    00599                // Record the stack level where we start the copy
    00600                // (and temporarily abandon the sync)
    00601                // so that we can return to the sync operation when this
    00602                // stack level is reached again (i.e. when the tree
    00603                // under the current subkey is fully copied)
    00604                //
    00605
    00606                SyncTreeCopyStackStart = CmpCopyStackTop;
    00607
    00608                //
    00609                // Pretend that this is not a sync in order
    00610                // to simply start copying
    00611                //
    00612
    00613                TreeSync = FALSE;
    00614             }
    00615
    00616 NewKeyCreated:
    00617
    00618                     //
    00619                     // We succeeded in copying/syncing the subkey, apply
    00620                     // ourselves to it
    00621                     //
    00622                     CmpCopyStackTop++;
    00623
    00624                     if (CmpCopyStackTop >= CmpCopyStackSize) {
    00625
    00626                         //
    00627                         // if we're here, it means that the tree
    00628                         // we're trying to copy is more than 1024
    00629                         // COMPONENTS deep (from 2048 to 256k bytes)
    00630                         // we could grow the stack, but this is pretty
    00631                         // severe, so return FALSE and fail the copy
    00632                         //
    00633
    00634                         goto CopyEnd;
    00635                     }
    00636
    00637                     CmpCopyStack[CmpCopyStackTop].SourceCell =
    00638                             SourceChild;
    00639
    00640                     CmpCopyStack[CmpCopyStackTop].TargetCell =
    00641                             NewSubKey;
    00642
    00643                     goto Outer;
    00644
    00645
    00646         } // Inner: while
    00647
    00648         if (CmpCopyStackTop == 0) {
    00649             Ret = TRUE;
    00650             goto CopyEnd;
    00651         }
    00652
    00653         CmpCopyStackTop--;
    00654         Frame = &(CmpCopyStack[CmpCopyStackTop]);
    00655
    00656         //
    00657         // We have just completed working at a certain stack level.
    00658         // This is a good time to check if we need to resume a temporarily
    00659         // suspended sync operation.
    00660         //
    00661
    00662         if(SyncNeedsTreeCopy && (CmpCopyStackTop == SyncTreeCopyStackStart))
    00663         {
    00664            //
    00665            // We've been copying a tree for a sync. But now, that tree is fully
    00666            // copied. So, let's resume the sync once again.
    00667            //
    00668
    00669            TreeSync = TRUE;
    00670            SyncNeedsTreeCopy = FALSE;
    00671         }
    00672
    00673
    00674         goto Inner;
    00675
    00676     } // Outer: while
    00677
    00678 CopyEnd:
    00679
    00680    if (NameBuffer) ExFreePool(NameBuffer);
    00681    return Ret;
    00682 }

HCELL_INDEX CmpCopyValue | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceValueCell,
|  | PHHIVE | TargetHive,
|  | HSTORAGE_TYPE | Type
| ) |

Definition at line 895 of file cmtrecpy.c.

References CM_KEY_VALUE_SMALL, CM_KEY_VALUE_SPECIAL_SIZE, CML_MINOR, CMLOG, CmpCopyCell(), CmpIsHKeyValueSmall, CMS_SAVRES, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, HCELL_INDEX, HCELL_NIL, HvFreeCell(), HvGetCell, _CELL_DATA::_u::KeyValue, and _CELL_DATA::u.

Referenced by CmpCopyKeyPartial(), CmpMergeKeyValues(), and CmpSyncKeyValues().

    00903                    :
    00904
    00905     Copy a value entry.  Copies the body of a value entry and the
    00906     data.  Returns cell of new value entry.
    00907
    00908 Arguments:
    00909
    00910     SourceHive - pointer to hive control structure for source
    00911
    00912     SourceValueCell - value entry being copied
    00913
    00914     TargetHive - pointer to hive control structure for target
    00915
    00916     Type - storage type to allocate for target (stable or volatile)
    00917
    00918 Return Value:
    00919
    00920     HCELL_INDEX - Cell of body of new value entry, or HCELL_NIL
    00921         if some error.
    00922
    00923 --*/
    00924 {
    00925     HCELL_INDEX newvalue;
    00926     HCELL_INDEX newdata;
    00927     PCELL_DATA pvalue;
    00928     ULONG       datalength;
    00929     HCELL_INDEX olddata;
    00930     ULONG       tempdata;
    00931     BOOLEAN     small;
    00932
    00933     CMLOG(CML_MINOR, CMS_SAVRES) {
    00934         KdPrint(("CmpCopyValue:\n"));
    00935         KdPrint(("\tSHive=%08lx SCell=%08lx\n",SourceHive,SourceValueCell));
    00936         KdPrint(("\tTargetHive=%08lx\n",TargetHive));
    00937     }
    00938
    00939     //
    00940     // get source data
    00941     //
    00942     pvalue = HvGetCell(SourceHive, SourceValueCell);
    00943     small = CmpIsHKeyValueSmall(datalength, pvalue->u.KeyValue.DataLength);
    00944     olddata = pvalue->u.KeyValue.Data;
    00945
    00946     //
    00947     // Copy body
    00948     //
    00949     newvalue = CmpCopyCell(SourceHive, SourceValueCell, TargetHive, Type);
    00950     if (newvalue == HCELL_NIL) {
    00951         return HCELL_NIL;
    00952     }
    00953
    00954     //
    00955     // Copy data (if any)
    00956     //
    00957     if (datalength > 0) {
    00958
    00959         if (datalength > CM_KEY_VALUE_SMALL) {
    00960
    00961             //
    00962             // there's data, and it's "big", so do standard copy
    00963             //
    00964             newdata = CmpCopyCell(SourceHive, olddata, TargetHive, Type);
    00965
    00966             if (newdata == HCELL_NIL) {
    00967                 HvFreeCell(TargetHive, newvalue);
    00968                 return HCELL_NIL;
    00969             }
    00970
    00971             pvalue = HvGetCell(TargetHive, newvalue);
    00972             pvalue->u.KeyValue.Data = newdata;
    00973             pvalue->u.KeyValue.DataLength = datalength;
    00974
    00975         } else {
    00976
    00977             //
    00978             // the data is small, but may be stored in either large or
    00979             // small format for historical reasons
    00980             //
    00981             if (small) {
    00982
    00983                 //
    00984                 // data is already small, so just do a body to body copy
    00985                 //
    00986                 tempdata = pvalue->u.KeyValue.Data;
    00987
    00988             } else {
    00989
    00990                 //
    00991                 // data is stored externally in old cell, will be internal in new
    00992                 //
    00993                 pvalue = HvGetCell(SourceHive, pvalue->u.KeyValue.Data);
    00994                 tempdata = *((PULONG)pvalue);
    00995             }
    00996             pvalue = HvGetCell(TargetHive, newvalue);
    00997             pvalue->u.KeyValue.Data = tempdata;
    00998             pvalue->u.KeyValue.DataLength =
    00999                 datalength + CM_KEY_VALUE_SPECIAL_SIZE;
    01000
    01001         }
    01002     }
    01003
    01004     return newvalue;
    01005 }

BOOLEAN CmpFreeKeyValues | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | PCM_KEY_NODE | Node
| ) |

Definition at line 1064 of file cmtrecpy.c.

References Cell, _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, CmpFreeSecurityDescriptor(), CmpFreeValue(), CmpMarkKeyValuesDirty(), _CHILD_LIST::Count, FALSE, _CM_KEY_NODE::Flags, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, KEY_HIVE_EXIT, _CELL_DATA::_u::KeyList, _CHILD_LIST::List, TRUE, _CELL_DATA::u, and _CM_KEY_NODE::ValueList.

Referenced by CmpSyncKeyValues().

    01071                    :
    01072
    01073    Free the cells associated with the value entries, the security descriptor,
    01074    and the class of a particular key.
    01075
    01076 Arguments:
    01077
    01078    Hive        - The hive of the key in question
    01079    Cell        - The cell of the key in question
    01080    Node        - The key body of the key in question
    01081
    01082 Return Value:
    01083
    01084    TRUE if successful, FALSE otherwise.
    01085
    01086 --*/
    01087 {
    01088     PCELL_DATA  plist;
    01089     ULONG       i;
    01090
    01091     //
    01092     // Mark all the value-related cells dirty
    01093     //
    01094
    01095     if (! CmpMarkKeyValuesDirty(Hive, Cell, Node)) {
    01096         return FALSE;
    01097     }
    01098
    01099     //
    01100     // Link nodes don't have things that we need to free
    01101     //
    01102
    01103     if (!(Node->Flags & KEY_HIVE_EXIT)) {
    01104
    01105         //
    01106         // First, free the value entries
    01107         //
    01108         if (Node->ValueList.Count > 0) {
    01109
    01110             // Get value list
    01111             plist = HvGetCell(Hive, Node->ValueList.List);
    01112
    01113             // Free each value
    01114             for (i = 0; i < Node->ValueList.Count; i++) {
    01115                 CmpFreeValue(Hive, plist->u.KeyList[i]);
    01116             }
    01117
    01118             // Free the value list
    01119             HvFreeCell(Hive, Node->ValueList.List);
    01120         }
    01121
    01122         //
    01123         // Make this key value-less
    01124         //
    01125
    01126         Node->ValueList.List = HCELL_NIL;
    01127         Node->ValueList.Count = 0;
    01128
    01129         //
    01130         // Free the security descriptor
    01131         //
    01132         CmpFreeSecurityDescriptor(Hive, Cell);
    01133
    01134         //
    01135         // Free the Class information
    01136         //
    01137
    01138         if (Node->ClassLength > 0) {
    01139             HvFreeCell(Hive, Node->Class);
    01140             Node->Class = HCELL_NIL;
    01141             Node->ClassLength = 0;
    01142         }
    01143
    01144     }
    01145
    01146     return TRUE;
    01147 }

VOID CmpInitializeKeyNameString | ( | PCM_KEY_NODE | Cell,
|  | PUNICODE_STRING | KeyName,
|  | WCHAR * | NameBuffer
| ) |

Definition at line 1515 of file cmtrecpy.c.

References Cell, CmpCompressedNameSize(), CmpCopyCompressedName(), KEY_COMP_NAME, KeyName, MAX_KEY_NAME_LENGTH, and USHORT.

Referenced by CmpCopySyncTree2(), CmpFlushNotify(), CmpFreePostBlock(), CmpNotifyChangeKey(), CmpPostNotify(), and CmpSyncSubKeysAfterDelete().

    01521                    :
    01522
    01523    Initializes a UNICODE_STRING with the name of a given key.
    01524
    01525    N.B. The initialized string's buffer is not meant
    01526          to be modified.
    01527
    01528 Arguments:
    01529
    01530    Cell       - The body of the key in question
    01531    KeyName    - The UNICODE_STRING to initialize
    01532    NameBuffer - A buffer MAX_KEY_NAME_LENGTH bytes in size
    01533                 that will possibly be used as the UNICODE_STRING's
    01534                 buffer.
    01535
    01536 Return Value:
    01537
    01538    NONE.
    01539
    01540 --*/
    01541 {
    01542    // is the name stored in compressed form?
    01543
    01544    if(Cell->Flags & KEY_COMP_NAME) {
    01545
    01546       // Name is compressed.
    01547
    01548       // Get the uncompressed length.
    01549
    01550       KeyName->Length = CmpCompressedNameSize(Cell->Name,
    01551                                               Cell->NameLength);
    01552
    01553       // Decompress the name into a buffer.
    01554
    01555       CmpCopyCompressedName(NameBuffer,
    01556                             MAX_KEY_NAME_LENGTH,
    01557                             Cell->Name,
    01558                             Cell->NameLength);
    01559
    01560       //
    01561       // Use the decompression buffer as the string buffer
    01562       //
    01563
    01564       KeyName->Buffer = NameBuffer;
    01565       KeyName->MaximumLength = MAX_KEY_NAME_LENGTH;
    01566
    01567    } else {
    01568
    01569       //
    01570       // Name is not compressed. Just use the name string
    01571       // from the key buffer as the string buffer.
    01572       //
    01573
    01574       KeyName->Length = Cell->NameLength;
    01575       KeyName->Buffer = Cell->Name;
    01576       KeyName->MaximumLength = (USHORT)Cell->MaxNameLen;
    01577
    01578    }
    01579 }

VOID CmpInitializeValueNameString | ( | PCM_KEY_VALUE | Cell,
|  | PUNICODE_STRING | ValueName,
|  | WCHAR * | NameBuffer
| ) |

Definition at line 1582 of file cmtrecpy.c.

References Cell, CmpCompressedNameSize(), CmpCopyCompressedName(), MAX_KEY_VALUE_NAME_LENGTH, VALUE_COMP_NAME, and ValueName.

Referenced by CmpMergeKeyValues().

    01587                    :
    01588
    01589    Initializes a UNICODE_STRING with the name of a given value key.
    01590
    01591    N.B. The initialized string's buffer is not meant
    01592          to be modified.
    01593
    01594 Arguments:
    01595
    01596    Cell       - The value key in question
    01597    ValueName    - The UNICODE_STRING to initialize
    01598    NameBuffer - A buffer MAX_KEY_NAME_LENGTH bytes in size
    01599                 that will possibly be used as the UNICODE_STRING's
    01600                 buffer.
    01601
    01602 Return Value:
    01603
    01604    NONE.
    01605 */
    01606
    01607 {
    01608    // is the name stored in compressed form?
    01609
    01610    if(Cell->Flags & VALUE_COMP_NAME) {
    01611
    01612       // Name is compressed.
    01613
    01614       // Get the uncompressed length.
    01615
    01616       ValueName->Length = CmpCompressedNameSize(Cell->Name,
    01617                                               Cell->NameLength);
    01618
    01619       // Decompress the name into a buffer.
    01620
    01621       CmpCopyCompressedName(NameBuffer,
    01622                             MAX_KEY_VALUE_NAME_LENGTH,
    01623                             Cell->Name,
    01624                             Cell->NameLength);
    01625
    01626       //
    01627       // Use the decompression buffer as the string buffer
    01628       //
    01629
    01630       ValueName->Buffer = NameBuffer;
    01631       ValueName->MaximumLength = MAX_KEY_VALUE_NAME_LENGTH;
    01632
    01633    } else {
    01634
    01635       //
    01636       // Name is not compressed. Just use the name string
    01637       // from the ValueName buffer as the string buffer.
    01638       //
    01639
    01640       ValueName->Length = Cell->NameLength;
    01641       ValueName->Buffer = Cell->Name;
    01642       ValueName->MaximumLength = ValueName->Length;
    01643
    01644    }
    01645 }

BOOLEAN CmpMarkKeyParentDirty | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell
| ) |

Definition at line 1870 of file cmtrecpy.c.

References Cell, CmpMarkIndexDirty(), FALSE, _CM_KEY_NODE::Flags, Hive, HvGetCell, HvMarkCellDirty(), KEY_HIVE_ENTRY, _CELL_DATA::_u::KeyNode, _CM_KEY_NODE::Parent, TRUE, and _CELL_DATA::u.

Referenced by CmpCopySyncTree2().

    01876                    :
    01877
    01878    Marks the parent of a given key and the parent's subkey list as dirty.
    01879
    01880 Arguments:
    01881
    01882    Hive     - The hive of the key in question.
    01883    Cell     - The cell of the key in question.
    01884
    01885
    01886 Return Value:
    01887
    01888    TRUE if successful, FALSE otherwise.
    01889
    01890    A failure probably indicates that no log space was available.
    01891
    01892 --*/
    01893 {
    01894
    01895     PCELL_DATA ptarget;
    01896
    01897     //
    01898     // Map in the target
    01899     //
    01900     ptarget = HvGetCell(Hive, Cell);
    01901
    01902
    01903     if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
    01904
    01905         //
    01906         // if this is an entry node, we are done.  our parent will
    01907         // be in the master hive (and thus volatile)
    01908         //
    01909         return TRUE;
    01910     }
    01911
    01912     //
    01913     // Mark the parent's Subkey list
    01914     //
    01915     if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
    01916         return FALSE;
    01917     }
    01918
    01919     //
    01920     // Mark the parent
    01921     //
    01922     if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
    01923         return FALSE;
    01924     }
    01925
    01926     return TRUE;
    01927 }
    }

BOOLEAN CmpMarkKeyValuesDirty | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | PCM_KEY_NODE | Node
| ) |

Definition at line 1767 of file cmtrecpy.c.

References _CM_KEY_SECURITY::Blink, Cell, _CM_KEY_NODE::Class, CmpIsHKeyValueSmall, _CHILD_LIST::Count, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, FALSE, _CM_KEY_NODE::Flags, _CM_KEY_SECURITY::Flink, HCELL_NIL, Hive, HvGetCell, HvMarkCellDirty(), KEY_HIVE_EXIT, _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeySecurity, _CELL_DATA::_u::KeyValue, _CHILD_LIST::List, _CM_KEY_NODE::Security, TRUE, _CELL_DATA::u, and _CM_KEY_NODE::ValueList.

Referenced by CmpFreeKeyValues().

    01774                    :
    01775
    01776
    01777    Marks the cells associated with a key's value entries, security descriptor,
    01778    and class information as dirty.
    01779
    01780 Arguments:
    01781
    01782    Hive     - The hive of the key in question
    01783    Cell     - The cell of the key in question
    01784    Node     - The body of the key in question
    01785
    01786
    01787 Return Value:
    01788
    01789    TRUE if successful, FALSE otherwise.
    01790
    01791    A failure probably indicates that no log space was available.
    01792
    01793 --*/
    01794 {
    01795     PCELL_DATA  plist, security, pvalue;
    01796     ULONG       i, realsize;
    01797
    01798     if (Node->Flags & KEY_HIVE_EXIT) {
    01799
    01800         //
    01801         // If this is a link node, we are done.  Link nodes never have
    01802         // classes, values, subkeys, or security descriptors.  Since
    01803         // they always reside in the master hive, they're always volatile.
    01804         //
    01805         return(TRUE);
    01806     }
    01807
    01808     //
    01809     // mark cell itself
    01810     //
    01811     if (! HvMarkCellDirty(Hive, Cell)) {
    01812         return FALSE;
    01813     }
    01814
    01815     //
    01816     // Mark the class
    01817     //
    01818     if (Node->Class != HCELL_NIL) {
    01819         if (! HvMarkCellDirty(Hive, Node->Class)) {
    01820             return FALSE;
    01821         }
    01822     }
    01823
    01824     //
    01825     // Mark security
    01826     //
    01827     if (Node->Security != HCELL_NIL) {
    01828         if (! HvMarkCellDirty(Hive, Node->Security)) {
    01829             return FALSE;
    01830         }
    01831
    01832         security = HvGetCell(Hive, Node->Security);
    01833         if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
    01834                HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
    01835         {
    01836             return FALSE;
    01837         }
    01838     }
    01839
    01840     //
    01841     // Mark the value entries and their data
    01842     //
    01843     if (Node->ValueList.Count > 0) {
    01844
    01845         // Value list
    01846         if (! HvMarkCellDirty(Hive, Node->ValueList.List)) {
    01847             return FALSE;
    01848         }
    01849         plist = HvGetCell(Hive, Node->ValueList.List);
    01850
    01851         for (i = 0; i < Node->ValueList.Count; i++) {
    01852             if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
    01853                 return FALSE;
    01854             }
    01855
    01856             pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
    01857
    01858             if (!CmpIsHKeyValueSmall(realsize, pvalue->u.KeyValue.DataLength)) {
    01859                 if (! HvMarkCellDirty(Hive, pvalue->u.KeyValue.Data)) {
    01860                     return(FALSE);
    01861                 }
    01862             }
    01863         }
    01864     }
    01865
    01866     return TRUE;
    01867 }

BOOLEAN CmpMergeKeyValues | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceKeyCell,
|  | PCM_KEY_NODE | SourceKeyNode,
|  | PHHIVE | TargetHive,
|  | HCELL_INDEX | TargetKeyCell,
|  | PCM_KEY_NODE | TargetKeyNode
| ) |

| Referenced by CmpCopySyncTree2(), and CmSaveMergedKeys().

BOOLEAN CmpSyncKeyValues | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceKeyCell,
|  | PCM_KEY_NODE | SourceKeyNode,
|  | PHHIVE | TargetHive,
|  | HCELL_INDEX | TargetKeyCell,
|  | PCM_KEY_NODE | TargetKeyNode
| ) |

Definition at line 1338 of file cmtrecpy.c.

References _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, CmpAssignSecurityDescriptor(), CmpCopyCell(), CmpCopyValue(), CmpFreeKeyValues(), _CHILD_LIST::Count, _CM_KEY_SECURITY::Descriptor, FALSE, HCELL_INDEX, HCELL_NIL, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeySecurity, _CHILD_LIST::List, NT_SUCCESS, NTSTATUS(), _CM_KEY_NODE::Security, TRUE, _CELL_DATA::u, and _CM_KEY_NODE::ValueList.

Referenced by CmpCopySyncTree2(), and CmpMergeKeyValues().

    01348                    :
    01349
    01350     Synchronizes the value entries, security descriptor, and class of a
    01351     target key with that of a source key - ensuring that the keys are
    01352     identical with respect to the synchronized information.
    01353
    01354 Arguments:
    01355
    01356    SourceHive     - Hive of the source key
    01357    SourceKeyCell  - The source key's cell
    01358    SourceKeyNode  - The source key's body
    01359
    01360    TargetHive     - Hive of the target key
    01361    TargetKeyCell  - The target key's cell
    01362    TargetKeyNode  - The target key's body
    01363
    01364 Return Value:
    01365
    01366    TRUE of successful, FALSE otherwise.
    01367
    01368 --*/
    01369 {
    01370     NTSTATUS    status;
    01371     BOOLEAN success = FALSE;
    01372     PCELL_DATA psrclist, ptarlist, psrcsecurity;
    01373     HCELL_INDEX newvalue, newlist = HCELL_NIL, newclass = HCELL_NIL, newsecurity = HCELL_NIL;
    01374     ULONG i, count, Type;
    01375
    01376     //
    01377     // First, free the target key's values, sd, and class info.
    01378     //
    01379
    01380     if(!CmpFreeKeyValues(TargetHive, TargetKeyCell, TargetKeyNode))
    01381        return FALSE;
    01382
    01383     //
    01384     // Now, copy the values, class, & sd from the source cell
    01385     //
    01386
    01387     //
    01388     // The type of the new cells will be the same as that
    01389     // of the target cell.
    01390     //
    01391
    01392     Type = HvGetCellType(TargetKeyCell);
    01393
    01394     //
    01395     // Allocate and copy class
    01396     //
    01397     if ((SourceKeyNode->ClassLength > 0) && (SourceKeyNode->Class != HCELL_NIL)) {
    01398         newclass = CmpCopyCell(SourceHive, SourceKeyNode->Class, TargetHive, Type);
    01399         if (newclass == HCELL_NIL) {
    01400             goto EndValueSync;
    01401         }
    01402
    01403         // only if class is valid. Otherwise remains 0 (set by CmpFreeKeyValues)
    01404         TargetKeyNode->ClassLength = SourceKeyNode->ClassLength;
    01405     }
    01406
    01407     //
    01408     // Associate the new class with the target key
    01409     // and prepare and security descriptor assignment.
    01410     //
    01411
    01412     TargetKeyNode->Class = newclass;
    01413     TargetKeyNode->Security = HCELL_NIL;
    01414
    01415     //
    01416     // Allocate and assign security
    01417     //
    01418     psrcsecurity = HvGetCell(SourceHive, SourceKeyNode->Security);
    01419
    01420     status = CmpAssignSecurityDescriptor(TargetHive,
    01421                                          TargetKeyCell,
    01422                                          TargetKeyNode,
    01423                                          &(psrcsecurity->u.KeySecurity.Descriptor));
    01424     if (!NT_SUCCESS(status)) {
    01425         goto EndValueSync;
    01426     }
    01427
    01428     //
    01429     // Set up the value list
    01430     //
    01431     count = SourceKeyNode->ValueList.Count;
    01432
    01433     if (count == 0) {
    01434
    01435         // No values in source, no list needed.
    01436
    01437         TargetKeyNode->ValueList.List = HCELL_NIL;
    01438         TargetKeyNode->ValueList.Count = 0;
    01439         success = TRUE;
    01440     } else {
    01441
    01442         // Allocate the value list for target
    01443
    01444         psrclist = HvGetCell(SourceHive, SourceKeyNode->ValueList.List);
    01445
    01446         newlist = HvAllocateCell(
    01447                     TargetHive,
    01448                     count * sizeof(HCELL_INDEX),
    01449                     Type
    01450                     );
    01451         if (newlist == HCELL_NIL) {
    01452             goto EndValueSync;
    01453         }
    01454         TargetKeyNode->ValueList.List = newlist;
    01455         ptarlist = HvGetCell(TargetHive, newlist);
    01456
    01457
    01458         //
    01459         // Copy the values
    01460         //
    01461         for (i = 0; i < count; i++) {
    01462
    01463             newvalue = CmpCopyValue(
    01464                             SourceHive,
    01465                             psrclist->u.KeyList[i],
    01466                             TargetHive,
    01467                             Type
    01468                             );
    01469
    01470             if (newvalue != HCELL_NIL) {
    01471
    01472                 ptarlist->u.KeyList[i] = newvalue;
    01473
    01474             } else {
    01475
    01476                 // Delete all the copied values on an error.
    01477
    01478                 for (; i > 0; i--) {
    01479                     HvFreeCell(
    01480                         TargetHive,
    01481                         ptarlist->u.KeyList[i - 1]
    01482                         );
    01483                 }
    01484                 goto EndValueSync;
    01485             }
    01486         }
    01487
    01488         TargetKeyNode->ValueList.Count = count;
    01489         success = TRUE;
    01490     }
    01491
    01492 EndValueSync:
    01493     if (success == FALSE) {
    01494
    01495         // Clean-up on failure
    01496
    01497         if (newlist != HCELL_NIL) {
    01498             HvFreeCell(TargetHive, newlist);
    01499         }
    01500
    01501         if (newsecurity != HCELL_NIL) {
    01502             HvFreeCell(TargetHive, newsecurity);
    01503         }
    01504
    01505         if (newclass != HCELL_NIL) {
    01506             HvFreeCell(TargetHive, newclass);
    01507         }
    01508
    01509     }
    01510
    01511     return success;
    01512 }

BOOLEAN CmpSyncSubKeysAfterDelete | ( | PHHIVE | SourceHive,
|  | PCM_KEY_NODE | SourceCell,
|  | PHHIVE | TargetHive,
|  | PCM_KEY_NODE | TargetCell,
|  | WCHAR * | NameBuffer
| ) |

Definition at line 1648 of file cmtrecpy.c.

References CmpDeleteTree(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpFreeKeyByCell(), CmpInitializeKeyNameString(), FALSE, HCELL_INDEX, HCELL_NIL, HvGetCell, NT_SUCCESS, Stable, _CM_KEY_NODE::SubKeyCounts, TRUE, and Volatile.

Referenced by CmpCopySyncTree2().

    01655                    :
    01656
    01657    This routine makes sure that any subkeys present in the target key
    01658    but not present in the source key are deleted from the target key
    01659    along with any trees under those subkeys.
    01660
    01661    This routine is useful for synchronizing key deletion changes
    01662    in a source cell with a target cell. It is used in this way
    01663    from CmpCopySyncTree.
    01664
    01665    NOTE: It is assumed that no open handles are held for the keys
    01666          being deleted. If this is not so, registry in-memory
    01667          data structures may become corrupted.
    01668
    01669 Arguments:
    01670
    01671    SourceHive  - The hive of the source key
    01672    SourceCell  - The body of the source key
    01673    TargetHive  - The hive of the target key
    01674    TargetCell  - The body of the target key
    01675    NameBuffer  - A buffer MAX_KEY_NAME_LENGTH bytes in size
    01676
    01677 Return Value:
    01678
    01679    TRUE if successful, FALSE otherwise.
    01680
    01681 --*/
    01682 {
    01683    HCELL_INDEX TargetSubKey, SourceSubKey;
    01684    ULONG i = 0;
    01685    PCM_KEY_NODE SubKeyCell;
    01686    UNICODE_STRING SubKeyName;
    01687
    01688    //
    01689    // Run through all of the target cell's subkeys
    01690    //
    01691
    01692    while((TargetSubKey = CmpFindSubKeyByNumber(
    01693                                                TargetHive,
    01694                                                TargetCell,
    01695                                                i)) != HCELL_NIL)
    01696    {
    01697
    01698       //
    01699       // Check if the current subkey has a counterpart
    01700       // subkey of the source cell.
    01701       // (Note that we use similar techniques as in the code
    01702       //  of CmpCopySyncTree2)
    01703       //
    01704
    01705       SubKeyCell = (PCM_KEY_NODE)HvGetCell(TargetHive, TargetSubKey);
    01706
    01707       CmpInitializeKeyNameString(SubKeyCell,
    01708                                  &SubKeyName,
    01709                                  NameBuffer);
    01710
    01711       SourceSubKey = CmpFindSubKeyByName(SourceHive,
    01712                                          SourceCell,
    01713                                          &SubKeyName);
    01714
    01715       if(SourceSubKey == HCELL_NIL)
    01716       {
    01717          //
    01718          // The current subkey has no counterpart,
    01719          // it must therefore be deleted from the target cell.
    01720          //
    01721
    01722 #if DEBUG_TREE_SYNC
    01723          KdPrint(("CONFIG: SubKey Deletion of %.*S\n",
    01724                SubKeyName.Length / sizeof(WCHAR),
    01725                SubKeyName.Buffer));
    01726 #endif
    01727
    01728          if(SubKeyCell->SubKeyCounts[Stable] + SubKeyCell->SubKeyCounts[Volatile])
    01729          {
    01730             // The subkey we are deleting has subkeys - use delete tree to get rid of them
    01731
    01732             CmpDeleteTree(TargetHive, TargetSubKey);
    01733
    01734 #if DEBUG_TREE_SYNC
    01735             KdPrint(("CONFIG: Delete TREE performed.\n"));
    01736 #endif
    01737          }
    01738
    01739          // The subkey we are deleting is now a leaf (or has always been one),
    01740          // just delete it.
    01741
    01742          if(!NT_SUCCESS(CmpFreeKeyByCell(TargetHive, TargetSubKey, TRUE)))
    01743          {
    01744             return FALSE;
    01745          }
    01746
    01747          //
    01748          // We have deleted a subkey, so *i* does not need to get incremented
    01749          // here because it now refers to the next subkey.
    01750          //
    01751       }
    01752       else
    01753       {
    01754          //
    01755          // Counterpart found. No deletion necessary. Move on to the next subkey
    01756          //
    01757
    01758          i++;
    01759       }
    01760    }
    01761
    01762    return TRUE;
    01763 }