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

176 lines
4.4 KiB
C

//
// REGQKEY.C
//
// Copyright (C) Microsoft Corporation, 1995
//
// Implementation of RegQueryInfoKey.
//
#include "pch.h"
//
// VMMRegQueryInfoKey
//
// See Win32 documentation of RegQueryInfoKey. When VXD is defined, this
// function does not take all of the parameters that we end up ignoring anyway
// (class, security, timestamp parameters).
//
#ifdef VXD
LONG
REGAPI
VMMRegQueryInfoKey(
HKEY hKey,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueName,
LPDWORD lpcbMaxValueData
)
#else
LONG
REGAPI
VMMRegQueryInfoKey(
HKEY hKey,
LPSTR lpClass,
LPDWORD lpcbClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueName,
LPDWORD lpcbMaxValueData,
LPVOID lpcbSecurityDescriptor,
LPVOID lpftLastWriteTime
)
#endif
{
int ErrorCode;
LPVALUE_RECORD lpValueRecord;
UINT cItems;
DWORD cbValueData;
DWORD cbMaxValueData;
DWORD cbStringLen;
DWORD cbMaxStringLen;
if (IsBadHugeOptionalWritePtr(lpcSubKeys, sizeof(DWORD)) ||
IsBadHugeOptionalWritePtr(lpcbMaxSubKeyLen, sizeof(DWORD)) ||
IsBadHugeOptionalWritePtr(lpcValues, sizeof(DWORD)) ||
IsBadHugeOptionalWritePtr(lpcbMaxValueName, sizeof(DWORD)) ||
IsBadHugeOptionalWritePtr(lpcbMaxValueData, sizeof(DWORD)))
return ERROR_INVALID_PARAMETER;
if (!RgLockRegistry())
return ERROR_LOCK_FAILED;
if ((ErrorCode = RgValidateAndConvertKeyHandle(&hKey)) != ERROR_SUCCESS)
goto ReturnErrorCode;
//
// Compute cValues, cbMaxValueName, and cbMaxValueData.
//
if (!IsNullPtr(lpcValues) || !IsNullPtr(lpcbMaxValueName) ||
!IsNullPtr(lpcbMaxValueData)) {
cItems = 0;
cbMaxStringLen = 0;
cbMaxValueData = 0;
while ((ErrorCode = RgLookupValueByIndex(hKey, cItems,
&lpValueRecord)) == ERROR_SUCCESS) {
cItems++;
if (lpValueRecord-> NameLength > cbMaxStringLen)
cbMaxStringLen = lpValueRecord-> NameLength;
// RgCopyFromValueRecord will handle static and dynamic keys...
ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, NULL, NULL,
NULL, NULL, &cbValueData);
RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BigKeyLockedBlockIndex, FALSE);
if (ErrorCode != ERROR_SUCCESS)
goto ReturnErrorCode;
if (cbValueData > cbMaxValueData)
cbMaxValueData = cbValueData;
}
if (ErrorCode == ERROR_NO_MORE_ITEMS) {
if (!IsNullPtr(lpcValues))
*lpcValues = cItems;
if (!IsNullPtr(lpcbMaxValueName))
*lpcbMaxValueName = cbMaxStringLen;
if (!IsNullPtr(lpcbMaxValueData))
*lpcbMaxValueData = cbMaxValueData;
ErrorCode = ERROR_SUCCESS;
}
}
//
// Compute cSubKeys and cbMaxSubKeyLen. Somewhat painful because we must
// touch each child keynode and datablock.
//
if (!IsNullPtr(lpcSubKeys) || !IsNullPtr(lpcbMaxSubKeyLen)) {
cItems = 0;
cbMaxStringLen = 0;
cbStringLen = 0;
while (TRUE) {
ErrorCode = RgLookupKeyByIndex(hKey, cItems, NULL,
&cbStringLen, 0);
if ((ErrorCode != ERROR_SUCCESS) && (ErrorCode != ERROR_MORE_DATA))
break;
cItems++;
// Win95 compatibility: the old code included the null terminator, even
// though the documentation for RegQueryInfoKey states that it doesn't.
if (cbStringLen && (cbStringLen + 1 > cbMaxStringLen))
cbMaxStringLen = cbStringLen + 1;
}
if (ErrorCode == ERROR_NO_MORE_ITEMS) {
if (!IsNullPtr(lpcSubKeys))
*lpcSubKeys = cItems;
if (!IsNullPtr(lpcbMaxSubKeyLen))
*lpcbMaxSubKeyLen = cbMaxStringLen;
ErrorCode = ERROR_SUCCESS;
}
}
ReturnErrorCode:
RgUnlockRegistry();
return ErrorCode;
#ifndef VXD
UNREFERENCED_PARAMETER(lpClass);
UNREFERENCED_PARAMETER(lpcbClass);
UNREFERENCED_PARAMETER(lpReserved);
UNREFERENCED_PARAMETER(lpcbMaxClassLen);
UNREFERENCED_PARAMETER(lpcbSecurityDescriptor);
UNREFERENCED_PARAMETER(lpftLastWriteTime);
#endif
}