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

423 lines
9.3 KiB
C

/*
5/06/99 AndrewR Created.
*/
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <shellapi.h>
#if DBG
VOID
RtlAssert(
PVOID FailedAssertion,
PVOID FileName,
ULONG LineNumber,
PCHAR Message
);
#define ASSERT( exp ) \
if (!(exp)) \
RtlAssert( #exp, __FILE__, __LINE__, NULL )
#else
#define ASSERT( exp )
#endif // DBG
void PrintUsage(void) {
printf("retrieves information about a hive\n");
printf("\n");
printf("Usage: checkhiv -h HiveName -t TimeBomb -s Suite -p ProcCount -u Upgrade only\n");
return;
}
BOOL
FileExists(
IN PCTSTR FileName,
OUT PWIN32_FIND_DATA FindData OPTIONAL
)
/*++
Routine Description:
Determine if a file exists and is accessible.
Errormode is set (and then restored) so the user will not see
any pop-ups.
Arguments:
FileName - supplies full path of file to check for existance.
FindData - if specified, receives find data for the file.
Return Value:
TRUE if the file exists and is accessible.
FALSE if not. GetLastError() returns extended error info.
--*/
{
WIN32_FIND_DATA findData;
HANDLE FindHandle;
UINT OldMode;
DWORD Error;
OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
FindHandle = FindFirstFile(FileName,&findData);
if(FindHandle == INVALID_HANDLE_VALUE) {
Error = GetLastError();
} else {
FindClose(FindHandle);
if(FindData) {
*FindData = findData;
}
Error = NO_ERROR;
}
SetErrorMode(OldMode);
SetLastError(Error);
return (Error == NO_ERROR);
}
BOOLEAN
AdjustPrivilege(
PCTSTR Privilege
)
/*++
Routine Description:
This routine tries to adjust the priviliege of the current process.
Arguments:
Privilege - String with the name of the privilege to be adjusted.
Return Value:
Returns TRUE if the privilege could be adjusted.
Returns FALSE, otherwise.
--*/
{
HANDLE TokenHandle;
LUID_AND_ATTRIBUTES LuidAndAttributes;
TOKEN_PRIVILEGES TokenPrivileges;
if( !OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&TokenHandle ) ) {
return( FALSE );
}
if( !LookupPrivilegeValue( NULL,
Privilege,
&( LuidAndAttributes.Luid ) ) ) {
return( FALSE );
}
LuidAndAttributes.Attributes = SE_PRIVILEGE_ENABLED;
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0] = LuidAndAttributes;
if( !AdjustTokenPrivileges( TokenHandle,
FALSE,
&TokenPrivileges,
0,
NULL,
NULL ) ) {
return( FALSE );
}
if( GetLastError() != NO_ERROR ) {
return( FALSE );
}
return( TRUE );
}
BOOL
GetHiveData(
IN PCTSTR OriginalHiveName,
OUT PDWORD SuiteMask,
OUT PDWORD TimeBomb,
OUT PDWORD ProcCount,
OUT PBOOL StepUp
)
{
TCHAR HiveTarget[MAX_PATH];
TCHAR HiveName[MAX_PATH] = TEXT("xSETREG");
TCHAR lpszSetupReg[MAX_PATH] = TEXT("xSETREG\\ControlSet001\\Services\\setupdd");
TCHAR TargetPath[MAX_PATH];
LONG rslt;
HKEY hKey;
DWORD Type;
DWORD Buffer[4];
DWORD BufferSize = sizeof(Buffer);
DWORD tmp,i;
BOOL RetVal = FALSE;
TCHAR Dbg[1000];
ASSERT(OriginalHiveName && SuiteMask && TimeBomb && ProcCount && StepUp);
*SuiteMask = 0;
*TimeBomb = 0;
*ProcCount = 0;
*StepUp = FALSE;
//
// copy the hive locally since you can only have one open on a hive at a time
//
GetTempPath(MAX_PATH,TargetPath);
GetTempFileName(TargetPath,TEXT("set"),0,HiveTarget);
CopyFile(OriginalHiveName,HiveTarget,FALSE);
SetFileAttributes(HiveTarget,FILE_ATTRIBUTE_NORMAL);
//
// try to unload this first in case we faulted or something and the key is still loaded
//
RegUnLoadKey( HKEY_LOCAL_MACHINE, HiveName );
//
// need SE_RESTORE_NAME priviledge to call this API!
//
AdjustPrivilege((PWSTR)SE_RESTORE_NAME);
rslt = RegLoadKey( HKEY_LOCAL_MACHINE, HiveName, HiveTarget );
if (rslt != ERROR_SUCCESS) {
#ifdef DBG
wsprintf( Dbg, TEXT("Couldn't RegLoadKey, ec = %d\n"), rslt );
OutputDebugString(Dbg);
#endif
goto e1;
}
rslt = RegOpenKey(HKEY_LOCAL_MACHINE,lpszSetupReg,&hKey);
if (rslt != ERROR_SUCCESS) {
#ifdef DBG
OutputDebugString(TEXT("Couldn't RegOpenKey\n"));
#endif
goto e2;
}
rslt = RegQueryValueEx(hKey, NULL, NULL, &Type, (LPBYTE) Buffer, &BufferSize);
if (rslt != ERROR_SUCCESS || Type != REG_BINARY) {
#ifdef DBG
OutputDebugString(TEXT("Couldn't RegQueryValueEx\n"));
#endif
goto e3;
}
*TimeBomb = Buffer[0];
*StepUp = (BOOL)Buffer[1];
*ProcCount = Buffer[2];
*SuiteMask = Buffer[3];
RetVal = TRUE;
e3:
RegCloseKey( hKey );
e2:
RegUnLoadKey( HKEY_LOCAL_MACHINE, HiveName );
e1:
if (GetFileAttributes(HiveTarget) != 0xFFFFFFFF) {
SetFileAttributes(HiveTarget,FILE_ATTRIBUTE_NORMAL);
DeleteFile(HiveTarget);
}
return(RetVal);
}
int _cdecl
main(
int argc,
char *argvA[]
)
{
PTSTR *argv;
PTSTR HiveName = NULL;
PTSTR TimeBombString = NULL;
PTSTR SuiteString = NULL;
PTSTR ProcCountString = NULL;
PTSTR UpgradeOnlyString = NULL;
TCHAR TempFile[MAX_PATH];
PTSTR p;
DWORD SuiteMask;
DWORD TimeBomb;
DWORD ProcCount;
BOOL Upgrade;
DWORD Result = 0;
DWORD ActualSuiteMask, ActualTimeBomb, ActualProcCount;
BOOL ActualStepUp;
// do commandline stuff
#ifdef UNICODE
argv = CommandLineToArgvW( GetCommandLine(), &argc );
#else
argv = argvA;
#endif
//
// parse args
//
while (--argc) {
argv++;
if ((argv[0][0] == TEXT('-')) || (argv[0][0] == TEXT('/'))) {
switch (argv[0][1]) {
case TEXT('h'):
case TEXT('H'):
HiveName = argv[1];
goto Next;
break;
case TEXT('p'):
case TEXT('P'):
ProcCountString = argv[1];
goto Next;
break;
case TEXT('s'):
case TEXT('S'):
SuiteString = argv[1];
goto Next;
break;
case TEXT('t'):
case TEXT('T'):
TimeBombString = argv[1];
goto Next;
break;
case TEXT('u'):
case TEXT('U'):
UpgradeOnlyString = argv[1];
goto Next;
break;
default:
PrintUsage();
return ERROR_INVALID_PARAMETER;
}
}
Next:
;
}
//
// Validate parameters
//
if (!HiveName || (!ProcCountString && !SuiteString && !TimeBombString && !UpgradeOnlyString)) {
printf("Invalid usage\n" );
PrintUsage();
return ERROR_INVALID_PARAMETER;
}
GetFullPathName(HiveName,sizeof(TempFile)/sizeof(TCHAR),TempFile,&p);
if (!FileExists(TempFile,NULL)) {
printf("Could not find hive file %S\n", TempFile );
PrintUsage();
return ERROR_FILE_NOT_FOUND;
}
HiveName = TempFile;
//
// retrieve hive information
//
if (!GetHiveData(HiveName,
&ActualSuiteMask,
&ActualTimeBomb,
&ActualProcCount,
&ActualStepUp
)) {
printf("Could not retrive information from hive\n" );
return ERROR_INVALID_DATA;
}
//marrq result was init to 1, changed to 0
Result = 0;
if (UpgradeOnlyString) {
Upgrade = !lstrcmpi(UpgradeOnlyString,L"TRUE");
if (Upgrade != ActualStepUp) {
printf("Upgrade only inconsistent --> hive says Upgrade = %s\n", ActualStepUp ? "TRUE" : "FALSE");
Result = ERROR_INVALID_DATA;
}
}
if (ProcCountString) {
ProcCount = _ttoi(ProcCountString);
if (ProcCount != ActualProcCount) {
printf("Proc count inconsistent --> hive says Proc count = %d\n", ActualProcCount);
Result = ERROR_INVALID_DATA;
}
}
if (SuiteString) {
SuiteMask = _ttoi(SuiteString);
if (SuiteMask != ActualSuiteMask) {
printf("Suite mask inconsistent --> hive says suite mask = %d\n", ActualSuiteMask);
Result = ERROR_INVALID_DATA;
}
}
if (TimeBombString) {
TimeBomb = _ttoi(TimeBombString);
//
// convert to minutes
//
TimeBomb = TimeBomb * 60 * 24;
if (TimeBomb != ActualTimeBomb) {
printf("Time bomb inconsistent --> hive says Time bomb = %d days\n", (ActualTimeBomb / (60*24)));
Result = ERROR_INVALID_DATA;
}
}
//marrq this was checking for 1, changed to 0
if (Result == 0) {
printf("Hive is valid.\n");
} else {
printf("One or more inconsistencies detected in hive.\n");
}
return Result;
}