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.

537 lines
15 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1998
  3. All rights reserved
  4. File: ApplDlg.CPP
  5. ***************************************************************************/
  6. #include "pch.h"
  7. #include <winperf.h>
  8. #include "utils.h"
  9. #include <commctrl.h>
  10. DEFINE_MODULE("RIPREP")
  11. #define INITIAL_SIZE 51200
  12. #define EXTEND_SIZE 25600
  13. #define REGKEY_PERF L"software\\microsoft\\windows nt\\currentversion\\perflib"
  14. #define REGSUBKEY_COUNTERS L"Counters"
  15. #define PROCESS_COUNTER L"process"
  16. // Globals
  17. LPBYTE g_pBuffer = NULL;
  18. DWORD g_cbBuffer = 1;
  19. typedef struct _TASKITEM {
  20. LPWSTR pszImageName;
  21. LPWSTR pszServiceName;
  22. DWORD dwProcessId;
  23. } TASKITEM, * LPTASKITEM;
  24. //
  25. // GetServiceProcessInfo( )
  26. //
  27. // BORROWED FROM "TLIST"'s common.c
  28. //
  29. DWORD
  30. GetServiceProcessInfo(
  31. LPENUM_SERVICE_STATUS_PROCESS* ppInfo
  32. )
  33. /*++
  34. Routine Description:
  35. Provides an API for getting a list of process information for Win 32
  36. services that are running at the time of the API call.
  37. Arguments:
  38. ppInfo - address of a pointer to return the information.
  39. *ppInfo points to memory allocated with malloc.
  40. Return Value:
  41. Number of ENUM_SERVICE_STATUS_PROCESS structures pointed at by *ppInfo.
  42. --*/
  43. {
  44. DWORD dwNumServices = 0;
  45. SC_HANDLE hScm;
  46. TraceFunc( "GetServiceProcessInfo( )\n" );
  47. // Initialize the output parmeter.
  48. *ppInfo = NULL;
  49. // Connect to the service controller.
  50. //
  51. hScm = OpenSCManager(
  52. NULL,
  53. NULL,
  54. SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
  55. if (hScm) {
  56. LPENUM_SERVICE_STATUS_PROCESS pInfo = NULL;
  57. DWORD cbInfo = 4 * 1024;
  58. DWORD dwErr = ERROR_SUCCESS;
  59. DWORD dwResume = 0;
  60. DWORD cLoop = 0;
  61. const DWORD cLoopMax = 2;
  62. // First pass through the loop allocates from an initial guess. (4K)
  63. // If that isn't sufficient, we make another pass and allocate
  64. // what is actually needed. (We only go through the loop a
  65. // maximum of two times.)
  66. //
  67. do {
  68. if (pInfo != NULL) {
  69. TraceFree(pInfo);
  70. }
  71. pInfo = (LPENUM_SERVICE_STATUS_PROCESS)TraceAlloc( LMEM_FIXED, cbInfo );
  72. if (!pInfo) {
  73. dwErr = ERROR_OUTOFMEMORY;
  74. break;
  75. }
  76. dwErr = ERROR_SUCCESS;
  77. if (!EnumServicesStatusEx(
  78. hScm,
  79. SC_ENUM_PROCESS_INFO,
  80. SERVICE_WIN32,
  81. SERVICE_ACTIVE,
  82. (LPBYTE)pInfo,
  83. cbInfo,
  84. &cbInfo,
  85. &dwNumServices,
  86. &dwResume,
  87. NULL)) {
  88. dwErr = GetLastError();
  89. }
  90. }
  91. while ((ERROR_MORE_DATA == dwErr) && (++cLoop < cLoopMax));
  92. if ((ERROR_SUCCESS == dwErr) && dwNumServices) {
  93. *ppInfo = pInfo;
  94. } else {
  95. if (pInfo != NULL) {
  96. TraceFree(pInfo);
  97. pInfo = NULL;
  98. }
  99. dwNumServices = 0;
  100. }
  101. CloseServiceHandle(hScm);
  102. }
  103. RETURN(dwNumServices);
  104. }
  105. //
  106. // EnumWindowsProc( )
  107. //
  108. BOOL CALLBACK
  109. EnumWindowsProc(
  110. HWND hwnd,
  111. LPARAM lParam
  112. )
  113. {
  114. // TraceFunc( "EnumWindowsProc( )\n" );
  115. LPTASKITEM pTask = (LPTASKITEM) lParam;
  116. DWORD pid;
  117. DWORD dwLen;
  118. if (!GetWindowThreadProcessId( hwnd, &pid ))
  119. {
  120. // RETURN(TRUE); // keep enumerating
  121. return TRUE;
  122. }
  123. if ( pTask->dwProcessId != pid )
  124. {
  125. // RETURN(TRUE); // keep enumerating
  126. return TRUE;
  127. }
  128. if ( GetWindow( hwnd, GW_OWNER )
  129. || !(GetWindowLong( hwnd, GWL_STYLE ) & WS_VISIBLE ) )
  130. { // not a top level window
  131. // RETURN(TRUE); // keep enumerating
  132. return TRUE;
  133. }
  134. dwLen = GetWindowTextLength( hwnd ) + 1;
  135. pTask->pszServiceName = (LPWSTR) TraceAllocString( LMEM_FIXED, dwLen );
  136. if ( pTask->pszServiceName )
  137. {
  138. GetWindowText( hwnd, pTask->pszServiceName, dwLen );
  139. }
  140. // RETURN(FALSE); // hummm ... found it - stop enumeration
  141. return FALSE;
  142. }
  143. //
  144. // CheckForRunningApplications( )
  145. //
  146. // Returns: TRUE - possibly "unsafe" running applications/services
  147. // FALSE - Ok to continue.
  148. //
  149. BOOL
  150. CheckForRunningApplications(
  151. HWND hwndList )
  152. {
  153. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  154. NTSTATUS status;
  155. ULONG TotalOffset;
  156. LV_ITEM lvI;
  157. LPENUM_SERVICE_STATUS_PROCESS pServiceInfo;
  158. BOOL fReturn = FALSE;
  159. SC_HANDLE hScm;
  160. LPTASKITEM pTask;
  161. HKEY hkey;
  162. LRESULT lResult;
  163. DWORD dwNumServices;
  164. TraceFunc( "CheckForRunningApplications( )\n" );
  165. ListView_DeleteAllItems( hwndList );
  166. lvI.mask = LVIF_TEXT | LVIF_PARAM;
  167. lvI.iSubItem = 0;
  168. hScm = OpenSCManager(
  169. NULL,
  170. NULL,
  171. SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
  172. lResult = RegOpenKey( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services", &hkey );
  173. Assert( lResult == ERROR_SUCCESS );
  174. dwNumServices = GetServiceProcessInfo( &pServiceInfo );
  175. hScm = OpenSCManager(
  176. NULL,
  177. NULL,
  178. SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
  179. retry:
  180. if ( g_pBuffer == NULL )
  181. {
  182. g_pBuffer = (LPBYTE) VirtualAlloc ( NULL, g_cbBuffer, MEM_COMMIT, PAGE_READWRITE);
  183. if ( g_pBuffer == NULL )
  184. {
  185. RRETURN(TRUE); // be paranoid and show page
  186. }
  187. }
  188. status = NtQuerySystemInformation( SystemProcessInformation,
  189. g_pBuffer,
  190. g_cbBuffer,
  191. NULL );
  192. if ( status == STATUS_INFO_LENGTH_MISMATCH ) {
  193. g_cbBuffer += 8192;
  194. VirtualFree ( g_pBuffer, 0, MEM_RELEASE );
  195. g_pBuffer = NULL;
  196. goto retry;
  197. }
  198. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) g_pBuffer;
  199. TotalOffset = 0;
  200. while ( TRUE )
  201. {
  202. LPWSTR pszImageName;
  203. INT iCount = 0;
  204. if ( ProcessInfo->ImageName.Buffer )
  205. {
  206. pszImageName = wcsrchr( ProcessInfo->ImageName.Buffer, L'\\' );
  207. if ( pszImageName ) {
  208. pszImageName++;
  209. }
  210. else {
  211. pszImageName = ProcessInfo->ImageName.Buffer;
  212. }
  213. }
  214. else {
  215. goto skiptask; // system process, skip it
  216. }
  217. if (g_hCompatibilityInf != INVALID_HANDLE_VALUE) {
  218. INFCONTEXT Context;
  219. if (SetupFindFirstLine(
  220. g_hCompatibilityInf,
  221. L"ProcessesToIgnore",
  222. pszImageName,
  223. &Context )) {
  224. DebugMsg( "Skipping process %s, it's listed in inf exemption list...\n", pszImageName );
  225. goto skiptask;
  226. }
  227. }
  228. #ifdef DEBUG
  229. if ( StrStrI( L"MSDEV.EXE", pszImageName ) || StrStrI( L"NTSD.EXE", pszImageName ) )
  230. goto skiptask; // allowed process
  231. #endif
  232. //
  233. // othewize, it is an unknown or not allowed process
  234. // add it to the listview
  235. //
  236. fReturn = TRUE;
  237. pTask = (LPTASKITEM) TraceAlloc( LMEM_FIXED, sizeof(TASKITEM) );
  238. if ( !pTask )
  239. goto skiptask;
  240. pTask->pszImageName = (LPWSTR) TraceStrDup( pszImageName );
  241. if ( !pTask->pszImageName )
  242. goto skiptask;
  243. pTask->dwProcessId = (DWORD)(DWORD_PTR)ProcessInfo->UniqueProcessId;
  244. pTask->pszServiceName = NULL;
  245. if ( dwNumServices )
  246. {
  247. // For each service with this process id, append it's service
  248. // name to the buffer. Separate each with a comma.
  249. //
  250. DWORD iSvc;
  251. WCHAR szText[ MAX_PATH ]; // random
  252. for ( iSvc = 0; iSvc < dwNumServices; iSvc++ )
  253. {
  254. if ( pTask->dwProcessId == pServiceInfo[iSvc].ServiceStatusProcess.dwProcessId )
  255. {
  256. LPWSTR pszServiceName = pServiceInfo[iSvc].lpServiceName;
  257. if (hScm)
  258. {
  259. ULONG cbSize = ARRAYSIZE(szText);
  260. if ( GetServiceDisplayName( hScm, pServiceInfo[iSvc].lpServiceName, szText, &cbSize ) )
  261. {
  262. pszServiceName = szText;
  263. }
  264. }
  265. size_t cch = wcslen( pszServiceName ) + 1;
  266. if ( !pTask->pszServiceName )
  267. {
  268. pTask->pszServiceName = (LPWSTR) TraceAllocString( LMEM_FIXED, cch);
  269. if ( pTask->pszServiceName )
  270. {
  271. wcscpy( pTask->pszServiceName, pszServiceName );
  272. }
  273. }
  274. else
  275. { // not the most efficent, but it'll work
  276. LPWSTR pszNew = (LPWSTR) TraceAllocString( LMEM_FIXED, wcslen(pTask->pszServiceName) + 1 + cch );
  277. if ( pszNew )
  278. {
  279. wcscpy( pszNew, pTask->pszServiceName );
  280. wcscat( pszNew, L"," );
  281. wcscat( pszNew, pszServiceName );
  282. TraceFree( pTask->pszServiceName );
  283. pTask->pszServiceName = pszNew;
  284. }
  285. }
  286. }
  287. }
  288. }
  289. if ( hkey && !pTask->pszServiceName )
  290. {
  291. DWORD iSvc = 0;
  292. WCHAR szService[ MAX_PATH ]; // random
  293. while ( RegEnumKey( hkey, iSvc, szService, ARRAYSIZE(szService) ) )
  294. {
  295. HKEY hkeyService;
  296. WCHAR szPath[ MAX_PATH ];
  297. LONG cb = ARRAYSIZE(szPath);
  298. lResult = RegOpenKey( hkey, szService, &hkeyService );
  299. Assert( lResult );
  300. lResult = RegQueryValue( hkeyService, L"ImagePath", szPath, &cb );
  301. Assert( lResult );
  302. if ( StrStrI( szPath, pTask->pszImageName ) )
  303. { // match!
  304. WCHAR szText[ MAX_PATH ]; // random
  305. cb = ARRAYSIZE(szText);
  306. lResult = RegQueryValue( hkeyService, L"DisplayName", szText, &cb );
  307. if ( lResult == ERROR_SUCCESS )
  308. {
  309. pTask->pszServiceName = (LPWSTR) TraceStrDup( szText );
  310. break;
  311. }
  312. }
  313. RegCloseKey( hkeyService );
  314. iSvc++;
  315. }
  316. }
  317. if ( !pTask->pszServiceName )
  318. {
  319. EnumWindows( &EnumWindowsProc, (LPARAM) pTask );
  320. }
  321. lvI.cchTextMax = wcslen(pTask->pszImageName);
  322. lvI.lParam = (LPARAM) pTask;
  323. lvI.iItem = iCount;
  324. lvI.pszText = pTask->pszImageName;
  325. iCount = ListView_InsertItem( hwndList, &lvI );
  326. Assert( iCount != -1 );
  327. if ( iCount == -1 )
  328. goto skiptask;
  329. if ( pTask->pszServiceName )
  330. {
  331. ListView_SetItemText( hwndList, iCount, 1, pTask->pszServiceName );
  332. }
  333. skiptask:
  334. if ( ProcessInfo->NextEntryOffset == 0 ) {
  335. break;
  336. }
  337. TotalOffset += ProcessInfo->NextEntryOffset;
  338. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&g_pBuffer[TotalOffset];
  339. }
  340. if ( hScm )
  341. {
  342. CloseServiceHandle(hScm);
  343. }
  344. if ( pServiceInfo )
  345. {
  346. TraceFree( pServiceInfo );
  347. }
  348. RegCloseKey( hkey );
  349. RETURN(fReturn);
  350. }
  351. //
  352. // ApplicationDlgProc()
  353. //
  354. INT_PTR CALLBACK
  355. ApplicationDlgProc(
  356. HWND hDlg,
  357. UINT uMsg,
  358. WPARAM wParam,
  359. LPARAM lParam )
  360. {
  361. switch (uMsg)
  362. {
  363. default:
  364. return FALSE;
  365. case WM_INITDIALOG:
  366. {
  367. LV_COLUMN lvC;
  368. WCHAR szText[ 80 ];
  369. INT i;
  370. HWND hwndList = GetDlgItem( hDlg, IDC_L_PROCESSES );
  371. RECT rect;
  372. DWORD dw;
  373. // Create the columns
  374. lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  375. lvC.fmt = LVCFMT_LEFT;
  376. lvC.pszText = szText;
  377. // Add first column
  378. lvC.iSubItem = 0;
  379. lvC.cx = 100;
  380. dw = LoadString( g_hinstance, IDS_PROCESS_NAME_COLUMN, szText, ARRAYSIZE(szText));
  381. Assert( dw );
  382. i = ListView_InsertColumn ( hwndList, 0, &lvC );
  383. Assert( i != -1 );
  384. // Add second column
  385. lvC.iSubItem++;
  386. GetWindowRect( hwndList, &rect );
  387. lvC.cx = ( rect.right - rect.left ) - lvC.cx; // autosize - make Tony happy
  388. dw = LoadString( g_hinstance, IDS_APPL_NAME_COLUMN, szText, ARRAYSIZE(szText));
  389. Assert( dw );
  390. i = ListView_InsertColumn ( hwndList, lvC.iSubItem, &lvC );
  391. Assert( i != -1 );
  392. }
  393. return FALSE;
  394. case WM_DESTROY:
  395. VirtualFree ( g_pBuffer, 0, MEM_RELEASE );
  396. g_pBuffer = NULL; // paranoid
  397. break;
  398. case WM_NOTIFY:
  399. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, FALSE );
  400. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  401. switch ( lpnmhdr->code )
  402. {
  403. case PSN_QUERYCANCEL:
  404. return VerifyCancel( hDlg );
  405. case PSN_WIZNEXT:
  406. #if 0
  407. if ( CheckForRunningApplications( GetDlgItem( hDlg, IDC_L_PROCESSES ) ) )
  408. {
  409. MessageBoxFromStrings( hDlg, IDS_NOT_ALL_PROCESSES_KILLED_TITLE, IDS_NOT_ALL_PROCESSES_KILLED_TEXT, MB_OK );
  410. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't show
  411. }
  412. #endif
  413. break;
  414. case PSN_SETACTIVE:
  415. {
  416. if ( !CheckForRunningApplications( GetDlgItem( hDlg, IDC_L_PROCESSES ) ) )
  417. {
  418. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't show
  419. break;
  420. }
  421. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  422. ClearMessageQueue( );
  423. }
  424. break;
  425. case LVN_DELETEALLITEMS:
  426. TraceMsg( TF_WM, "LVN_DELETEALLITEMS - Deleting all items.\n" );
  427. break;
  428. case LVN_DELETEITEM:
  429. TraceMsg( TF_WM, "LVN_DELETEITEM - Deleting an item.\n" );
  430. {
  431. LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
  432. HWND hwndList = GetDlgItem( hDlg, IDC_L_PROCESSES );
  433. LPTASKITEM pTask;
  434. LVITEM lvi;
  435. BOOL b;
  436. lvi.iItem = pnmv->iItem;
  437. lvi.iSubItem = 0;
  438. lvi.mask = LVIF_PARAM;
  439. b = ListView_GetItem( hwndList, &lvi );
  440. Assert( b );
  441. pTask = (LPTASKITEM) lvi.lParam;
  442. Assert( pTask );
  443. TraceFree( pTask->pszImageName );
  444. TraceFree( pTask->pszServiceName );
  445. TraceFree( pTask );
  446. }
  447. break;
  448. }
  449. break;
  450. }
  451. return TRUE;
  452. }