Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. dirscan.c
  5. Abstract:
  6. Implementation of directory scanner.
  7. Author:
  8. Wesley Witt (wesw) 18-Dec-1998
  9. Revision History:
  10. Andrew Ritz (andrewr) 7-Jul-1999 : added comments
  11. --*/
  12. #include "sfcp.h"
  13. #pragma hdrstop
  14. NTSTATUS
  15. SfcDoScan(
  16. IN PSCAN_PARAMS ScanParams
  17. )
  18. /*++
  19. Routine Description:
  20. Scan the set of protected DLLs and compare them with the cached versions.
  21. If any are different, copy the correct one back.
  22. Arguments:
  23. ScanParams - pointer to SCAN_PARAMS structure indicating scanning behavior
  24. (such as whether to display UI or not)
  25. Return Value:
  26. NTSTATUS code of any fatal error.
  27. --*/
  28. {
  29. NTSTATUS StatusPopulate, StatusSxsScan, rStatus;
  30. StatusPopulate = SfcPopulateCache( ScanParams->ProgressWindow, TRUE, ScanParams->AllowUI, NULL ) ?
  31. STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  32. StatusSxsScan = SfcDoForcedSxsScan( ScanParams->ProgressWindow, TRUE, ScanParams->AllowUI );
  33. // Figure out which of these two failed. We really do need to do both, rather than
  34. // just returning after a check of the SfcPopulateCache call.
  35. if ( !NT_SUCCESS( StatusPopulate ) ) {
  36. rStatus = StatusPopulate;
  37. DebugPrint1( LVL_MINIMAL, L"Failed scanning SFC: 0x%08x\n", rStatus );
  38. } else if ( !NT_SUCCESS( StatusSxsScan ) ) {
  39. rStatus = StatusSxsScan;
  40. DebugPrint1( LVL_MINIMAL, L"Failed scanning SxS: 0x%08x\n", rStatus );
  41. } else {
  42. rStatus = STATUS_SUCCESS;
  43. }
  44. return rStatus;
  45. }
  46. INT_PTR
  47. CALLBACK
  48. ProgressDialogProc(
  49. HWND hwndDlg,
  50. UINT uMsg,
  51. WPARAM wParam,
  52. LPARAM lParam
  53. )
  54. {
  55. UNREFERENCED_PARAMETER( lParam );
  56. if (uMsg == WM_INITDIALOG) {
  57. if (hEventScanCancel == NULL) {
  58. EnableWindow( GetDlgItem(hwndDlg,IDCANCEL), FALSE );
  59. }
  60. CenterDialog( hwndDlg );
  61. ShowWindow( hwndDlg, SW_SHOWNORMAL );
  62. UpdateWindow( hwndDlg );
  63. SetForegroundWindow( hwndDlg );
  64. return TRUE;
  65. }
  66. if (uMsg == WM_COMMAND && LOWORD(wParam) == IDCANCEL) {
  67. SetEvent( hEventScanCancel );
  68. EndDialog( hwndDlg, 0 );
  69. }
  70. return FALSE;
  71. }
  72. NTSTATUS
  73. SfcScanProtectedDlls(
  74. PSCAN_PARAMS ScanParams
  75. )
  76. /*++
  77. Routine Description:
  78. Thread routine to scan for protected dlls on the system. The routine
  79. creates a dialog so the user can tell what's going on (if requested) and
  80. then calls into the main scanning routine.
  81. Arguments:
  82. ScanParams - pointer to SCAN_PARAMS structure indicating scanning behavior
  83. (such as whether to display UI or not)
  84. Return Value:
  85. NTSTATUS code indicating outcome.
  86. --*/
  87. {
  88. NTSTATUS Status = STATUS_SUCCESS;
  89. HWND hDlg = NULL;
  90. #if 0
  91. HDESK hDesk = NULL;
  92. #endif
  93. HANDLE hThread;
  94. ASSERT( ScanParams != NULL );
  95. //
  96. // make sure we only kick off one of these at a time
  97. //
  98. if (ScanInProgress) {
  99. if (ScanParams->FreeMemory) {
  100. MemFree( ScanParams );
  101. }
  102. return(ERROR_IO_PENDING);
  103. }
  104. //
  105. // if the system is configured to show UI progress and we don't
  106. // have a progress window, then we need to create a new thread
  107. // to do the scan as well as a progress dialog.
  108. //
  109. if (SfcQueryRegDwordWithAlternate(REGKEY_POLICY, REGKEY_WINLOGON, REGVAL_SFCSHOWPROGRESS, 1) &&
  110. ScanParams->ProgressWindow == NULL &&
  111. 0 == m_gulAfterRestore) {
  112. //
  113. // if the user isn't logged in, we need to wait for them to do so
  114. // before thinking about creating a dialog
  115. //
  116. if (!UserLoggedOn) {
  117. Status = NtWaitForSingleObject(hEventLogon,TRUE,NULL);
  118. if (!NT_SUCCESS(Status)) {
  119. DebugPrint1(LVL_MINIMAL, L"Failed waiting for the logon event, ec=0x%08x",Status);
  120. }
  121. }
  122. //
  123. // we need access to the user's desktop now that they're logged in
  124. //
  125. #if 0
  126. hDesk = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
  127. if ( hDesk ) {
  128. SetThreadDesktop( hDesk );
  129. CloseDesktop( hDesk );
  130. } else {
  131. DebugPrint1(LVL_MINIMAL, L"OpenInputDesktop failed, ec=0x%08x",GetLastError());
  132. }
  133. #else
  134. SetThreadDesktop( hUserDesktop );
  135. #endif
  136. //
  137. // create an event so the user can cancel the scan
  138. //
  139. // (note that we should only have one scan going on at any given
  140. // time or our cancel object can get out of sync)
  141. //
  142. ASSERT( hEventScanCancel == NULL );
  143. ASSERT( hEventScanCancelComplete == NULL);
  144. hEventScanCancel = CreateEvent( NULL, FALSE, FALSE, NULL );
  145. hEventScanCancelComplete = CreateEvent( NULL, FALSE, FALSE, NULL );
  146. //
  147. // create the dialog the user will see UI in
  148. //
  149. hDlg = CreateDialog(
  150. SfcInstanceHandle,
  151. MAKEINTRESOURCE(IDD_PROGRESS),
  152. NULL,
  153. ProgressDialogProc
  154. );
  155. if (hDlg) {
  156. //
  157. // scale the progress dialog (we assume that it takes the same
  158. // amount of time to scan each file in the system)
  159. //
  160. ScanParams->ProgressWindow = GetDlgItem( hDlg, IDC_PROGRESS );
  161. SendMessage( ScanParams->ProgressWindow, PBM_SETRANGE, 0, MAKELPARAM(0,SfcProtectedDllCount) );
  162. SendMessage( ScanParams->ProgressWindow, PBM_SETPOS, 0, 0 );
  163. SendMessage( ScanParams->ProgressWindow, PBM_SETSTEP, 1, 0 );
  164. //
  165. // create a thread to do the work so we can pump messages in this
  166. // thread that already has access to the desktop
  167. //
  168. hThread = CreateThread(
  169. NULL,
  170. 0,
  171. (LPTHREAD_START_ROUTINE)SfcDoScan,
  172. ScanParams,
  173. 0,
  174. NULL
  175. );
  176. if (hThread) {
  177. MSG msg;
  178. while(1) {
  179. //
  180. // pump messages until the "worker" thread goes away or the
  181. // dialog ends
  182. //
  183. if (WAIT_OBJECT_0+1 == MsgWaitForMultipleObjects( 1, &hThread, FALSE, INFINITE, QS_ALLEVENTS )) {
  184. while (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) {
  185. if (!IsDialogMessage( hDlg, &msg )) {
  186. TranslateMessage (&msg);
  187. DispatchMessage (&msg);
  188. }
  189. }
  190. } else {
  191. break;
  192. }
  193. }
  194. CloseHandle( hThread );
  195. EndDialog( hDlg, 0 );
  196. } else {
  197. //
  198. // CreateThread failed... kill the dialog and try to do it
  199. // synchronously
  200. //
  201. EndDialog( hDlg, 0 );
  202. SfcDoScan( ScanParams );
  203. }
  204. } else {
  205. //
  206. // CreateDialog failed... just try to do it synchronously
  207. //
  208. SfcDoScan( ScanParams );
  209. }
  210. //
  211. // cleanup
  212. //
  213. if (hEventScanCancel) {
  214. CloseHandle( hEventScanCancel );
  215. hEventScanCancel = NULL;
  216. }
  217. if (hEventScanCancelComplete) {
  218. CloseHandle( hEventScanCancelComplete );
  219. hEventScanCancelComplete = NULL;
  220. }
  221. } else {
  222. //
  223. // no UI to be shown, just do this synchronously
  224. //
  225. SfcDoScan( ScanParams );
  226. }
  227. if (ScanParams->FreeMemory) {
  228. MemFree( ScanParams );
  229. }
  230. return Status;
  231. }
  232. NTSTATUS
  233. SfcDoForcedSxsScan(
  234. IN HWND hwDialogProgress,
  235. IN BOOL bValidate,
  236. IN BOOL bAllowUI
  237. )
  238. {
  239. NTSTATUS Status;
  240. Status = SfcLoadSxsProtection();
  241. if ( !NT_SUCCESS( Status ) ) {
  242. return Status;
  243. }
  244. ASSERT( SxsScanForcedFunc != NULL );
  245. if ( !SxsScanForcedFunc( hwDialogProgress, bValidate, bAllowUI ) ) {
  246. return STATUS_SUCCESS;
  247. } else
  248. return STATUS_NO_MEMORY;
  249. }