2029 lines
41 KiB
C
2029 lines
41 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
userdiff.c
|
||
|
||
Abstract:
|
||
|
||
This module contains routines for updating the userdifr hive.
|
||
|
||
In the following, the list of changes to be applied when a user
|
||
logs on after an upgrade will be called UserRun. UserRun is
|
||
developed from three sources:
|
||
|
||
1) The UserRun generated on the last upgrade. This forms the
|
||
basis for this upgrade's UserRun.
|
||
|
||
2) The list of changes shipped with the system. Call this
|
||
UserShip. The changes from all build numbers that are
|
||
present in UserShip but not in UserRun are copied into
|
||
UserRun. (Note that if a build number is already present
|
||
in UserRun, we don't copy the UserShip changes. This
|
||
means that changes cannot be made retroactively in UserShip.)
|
||
|
||
3) Changes made during the current upgrade. These changes are
|
||
detected at run time (see watch.c). All changes detected
|
||
during the upgrade are added to UserRun.
|
||
|
||
Author:
|
||
|
||
Chuck Lenzmeier (chuckl)
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "setupp.h"
|
||
#pragma hdrstop
|
||
|
||
|
||
//
|
||
// Debugging aids.
|
||
//
|
||
|
||
#if USERDIFF_DEBUG
|
||
|
||
DWORD UserdiffDebugLevel = 0;
|
||
#define dprintf(_lvl_,_x_) if ((_lvl_) <= UserdiffDebugLevel) DbgPrint _x_
|
||
|
||
#else
|
||
|
||
#define dprintf(_lvl_,_x_)
|
||
|
||
#endif
|
||
|
||
//
|
||
// Macro to calculate length of string including terminator.
|
||
//
|
||
|
||
#define SZLEN(_wcs) ((wcslen(_wcs) + 1) * sizeof(WCHAR))
|
||
|
||
//
|
||
// Context record used in this module to track registry state.
|
||
//
|
||
|
||
typedef struct _USERRUN_CONTEXT {
|
||
BOOL UserRunLoaded;
|
||
HKEY UserRunKey;
|
||
HKEY BuildKey;
|
||
HKEY FilesKey;
|
||
HKEY HiveKey;
|
||
ULONG FilesIndex;
|
||
ULONG HiveIndex;
|
||
HKEY UserShipKey;
|
||
} USERRUN_CONTEXT, *PUSERRUN_CONTEXT;
|
||
|
||
//
|
||
// Context record used in MakeUserRunEnumRoutine.
|
||
//
|
||
|
||
typedef struct _KEY_ENUM_CONTEXT {
|
||
PUSERRUN_CONTEXT UserRunContext;
|
||
PWCH CurrentPath;
|
||
} KEY_ENUM_CONTEXT, *PKEY_ENUM_CONTEXT;
|
||
|
||
|
||
//
|
||
// Forward declaration of local subroutines.
|
||
//
|
||
|
||
DWORD
|
||
LoadUserRun (
|
||
OUT PUSERRUN_CONTEXT Context,
|
||
IN PWCH UserRunPath
|
||
);
|
||
|
||
DWORD
|
||
MergeUserShipIntoUserRun (
|
||
IN OUT PUSERRUN_CONTEXT Context,
|
||
IN PWCH UserShipPath
|
||
);
|
||
|
||
DWORD
|
||
CreateAndLoadUserRun (
|
||
OUT PUSERRUN_CONTEXT Context,
|
||
IN PWCH UserRunPath
|
||
);
|
||
|
||
DWORD
|
||
OpenUserRunKeys (
|
||
IN OUT PUSERRUN_CONTEXT Context
|
||
);
|
||
|
||
VOID
|
||
UnloadUserRun (
|
||
IN OUT PUSERRUN_CONTEXT Context
|
||
);
|
||
|
||
DWORD
|
||
CheckUserShipKey (
|
||
IN PVOID Context,
|
||
IN DWORD KeyNameLength,
|
||
IN PWCH KeyName
|
||
);
|
||
|
||
DWORD
|
||
MakeUserRunEnumRoutine (
|
||
IN PVOID Context,
|
||
IN PWATCH_ENTRY Entry
|
||
);
|
||
|
||
DWORD
|
||
MakeAddDirectory (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
);
|
||
|
||
DWORD
|
||
MakeAddValue (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
);
|
||
|
||
DWORD
|
||
MakeDeleteValue (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
);
|
||
|
||
DWORD
|
||
MakeAddKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
);
|
||
|
||
DWORD
|
||
MakeDeleteKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
);
|
||
|
||
DWORD
|
||
AddDirectory (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH FullPath,
|
||
IN PWCH Path
|
||
);
|
||
|
||
DWORD
|
||
AddKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Path
|
||
);
|
||
|
||
DWORD
|
||
AddValueDuringAddKey (
|
||
IN PVOID Context,
|
||
IN DWORD ValueNameLength,
|
||
IN PWCH ValueName,
|
||
IN DWORD ValueType,
|
||
IN PVOID ValueData,
|
||
IN DWORD ValueDataLength
|
||
);
|
||
|
||
DWORD
|
||
AddKeyDuringAddKey (
|
||
IN PVOID Context,
|
||
IN DWORD KeyNameLength,
|
||
IN PWCH KeyName
|
||
);
|
||
|
||
DWORD
|
||
AddValue (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH KeyName OPTIONAL,
|
||
IN PWCH ValueName,
|
||
IN DWORD ValueType,
|
||
IN PVOID ValueData,
|
||
IN DWORD ValueDataLength
|
||
);
|
||
|
||
DWORD
|
||
CreateUserRunSimpleFileKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN DWORD Action,
|
||
IN PWCH Name
|
||
);
|
||
|
||
DWORD
|
||
CreateUserRunKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN BOOL IsFileKey,
|
||
OUT PHKEY NewKeyHandle
|
||
);
|
||
|
||
DWORD
|
||
QueryValue (
|
||
IN PWCH KeyName OPTIONAL,
|
||
IN PWCH ValueName,
|
||
OUT PDWORD ValueType,
|
||
OUT PVOID *ValueData,
|
||
OUT PDWORD ValueDataLength
|
||
);
|
||
|
||
VOID
|
||
SzToMultiSz (
|
||
IN PWCH Sz,
|
||
OUT PWCH *MultiSz,
|
||
OUT PDWORD MultiSzLength
|
||
);
|
||
|
||
|
||
DWORD
|
||
MakeUserdifr (
|
||
IN PVOID WatchHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates the UserRun hive based on the changes made to the current user's
|
||
profile directory and the HKEY_CURRENT_USER key.
|
||
|
||
Arguments:
|
||
|
||
WatchHandle - supplies the handle returned by WatchStart.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY userrunKey;
|
||
USERRUN_CONTEXT context;
|
||
DWORD error;
|
||
DWORD disposition;
|
||
WCHAR userRunPath[MAX_PATH + 1];
|
||
WCHAR userShipPath[MAX_PATH + 1];
|
||
|
||
//
|
||
// Merge UserShip with UserRun.
|
||
//
|
||
// If both UserRun and UserShip exist, merge into UserRun those build
|
||
// keys from UserShip that do no exist in UserRun.
|
||
//
|
||
// If the UserRun hive file doesn't exist, this means that no
|
||
// upgrade has ever been run on this machine. Copy the UserShip
|
||
// hive file into place as UserRun. This effectively does the
|
||
// registry merge by using a file copy.
|
||
//
|
||
// In the unlikely event that neither UserRun nor UserShip exists,
|
||
// create an empty UserRun.
|
||
//
|
||
|
||
//
|
||
// Initialize the context record.
|
||
//
|
||
|
||
context.UserRunLoaded = FALSE;
|
||
context.UserRunKey = NULL;
|
||
context.BuildKey = NULL;
|
||
context.FilesKey = NULL;
|
||
context.HiveKey = NULL;
|
||
|
||
//
|
||
// Enable SeBackupPrivilege and SeRestorePrivilege.
|
||
//
|
||
|
||
pSetupEnablePrivilege( SE_BACKUP_NAME, TRUE );
|
||
pSetupEnablePrivilege( SE_RESTORE_NAME, TRUE );
|
||
|
||
//
|
||
// Check to see whether UserRun exists.
|
||
//
|
||
|
||
error = GetWindowsDirectory( userRunPath, MAX_PATH );
|
||
if( error == 0) {
|
||
MYASSERT(FALSE);
|
||
return ERROR_PATH_NOT_FOUND;
|
||
}
|
||
wcscat( userRunPath, TEXT("\\") );
|
||
wcscpy( userShipPath, userRunPath );
|
||
wcscat( userRunPath, USERRUN_PATH );
|
||
wcscat( userShipPath, USERSHIP_PATH );
|
||
|
||
if ( FileExists( userRunPath, NULL ) ) {
|
||
|
||
//
|
||
// UserRun exists. Load it into the registry. Check to see whether
|
||
// UserShip exists.
|
||
//
|
||
|
||
error = LoadUserRun( &context, userRunPath );
|
||
if ( error == NO_ERROR ) {
|
||
|
||
if ( FileExists( userShipPath, NULL ) ) {
|
||
|
||
//
|
||
// UserShip also exists. Merge UserShip into UserRun.
|
||
//
|
||
|
||
error = MergeUserShipIntoUserRun( &context, userShipPath );
|
||
|
||
} else {
|
||
|
||
//
|
||
// UserShip doesn't exist. Just use the existing UserRun.
|
||
//
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// UserRun doesn't exist. If UserShip exists, just copy the UserShip
|
||
// hive file into place as UserRun. If neither one exists, create
|
||
// an empty UserRun.
|
||
//
|
||
|
||
if ( FileExists( userShipPath, NULL ) ) {
|
||
|
||
//
|
||
// UserShip exists. Copy UserShip into UserRun.
|
||
//
|
||
|
||
if ( !CopyFile( userShipPath, userRunPath, TRUE ) ) {
|
||
error = GetLastError();
|
||
|
||
} else {
|
||
|
||
//
|
||
// Load the new UserRun.
|
||
//
|
||
|
||
error = LoadUserRun( &context, userRunPath );
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// UserShip doesn't exist. Create an empty UserRun.
|
||
//
|
||
|
||
error = CreateAndLoadUserRun( &context, userRunPath );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Add changes from this upgrade to UserRun.
|
||
//
|
||
|
||
if ( error == NO_ERROR ) {
|
||
|
||
error = OpenUserRunKeys( &context );
|
||
if ( error == NO_ERROR ) {
|
||
error = WatchEnum( WatchHandle, &context, MakeUserRunEnumRoutine );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Unload the UserRun hive.
|
||
//
|
||
|
||
UnloadUserRun( &context );
|
||
|
||
return error;
|
||
|
||
} // MakeUserdifr
|
||
|
||
|
||
DWORD
|
||
LoadUserRun (
|
||
OUT PUSERRUN_CONTEXT Context,
|
||
IN PWCH UserRunPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Loads the UserRun hive into the registry and opens the root key.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
UserRunPath - supplies the path to the UserRun hive file.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD error;
|
||
|
||
//
|
||
// Load the UserRun hive into the registry.
|
||
//
|
||
|
||
error = RegLoadKey( HKEY_USERS, USERRUN_KEY, UserRunPath );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
Context->UserRunLoaded = TRUE;
|
||
|
||
//
|
||
// Open the UserRun root.
|
||
//
|
||
|
||
error = RegOpenKeyEx( HKEY_USERS,
|
||
USERRUN_KEY,
|
||
0,
|
||
KEY_READ | KEY_WRITE,
|
||
&Context->UserRunKey );
|
||
|
||
return error;
|
||
|
||
} // LoadUserRun
|
||
|
||
|
||
DWORD
|
||
MergeUserShipIntoUserRun (
|
||
IN OUT PUSERRUN_CONTEXT Context,
|
||
IN PWCH UserShipPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Merges the UserShip hive into the UserRun hive.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
UserShipPath - supplies the path to the UserShip file.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD error;
|
||
DWORD disposition;
|
||
|
||
//
|
||
// Load the UserShip hive into the registry.
|
||
//
|
||
|
||
error = RegLoadKey( HKEY_USERS, USERSHIP_KEY, UserShipPath );
|
||
if ( error == NO_ERROR ) {
|
||
|
||
//
|
||
// Open the UserShip root.
|
||
//
|
||
|
||
error = RegOpenKeyEx( HKEY_USERS,
|
||
USERSHIP_KEY,
|
||
0,
|
||
KEY_READ | KEY_WRITE,
|
||
&Context->UserShipKey );
|
||
if ( error == NO_ERROR ) {
|
||
|
||
//
|
||
// Enumerate the build number keys in UserShip, looking for
|
||
// builds that aren't represented in UserRun.
|
||
//
|
||
|
||
error = EnumerateKey( Context->UserShipKey,
|
||
Context,
|
||
NULL, // don't enumerate values
|
||
CheckUserShipKey );
|
||
|
||
//
|
||
// Close the UserShip root.
|
||
//
|
||
|
||
RegCloseKey( Context->UserShipKey );
|
||
}
|
||
|
||
//
|
||
// Unload the UserShip hive.
|
||
//
|
||
|
||
RegUnLoadKey( HKEY_USERS, USERSHIP_KEY );
|
||
}
|
||
|
||
return error;
|
||
|
||
} // MergeUserShipIntoUserRun
|
||
|
||
|
||
DWORD
|
||
CreateAndLoadUserRun (
|
||
OUT PUSERRUN_CONTEXT Context,
|
||
IN PWCH UserRunPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create a new UserRun hive and load it into the registry.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
UserRunPath - supplies the path to the UserRun file.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD error;
|
||
DWORD disposition;
|
||
HKEY userRunKey;
|
||
|
||
//
|
||
// Create the UserRun key under HKEY_CURRENT_USER.
|
||
//
|
||
// NOTE: Trying to create this under HKEY_USERS doesn't work.
|
||
//
|
||
|
||
error = RegCreateKeyEx( HKEY_CURRENT_USER,
|
||
USERRUN_KEY,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&userRunKey,
|
||
&disposition );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
//
|
||
// Save the newly created UserRun key to a hive file.
|
||
//
|
||
|
||
error = RegSaveKey( userRunKey,
|
||
UserRunPath,
|
||
NULL );
|
||
|
||
//
|
||
// Close and delete the UserRun key.
|
||
//
|
||
|
||
RegCloseKey( userRunKey );
|
||
|
||
RegDeleteKey( HKEY_CURRENT_USER, USERRUN_KEY );
|
||
|
||
//
|
||
// Now load UserRun back into the registry.
|
||
//
|
||
|
||
if ( error == NO_ERROR ) {
|
||
error = LoadUserRun( Context, UserRunPath );
|
||
}
|
||
|
||
return error;
|
||
|
||
} // CreateAndLoadUserRun
|
||
|
||
|
||
DWORD
|
||
OpenUserRunKeys (
|
||
IN OUT PUSERRUN_CONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Opens the core keys in the UserRun hive.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD error;
|
||
DWORD disposition;
|
||
OSVERSIONINFO versionInfo;
|
||
WCHAR buildNumber[6];
|
||
|
||
//
|
||
// Get the current build number.
|
||
//
|
||
|
||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
||
if ( !GetVersionEx( &versionInfo ) ) {
|
||
return GetLastError();
|
||
}
|
||
|
||
wsprintf( buildNumber, TEXT("%d"), LOWORD(versionInfo.dwBuildNumber) );
|
||
|
||
//
|
||
// Open/create a subkey for the current build.
|
||
//
|
||
|
||
error = RegCreateKeyEx( Context->UserRunKey,
|
||
buildNumber,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ | KEY_WRITE,
|
||
NULL,
|
||
&Context->BuildKey,
|
||
&disposition );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
//
|
||
// Create a Files subkey.
|
||
//
|
||
|
||
error = RegCreateKeyEx( Context->BuildKey,
|
||
FILES_KEY,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ | KEY_WRITE,
|
||
NULL,
|
||
&Context->FilesKey,
|
||
&disposition );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
//
|
||
// Create a Hive subkey.
|
||
//
|
||
|
||
error = RegCreateKeyEx( Context->BuildKey,
|
||
HIVE_KEY,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ | KEY_WRITE,
|
||
NULL,
|
||
&Context->HiveKey,
|
||
&disposition );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
//
|
||
// Set the FilesIndex and HiveIndex so that we append to whatever
|
||
// information already exists for the current build.
|
||
//
|
||
|
||
error = RegQueryInfoKey( Context->FilesKey,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&Context->FilesIndex,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
error = RegQueryInfoKey( Context->HiveKey,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&Context->HiveIndex,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL );
|
||
|
||
return error;
|
||
|
||
} // OpenUserRunKeys
|
||
|
||
|
||
VOID
|
||
UnloadUserRun (
|
||
IN OUT PUSERRUN_CONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Unloads the UserRun hive from the registry.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Close the core keys, if they are open.
|
||
//
|
||
|
||
if ( Context->HiveKey != NULL ) {
|
||
RegCloseKey( Context->HiveKey );
|
||
}
|
||
if ( Context->FilesKey != NULL ) {
|
||
RegCloseKey( Context->FilesKey );
|
||
}
|
||
if ( Context->BuildKey != NULL ) {
|
||
RegCloseKey( Context->BuildKey );
|
||
}
|
||
|
||
//
|
||
// Close the root key, if it is open.
|
||
//
|
||
|
||
if ( Context->UserRunKey != NULL ) {
|
||
RegCloseKey( Context->UserRunKey );
|
||
}
|
||
|
||
//
|
||
// Unload the hive, if it has been loaded.
|
||
//
|
||
|
||
if ( Context->UserRunLoaded ) {
|
||
RegUnLoadKey( HKEY_USERS, USERRUN_KEY );
|
||
}
|
||
|
||
return;
|
||
|
||
} // UnloadUserRun
|
||
|
||
|
||
DWORD
|
||
CheckUserShipKey (
|
||
IN PVOID Context,
|
||
IN DWORD KeyNameLength,
|
||
IN PWCH KeyName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks an enumerated key in the UserShip hive to see if a corresponding
|
||
key is present in the UserRun hive. If not, copies the key from UserShip
|
||
into UserRun.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
KeyNameLength - length in characters of key name.
|
||
|
||
KeyName - pointer to name of key.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUSERRUN_CONTEXT context = Context;
|
||
|
||
DWORD error;
|
||
DWORD disposition;
|
||
HKEY userRunBuildKey;
|
||
HKEY userShipBuildKey;
|
||
WCHAR path[MAX_PATH + 1];
|
||
|
||
//
|
||
// We have the name of a key in UserShip. Try to open the
|
||
// corresponding key in UserRun.
|
||
//
|
||
|
||
error = RegCreateKeyEx( context->UserRunKey,
|
||
KeyName,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ | KEY_WRITE,
|
||
NULL,
|
||
&userRunBuildKey,
|
||
&disposition );
|
||
if ( error != NO_ERROR ) {
|
||
return error;
|
||
}
|
||
|
||
//
|
||
// No error occurred. The key was either opened or created.
|
||
//
|
||
|
||
if ( disposition == REG_OPENED_EXISTING_KEY ) {
|
||
|
||
//
|
||
// The key already existed in UserRun. We assume that it already
|
||
// contains the information that is in UserShip.
|
||
//
|
||
|
||
} else {
|
||
|
||
//
|
||
// The key didn't exist in UserRun. Copy the key from UserShip
|
||
// into UserRun. This is done by saving the UserShip key to
|
||
// a file, then restoring the file back under the UserRun key.
|
||
//
|
||
// Note that the copy operation will fail if the file already
|
||
// exists.
|
||
//
|
||
|
||
error = RegOpenKeyEx( context->UserShipKey,
|
||
KeyName,
|
||
0,
|
||
KEY_READ,
|
||
&userShipBuildKey );
|
||
if ( error == NO_ERROR ) {
|
||
|
||
GetWindowsDirectory( path, MAX_PATH );
|
||
wcscat( path, TEXT("\\") );
|
||
wcscat( path, USERTMP_PATH );
|
||
|
||
error = RegSaveKey( userShipBuildKey,
|
||
path,
|
||
NULL );
|
||
if ( error == NO_ERROR ) {
|
||
|
||
error = RegRestoreKey( userRunBuildKey,
|
||
path,
|
||
0 );
|
||
|
||
DeleteFile( path );
|
||
}
|
||
|
||
RegCloseKey( userShipBuildKey );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Close the UserRun key.
|
||
//
|
||
|
||
RegCloseKey( userRunBuildKey );
|
||
|
||
return error;
|
||
|
||
} // CheckUserShipKey
|
||
|
||
|
||
DWORD
|
||
MakeUserRunEnumRoutine (
|
||
IN PVOID Context,
|
||
IN PWATCH_ENTRY Entry
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
EnumRoutine for the MakeUserdifr operation. Calls the appropriate
|
||
processing routine based on the entry type (file/directory/key/value)
|
||
and the change type (changed, new, deleted).
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Entry - description of the changed entry.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUSERRUN_CONTEXT context = Context;
|
||
DWORD index;
|
||
HKEY newKey;
|
||
DWORD error;
|
||
DWORD dword;
|
||
|
||
//
|
||
// Call the appropriate processing routine.
|
||
//
|
||
|
||
switch ( Entry->EntryType ) {
|
||
|
||
case WATCH_DIRECTORY:
|
||
|
||
switch ( Entry->ChangeType ) {
|
||
|
||
case WATCH_NEW:
|
||
dprintf( 1, ("New directory %ws\n", Entry->Name) );
|
||
error = MakeAddDirectory( Context, Entry->Name );
|
||
break;
|
||
|
||
case WATCH_DELETED:
|
||
dprintf( 1, ("Deleted directory %ws\n", Entry->Name) );
|
||
error = CreateUserRunSimpleFileKey( Context, 2, Entry->Name );
|
||
break;
|
||
|
||
default:
|
||
error = ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
break;
|
||
|
||
case WATCH_FILE:
|
||
|
||
switch ( Entry->ChangeType ) {
|
||
|
||
case WATCH_NEW:
|
||
case WATCH_CHANGED:
|
||
dprintf( 1, ("New or changed file %ws\n", Entry->Name) );
|
||
error = CreateUserRunSimpleFileKey( Context, 3, Entry->Name );
|
||
break;
|
||
|
||
case WATCH_DELETED:
|
||
dprintf( 1, ("Deleted file %ws\n", Entry->Name) );
|
||
error = CreateUserRunSimpleFileKey( Context, 4, Entry->Name );
|
||
break;
|
||
|
||
default:
|
||
error = ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
break;
|
||
|
||
case WATCH_KEY:
|
||
switch ( Entry->ChangeType ) {
|
||
|
||
case WATCH_NEW:
|
||
dprintf( 1, ("New key %ws\n", Entry->Name) );
|
||
error = MakeAddKey( Context, Entry->Name );
|
||
break;
|
||
|
||
case WATCH_DELETED:
|
||
dprintf( 1, ("Deleted key %ws\n", Entry->Name) );
|
||
error = MakeDeleteKey( Context, Entry->Name );
|
||
break;
|
||
|
||
default:
|
||
error = ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
break;
|
||
|
||
case WATCH_VALUE:
|
||
|
||
switch ( Entry->ChangeType ) {
|
||
|
||
case WATCH_NEW:
|
||
case WATCH_CHANGED:
|
||
dprintf( 1, ("New or changed value %ws\n", Entry->Name) );
|
||
error = MakeAddValue( Context, Entry->Name );
|
||
break;
|
||
|
||
case WATCH_DELETED:
|
||
dprintf( 1, ("Deleted value %ws\n", Entry->Name) );
|
||
error = MakeDeleteValue( Context, Entry->Name );
|
||
break;
|
||
|
||
default:
|
||
error = ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
error = ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
return error;
|
||
|
||
} // MakeUserRunEnumRoutine
|
||
|
||
|
||
DWORD
|
||
MakeAddDirectory (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds entries to the UserRun hive for a new directory.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Name - name of new directory (relative to root of watched tree).
|
||
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
WCHAR fullpath[MAX_PATH + 1];
|
||
PWCH path;
|
||
BOOL ok;
|
||
|
||
//
|
||
// Get the full path to the new directory. "fullpath" is the full path;
|
||
// "path" is just this directory.
|
||
//
|
||
|
||
ok = GetSpecialFolderPath ( CSIDL_PROGRAMS, fullpath );
|
||
if ( !ok ) {
|
||
return GetLastError();
|
||
}
|
||
wcscat( fullpath, TEXT("\\") );
|
||
path = fullpath + wcslen(fullpath);
|
||
wcscpy( path, Name );
|
||
|
||
//
|
||
// Call AddDirectory to do the recursive work.
|
||
//
|
||
|
||
return AddDirectory( Context, fullpath, path );
|
||
|
||
} // MakeAddDirectory
|
||
|
||
|
||
DWORD
|
||
MakeAddValue (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds an entry to the UserRun hive for a new value.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Name - name of new value (relative to HKEY_CURRENT_USER).
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
PWCH keyName;
|
||
PWCH valueName;
|
||
PWCH splitPoint;
|
||
DWORD valueType;
|
||
PVOID valueData;
|
||
DWORD valueDataLength;
|
||
DWORD error;
|
||
DWORD dword;
|
||
|
||
//
|
||
// Split the name into key and value portions.
|
||
//
|
||
|
||
splitPoint = wcsrchr( Name, TEXT('\\') );
|
||
if ( splitPoint != NULL ) {
|
||
keyName = Name;
|
||
valueName = splitPoint + 1;
|
||
*splitPoint = 0;
|
||
} else {
|
||
keyName = NULL;
|
||
valueName = Name;
|
||
}
|
||
|
||
//
|
||
// Query the value data.
|
||
//
|
||
|
||
valueData = NULL;
|
||
error = QueryValue( keyName, valueName, &valueType, &valueData, &valueDataLength );
|
||
|
||
//
|
||
// Add an entry for the value.
|
||
//
|
||
|
||
if ( error == NO_ERROR ) {
|
||
error = AddValue( Context, keyName, valueName, valueType, valueData, valueDataLength );
|
||
}
|
||
|
||
//
|
||
// Free the value data buffer allocated by QueryValue.
|
||
//
|
||
|
||
if ( valueData != NULL ) {
|
||
MyFree( valueData );
|
||
}
|
||
|
||
//
|
||
// Restore the input value name string.
|
||
//
|
||
|
||
if ( splitPoint != NULL ) {
|
||
*splitPoint = TEXT('\\');
|
||
}
|
||
|
||
return error;
|
||
|
||
} // MakeAddValue
|
||
|
||
|
||
DWORD
|
||
MakeDeleteValue (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds an entry to the UserRun hive for a deleted value.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Name - name of deleted value (relative to HKEY_CURRENT_USER).
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
PWCH keyName;
|
||
PWCH valueName;
|
||
PWCH valueNames;
|
||
PWCH splitPoint;
|
||
DWORD valueNamesLength;
|
||
DWORD error;
|
||
DWORD dword;
|
||
|
||
error = NO_ERROR;
|
||
|
||
//
|
||
// Split the name into key and value portions. Create a MULTI_SZ
|
||
// version of the deleted name (to match userdiff format).
|
||
//
|
||
|
||
splitPoint = wcsrchr( Name, TEXT('\\') );
|
||
if ( splitPoint != NULL ) {
|
||
keyName = Name;
|
||
valueName = splitPoint + 1;
|
||
*splitPoint = 0;
|
||
} else {
|
||
keyName = NULL;
|
||
valueName = Name;
|
||
}
|
||
|
||
SzToMultiSz( valueName, &valueNames, &valueNamesLength );
|
||
if ( valueNames == NULL ) {
|
||
error = ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
//
|
||
// Create an entry key and popuplate it.
|
||
//
|
||
|
||
newKey = NULL;
|
||
if ( error == NO_ERROR ) {
|
||
error = CreateUserRunKey( Context, FALSE, &newKey );
|
||
}
|
||
|
||
if ( error == NO_ERROR ) {
|
||
dword = 4;
|
||
error = RegSetValueEx( newKey, ACTION_VALUE, 0, REG_DWORD, (PBYTE)&dword, sizeof(DWORD) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, KEYNAME_VALUE, 0, REG_SZ, (PBYTE)keyName, SZLEN(keyName) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, VALUENAMES_VALUE, 0, REG_MULTI_SZ, (PBYTE)valueNames, valueNamesLength );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
if ( *valueNames == 0 ) {
|
||
dword = 1;
|
||
error = RegSetValueEx( newKey, FLAGS_VALUE, 0, REG_DWORD, (PBYTE)&dword, sizeof(DWORD) );
|
||
}
|
||
}
|
||
|
||
if ( newKey != NULL ) {
|
||
RegCloseKey( newKey );
|
||
}
|
||
|
||
//
|
||
// Free the buffer allocated by SzToMultiSz.
|
||
//
|
||
|
||
if ( valueNames != NULL ) {
|
||
MyFree( valueNames );
|
||
}
|
||
|
||
//
|
||
// Restore the input value name string.
|
||
//
|
||
|
||
if ( splitPoint != NULL ) {
|
||
*splitPoint = TEXT('\\');
|
||
}
|
||
|
||
return error;
|
||
|
||
} // MakeDeleteValue
|
||
|
||
|
||
DWORD
|
||
MakeAddKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds entries to the UserRun hive for a new key.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Name - name of new key (relative to HKEY_CURRENT_USER).
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
WCHAR path[MAX_PATH + 1];
|
||
|
||
//
|
||
// Copy the key name into a large buffer and call AddKey to do the
|
||
// recursive work.
|
||
//
|
||
|
||
wcscpy( path, Name );
|
||
return AddKey( Context, path );
|
||
|
||
} // MakeAddKey
|
||
|
||
|
||
DWORD
|
||
MakeDeleteKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds an entry to the UserRun hive for a deleted key.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Name - name of deleted key (relative to HKEY_CURRENT_USER).
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
DWORD error;
|
||
DWORD dword;
|
||
|
||
//
|
||
// Create an entry key and popuplate it.
|
||
//
|
||
|
||
newKey = NULL;
|
||
error = CreateUserRunKey( Context, FALSE, &newKey );
|
||
|
||
if ( error == NO_ERROR ) {
|
||
dword = 2;
|
||
error = RegSetValueEx( newKey, ACTION_VALUE, 0, REG_DWORD, (PBYTE)&dword, sizeof(DWORD) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, KEYNAME_VALUE, 0, REG_SZ, (PBYTE)Name, SZLEN(Name) );
|
||
}
|
||
|
||
if ( newKey != NULL ) {
|
||
RegCloseKey( newKey );
|
||
}
|
||
|
||
return error;
|
||
|
||
} // MakeDeleteKey
|
||
|
||
|
||
DWORD
|
||
AddDirectory (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH FullPath,
|
||
IN PWCH Path
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Recursively adds entries to the UserRun hive for a new directory
|
||
and its subtree.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
FullPath - full path to directory.
|
||
|
||
Path - path to directory relative to root of watched directory.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
DWORD error;
|
||
DWORD dword;
|
||
HANDLE findHandle;
|
||
WIN32_FIND_DATA fileData;
|
||
BOOL ok;
|
||
|
||
//
|
||
// Create an entry key for the directory and popuplate it.
|
||
//
|
||
|
||
newKey = NULL;
|
||
error = CreateUserRunKey( Context, TRUE, &newKey );
|
||
|
||
if ( error == NO_ERROR ) {
|
||
dword = 1;
|
||
error = RegSetValueEx( newKey, ACTION_VALUE, 0, REG_DWORD, (PBYTE)&dword, sizeof(DWORD) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, ITEM_VALUE, 0, REG_SZ, (PBYTE)Path, SZLEN(Path) );
|
||
}
|
||
|
||
if ( newKey != NULL ) {
|
||
RegCloseKey( newKey );
|
||
}
|
||
|
||
if ( error == NO_ERROR ) {
|
||
|
||
//
|
||
// Search the directory and add file and directory entries.
|
||
//
|
||
|
||
wcscat( Path, TEXT("\\*") );
|
||
findHandle = FindFirstFile( FullPath, &fileData );
|
||
Path[wcslen(Path) - 2] = 0;
|
||
|
||
if ( findHandle != INVALID_HANDLE_VALUE ) {
|
||
|
||
do {
|
||
|
||
//
|
||
// Append the name of the current directory entry to the path.
|
||
//
|
||
|
||
wcscat( Path, TEXT("\\") );
|
||
wcscat( Path, fileData.cFileName );
|
||
|
||
//
|
||
// If the current entry is a file, add an entry in UserRun
|
||
// for it. If the current entry is a directory, call
|
||
// AddDirectory recursively to process it.
|
||
//
|
||
|
||
if ( FlagOff(fileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY) ) {
|
||
error = CreateUserRunSimpleFileKey( Context, 3, Path );
|
||
} else if ((wcscmp(fileData.cFileName,TEXT(".")) != 0) &&
|
||
(wcscmp(fileData.cFileName,TEXT("..")) != 0)) {
|
||
error = AddDirectory( Context, FullPath, Path );
|
||
}
|
||
|
||
*wcsrchr( Path, TEXT('\\') ) = 0;
|
||
|
||
if ( error == NO_ERROR ) {
|
||
ok = FindNextFile( findHandle, &fileData );
|
||
}
|
||
|
||
} while ( (error == NO_ERROR) && ok );
|
||
|
||
FindClose( findHandle );
|
||
|
||
} // findHandle != INVALID_HANDLE_VALUE
|
||
|
||
}
|
||
|
||
return error;
|
||
|
||
} // AddDirectory
|
||
|
||
|
||
DWORD
|
||
AddKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH Path
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Recursively adds entries to the UserRun hive for a new key
|
||
and its subtree.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to WatchEnum.
|
||
|
||
Path - path to key relative to HKEY_CURRENT_USER.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
DWORD error;
|
||
DWORD dword;
|
||
HKEY findHandle;
|
||
KEY_ENUM_CONTEXT enumContext;
|
||
|
||
//
|
||
// Create an entry key for the key and popuplate it.
|
||
//
|
||
|
||
newKey = NULL;
|
||
error = CreateUserRunKey( Context, FALSE, &newKey );
|
||
|
||
if ( error == NO_ERROR ) {
|
||
dword = 1;
|
||
error = RegSetValueEx( newKey, ACTION_VALUE, 0, REG_DWORD, (PBYTE)&dword, sizeof(DWORD) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, KEYNAME_VALUE, 0, REG_SZ, (PBYTE)Path, SZLEN(Path) );
|
||
}
|
||
|
||
if ( newKey != NULL ) {
|
||
RegCloseKey( newKey );
|
||
}
|
||
|
||
if ( error == NO_ERROR ) {
|
||
|
||
//
|
||
// Search the key and add value and key entries.
|
||
//
|
||
|
||
findHandle = NULL;
|
||
|
||
error = RegOpenKeyEx( HKEY_CURRENT_USER,
|
||
Path,
|
||
0,
|
||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
||
&findHandle );
|
||
if ( error == NO_ERROR ) {
|
||
|
||
//
|
||
// Enumerate the values and subkeys of the key, adding entries
|
||
// to the UserRun hive for each one.
|
||
//
|
||
|
||
enumContext.UserRunContext = Context;
|
||
enumContext.CurrentPath = Path;
|
||
error = EnumerateKey( findHandle,
|
||
&enumContext,
|
||
AddValueDuringAddKey,
|
||
AddKeyDuringAddKey );
|
||
|
||
RegCloseKey( findHandle );
|
||
}
|
||
}
|
||
|
||
return error;
|
||
|
||
} // AddKey
|
||
|
||
|
||
DWORD
|
||
AddValueDuringAddKey (
|
||
IN PVOID Context,
|
||
IN DWORD ValueNameLength,
|
||
IN PWCH ValueName,
|
||
IN DWORD ValueType,
|
||
IN PVOID ValueData,
|
||
IN DWORD ValueDataLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds a value entry to UserRun during AddKey.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to EnumerateKey.
|
||
|
||
ValueNameLength - length in characters of ValueName.
|
||
|
||
ValueName - pointer to name of the value.
|
||
|
||
ValueType - type of the value data.
|
||
|
||
ValueData - pointer to value data.
|
||
|
||
ValueDataLength - length in bytes of ValueData.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
PKEY_ENUM_CONTEXT context = Context;
|
||
|
||
//
|
||
// Add the value entry to UserRun.
|
||
//
|
||
|
||
return AddValue( context->UserRunContext,
|
||
context->CurrentPath,
|
||
ValueName,
|
||
ValueType,
|
||
ValueData,
|
||
ValueDataLength );
|
||
|
||
} // AddValueDuringAddKey
|
||
|
||
|
||
DWORD
|
||
AddKeyDuringAddKey (
|
||
IN PVOID Context,
|
||
IN DWORD KeyNameLength,
|
||
IN PWCH KeyName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds a key entry to UserRun during AddKey.
|
||
|
||
Arguments:
|
||
|
||
Context - context value passed to EnumerateKey.
|
||
|
||
KeyNameLength - length in characters of KeyName.
|
||
|
||
KeyName - pointer to name of the key.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
PKEY_ENUM_CONTEXT context = Context;
|
||
DWORD error;
|
||
|
||
//
|
||
// Append the key name to the path and call AddKey to do the
|
||
// recursive work.
|
||
//
|
||
|
||
wcscat( context->CurrentPath, TEXT("\\") );
|
||
wcscat( context->CurrentPath, KeyName );
|
||
error = AddKey( context->UserRunContext, context->CurrentPath );
|
||
|
||
//
|
||
// Remove the key name from the path.
|
||
//
|
||
|
||
*wcsrchr( context->CurrentPath, TEXT('\\') ) = 0;
|
||
|
||
return error;
|
||
|
||
} // AddKeyDuringAddKey
|
||
|
||
|
||
DWORD
|
||
AddValue (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN PWCH KeyName OPTIONAL,
|
||
IN PWCH ValueName,
|
||
IN DWORD ValueType,
|
||
IN PVOID ValueData,
|
||
IN DWORD ValueDataLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds an entry for a new value to UserRun.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
KeyName - pointer to name of the key containing the value.
|
||
|
||
ValueName - pointer to name of the value.
|
||
|
||
ValueType - type of the value data.
|
||
|
||
ValueData - pointer to value data.
|
||
|
||
ValueDataLength - length in bytes of ValueData.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
DWORD error;
|
||
DWORD dword;
|
||
|
||
//
|
||
// Create an entry key for the value and popuplate it.
|
||
//
|
||
|
||
newKey = NULL;
|
||
error = CreateUserRunKey( Context, FALSE, &newKey );
|
||
|
||
if ( error == NO_ERROR ) {
|
||
dword = 3;
|
||
error = RegSetValueEx( newKey, ACTION_VALUE, 0, REG_DWORD, (PBYTE)&dword, sizeof(DWORD) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, KEYNAME_VALUE, 0, REG_SZ, (PBYTE)KeyName, SZLEN(KeyName) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, VALUENAME_VALUE, 0, REG_SZ, (PBYTE)ValueName, SZLEN(ValueName) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, VALUE_VALUE, 0, ValueType, (PBYTE)ValueData, ValueDataLength );
|
||
}
|
||
|
||
if ( newKey != NULL ) {
|
||
RegCloseKey( newKey );
|
||
}
|
||
|
||
return error;
|
||
|
||
} // AddValue
|
||
|
||
|
||
DWORD
|
||
CreateUserRunSimpleFileKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN DWORD Action,
|
||
IN PWCH Name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates an entry under the Files key for the "simple" cases -- delete
|
||
directory, add file, delete file.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
Action - value to store in Action value of entry.
|
||
|
||
Name - pointer to name of the file or directory.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY newKey;
|
||
DWORD error;
|
||
|
||
//
|
||
// Create an entry key and popuplate it.
|
||
//
|
||
|
||
newKey = NULL;
|
||
error = CreateUserRunKey( Context, TRUE, &newKey );
|
||
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, ACTION_VALUE, 0, REG_DWORD, (PBYTE)&Action, sizeof(DWORD) );
|
||
}
|
||
if ( error == NO_ERROR ) {
|
||
error = RegSetValueEx( newKey, ITEM_VALUE, 0, REG_SZ, (PBYTE)Name, SZLEN(Name) );
|
||
}
|
||
|
||
if ( newKey != NULL ) {
|
||
RegCloseKey( newKey );
|
||
}
|
||
|
||
return error;
|
||
|
||
} // CreateUserRunSimpleFileKey
|
||
|
||
|
||
DWORD
|
||
CreateUserRunKey (
|
||
IN PUSERRUN_CONTEXT Context,
|
||
IN BOOL IsFileKey,
|
||
OUT PHKEY NewKeyHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates an indexed key in UserRun, under either the Files key or the
|
||
Hive key.
|
||
|
||
Arguments:
|
||
|
||
Context - pointer to context record.
|
||
|
||
IsFileKey - indicates whether to create the key under Files or Hive.
|
||
|
||
NewKeyHandle - returns the handle to the new key.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY parentKeyHandle;
|
||
DWORD index;
|
||
WCHAR keyName[11];
|
||
DWORD disposition;
|
||
|
||
//
|
||
// Get the handle to the parent key and the index for this entry.
|
||
//
|
||
|
||
if ( IsFileKey ) {
|
||
parentKeyHandle = Context->FilesKey;
|
||
index = ++Context->FilesIndex;
|
||
} else {
|
||
parentKeyHandle = Context->HiveKey;
|
||
index = ++Context->HiveIndex;
|
||
}
|
||
|
||
//
|
||
// Convert the index number into a string.
|
||
//
|
||
|
||
wsprintf( keyName, TEXT("%d"), index );
|
||
|
||
//
|
||
// Create the entry key.
|
||
//
|
||
|
||
return RegCreateKeyEx( parentKeyHandle,
|
||
keyName,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
NewKeyHandle,
|
||
&disposition );
|
||
|
||
} // CreateUserRunKey
|
||
|
||
|
||
DWORD
|
||
QueryValue (
|
||
IN PWCH KeyName OPTIONAL,
|
||
IN PWCH ValueName,
|
||
OUT PDWORD ValueType,
|
||
OUT PVOID *ValueData,
|
||
OUT PDWORD ValueDataLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Queries the data for a value.
|
||
|
||
Arguments:
|
||
|
||
KeyName - pointer to name of the key containing the value.
|
||
|
||
ValueName - pointer to name of the value.
|
||
|
||
ValueType - returns the type of the value data.
|
||
|
||
ValueData - returns a pointer to value data. This buffer must be
|
||
freed by the caller using MyFree.
|
||
|
||
ValueDataLength - length in bytes of ValueData.
|
||
|
||
Return Value:
|
||
|
||
DWORD - Win32 status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hkey;
|
||
DWORD disposition;
|
||
DWORD error;
|
||
|
||
//
|
||
// Open the parent key.
|
||
//
|
||
|
||
if ( (KeyName == NULL) || (wcslen(KeyName) == 0) ) {
|
||
hkey = HKEY_CURRENT_USER;
|
||
} else {
|
||
error = RegCreateKeyEx( HKEY_CURRENT_USER,
|
||
KeyName,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&hkey,
|
||
&disposition );
|
||
if ( error != ERROR_SUCCESS ) {
|
||
return error;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Query the value to get the length of its data.
|
||
//
|
||
|
||
*ValueDataLength = 0;
|
||
*ValueData = NULL;
|
||
error = RegQueryValueEx( hkey,
|
||
ValueName,
|
||
NULL,
|
||
ValueType,
|
||
NULL,
|
||
ValueDataLength );
|
||
|
||
//
|
||
// Allocate a buffer to hold the value data.
|
||
//
|
||
|
||
if ( error == NO_ERROR ) {
|
||
*ValueData = MyMalloc( *ValueDataLength );
|
||
if ( *ValueData == NULL ) {
|
||
error = ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Query the value again, this time retrieving the data.
|
||
//
|
||
|
||
if ( error == NO_ERROR ) {
|
||
error = RegQueryValueEx( hkey,
|
||
ValueName,
|
||
NULL,
|
||
ValueType,
|
||
*ValueData,
|
||
ValueDataLength );
|
||
if ( error != NO_ERROR ) {
|
||
MyFree( *ValueData );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Close the parent key.
|
||
//
|
||
|
||
if ( hkey != HKEY_CURRENT_USER ) {
|
||
RegCloseKey( hkey );
|
||
}
|
||
|
||
return error;
|
||
}
|
||
|
||
|
||
VOID
|
||
SzToMultiSz (
|
||
IN PWCH Sz,
|
||
OUT PWCH *MultiSz,
|
||
OUT PDWORD MultiSzLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates a MULTI_SZ version of a null-terminated string. Allocates
|
||
a buffer, copies the string to the buffer, and appends an additional
|
||
null terminator.
|
||
|
||
Arguments:
|
||
|
||
Sz - pointer to the string that is to be copied.
|
||
|
||
MultiSz - returns a pointer to the MULTI_SZ version of Sz. The caller
|
||
must free this buffer using MyFree. If the allocation fails,
|
||
MultiSz will be NULL.
|
||
|
||
MultiSzLength - returns the length in bytes of MultiSz, including the
|
||
null terminators.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD szlen;
|
||
|
||
//
|
||
// Get the length of the input string and calculate the MULTI_SZ length.
|
||
//
|
||
|
||
szlen = wcslen(Sz);
|
||
*MultiSzLength = (szlen + 1 + 1) * sizeof(WCHAR);
|
||
|
||
//
|
||
// Allocate the MULTI_SZ buffer, copy the input string, and append
|
||
// an additional null.
|
||
//
|
||
|
||
*MultiSz = MyMalloc( *MultiSzLength );
|
||
if ( *MultiSz != NULL ) {
|
||
wcscpy( *MultiSz, Sz );
|
||
(*MultiSz)[szlen+1] = 0;
|
||
}
|
||
|
||
return;
|
||
}
|