|
|
/*++
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; }
|