304 lines
8 KiB
C
304 lines
8 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
dirscan.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implementation of directory scanner.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Wesley Witt (wesw) 18-Dec-1998
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Andrew Ritz (andrewr) 7-Jul-1999 : added comments
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "sfcp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
SfcDoScan(
|
||
|
IN PSCAN_PARAMS ScanParams
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Scan the set of protected DLLs and compare them with the cached versions.
|
||
|
If any are different, copy the correct one back.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ScanParams - pointer to SCAN_PARAMS structure indicating scanning behavior
|
||
|
(such as whether to display UI or not)
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS code of any fatal error.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS StatusPopulate, StatusSxsScan, rStatus;
|
||
|
|
||
|
StatusPopulate = SfcPopulateCache( ScanParams->ProgressWindow, TRUE, ScanParams->AllowUI, NULL ) ?
|
||
|
STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
StatusSxsScan = SfcDoForcedSxsScan( ScanParams->ProgressWindow, TRUE, ScanParams->AllowUI );
|
||
|
|
||
|
// Figure out which of these two failed. We really do need to do both, rather than
|
||
|
// just returning after a check of the SfcPopulateCache call.
|
||
|
if ( !NT_SUCCESS( StatusPopulate ) ) {
|
||
|
rStatus = StatusPopulate;
|
||
|
DebugPrint1( LVL_MINIMAL, L"Failed scanning SFC: 0x%08x\n", rStatus );
|
||
|
} else if ( !NT_SUCCESS( StatusSxsScan ) ) {
|
||
|
rStatus = StatusSxsScan;
|
||
|
DebugPrint1( LVL_MINIMAL, L"Failed scanning SxS: 0x%08x\n", rStatus );
|
||
|
} else {
|
||
|
rStatus = STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
return rStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
INT_PTR
|
||
|
CALLBACK
|
||
|
ProgressDialogProc(
|
||
|
HWND hwndDlg,
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER( lParam );
|
||
|
|
||
|
if (uMsg == WM_INITDIALOG) {
|
||
|
if (hEventScanCancel == NULL) {
|
||
|
EnableWindow( GetDlgItem(hwndDlg,IDCANCEL), FALSE );
|
||
|
}
|
||
|
CenterDialog( hwndDlg );
|
||
|
ShowWindow( hwndDlg, SW_SHOWNORMAL );
|
||
|
UpdateWindow( hwndDlg );
|
||
|
SetForegroundWindow( hwndDlg );
|
||
|
return TRUE;
|
||
|
}
|
||
|
if (uMsg == WM_COMMAND && LOWORD(wParam) == IDCANCEL) {
|
||
|
SetEvent( hEventScanCancel );
|
||
|
EndDialog( hwndDlg, 0 );
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
SfcScanProtectedDlls(
|
||
|
PSCAN_PARAMS ScanParams
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Thread routine to scan for protected dlls on the system. The routine
|
||
|
creates a dialog so the user can tell what's going on (if requested) and
|
||
|
then calls into the main scanning routine.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ScanParams - pointer to SCAN_PARAMS structure indicating scanning behavior
|
||
|
(such as whether to display UI or not)
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS code indicating outcome.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
HWND hDlg = NULL;
|
||
|
#if 0
|
||
|
HDESK hDesk = NULL;
|
||
|
#endif
|
||
|
HANDLE hThread;
|
||
|
|
||
|
ASSERT( ScanParams != NULL );
|
||
|
|
||
|
//
|
||
|
// make sure we only kick off one of these at a time
|
||
|
//
|
||
|
if (ScanInProgress) {
|
||
|
if (ScanParams->FreeMemory) {
|
||
|
MemFree( ScanParams );
|
||
|
}
|
||
|
return(ERROR_IO_PENDING);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// if the system is configured to show UI progress and we don't
|
||
|
// have a progress window, then we need to create a new thread
|
||
|
// to do the scan as well as a progress dialog.
|
||
|
//
|
||
|
if (SfcQueryRegDwordWithAlternate(REGKEY_POLICY, REGKEY_WINLOGON, REGVAL_SFCSHOWPROGRESS, 1) &&
|
||
|
ScanParams->ProgressWindow == NULL &&
|
||
|
0 == m_gulAfterRestore) {
|
||
|
//
|
||
|
// if the user isn't logged in, we need to wait for them to do so
|
||
|
// before thinking about creating a dialog
|
||
|
//
|
||
|
if (!UserLoggedOn) {
|
||
|
Status = NtWaitForSingleObject(hEventLogon,TRUE,NULL);
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DebugPrint1(LVL_MINIMAL, L"Failed waiting for the logon event, ec=0x%08x",Status);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// we need access to the user's desktop now that they're logged in
|
||
|
//
|
||
|
#if 0
|
||
|
hDesk = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
|
||
|
if ( hDesk ) {
|
||
|
SetThreadDesktop( hDesk );
|
||
|
CloseDesktop( hDesk );
|
||
|
} else {
|
||
|
DebugPrint1(LVL_MINIMAL, L"OpenInputDesktop failed, ec=0x%08x",GetLastError());
|
||
|
}
|
||
|
#else
|
||
|
SetThreadDesktop( hUserDesktop );
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// create an event so the user can cancel the scan
|
||
|
//
|
||
|
// (note that we should only have one scan going on at any given
|
||
|
// time or our cancel object can get out of sync)
|
||
|
//
|
||
|
ASSERT( hEventScanCancel == NULL );
|
||
|
ASSERT( hEventScanCancelComplete == NULL);
|
||
|
hEventScanCancel = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||
|
hEventScanCancelComplete = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||
|
|
||
|
//
|
||
|
// create the dialog the user will see UI in
|
||
|
//
|
||
|
hDlg = CreateDialog(
|
||
|
SfcInstanceHandle,
|
||
|
MAKEINTRESOURCE(IDD_PROGRESS),
|
||
|
NULL,
|
||
|
ProgressDialogProc
|
||
|
);
|
||
|
if (hDlg) {
|
||
|
//
|
||
|
// scale the progress dialog (we assume that it takes the same
|
||
|
// amount of time to scan each file in the system)
|
||
|
//
|
||
|
ScanParams->ProgressWindow = GetDlgItem( hDlg, IDC_PROGRESS );
|
||
|
SendMessage( ScanParams->ProgressWindow, PBM_SETRANGE, 0, MAKELPARAM(0,SfcProtectedDllCount) );
|
||
|
SendMessage( ScanParams->ProgressWindow, PBM_SETPOS, 0, 0 );
|
||
|
SendMessage( ScanParams->ProgressWindow, PBM_SETSTEP, 1, 0 );
|
||
|
|
||
|
//
|
||
|
// create a thread to do the work so we can pump messages in this
|
||
|
// thread that already has access to the desktop
|
||
|
//
|
||
|
hThread = CreateThread(
|
||
|
NULL,
|
||
|
0,
|
||
|
(LPTHREAD_START_ROUTINE)SfcDoScan,
|
||
|
ScanParams,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
if (hThread) {
|
||
|
MSG msg;
|
||
|
while(1) {
|
||
|
//
|
||
|
// pump messages until the "worker" thread goes away or the
|
||
|
// dialog ends
|
||
|
//
|
||
|
if (WAIT_OBJECT_0+1 == MsgWaitForMultipleObjects( 1, &hThread, FALSE, INFINITE, QS_ALLEVENTS )) {
|
||
|
while (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) {
|
||
|
if (!IsDialogMessage( hDlg, &msg )) {
|
||
|
TranslateMessage (&msg);
|
||
|
DispatchMessage (&msg);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
CloseHandle( hThread );
|
||
|
EndDialog( hDlg, 0 );
|
||
|
} else {
|
||
|
//
|
||
|
// CreateThread failed... kill the dialog and try to do it
|
||
|
// synchronously
|
||
|
//
|
||
|
EndDialog( hDlg, 0 );
|
||
|
SfcDoScan( ScanParams );
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// CreateDialog failed... just try to do it synchronously
|
||
|
//
|
||
|
SfcDoScan( ScanParams );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// cleanup
|
||
|
//
|
||
|
if (hEventScanCancel) {
|
||
|
CloseHandle( hEventScanCancel );
|
||
|
hEventScanCancel = NULL;
|
||
|
}
|
||
|
|
||
|
if (hEventScanCancelComplete) {
|
||
|
CloseHandle( hEventScanCancelComplete );
|
||
|
hEventScanCancelComplete = NULL;
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// no UI to be shown, just do this synchronously
|
||
|
//
|
||
|
SfcDoScan( ScanParams );
|
||
|
}
|
||
|
|
||
|
if (ScanParams->FreeMemory) {
|
||
|
MemFree( ScanParams );
|
||
|
}
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
SfcDoForcedSxsScan(
|
||
|
IN HWND hwDialogProgress,
|
||
|
IN BOOL bValidate,
|
||
|
IN BOOL bAllowUI
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
Status = SfcLoadSxsProtection();
|
||
|
if ( !NT_SUCCESS( Status ) ) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
ASSERT( SxsScanForcedFunc != NULL );
|
||
|
|
||
|
if ( !SxsScanForcedFunc( hwDialogProgress, bValidate, bAllowUI ) ) {
|
||
|
return STATUS_SUCCESS;
|
||
|
} else
|
||
|
return STATUS_NO_MEMORY;
|
||
|
}
|