windows-nt/Source/XPSP1/NT/base/screg/winreg/client/regqkey.c

513 lines
14 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Regqkey.c
Abstract:
This module contains the client side wrappers for the Win32 Registry
query key APIs. That is:
- RegQueryInfoKeyA
- RegQueryInfoKeyW
Author:
David J. Gilman (davegi) 18-Mar-1992
Notes:
See the notes in server\regqkey.c.
--*/
#include <rpc.h>
#include "regrpc.h"
#include "client.h"
LONG
RegQueryInfoKeyA (
HKEY hKey,
LPSTR lpClass,
LPDWORD lpcbClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime
)
/*++
Routine Description:
Win32 ANSI RPC wrapper for querying information about a previously
opened key.
--*/
{
PUNICODE_STRING Class;
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
NTSTATUS Status;
LONG Error;
DWORD cSubKeys;
DWORD cbMaxSubKeyLen;
DWORD cValues;
DWORD cbMaxValueNameLen;
DWORD cbMaxValueLen;
FILETIME ftLastWriteTime;
HKEY TempHandle = NULL;
DWORD cbMaxClassLen;
DWORD cbSecurityDescriptor;
PDWORD pCbMaxClassLen = NULL;
PDWORD pCbSecurityDescriptor = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
if( ARGUMENT_PRESENT( lpReserved ) ||
(ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass )))) {
return ERROR_INVALID_PARAMETER;
}
hKey = MapPredefinedHandle( hKey, &TempHandle );
if( hKey == NULL ) {
Error = ERROR_INVALID_HANDLE;
goto ExitCleanup;
}
//
// Make sure that the buffer size for lpClass is zero if lpClass is NULL
//
if( !ARGUMENT_PRESENT( lpClass ) && ARGUMENT_PRESENT( lpcbClass ) ) {
*lpcbClass = 0;
}
if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
pCbMaxClassLen = &cbMaxClassLen;
}
if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
pCbSecurityDescriptor = &cbSecurityDescriptor;
}
//
// If the count of bytes in the class is 0, pass a NULL pointer
// instead of what was supplied. This ensures that RPC won't
// attempt to copy data to a bogus pointer. Note that in this
// case we use the unicode string allocated on the stack, because
// we must not change the Buffer or MaximumLength fields of the
// static unicode string in the TEB.
//
if ( !ARGUMENT_PRESENT( lpClass ) || *lpcbClass == 0 ) {
Class = &UnicodeString;
Class->Length = 0;
Class->MaximumLength = 0;
Class->Buffer = NULL;
} else {
//
// Use the static Unicode string in the TEB as a temporary for the
// key's class.
//
Class = &NtCurrentTeb( )->StaticUnicodeString;
ASSERT( Class != NULL );
Class->Length = 0;
}
//
// Call the Base API passing it a pointer to a counted Unicode string
// for the class string.
//
if( IsLocalHandle( hKey )) {
Error = (LONG)LocalBaseRegQueryInfoKey(
hKey,
Class,
&cSubKeys,
&cbMaxSubKeyLen,
pCbMaxClassLen,
&cValues,
&cbMaxValueNameLen,
&cbMaxValueLen,
pCbSecurityDescriptor,
&ftLastWriteTime
);
} else {
//
// on RPC always send valid pointers!!!
//
pCbMaxClassLen = &cbMaxClassLen;
pCbSecurityDescriptor = &cbSecurityDescriptor;
Error = (LONG)BaseRegQueryInfoKey(
DereferenceRemoteHandle( hKey ),
Class,
&cSubKeys,
&cbMaxSubKeyLen,
pCbMaxClassLen,
&cValues,
&cbMaxValueNameLen,
&cbMaxValueLen,
pCbSecurityDescriptor,
&ftLastWriteTime
);
if (Error == ERROR_SUCCESS) {
DWORD dwVersion;
//
// Check for a downlevel Win95 server, which requires
// us to work around their BaseRegQueryInfoKey bugs.
// They do not account for Unicode correctly.
//
if (IsWin95Server(DereferenceRemoteHandle(hKey),dwVersion)) {
//
// This is a Win95 server.
// Double the maximum value name length and
// maximum value data length to account for
// the Unicode translation that Win95 forgot
// to account for.
//
cbMaxValueNameLen *= sizeof(WCHAR);
cbMaxValueLen *= sizeof(WCHAR);
}
}
}
//
// MaxSubKeyLen, MaxClassLen, and MaxValueNameLen should be in
// number of characters, without counting the NULL.
// Note that the server side will return the number of bytes,
// without counting the NUL
//
cbMaxSubKeyLen /= sizeof( WCHAR );
if( pCbMaxClassLen != NULL ) {
cbMaxClassLen /= sizeof( WCHAR );
ASSERT( *pCbMaxClassLen == cbMaxClassLen );
}
cbMaxValueNameLen /= sizeof( WCHAR );
//
// Subtract the NULL from the Length. This was added on
// the server side so that RPC would transmit it.
//
if ( Class->Length > 0 ) {
Class->Length -= sizeof( UNICODE_NULL );
}
//
// If all the information was succesfully queried from the key
// convert the class name to ANSI and update the class length value.
//
if( ( Error == ERROR_SUCCESS ) &&
ARGUMENT_PRESENT( lpClass ) && ( *lpcbClass != 0 ) ) {
if (*lpcbClass > (DWORD)0xFFFF) {
AnsiString.MaximumLength = ( USHORT ) 0xFFFF;
} else {
AnsiString.MaximumLength = ( USHORT ) *lpcbClass;
}
AnsiString.Buffer = lpClass;
Status = RtlUnicodeStringToAnsiString(
&AnsiString,
Class,
FALSE
);
ASSERTMSG( "Unicode->ANSI conversion of Class ",
NT_SUCCESS( Status ));
//
// Update the class length return parameter.
//
*lpcbClass = AnsiString.Length;
Error = RtlNtStatusToDosError( Status );
} else {
//
// Not all of the information was succesfully queried, or Class
// doesn't have to be converted from UNICODE to ANSI
//
if( ARGUMENT_PRESENT( lpcbClass ) ) {
if( Class->Length == 0 ) {
*lpcbClass = 0;
} else {
*lpcbClass = ( Class->Length >> 1 );
}
}
}
if( ARGUMENT_PRESENT( lpcSubKeys ) ) {
*lpcSubKeys = cSubKeys;
}
if( ARGUMENT_PRESENT( lpcbMaxSubKeyLen ) ) {
*lpcbMaxSubKeyLen = cbMaxSubKeyLen;
}
if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
*lpcbMaxClassLen = cbMaxClassLen;
ASSERT( *pCbMaxClassLen == cbMaxClassLen );
}
if( ARGUMENT_PRESENT( lpcValues ) ) {
*lpcValues = cValues;
}
if( ARGUMENT_PRESENT( lpcbMaxValueNameLen ) ) {
*lpcbMaxValueNameLen = cbMaxValueNameLen;
}
if( ARGUMENT_PRESENT( lpcbMaxValueLen ) ) {
*lpcbMaxValueLen = cbMaxValueLen;
}
if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
*lpcbSecurityDescriptor = cbSecurityDescriptor;
ASSERT( *pCbSecurityDescriptor == cbSecurityDescriptor );
}
if( ARGUMENT_PRESENT( lpftLastWriteTime ) ) {
*lpftLastWriteTime = ftLastWriteTime;
}
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}
LONG
RegQueryInfoKeyW (
HKEY hKey,
LPWSTR lpClass,
LPDWORD lpcbClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime
)
/*++
Routine Description:
Win32 Unicode RPC wrapper for querying information about a previously
opened key.
--*/
{
UNICODE_STRING Class;
LONG Error;
DWORD cbClass;
DWORD cSubKeys;
DWORD cbMaxSubKeyLen;
DWORD cValues;
DWORD cbMaxValueNameLen;
DWORD cbMaxValueLen;
FILETIME ftLastWriteTime;
HKEY TempHandle = NULL;
DWORD cbMaxClassLen;
DWORD cbSecurityDescriptor;
PDWORD pCbMaxClassLen = NULL;
PDWORD pCbSecurityDescriptor = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
if( ARGUMENT_PRESENT( lpReserved ) ||
(ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass )))) {
return ERROR_INVALID_PARAMETER;
}
hKey = MapPredefinedHandle( hKey, &TempHandle );
if( hKey == NULL ) {
Error = ERROR_INVALID_HANDLE;
goto ExitCleanup;
}
//
// Make sure that the buffer size for lpClass is zero if lpClass is NULL
//
if( !ARGUMENT_PRESENT( lpClass ) && ARGUMENT_PRESENT( lpcbClass ) ) {
*lpcbClass = 0;
}
if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
pCbMaxClassLen = &cbMaxClassLen;
}
if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
pCbSecurityDescriptor = &cbSecurityDescriptor;
}
//
// Use the supplied class Class buffer as the buffer in a counted
// Unicode Class.
//
Class.Length = 0;
if( ARGUMENT_PRESENT( lpcbClass ) && ( *lpcbClass != 0 ) ) {
Class.MaximumLength = ( USHORT )( *lpcbClass << 1 );
Class.Buffer = lpClass;
} else {
//
// If the count of bytes in the class is 0, pass a NULL pointer
// instead of what was supplied. This ensures that RPC won't
// attempt to copy data to a bogus pointer.
//
Class.MaximumLength = 0;
Class.Buffer = NULL;
}
//
// Call the Base API.
//
if( IsLocalHandle( hKey )) {
Error = (LONG)LocalBaseRegQueryInfoKey(
hKey,
&Class,
&cSubKeys,
&cbMaxSubKeyLen,
pCbMaxClassLen,
&cValues,
&cbMaxValueNameLen,
&cbMaxValueLen,
pCbSecurityDescriptor,
&ftLastWriteTime
);
} else {
//
// on RPC always send valid pointers!!!
//
pCbMaxClassLen = &cbMaxClassLen;
pCbSecurityDescriptor = &cbSecurityDescriptor;
Error = (LONG)BaseRegQueryInfoKey(
DereferenceRemoteHandle( hKey ),
&Class,
&cSubKeys,
&cbMaxSubKeyLen,
pCbMaxClassLen,
&cValues,
&cbMaxValueNameLen,
&cbMaxValueLen,
pCbSecurityDescriptor,
&ftLastWriteTime
);
if (Error == ERROR_SUCCESS) {
DWORD dwVersion;
//
// Check for a downlevel Win95 server, which requires
// us to work around their BaseRegQueryInfoKey bugs.
// They do not account for Unicode correctly.
//
if (IsWin95Server(DereferenceRemoteHandle(hKey),dwVersion)) {
//
// This is a Win95 server.
// Double the maximum value name length and
// maximum value data length to account for
// the Unicode translation that Win95 forgot
// to account for.
//
cbMaxValueNameLen *= sizeof(WCHAR);
cbMaxValueLen *= sizeof(WCHAR);
}
}
}
//
// MaxSubKeyLen, MaxClassLen, and MaxValueNameLen should be in
// number of characters, without counting the NULL.
// Note that the server side will return the number of bytes,
// without counting the NUL
//
cbMaxSubKeyLen /= sizeof( WCHAR );
if( pCbMaxClassLen != NULL ) {
cbMaxClassLen /= sizeof( WCHAR );
ASSERT( *pCbMaxClassLen == cbMaxClassLen );
}
cbMaxValueNameLen /= sizeof( WCHAR );
if( ARGUMENT_PRESENT( lpcbClass ) ) {
if( Class.Length == 0 ) {
*lpcbClass = 0;
} else {
*lpcbClass = ( Class.Length >> 1 ) - 1;
}
}
if( ARGUMENT_PRESENT( lpcSubKeys ) ) {
*lpcSubKeys = cSubKeys;
}
if( ARGUMENT_PRESENT( lpcbMaxSubKeyLen ) ) {
*lpcbMaxSubKeyLen = cbMaxSubKeyLen;
}
if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
*lpcbMaxClassLen = cbMaxClassLen;
ASSERT( *pCbMaxClassLen == cbMaxClassLen );
}
if( ARGUMENT_PRESENT( lpcValues ) ) {
*lpcValues = cValues;
}
if( ARGUMENT_PRESENT( lpcbMaxValueNameLen ) ) {
*lpcbMaxValueNameLen = cbMaxValueNameLen;
}
if( ARGUMENT_PRESENT( lpcbMaxValueLen ) ) {
*lpcbMaxValueLen = cbMaxValueLen;
}
if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
*lpcbSecurityDescriptor = cbSecurityDescriptor;
ASSERT( *pCbSecurityDescriptor == cbSecurityDescriptor );
}
if( ARGUMENT_PRESENT( lpftLastWriteTime ) ) {
*lpftLastWriteTime = ftLastWriteTime;
}
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}