1003 lines
29 KiB
C
1003 lines
29 KiB
C
|
//
|
||
|
// SIGVERIF.C
|
||
|
//
|
||
|
#define SIGVERIF_DOT_C
|
||
|
#include "sigverif.h"
|
||
|
|
||
|
// Allocate our global data structure
|
||
|
GAPPDATA g_App;
|
||
|
|
||
|
//
|
||
|
// Load a resource string into a buffer that is assumed to be MAX_PATH bytes.
|
||
|
//
|
||
|
void
|
||
|
MyLoadString(
|
||
|
LPTSTR lpString,
|
||
|
ULONG CchStringSize,
|
||
|
UINT uId
|
||
|
)
|
||
|
{
|
||
|
LoadString(g_App.hInstance, uId, lpString, CchStringSize);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Pop an OK messagebox with a specific string
|
||
|
//
|
||
|
void
|
||
|
MyMessageBox(
|
||
|
LPTSTR lpString
|
||
|
)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_MSGBOX);
|
||
|
MessageBox(g_App.hDlg, lpString, szBuffer, MB_OK);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Pop an OK messagebox with a resource string ID
|
||
|
//
|
||
|
void
|
||
|
MyMessageBoxId(
|
||
|
UINT uId
|
||
|
)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
|
||
|
MyLoadString(szBuffer, cA(szBuffer), uId);
|
||
|
MyMessageBox(szBuffer);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Pop an error messagebox with a specific string
|
||
|
//
|
||
|
void
|
||
|
MyErrorBox(
|
||
|
LPTSTR lpString
|
||
|
)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_ERRORBOX);
|
||
|
MessageBox(g_App.hDlg, lpString, szBuffer, MB_OK);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Pop an error messagebox with a resource string ID
|
||
|
//
|
||
|
void
|
||
|
MyErrorBoxId(
|
||
|
UINT uId
|
||
|
)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
|
||
|
MyLoadString(szBuffer, cA(szBuffer), uId);
|
||
|
MyErrorBox(szBuffer);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
MyErrorBoxIdWithErrorCode(
|
||
|
UINT uId,
|
||
|
DWORD ErrorCode
|
||
|
)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
ULONG cchSize;
|
||
|
HRESULT hr;
|
||
|
PTSTR errorMessage = NULL;
|
||
|
LPVOID lpLastError = NULL;
|
||
|
|
||
|
//
|
||
|
// Get the error text for the error code.
|
||
|
//
|
||
|
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
NULL,
|
||
|
ErrorCode,
|
||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||
|
(LPTSTR)&lpLastError,
|
||
|
0,
|
||
|
NULL) != 0) {
|
||
|
|
||
|
if (lpLastError) {
|
||
|
|
||
|
MyLoadString(szBuffer, cA(szBuffer), uId);
|
||
|
|
||
|
cchSize = lstrlen(szBuffer) + lstrlen(lpLastError) + 1;
|
||
|
|
||
|
errorMessage = MALLOC(cchSize * sizeof(TCHAR));
|
||
|
|
||
|
if (errorMessage) {
|
||
|
|
||
|
hr = StringCchCopy(errorMessage, cchSize, szBuffer);
|
||
|
|
||
|
if (SUCCEEDED(hr)) {
|
||
|
hr = StringCchCat(errorMessage, cchSize, lpLastError);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We want to show the error message, even if the
|
||
|
// buffer was truncated.
|
||
|
//
|
||
|
if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) {
|
||
|
MyMessageBox(errorMessage);
|
||
|
}
|
||
|
|
||
|
FREE(errorMessage);
|
||
|
}
|
||
|
|
||
|
LocalFree(lpLastError);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Since Multi-User Windows will give me back a Profile directory, I need to get the real Windows directory
|
||
|
// Dlg_OnInitDialog initializes g_App.szWinDir with the real Windows directory, so I just use that.
|
||
|
//
|
||
|
UINT
|
||
|
MyGetWindowsDirectory(
|
||
|
LPTSTR lpDirName,
|
||
|
UINT DirNameCchSize
|
||
|
)
|
||
|
{
|
||
|
UINT uRet = 0;
|
||
|
|
||
|
if (lpDirName) {
|
||
|
|
||
|
if (SUCCEEDED(StringCchCopy(lpDirName, DirNameCchSize, g_App.szWinDir))) {
|
||
|
uRet = lstrlen(lpDirName);
|
||
|
} else {
|
||
|
//
|
||
|
// If the directory name can't fit in the buffer that the caller
|
||
|
// provided, then set it to 0 (if they provided a buffer of at
|
||
|
// least size 1) since we don't want to return a truncated
|
||
|
// directory to the caller.
|
||
|
//
|
||
|
if (DirNameCchSize > 0) {
|
||
|
*lpDirName = 0;
|
||
|
}
|
||
|
|
||
|
uRet = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return uRet;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialization of main dialog.
|
||
|
//
|
||
|
BOOL
|
||
|
Dlg_OnInitDialog(
|
||
|
HWND hwnd
|
||
|
)
|
||
|
{
|
||
|
DWORD Err = ERROR_SUCCESS;
|
||
|
HKEY hKey;
|
||
|
LONG lRes;
|
||
|
DWORD dwType, dwFlags, cbData;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
LPTSTR lpCommandLine, lpStart, lpEnd;
|
||
|
ULONG cchSize;
|
||
|
|
||
|
//
|
||
|
// Initialize global hDlg to current hwnd.
|
||
|
//
|
||
|
g_App.hDlg = hwnd;
|
||
|
|
||
|
//
|
||
|
// Set the window class to have the icon in the resource file
|
||
|
//
|
||
|
if (g_App.hIcon) {
|
||
|
SetClassLongPtr(hwnd, GCLP_HICON, (LONG_PTR) g_App.hIcon);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure the IDC_STATUS control is hidden until something happens.
|
||
|
//
|
||
|
ShowWindow(GetDlgItem(g_App.hDlg, IDC_STATUS), SW_HIDE);
|
||
|
|
||
|
//
|
||
|
// Set the range for the custom progress bar to 0-100.
|
||
|
//
|
||
|
SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETRANGE, (WPARAM) 0, (LPARAM) MAKELPARAM(0, 100));
|
||
|
|
||
|
//
|
||
|
// Set the global lpLogName to the one that's given in the resource file
|
||
|
//
|
||
|
MyLoadString(g_App.szLogFile, cA(g_App.szLogFile), IDS_LOGNAME);
|
||
|
|
||
|
//
|
||
|
// Figure out what the real Windows directory is and store it in g_App.szWinDir
|
||
|
// This is required because Hydra makes GetWindowsDirectory return a PROFILE directory
|
||
|
//
|
||
|
// We store the original CurrentDirectory in szBuffer so we can restore it after this hack.
|
||
|
// Next we switch into the SYSTEM/SYSTEM32 directory and then into its parent directory.
|
||
|
// This is what we want to store in g_App.szWinDir.
|
||
|
//
|
||
|
GetCurrentDirectory(cA(szBuffer), szBuffer);
|
||
|
GetSystemDirectory(g_App.szWinDir, cA(g_App.szWinDir));
|
||
|
SetCurrentDirectory(g_App.szWinDir);
|
||
|
SetCurrentDirectory(TEXT(".."));
|
||
|
GetCurrentDirectory(cA(g_App.szWinDir), g_App.szWinDir);
|
||
|
SetCurrentDirectory(szBuffer);
|
||
|
|
||
|
//
|
||
|
// Set the global search folder to %WinDir%
|
||
|
//
|
||
|
MyGetWindowsDirectory(g_App.szScanPath, cA(g_App.szScanPath));
|
||
|
|
||
|
//
|
||
|
// Set the global search pattern to "*.*"
|
||
|
//
|
||
|
MyLoadString(g_App.szScanPattern, cA(g_App.szScanPattern), IDS_ALL);
|
||
|
|
||
|
//
|
||
|
// Reset the progress bar back to zero percent
|
||
|
//
|
||
|
SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM) 0, (LPARAM) 0);
|
||
|
|
||
|
//
|
||
|
// By default, we want to turn logging and set the logging mode to OVERWRITE
|
||
|
//
|
||
|
g_App.bLoggingEnabled = TRUE;
|
||
|
g_App.bOverwrite = TRUE;
|
||
|
|
||
|
//
|
||
|
// Look in the registry for any settings from the last SigVerif session
|
||
|
//
|
||
|
lRes = RegOpenKeyEx(HKEY_CURRENT_USER,
|
||
|
SIGVERIF_KEY,
|
||
|
0,
|
||
|
KEY_READ,
|
||
|
&hKey);
|
||
|
|
||
|
if (lRes == ERROR_SUCCESS) {
|
||
|
|
||
|
cbData = sizeof(DWORD);
|
||
|
lRes = RegQueryValueEx( hKey,
|
||
|
SIGVERIF_FLAGS,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) &dwFlags,
|
||
|
&cbData);
|
||
|
if (lRes == ERROR_SUCCESS) {
|
||
|
|
||
|
g_App.bLoggingEnabled = (dwFlags & 0x1);
|
||
|
g_App.bOverwrite = (dwFlags & 0x2);
|
||
|
}
|
||
|
|
||
|
cbData = sizeof(szBuffer);
|
||
|
lRes = RegQueryValueEx( hKey,
|
||
|
SIGVERIF_LOGNAME,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) szBuffer,
|
||
|
&cbData);
|
||
|
if (lRes == ERROR_SUCCESS && dwType == REG_SZ) {
|
||
|
//
|
||
|
// This should never happen unless the code is changed
|
||
|
// so that szBuffer is larger then g_App.szLogFile, but
|
||
|
// for safety if we can't copy szBuffer fully into
|
||
|
// g_App.szLogFile, then set g_App.szLogFile to 0 so we
|
||
|
// don't log to a truncated location.
|
||
|
//
|
||
|
if (FAILED(StringCchCopy(g_App.szLogFile, cA(g_App.szLogFile), szBuffer))) {
|
||
|
g_App.szLogFile[0] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the user specified the LOGDIR flag, we want to create the log
|
||
|
// file in that directory.
|
||
|
//
|
||
|
//
|
||
|
// SECURITY: Verify that LOGDIR exists and the user has the correct access
|
||
|
// to it, and if they don't then fail up front.
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_LOGDIR);
|
||
|
if (SUCCEEDED(StringCchCat(szBuffer, cA(szBuffer), TEXT(":"))) &&
|
||
|
((lpStart = MyStrStr(GetCommandLine(), szBuffer)) != NULL)) {
|
||
|
|
||
|
lpStart += lstrlen(szBuffer);
|
||
|
|
||
|
if (lpStart && *lpStart) {
|
||
|
//
|
||
|
// The string in lpStart is the directory that we want to log
|
||
|
// into.
|
||
|
//
|
||
|
cchSize = lstrlen(lpStart) + 1;
|
||
|
lpCommandLine = MALLOC(cchSize * sizeof(TCHAR));
|
||
|
|
||
|
if (lpCommandLine) {
|
||
|
|
||
|
if (SUCCEEDED(StringCchCopy(lpCommandLine, cchSize, lpStart))) {
|
||
|
|
||
|
lpStart = lpCommandLine;
|
||
|
|
||
|
//
|
||
|
// First skip any white space.
|
||
|
//
|
||
|
|
||
|
while (*lpStart && (isspace(*lpStart))) {
|
||
|
|
||
|
lpStart++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We will deal with two cases, one where the path
|
||
|
// starts with a quote, and the other where it does
|
||
|
// not.
|
||
|
//
|
||
|
if (*lpStart) {
|
||
|
|
||
|
if (*lpStart == TEXT('\"')) {
|
||
|
//
|
||
|
// The log path starts with a quote. This means that
|
||
|
// we will use all of the string until we either hit
|
||
|
// the end of the string, or we find another quote.
|
||
|
//
|
||
|
lpStart++;
|
||
|
|
||
|
lpEnd = lpStart;
|
||
|
|
||
|
while (*lpEnd && (*lpEnd != TEXT('\"'))) {
|
||
|
|
||
|
lpEnd++;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// The log path does NOT start with a quote, so
|
||
|
// use the characters until we come to the end
|
||
|
// of the string or a space.
|
||
|
//
|
||
|
lpEnd = lpStart;
|
||
|
|
||
|
while (*lpEnd && (isspace(*lpEnd))) {
|
||
|
|
||
|
lpEnd++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*lpEnd = TEXT('\0');
|
||
|
|
||
|
if (FAILED(StringCchCopy(g_App.szLogDir, cA(g_App.szLogDir), lpStart))) {
|
||
|
//
|
||
|
// The user probably typed in too many characters for
|
||
|
// the log dir.
|
||
|
//
|
||
|
Err = ERROR_DIRECTORY;
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// Verify that the log dir exists and is a directory.
|
||
|
//
|
||
|
DWORD attributes;
|
||
|
|
||
|
attributes = GetFileAttributes(g_App.szLogDir);
|
||
|
|
||
|
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||
|
Err = ERROR_DIRECTORY;
|
||
|
} else if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||
|
Err = ERROR_DIRECTORY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FREE(lpCommandLine);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Err != ERROR_SUCCESS) {
|
||
|
MyMessageBoxId(IDS_LOGDIRERROR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the user specified the FULLSCAN flag we want to scan the specified
|
||
|
// directory and all of its subdirectories.
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_FULLSCAN);
|
||
|
if (SUCCEEDED(StringCchCat(szBuffer, cA(szBuffer), TEXT(":"))) &&
|
||
|
((lpStart = MyStrStr(GetCommandLine(), szBuffer)) != NULL)) {
|
||
|
|
||
|
Err = ERROR_SUCCESS;
|
||
|
|
||
|
lpStart += lstrlen(szBuffer);
|
||
|
|
||
|
if (lpStart && *lpStart) {
|
||
|
//
|
||
|
// The string in lpStart is the directory that we want to scan.
|
||
|
//
|
||
|
cchSize = lstrlen(lpStart) + 1;
|
||
|
lpCommandLine = MALLOC(cchSize * sizeof(TCHAR));
|
||
|
|
||
|
if (lpCommandLine) {
|
||
|
|
||
|
if (SUCCEEDED(StringCchCopy(lpCommandLine, cchSize, lpStart))) {
|
||
|
|
||
|
lpStart = lpCommandLine;
|
||
|
|
||
|
//
|
||
|
// First skip any white space.
|
||
|
//
|
||
|
|
||
|
while (*lpStart && (isspace(*lpStart))) {
|
||
|
|
||
|
lpStart++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We will deal with two cases, one where the path
|
||
|
// starts with a quote, and the other where it does
|
||
|
// not.
|
||
|
//
|
||
|
if (*lpStart) {
|
||
|
|
||
|
if (*lpStart == TEXT('\"')) {
|
||
|
//
|
||
|
// The scan path starts with a quote. This means that
|
||
|
// we will use all of the string until we either hit
|
||
|
// the end of the string, or we find another quote.
|
||
|
//
|
||
|
lpStart++;
|
||
|
|
||
|
lpEnd = lpStart;
|
||
|
|
||
|
while (*lpEnd && (*lpEnd != TEXT('\"'))) {
|
||
|
|
||
|
lpEnd++;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// The scan path does NOT start with a quote, so
|
||
|
// use the characters until we come to the end
|
||
|
// of the string or a space.
|
||
|
//
|
||
|
lpEnd = lpStart;
|
||
|
|
||
|
while (*lpEnd && (!isspace(*lpEnd))) {
|
||
|
|
||
|
lpEnd++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*lpEnd = TEXT('\0');
|
||
|
|
||
|
if (FAILED(StringCchCopy(g_App.szScanPath, cA(g_App.szScanPath), lpStart))) {
|
||
|
//
|
||
|
// The user probably typed in too many characters for
|
||
|
// the scan dir.
|
||
|
//
|
||
|
Err = ERROR_DIRECTORY;
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// Verify that the scan dir exists and is a directory.
|
||
|
//
|
||
|
DWORD attributes;
|
||
|
|
||
|
attributes = GetFileAttributes(g_App.szScanPath);
|
||
|
|
||
|
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||
|
Err = ERROR_DIRECTORY;
|
||
|
} else if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||
|
Err = ERROR_DIRECTORY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FREE(lpCommandLine);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Err == ERROR_SUCCESS) {
|
||
|
|
||
|
g_App.bAutomatedScan = TRUE;
|
||
|
g_App.bLoggingEnabled = TRUE;
|
||
|
g_App.bUserScan = TRUE;
|
||
|
g_App.bSubFolders = TRUE;
|
||
|
|
||
|
//
|
||
|
// Now that everything is set up, simulate a click to the START button...
|
||
|
//
|
||
|
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(ID_START, 0), (LPARAM)0);
|
||
|
|
||
|
} else {
|
||
|
MyMessageBoxId(IDS_FULLSCANERROR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the user specified the DEFSCAN flag, we want to automatically do a
|
||
|
// default scan and log the results.
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_DEFSCAN);
|
||
|
if (MyStrStr(GetCommandLine(), szBuffer)) {
|
||
|
|
||
|
g_App.bAutomatedScan = TRUE;
|
||
|
g_App.bLoggingEnabled = TRUE;
|
||
|
|
||
|
//
|
||
|
// Now that everything is set up, simulate a click to the START button...
|
||
|
//
|
||
|
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(ID_START, 0), (LPARAM) 0);
|
||
|
}
|
||
|
|
||
|
if (Err == ERROR_SUCCESS) {
|
||
|
return TRUE;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
g_App.LastError = Err;
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Build file list according to dialog settings, then verify the files in the list
|
||
|
//
|
||
|
void WINAPI
|
||
|
ProcessFileList(void)
|
||
|
{
|
||
|
DWORD Err = ERROR_SUCCESS;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
|
||
|
//
|
||
|
// Set the scanning flag to TRUE, so we don't double-scan
|
||
|
//
|
||
|
g_App.bScanning = TRUE;
|
||
|
|
||
|
// Assume a successfull scan.
|
||
|
g_App.LastError = ERROR_SUCCESS;
|
||
|
|
||
|
//
|
||
|
// Change the "Start" to "Stop"
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_STOP);
|
||
|
SetDlgItemText(g_App.hDlg, ID_START, szBuffer);
|
||
|
|
||
|
EnableWindow(GetDlgItem(g_App.hDlg, ID_ADVANCED), FALSE);
|
||
|
EnableWindow(GetDlgItem(g_App.hDlg, IDCANCEL), FALSE);
|
||
|
|
||
|
//
|
||
|
// Display the text that says "Building file list..."
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_STATUS_BUILD);
|
||
|
SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
|
||
|
|
||
|
//
|
||
|
// Make sure the IDC_STATUS text item visible
|
||
|
//
|
||
|
ShowWindow(GetDlgItem(g_App.hDlg, IDC_STATUS), SW_SHOW);
|
||
|
|
||
|
//
|
||
|
// Free any memory that we may have allocated for the g_App.lpFileList
|
||
|
//
|
||
|
DestroyFileList(TRUE);
|
||
|
|
||
|
//
|
||
|
// Now actually build the g_App.lpFileList list given the dialog settings
|
||
|
//
|
||
|
if (g_App.bUserScan) {
|
||
|
|
||
|
Err = BuildFileList(g_App.szScanPath);
|
||
|
|
||
|
} else {
|
||
|
if (!g_App.bStopScan && (Err == ERROR_SUCCESS)) {
|
||
|
Err = BuildDriverFileList();
|
||
|
}
|
||
|
|
||
|
if (!g_App.bStopScan && (Err == ERROR_SUCCESS)) {
|
||
|
Err = BuildPrinterFileList();
|
||
|
}
|
||
|
|
||
|
if (!g_App.bStopScan && (Err == ERROR_SUCCESS)) {
|
||
|
Err = BuildCoreFileList();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!g_App.bAutomatedScan &&
|
||
|
(Err != ERROR_SUCCESS) &&
|
||
|
(Err != ERROR_CANCELLED)) {
|
||
|
|
||
|
g_App.LastError = Err;
|
||
|
MyErrorBoxIdWithErrorCode(IDS_BUILDLISTERROR, Err);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we encountered an error building the file list then don't bother
|
||
|
// scanning the files.
|
||
|
//
|
||
|
if (Err == ERROR_SUCCESS) {
|
||
|
//
|
||
|
// Check if there is even a file list to verify.
|
||
|
//
|
||
|
if (g_App.lpFileList) {
|
||
|
|
||
|
if (!g_App.bStopScan) {
|
||
|
//
|
||
|
// Display the "Scanning File List..." text
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_STATUS_SCAN);
|
||
|
SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
|
||
|
|
||
|
//
|
||
|
// Reset the progress bar back to zero percent while it's invisible.
|
||
|
//
|
||
|
SendMessage(GetDlgItem(g_App.hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM) 0, (LPARAM) 0);
|
||
|
|
||
|
//
|
||
|
// WooHoo! Let's display the progress bar and start cranking on the file list!
|
||
|
//
|
||
|
ShowWindow(GetDlgItem(g_App.hDlg, IDC_PROGRESS), SW_SHOW);
|
||
|
VerifyFileList();
|
||
|
ShowWindow(GetDlgItem(g_App.hDlg, IDC_PROGRESS), SW_HIDE);
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// The IDC_NOTMS code displays it's own error message, so only display
|
||
|
// an error dialog if we are doing a System Integrity Scan
|
||
|
//
|
||
|
if (!g_App.bStopScan && !g_App.bUserScan) {
|
||
|
MyMessageBoxId(IDS_NOSYSTEMFILES);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Disable the start button while we clean up the g_App.lpFileList
|
||
|
//
|
||
|
EnableWindow(GetDlgItem(g_App.hDlg, ID_START), FALSE);
|
||
|
|
||
|
//
|
||
|
// Log the results. Note that sigverif will do this even if we encountered
|
||
|
// an error building or scanning the list, since the logfile may help
|
||
|
// figure out which file is causing the problem. Only log the results
|
||
|
// if we found any files to scan.
|
||
|
//
|
||
|
if (!g_App.bStopScan) {
|
||
|
//
|
||
|
// Display the text that says "Writing Log File..."
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_STATUS_LOG);
|
||
|
SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
|
||
|
|
||
|
//
|
||
|
// Write the results to the log file
|
||
|
//
|
||
|
if (!PrintFileList()) {
|
||
|
//
|
||
|
// We failed while logging for some reason, probably permissions
|
||
|
// or out of disk space. Let the user know that we could not finish
|
||
|
// logging all of the files.
|
||
|
//
|
||
|
Err = GetLastError();
|
||
|
|
||
|
if (Err != ERROR_SUCCESS) {
|
||
|
|
||
|
MyErrorBoxIdWithErrorCode(IDS_LOGERROR, Err);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// If the user clicked STOP, let them know about it.
|
||
|
//
|
||
|
MyMessageBoxId(IDS_SCANSTOPPED);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Display the text that says "Freeing File List..."
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_STATUS_FREE);
|
||
|
SetDlgItemText(g_App.hDlg, IDC_STATUS, szBuffer);
|
||
|
|
||
|
//
|
||
|
// Hide the IDC_STATUS text item so it doesn't cover IDC_STATUS
|
||
|
//
|
||
|
ShowWindow(GetDlgItem(g_App.hDlg, IDC_STATUS), SW_HIDE);
|
||
|
|
||
|
//
|
||
|
// Change the "Stop" button back to "Start"
|
||
|
//
|
||
|
MyLoadString(szBuffer, cA(szBuffer), IDS_START);
|
||
|
SetDlgItemText(g_App.hDlg, ID_START, szBuffer);
|
||
|
|
||
|
EnableWindow(GetDlgItem(g_App.hDlg, ID_START), TRUE);
|
||
|
EnableWindow(GetDlgItem(g_App.hDlg, ID_ADVANCED), TRUE);
|
||
|
EnableWindow(GetDlgItem(g_App.hDlg, IDCANCEL), TRUE);
|
||
|
|
||
|
//
|
||
|
// Free all the memory that we allocated for the g_App.lpFileList
|
||
|
//
|
||
|
DestroyFileList(FALSE);
|
||
|
|
||
|
//
|
||
|
// Clear the scanning flag
|
||
|
//
|
||
|
g_App.bScanning = FALSE;
|
||
|
g_App.bStopScan = FALSE;
|
||
|
|
||
|
//
|
||
|
// If the user started SigVerif with the /DEFSCAN flag, then we exit.
|
||
|
//
|
||
|
if (g_App.bAutomatedScan) {
|
||
|
PostMessage(g_App.hDlg, WM_CLOSE, (WPARAM) 0, (LPARAM) 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Spawns a thread to do the scan so the GUI remains responsive.
|
||
|
//
|
||
|
void
|
||
|
Dlg_OnPushStartButton(
|
||
|
HWND hwnd
|
||
|
)
|
||
|
{
|
||
|
HANDLE hThread;
|
||
|
DWORD dwThreadId;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(hwnd);
|
||
|
|
||
|
//
|
||
|
// Check if we are already scanning... if so, bail.
|
||
|
//
|
||
|
if (g_App.bScanning) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create a thread where Search_ProcessFileList can go without tying up the GUI thread.
|
||
|
//
|
||
|
hThread = CreateThread(NULL,
|
||
|
0,
|
||
|
(LPTHREAD_START_ROUTINE) ProcessFileList,
|
||
|
0,
|
||
|
0,
|
||
|
&dwThreadId);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Handle any WM_COMMAND messages sent to the search dialog
|
||
|
//
|
||
|
void
|
||
|
Dlg_OnCommand(
|
||
|
HWND hwnd,
|
||
|
int id,
|
||
|
HWND hwndCtl,
|
||
|
UINT codeNotify
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(hwndCtl);
|
||
|
UNREFERENCED_PARAMETER(codeNotify);
|
||
|
|
||
|
switch(id) {
|
||
|
//
|
||
|
// The user clicked ID_START, so if we aren't scanning start scanning.
|
||
|
// If we are scanning, then stop the tests because the button actually says "Stop"
|
||
|
//
|
||
|
case ID_START:
|
||
|
if (!g_App.bScanning) {
|
||
|
|
||
|
Dlg_OnPushStartButton(hwnd);
|
||
|
|
||
|
} else if (!g_App.bStopScan) {
|
||
|
|
||
|
g_App.bStopScan = TRUE;
|
||
|
g_App.LastError = ERROR_CANCELLED;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// The user clicked IDCANCEL, so if the tests are running try to stop them before exiting.
|
||
|
//
|
||
|
case IDCANCEL:
|
||
|
if (g_App.bScanning) {
|
||
|
|
||
|
g_App.bStopScan = TRUE;
|
||
|
g_App.LastError = ERROR_CANCELLED;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Pop up the IDD_SETTINGS dialog so the user can change their log settings.
|
||
|
case ID_ADVANCED:
|
||
|
if (!g_App.bScanning) {
|
||
|
|
||
|
AdvancedPropertySheet(hwnd);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
SigVerif_Help(
|
||
|
HWND hwnd,
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam,
|
||
|
BOOL bContext
|
||
|
)
|
||
|
{
|
||
|
static DWORD SigVerif_HelpIDs[] =
|
||
|
{
|
||
|
IDC_SCAN, IDH_SIGVERIF_SEARCH_CHECK_SYSTEM,
|
||
|
IDC_NOTMS, IDH_SIGVERIF_SEARCH_LOOK_FOR,
|
||
|
IDC_TYPE, IDH_SIGVERIF_SEARCH_SCAN_FILES,
|
||
|
IDC_FOLDER, IDH_SIGVERIF_SEARCH_LOOK_IN_FOLDER,
|
||
|
IDC_SUBFOLDERS, IDH_SIGVERIF_SEARCH_INCLUDE_SUBFOLDERS,
|
||
|
IDC_ENABLELOG, IDH_SIGVERIF_LOGGING_ENABLE_LOGGING,
|
||
|
IDC_APPEND, IDH_SIGVERIF_LOGGING_APPEND,
|
||
|
IDC_OVERWRITE, IDH_SIGVERIF_LOGGING_OVERWRITE,
|
||
|
IDC_LOGNAME, IDH_SIGVERIF_LOGGING_FILENAME,
|
||
|
IDC_VIEWLOG, IDH_SIGVERIF_LOGGING_VIEW_LOG,
|
||
|
0,0
|
||
|
};
|
||
|
|
||
|
static DWORD Windows_HelpIDs[] =
|
||
|
{
|
||
|
ID_BROWSE, IDH_BROWSE,
|
||
|
0,0
|
||
|
};
|
||
|
|
||
|
HWND hItem = NULL;
|
||
|
LPHELPINFO lphi = NULL;
|
||
|
POINT point;
|
||
|
|
||
|
switch (uMsg) {
|
||
|
|
||
|
case WM_HELP:
|
||
|
lphi = (LPHELPINFO) lParam;
|
||
|
if (lphi && (lphi->iContextType == HELPINFO_WINDOW)) {
|
||
|
hItem = (HWND) lphi->hItemHandle;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
hItem = (HWND) wParam;
|
||
|
point.x = GET_X_LPARAM(lParam);
|
||
|
point.y = GET_Y_LPARAM(lParam);
|
||
|
if (ScreenToClient(hwnd, &point)) {
|
||
|
hItem = ChildWindowFromPoint(hwnd, point);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (hItem) {
|
||
|
if (GetWindowLong(hItem, GWL_ID) == ID_BROWSE) {
|
||
|
WinHelp(hItem,
|
||
|
(LPCTSTR) WINDOWS_HELPFILE,
|
||
|
(bContext ? HELP_CONTEXTMENU : HELP_WM_HELP),
|
||
|
(ULONG_PTR) Windows_HelpIDs);
|
||
|
} else {
|
||
|
WinHelp(hItem,
|
||
|
(LPCTSTR) SIGVERIF_HELPFILE,
|
||
|
(bContext ? HELP_CONTEXTMENU : HELP_WM_HELP),
|
||
|
(ULONG_PTR) SigVerif_HelpIDs);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The main dialog procedure. Needs to handle WM_INITDIALOG, WM_COMMAND, and WM_CLOSE/WM_DESTROY.
|
||
|
//
|
||
|
INT_PTR CALLBACK
|
||
|
DlgProc(
|
||
|
HWND hwnd,
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
BOOL fProcessed = TRUE;
|
||
|
|
||
|
switch (uMsg) {
|
||
|
|
||
|
HANDLE_MSG(hwnd, WM_COMMAND, Dlg_OnCommand);
|
||
|
|
||
|
case WM_INITDIALOG:
|
||
|
fProcessed = Dlg_OnInitDialog(hwnd);
|
||
|
break;
|
||
|
|
||
|
case WM_CLOSE:
|
||
|
if (g_App.bScanning) {
|
||
|
g_App.bStopScan = TRUE;
|
||
|
g_App.LastError = ERROR_CANCELLED;
|
||
|
|
||
|
} else {
|
||
|
EndDialog(hwnd, IDCANCEL);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
fProcessed = FALSE;
|
||
|
}
|
||
|
|
||
|
return fProcessed;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Program entry point. Set up for creation of IDD_DIALOG.
|
||
|
//
|
||
|
WINAPI
|
||
|
WinMain(
|
||
|
HINSTANCE hInstance,
|
||
|
HINSTANCE hPrevInstance,
|
||
|
LPSTR lpszCmdParam,
|
||
|
int nCmdShow
|
||
|
)
|
||
|
{
|
||
|
HWND hwnd;
|
||
|
TCHAR szAppName[MAX_PATH];
|
||
|
|
||
|
UNREFERENCED_PARAMETER(hPrevInstance);
|
||
|
UNREFERENCED_PARAMETER(lpszCmdParam);
|
||
|
UNREFERENCED_PARAMETER(nCmdShow);
|
||
|
|
||
|
ZeroMemory(&g_App, sizeof(GAPPDATA));
|
||
|
|
||
|
g_App.hInstance = hInstance;
|
||
|
|
||
|
//
|
||
|
// Look for any existing instances of SigVerif...
|
||
|
//
|
||
|
MyLoadString(szAppName, cA(szAppName), IDS_SIGVERIF);
|
||
|
hwnd = FindWindow(NULL, szAppName);
|
||
|
if (!hwnd) {
|
||
|
//
|
||
|
// We definitely need this for the progress bar, and maybe other stuff too.
|
||
|
//
|
||
|
InitCommonControls();
|
||
|
|
||
|
//
|
||
|
// Register the custom control we use for the progress bar
|
||
|
//
|
||
|
Progress_InitRegisterClass();
|
||
|
|
||
|
//
|
||
|
// Load the icon from the resource file that we will use everywhere
|
||
|
//
|
||
|
g_App.hIcon = LoadIcon(g_App.hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||
|
|
||
|
//
|
||
|
// Create the IDD_DIALOG and use DlgProc as the main procedure
|
||
|
//
|
||
|
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);
|
||
|
|
||
|
if (g_App.hIcon) {
|
||
|
DestroyIcon(g_App.hIcon);
|
||
|
g_App.hIcon = NULL;
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// If there is already an instance of SigVerif running, make that one
|
||
|
// foreground and we exit.
|
||
|
//
|
||
|
SetForegroundWindow(hwnd);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we encountered any errors during our scan, then return the error code,
|
||
|
// otherwise return 0 if all the files are signed or 1 if we found any
|
||
|
// unsigned files.
|
||
|
//
|
||
|
if (g_App.LastError != ERROR_SUCCESS) {
|
||
|
return g_App.LastError;
|
||
|
} else {
|
||
|
return ((g_App.dwUnsigned > 0) ? 1 : 0);
|
||
|
}
|
||
|
}
|