test: cmsubs2.c Source File

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

# cmsubs2.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1991  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     cmsubs2.c
    00008
    00009 Abstract:
    00010
    00011     This module various support routines for the configuration manager.
    00012
    00013     The routines in this module are independent enough to be linked into
    00014     any other program.  The routines in cmsubs.c are not.
    00015
    00016 Author:
    00017
    00018     Bryan M. Willman (bryanwi) 12-Sep-1991
    00019
    00020 Revision History:
    00021
    00022 --*/
    00023
    00024 #include    "cmp.h"
    00025
    00026 PUCHAR
    00027 CmpGetValueDataFromCache(
    00028     IN PHHIVE  Hive,
    00029     IN PPCM_CACHED_VALUE ContainingList,
    00030     IN PCELL_DATA ValueKey,
    00031     IN BOOLEAN    ValueCached
    00032 );
    00033
    00034 #ifdef ALLOC_PRAGMA
    00035 #pragma alloc_text(PAGE,CmpGetValueDataFromCache)
    00036 #pragma alloc_text(PAGE,CmpFreeValue)
    00037 #pragma alloc_text(PAGE,CmpQueryKeyData)
    00038 #pragma alloc_text(PAGE,CmpQueryKeyValueData)
    00039 #endif
    00040
    00041 //
    00042 // Define alignment macro.
    00043 //
    00044
    00045 #define ALIGN_OFFSET(Offset) (ULONG) \
    00046         ((((ULONG)(Offset) + sizeof(ULONG)-1)) & (~(sizeof(ULONG) - 1)))
    00047
    00048 #define ALIGN_OFFSET64(Offset) (ULONG) \
    00049         ((((ULONG)(Offset) + sizeof(ULONGLONG)-1)) & (~(sizeof(ULONGLONG) - 1)))
    00050
    00051
    00052 VOID
    00053 CmpFreeValue(
    00054     PHHIVE Hive,
    00055     HCELL_INDEX Cell
    00056     )
    00057 /*++
    00058
    00059 Routine Description:
    00060
    00061     Free the value entry Hive.Cell refers to, including
    00062     its name and data cells.
    00063
    00064 Arguments:
    00065
    00066     Hive - supplies a pointer to the hive control structure for the hive
    00067
    00068     Cell - supplies index of value to delete
    00069
    00070 Return Value:
    00071
    00072     NTSTATUS - Result code from call, among the following:
    00073
    00074         <TBS>
    00075
    00076 --*/
    00077 {
    00078     PCELL_DATA value;
    00079     ULONG       realsize;
    00080     BOOLEAN     small;
    00081
    00082     //
    00083     // map in the cell
    00084     //
    00085     value = HvGetCell(Hive, Cell);
    00086
    00087     //
    00088     // free data if present
    00089     //
    00090     small = CmpIsHKeyValueSmall(realsize, value->u.KeyValue.DataLength);
    00091     if ((! small) && (realsize > 0))
    00092     {
    00093         HvFreeCell(Hive, value->u.KeyValue.Data);
    00094     }
    00095
    00096     //
    00097     // free the cell itself
    00098     //
    00099     HvFreeCell(Hive, Cell);
    00100
    00101     return;
    00102 }
    00103
    00104
    00105 //
    00106 // Data transfer workers
    00107 //
    00108
    00109 NTSTATUS
    00110 CmpQueryKeyData(
    00111     PHHIVE Hive,
    00112     PCM_KEY_NODE Node,
    00113     KEY_INFORMATION_CLASS KeyInformationClass,
    00114     PVOID KeyInformation,
    00115     ULONG Length,
    00116     PULONG ResultLength
    00117     )
    00118 /*++
    00119
    00120 Routine Description:
    00121
    00122     Do the actual copy of data for a key into caller's buffer.
    00123
    00124     If KeyInformation is not long enough to hold all requested data,
    00125     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00126     set to the number of bytes actually required.
    00127
    00128 Arguments:
    00129
    00130     Hive - supplies a pointer to the hive control structure for the hive
    00131
    00132     Node - Supplies pointer to node whose subkeys are to be found
    00133
    00134     KeyInformationClass - Specifies the type of information returned in
    00135         Buffer.  One of the following types:
    00136
    00137         KeyBasicInformation - return last write time, title index, and name.
    00138             (see KEY_BASIC_INFORMATION structure)
    00139
    00140         KeyNodeInformation - return last write time, title index, name, class.
    00141             (see KEY_NODE_INFORMATION structure)
    00142
    00143     KeyInformation -Supplies pointer to buffer to receive the data.
    00144
    00145     Length - Length of KeyInformation in bytes.
    00146
    00147     ResultLength - Number of bytes actually written into KeyInformation.
    00148
    00149 Return Value:
    00150
    00151     NTSTATUS - Result code from call, among the following:
    00152
    00153         <TBS>
    00154
    00155 --*/
    00156 {
    00157     NTSTATUS    status;
    00158     PCELL_DATA  pclass;
    00159     ULONG       requiredlength;
    00160     LONG        leftlength;
    00161     ULONG       offset;
    00162     ULONG       minimumlength;
    00163     PKEY_INFORMATION pbuffer;
    00164     USHORT      NameLength;
    00165
    00166     pbuffer = (PKEY_INFORMATION)KeyInformation;
    00167     NameLength = CmpHKeyNameLen(Node);
    00168
    00169     switch (KeyInformationClass) {
    00170
    00171     case KeyBasicInformation:
    00172
    00173         //
    00174         // LastWriteTime, TitleIndex, NameLength, Name
    00175
    00176         requiredlength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) +
    00177                          NameLength;
    00178
    00179         minimumlength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name);
    00180
    00181         *ResultLength = requiredlength;
    00182
    00183         status = STATUS_SUCCESS;
    00184
    00185         if (Length < minimumlength) {
    00186
    00187             status = STATUS_BUFFER_TOO_SMALL;
    00188
    00189         } else {
    00190
    00191             pbuffer->KeyBasicInformation.LastWriteTime =
    00192                 Node->LastWriteTime;
    00193
    00194             pbuffer->KeyBasicInformation.TitleIndex = 0;
    00195
    00196             pbuffer->KeyBasicInformation.NameLength =
    00197                 NameLength;
    00198
    00199             leftlength = Length - minimumlength;
    00200
    00201             requiredlength = NameLength;
    00202
    00203             if (leftlength < (LONG)requiredlength) {
    00204                 requiredlength = leftlength;
    00205                 status = STATUS_BUFFER_OVERFLOW;
    00206             }
    00207
    00208             if (Node->Flags & KEY_COMP_NAME) {
    00209                 CmpCopyCompressedName(pbuffer->KeyBasicInformation.Name,
    00210                                       leftlength,
    00211                                       Node->Name,
    00212                                       Node->NameLength);
    00213             } else {
    00214                 RtlCopyMemory(
    00215                     &(pbuffer->KeyBasicInformation.Name[0]),
    00216                     &(Node->Name[0]),
    00217                     requiredlength
    00218                     );
    00219             }
    00220         }
    00221
    00222         break;
    00223
    00224
    00225     case KeyNodeInformation:
    00226
    00227         //
    00228         // LastWriteTime, TitleIndex, ClassOffset, ClassLength
    00229         // NameLength, Name, Class
    00230         //
    00231         requiredlength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
    00232                          NameLength +
    00233                          Node->ClassLength;
    00234
    00235         minimumlength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
    00236
    00237         *ResultLength = requiredlength;
    00238
    00239         status = STATUS_SUCCESS;
    00240
    00241         if (Length < minimumlength) {
    00242
    00243             status = STATUS_BUFFER_TOO_SMALL;
    00244
    00245         } else {
    00246
    00247             pbuffer->KeyNodeInformation.LastWriteTime =
    00248                 Node->LastWriteTime;
    00249
    00250             pbuffer->KeyNodeInformation.TitleIndex = 0;
    00251
    00252             pbuffer->KeyNodeInformation.ClassLength =
    00253                 Node->ClassLength;
    00254
    00255             pbuffer->KeyNodeInformation.NameLength =
    00256                 NameLength;
    00257
    00258             leftlength = Length - minimumlength;
    00259             requiredlength = NameLength;
    00260
    00261             if (leftlength < (LONG)requiredlength) {
    00262                 requiredlength = leftlength;
    00263                 status = STATUS_BUFFER_OVERFLOW;
    00264             }
    00265
    00266             if (Node->Flags & KEY_COMP_NAME) {
    00267                 CmpCopyCompressedName(pbuffer->KeyNodeInformation.Name,
    00268                                       leftlength,
    00269                                       Node->Name,
    00270                                       Node->NameLength);
    00271             } else {
    00272                 RtlCopyMemory(
    00273                     &(pbuffer->KeyNodeInformation.Name[0]),
    00274                     &(Node->Name[0]),
    00275                     requiredlength
    00276                     );
    00277             }
    00278
    00279             if (Node->ClassLength > 0) {
    00280
    00281                 offset = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
    00282                             NameLength;
    00283                 offset = ALIGN_OFFSET(offset);
    00284
    00285                 pbuffer->KeyNodeInformation.ClassOffset = offset;
    00286
    00287                 pclass = HvGetCell(Hive, Node->Class);
    00288
    00289                 pbuffer = (PKEY_INFORMATION)((PUCHAR)pbuffer + offset);
    00290
    00291                 leftlength = (((LONG)Length - (LONG)offset) < 0) ?
    00292                                     0 :
    00293                                     Length - offset;
    00294
    00295                 requiredlength = Node->ClassLength;
    00296
    00297                 if (leftlength < (LONG)requiredlength) {
    00298                     requiredlength = leftlength;
    00299                     status = STATUS_BUFFER_OVERFLOW;
    00300                 }
    00301
    00302                 RtlMoveMemory(
    00303                     pbuffer,
    00304                     pclass,
    00305                     requiredlength
    00306                     );
    00307
    00308             } else {
    00309                 pbuffer->KeyNodeInformation.ClassOffset = (ULONG)-1;
    00310             }
    00311         }
    00312
    00313         break;
    00314
    00315
    00316     case KeyFullInformation:
    00317
    00318         //
    00319         // LastWriteTime, TitleIndex, ClassOffset, ClassLength,
    00320         // SubKeys, MaxNameLen, MaxClassLen, Values, MaxValueNameLen,
    00321         // MaxValueDataLen, Class
    00322         //
    00323         requiredlength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
    00324                          Node->ClassLength;
    00325
    00326         minimumlength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
    00327
    00328         *ResultLength = requiredlength;
    00329
    00330         status = STATUS_SUCCESS;
    00331
    00332         if (Length < minimumlength) {
    00333
    00334             status = STATUS_BUFFER_TOO_SMALL;
    00335
    00336         } else {
    00337
    00338             pbuffer->KeyFullInformation.LastWriteTime =
    00339                 Node->LastWriteTime;
    00340
    00341             pbuffer->KeyFullInformation.TitleIndex = 0;
    00342
    00343             pbuffer->KeyFullInformation.ClassLength =
    00344                 Node->ClassLength;
    00345
    00346             if (Node->ClassLength > 0) {
    00347
    00348                 pbuffer->KeyFullInformation.ClassOffset =
    00349                         FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
    00350
    00351                 pclass = HvGetCell(Hive, Node->Class);
    00352
    00353                 leftlength = Length - minimumlength;
    00354                 requiredlength = Node->ClassLength;
    00355
    00356                 if (leftlength < (LONG)requiredlength) {
    00357                     requiredlength = leftlength;
    00358                     status = STATUS_BUFFER_OVERFLOW;
    00359                 }
    00360
    00361                 RtlMoveMemory(
    00362                     &(pbuffer->KeyFullInformation.Class[0]),
    00363                     pclass,
    00364                     requiredlength
    00365                     );
    00366
    00367             } else {
    00368                 pbuffer->KeyFullInformation.ClassOffset = (ULONG)-1;
    00369             }
    00370
    00371             pbuffer->KeyFullInformation.SubKeys =
    00372                 Node->SubKeyCounts[Stable] +
    00373                 Node->SubKeyCounts[Volatile];
    00374
    00375             pbuffer->KeyFullInformation.Values =
    00376                 Node->ValueList.Count;
    00377
    00378             pbuffer->KeyFullInformation.MaxNameLen =
    00379                 Node->MaxNameLen;
    00380
    00381             pbuffer->KeyFullInformation.MaxClassLen =
    00382                 Node->MaxClassLen;
    00383
    00384             pbuffer->KeyFullInformation.MaxValueNameLen =
    00385                 Node->MaxValueNameLen;
    00386
    00387             pbuffer->KeyFullInformation.MaxValueDataLen =
    00388                 Node->MaxValueDataLen;
    00389
    00390         }
    00391
    00392         break;
    00393
    00394
    00395     default:
    00396         status = STATUS_INVALID_PARAMETER;
    00397         break;
    00398     }
    00399     return status;
    00400 }
    00401
    00402 PUCHAR
    00403 CmpGetValueDataFromCache(
    00404     IN PHHIVE  Hive,
    00405     IN PPCM_CACHED_VALUE ContainingList,
    00406     IN PCELL_DATA ValueKey,
    00407     IN BOOLEAN    ValueCached
    00408 )
    00409 /*++
    00410
    00411 Routine Description:
    00412
    00413     Get the cached Value Data given a value node.
    00414
    00415 Arguments:
    00416
    00417     Hive - pointer to hive control structure for hive of interest
    00418
    00419     ContainingList - Address that stores the allocation address of the value node.
    00420                      We need to update this when we do a re-allocate to cache
    00421                      both value key and value data.
    00422
    00423     ValueKey - pointer to the Value Key
    00424
    00425     ValueCached - Indicating whether Value key is cached or not.
    00426
    00427 Return Value:
    00428
    00429     Pointer to the Valve Index.
    00430 --*/
    00431 {
    00432     //
    00433     // Cache the data if needed.
    00434     //
    00435     PCM_CACHED_VALUE OldEntry;
    00436     PCM_CACHED_VALUE NewEntry;
    00437     PUCHAR      datapointer;
    00438     PUCHAR      Cacheddatapointer;
    00439     ULONG       AllocSize;
    00440     ULONG       CopySize;
    00441     ULONG       DataSize;
    00442
    00443     if (ValueCached) {
    00444         OldEntry = (PCM_CACHED_VALUE) CMP_GET_CACHED_ADDRESS(*ContainingList);
    00445         if (OldEntry->DataCacheType == CM_CACHE_DATA_CACHED) {
    00446             //
    00447             // Data is already cached, use it.
    00448             //
    00449             datapointer = (PUCHAR) ((ULONG_PTR) ValueKey + OldEntry->ValueKeySize);
    00450         } else if (OldEntry->DataCacheType == CM_CACHE_DATA_TOO_BIG) {
    00451             //
    00452             // Data is too big to warrent caching, get it from the registry.
    00453             //
    00454             datapointer = (PUCHAR)HvGetCell(Hive, ValueKey->u.KeyValue.Data);
    00455         } else {
    00456             //
    00457             // consistency check
    00458             //
    00459             ASSERT(OldEntry->DataCacheType == CM_CACHE_DATA_NOT_CACHED);
    00460
    00461             //
    00462             // Value data is not cached.
    00463             // Check the size of value data, if it is smaller than MAXIMUM_CACHED_DATA, cache it.
    00464             //
    00465             datapointer = (PUCHAR)HvGetCell(Hive, ValueKey->u.KeyValue.Data);
    00466             DataSize = (ULONG) HvGetCellSize(Hive, datapointer);
    00467             if (DataSize <= MAXIMUM_CACHED_DATA) {
    00468                 //
    00469                 // Data is not cached and now we are going to do it.
    00470                 // Reallocate a new cached entry for both value key and value data.
    00471                 //
    00472                 CopySize = DataSize + OldEntry->ValueKeySize;
    00473                 AllocSize = CopySize + FIELD_OFFSET(CM_CACHED_VALUE, KeyValue);
    00474
    00475                 // Dragos: Changed to catch the memory violator
    00476                 // it didn't work
    00477                 //NewEntry = (PCM_CACHED_VALUE) ExAllocatePoolWithTagPriority(PagedPool, AllocSize, CM_CACHE_VALUE_DATA_TAG,NormalPoolPrioritySpecialPoolUnderrun);
    00478                 NewEntry = (PCM_CACHED_VALUE) ExAllocatePoolWithTag(PagedPool, AllocSize, CM_CACHE_VALUE_DATA_TAG);
    00479
    00480                 if (NewEntry) {
    00481                     //
    00482                     // Now fill the data to the new cached entry
    00483                     //
    00484                     NewEntry->DataCacheType = CM_CACHE_DATA_CACHED;
    00485                     NewEntry->ValueKeySize = OldEntry->ValueKeySize;
    00486
    00487                     RtlCopyMemory((PVOID)&(NewEntry->KeyValue),
    00488                                   (PVOID)&(OldEntry->KeyValue),
    00489                                   NewEntry->ValueKeySize);
    00490
    00491                     Cacheddatapointer = (PUCHAR) ((ULONG_PTR) &(NewEntry->KeyValue) + OldEntry->ValueKeySize);
    00492                     RtlCopyMemory(Cacheddatapointer, datapointer, DataSize);
    00493
    00494                     // Trying to catch the BAD guy who writes over our pool.
    00495                     CmpMakeSpecialPoolReadWrite( OldEntry );
    00496
    00497                     *ContainingList = (PCM_CACHED_VALUE) CMP_MARK_CELL_CACHED(NewEntry);
    00498
    00499                     // Trying to catch the BAD guy who writes over our pool.
    00500                     CmpMakeSpecialPoolReadOnly( NewEntry );
    00501
    00502                     //
    00503                     // Free the old entry
    00504                     //
    00505
    00506                     ExFreePool(OldEntry);
    00507                 }
    00508             } else {
    00509                 // Trying to catch the BAD guy who writes over our pool.
    00510                 CmpMakeSpecialPoolReadWrite( OldEntry );
    00511
    00512                 //
    00513                 // Mark the type and do not cache it.
    00514                 //
    00515                 OldEntry->DataCacheType = CM_CACHE_DATA_TOO_BIG;
    00516
    00517                 // Trying to catch the BAD guy who writes over our pool.
    00518                 CmpMakeSpecialPoolReadOnly( OldEntry );
    00519             }
    00520         }
    00521     } else {
    00522         datapointer = (PUCHAR)HvGetCell(Hive, ValueKey->u.KeyValue.Data);
    00523     }
    00524
    00525     return (datapointer);
    00526 }
    00527
    00528
    00529
    00530 NTSTATUS
    00531 CmpQueryKeyValueData(
    00532     PHHIVE Hive,
    00533     PPCM_CACHED_VALUE ContainingList,
    00534     PCM_KEY_VALUE ValueKey,
    00535     BOOLEAN     ValueCached,
    00536     KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
    00537     PVOID KeyValueInformation,
    00538     ULONG Length,
    00539     PULONG ResultLength
    00540     )
    00541 /*++
    00542
    00543 Routine Description:
    00544
    00545     Do the actual copy of data for a key value into caller's buffer.
    00546
    00547     If KeyValueInformation is not long enough to hold all requested data,
    00548     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00549     set to the number of bytes actually required.
    00550
    00551 Arguments:
    00552
    00553     Hive - supplies a pointer to the hive control structure for the hive
    00554
    00555     Cell - supplies index of node to whose sub keys are to be found
    00556
    00557     KeyValueInformationClass - Specifies the type of information returned in
    00558         KeyValueInformation.  One of the following types:
    00559
    00560     KeyValueInformation -Supplies pointer to buffer to receive the data.
    00561
    00562     Length - Length of KeyInformation in bytes.
    00563
    00564     ResultLength - Number of bytes actually written into KeyInformation.
    00565
    00566 Return Value:
    00567
    00568     NTSTATUS - Result code from call, among the following:
    00569
    00570         <TBS>
    00571
    00572 --*/
    00573 {
    00574     NTSTATUS    status;
    00575     PKEY_VALUE_INFORMATION pbuffer;
    00576     PCELL_DATA  pcell;
    00577     LONG        leftlength;
    00578     ULONG       requiredlength;
    00579     ULONG       minimumlength;
    00580     ULONG       offset;
    00581     ULONG       base;
    00582     ULONG       realsize;
    00583     PUCHAR      datapointer;
    00584     BOOLEAN     small;
    00585     USHORT      NameLength;
    00586
    00587     pbuffer = (PKEY_VALUE_INFORMATION)KeyValueInformation;
    00588
    00589     pcell = (PCELL_DATA) ValueKey;
    00590     NameLength = CmpValueNameLen(&pcell->u.KeyValue);
    00591
    00592     switch (KeyValueInformationClass) {
    00593
    00594     case KeyValueBasicInformation:
    00595
    00596         //
    00597         // TitleIndex, Type, NameLength, Name
    00598         //
    00599         requiredlength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
    00600                          NameLength;
    00601
    00602         minimumlength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name);
    00603
    00604         *ResultLength = requiredlength;
    00605
    00606         status = STATUS_SUCCESS;
    00607
    00608         if (Length < minimumlength) {
    00609
    00610             status = STATUS_BUFFER_TOO_SMALL;
    00611
    00612         } else {
    00613
    00614             pbuffer->KeyValueBasicInformation.TitleIndex = 0;
    00615
    00616             pbuffer->KeyValueBasicInformation.Type =
    00617                 pcell->u.KeyValue.Type;
    00618
    00619             pbuffer->KeyValueBasicInformation.NameLength =
    00620                 NameLength;
    00621
    00622             leftlength = Length - minimumlength;
    00623             requiredlength = NameLength;
    00624
    00625             if (leftlength < (LONG)requiredlength) {
    00626                 requiredlength = leftlength;
    00627                 status = STATUS_BUFFER_OVERFLOW;
    00628             }
    00629
    00630             if (pcell->u.KeyValue.Flags & VALUE_COMP_NAME) {
    00631                 CmpCopyCompressedName(pbuffer->KeyValueBasicInformation.Name,
    00632                                       requiredlength,
    00633                                       pcell->u.KeyValue.Name,
    00634                                       pcell->u.KeyValue.NameLength);
    00635             } else {
    00636                 RtlCopyMemory(&(pbuffer->KeyValueBasicInformation.Name[0]),
    00637                               &(pcell->u.KeyValue.Name[0]),
    00638                               requiredlength);
    00639             }
    00640         }
    00641
    00642         break;
    00643
    00644
    00645
    00646     case KeyValueFullInformation:
    00647     case KeyValueFullInformationAlign64:
    00648
    00649         //
    00650         // TitleIndex, Type, DataOffset, DataLength, NameLength,
    00651         // Name, Data
    00652         //
    00653         small = CmpIsHKeyValueSmall(realsize, pcell->u.KeyValue.DataLength);
    00654
    00655         requiredlength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) +
    00656                          NameLength +
    00657                          realsize;
    00658
    00659         minimumlength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
    00660         if (realsize > 0) {
    00661             base = requiredlength - realsize;
    00662
    00663 #if defined(_WIN64)
    00664
    00665             offset = ALIGN_OFFSET64(base);
    00666
    00667 #else
    00668
    00669             if (KeyValueInformationClass == KeyValueFullInformationAlign64) {
    00670                 offset = ALIGN_OFFSET64(base);
    00671
    00672             } else {
    00673                 offset = ALIGN_OFFSET(base);
    00674             }
    00675
    00676 #endif
    00677
    00678             if (offset > base) {
    00679                 requiredlength += (offset - base);
    00680             }
    00681
    00682 #if DBG && defined(_WIN64)
    00683
    00684             //
    00685             // Some clients will have passed in a structure that they "know"
    00686             // will be exactly the right size.  The fact that alignment
    00687             // has changed on NT64 may cause these clients to have problems.
    00688             //
    00689             // The solution is to fix the client, but print out some debug
    00690             // spew here if it looks like this is the case.  This problem
    00691             // isn't particularly easy to spot from the client end.
    00692             //
    00693
    00694             if((KeyValueInformationClass == KeyValueFullInformation) &&
    00695                 (Length != minimumlength) &&
    00696                 (requiredlength > Length) &&
    00697                 ((requiredlength - Length) <=
    00698                                 (ALIGN_OFFSET64(base) - ALIGN_OFFSET(base)))) {
    00699
    00700                 KdPrint(("ntos/config-64 KeyValueFullInformation: "
    00701                          "Possible client buffer size problem.\n"));
    00702
    00703                 KdPrint(("    Required size = %d\n", requiredlength));
    00704                 KdPrint(("    Supplied size = %d\n", Length));
    00705             }
    00706
    00707 #endif
    00708
    00709         }
    00710
    00711         *ResultLength = requiredlength;
    00712
    00713         status = STATUS_SUCCESS;
    00714
    00715         if (Length < minimumlength) {
    00716
    00717             status = STATUS_BUFFER_TOO_SMALL;
    00718
    00719         } else {
    00720
    00721             pbuffer->KeyValueFullInformation.TitleIndex = 0;
    00722
    00723             pbuffer->KeyValueFullInformation.Type =
    00724                 pcell->u.KeyValue.Type;
    00725
    00726             pbuffer->KeyValueFullInformation.DataLength =
    00727                 realsize;
    00728
    00729             pbuffer->KeyValueFullInformation.NameLength =
    00730                 NameLength;
    00731
    00732             leftlength = Length - minimumlength;
    00733             requiredlength = NameLength;
    00734
    00735             if (leftlength < (LONG)requiredlength) {
    00736                 requiredlength = leftlength;
    00737                 status = STATUS_BUFFER_OVERFLOW;
    00738             }
    00739
    00740             if (pcell->u.KeyValue.Flags & VALUE_COMP_NAME) {
    00741                 CmpCopyCompressedName(pbuffer->KeyValueFullInformation.Name,
    00742                                       requiredlength,
    00743                                       pcell->u.KeyValue.Name,
    00744                                       pcell->u.KeyValue.NameLength);
    00745             } else {
    00746                 RtlMoveMemory(
    00747                     &(pbuffer->KeyValueFullInformation.Name[0]),
    00748                     &(pcell->u.KeyValue.Name[0]),
    00749                     requiredlength
    00750                     );
    00751             }
    00752
    00753             if (realsize > 0) {
    00754
    00755                 if (small == TRUE) {
    00756                     datapointer = (PUCHAR)(&(pcell->u.KeyValue.Data));
    00757                 } else {
    00758                     datapointer = CmpGetValueDataFromCache(Hive, ContainingList, pcell, ValueCached);
    00759                 }
    00760
    00761                 pbuffer->KeyValueFullInformation.DataOffset = offset;
    00762
    00763                 leftlength = (((LONG)Length - (LONG)offset) < 0) ?
    00764                                     0 :
    00765                                     Length - offset;
    00766
    00767                 requiredlength = realsize;
    00768
    00769                 if (leftlength < (LONG)requiredlength) {
    00770                     requiredlength = leftlength;
    00771                     status = STATUS_BUFFER_OVERFLOW;
    00772                 }
    00773
    00774                 ASSERT((small ? (requiredlength <= CM_KEY_VALUE_SMALL) : TRUE));
    00775
    00776                 RtlMoveMemory(
    00777                     ((PUCHAR)pbuffer + offset),
    00778                     datapointer,
    00779                     requiredlength
    00780                     );
    00781
    00782             } else {
    00783                 pbuffer->KeyValueFullInformation.DataOffset = (ULONG)-1;
    00784             }
    00785         }
    00786
    00787         break;
    00788
    00789
    00790     case KeyValuePartialInformation:
    00791
    00792         //
    00793         // TitleIndex, Type, DataLength, Data
    00794         //
    00795         small = CmpIsHKeyValueSmall(realsize, pcell->u.KeyValue.DataLength);
    00796         requiredlength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
    00797                          realsize;
    00798
    00799         minimumlength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
    00800
    00801         *ResultLength = requiredlength;
    00802
    00803         status = STATUS_SUCCESS;
    00804
    00805         if (Length < minimumlength) {
    00806
    00807             status = STATUS_BUFFER_TOO_SMALL;
    00808
    00809         } else {
    00810
    00811             pbuffer->KeyValuePartialInformation.TitleIndex = 0;
    00812
    00813             pbuffer->KeyValuePartialInformation.Type =
    00814                 pcell->u.KeyValue.Type;
    00815
    00816             pbuffer->KeyValuePartialInformation.DataLength =
    00817                 realsize;
    00818
    00819             leftlength = Length - minimumlength;
    00820             requiredlength = realsize;
    00821
    00822             if (leftlength < (LONG)requiredlength) {
    00823                 requiredlength = leftlength;
    00824                 status = STATUS_BUFFER_OVERFLOW;
    00825             }
    00826
    00827             if (realsize > 0) {
    00828
    00829                 if (small == TRUE) {
    00830                     datapointer = (PUCHAR)(&(pcell->u.KeyValue.Data));
    00831                 } else {
    00832                     datapointer = CmpGetValueDataFromCache(Hive, ContainingList, pcell, ValueCached);
    00833                 }
    00834
    00835                 ASSERT((small ? (requiredlength <= CM_KEY_VALUE_SMALL) : TRUE));
    00836
    00837                 RtlMoveMemory((PUCHAR)&(pbuffer->KeyValuePartialInformation.Data[0]),
    00838                               datapointer,
    00839                               requiredlength);
    00840             }
    00841         }
    00842
    00843         break;
    00844     case KeyValuePartialInformationAlign64:
    00845
    00846         //
    00847         // TitleIndex, Type, DataLength, Data
    00848         //
    00849         small = CmpIsHKeyValueSmall(realsize, pcell->u.KeyValue.DataLength);
    00850         requiredlength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data) +
    00851                          realsize;
    00852
    00853         minimumlength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data);
    00854
    00855         *ResultLength = requiredlength;
    00856
    00857         status = STATUS_SUCCESS;
    00858
    00859         if (Length < minimumlength) {
    00860
    00861             status = STATUS_BUFFER_TOO_SMALL;
    00862
    00863         } else {
    00864
    00865             pbuffer->KeyValuePartialInformationAlign64.Type =
    00866                 pcell->u.KeyValue.Type;
    00867
    00868             pbuffer->KeyValuePartialInformationAlign64.DataLength =
    00869                 realsize;
    00870
    00871             leftlength = Length - minimumlength;
    00872             requiredlength = realsize;
    00873
    00874             if (leftlength < (LONG)requiredlength) {
    00875                 requiredlength = leftlength;
    00876                 status = STATUS_BUFFER_OVERFLOW;
    00877             }
    00878
    00879             if (realsize > 0) {
    00880
    00881                 if (small == TRUE) {
    00882                     datapointer = (PUCHAR)(&(pcell->u.KeyValue.Data));
    00883                 } else {
    00884                     datapointer = CmpGetValueDataFromCache(Hive, ContainingList, pcell, ValueCached);
    00885                 }
    00886
    00887                 ASSERT((small ? (requiredlength <= CM_KEY_VALUE_SMALL) : TRUE));
    00888                 RtlMoveMemory((PUCHAR)&(pbuffer->KeyValuePartialInformationAlign64.Data[0]),
    00889                               datapointer,
    00890                               requiredlength);
    00891             }
    00892         }
    00893
    00894         break;
    00895
    00896     default:
    00897         status = STATUS_INVALID_PARAMETER;
    00898         break;
    00899     }
    00900     return status;
    00901 }
    00902