|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
Regsval.c
Abstract:
This module contains the server side implementation for the Win32 Registry set value API. That is:
- BaseRegSetValue Author:
David J. Gilman (davegi) 27-Nov-1991
Notes:
See the Notes in Regkey.c.
--*/
#include <rpc.h>
#include "regrpc.h"
#include "localreg.h"
#ifdef LOCAL
#include "tsappcmp.h"
#include "regclass.h"
#endif
error_status_t BaseRegSetValue( HKEY hKey, PUNICODE_STRING lpValueName, DWORD dwType, LPBYTE lpData, DWORD cbData )
/*++
Routine Description:
Set the type and value of an open key. Changes are not committed until the key is flushed. By "committed" we mean written to disk. Changes will be seen by subsequent queries as soon as this call returns.
Arguments:
hKey - Supplies a handle to the open key. Any of the predefined reserved handles or a previously opened key handle may be used for hKey.
lpValueName - Supplies the name of the value to set. If the ValueName is not present, it is added to the key.
dwType - Supplies the type of information to be stored: REG_SZ, etc.
lpData - supplies a pointer to a buffer containing the data to set for the value entry.
cbData - Supplies the length (in bytes) of the information to be stored.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
Notes:
A set may fail due to memory limits - any config entry must fit in main memory. If successful, RegSetValue will set the type, contents, and length of the information stored at the specified key. KEY_SET_VALUE access is required.
--*/
{ NTSTATUS Status; HKEY hkSet;
#ifdef LOCAL
PVOID PreSetData = NULL;
HKEY hkUserClasses; HKEY hkMachineClasses;
hkUserClasses = NULL; hkMachineClasses = NULL;
#endif
if( (lpValueName == NULL) || (lpValueName->Length & 1)) { //
// malicious client/RPC attack
//
return ERROR_INVALID_PARAMETER; } hkSet = hKey;
//
// Subtract the NULL from the Length. This was added on the
// client side so that RPC would transmit it.
//
if ( lpValueName->Length > 0 ) { lpValueName->Length -= sizeof( UNICODE_NULL ); } if ((hKey == HKEY_PERFORMANCE_DATA) || (hKey==HKEY_PERFORMANCE_TEXT) || (hKey==HKEY_PERFORMANCE_NLSTEXT)) { #ifdef LOCAL
return(PerfRegSetValue(hKey, lpValueName->Buffer, 0, dwType, lpData, cbData)); #else
return ERROR_ACCESS_DENIED; #endif
}
#ifdef LOCAL
if (gpfnTermsrvSetValueKey && gpfnTermsrvGetPreSetValue ) {
//
// Find any pre-set values
//
Status = gpfnTermsrvGetPreSetValue( hKey, lpValueName, dwType, &PreSetData ); //
// Use the pre-set values if they exists
//
if ( NT_SUCCESS(Status) ) { lpData = (( PKEY_VALUE_PARTIAL_INFORMATION ) PreSetData )->Data; cbData = (( PKEY_VALUE_PARTIAL_INFORMATION ) PreSetData )->DataLength; } else { PreSetData = NULL; } //
// Save the Master Copy
//
gpfnTermsrvSetValueKey(hKey, lpValueName, 0, dwType, lpData, cbData); }
if ( PreSetData ) {
//
// Set the value and free any data
//
Status = NtSetValueKey( hKey, lpValueName, 0, dwType, lpData, cbData );
RtlFreeHeap( RtlProcessHeap( ), 0, PreSetData );
return (error_status_t)RtlNtStatusToDosError( Status ); } else //
// No pre-set values, just do original code
//
#endif
//
// Call the Nt API to set the value, map the NTSTATUS code to a
// Win32 Registry error code and return.
//
#ifdef LOCAL
if (REG_CLASS_IS_SPECIAL_KEY(hKey)) {
Status = BaseRegGetUserAndMachineClass( NULL, hkSet, MAXIMUM_ALLOWED, &hkMachineClasses, &hkUserClasses);
if (!NT_SUCCESS(Status)) { return (error_status_t)RtlNtStatusToDosError(Status); } }
if (hkUserClasses && hkMachineClasses) { hkSet = hkUserClasses; } #endif
Status = NtSetValueKey( hkSet, lpValueName, 0, dwType, lpData, cbData );
#ifdef LOCAL
if (hkUserClasses && hkMachineClasses) { if (hkUserClasses != hKey) { NtClose(hkUserClasses); } else { NtClose(hkMachineClasses); } }
//if it is a HKLM\Software\Classes subkey and we get ACCDENIED try to create the
//key in HKCU\Software\Classes and set value there
if( (gdwRegistryExtensionFlags & TERMSRV_ENABLE_ACCESS_FLAG_MODIFICATION ) && STATUS_ACCESS_DENIED == Status && hkSet == hkMachineClasses && REG_CLASS_IS_SPECIAL_KEY(hKey) ) { Status = CreateMultipartUserClassKey( hKey, &hkSet );
if(!NT_SUCCESS(Status)) { return ERROR_ACCESS_DENIED; }
Status = NtSetValueKey( hkSet, lpValueName, 0, dwType, lpData, cbData ); NtClose(hkSet);
if(!NT_SUCCESS(Status)) { return ERROR_ACCESS_DENIED; } }
#endif // LOCAL
return (error_status_t) RtlNtStatusToDosError(Status);
}
|