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

cmvalche.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/config/cmvalche.c
00005  * PURPOSE:         Configuration Manager - Value Cell Cache
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "ntoskrnl.h"
00012 #define NDEBUG
00013 #include "debug.h"
00014 
00015 FORCEINLINE
00016 BOOLEAN
00017 CmpIsValueCached(IN HCELL_INDEX CellIndex)
00018 {
00019     /* Make sure that the cell is valid in the first place */
00020     if (CellIndex == HCELL_NIL) return FALSE;
00021 
00022     /*Is this cell actually a pointer to the cached value data? */
00023     if (CellIndex & 1) return TRUE;
00024 
00025     /* This is a regular cell */
00026     return FALSE;
00027 }
00028 
00029 FORCEINLINE
00030 VOID
00031 CmpSetValueCached(IN PHCELL_INDEX CellIndex)
00032 {
00033     /* Set the cached bit */
00034     *CellIndex |= 1;
00035 }
00036 
00037 #define ASSERT_VALUE_CACHE() \
00038     ASSERTMSG("Cached Values Not Yet Supported!", FALSE);
00039 
00040 /* FUNCTIONS *****************************************************************/
00041 
00042 VALUE_SEARCH_RETURN_TYPE
00043 NTAPI
00044 CmpGetValueListFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
00045                          OUT PCELL_DATA *CellData,
00046                          OUT BOOLEAN *IndexIsCached,
00047                          OUT PHCELL_INDEX ValueListToRelease)
00048 {
00049     PHHIVE Hive;
00050     PCACHED_CHILD_LIST ChildList;
00051     HCELL_INDEX CellToRelease;
00052 
00053     /* Set defaults */
00054     *ValueListToRelease = HCELL_NIL;
00055     *IndexIsCached = FALSE;
00056 
00057     /* Get the hive and value cache */
00058     Hive = Kcb->KeyHive;
00059     ChildList = &Kcb->ValueCache;
00060 
00061     /* Check if the value is cached */
00062     if (CmpIsValueCached(ChildList->ValueList))
00063     {
00064         /* It is: we don't expect this yet! */
00065         ASSERT_VALUE_CACHE();
00066         *IndexIsCached = TRUE;
00067         *CellData = NULL;
00068     }
00069     else
00070     {
00071         /* Make sure the KCB is locked exclusive */
00072         if (!(CmpIsKcbLockedExclusive(Kcb)) &&
00073             !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
00074         {
00075             /* We need the exclusive lock */
00076             return SearchNeedExclusiveLock;
00077         }
00078 
00079         /* Select the value list as our cell, and get the actual list array */
00080         CellToRelease = ChildList->ValueList;
00081         *CellData = (PCELL_DATA)HvGetCell(Hive, CellToRelease);
00082         if (!(*CellData)) return SearchFail;
00083         
00084         /* FIXME: Here we would cache the value */
00085 
00086         /* Return the cell to be released */
00087         *ValueListToRelease = CellToRelease;
00088     }
00089 
00090     /* If we got here, then the value list was found */
00091     return SearchSuccess;
00092 }
00093 
00094 VALUE_SEARCH_RETURN_TYPE
00095 NTAPI
00096 CmpGetValueKeyFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
00097                         IN PCELL_DATA CellData,
00098                         IN ULONG Index,
00099                         OUT PCM_CACHED_VALUE **CachedValue,
00100                         OUT PCM_KEY_VALUE *Value,
00101                         IN BOOLEAN IndexIsCached,
00102                         OUT BOOLEAN *ValueIsCached,
00103                         OUT PHCELL_INDEX CellToRelease)
00104 {
00105     PHHIVE Hive;
00106     PCM_KEY_VALUE KeyValue;
00107     HCELL_INDEX Cell;
00108 
00109     /* Set defaults */
00110     *CellToRelease = HCELL_NIL;
00111     *Value = NULL;
00112     *ValueIsCached = FALSE;
00113 
00114     /* Get the hive */
00115     Hive = Kcb->KeyHive;
00116 
00117     /* Check if the index was cached */
00118     if (IndexIsCached)
00119     {
00120         /* Not expected yet! */
00121         ASSERT_VALUE_CACHE();
00122         *ValueIsCached = TRUE;
00123     }
00124     else
00125     {
00126         /* Get the cell index and the key value associated to it */
00127         Cell = CellData->u.KeyList[Index];
00128         KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
00129         if (!KeyValue) return SearchFail;
00130 
00131         /* Return the cell and the actual key value */
00132         *CellToRelease = Cell;
00133         *Value = KeyValue;
00134     }
00135 
00136     /* If we got here, then we found the key value */
00137     return SearchSuccess;
00138 }
00139 
00140 VALUE_SEARCH_RETURN_TYPE
00141 NTAPI
00142 CmpGetValueDataFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
00143                          IN PCM_CACHED_VALUE *CachedValue,
00144                          IN PCELL_DATA ValueKey,
00145                          IN BOOLEAN ValueIsCached,
00146                          OUT PVOID *DataPointer,
00147                          OUT PBOOLEAN Allocated,
00148                          OUT PHCELL_INDEX CellToRelease)
00149 {
00150     PHHIVE Hive;
00151     ULONG Length;
00152 
00153     /* Sanity checks */
00154     ASSERT(MAXIMUM_CACHED_DATA < CM_KEY_VALUE_BIG);
00155     ASSERT((ValueKey->u.KeyValue.DataLength & CM_KEY_VALUE_SPECIAL_SIZE) == 0);
00156 
00157     /* Set defaults */
00158     *DataPointer = NULL;
00159     *Allocated = FALSE;
00160     *CellToRelease = HCELL_NIL;
00161 
00162     /* Get the hive */
00163     Hive = Kcb->KeyHive;
00164 
00165     /* Check it the value is cached */
00166     if (ValueIsCached)
00167     {
00168         /* This isn't expected! */
00169         ASSERT_VALUE_CACHE();
00170     }
00171     else
00172     {
00173         /* It's not, get the value data using the typical routine */
00174         if (!CmpGetValueData(Hive,
00175                              &ValueKey->u.KeyValue,
00176                              &Length,
00177                              DataPointer,
00178                              Allocated,
00179                              CellToRelease))
00180         {
00181             /* Nothing found: make sure no data was allocated */
00182             ASSERT(*Allocated == FALSE);
00183             ASSERT(*DataPointer == NULL);
00184             return SearchFail;
00185         }
00186     }
00187 
00188     /* We found the actual data, return success */
00189     return SearchSuccess;
00190 }
00191 
00192 VALUE_SEARCH_RETURN_TYPE
00193 NTAPI
00194 CmpFindValueByNameFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
00195                             IN PCUNICODE_STRING Name,
00196                             OUT PCM_CACHED_VALUE **CachedValue,
00197                             OUT ULONG *Index,
00198                             OUT PCM_KEY_VALUE *Value,
00199                             OUT BOOLEAN *ValueIsCached,
00200                             OUT PHCELL_INDEX CellToRelease)
00201 {
00202     PHHIVE Hive;
00203     VALUE_SEARCH_RETURN_TYPE SearchResult = SearchFail;
00204     LONG Result;
00205     UNICODE_STRING SearchName;
00206     PCELL_DATA CellData;
00207     PCACHED_CHILD_LIST ChildList;
00208     PCM_KEY_VALUE KeyValue;
00209     BOOLEAN IndexIsCached;
00210     ULONG i = 0;
00211     HCELL_INDEX Cell = HCELL_NIL;
00212 
00213     /* Set defaults */
00214     *CellToRelease = HCELL_NIL;
00215     *Value = NULL;
00216 
00217     /* Get the hive and child list */
00218     Hive = Kcb->KeyHive;
00219     ChildList = &Kcb->ValueCache;
00220 
00221     /* Check if the child list has any entries */
00222     if (ChildList->Count != 0)
00223     {
00224         /* Get the value list associated to this child list */
00225         SearchResult = CmpGetValueListFromCache(Kcb,
00226                                                 &CellData,
00227                                                 &IndexIsCached,
00228                                                 &Cell);
00229         if (SearchResult != SearchSuccess)
00230         {
00231             /* We either failed or need the exclusive lock */
00232             ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
00233             ASSERT(Cell == HCELL_NIL);
00234             return SearchResult;
00235         }
00236 
00237         /* The index shouldn't be cached right now */
00238         if (IndexIsCached) ASSERT_VALUE_CACHE();
00239 
00240         /* Loop every value */
00241         while (TRUE)
00242         {
00243             /* Check if there's any cell to release */
00244             if (*CellToRelease != HCELL_NIL)
00245             {
00246                 /* Release it now */
00247                 HvReleaseCell(Hive, *CellToRelease);
00248                 *CellToRelease = HCELL_NIL;
00249             }
00250 
00251             /* Get the key value for this index */
00252             SearchResult =  CmpGetValueKeyFromCache(Kcb,
00253                                                     CellData,
00254                                                     i,
00255                                                     CachedValue,
00256                                                     Value,
00257                                                     IndexIsCached,
00258                                                     ValueIsCached,
00259                                                     CellToRelease);
00260             if (SearchResult != SearchSuccess)
00261             {
00262                 /* We either failed or need the exclusive lock */
00263                 ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
00264                 ASSERT(Cell == HCELL_NIL);
00265                 return SearchResult;
00266             }
00267 
00268             /* Check if the both the index and the value are cached */
00269             if ((IndexIsCached) && (*ValueIsCached))
00270             {
00271                 /* We don't expect this yet */
00272                 ASSERT_VALUE_CACHE();
00273                 Result = -1;
00274             }
00275             else
00276             {
00277                 /* No cache, so try to compare the name. Is it compressed? */
00278                 KeyValue = *Value;
00279                 if (KeyValue->Flags & VALUE_COMP_NAME)
00280                 {
00281                     /* It is, do a compressed name comparison */
00282                     Result = CmpCompareCompressedName(Name,
00283                                                       KeyValue->Name,
00284                                                       KeyValue->NameLength);
00285                 }
00286                 else
00287                 {
00288                     /* It's not compressed, so do a standard comparison */
00289                     SearchName.Length = KeyValue->NameLength;
00290                     SearchName.MaximumLength = SearchName.Length;
00291                     SearchName.Buffer = KeyValue->Name;
00292                     Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
00293                 }
00294             }
00295 
00296             /* Check if we found the value data */
00297             if (!Result)
00298             {
00299                 /* We have, return the index of the value and success */
00300                 *Index = i;
00301                 SearchResult = SearchSuccess;
00302                 goto Quickie;
00303             }
00304 
00305             /* We didn't find it, try the next entry */
00306             if (++i == ChildList->Count)
00307             {
00308                 /* The entire list was parsed, fail */
00309                 *Value = NULL;
00310                 SearchResult = SearchFail;
00311                 goto Quickie;
00312             }
00313         }
00314     }
00315 
00316     /* We should only get here if the child list is empty */
00317     ASSERT(ChildList->Count == 0);
00318 
00319 Quickie:
00320     /* Release the value list cell if required, and return search result */
00321     if (Cell != HCELL_NIL) HvReleaseCell(Hive, Cell);
00322     return SearchResult;
00323 }
00324 
00325 VALUE_SEARCH_RETURN_TYPE
00326 NTAPI
00327 CmpQueryKeyValueData(IN PCM_KEY_CONTROL_BLOCK Kcb,
00328                      IN PCM_CACHED_VALUE *CachedValue,
00329                      IN PCM_KEY_VALUE ValueKey,
00330                      IN BOOLEAN ValueIsCached,
00331                      IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
00332                      IN PVOID KeyValueInformation,
00333                      IN ULONG Length,
00334                      OUT PULONG ResultLength,
00335                      OUT PNTSTATUS Status)
00336 {
00337     PKEY_VALUE_INFORMATION Info = (PKEY_VALUE_INFORMATION)KeyValueInformation;
00338     PCELL_DATA CellData;
00339     USHORT NameSize;
00340     ULONG Size, MinimumSize, SizeLeft, KeySize, AlignedData = 0, DataOffset;
00341     PVOID Buffer;
00342     BOOLEAN IsSmall, BufferAllocated = FALSE;
00343     HCELL_INDEX CellToRelease = HCELL_NIL;
00344     VALUE_SEARCH_RETURN_TYPE Result = SearchSuccess;
00345 
00346     /* Get the value data */
00347     CellData = (PCELL_DATA)ValueKey;
00348 
00349     /* Check if the value is compressed */
00350     if (CellData->u.KeyValue.Flags & VALUE_COMP_NAME)
00351     {
00352         /* Get the compressed name size */
00353         NameSize = CmpCompressedNameSize(CellData->u.KeyValue.Name,
00354                                          CellData->u.KeyValue.NameLength);
00355     }
00356     else
00357     {
00358         /* Get the real size */
00359         NameSize = CellData->u.KeyValue.NameLength;
00360     }
00361 
00362     /* Check what kind of information the caller is requesting */
00363     switch (KeyValueInformationClass)
00364     {
00365         /* Basic information */
00366         case KeyValueBasicInformation:
00367 
00368             /* This is how much size we'll need */
00369             Size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) + NameSize;
00370 
00371             /* This is the minimum we can work with */
00372             MinimumSize = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name);
00373 
00374             /* Return the size we'd like, and assume success */
00375             *ResultLength = Size;
00376             *Status = STATUS_SUCCESS;
00377 
00378             /* Check if the caller gave us below our minimum */
00379             if (Length < MinimumSize)
00380             {
00381                 /* Then we must fail */
00382                 *Status = STATUS_BUFFER_TOO_SMALL;
00383                 break;
00384             }
00385 
00386             /* Fill out the basic information */
00387             Info->KeyValueBasicInformation.TitleIndex = 0;
00388             Info->KeyValueBasicInformation.Type = CellData->u.KeyValue.Type;
00389             Info->KeyValueBasicInformation.NameLength = NameSize;
00390 
00391             /* Now only the name is left */
00392             SizeLeft = Length - MinimumSize;
00393             Size = NameSize;
00394 
00395             /* Check if the remaining buffer is too small for the name */
00396             if (SizeLeft < Size)
00397             {
00398                 /* Copy only as much as can fit, and tell the caller */
00399                 Size = SizeLeft;
00400                 *Status = STATUS_BUFFER_OVERFLOW;
00401             }
00402 
00403             /* Check if this is a compressed name */
00404             if (CellData->u.KeyValue.Flags & VALUE_COMP_NAME)
00405             {
00406                 /* Copy as much as we can of the compressed name */
00407                 CmpCopyCompressedName(Info->KeyValueBasicInformation.Name,
00408                                       Size,
00409                                       CellData->u.KeyValue.Name,
00410                                       CellData->u.KeyValue.NameLength);
00411             }
00412             else
00413             {
00414                 /* Copy as much as we can of the raw name */
00415                 RtlCopyMemory(Info->KeyValueBasicInformation.Name,
00416                               CellData->u.KeyValue.Name,
00417                               Size);
00418             }
00419 
00420             /* We're all done */
00421             break;
00422 
00423         /* Full key information */
00424         case KeyValueFullInformation:
00425         case KeyValueFullInformationAlign64:
00426 
00427             /* Check if this is a small key and compute key size */
00428             IsSmall = CmpIsKeyValueSmall(&KeySize,
00429                                          CellData->u.KeyValue.DataLength);
00430 
00431             /* Calculate the total size required */
00432             Size = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) +
00433                    NameSize +
00434                    KeySize;
00435 
00436             /* And this is the least we can work with */
00437             MinimumSize = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
00438 
00439             /* Check if there's any key data */
00440             if (KeySize > 0)
00441             {
00442                 /* Calculate the data offset */
00443                 DataOffset = Size - KeySize;
00444 
00445 #ifdef _WIN64
00446                 /* On 64-bit, always align to 8 bytes */
00447                 AlignedData = ALIGN_UP(DataOffset, ULONGLONG);
00448 #else
00449                 /* On 32-bit, align the offset to 4 or 8 bytes */
00450                 if (KeyValueInformationClass == KeyValueFullInformationAlign64)
00451                 {
00452                     AlignedData = ALIGN_UP(DataOffset, ULONGLONG);
00453                 }
00454                 else
00455                 {
00456                     AlignedData = ALIGN_UP(DataOffset, ULONG);
00457                 }
00458 #endif
00459                 /* If alignment was required, we'll need more space */
00460                 if (AlignedData > DataOffset) Size += (AlignedData-DataOffset);
00461             }
00462 
00463             /* Tell the caller the size we'll finally need, and set success */
00464             *ResultLength = Size;
00465             *Status = STATUS_SUCCESS;
00466 
00467             /* Check if the caller is giving us too little */
00468             if (Length < MinimumSize)
00469             {
00470                 /* Then fail right now */
00471                 *Status = STATUS_BUFFER_TOO_SMALL;
00472                 break;
00473             }
00474 
00475             /* Fill out the basic information */
00476             Info->KeyValueFullInformation.TitleIndex = 0;
00477             Info->KeyValueFullInformation.Type = CellData->u.KeyValue.Type;
00478             Info->KeyValueFullInformation.DataLength = KeySize;
00479             Info->KeyValueFullInformation.NameLength = NameSize;
00480 
00481             /* Only the name is left now */
00482             SizeLeft = Length - MinimumSize;
00483             Size = NameSize;
00484 
00485             /* Check if the name fits */
00486             if (SizeLeft < Size)
00487             {
00488                 /* It doesn't, truncate what we'll copy, and tell the caller */
00489                 Size = SizeLeft;
00490                 *Status = STATUS_BUFFER_OVERFLOW;
00491             }
00492 
00493             /* Check if this key value is compressed */
00494             if (CellData->u.KeyValue.Flags & VALUE_COMP_NAME)
00495             {
00496                 /* It is, copy the compressed name */
00497                 CmpCopyCompressedName(Info->KeyValueFullInformation.Name,
00498                                       Size,
00499                                       CellData->u.KeyValue.Name,
00500                                       CellData->u.KeyValue.NameLength);
00501             }
00502             else
00503             {
00504                 /* It's not, copy the raw name */
00505                 RtlCopyMemory(Info->KeyValueFullInformation.Name,
00506                               CellData->u.KeyValue.Name,
00507                               Size);
00508             }
00509 
00510             /* Now check if the key had any data */
00511             if (KeySize > 0)
00512             {
00513                 /* Was it a small key? */
00514                 if (IsSmall)
00515                 {
00516                     /* Then the data is directly into the cell */
00517                     Buffer = &CellData->u.KeyValue.Data;
00518                 }
00519                 else
00520                 {
00521                     /* Otherwise, we must retrieve it from the value cache */
00522                     Result = CmpGetValueDataFromCache(Kcb,
00523                                                       CachedValue,
00524                                                       CellData,
00525                                                       ValueIsCached,
00526                                                       &Buffer,
00527                                                       &BufferAllocated,
00528                                                       &CellToRelease);
00529                     if (Result != SearchSuccess)
00530                     {
00531                         /* We failed, nothing should be allocated */
00532                         ASSERT(Buffer == NULL);
00533                         ASSERT(BufferAllocated == FALSE);
00534                         *Status = STATUS_INSUFFICIENT_RESOURCES;
00535                     }
00536                 }
00537 
00538                 /* Now that we know we truly have data, set its offset */
00539                 Info->KeyValueFullInformation.DataOffset = AlignedData;
00540 
00541                 /* Only the data remains to be copied */
00542                 SizeLeft = (((LONG)Length - (LONG)AlignedData) < 0) ?
00543                            0 : (Length - AlignedData);
00544                 Size = KeySize;
00545 
00546                 /* Check if the caller has no space for it */
00547                 if (SizeLeft < Size)
00548                 {
00549                     /* Truncate what we'll copy, and tell the caller */
00550                     Size = SizeLeft;
00551                     *Status = STATUS_BUFFER_OVERFLOW;
00552                 }
00553 
00554                 /* Sanity check */
00555                 ASSERT((IsSmall ? (Size <= CM_KEY_VALUE_SMALL) : TRUE));
00556 
00557                 /* Make sure we have a valid buffer */
00558                 if (Buffer)
00559                 {
00560                     /* Copy the data into the aligned offset */
00561                     RtlCopyMemory((PVOID)((ULONG_PTR)Info + AlignedData),
00562                                   Buffer,
00563                                   Size);
00564                 }
00565             }
00566             else
00567             {
00568                 /* We don't have any data, set the offset to -1, not 0! */
00569                 Info->KeyValueFullInformation.DataOffset = 0xFFFFFFFF;
00570             }
00571 
00572             /* We're done! */
00573             break;
00574 
00575         /* Partial information requested (no name or alignment!) */
00576         case KeyValuePartialInformation:
00577 
00578             /* Check if this is a small key and compute key size */
00579             IsSmall = CmpIsKeyValueSmall(&KeySize,
00580                                          CellData->u.KeyValue.DataLength);
00581 
00582             /* Calculate the total size required */
00583             Size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + KeySize;
00584 
00585             /* And this is the least we can work with */
00586             MinimumSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
00587 
00588             /* Tell the caller the size we'll finally need, and set success */
00589             *ResultLength = Size;
00590             *Status = STATUS_SUCCESS;
00591 
00592             /* Check if the caller is giving us too little */
00593             if (Length < MinimumSize)
00594             {
00595                 /* Then fail right now */
00596                 *Status = STATUS_BUFFER_TOO_SMALL;
00597                 break;
00598             }
00599 
00600             /* Fill out the basic information */
00601             Info->KeyValuePartialInformation.TitleIndex = 0;
00602             Info->KeyValuePartialInformation.Type = CellData->u.KeyValue.Type;
00603             Info->KeyValuePartialInformation.DataLength = KeySize;
00604 
00605             /* Now check if the key had any data */
00606             if (KeySize > 0)
00607             {
00608                 /* Was it a small key? */
00609                 if (IsSmall)
00610                 {
00611                     /* Then the data is directly into the cell */
00612                     Buffer = &CellData->u.KeyValue.Data;
00613                 }
00614                 else
00615                 {
00616                     /* Otherwise, we must retrieve it from the value cache */
00617                     Result = CmpGetValueDataFromCache(Kcb,
00618                                                       CachedValue,
00619                                                       CellData,
00620                                                       ValueIsCached,
00621                                                       &Buffer,
00622                                                       &BufferAllocated,
00623                                                       &CellToRelease);
00624                     if (Result != SearchSuccess)
00625                     {
00626                         /* We failed, nothing should be allocated */
00627                         ASSERT(Buffer == NULL);
00628                         ASSERT(BufferAllocated == FALSE);
00629                         *Status = STATUS_INSUFFICIENT_RESOURCES;
00630                     }
00631                 }
00632 
00633                 /* Only the data remains to be copied */
00634                 SizeLeft = Length - MinimumSize;
00635                 Size = KeySize;
00636 
00637                 /* Check if the caller has no space for it */
00638                 if (SizeLeft < Size)
00639                 {
00640                     /* Truncate what we'll copy, and tell the caller */
00641                     Size = SizeLeft;
00642                     *Status = STATUS_BUFFER_OVERFLOW;
00643                 }
00644 
00645                 /* Sanity check */
00646                 ASSERT((IsSmall ? (Size <= CM_KEY_VALUE_SMALL) : TRUE));
00647 
00648                 /* Make sure we have a valid buffer */
00649                 if (Buffer)
00650                 {
00651                     /* Copy the data into the aligned offset */
00652                     RtlCopyMemory(Info->KeyValuePartialInformation.Data,
00653                                   Buffer,
00654                                   Size);
00655                 }
00656             }
00657 
00658             /* We're done! */
00659             break;
00660 
00661         /* Other information class */
00662         default:
00663 
00664             /* We got some class that we don't support */
00665             DPRINT1("Caller requested unknown class: %lx\n", KeyValueInformationClass);
00666             *Status = STATUS_INVALID_PARAMETER;
00667             break;
00668     }
00669 
00670     /* Return the search result as well */
00671     return Result;
00672 }
00673 
00674 VALUE_SEARCH_RETURN_TYPE
00675 NTAPI
00676 CmpCompareNewValueDataAgainstKCBCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
00677                                       IN PUNICODE_STRING ValueName,
00678                                       IN ULONG Type,
00679                                       IN PVOID Data,
00680                                       IN ULONG DataSize)
00681 {
00682     VALUE_SEARCH_RETURN_TYPE SearchResult;
00683     PCM_KEY_NODE KeyNode;
00684     PCM_CACHED_VALUE *CachedValue;
00685     ULONG Index;
00686     PCM_KEY_VALUE Value;
00687     BOOLEAN ValueCached, BufferAllocated = FALSE;
00688     PVOID Buffer;
00689     HCELL_INDEX ValueCellToRelease = HCELL_NIL, CellToRelease = HCELL_NIL;
00690     BOOLEAN IsSmall;
00691     ULONG_PTR CompareResult;
00692     PAGED_CODE();
00693 
00694     /* Check if this is a symlink */
00695     if (Kcb->Flags & KEY_SYM_LINK)
00696     {
00697         /* We need the exclusive lock */
00698         if (!(CmpIsKcbLockedExclusive(Kcb)) &&
00699             !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
00700         {
00701             /* We need the exclusive lock */
00702             return SearchNeedExclusiveLock;
00703         }
00704         
00705         /* Otherwise, get the key node */
00706         KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
00707         if (!KeyNode) return SearchFail;
00708         
00709         /* Cleanup the KCB cache */
00710         CmpCleanUpKcbValueCache(Kcb);
00711         
00712         /* Sanity checks */
00713         ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
00714         ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
00715         
00716         /* Set the value cache */
00717         Kcb->ValueCache.Count = KeyNode->ValueList.Count;
00718         Kcb->ValueCache.ValueList = KeyNode->ValueList.List;
00719         
00720         /* Release the cell */
00721         HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
00722     }
00723     
00724     /* Do the search */
00725     SearchResult = CmpFindValueByNameFromCache(Kcb,
00726                                                ValueName,
00727                                                &CachedValue,
00728                                                &Index,
00729                                                &Value,
00730                                                &ValueCached,
00731                                                &ValueCellToRelease);
00732     if (SearchResult == SearchNeedExclusiveLock)
00733     {
00734         /* We need the exclusive lock */
00735         ASSERT(!CmpIsKcbLockedExclusive(Kcb));
00736         ASSERT(ValueCellToRelease == HCELL_NIL);
00737         ASSERT(Value == NULL);
00738         goto Quickie;
00739     }
00740     else if (SearchResult == SearchSuccess)
00741     {
00742         /* Sanity check */
00743         ASSERT(Value);
00744         
00745         /* First of all, check if the key size and type matches */
00746         if ((Type == Value->Type) &&
00747             (DataSize == (Value->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE)))
00748         {
00749             /* Check if this is a small key */
00750             IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
00751             if (IsSmall)
00752             {
00753                 /* Compare against the data directly */
00754                 Buffer = &Value->Data;
00755             }
00756             else
00757             {
00758                 /* Do a search */
00759                 SearchResult = CmpGetValueDataFromCache(Kcb,
00760                                                         CachedValue,
00761                                                         (PCELL_DATA)Value,
00762                                                         ValueCached,
00763                                                         &Buffer,
00764                                                         &BufferAllocated,
00765                                                         &CellToRelease);
00766                 if (SearchResult != SearchSuccess)
00767                 {
00768                     /* Sanity checks */
00769                     ASSERT(Buffer == NULL);
00770                     ASSERT(BufferAllocated == FALSE);
00771                     goto Quickie;
00772                 }
00773             }
00774             
00775             /* Now check the data size */
00776             if (DataSize)
00777             {
00778                 /* Do the compare */
00779                 CompareResult = RtlCompareMemory(Buffer,
00780                                                  Data,
00781                                                  DataSize &
00782                                                  ~CM_KEY_VALUE_SPECIAL_SIZE);
00783             }
00784             else
00785             {
00786                 /* It's equal */
00787                 CompareResult = 0;
00788             }
00789             
00790             /* Now check if the compare wasn't equal */
00791             if (CompareResult != DataSize) SearchResult = SearchFail;
00792         }
00793         else
00794         {
00795             /* The length or type isn't equal */
00796             SearchResult = SearchFail;
00797         }
00798     }
00799 
00800 Quickie:
00801     /* Release the value cell */
00802     if (ValueCellToRelease) HvReleaseCell(Kcb->KeyHive, ValueCellToRelease);
00803     
00804     /* Free the buffer */
00805     if (BufferAllocated) CmpFree(Buffer, 0);
00806     
00807     /* Free the cell */
00808     if (CellToRelease) HvReleaseCell(Kcb->KeyHive, CellToRelease);
00809 
00810     /* Return the search result */
00811     return SearchResult;
00812 }

Generated on Sat May 26 2012 04:35:59 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.