windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/common/regw32d/regeval.c
2020-09-26 16:20:57 +08:00

209 lines
5.3 KiB
C

//
// REGEVAL.C
//
// Copyright (C) Microsoft Corporation, 1995
//
// Implementation of RegEnumValue and supporting functions.
//
#include "pch.h"
//
// RgLookupValueByIndex
// (BIGKEY aware)
//
// Searches for the value with the specified index and returns a pointer to its
// VALUE_RECORD.
//
// This locks the datablock associated with the KEY_RECORD and VALUE_RECORD.
// This is always hKey->BigKeyLockedBlockIndex
// It is the callers responsibility to unlock the datablock.
//
int
INTERNAL
RgLookupValueByIndex(
HKEY hKey,
UINT Index,
LPVALUE_RECORD FAR* lplpValueRecord
)
{
int ErrorCode;
HKEY hKeyExtent;
UINT IndexKey;
LPSTR KeyName;
DWORD cbKeyName;
UINT ValueCount;
ErrorCode = RgLookupValueByIndexStd(hKey, Index, lplpValueRecord, &ValueCount);
hKey-> BigKeyLockedBlockIndex = hKey-> BlockIndex;
if (ErrorCode == ERROR_NO_MORE_ITEMS && (hKey->Flags & KEYF_BIGKEYROOT)) {
if (IsNullPtr(KeyName = RgSmAllocMemory(MAXIMUM_SUB_KEY_LENGTH)))
return ERROR_OUTOFMEMORY;
IndexKey = 0;
while (ErrorCode == ERROR_NO_MORE_ITEMS && Index >= ValueCount)
{
Index -= ValueCount;
cbKeyName = MAXIMUM_SUB_KEY_LENGTH;
if (RgLookupKeyByIndex(hKey, IndexKey++, KeyName, &cbKeyName, LK_BIGKEYEXT) != ERROR_SUCCESS) {
ErrorCode = ERROR_NO_MORE_ITEMS;
goto lFreeKeyName;
}
if (RgLookupKey(hKey, KeyName, &hKeyExtent, LK_OPEN | LK_BIGKEYEXT) != ERROR_SUCCESS) {
ErrorCode = ERROR_NO_MORE_ITEMS;
goto lFreeKeyName;
}
hKey-> BigKeyLockedBlockIndex = hKeyExtent-> BlockIndex;
ErrorCode = RgLookupValueByIndexStd(hKeyExtent, Index,
lplpValueRecord, &ValueCount);
RgDestroyKeyHandle(hKeyExtent);
}
lFreeKeyName:
RgSmFreeMemory(KeyName);
}
return ErrorCode;
}
//
// RgLookupValueByIndexStd
//
// Searches for the value with the specified index and returns a pointer to its
// VALUE_RECORD.
//
// This locks the datablock associated with the VALUE_RECORD.
// This is always hKey->BlockIndex
// It is the callers responsibility to unlock the datablock.
//
int
INTERNAL
RgLookupValueByIndexStd(
HKEY hKey,
UINT Index,
LPVALUE_RECORD FAR* lplpValueRecord,
UINT FAR* lpValueCount
)
{
int ErrorCode;
LPKEY_RECORD lpKeyRecord;
LPVALUE_RECORD lpValueRecord;
*lpValueCount = 0;
// Handle Win95 registries that don't have a key record for the root key.
if (IsNullBlockIndex(hKey-> BlockIndex))
return ERROR_NO_MORE_ITEMS;
if ((ErrorCode = RgLockKeyRecord(hKey-> lpFileInfo, hKey-> BlockIndex,
hKey-> KeyRecordIndex, &lpKeyRecord)) == ERROR_SUCCESS) {
*lpValueCount = lpKeyRecord-> ValueCount;
if (Index >= lpKeyRecord-> ValueCount) {
RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BlockIndex, FALSE);
ErrorCode = ERROR_NO_MORE_ITEMS;
}
else {
lpValueRecord = (LPVALUE_RECORD) ((LPBYTE) &lpKeyRecord-> Name +
lpKeyRecord-> NameLength + lpKeyRecord-> ClassLength);
// Should probably do more sanity checking on lpValueRecord
while (Index--) {
lpValueRecord = (LPVALUE_RECORD) ((LPBYTE) &lpValueRecord->
Name + lpValueRecord-> NameLength + lpValueRecord->
DataLength);
}
*lplpValueRecord = lpValueRecord;
ErrorCode = ERROR_SUCCESS;
}
}
return ErrorCode;
}
//
// VMMRegEnumValue
//
// See Win32 documentation for a description of the behavior.
//
LONG
REGAPI
VMMRegEnumValue(
HKEY hKey,
DWORD Index,
LPSTR lpValueName,
LPDWORD lpcbValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
)
{
int ErrorCode;
LPVALUE_RECORD lpValueRecord;
if (IsBadHugeWritePtr(lpcbValueName, sizeof(DWORD)) ||
IsBadHugeWritePtr(lpValueName, *lpcbValueName) ||
(IsBadHugeOptionalWritePtr(lpType, sizeof(DWORD))))
return ERROR_INVALID_PARAMETER;
if (IsBadHugeOptionalWritePtr(lpType, sizeof(DWORD)))
return ERROR_INVALID_PARAMETER;
if (IsNullPtr(lpcbData)) {
if (!IsNullPtr(lpData))
return ERROR_INVALID_PARAMETER;
}
else {
// Win95 compatibility: don't validate lpData is of size *lpcbData.
// Instead of validating the entire buffer, we'll validate just the
// required buffer length in RgCopyFromValueRecord.
if (IsBadHugeWritePtr(lpcbData, sizeof(DWORD)))
return ERROR_INVALID_PARAMETER;
}
if (IsEnumIndexTooBig(Index))
return ERROR_NO_MORE_ITEMS;
if (!RgLockRegistry())
return ERROR_LOCK_FAILED;
if ((ErrorCode = RgValidateAndConvertKeyHandle(&hKey)) == ERROR_SUCCESS) {
if ((ErrorCode = RgLookupValueByIndex(hKey, (UINT) Index,
&lpValueRecord)) == ERROR_SUCCESS) {
ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, lpValueName,
lpcbValueName, lpType, lpData, lpcbData);
RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BigKeyLockedBlockIndex, FALSE);
}
}
RgUnlockRegistry();
return ErrorCode;
UNREFERENCED_PARAMETER(lpReserved);
}