// // 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 }