windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/registry.c
2020-09-26 16:20:57 +08:00

595 lines
12 KiB
C

#include "precomp.h"
#pragma hdrstop
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
registry.c
Abstract:
Registry related functions in the setupdll
Detect Routines:
----------------
1. GetEnvVar <SYSTEM | USER> <VARNAME> returns
List <ValueName, ValueTitle, ValueRegType, ValueData>
The value data is decomposed into a list of the elements:
e.g. val1;val2;val3 becomes {val1, val2, val3}
2. GetMyComputerName
Install Routines Workers:
-------------------------
2. SetEnvVarWorker: To set a USER or SYSTEM environment variable
3. ExpandSzWorker: To expand all the expand sz components in an
environment string.
General Subroutines:
--------------------
1. GetValueEntry: To fetch a value entry given a key and a value name
This is useful when we don't know the size of the
value entry.
2. GetMaxSizeValueInKey: This is to find the maximum size needed to
query a value in the key.
Author:
Sunil Pai (sunilp) April 1992
--*/
extern CHAR ReturnTextBuffer[];
//
// Detect Routines
//
CB
GetEnvVar(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
SZ sz, sz1, szEnv;
HKEY hKey, hRootKey;
DWORD cbData;
CB Length;
LONG Status;
DWORD ValueType;
PVOID ValueData;
CHAR szValueType[25];
RGSZ rgsz;
#define UNDEF_VAR_VALUE "{}"
Unused( cbReturnBuffer );
//
// If the environment variable cannot be determine we
// return the empty list as the value of this call.
// Initialise this anyway to avoid doing this at a
// a number of places.
//
lstrcpy( ReturnBuffer, UNDEF_VAR_VALUE );
Length = lstrlen( UNDEF_VAR_VALUE ) + 1;
//
// Do parameter validation
//
if( cArgs < 2 ) {
return( Length );
}
//
// Check to see if the user wants a system environment variable or
// a user environment variable. Accordingly find out the right
// place in the registry to look.
//
if ( !lstrcmpi( Args[0], "SYSTEM" ) ) {
hRootKey = HKEY_LOCAL_MACHINE;
szEnv = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";
}
else if ( !lstrcmpi( Args[0], "USER" ) ) {
hRootKey = HKEY_CURRENT_USER;
szEnv = "Environment";
}
else {
return( Length );
}
//
// Open the environment variable key.
//
Status = RegOpenKeyEx(
hRootKey,
szEnv,
0,
KEY_READ,
&hKey
);
if( Status != ERROR_SUCCESS ) {
return( Length );
}
//
// Get the environment variable value
//
if( !GetMaxSizeValueInKey( hKey, &cbData ) ||
( ValueData = SAlloc( cbData ) ) == NULL
) {
RegCloseKey( hKey );
return( Length );
}
Status = RegQueryValueEx(
hKey,
Args[1],
NULL,
&ValueType,
ValueData,
&cbData
);
RegCloseKey( hKey );
if (Status != ERROR_SUCCESS) {
SFree( ValueData );
return( Length );
}
if ( ( sz = SzListValueFromPath( (SZ)ValueData ) ) == NULL ) {
SFree( ValueData );
return( Length );
}
SFree( ValueData );
_ultoa( ValueType, szValueType, 10 );
//
// Allocate an Rgsz structure: (Note same style as internal registry usage)
//
// Field 0: EnvVarValueName
// Field 1: EnvVarTitleIndex "0"
// Field 2: EnvVarValueType
// Field 3: EnvVarValue
//
if ( rgsz = RgszAlloc( 5 ) ) {
rgsz[0] = Args[1];
rgsz[1] = "0";
rgsz[2] = szValueType;
rgsz[3] = sz;
rgsz[4] = NULL;
sz1 = SzListValueFromRgsz( rgsz );
if( sz1 ) {
lstrcpy( ReturnBuffer, sz1 );
Length = lstrlen( sz1 ) + 1;
SFree( sz1 );
}
SFree( rgsz );
}
SFree( sz );
return( Length );
}
CB
GetMyComputerName(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
/*++
Routine Description:
DetectRoutine for GetComputerName. This finds out the computername of
this machine in the current control set.
Arguments:
Args - C argument list to this detect routine (None exist)
cArgs - Number of arguments.
ReturnBuffer - Buffer in which detected value is returned.
cbReturnBuffer - Buffer Size.
Return value:
Returns length of detected value.
--*/
{
CHAR ComputerName[MAX_PATH];
DWORD nSize = MAX_PATH;
BOOL bStatus = FALSE;
CB Length;
#define DEFAULT_COMPUTERNAME ""
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
if( GetComputerName( ComputerName, &nSize ) ) {
lstrcpy( ReturnBuffer, ComputerName );
Length = lstrlen( ComputerName ) + 1;
}
else {
lstrcpy( ReturnBuffer, DEFAULT_COMPUTERNAME );
Length = lstrlen( DEFAULT_COMPUTERNAME ) + 1;
}
return( Length );
}
//
// Install Routines
//
BOOL
SetEnvVarWorker(
LPSTR UserOrSystem,
LPSTR Name,
LPSTR Title,
LPSTR RegType,
LPSTR Data
)
{
HKEY hKey, hRootKey;
SZ szEnv;
LONG Status;
Unused(Title);
//
// Check to see if the user wants to modify a system environment variable
// or a user environment variable. Accordingly find out the right
// place in the registry to look.
//
if ( !lstrcmpi( UserOrSystem, "SYSTEM" ) ) {
hRootKey = HKEY_LOCAL_MACHINE;
szEnv = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";
}
else if ( !lstrcmpi( UserOrSystem, "USER" ) ) {
hRootKey = HKEY_CURRENT_USER;
szEnv = "Environment";
}
else {
return( FALSE );
}
//
// Open the environment variable key.
//
Status = RegOpenKeyEx(
hRootKey,
szEnv,
0,
KEY_WRITE,
&hKey
);
if( Status != ERROR_SUCCESS ) {
SetErrorText( IDS_ERROR_REGOPEN );
return( FALSE );
}
//
// Write the value given
//
Status = RegSetValueEx(
hKey,
Name,
0,
(DWORD)atol( RegType ),
(LPBYTE)Data,
lstrlen( Data ) + 1
);
RegCloseKey( hKey );
if( Status != ERROR_SUCCESS ) {
SetErrorText( IDS_ERROR_REGSETVALUE );
return( FALSE );
}
//
// Send a WM_WININICHANGE message so that progman picks up the new
// variable
//
SendMessageTimeout(
(HWND)-1,
WM_WININICHANGE,
0,
(LPARAM)"Environment",
SMTO_ABORTIFHUNG,
1000,
NULL
);
return( TRUE );
}
BOOL
ExpandSzWorker(
LPSTR EnvironmentString,
LPSTR ReturnBuffer,
DWORD cbReturnBuffer
)
{
DWORD cbBuffer;
cbBuffer = ExpandEnvironmentStrings(
(LPCSTR)EnvironmentString,
ReturnBuffer,
cbReturnBuffer
);
if ( cbBuffer > cbReturnBuffer ) {
SetErrorText( IDS_BUFFER_OVERFLOW );
return( FALSE );
}
return( TRUE );
}
BOOL
SetMyComputerNameWorker(
LPSTR ComputerName
)
/*++
Routine Description:
To set the computername value in the services tree.
Arguments:
ComputerName - Value to set as the computername
Return value:
TRUE if successful, FALSE otherwise.
--*/
{
if( !SetComputerName( ComputerName ) ) {
SetErrorText(IDS_ERROR_SETCOMPUTERNAME);
return( FALSE );
}
return( TRUE );
}
//=====================================================================
// The following are registry access subroutines..
//=====================================================================
BOOL
GetMaxSizeValueInKey(
HKEY hKey,
LPDWORD cbData
)
{
LONG Status;
CHAR szKClass[ MAX_PATH ];
DWORD cbKClass = MAX_PATH;
DWORD KSubKeys;
DWORD cbKMaxSubKeyLen;
DWORD cbKMaxClassLen;
DWORD KValues;
DWORD cbKMaxValueNameLen;
DWORD SizeSecurityDescriptor;
FILETIME KLastWriteTime;
Status = RegQueryInfoKey (
hKey,
szKClass,
&cbKClass,
NULL,
&KSubKeys,
&cbKMaxSubKeyLen,
&cbKMaxClassLen,
&KValues,
&cbKMaxValueNameLen,
cbData,
&SizeSecurityDescriptor,
&KLastWriteTime
);
if (Status != ERROR_SUCCESS) {
return( FALSE );
}
return( TRUE );
}
PVOID
GetValueEntry(
HKEY hKey,
LPSTR szValueName
)
{
LONG Status;
CHAR szKClass[ MAX_PATH ];
DWORD cbKClass = MAX_PATH;
DWORD KSubKeys;
DWORD cbKMaxSubKeyLen;
DWORD cbKMaxClassLen;
DWORD KValues;
DWORD cbKMaxValueNameLen;
DWORD cbData;
DWORD SizeSecurityDescriptor;
FILETIME KLastWriteTime;
DWORD ValueType;
PVOID ValueData;
Status = RegQueryInfoKey (
hKey,
szKClass,
&cbKClass,
NULL,
&KSubKeys,
&cbKMaxSubKeyLen,
&cbKMaxClassLen,
&KValues,
&cbKMaxValueNameLen,
&cbData,
&SizeSecurityDescriptor,
&KLastWriteTime
);
if (Status != ERROR_SUCCESS) {
return( NULL );
}
if ( ( ValueData = SAlloc( cbData ) ) == NULL ) {
return( NULL );
}
Status = RegQueryValueEx(
hKey,
szValueName,
NULL,
&ValueType,
ValueData,
&cbData
);
if (Status != ERROR_SUCCESS) {
SFree( ValueData );
return( NULL );
}
else {
return( ValueData );
}
}
BOOL
GenerateUniqueFileName(
IN LPSTR TempPath,
IN LPSTR Prefix,
IN OUT LPSTR TempFile
)
/*++
Routine Description:
To generate a unique filename (with no extension) in the TempPath
Directory with the Prefix given and digits from 1 to 99999
Arguments:
TempPath - string containing a valid directory path ending
in a backslash.
Prefix - a prefix string no longer than 3 characters.
TempFile - buffer to return the full path to the temp file
Return value:
TRUE if succeds in finding, FALSE otherwise. If TRUE, TempFile buffer
has the full path to the temp file.
--*/
{
CHAR Number[6];
DWORD i;
//
// Check parameters
//
if ( TempPath == (LPSTR)NULL
|| Prefix == (LPSTR)NULL
|| TempFile == (LPSTR)NULL
|| lstrlen( Prefix ) > 3
) {
return( FALSE );
}
//
// go through all numbers upto 5 digits long looking
// for file which doesn't exist
//
for( i = 1; i <99999; i++ ) {
lstrcpy( TempFile, TempPath);
lstrcat( TempFile, "\\" );
lstrcat( TempFile, Prefix );
sprintf( Number, "%d", i );
lstrcat( TempFile, Number );
if (!FFileExist( TempFile ) ) {
return( TRUE );
}
}
//
// not found, return false
//
return( FALSE );
}