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

653 lines
15 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:
Regsval.c
Abstract:
This module contains the client side wrappers for the Win32 Registry
set value APIs. That is:
- RegSetValueA
- RegSetValueW
- RegSetValueExA
- RegSetValueExW
Author:
David J. Gilman (davegi) 18-Mar-1992
Notes:
See the notes in server\regsval.c.
--*/
#include <rpc.h>
#include "regrpc.h"
#include "client.h"
#include <string.h>
#include <wow64reg.h>
LONG
RegSetValueA (
HKEY hKey,
LPCSTR lpSubKey,
DWORD dwType,
LPCSTR lpData,
DWORD cbData
)
/*++
Routine Description:
Win 3.1 ANSI RPC wrapper for setting a value.
--*/
{
HKEY ChildKey;
LONG Error;
HKEY TempHandle = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
//
if( hKey == HKEY_PERFORMANCE_DATA ) {
return ERROR_INVALID_HANDLE;
}
//
// Check the value type for compatability w/Win 3.1
//
if( dwType != REG_SZ ) {
return ERROR_INVALID_PARAMETER;
}
hKey = MapPredefinedHandle( hKey, &TempHandle );
if( hKey == NULL ) {
Error = ERROR_INVALID_HANDLE;
goto ExitCleanup;
}
//
// Win3.1ism - Win 3.1 ignores the cbData parameter so it is computed
// here instead as the length of the string plus the NUL character.
//
cbData = strlen( lpData ) + 1;
//
// If the sub-key is NULL or points to an empty string then the value is
// set in this key (i.e. hKey) otherwise the sub-key needs to be
// opened/created.
//
if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
ChildKey = hKey;
} else {
//
// The sub-key was supplied so attempt to open/create it.
//
Error = RegCreateKeyExA(
hKey,
lpSubKey,
0,
WIN31_CLASS,
0,
KEY_SET_VALUE,
NULL,
&ChildKey,
NULL
);
if( Error != ERROR_SUCCESS ) {
goto ExitCleanup;
}
}
//
// ChildKey contains an HKEY which may be the one supplied (hKey) or
// returned from RegCreateKeyA. Set the value using the special value
// name NULL.
//
Error = RegSetValueExA(
ChildKey,
NULL,
0,
dwType,
lpData,
cbData
);
//
// If the sub key was opened, close it.
//
if( ChildKey != hKey ) {
Error = RegCloseKey( ChildKey );
ASSERT( Error == ERROR_SUCCESS );
}
//
// Return the results of setting the value.
//
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}
LONG
RegSetValueW (
HKEY hKey,
LPCWSTR lpSubKey,
DWORD dwType,
LPCWSTR lpData,
DWORD cbData
)
/*++
Routine Description:
Win 3.1 Unicode RPC wrapper for setting a value.
--*/
{
HKEY ChildKey;
LONG Error;
HKEY TempHandle = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
//
if( hKey == HKEY_PERFORMANCE_DATA ) {
return ERROR_INVALID_HANDLE;
}
//
// Check the value type for compatability w/Win 3.1
//
if( dwType != REG_SZ ) {
return ERROR_INVALID_PARAMETER;
}
hKey = MapPredefinedHandle( hKey, &TempHandle);
if( hKey == NULL ) {
Error = ERROR_INVALID_HANDLE;
goto ExitCleanup;
}
//
// Win3.1ism - Win 3.1 ignores the cbData parameter so it is computed
// here instead as the length of the string plus the UNICODE_NUL
// character.
//
cbData = wcslen( lpData ) * sizeof( WCHAR ) + sizeof( UNICODE_NULL );;
//
// If the sub-key is NULL or points to an empty string then the value is
// set in this key (i.e. hKey) otherwise the sub-key needs to be
// opened/created.
//
if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
ChildKey = hKey;
} else {
//
// The sub-key was supplied attempt to open/create it.
//
Error = RegCreateKeyExW(
hKey,
lpSubKey,
0,
WIN31_CLASS,
0,
KEY_SET_VALUE,
NULL,
&ChildKey,
NULL
);
if( Error != ERROR_SUCCESS ) {
goto ExitCleanup;
}
}
//
// ChildKey contains an HKEY which may be the one supplied (hKey) or
// returned from RegCreateKeyW. Set the value using the special value
// name NULL.
//
Error = RegSetValueExW(
ChildKey,
NULL,
0,
dwType,
( LPBYTE ) lpData,
cbData
);
//
// If the sub key was opened/created, close it.
//
if( ChildKey != hKey ) {
RegCloseKey( ChildKey );
}
//
// Return the results of querying the value.
//
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}
LONG
APIENTRY
RegSetValueExA (
HKEY hKey,
LPCSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE* lpData,
DWORD cbData
)
/*++
Routine Description:
Win32 ANSI RPC wrapper for setting a value.
RegSetValueExA converts the lpValueName argument to a counted Unicode
string and then calls BaseRegSetValue.
--*/
{
PUNICODE_STRING ValueName;
UNICODE_STRING TempValueName;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
LPBYTE ValueData;
PSTR AnsiValueBuffer;
ULONG AnsiValueLength;
PWSTR UnicodeValueBuffer;
ULONG UnicodeValueLength;
ULONG Index;
LONG Error;
HKEY TempHandle = NULL;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
//
if( hKey == HKEY_PERFORMANCE_DATA ) {
return ERROR_INVALID_HANDLE;
}
//
// Ensure Reserved is zero to avoid future compatability problems.
//
if( Reserved != 0 ) {
return ERROR_INVALID_PARAMETER;
}
hKey = MapPredefinedHandle( hKey, &TempHandle );
if( hKey == NULL ) {
Error = ERROR_INVALID_HANDLE;
goto ExitCleanup;
}
//
// Convert the value name to a counted Unicode string
//
if ( lpValueName ) {
//
// Convert the SubKey name to a counted Unicode
//
if( !RtlCreateUnicodeStringFromAsciiz(&TempValueName,lpValueName) ) {
Status = STATUS_NO_MEMORY;
Error = RtlNtStatusToDosError( Status );
goto ExitCleanup;
}
ValueName = &TempValueName;
//
// Add the NULL to the Length, so that RPC will transmit it
//
ValueName->Length += sizeof( UNICODE_NULL );
if( ValueName->Length == 0 ) {
//
// overflow in RtlCreateUnicodeStringFromAsciiz
//
Error = ERROR_INVALID_PARAMETER;
goto ExitCleanup;
}
} else {
//
// No name was passed. Use our internal UNICODE string
// and set its fields to NULL. We don't use the static
// unicode string in the TEB in this case because we
// can't mess with its Buffer and MaximumLength fields.
//
ValueName = &UnicodeString;
ValueName->Length = 0;
ValueName->MaximumLength = 0;
ValueName->Buffer = NULL;
}
//
// If type is one of the null terminated string types, then do the ANSI to
// UNICODE translation into an allocated buffer.
//
ValueData = ( LPBYTE )lpData;
if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ) {
//
// Special hack to help out all the people who
// believe the length of a NULL terminated string is
// strlen(foo) instead of strlen(foo) + 1.
//
if ((cbData > 0) &&
(lpData[cbData-1] != 0)) {
//
// Do this under an exception handler in case the last
// little bit crosses a page boundary.
//
try {
if (lpData[cbData] == 0) {
cbData += 1; // increase string length to account for NULL terminator
}
} except (EXCEPTION_EXECUTE_HANDLER) {
; // guess they really really did not want a NULL terminator
}
}
AnsiValueBuffer = ValueData;
AnsiValueLength = cbData;
UnicodeValueLength = cbData * sizeof( WCHAR );
UnicodeValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
UnicodeValueLength
);
if (UnicodeValueBuffer == NULL) {
Error = ERROR_NOT_ENOUGH_MEMORY;
} else {
Status = RtlMultiByteToUnicodeN( UnicodeValueBuffer,
UnicodeValueLength,
&Index,
AnsiValueBuffer,
AnsiValueLength
);
if (!NT_SUCCESS( Status )) {
Error = RtlNtStatusToDosError( Status );
} else {
ValueData = (LPBYTE)UnicodeValueBuffer;
cbData = Index;
Error = ERROR_SUCCESS;
}
}
} else {
Error = ERROR_SUCCESS;
}
if ( Error == ERROR_SUCCESS ) {
//
// Call the Base API, passing it the supplied parameters and the
// counted Unicode strings.
//
if( IsLocalHandle( hKey )) {
Error = (LONG)LocalBaseRegSetValue (
hKey,
ValueName,
dwType,
ValueData,
cbData
);
#if defined(_WIN64)
if ( Error == 0)
Wow64RegSetKeyDirty (hKey);
#endif
} else {
Error = (LONG)BaseRegSetValue (
DereferenceRemoteHandle( hKey ),
ValueName,
dwType,
ValueData,
cbData
);
}
}
if( ValueData != lpData ) {
RtlFreeHeap( RtlProcessHeap(), 0, UnicodeValueBuffer );
}
if ( lpValueName ) {
// free the allocated unicode string
RtlFreeUnicodeString( &TempValueName );
}
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}
LONG
APIENTRY
RegSetValueExW (
HKEY hKey,
LPCWSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE* lpData,
DWORD cbData
)
/*++
Routine Description:
Win32 Unicode RPC wrapper for setting a value.
RegSetValueExW converts the lpValueName argument to a counted Unicode
string and then calls BaseRegSetValue.
--*/
{
UNICODE_STRING ValueName;
UNALIGNED WCHAR *String;
DWORD StringLength;
LONG Error;
HKEY TempHandle = NULL;
ULONG Length;
#if DBG
if ( BreakPointOnEntry ) {
DbgBreakPoint();
}
#endif
//
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
//
if( hKey == HKEY_PERFORMANCE_DATA ) {
return ERROR_INVALID_HANDLE;
}
if ((hKey == HKEY_PERFORMANCE_TEXT) ||
(hKey == HKEY_PERFORMANCE_NLSTEXT)) {
return(PerfRegSetValue(hKey,
( LPWSTR )lpValueName,
Reserved,
dwType,
( LPBYTE )lpData,
cbData));
}
//
// Ensure Reserved is zero to avoid future compatability problems.
//
if( Reserved != 0 ) {
return ERROR_INVALID_PARAMETER;
}
hKey = MapPredefinedHandle( hKey, &TempHandle );
if( hKey == NULL ) {
Error = ERROR_INVALID_HANDLE;
goto ExitCleanup;
}
//
// Special hack to help out all the people who
// believe the length of a NULL terminated string is
// strlen(foo) instead of strlen(foo) + 1.
//
String = (UNALIGNED WCHAR *)lpData;
StringLength = cbData/sizeof(WCHAR);
if (((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ) || (dwType == REG_MULTI_SZ)) &&
(StringLength > 0) &&
(String[StringLength-1] != 0)) {
//
// Do this under an exception handler in case the last
// little bit crosses a page boundary.
//
try {
if (String[StringLength] == 0) {
cbData += sizeof(WCHAR); // increase string length to account for NULL terminator
}
} except (EXCEPTION_EXECUTE_HANDLER) {
; // guess they really really did not want a NULL terminator
}
}
if( lpValueName != NULL ) {
Length = wcslen( lpValueName ) * sizeof( WCHAR );
ValueName.Length = (USHORT)Length;
if( Length != (ULONG)ValueName.Length ) {
//
// 32K overflow
//
Error = ERROR_INVALID_PARAMETER;
goto ExitCleanup;
}
}
//
// Convert the value name to a counted Unicode string.
//
RtlInitUnicodeString( &ValueName, lpValueName );
//
// Add the NULL to the Length, so that RPC will transmit it
//
ValueName.Length += sizeof( UNICODE_NULL );
if( ValueName.Length == 0 ) {
//
// overflow in RtlInitUnicodeString
//
Error = ERROR_INVALID_PARAMETER;
goto ExitCleanup;
}
//
// Call the Base API, passing it the supplied parameters and the
// counted Unicode strings.
//
if( IsLocalHandle( hKey )) {
Error = (LONG)LocalBaseRegSetValue (
hKey,
&ValueName,
dwType,
( LPBYTE )lpData,
cbData
);
#if defined(_WIN64)
if ( Error == 0)
Wow64RegSetKeyDirty (hKey);
#endif
} else {
Error = (LONG)BaseRegSetValue (
DereferenceRemoteHandle( hKey ),
&ValueName,
dwType,
( LPBYTE )lpData,
cbData
);
}
ExitCleanup:
CLOSE_LOCAL_HANDLE(TempHandle);
return Error;
}