windows-nt/Source/XPSP1/NT/admin/pchealth/sr/nttest/srdiag/main.cpp
2020-09-26 16:20:57 +08:00

500 lines
16 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: Main.cpp
//
// Contents: Main wrapper file for SRDiag, this will call into cab.cpp,
// chglog.cpp, getreg.cpp, rpenum.cpp for getting changlog,
// restore points, registry information. This file also contains
// routines for getting file information, restore Guid, and generic
// logging imposed by cab.cpp
//
// Objects:
//
// Coupling:
//
// Notes:
//
// History: 9/21/00 SHeffner Created
// 10/5/00 SHeffner Moved file specific gathering to the header file.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Common Includes
//
//----------------------------------------------------------------------------
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <cab.h>
#include <main.h>
#include <dbgtrace.h>
#include <winver.h>
#include "srrpcapi.h"
//+---------------------------------------------------------------------------
//
// Function proto typing for rpenum.cpp, getreg.cpp, Chglog.cpp
//
//----------------------------------------------------------------------------
bool GetSRRegistry(char *szFilename, WCHAR *szPath, bool bRecurse);
void GetChgLog(char *szLogfile);
void RPEnumDrive(HFCI hc, char *szLogFile);
//+---------------------------------------------------------------------------
//
// Global Variables used within main, and through cab.cpp
//
//----------------------------------------------------------------------------
FILE *fLogStream = NULL; //For the Log, and Log2 routines
extern char g_szCabFileLocation[_MAX_PATH]; //This is actually defined in cab.cpp
extern char g_szCabFileName[_MAX_PATH]; //This is actually defined in cab.cpp
void __cdecl main(int argc, char *argv[])
{
HFCI hc = NULL;
int i=0;
bool bResult=false;
char szString[_MAX_PATH], szRestoreDirPath[_MAX_PATH];
char *szTest[1], *szArgCmd[200];
//Process any commandline arguments
memset(szArgCmd, 0, sizeof(char)*200); //Clean up before relying on this DS.
ArgParse(argc, argv, szArgCmd);
//Open up the log file, and start logging all activity
strcpy(szString, getenv("TEMP"));
strcat(szString, "\\SRDIAG.LOG");
fLogStream = fopen(szString, "w");
//Create a cab, if we fail then just skip,
// else gather all of the relevant files required.
if (NULL != (hc = create_cab()) )
{
//First add in any files that were specified on the command line, but first figuring out
// how many were really specified
for(i=0;i<200;i++) if(NULL == szArgCmd[i]) break;
bResult = test_fci(hc, i, szArgCmd, "");
//Get the Temp Location, ensure we have a new file, then
// get the registry keys, and dump into our text file
strcpy(szString, getenv("TEMP"));
strcat(szString, "\\SR-Reg.txt");
DeleteFileA(szString);
i = 0;
while (NULL != *wszRegKeys[i][0]) {
if(0 == wcscmp(wszRegKeys[i][1], TEXT("0")))
GetSRRegistry(szString, wszRegKeys[i][0], false);
else
GetSRRegistry(szString, wszRegKeys[i][0], true);
i++;
}
//Add the log to the Cab, and clean up
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
DeleteFileA(szString);
//Add files Bases on WinDir relative root
i = 0;
while (NULL != *szWindirFileCollection[i]) {
strcpy(szString, getenv("WINDIR"));
strcat(szString, szWindirFileCollection[i]);
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
i++;
}
//Get the restore directory on the system drive, and then Add in critial files
GetRestoreGuid(szString);
sprintf(szRestoreDirPath, "%s\\System Volume Information\\_Restore%s\\", getenv("SYSTEMDRIVE"), szString );
//Add files Bases on System Volume Information relative root
i = 0;
while (NULL != *szSysVolFileCollection[i]) {
strcpy(szString, szRestoreDirPath);
strcat(szString, szSysVolFileCollection[i]);
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
i++;
}
//Get the Restore point enumeration, and then cab the file
strcpy(szString, getenv("TEMP"));
strcat(szString, "\\SR-RP.LOG");
RPEnumDrive(hc, szString);
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
DeleteFileA(szString);
//Get the ChangeLog enumeration, and then cab and delete the file
//first we need to switch the log, then gather the log
SRSwitchLog();
strcpy(szString, getenv("TEMP"));
strcat(szString, "\\SR-CHGLog.LOG");
GetChgLog(szString);
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
DeleteFileA(szString);
//Get the fileversion info for each of the Files
strcpy(szString, getenv("TEMP"));
strcat(szString, "\\SR-FileList.LOG");
SRGetFileInfo(szString);
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
DeleteFileA(szString);
//Close out logging, and add the log to the cab
// (THIS SHOULD BE THE LAST THING WE ARE DOING!!)
fclose(fLogStream);
fLogStream = NULL;
strcpy(szString, getenv("TEMP"));
strcat(szString, "\\SRDIAG.LOG");
szTest[0] = szString;
bResult = test_fci(hc, 1, szTest, "");
DeleteFileA(szString);
}
//Completes cab file under construction
if (flush_cab(hc))
{
Log("Cabbing Process was Sucessful");
}
else
{
Log("Cabbing Process has failed");
}
}
//+---------------------------------------------------------------------------
//
// Function: Log
//
// Synopsis: Will print a String to both our log file, and also the console
//
// Arguments: [szString] -- Simple ANSI string to log
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void Log(char *szString)
{
if( NULL != fLogStream)
fprintf(fLogStream, "%s\n", szString);
puts(szString);
}
//+---------------------------------------------------------------------------
//
// Function: Log2
//
// Synopsis: Takes two strings, and will print them back to back to both the
// log file, and also to the console
//
// Arguments: [szString] -- Simple ANSI string to log
// [szString2] -- Simple ANSI string to log
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void Log2(char *szString, char *szString2)
{
if( NULL != fLogStream)
fprintf(fLogStream,"%s %s\n", szString, szString2);
printf("%s %s\n", szString, szString2);
}
//+---------------------------------------------------------------------------
//
// Function: GetRestoreGuid
//
// Synopsis: Will retrieve from the registry what the GUID is for the current
// Restore directory, and return this in the string pointer passed
// to the function.
//
// Arguments: [szString] -- Simple ANSI string to receive the string
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void GetRestoreGuid(char *szString)
{
long lResult;
HKEY mHkey;
DWORD dwType, dwLength;
lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SystemRestore\\Cfg", 0, KEY_READ, &mHkey);
dwLength = _MAX_PATH +1;
lResult = RegQueryValueExA(mHkey, "MachineGuid", NULL, &dwType, (unsigned char *)szString, &dwLength);
}
//+---------------------------------------------------------------------------
//
// Function: SRGetFileInfo
//
// Synopsis: This is the wrapper function for InfoPerFile, where I will assemble
// the file path for each of the relevant files that we need to get
// file statistics.
//
// Arguments: [szLogFile] -- The path to the file that I will log this information to.
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void SRGetFileInfo(char *szLogFile)
{
int iCount;
WCHAR szString[_MAX_PATH];
//Initialize counter, and walk through the filelist that we have
iCount = 0;
while(NULL != *wszFileVersionList[iCount])
{
//Assemble the path, since I just have the relative path from windir
wcscpy(szString, _wgetenv(L"WINDIR"));
wcscat(szString, wszFileVersionList[iCount]);
//Call function to do the work since we have full path, and log file name
InfoPerFile(szLogFile, szString);
iCount++;
}
}
//+---------------------------------------------------------------------------
//
// Function: InfoPerFile
//
// Synopsis: This function takes the log file path, and the filename, and then
// will put out the relevant information from the file to be logged.
//
//
// Arguments: [szLogFile] -- The path to the file that I will log this information to.
// [szFileName] -- The full path, and name of the file to get the information for.
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void InfoPerFile(char *szLogFile, WCHAR *szFileName)
{
BY_HANDLE_FILE_INFORMATION finfo;
SYSTEMTIME st;
HANDLE handle;
FILE *fStream;
WCHAR szString[_MAX_PATH];
VOID *pBuffer;
VS_FIXEDFILEINFO FixedFileInfo;
UINT uLen;
DWORD dSize, dResult, i;
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
WCHAR *szMonth[] = { L"January", L"Feburary", L"March", L"April", L"May", L"June", L"July", L"August", L"September", L"October", L"November", L"December" };
WCHAR *szDay[] = {L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday", L"Friday", L"Saturday" };
if ( NULL == *szFileName) return;
//Open up our log file, and log the file we are processing
fStream = fopen(szLogFile, "a");
if( NULL == fStream) return; //if we have an invalid handle just return back.
fprintf(fStream, "\n%S\n", szFileName);
//Open up the file so that we can get the information from the handle
// If we are unable to do this we will just log the generic not able to find file.
if( INVALID_HANDLE_VALUE != (handle = CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) )
{
if (FALSE != GetFileInformationByHandle(handle, &finfo))
{
//FileCreation
FileTimeToSystemTime( &finfo.ftCreationTime, &st);
fprintf(fStream, "\tCreation Date=%S %S %lu, %lu %lu:%lu:%lu\n",
szDay[st.wDayOfWeek],szMonth[st.wMonth-1],st.wDay,st.wYear,st.wHour,st.wMinute,st.wSecond);
//FileLastAccess
FileTimeToSystemTime( &finfo.ftLastAccessTime, &st);
fprintf(fStream, "\tLast Access Date=%S %S %lu, %lu %lu:%lu:%lu\n",
szDay[st.wDayOfWeek],szMonth[st.wMonth-1],st.wDay,st.wYear,st.wHour,st.wMinute,st.wSecond);
//FileLastWrite
FileTimeToSystemTime( &finfo.ftLastWriteTime, &st);
fprintf(fStream, "\tLast Write Date=%S %S %lu, %lu %lu:%lu:%lu\n",
szDay[st.wDayOfWeek],szMonth[st.wMonth-1],st.wDay,st.wYear,st.wHour,st.wMinute,st.wSecond);
//File Attributes
wcscpy(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? L"ARCHIVE " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ? L"COMPRESSED " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? L"DIRECTORY " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED ? L"ENCRYPTED " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? L"HIDDEN " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? L"NORMAL " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE ? L"OFFLINE " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? L"READONLY " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? L"REPARSE_POINT " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? L"SPARSE_FILE " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? L"SYSTEM " : L"");
wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ? L"TEMPORARY " : L"");
fprintf(fStream, "\tAttributes=%S\n", szString);
//Get the VolumeSerialNumber, FileSize, and Number of Links
fprintf(fStream, "\tVolumeSerialNumber=%lu\n", finfo.dwVolumeSerialNumber);
fprintf(fStream, "\tFileSize=%lu%lu\n", finfo.nFileSizeHigh, finfo.nFileSizeLow);
fprintf(fStream, "\tNumberOfLinks=%lu\n", finfo.nNumberOfLinks);
if( 0 != (dSize = GetFileVersionInfoSize(szFileName, &dResult)) )
{
if( NULL != (pBuffer = malloc(dSize)) )
{
GetFileVersionInfo(szFileName, dResult, dSize, (LPVOID) pBuffer);
// Read the list of languages and code pages.
VerQueryValue(pBuffer,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID*)&lpTranslate,
&uLen);
// Read the Version info for each language and code page.
for( i=0; i < (uLen/sizeof(struct LANGANDCODEPAGE)); i++ )
{
char *lpBuffer;
DWORD dwBytes, dwCount = 0;
fprintf(fStream, "\tLanguage=%x%x\n", lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
while (NULL != *wszVersionResource[dwCount] )
{
//Generate the string, for getting the resource based on the language, then
// retrieve this, and then put it to the log file.
wsprintf( szString, L"\\StringFileInfo\\%04x%04x\\%s",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage,
wszVersionResource[dwCount]);
VerQueryValue(pBuffer,
szString,
(LPVOID *) &lpBuffer,
&uLen);
if( 0 != uLen )
fprintf(fStream, "\t%S=%S\n", wszVersionResource[dwCount], lpBuffer);
dwCount++;
} //While loop end, for each resource
} //for loop end for each language
//Clean up the allocated memory
free(pBuffer);
} //If check for getting memory
} //If check for getting the fileversioninfosize
} //if check for GetFileInformationByHandle on the file
CloseHandle(handle);
} //if check on can I open this file
//Cleanup
fclose(fStream);
}
//+---------------------------------------------------------------------------
//
// Function: ArgParse
//
// Synopsis: This function simply looks for the key word parameters, and will build
// an array pointing to each of the files that we want to include in the cab
// in addition to the normal files.
//
//
// Arguments: [argc] -- Count of the number of arguments
// [argv] -- Array of the arguments.
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void ArgParse(int argc, char *argv[], char *szArgCmd[])
{
int iCount, iWalk;
//If no command line specified then just do the normal cabbing, with core files
if(1 == argc)
return;
//walk through each of the arguments, and check to see if its a help, file, cabname, cabloc, or a ?
for(iCount = 1; iCount < argc; iCount++)
{
if( 0 == _strnicoll(&argv[iCount][1], "?", strlen("?")) )
Usage();
if( 0 == _strnicoll(&argv[iCount][1], "help", strlen("help")) )
Usage();
if( 0 == _strnicoll(&argv[iCount][1], "cabname", strlen("cabname")) )
strcpy(g_szCabFileName, (strstr(argv[iCount], ":") + 1));
if( 0 == _strnicoll(&argv[iCount][1], "cabloc", strlen("cabloc")) )
strcpy(g_szCabFileLocation, (strstr(argv[iCount], ":") + 1));
if( 0 == _strnicoll(&argv[iCount][1], "file", strlen("file")) )
{
//find the first spot where I can put the pointer to this filename
for( iWalk=0; iWalk < 200; iWalk++)
{
if( NULL == szArgCmd[iWalk] )
{
szArgCmd[iWalk] = strstr(argv[iCount], ":") + 1;
break;
}
} //end for loop, walking through DS
} //end of if for is this an added file
} //end of for loop walking through all of the arguments
}
//+---------------------------------------------------------------------------
//
// Function: Usage
//
// Synopsis: Displaies the command line usage
//
//
// Arguments:
//
// Returns: void
//
// History: 9/21/00 SHeffner Created
//
//
//----------------------------------------------------------------------------
void Usage()
{
printf("Usage: SrDiag [/Cabname:test.cab] [/Cabloc:\"c:\\temp\\\"] [/file:\"c:\\boot.ini\"]\n");
printf(" /cabloc is pointing to the location to store the cab, this should have a \\ on the end\n");
printf(" /cabname is the full name of the cab file that you wish to use. \n");
printf(" /file is the name and path of a file that you wish to add to the cab, this can be used many times\n");
exit(0);
}