209 lines
5.3 KiB
C
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);
|
|
|
|
}
|