00543 :
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
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
00651
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
00686
00687
00688
00689
00690
00691
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
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
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 }
}