mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +00:00
Correctly handle small buffers in NtEnumerate[Value]Key and NtQuery[Value]Key registry routines:
- If buffer is too small to contain even fixed size information for specified type return STATUS_BUFFER_TOO_SMALL. - If buffer is large enough to contain some information, but not all information requested, fill as much as we can and return STATUS_BUFFER_OVERFLOW. - If we fill the entire buffer return STATUS_SUCCESS. svn path=/trunk/; revision=11235
This commit is contained in:
parent
ef253bf9d3
commit
1e09759df9
2 changed files with 257 additions and 100 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: reg.c,v 1.58 2004/09/28 20:40:15 gvg Exp $
|
/* $Id: reg.c,v 1.59 2004/10/08 21:19:12 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -2304,7 +2304,7 @@ RegQueryValueExW (HKEY hKey,
|
||||||
BufferSize,
|
BufferSize,
|
||||||
&ResultSize);
|
&ResultSize);
|
||||||
DPRINT("Status 0x%X\n", Status);
|
DPRINT("Status 0x%X\n", Status);
|
||||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
if (Status == STATUS_BUFFER_OVERFLOW)
|
||||||
{
|
{
|
||||||
/* Return ERROR_SUCCESS and the buffer space needed for a successful call */
|
/* Return ERROR_SUCCESS and the buffer space needed for a successful call */
|
||||||
MaxCopy = 0;
|
MaxCopy = 0;
|
||||||
|
|
|
@ -313,7 +313,7 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
PKEY_NODE_INFORMATION NodeInformation;
|
PKEY_NODE_INFORMATION NodeInformation;
|
||||||
PKEY_FULL_INFORMATION FullInformation;
|
PKEY_FULL_INFORMATION FullInformation;
|
||||||
PDATA_CELL ClassCell;
|
PDATA_CELL ClassCell;
|
||||||
ULONG NameSize;
|
ULONG NameSize, ClassSize;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
|
DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
|
||||||
|
@ -444,6 +444,8 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: It's perfetly valid to call NtEnumerateKey to get
|
* NOTE: It's perfetly valid to call NtEnumerateKey to get
|
||||||
* all the information but name. Actually the NT4 sound
|
* all the information but name. Actually the NT4 sound
|
||||||
|
@ -452,7 +454,7 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
*/
|
*/
|
||||||
if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
|
if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -463,7 +465,12 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
BasicInformation->TitleIndex = Index;
|
BasicInformation->TitleIndex = Index;
|
||||||
BasicInformation->NameLength = NameSize;
|
BasicInformation->NameLength = NameSize;
|
||||||
|
|
||||||
NameSize = min(NameSize, Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]));
|
if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) < NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
if (SubKeyObject != NULL)
|
if (SubKeyObject != NULL)
|
||||||
{
|
{
|
||||||
|
@ -487,8 +494,6 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyNodeInformation:
|
case KeyNodeInformation:
|
||||||
|
@ -505,12 +510,14 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
NameSize *= sizeof(WCHAR);
|
NameSize *= sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
|
ClassSize = SubKeyCell->ClassSize;
|
||||||
NameSize + SubKeyCell->ClassSize;
|
|
||||||
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
|
||||||
|
NameSize + ClassSize;
|
||||||
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -521,51 +528,68 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
NodeInformation->TitleIndex = Index;
|
NodeInformation->TitleIndex = Index;
|
||||||
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NameSize;
|
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NameSize;
|
||||||
NodeInformation->ClassLength = SubKeyCell->ClassSize;
|
NodeInformation->ClassLength = SubKeyCell->ClassSize;
|
||||||
|
NodeInformation->NameLength = NameSize;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
|
||||||
|
ClassSize = 0;
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
else if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
|
||||||
|
NameSize < ClassSize)
|
||||||
|
{
|
||||||
|
ClassSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
|
||||||
|
NameSize;
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
if (SubKeyObject != NULL)
|
if (SubKeyObject != NULL)
|
||||||
{
|
{
|
||||||
NodeInformation->NameLength = SubKeyObject->Name.Length;
|
|
||||||
RtlCopyMemory(NodeInformation->Name,
|
RtlCopyMemory(NodeInformation->Name,
|
||||||
SubKeyObject->Name.Buffer,
|
SubKeyObject->Name.Buffer,
|
||||||
SubKeyObject->Name.Length);
|
NameSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NodeInformation->NameLength = NameSize;
|
|
||||||
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
||||||
{
|
{
|
||||||
CmiCopyPackedName(NodeInformation->Name,
|
CmiCopyPackedName(NodeInformation->Name,
|
||||||
SubKeyCell->Name,
|
SubKeyCell->Name,
|
||||||
SubKeyCell->NameSize);
|
NameSize / sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory(NodeInformation->Name,
|
RtlCopyMemory(NodeInformation->Name,
|
||||||
SubKeyCell->Name,
|
SubKeyCell->Name,
|
||||||
SubKeyCell->NameSize);
|
NameSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SubKeyCell->ClassSize != 0)
|
if (ClassSize != 0)
|
||||||
{
|
{
|
||||||
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
||||||
SubKeyCell->ClassNameOffset,
|
SubKeyCell->ClassNameOffset,
|
||||||
NULL);
|
NULL);
|
||||||
RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize,
|
RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize,
|
||||||
ClassCell->Data,
|
ClassCell->Data,
|
||||||
SubKeyCell->ClassSize);
|
ClassSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyFullInformation:
|
case KeyFullInformation:
|
||||||
/* Check size of buffer */
|
ClassSize = SubKeyCell->ClassSize;
|
||||||
*ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) +
|
|
||||||
SubKeyCell->ClassSize;
|
|
||||||
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) +
|
||||||
|
ClassSize;
|
||||||
|
|
||||||
|
/* Check size of buffer */
|
||||||
|
if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -585,14 +609,22 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
CmiGetMaxValueNameLength(RegistryHive, SubKeyCell);
|
CmiGetMaxValueNameLength(RegistryHive, SubKeyCell);
|
||||||
FullInformation->MaxValueDataLen =
|
FullInformation->MaxValueDataLen =
|
||||||
CmiGetMaxValueDataLength(RegistryHive, SubKeyCell);
|
CmiGetMaxValueDataLength(RegistryHive, SubKeyCell);
|
||||||
if (SubKeyCell->ClassSize != 0)
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
|
||||||
|
{
|
||||||
|
ClassSize = Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassSize != 0)
|
||||||
{
|
{
|
||||||
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
||||||
SubKeyCell->ClassNameOffset,
|
SubKeyCell->ClassNameOffset,
|
||||||
NULL);
|
NULL);
|
||||||
RtlCopyMemory (FullInformation->Class,
|
RtlCopyMemory (FullInformation->Class,
|
||||||
ClassCell->Data,
|
ClassCell->Data,
|
||||||
SubKeyCell->ClassSize);
|
ClassSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -626,7 +658,7 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
PKEY_CELL KeyCell;
|
PKEY_CELL KeyCell;
|
||||||
PVALUE_CELL ValueCell;
|
PVALUE_CELL ValueCell;
|
||||||
PDATA_CELL DataCell;
|
PDATA_CELL DataCell;
|
||||||
ULONG NameSize;
|
ULONG NameSize, DataSize;
|
||||||
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
|
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
|
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
|
||||||
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
|
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
|
||||||
|
@ -686,10 +718,12 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
{
|
{
|
||||||
NameSize *= sizeof(WCHAR);
|
NameSize *= sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ResultLength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) + NameSize;
|
*ResultLength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) + NameSize;
|
||||||
if (Length < *ResultLength)
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -698,11 +732,20 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
ValueBasicInformation->TitleIndex = 0;
|
ValueBasicInformation->TitleIndex = 0;
|
||||||
ValueBasicInformation->Type = ValueCell->DataType;
|
ValueBasicInformation->Type = ValueCell->DataType;
|
||||||
ValueBasicInformation->NameLength = NameSize;
|
ValueBasicInformation->NameLength = NameSize;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) <
|
||||||
|
NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
||||||
{
|
{
|
||||||
CmiCopyPackedName(ValueBasicInformation->Name,
|
CmiCopyPackedName(ValueBasicInformation->Name,
|
||||||
ValueCell->Name,
|
ValueCell->Name,
|
||||||
ValueCell->NameSize);
|
NameSize / sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -714,11 +757,14 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyValuePartialInformation:
|
case KeyValuePartialInformation:
|
||||||
|
DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
|
|
||||||
*ResultLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) +
|
*ResultLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) +
|
||||||
(ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize;
|
||||||
if (Length < *ResultLength)
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -727,18 +773,27 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
ValuePartialInformation->TitleIndex = 0;
|
ValuePartialInformation->TitleIndex = 0;
|
||||||
ValuePartialInformation->Type = ValueCell->DataType;
|
ValuePartialInformation->Type = ValueCell->DataType;
|
||||||
ValuePartialInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
ValuePartialInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) <
|
||||||
|
DataSize)
|
||||||
|
{
|
||||||
|
DataSize = Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
||||||
{
|
{
|
||||||
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
||||||
RtlCopyMemory(ValuePartialInformation->Data,
|
RtlCopyMemory(ValuePartialInformation->Data,
|
||||||
DataCell->Data,
|
DataCell->Data,
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory(ValuePartialInformation->Data,
|
RtlCopyMemory(ValuePartialInformation->Data,
|
||||||
&ValueCell->DataOffset,
|
&ValueCell->DataOffset,
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -749,11 +804,14 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
{
|
{
|
||||||
NameSize *= sizeof(WCHAR);
|
NameSize *= sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
*ResultLength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) +
|
DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
NameSize + (ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
|
||||||
|
Name[0]) + NameSize, sizeof(PVOID)) + DataSize;
|
||||||
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -762,18 +820,6 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
ValueFullInformation->TitleIndex = 0;
|
ValueFullInformation->TitleIndex = 0;
|
||||||
ValueFullInformation->Type = ValueCell->DataType;
|
ValueFullInformation->Type = ValueCell->DataType;
|
||||||
ValueFullInformation->NameLength = NameSize;
|
ValueFullInformation->NameLength = NameSize;
|
||||||
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
|
||||||
{
|
|
||||||
CmiCopyPackedName(ValueFullInformation->Name,
|
|
||||||
ValueCell->Name,
|
|
||||||
ValueCell->NameSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RtlCopyMemory(ValueFullInformation->Name,
|
|
||||||
ValueCell->Name,
|
|
||||||
ValueCell->NameSize);
|
|
||||||
}
|
|
||||||
ValueFullInformation->DataOffset =
|
ValueFullInformation->DataOffset =
|
||||||
(ULONG_PTR)ValueFullInformation->Name -
|
(ULONG_PTR)ValueFullInformation->Name -
|
||||||
(ULONG_PTR)ValueFullInformation +
|
(ULONG_PTR)ValueFullInformation +
|
||||||
|
@ -781,20 +827,48 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
ValueFullInformation->DataOffset =
|
ValueFullInformation->DataOffset =
|
||||||
ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
|
ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
|
||||||
ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) <
|
||||||
|
NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
|
||||||
|
DataSize = 0;
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
else if (ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
|
||||||
|
Name[0]) - NameSize, sizeof(PVOID)) < DataSize)
|
||||||
|
{
|
||||||
|
DataSize = ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) - NameSize, sizeof(PVOID));
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
||||||
|
{
|
||||||
|
CmiCopyPackedName(ValueFullInformation->Name,
|
||||||
|
ValueCell->Name,
|
||||||
|
NameSize / sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlCopyMemory(ValueFullInformation->Name,
|
||||||
|
ValueCell->Name,
|
||||||
|
NameSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
||||||
{
|
{
|
||||||
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
||||||
RtlCopyMemory((PCHAR) ValueFullInformation
|
RtlCopyMemory((PCHAR) ValueFullInformation
|
||||||
+ ValueFullInformation->DataOffset,
|
+ ValueFullInformation->DataOffset,
|
||||||
DataCell->Data,
|
DataCell->Data, DataSize);
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory((PCHAR) ValueFullInformation
|
RtlCopyMemory((PCHAR) ValueFullInformation
|
||||||
+ ValueFullInformation->DataOffset,
|
+ ValueFullInformation->DataOffset,
|
||||||
&ValueCell->DataOffset,
|
&ValueCell->DataOffset, DataSize);
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -941,6 +1015,7 @@ NtQueryKey(IN HANDLE KeyHandle,
|
||||||
PDATA_CELL ClassCell;
|
PDATA_CELL ClassCell;
|
||||||
PKEY_OBJECT KeyObject;
|
PKEY_OBJECT KeyObject;
|
||||||
PKEY_CELL KeyCell;
|
PKEY_CELL KeyCell;
|
||||||
|
ULONG NameSize, ClassSize;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
|
DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
|
||||||
|
@ -976,11 +1051,12 @@ NtQueryKey(IN HANDLE KeyHandle,
|
||||||
switch (KeyInformationClass)
|
switch (KeyInformationClass)
|
||||||
{
|
{
|
||||||
case KeyBasicInformation:
|
case KeyBasicInformation:
|
||||||
/* Check size of buffer */
|
NameSize = KeyObject->Name.Length;
|
||||||
*ResultLength = sizeof(KEY_BASIC_INFORMATION) +
|
|
||||||
KeyObject->Name.Length;
|
|
||||||
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
|
||||||
|
|
||||||
|
/* Check size of buffer */
|
||||||
|
if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
@ -993,17 +1069,28 @@ NtQueryKey(IN HANDLE KeyHandle,
|
||||||
BasicInformation->TitleIndex = 0;
|
BasicInformation->TitleIndex = 0;
|
||||||
BasicInformation->NameLength = KeyObject->Name.Length;
|
BasicInformation->NameLength = KeyObject->Name.Length;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) <
|
||||||
|
NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
RtlCopyMemory(BasicInformation->Name,
|
RtlCopyMemory(BasicInformation->Name,
|
||||||
KeyObject->Name.Buffer,
|
KeyObject->Name.Buffer,
|
||||||
KeyObject->Name.Length);
|
NameSize);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyNodeInformation:
|
case KeyNodeInformation:
|
||||||
/* Check size of buffer */
|
NameSize = KeyObject->Name.Length;
|
||||||
*ResultLength = sizeof(KEY_NODE_INFORMATION) +
|
ClassSize = KeyCell->ClassSize;
|
||||||
KeyObject->Name.Length + KeyCell->ClassSize;
|
|
||||||
|
|
||||||
|
*ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
|
||||||
|
NameSize + ClassSize;
|
||||||
|
|
||||||
|
/* Check size of buffer */
|
||||||
if (Length < *ResultLength)
|
if (Length < *ResultLength)
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
@ -1020,28 +1107,46 @@ NtQueryKey(IN HANDLE KeyHandle,
|
||||||
NodeInformation->ClassLength = KeyCell->ClassSize;
|
NodeInformation->ClassLength = KeyCell->ClassSize;
|
||||||
NodeInformation->NameLength = KeyObject->Name.Length;
|
NodeInformation->NameLength = KeyObject->Name.Length;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
|
||||||
|
ClassSize = 0;
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
else if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
|
||||||
|
NameSize < ClassSize)
|
||||||
|
{
|
||||||
|
ClassSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
|
||||||
|
NameSize;
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
RtlCopyMemory(NodeInformation->Name,
|
RtlCopyMemory(NodeInformation->Name,
|
||||||
KeyObject->Name.Buffer,
|
KeyObject->Name.Buffer,
|
||||||
KeyObject->Name.Length);
|
NameSize);
|
||||||
|
|
||||||
if (KeyCell->ClassSize != 0)
|
if (ClassSize != 0)
|
||||||
{
|
{
|
||||||
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
||||||
KeyCell->ClassNameOffset,
|
KeyCell->ClassNameOffset,
|
||||||
NULL);
|
NULL);
|
||||||
RtlCopyMemory (NodeInformation->Name + KeyObject->Name.Length,
|
RtlCopyMemory (NodeInformation->Name + KeyObject->Name.Length,
|
||||||
ClassCell->Data,
|
ClassCell->Data,
|
||||||
KeyCell->ClassSize);
|
ClassSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyFullInformation:
|
case KeyFullInformation:
|
||||||
/* Check size of buffer */
|
ClassSize = KeyCell->ClassSize;
|
||||||
*ResultLength = sizeof(KEY_FULL_INFORMATION) +
|
|
||||||
KeyCell->ClassSize;
|
|
||||||
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
|
||||||
|
ClassSize;
|
||||||
|
|
||||||
|
/* Check size of buffer */
|
||||||
|
if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
@ -1062,14 +1167,21 @@ NtQueryKey(IN HANDLE KeyHandle,
|
||||||
CmiGetMaxValueNameLength(RegistryHive, KeyCell);
|
CmiGetMaxValueNameLength(RegistryHive, KeyCell);
|
||||||
FullInformation->MaxValueDataLen =
|
FullInformation->MaxValueDataLen =
|
||||||
CmiGetMaxValueDataLength(RegistryHive, KeyCell);
|
CmiGetMaxValueDataLength(RegistryHive, KeyCell);
|
||||||
if (KeyCell->ClassSize != 0)
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
|
||||||
|
{
|
||||||
|
ClassSize = Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassSize)
|
||||||
{
|
{
|
||||||
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
ClassCell = CmiGetCell (KeyObject->RegistryHive,
|
||||||
KeyCell->ClassNameOffset,
|
KeyCell->ClassNameOffset,
|
||||||
NULL);
|
NULL);
|
||||||
RtlCopyMemory (FullInformation->Class,
|
RtlCopyMemory (FullInformation->Class,
|
||||||
ClassCell->Data,
|
ClassCell->Data, ClassSize);
|
||||||
KeyCell->ClassSize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1097,7 +1209,7 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
OUT PULONG ResultLength)
|
OUT PULONG ResultLength)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG NameSize;
|
ULONG NameSize, DataSize;
|
||||||
PKEY_OBJECT KeyObject;
|
PKEY_OBJECT KeyObject;
|
||||||
PREGISTRY_HIVE RegistryHive;
|
PREGISTRY_HIVE RegistryHive;
|
||||||
PKEY_CELL KeyCell;
|
PKEY_CELL KeyCell;
|
||||||
|
@ -1155,8 +1267,11 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
{
|
{
|
||||||
NameSize *= sizeof(WCHAR);
|
NameSize *= sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameSize;
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) +
|
||||||
|
NameSize;
|
||||||
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
@ -1167,25 +1282,37 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
ValueBasicInformation->TitleIndex = 0;
|
ValueBasicInformation->TitleIndex = 0;
|
||||||
ValueBasicInformation->Type = ValueCell->DataType;
|
ValueBasicInformation->Type = ValueCell->DataType;
|
||||||
ValueBasicInformation->NameLength = NameSize;
|
ValueBasicInformation->NameLength = NameSize;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) <
|
||||||
|
NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
||||||
{
|
{
|
||||||
CmiCopyPackedName(ValueBasicInformation->Name,
|
CmiCopyPackedName(ValueBasicInformation->Name,
|
||||||
ValueCell->Name,
|
ValueCell->Name,
|
||||||
ValueCell->NameSize);
|
NameSize / sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory(ValueBasicInformation->Name,
|
RtlCopyMemory(ValueBasicInformation->Name,
|
||||||
ValueCell->Name,
|
ValueCell->Name,
|
||||||
ValueCell->NameSize * sizeof(WCHAR));
|
NameSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyValuePartialInformation:
|
case KeyValuePartialInformation:
|
||||||
*ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
|
DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
+ (ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) +
|
||||||
|
DataSize;
|
||||||
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
@ -1195,19 +1322,28 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
KeyValueInformation;
|
KeyValueInformation;
|
||||||
ValuePartialInformation->TitleIndex = 0;
|
ValuePartialInformation->TitleIndex = 0;
|
||||||
ValuePartialInformation->Type = ValueCell->DataType;
|
ValuePartialInformation->Type = ValueCell->DataType;
|
||||||
ValuePartialInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
ValuePartialInformation->DataLength = DataSize;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) <
|
||||||
|
DataSize)
|
||||||
|
{
|
||||||
|
DataSize = Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
||||||
{
|
{
|
||||||
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
||||||
RtlCopyMemory(ValuePartialInformation->Data,
|
RtlCopyMemory(ValuePartialInformation->Data,
|
||||||
DataCell->Data,
|
DataCell->Data,
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory(ValuePartialInformation->Data,
|
RtlCopyMemory(ValuePartialInformation->Data,
|
||||||
&ValueCell->DataOffset,
|
&ValueCell->DataOffset,
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1218,9 +1354,12 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
{
|
{
|
||||||
NameSize *= sizeof(WCHAR);
|
NameSize *= sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
*ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
|
DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
NameSize + (ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
|
||||||
if (Length < *ResultLength)
|
*ResultLength = ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
|
||||||
|
Name[0]) + NameSize, sizeof(PVOID)) + DataSize;
|
||||||
|
|
||||||
|
if (Length < FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]))
|
||||||
{
|
{
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
@ -1231,18 +1370,6 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
ValueFullInformation->TitleIndex = 0;
|
ValueFullInformation->TitleIndex = 0;
|
||||||
ValueFullInformation->Type = ValueCell->DataType;
|
ValueFullInformation->Type = ValueCell->DataType;
|
||||||
ValueFullInformation->NameLength = NameSize;
|
ValueFullInformation->NameLength = NameSize;
|
||||||
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
|
||||||
{
|
|
||||||
CmiCopyPackedName(ValueFullInformation->Name,
|
|
||||||
ValueCell->Name,
|
|
||||||
ValueCell->NameSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RtlCopyMemory(ValueFullInformation->Name,
|
|
||||||
ValueCell->Name,
|
|
||||||
ValueCell->NameSize);
|
|
||||||
}
|
|
||||||
ValueFullInformation->DataOffset =
|
ValueFullInformation->DataOffset =
|
||||||
(ULONG_PTR)ValueFullInformation->Name -
|
(ULONG_PTR)ValueFullInformation->Name -
|
||||||
(ULONG_PTR)ValueFullInformation +
|
(ULONG_PTR)ValueFullInformation +
|
||||||
|
@ -1250,20 +1377,50 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
||||||
ValueFullInformation->DataOffset =
|
ValueFullInformation->DataOffset =
|
||||||
ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
|
ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
|
||||||
ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
|
||||||
|
|
||||||
|
if (Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) <
|
||||||
|
NameSize)
|
||||||
|
{
|
||||||
|
NameSize = Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
|
||||||
|
DataSize = 0;
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
else if (ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
|
||||||
|
Name[0]) - NameSize, sizeof(PVOID)) < DataSize)
|
||||||
|
{
|
||||||
|
DataSize = ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
|
||||||
|
Name[0]) - NameSize, sizeof(PVOID));
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
CHECKPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
|
||||||
|
{
|
||||||
|
CmiCopyPackedName(ValueFullInformation->Name,
|
||||||
|
ValueCell->Name,
|
||||||
|
NameSize / sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlCopyMemory(ValueFullInformation->Name,
|
||||||
|
ValueCell->Name,
|
||||||
|
NameSize);
|
||||||
|
}
|
||||||
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
|
||||||
{
|
{
|
||||||
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
|
||||||
RtlCopyMemory((PCHAR) ValueFullInformation
|
RtlCopyMemory((PCHAR) ValueFullInformation
|
||||||
+ ValueFullInformation->DataOffset,
|
+ ValueFullInformation->DataOffset,
|
||||||
DataCell->Data,
|
DataCell->Data,
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory((PCHAR) ValueFullInformation
|
RtlCopyMemory((PCHAR) ValueFullInformation
|
||||||
+ ValueFullInformation->DataOffset,
|
+ ValueFullInformation->DataOffset,
|
||||||
&ValueCell->DataOffset,
|
&ValueCell->DataOffset,
|
||||||
ValueCell->DataSize & REG_DATA_SIZE_MASK);
|
DataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue