windows-nt/Source/XPSP1/NT/base/screg/winreg/client/regekey.c
2020-09-26 16:20:57 +08:00

481 lines
9.7 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Regekey.c
Abstract:
This module contains the client side wrappers for the Win32 Registry
enumerate key APIs. That is:
- RegEnumKeyA
- RegEnumKeyW
- RegEnumKeyExA
- RegEnumKeyExW
Author:
David J. Gilman (davegi) 18-Mar-1992
Notes:
See the notes in server\regekey.c.
--*/
#include <rpc.h>
#include "regrpc.h"
#include "client.h"
LONG
APIENTRY
RegEnumKeyA (
HKEY hKey,
DWORD dwIndex,
LPSTR lpName,
DWORD cbName
)
/*++
Routine Description:
Win 3.1 ANSI RPC wrapper for enumerating keys.
--*/
{
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
//
if( hKey == HKEY_PERFORMANCE_DATA ) {
return ERROR_INVALID_HANDLE;
}
return RegEnumKeyExA (
hKey,
dwIndex,
lpName,
&cbName,
NULL,
NULL,
NULL,
NULL
);
}
LONG
APIENTRY
RegEnumKeyW (
HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
DWORD cbName
)
/*++
Routine Description:
Win 3.1 Unicode RPC wrapper for enumerating keys.
--*/
{
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
//
if( hKey == HKEY_PERFORMANCE_DATA ) {
return ERROR_INVALID_HANDLE;
}
return RegEnumKeyExW (
hKey,
dwIndex,
lpName,
&cbName,
NULL,
NULL,
NULL,
NULL
);
}
LONG
APIENTRY
RegEnumKeyExA (
HKEY hKey,
DWORD dwIndex,
LPSTR lpName,
LPDWORD lpcbName,
LPDWORD lpReserved,
LPSTR lpClass,
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime
)
/*++
Routine Description:
Win32 ANSI API for enumerating keys.
--*/
{
UNICODE_STRING Name;
UNICODE_STRING Class;
WCHAR ClassBuffer[ MAX_PATH ];
PUNICODE_STRING ClassPointer;
ANSI_STRING AnsiString;
NTSTATUS Status;
LONG Error = ERROR_SUCCESS;
HKEY TempHandle = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Validate dependency between lpClass and lpcbClass parameters.
//
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;
}
//
// Allocate temporary buffer for the Name
//
Name.Length = 0;
Name.MaximumLength = (USHORT)((*lpcbName + 1) * sizeof( WCHAR ));
Name.Buffer = RtlAllocateHeap( RtlProcessHeap(), 0, Name.MaximumLength );
if( Name.Buffer == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto ExitCleanup;
}
//
// If the class string is to be returned, initialize a UNICODE_STRING
//
ClassPointer = &Class;
ClassPointer->Length = 0;
if( ARGUMENT_PRESENT( lpClass )) {
ClassPointer->MaximumLength = MAX_PATH;
ClassPointer->Buffer = ( PVOID ) ClassBuffer;
} else {
ClassPointer->MaximumLength = 0;
ClassPointer->Buffer = NULL;
}
//
// Call the Base API passing it a pointer to the counted Unicode
// strings for the name and class.
//
if( IsLocalHandle( hKey )) {
Error = (LONG)LocalBaseRegEnumKey (
hKey,
dwIndex,
&Name,
ClassPointer,
lpftLastWriteTime
);
} else {
Error = (LONG)BaseRegEnumKey (
DereferenceRemoteHandle( hKey ),
dwIndex,
&Name,
ClassPointer,
lpftLastWriteTime
);
}
//
// If the information was not succesfully queried return the error.
//
if( Error != ERROR_SUCCESS ) {
// free allocated buffer
RtlFreeHeap( RtlProcessHeap(), 0, Name.Buffer );
goto ExitCleanup;
}
//
// Subtact the NULL from Length, which was added by the server
// so that RPC would transmit it.
//
Name.Length -= sizeof( UNICODE_NULL );
if ( ClassPointer->Length > 0 ) {
ClassPointer->Length -= sizeof( UNICODE_NULL );
}
//
// Convert the name to ANSI.
//
// If somebody passed in a really big buffer, pretend it's
// not quite so big so that it doesn't get truncated to zero.
//
if (*lpcbName > 0xFFFF) {
AnsiString.MaximumLength = ( USHORT ) 0xFFFF;
} else {
AnsiString.MaximumLength = ( USHORT ) *lpcbName;
}
AnsiString.Buffer = lpName;
Status = RtlUnicodeStringToAnsiString(
&AnsiString,
&Name,
FALSE
);
// free allocated buffer
RtlFreeHeap( RtlProcessHeap(), 0, Name.Buffer );
//
// If the name conversion failed, map and return the error.
//
if( ! NT_SUCCESS( Status )) {
Error = RtlNtStatusToDosError( Status );
goto ExitCleanup;
}
//
// Update the name length return parameter.
//
*lpcbName = AnsiString.Length;
//
// If requested, convert the class to ANSI.
//
if( ARGUMENT_PRESENT( lpClass )) {
AnsiString.MaximumLength = ( USHORT ) *lpcbClass;
AnsiString.Buffer = lpClass;
Status = RtlUnicodeStringToAnsiString(
&AnsiString,
ClassPointer,
FALSE
);
//
// If the class conversion failed, map and return the error.
//
if( ! NT_SUCCESS( Status )) {
Error = RtlNtStatusToDosError( Status );
goto ExitCleanup;
}
//
// If requested, return the class length parameter w/o the NUL.
//
if( ARGUMENT_PRESENT( lpcbClass )) {
*lpcbClass = AnsiString.Length;
}
//
// It is possible to ask for the size of the class w/o asking for the
// class itself.
//
} else if( ARGUMENT_PRESENT( lpcbClass )) {
*lpcbClass = ( ClassPointer->Length >> 1 );
}
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}
LONG
APIENTRY
RegEnumKeyExW (
HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
LPDWORD lpcbName,
LPDWORD lpReserved,
LPWSTR lpClass,
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime
)
/*++
Routine Description:
Win32 Unicode RPC wrapper for enumerating keys.
--*/
{
LONG Error;
UNICODE_STRING Name;
UNICODE_STRING Class;
PUNICODE_STRING ClassPointer;
HKEY TempHandle = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Validate dependency between lpClass and lpcbClass parameters.
//
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;
}
//
// Use the supplied name string buffer as the buffer in a counted
// Unicode string.
//
Name.Length = 0;
if ((*lpcbName << 1) > 0xFFFE) {
Name.MaximumLength = ( USHORT ) 0xFFFE;
} else {
Name.MaximumLength = ( USHORT )( *lpcbName << 1 );
}
Name.Buffer = lpName;
//
// If supplied use the supplied name string buffer as the buffer in a
// counted Unicode string.
//
ClassPointer = &Class;
if( ARGUMENT_PRESENT( lpClass )) {
Class.Length = 0;
Class.MaximumLength = ( USHORT )( *lpcbClass << 1 );
Class.Buffer = lpClass;
} else {
Class.Length = 0;
Class.MaximumLength = 0;
Class.Buffer = NULL;
}
//
// Call the Base API passing it a pointer to the counted Unicode
// strings for the name and class and return the results.
//
if( IsLocalHandle( hKey )) {
Error = (LONG)LocalBaseRegEnumKey (
hKey,
dwIndex,
&Name,
ClassPointer,
lpftLastWriteTime
);
} else {
Error = (LONG)BaseRegEnumKey (
DereferenceRemoteHandle( hKey ),
dwIndex,
&Name,
ClassPointer,
lpftLastWriteTime
);
}
//
// Subtact the NULL from Length, which was added by the server
// so that RPC would transmit it.
//
if ( Name.Length > 0 ) {
Name.Length -= sizeof( UNICODE_NULL );
}
if ( ClassPointer->Length > 0 ) {
ClassPointer->Length -= sizeof( UNICODE_NULL );
}
//
// Return the name length parameter w/o the NUL.
//
if( Error == ERROR_SUCCESS ) {
*lpcbName = ( Name.Length >> 1 );
}
//
// If requested, return the class length parameter w/o the NUL.
//
if( ARGUMENT_PRESENT( lpcbClass )) {
*lpcbClass = ( Class.Length >> 1 );
}
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}