ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cmi.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 2006 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /* COPYRIGHT:       See COPYING in the top level directory
00020  * PROJECT:         ReactOS hive maker
00021  * FILE:            tools/mkhive/cmi.c
00022  * PURPOSE:         Registry file manipulation routines
00023  * PROGRAMMER:      Hervé Poussineau
00024  */
00025 
00026 #define NDEBUG
00027 #include "mkhive.h"
00028 
00029 static PVOID
00030 NTAPI
00031 CmpAllocate(
00032     IN SIZE_T Size,
00033     IN BOOLEAN Paged,
00034     IN ULONG Tag)
00035 {
00036     return (PVOID) malloc((size_t)Size);
00037 }
00038 
00039 static VOID
00040 NTAPI
00041 CmpFree(
00042     IN PVOID Ptr,
00043     IN ULONG Quota)
00044 {
00045     free(Ptr);
00046 }
00047 
00048 static BOOLEAN
00049 NTAPI
00050 CmpFileRead(
00051     IN PHHIVE RegistryHive,
00052     IN ULONG FileType,
00053     IN PULONG FileOffset,
00054     OUT PVOID Buffer,
00055     IN SIZE_T BufferLength)
00056 {
00057     DPRINT1("CmpFileRead() unimplemented\n");
00058     return FALSE;
00059 }
00060 
00061 static BOOLEAN
00062 NTAPI
00063 CmpFileWrite(
00064     IN PHHIVE RegistryHive,
00065     IN ULONG FileType,
00066     IN PULONG FileOffset,
00067     IN PVOID Buffer,
00068     IN SIZE_T BufferLength)
00069 {
00070     PCMHIVE CmHive = (PCMHIVE)RegistryHive;
00071     FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
00072     if (0 != fseek (File, *FileOffset, SEEK_SET))
00073         return FALSE;
00074     return BufferLength == fwrite (Buffer, 1, BufferLength, File);
00075 }
00076 
00077 static BOOLEAN
00078 NTAPI
00079 CmpFileSetSize(
00080     IN PHHIVE RegistryHive,
00081     IN ULONG FileType,
00082     IN ULONG FileSize,
00083     IN ULONG OldFileSize)
00084 {
00085     DPRINT1("CmpFileSetSize() unimplemented\n");
00086     return FALSE;
00087 }
00088 
00089 static BOOLEAN
00090 NTAPI
00091 CmpFileFlush(
00092     IN PHHIVE RegistryHive,
00093     IN ULONG FileType,
00094     PLARGE_INTEGER FileOffset,
00095     ULONG Length)
00096 {
00097     PCMHIVE CmHive = (PCMHIVE)RegistryHive;
00098     FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
00099     return 0 == fflush (File);
00100 }
00101 
00102 NTSTATUS
00103 CmiInitializeTempHive(
00104     IN OUT PCMHIVE Hive)
00105 {
00106     NTSTATUS Status;
00107 
00108     RtlZeroMemory (
00109         Hive,
00110         sizeof(CMHIVE));
00111 
00112     DPRINT("Hive 0x%p\n", Hive);
00113 
00114     Status = HvInitialize(&Hive->Hive,
00115                           HINIT_CREATE,
00116                           0,
00117                           0,
00118                           0,
00119                           CmpAllocate,
00120                           CmpFree,
00121                           CmpFileSetSize,
00122                           CmpFileWrite,
00123                           CmpFileRead,
00124                           CmpFileFlush,
00125                           1,
00126                           NULL);
00127     if (!NT_SUCCESS(Status))
00128     {
00129         return Status;
00130     }
00131 
00132     if (!CmCreateRootNode (&Hive->Hive, L""))
00133     {
00134         HvFree (&Hive->Hive);
00135         return STATUS_INSUFFICIENT_RESOURCES;
00136     }
00137 
00138     Hive->Flags = HIVE_NO_FILE;
00139 
00140     /* Add the new hive to the hive list */
00141     InsertTailList (
00142         &CmiHiveListHead,
00143         &Hive->HiveList);
00144 
00145     VERIFY_REGISTRY_HIVE (Hive);
00146 
00147     return STATUS_SUCCESS;
00148 }
00149 
00150 static NTSTATUS
00151 CmiAddKeyToHashTable(
00152     IN PCMHIVE RegistryHive,
00153     IN OUT PCM_KEY_FAST_INDEX HashCell,
00154    IN HCELL_INDEX HashCellIndex,
00155     IN PCM_KEY_NODE NewKeyCell,
00156     IN HCELL_INDEX NKBOffset)
00157 {
00158     ULONG i;
00159     ULONG HashKey = 0;
00160 
00161     if (NewKeyCell->Flags & KEY_COMP_NAME)
00162     {
00163         RtlCopyMemory(
00164             &HashKey,
00165             NewKeyCell->Name,
00166             min(NewKeyCell->NameLength, sizeof(ULONG)));
00167     }
00168 
00169     for (i = 0; i < HashCell->Count; i++)
00170     {
00171         if (HashCell->List[i].HashKey > HashKey)
00172             break;
00173     }
00174 
00175     if (i < HashCell->Count)
00176     {
00177         RtlMoveMemory(HashCell->List + i + 1,
00178                       HashCell->List + i,
00179                       (HashCell->Count - i) *
00180                       sizeof(HashCell->List[0]));
00181     }
00182 
00183     HashCell->List[i].Cell = NKBOffset;
00184     HashCell->List[i].HashKey = HashKey;
00185    HashCell->Count++;
00186     HvMarkCellDirty(&RegistryHive->Hive, HashCellIndex, FALSE);
00187     return STATUS_SUCCESS;
00188 }
00189 
00190 static NTSTATUS
00191 CmiAllocateHashTableCell (
00192     IN PCMHIVE RegistryHive,
00193     OUT PCM_KEY_FAST_INDEX *HashBlock,
00194     OUT HCELL_INDEX *HBOffset,
00195     IN USHORT SubKeyCount,
00196     IN HSTORAGE_TYPE Storage)
00197 {
00198     PCM_KEY_FAST_INDEX NewHashBlock;
00199     ULONG NewHashSize;
00200     NTSTATUS Status;
00201 
00202     Status = STATUS_SUCCESS;
00203     *HashBlock = NULL;
00204     NewHashSize = FIELD_OFFSET(CM_KEY_FAST_INDEX, List) +
00205         (SubKeyCount * sizeof(CM_INDEX));
00206     *HBOffset = HvAllocateCell(&RegistryHive->Hive, NewHashSize, Storage, HCELL_NIL);
00207 
00208     if (*HBOffset == HCELL_NIL)
00209     {
00210         Status = STATUS_INSUFFICIENT_RESOURCES;
00211     }
00212     else
00213     {
00214         NewHashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, *HBOffset);
00215         NewHashBlock->Signature = CM_KEY_FAST_LEAF;
00216         NewHashBlock->Count = 0;
00217         *HashBlock = NewHashBlock;
00218     }
00219 
00220     return Status;
00221 }
00222 
00223 NTSTATUS
00224 CmiAddSubKey(
00225     IN PCMHIVE RegistryHive,
00226     IN PCM_KEY_NODE ParentKeyCell,
00227     IN HCELL_INDEX ParentKeyCellOffset,
00228     IN PCUNICODE_STRING SubKeyName,
00229     IN ULONG CreateOptions,
00230     OUT PCM_KEY_NODE *pSubKeyCell,
00231     OUT HCELL_INDEX *pBlockOffset)
00232 {
00233     PCM_KEY_FAST_INDEX HashBlock;
00234     HCELL_INDEX NKBOffset;
00235     PCM_KEY_NODE NewKeyCell;
00236     ULONG NewBlockSize;
00237     NTSTATUS Status;
00238     USHORT NameLength;
00239     PWSTR NamePtr;
00240     BOOLEAN Packable;
00241     HSTORAGE_TYPE Storage;
00242     ULONG i;
00243 
00244     VERIFY_KEY_CELL(ParentKeyCell);
00245 
00246     /* Skip leading backslash */
00247     if (SubKeyName->Buffer[0] == L'\\')
00248     {
00249         NamePtr = &SubKeyName->Buffer[1];
00250         NameLength = SubKeyName->Length - sizeof(WCHAR);
00251     }
00252     else
00253     {
00254         NamePtr = SubKeyName->Buffer;
00255         NameLength = SubKeyName->Length;
00256     }
00257 
00258     /* Check whether key name can be packed */
00259     Packable = TRUE;
00260     for (i = 0; i < NameLength / sizeof(WCHAR); i++)
00261     {
00262         if (NamePtr[i] & 0xFF00)
00263         {
00264             Packable = FALSE;
00265             break;
00266         }
00267     }
00268 
00269     /* Adjust name size */
00270     if (Packable)
00271     {
00272         NameLength = NameLength / sizeof(WCHAR);
00273     }
00274 
00275     Status = STATUS_SUCCESS;
00276 
00277     Storage = (CreateOptions & REG_OPTION_VOLATILE) ? Volatile : Stable;
00278     NewBlockSize = FIELD_OFFSET(CM_KEY_NODE, Name) + NameLength;
00279     NKBOffset = HvAllocateCell(&RegistryHive->Hive, NewBlockSize, Storage, HCELL_NIL);
00280     if (NKBOffset == HCELL_NIL)
00281     {
00282         Status = STATUS_INSUFFICIENT_RESOURCES;
00283     }
00284     else
00285     {
00286         NewKeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, NKBOffset);
00287         NewKeyCell->Signature = CM_KEY_NODE_SIGNATURE;
00288         if (CreateOptions & REG_OPTION_VOLATILE)
00289         {
00290             NewKeyCell->Flags = KEY_IS_VOLATILE;
00291         }
00292         else
00293         {
00294             NewKeyCell->Flags = 0;
00295         }
00296         KeQuerySystemTime(&NewKeyCell->LastWriteTime);
00297         NewKeyCell->Parent = HCELL_NIL;
00298         NewKeyCell->SubKeyCounts[Stable] = 0;
00299         NewKeyCell->SubKeyCounts[Volatile] = 0;
00300         NewKeyCell->SubKeyLists[Stable] = HCELL_NIL;
00301         NewKeyCell->SubKeyLists[Volatile] = HCELL_NIL;
00302         NewKeyCell->ValueList.Count = 0;
00303         NewKeyCell->ValueList.List = HCELL_NIL;
00304         NewKeyCell->Security = HCELL_NIL;
00305         NewKeyCell->Class = HCELL_NIL;
00306 
00307         /* Pack the key name */
00308         NewKeyCell->NameLength = NameLength;
00309         if (Packable)
00310         {
00311             NewKeyCell->Flags |= KEY_COMP_NAME;
00312             for (i = 0; i < NameLength; i++)
00313             {
00314                 ((PCHAR)NewKeyCell->Name)[i] = (CHAR)(NamePtr[i] & 0x00FF);
00315             }
00316         }
00317         else
00318         {
00319             RtlCopyMemory(
00320                 NewKeyCell->Name,
00321                 NamePtr,
00322                 NameLength);
00323         }
00324 
00325         VERIFY_KEY_CELL(NewKeyCell);
00326     }
00327 
00328     if (!NT_SUCCESS(Status))
00329     {
00330         return Status;
00331     }
00332 
00333     if (ParentKeyCell->SubKeyLists[Storage] == HCELL_NIL)
00334     {
00335         Status = CmiAllocateHashTableCell (
00336             RegistryHive,
00337             &HashBlock,
00338             &ParentKeyCell->SubKeyLists[Storage],
00339             REG_INIT_HASH_TABLE_SIZE,
00340             Storage);
00341         if (!NT_SUCCESS(Status))
00342         {
00343             return(Status);
00344         }
00345     }
00346     else
00347     {
00348         HashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (
00349             &RegistryHive->Hive,
00350             ParentKeyCell->SubKeyLists[Storage]);
00351         ASSERT(HashBlock->Signature == CM_KEY_FAST_LEAF);
00352 
00353         if (HashBlock->Count ==
00354             ((HvGetCellSize(&RegistryHive->Hive, HashBlock) - FIELD_OFFSET(CM_KEY_FAST_INDEX, List)) / sizeof(CM_INDEX)))
00355         {
00356             PCM_KEY_FAST_INDEX NewHashBlock;
00357             HCELL_INDEX HTOffset;
00358 
00359             /* Reallocate the hash table cell */
00360             Status = CmiAllocateHashTableCell (
00361                 RegistryHive,
00362                 &NewHashBlock,
00363                 &HTOffset,
00364                 HashBlock->Count +
00365                 REG_EXTEND_HASH_TABLE_SIZE,
00366                 Storage);
00367             if (!NT_SUCCESS(Status))
00368             {
00369                 return Status;
00370             }
00371             RtlCopyMemory(
00372                 &NewHashBlock->List[0],
00373                 &HashBlock->List[0],
00374                 sizeof(NewHashBlock->List[0]) * HashBlock->Count);
00375          NewHashBlock->Count = HashBlock->Count;
00376             HvFreeCell (&RegistryHive->Hive, ParentKeyCell->SubKeyLists[Storage]);
00377             ParentKeyCell->SubKeyLists[Storage] = HTOffset;
00378             HashBlock = NewHashBlock;
00379         }
00380     }
00381 
00382     Status = CmiAddKeyToHashTable(
00383         RegistryHive,
00384         HashBlock,
00385       ParentKeyCell->SubKeyLists[Storage],
00386         NewKeyCell,
00387         NKBOffset);
00388     if (NT_SUCCESS(Status))
00389     {
00390         ParentKeyCell->SubKeyCounts[Storage]++;
00391         if (Packable)
00392         {
00393             if (NameLength*sizeof(WCHAR) > ParentKeyCell->MaxNameLen)
00394                 ParentKeyCell->MaxNameLen = NameLength*sizeof(WCHAR);
00395         }
00396         else
00397         {
00398             if (NameLength > ParentKeyCell->MaxNameLen)
00399                 ParentKeyCell->MaxNameLen = NameLength;
00400         }
00401         if (NewKeyCell->ClassLength > ParentKeyCell->MaxClassLen)
00402             ParentKeyCell->MaxClassLen = NewKeyCell->ClassLength;
00403 
00404         *pSubKeyCell = NewKeyCell;
00405         *pBlockOffset = NKBOffset;
00406     }
00407 
00408     KeQuerySystemTime(&ParentKeyCell->LastWriteTime);
00409     HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset, FALSE);
00410 
00411     return Status;
00412 }
00413 
00414 static BOOLEAN
00415 CmiCompareHash(
00416     IN PCUNICODE_STRING KeyName,
00417     IN PCHAR HashString)
00418 {
00419     CHAR Buffer[4];
00420 
00421     Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
00422     Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
00423     Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
00424     Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
00425 
00426     return (strncmp(Buffer, HashString, 4) == 0);
00427 }
00428 
00429 
00430 BOOLEAN
00431 CmiCompareHashI(
00432     IN PCUNICODE_STRING KeyName,
00433     IN PCHAR HashString)
00434 {
00435     CHAR Buffer[4];
00436 
00437     Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
00438     Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
00439     Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
00440     Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
00441 
00442     return (strncasecmp(Buffer, HashString, 4) == 0);
00443 }
00444 
00445 static BOOLEAN
00446 CmiCompareKeyNames(
00447     IN PCUNICODE_STRING KeyName,
00448     IN PCM_KEY_NODE KeyCell)
00449 {
00450     PWCHAR UnicodeName;
00451     USHORT i;
00452 
00453     if (KeyCell->Flags & KEY_COMP_NAME)
00454     {
00455         if (KeyName->Length != KeyCell->NameLength * sizeof(WCHAR))
00456             return FALSE;
00457 
00458         for (i = 0; i < KeyCell->NameLength; i++)
00459         {
00460             if (KeyName->Buffer[i] != ((PCHAR)KeyCell->Name)[i])
00461                 return FALSE;
00462         }
00463     }
00464     else
00465     {
00466         if (KeyName->Length != KeyCell->NameLength)
00467             return FALSE;
00468 
00469         UnicodeName = (PWCHAR)KeyCell->Name;
00470         for (i = 0; i < KeyCell->NameLength / sizeof(WCHAR); i++)
00471         {
00472             if (KeyName->Buffer[i] != UnicodeName[i])
00473                 return FALSE;
00474         }
00475     }
00476 
00477     return TRUE;
00478 }
00479 
00480 static BOOLEAN
00481 CmiCompareKeyNamesI(
00482     IN PCUNICODE_STRING KeyName,
00483     IN PCM_KEY_NODE KeyCell)
00484 {
00485     PWCHAR UnicodeName;
00486     USHORT i;
00487 
00488     DPRINT("Flags: %hx\n", KeyCell->Flags);
00489 
00490     if (KeyCell->Flags & KEY_COMP_NAME)
00491     {
00492         if (KeyName->Length != KeyCell->NameLength * sizeof(WCHAR))
00493             return FALSE;
00494 
00495         /* FIXME: use _strnicmp */
00496         for (i = 0; i < KeyCell->NameLength; i++)
00497         {
00498             if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) !=
00499                 RtlUpcaseUnicodeChar(((PCHAR)KeyCell->Name)[i]))
00500             return FALSE;
00501         }
00502     }
00503     else
00504     {
00505         if (KeyName->Length != KeyCell->NameLength)
00506             return FALSE;
00507 
00508         UnicodeName = (PWCHAR)KeyCell->Name;
00509         /* FIXME: use _strnicmp */
00510         for (i = 0; i < KeyCell->NameLength / sizeof(WCHAR); i++)
00511         {
00512             if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) !=
00513                 RtlUpcaseUnicodeChar(UnicodeName[i]))
00514                 return FALSE;
00515         }
00516     }
00517 
00518     return TRUE;
00519 }
00520 
00521 NTSTATUS
00522 CmiScanForSubKey(
00523     IN PCMHIVE RegistryHive,
00524     IN PCM_KEY_NODE KeyCell,
00525     IN PCUNICODE_STRING SubKeyName,
00526     IN ULONG Attributes,
00527     OUT PCM_KEY_NODE *pSubKeyCell,
00528     OUT HCELL_INDEX *pBlockOffset)
00529 {
00530     PCM_KEY_FAST_INDEX HashBlock;
00531     PCM_KEY_NODE CurSubKeyCell;
00532     ULONG Storage;
00533     ULONG i;
00534 
00535     VERIFY_KEY_CELL(KeyCell);
00536 
00537     ASSERT(RegistryHive);
00538 
00539     *pSubKeyCell = NULL;
00540 
00541     for (Storage = Stable; Storage < HTYPE_COUNT; Storage++)
00542     {
00543         if (KeyCell->SubKeyLists[Storage] == HCELL_NIL)
00544         {
00545             /* The key does not have any subkeys */
00546             continue;
00547         }
00548 
00549         /* Get hash table */
00550         HashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
00551         if (!HashBlock || HashBlock->Signature != CM_KEY_FAST_LEAF)
00552             return STATUS_UNSUCCESSFUL;
00553 
00554         for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
00555         {
00556             if (Attributes & OBJ_CASE_INSENSITIVE)
00557             {
00558                 if ((HashBlock->List[i].HashKey == 0
00559                  || CmiCompareHashI(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey)))
00560                 {
00561                     CurSubKeyCell = (PCM_KEY_NODE)HvGetCell (
00562                         &RegistryHive->Hive,
00563                         HashBlock->List[i].Cell);
00564 
00565                     if (CmiCompareKeyNamesI(SubKeyName, CurSubKeyCell))
00566                     {
00567                         *pSubKeyCell = CurSubKeyCell;
00568                         *pBlockOffset = HashBlock->List[i].Cell;
00569                         return STATUS_SUCCESS;
00570                     }
00571                 }
00572             }
00573             else
00574             {
00575                 if ((HashBlock->List[i].HashKey == 0
00576                  || CmiCompareHash(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey)))
00577                 {
00578                     CurSubKeyCell = (PCM_KEY_NODE)HvGetCell (
00579                         &RegistryHive->Hive,
00580                         HashBlock->List[i].Cell);
00581 
00582                     if (CmiCompareKeyNames(SubKeyName, CurSubKeyCell))
00583                     {
00584                         *pSubKeyCell = CurSubKeyCell;
00585                         *pBlockOffset = HashBlock->List[i].Cell;
00586                         return STATUS_SUCCESS;
00587                     }
00588                 }
00589             }
00590         }
00591     }
00592 
00593     return STATUS_OBJECT_NAME_NOT_FOUND;
00594 }
00595 
00596 static USHORT
00597 CmiGetPackedNameLength(
00598     IN PCUNICODE_STRING Name,
00599     OUT PBOOLEAN pPackable)
00600 {
00601     USHORT i;
00602 
00603     *pPackable = TRUE;
00604 
00605     for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
00606     {
00607         if (Name->Buffer[i] & 0xFF00)
00608         {
00609             *pPackable = FALSE;
00610             return Name->Length;
00611         }
00612     }
00613 
00614     return (Name->Length / sizeof(WCHAR));
00615 }
00616 
00617 static NTSTATUS
00618 CmiAllocateValueCell(
00619     IN PCMHIVE RegistryHive,
00620     OUT PCM_KEY_VALUE *ValueCell,
00621     OUT HCELL_INDEX *VBOffset,
00622     IN PCUNICODE_STRING ValueName,
00623     IN HSTORAGE_TYPE Storage)
00624 {
00625     PCM_KEY_VALUE NewValueCell;
00626     BOOLEAN Packable;
00627     USHORT NameLength, i;
00628     NTSTATUS Status;
00629 
00630     Status = STATUS_SUCCESS;
00631 
00632     NameLength = CmiGetPackedNameLength(ValueName, &Packable);
00633 
00634     DPRINT("ValueName->Length %u  NameLength %u\n", ValueName->Length, NameLength);
00635 
00636     *VBOffset = HvAllocateCell(&RegistryHive->Hive, sizeof(CM_KEY_VALUE) + NameLength, Storage, HCELL_NIL);
00637     if (*VBOffset == HCELL_NIL)
00638     {
00639         Status = STATUS_INSUFFICIENT_RESOURCES;
00640     }
00641     else
00642     {
00643         NewValueCell = (PCM_KEY_VALUE)HvGetCell (&RegistryHive->Hive, *VBOffset);
00644         NewValueCell->Signature = CM_KEY_VALUE_SIGNATURE;
00645         NewValueCell->NameLength = (USHORT)NameLength;
00646         if (Packable)
00647         {
00648             /* Pack the value name */
00649             for (i = 0; i < NameLength; i++)
00650                 ((PCHAR)NewValueCell->Name)[i] = (CHAR)ValueName->Buffer[i];
00651             NewValueCell->Flags |= VALUE_COMP_NAME;
00652         }
00653         else
00654         {
00655             /* Copy the value name */
00656             RtlCopyMemory(
00657                 NewValueCell->Name,
00658                 ValueName->Buffer,
00659                 NameLength);
00660             NewValueCell->Flags = 0;
00661         }
00662         NewValueCell->Type = 0;
00663         NewValueCell->DataLength = 0;
00664         NewValueCell->Data = HCELL_NIL;
00665         *ValueCell = NewValueCell;
00666     }
00667 
00668     return Status;
00669 }
00670 
00671 NTSTATUS
00672 CmiAddValueKey(
00673     IN PCMHIVE RegistryHive,
00674     IN PCM_KEY_NODE KeyCell,
00675     IN HCELL_INDEX KeyCellOffset,
00676     IN PCUNICODE_STRING ValueName,
00677     OUT PCM_KEY_VALUE *pValueCell,
00678     OUT HCELL_INDEX *pValueCellOffset)
00679 {
00680     PVALUE_LIST_CELL ValueListCell;
00681     PCM_KEY_VALUE NewValueCell;
00682     HCELL_INDEX ValueListCellOffset;
00683     HCELL_INDEX NewValueCellOffset;
00684     ULONG CellSize;
00685     HSTORAGE_TYPE Storage;
00686     NTSTATUS Status;
00687 
00688     Storage = (KeyCell->Flags & KEY_IS_VOLATILE) ? Volatile : Stable;
00689     if (KeyCell->ValueList.List == HCELL_NIL)
00690     {
00691         /* Allocate some room for the value list */
00692         CellSize = sizeof(VALUE_LIST_CELL) + (3 * sizeof(HCELL_INDEX));
00693         ValueListCellOffset = HvAllocateCell(&RegistryHive->Hive, CellSize, Storage, HCELL_NIL);
00694         if (ValueListCellOffset == HCELL_NIL)
00695             return STATUS_INSUFFICIENT_RESOURCES;
00696 
00697         ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
00698         if (!ValueListCell)
00699             return STATUS_UNSUCCESSFUL;
00700         KeyCell->ValueList.List = ValueListCellOffset;
00701         HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
00702     }
00703     else
00704     {
00705         ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
00706         if (!ValueListCell)
00707             return STATUS_UNSUCCESSFUL;
00708         CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell));
00709 
00710         if (KeyCell->ValueList.Count >= CellSize / sizeof(HCELL_INDEX))
00711         {
00712             CellSize *= 2;
00713             ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, KeyCell->ValueList.List, CellSize);
00714             if (ValueListCellOffset == HCELL_NIL)
00715                 return STATUS_INSUFFICIENT_RESOURCES;
00716 
00717             ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
00718             if (!ValueListCell)
00719                 return STATUS_UNSUCCESSFUL;
00720             KeyCell->ValueList.List = ValueListCellOffset;
00721             HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
00722         }
00723     }
00724 
00725     Status = CmiAllocateValueCell(
00726         RegistryHive,
00727         &NewValueCell,
00728         &NewValueCellOffset,
00729         ValueName,
00730         Storage);
00731     if (!NT_SUCCESS(Status))
00732         return Status;
00733 
00734     ValueListCell->ValueOffset[KeyCell->ValueList.Count] = NewValueCellOffset;
00735     KeyCell->ValueList.Count++;
00736     if (NewValueCell->Flags & VALUE_COMP_NAME)
00737     {
00738         if (NewValueCell->NameLength*sizeof(WCHAR) > KeyCell->MaxValueNameLen)
00739             KeyCell->MaxValueNameLen = NewValueCell->NameLength*sizeof(WCHAR);
00740     }
00741     else
00742     {
00743         if (NewValueCell->NameLength > KeyCell->MaxValueNameLen)
00744             KeyCell->MaxValueNameLen = NewValueCell->NameLength;
00745     }
00746 
00747     HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
00748     HvMarkCellDirty(&RegistryHive->Hive, KeyCell->ValueList.List, FALSE);
00749     HvMarkCellDirty(&RegistryHive->Hive, NewValueCellOffset, FALSE);
00750 
00751     *pValueCell = NewValueCell;
00752     *pValueCellOffset = NewValueCellOffset;
00753 
00754     return STATUS_SUCCESS;
00755 }
00756 
00757 static BOOLEAN
00758 CmiComparePackedNames(
00759     IN PCUNICODE_STRING Name,
00760     IN PUCHAR NameBuffer,
00761     IN USHORT NameBufferSize,
00762     IN BOOLEAN NamePacked)
00763 {
00764     PWCHAR UNameBuffer;
00765     ULONG i;
00766 
00767     if (NamePacked == TRUE)
00768     {
00769         if (Name->Length != NameBufferSize * sizeof(WCHAR))
00770             return FALSE;
00771 
00772         for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
00773         {
00774             if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar((WCHAR)NameBuffer[i]))
00775                 return FALSE;
00776         }
00777     }
00778     else
00779     {
00780         if (Name->Length != NameBufferSize)
00781             return FALSE;
00782 
00783         UNameBuffer = (PWCHAR)NameBuffer;
00784 
00785         for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
00786         {
00787             if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar(UNameBuffer[i]))
00788                 return FALSE;
00789         }
00790     }
00791 
00792     return TRUE;
00793 }
00794 
00795 NTSTATUS
00796 CmiScanForValueKey(
00797     IN PCMHIVE RegistryHive,
00798     IN PCM_KEY_NODE KeyCell,
00799     IN PCUNICODE_STRING ValueName,
00800     OUT PCM_KEY_VALUE *pValueCell,
00801     OUT HCELL_INDEX *pValueCellOffset)
00802 {
00803     PVALUE_LIST_CELL ValueListCell;
00804     PCM_KEY_VALUE CurValueCell;
00805     ULONG i;
00806 
00807     *pValueCell = NULL;
00808     *pValueCellOffset = HCELL_NIL;
00809 
00810     /* The key does not have any values */
00811     if (KeyCell->ValueList.List == HCELL_NIL)
00812     {
00813         return STATUS_OBJECT_NAME_NOT_FOUND;
00814     }
00815 
00816     ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
00817 
00818     VERIFY_VALUE_LIST_CELL(ValueListCell);
00819 
00820     for (i = 0; i < KeyCell->ValueList.Count; i++)
00821     {
00822         CurValueCell = (PCM_KEY_VALUE)HvGetCell(
00823             &RegistryHive->Hive,
00824             ValueListCell->ValueOffset[i]);
00825 
00826         if (CmiComparePackedNames(
00827             ValueName,
00828             (PUCHAR)CurValueCell->Name,
00829             CurValueCell->NameLength,
00830             (BOOLEAN)((CurValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE)))
00831         {
00832             *pValueCell = CurValueCell;
00833             *pValueCellOffset = ValueListCell->ValueOffset[i];
00834             return STATUS_SUCCESS;
00835         }
00836     }
00837 
00838     return STATUS_OBJECT_NAME_NOT_FOUND;
00839 }

Generated on Sun May 27 2012 04:37:46 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.