/*++ Copyright (c) 1994-1998 Microsoft Corporation Module Name: tlist.c Abstract: This module implements a task list application. Author: Wesley Witt (wesw) 20-May-1994 Mike Sartain (mikesart) 28-Oct-1994 Added detailed task information Julian Jiggins (julianj) 19-Mar-1998 Added list processes using specific module feature Shaun Cox (shaunco) 9-Jul-1998 Display services running in processes Environment: User Mode --*/ #include "pch.h" #pragma hdrstop #include #include "psapi.h" #define BAD_PID ((DWORD)-1) DWORD numTasks; TASK_LIST tlist[MAX_TASKS]; BOOL fShowServices; BOOL fShowMtsPackages; const char *Blanks = " "; VOID Usage(VOID); VOID PrintThreadInfo(PTASK_LIST pTaskList); BOOL FMatchTaskName(LPTSTR szPN, LPTSTR szWindowTitle, LPTSTR szProcessName); VOID GetFirstPidWithName(LPTSTR szTask); VOID PrintTask( DWORD i ) { BOOL NameShown = FALSE; printf( "%4d %-16s", tlist[i].dwProcessId, tlist[i].ProcessName ); if (fShowServices && tlist[i].ServiceNames[0]) { printf( "Svcs: %s", tlist[i].ServiceNames); NameShown = TRUE; } if (fShowMtsPackages && tlist[i].MtsPackageNames[0]) { printf( "%sMts: %s", NameShown ? " " : "", tlist[i].MtsPackageNames); NameShown = TRUE; } if (!NameShown && tlist[i].hwnd) { if (fShowServices || fShowMtsPackages) { printf( "Title: %s", tlist[i].WindowTitle ); } else { printf( " %s", tlist[i].WindowTitle ); } } printf( "\n" ); } VOID PrintTaskTree( DWORD level, DWORD id ) { DWORD i; DetectOrphans( tlist, numTasks ); for (i=0; i 1 && (argv[1][0] == '-' || argv[1][0] == '/') && argv[1][1] == '?') { Usage(); } fTree = FALSE; fFindTasksUsingModule = FALSE; if (argc > 1) { if ((argv[1][0] == '-' || argv[1][0] == '/') && (argv[1][1] == 't' || argv[1][1] == 'T')) { fTree = TRUE; } else if ((argv[1][0] == '-' || argv[1][0] == '/') && (argv[1][1] == 's' || argv[1][1] == 'S')) { fShowServices = TRUE; } else if ((argv[1][0] == '-' || argv[1][0] == '/') && (argv[1][1] == 'k' || argv[1][1] == 'K')) { fShowMtsPackages = TRUE; } else if ((argv[1][0] == '-' || argv[1][0] == '/') && (argv[1][1] == 'p' || argv[1][1] == 'P') && argc == 3) { _strlwr(argv[2]); if (!strcmp(argv[2], "system process")) { printf("0\n"); return 0; } fPidOnly = TRUE; } else if ((argv[1][0] == '-' || argv[1][0] == '/') && (argv[1][1] == 'p' || argv[1][1] == 'P') && argc == 4) { _strlwr(argv[2]); if (!strcmp(argv[2], "system")) { _strlwr(argv[3]); if (!strcmp(argv[3], "process")) { printf("0\n"); return 0; } } Usage(); } else if ((argv[1][0] == '-' || argv[1][0] == '/') && (argv[1][1] == 'm' || argv[1][1] == 'M') && argc == 3) { fFindTasksUsingModule = TRUE; } else { szPN = argv[1]; if (!(dwPID = atol(szPN)) && szPN[0] != '0' && szPN[1] != 0) { dwPID = BAD_PID; cchPN = strlen(szPN); _strupr(szPN); } } } // // lets be god // EnableDebugPriv(); //#if 0 // XXX olegk - enable the block after RI with debugger tree // // Include 32bit modules in enumeration // { DWORD SymOpt = SymGetOptions(); SymOpt |= SYMOPT_INCLUDE_32BIT_MODULES; SymSetOptions(SYMOPT_INCLUDE_32BIT_MODULES); } //#endif // XXX olegk // // get the task list for the system // // // Get the process information for all active Win32 services. // This allows us to print the service names next to the processes // that host them. // dwNumServices = GetServiceProcessInfo( &pServiceInfo ); numTasks = GetTaskListEx( tlist, MAX_TASKS, cchPN || (dwPID != BAD_PID), dwNumServices, pServiceInfo); free( pServiceInfo ); if (fShowMtsPackages) { AddMtsPackageNames(tlist, numTasks); } // // enumerate all windows and try to get the window // titles for each task // te.tlist = tlist; te.numtasks = numTasks; GetWindowTitles( &te ); // // print the task list // if (fTree) { PrintTaskTree( 0, 0 ); } else if (fFindTasksUsingModule) { PrintTasksUsingModule(argv[2]); } else if (fPidOnly) { GetFirstPidWithName(argv[2]); } else { for (i=0; i> | <-t> | | | <-p >> | <-k> | <-s>\n" " [options]:\n" " -t\n" " Print Task Tree\n\n" " \n" " List module information for this task.\n\n" " \n" " The pattern can be a complete task\n" " name or a regular expression pattern\n" " to use as a match. Tlist matches the\n" " supplied pattern against the task names\n" " and the window titles.\n\n" " -k\n" " Show MTS packages active in each process.\n\n" " -m \n" " Lists all tasks that have DLL modules loaded\n" " in them that match the given pattern name\n\n" " -s\n" " Show services active in each process.\n\n" " -p \n" " Returns the PID of the process specified or -1\n" " if the specified process doesn't exist. If there\n" " are multiple instances of the process running only\n" " the instance with the first PID value is returned.\n\n" "\n"); ExitProcess(0); } // // Routines used to list all processes that have a specific module in use // BOOL FindSpecificModuleCallback( LPSTR Name, DWORD_PTR Base, DWORD Size, PVOID Context ) /*++ Routine Description: Callback function for module enumeration to find a specific module Arguments: Name - Module name Base - Base address Size - Size of image Context - User context pointer Return Value: TRUE - Continue enumeration FALSE - Stop enumeration --*/ { PFIND_MODULE_INFO pFindModuleInfo; pFindModuleInfo = (PFIND_MODULE_INFO)Context; if (MatchPattern(Name, pFindModuleInfo->szModuleToFind)) { pFindModuleInfo->fFound = TRUE; strcpy(pFindModuleInfo->szMatchingModuleName, Name); return FALSE; // Found Module so stop enumerating } return TRUE; } BOOL IsTaskUsingModule( PTASK_LIST pTask, LPTSTR szModuleName, LPTSTR szMatchingModuleName ) /*++ Routine Description: Checks if the given task has the given module loaded Arguments: pTaskList - task to search for module szModule - module name to search for Return Value: TRUE - if the module is loaded in the task FALSE - if the module is not loaded in the task --*/ { FIND_MODULE_INFO FindModuleInfo; FindModuleInfo.fFound = FALSE; FindModuleInfo.szModuleToFind = szModuleName; FindModuleInfo.szMatchingModuleName = szMatchingModuleName; EnumerateLoadedModules( (HANDLE) UlongToPtr(pTask->dwProcessId), FindSpecificModuleCallback, &FindModuleInfo ); return FindModuleInfo.fFound; } void PrintTasksUsingModule( LPTSTR szModuleName ) /*++ Routine Description: Enumerates through all the tasks in the system looking for those that have loaded modules of the given name. Arguments: szModule - module name to search for Return Value: None --*/ { BOOL fUsed = FALSE; DWORD i; CHAR szMatchingModuleName[64]; _strupr(szModuleName); // Needed for wildcarding for (i=0; idwProcessId); if (!hProcess) return; // print the CWD and CmdLine FPrintPEBInfo(hProcess); printf( " VirtualSize: %6ld KB" " PeakVirtualSize: %6ld KB\n", pTaskList->VirtualSize / 1024, pTaskList->PeakVirtualSize / 1024); printf( " WorkingSetSize:%6ld KB" " PeakWorkingSetSize:%6ld KB\n", pTaskList->WorkingSetSize / 1024, pTaskList->PeakWorkingSetSize / 1024); printf( " NumberOfThreads: %ld\n", pTaskList->NumberOfThreads); // if we got any threadinfo, spit it out if (pTaskList->pThreadInfo) { for (nThread = 0; nThread < pTaskList->NumberOfThreads; nThread++) { PTHREAD_INFO pThreadInfo = &pTaskList->pThreadInfo[nThread]; HANDLE hThread = TlistOpenThread(THREAD_QUERY_INFORMATION, FALSE, (DWORD)(DWORD_PTR)pThreadInfo->UniqueThread); printf(" %4d Win32StartAddr:0x%08x LastErr:0x%08x State:%s\n", HandleToUlong(pThreadInfo->UniqueThread), GetWin32StartAddress(hThread), GetLastThreadErr(hThread), szThreadState[min(pThreadInfo->ThreadState, MAX_THREADSTATE - 1)]); if (hThread) NtClose(hThread); } } // print the modules PrintModuleList( pTaskList->dwProcessId ); // close the hProcess CloseHandle(hProcess); } BOOL FMatchTaskName( LPTSTR szPN, LPTSTR szWindowTitle, LPTSTR szProcessName ) { LPTSTR szT; TCHAR szTName[PROCESS_SIZE]; strncpy( szTName, szProcessName, PROCESS_SIZE ); if (szT = strchr( szTName, '.' )) szT[0] = '\0'; if (MatchPattern( szTName, szPN ) || MatchPattern( szProcessName, szPN ) || MatchPattern( szWindowTitle, szPN )) { return TRUE; } return FALSE; }