windows-nt/Source/XPSP1/NT/base/subsys/sm/sfc/dll/dirscan.c
2020-09-26 16:20:57 +08:00

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;
}