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 

Generated on Sat May 15 19:39:28 2004 for test by doxygen 1.3.7