home *** CD-ROM | disk | FTP | other *** search
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Copyright (C) 1993-1995 Microsoft Corporation. All Rights Reserved.
- //
- // MODULE: procthrd.c
- //
- // PURPOSE: Implements process and thread enumeration/manipulation
- // functions.
- //
- // FUNCTIONS:
- // InitToolhelp32 - Dynamically resolves addresses of 32-bit
- // Toolhelp functions
- // RefreshThreadList - Enumerates and displays active threads
- // RefreshProcessList - Enumerates and displays active processes
- // GetProcessModule - Gets information about a specific module in
- // a specified process
- // KillProcess - Kills the specified process
- // GetModuleNameFromExe - Returns a Win16 app/DLL's module name from
- // its executable file.
- //
- //
- // COMMENTS:
- //
-
- #include <windows.h>
- #include <tlhelp32.h> // Required for ToolHelp32 functions
- #include <commctrl.h>
- #include "procthrd.h"
- #include "listview.h"
- #include "globals.h"
-
-
- //-------------------------------------------------------------------------
- // Type definitions for functions pointers used to call 32-bit Toolhelp
- // functions.
- typedef BOOL (WINAPI *MODULEWALK)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
- typedef BOOL (WINAPI *THREADWALK)(HANDLE hSnapshot, LPTHREADENTRY32 lpte);
- typedef BOOL (WINAPI *PROCESSWALK)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
- typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);
-
-
- //-------------------------------------------------------------------------
- // File-scope globals. These pointers are declared because we have to
- // dynamically link to these funtions. They are exported only by the
- // Windows 95 KERNEL32.DLL. Explicitly linking to them will make this
- // application unloadable on Windows NT and will produce an ugly system
- // dialog that isn't nice for end-users to see.
-
- static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
- static MODULEWALK pModule32First = NULL;
- static MODULEWALK pModule32Next = NULL;
- static PROCESSWALK pProcess32First = NULL;
- static PROCESSWALK pProcess32Next = NULL;
- static THREADWALK pThread32First = NULL;
- static THREADWALK pThread32Next = NULL;
-
-
- //-------------------------------------------------------------------------
- // Local function prototypes.
-
- BOOL GetProcessModule (DWORD dwPID, DWORD dwModuleID, LPMODULEENTRY32 lpMe32,
- DWORD cbMe32);
- BOOL GetModuleNameFromExe (LPCSTR szFileName, LPSTR szModuleName, WORD cbLen);
-
-
- //
- // FUNCTION: InitToolhelp32(void)
- //
- // PURPOSE: Initializes pointers to the 32-bit Toolhelp APIs that are
- // exported only by the Windows 95 KERNEL32.DLL.
- //
- // PARAMETERS:
- // None.
- //
- // RETURN VALUE:
- // TRUE if addresses of all needed 32-bit Toolhelp functions were
- // retrieved.
- // FALSE if we couldn't get the address of even one needed 32-bit
- // Toolhelp function
- //
- // COMMENTS:
- // This function is needed to initialize the function pointers to the
- // 32-bit Toolhelp functions because at this time, only the Windows 95
- // KERNEL32.DLL exports them. If we did not dynamically resolve the
- // addresses of these functions, this application would not even load
- // on anything but Windows 95.
- //
- // In the case of this sample, this function is called in InitApplication
- // which will prevent this application from even running if it can't
- // access the necessary functions.
- //
-
- BOOL InitToolhelp32 (void)
- {
- BOOL bRet;
- HANDLE hKernel;
-
-
- // Obtain a module handle to KERNEL so that we can get the addresses of
- // the 32-bit Toolhelp functions we need.
-
- hKernel = GetModuleHandle("KERNEL32.DLL");
-
- if (hKernel)
- {
- pCreateToolhelp32Snapshot =
- (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");
-
- pModule32First = (MODULEWALK)GetProcAddress(hKernel,
- "Module32First");
- pModule32Next = (MODULEWALK)GetProcAddress(hKernel,
- "Module32Next");
-
- pProcess32First = (PROCESSWALK)GetProcAddress(hKernel,
- "Process32First");
- pProcess32Next = (PROCESSWALK)GetProcAddress(hKernel,
- "Process32Next");
-
- pThread32First = (THREADWALK)GetProcAddress(hKernel,
- "Thread32First");
- pThread32Next = (THREADWALK)GetProcAddress(hKernel,
- "Thread32Next");
-
- // All of our addresses must be non-NULL in order for us to be
- // successful. If even one of these addresses is NULL, then we
- // must fail because we won't be able to walk one of the lists
- // we need to.
- bRet = pModule32First && pModule32Next && pProcess32First &&
- pProcess32Next && pThread32First && pThread32Next &&
- pCreateToolhelp32Snapshot;
- }
- else
- bRet = FALSE; // Couldn't even get a module handle to KERNEL.
-
- return bRet;
- }
-
-
- //
- // FUNCTION: RefreshThreadList(HWND, DWORD)
- //
- // PURPOSE: Enumerates and displays the list of threads owned by a
- // specified process.
- //
- // PARAMETERS:
- // hListView - Handle of the listview that lists thread information
- // dwOwnerPID - ID of process whose threads we will list
- //
- // RETURN VALUE:
- // TRUE if the threads were successfully enumerated and listed
- // FALSE if the threads could not be enumerated or listed
- //
- // COMMENTS:
- //
-
- BOOL RefreshThreadList (HWND hListView, DWORD dwOwnerPID)
- {
- HANDLE hThreadSnap;
- BOOL bRet;
- THREADENTRY32 te32 = {0};
-
- // Take a snapshot of all threads currently in the system.
- hThreadSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
- if (hThreadSnap == (HANDLE)-1)
- return (FALSE);
-
- // Clear the current contents of the thread list view (which are now old).
- ListView_DeleteAllItems(g_hwndThread);
-
- // Size of the THREADENTRY32 structure must be filled out before use.
- te32.dwSize = sizeof(THREADENTRY32);
-
- // Walk thread snapshot to find all threads of the process we want.
- // If the thread belongs to the process we want, add its information
- // to the display list.
- if (pThread32First(hThreadSnap, &te32))
- {
- do
- {
- if (te32.th32OwnerProcessID == dwOwnerPID)
- {
- TINFO ti;
-
- ti.tid = te32.th32ThreadID;
- ti.pidOwner = te32.th32OwnerProcessID;
- ti.tpDeltaPri = te32.tpDeltaPri;
- ti.tpBasePri = te32.tpBasePri;
-
- AddThreadItem(hListView, ti);
- }
- }
- while (pThread32Next(hThreadSnap, &te32));
- bRet = TRUE;
- }
- else
- bRet = FALSE; // Couldn't walk the list of threads.
-
- // Don't forget to clean up the snapshot object...
- CloseHandle (hThreadSnap);
-
- return (bRet);
- }
-
-
- //
- // FUNCTION: RefreshProcessList(HWND)
- //
- // PURPOSE: Enumerates and displays the list of processes.
- //
- // PARAMETERS:
- // hListView - Handle of the listview that lists process information
- //
- // RETURN VALUE:
- // TRUE if the processes were successfully enumerated and listed
- // FALSE if the processes could not be enumerated or listed
- //
- // COMMENTS:
- // Refreshes the list of processes by making a process snapshot and
- // putting info about each process into the listview control specifed by
- // hListView.
-
- BOOL RefreshProcessList (HWND hListView)
- {
- HANDLE hProcessSnap;
- BOOL bRet;
- PROCESSENTRY32 pe32 = {0};
-
- // Take a snapshot of all processes currently in the system.
- hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (hProcessSnap == (HANDLE)-1)
- return (FALSE);
-
- // Clear the current contents of the process list view (which are now old).
- ListView_DeleteAllItems(g_hwndProcess);
-
- // Size of the PROCESSENTRY32 structure must be filled out before use.
- pe32.dwSize = sizeof(PROCESSENTRY32);
-
- // Walk the snapshot of processes and for each process, get information
- // to display.
- if (pProcess32First(hProcessSnap, &pe32))
- {
- BOOL bGotModule;
- MODULEENTRY32 me32 = {0};
- PINFO pi = {{0}, 0};
-
- do
- {
- bGotModule = GetProcessModule(pe32.th32ProcessID,
- pe32.th32ModuleID,
- &me32,
- sizeof(MODULEENTRY32));
- if (bGotModule)
- {
- HANDLE hProcess;
-
- // Get actual priority class
- hProcess = OpenProcess (PROCESS_ALL_ACCESS,
- FALSE,
- pe32.th32ProcessID);
- pi.dwPriorityClass = GetPriorityClass (hProcess);
- CloseHandle (hProcess);
-
- // Get process's base priority value
- pi.pcPriClassBase = pe32.pcPriClassBase;
- pi.pid = pe32.th32ProcessID;
- pi.cntThreads = pe32.cntThreads;
-
- lstrcpy(pi.szFullPath, pe32.szExeFile);
-
- // Test to see if the app is a Win16 or Win32 app. If the
- // file name returned in the PROCESSENTRY32 and MODULEENTRY32
- // structures are equal, then we have a Win32 app, otherwise,
- // we have a Win16 app.
-
- if (!lstrcmpi (pe32.szExeFile, me32.szExePath))
- {
- // Win32 app, use MODULENETRY32 module name
- lstrcpy(pi.szModName, me32.szModule);
- pi.uAppType = EXETYPE_32BIT;
- }
- else
- {
- // Win16 app, get module name out of EXE header of file
- if (!GetModuleNameFromExe (pe32.szExeFile, pi.szModName,
- sizeof(pi.szModName)))
- {
- // If we can't get the module name for some reason, at
- // least put something in the module name.
- lstrcpy(pi.szModName, me32.szModule);
- }
- pi.uAppType = EXETYPE_16BIT;
- }
- AddProcessItem(hListView, pi);
- }
- }
- while (pProcess32Next(hProcessSnap, &pe32));
- bRet = TRUE;
- }
- else
- bRet = FALSE; // Couldn't walk the list of processes.
-
- // Don't forget to clean up the snapshot object...
- CloseHandle (hProcessSnap);
- return (bRet);
- }
-
-
- //
- // FUNCTION: GetProcessModule(DWORD, DWORD, LPMODULEENTRY32, DWORD)
- //
- // PURPOSE: Given a Process ID and module ID, return its module information.
- //
- // PARAMETERS:
- // dwPID - ID of process that owns the module we want information
- // about.
- // dwModuleID - ToolHelp32 ID of the module within the process
- // lpMe32 - Structure to return data about the module we want
- // cbMe32 - Size of the buffer pointed to by lpMe32--to make sure we
- // don't copy too much data into lpMe32.
- //
- // RETURN VALUE:
- // TRUE if it returns information about the specifed module.
- // FALSE if it could not enumerate the modules in the process, or the
- // module is not found in the process.
- //
- // COMMENTS:
- //
-
- BOOL GetProcessModule (DWORD dwPID,
- DWORD dwModuleID,
- LPMODULEENTRY32 lpMe32,
- DWORD cbMe32)
- {
- BOOL bRet;
- BOOL bFound = FALSE;
- HANDLE hModuleSnap;
- MODULEENTRY32 me32 = {0};
-
- // Take a snapshot of all modules in the specified process.
- hModuleSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
- if (hModuleSnap == (HANDLE)-1)
- return (FALSE);
-
- // Size of the MODULEENTRY32 structure must be initialized before use!
- me32.dwSize = sizeof(MODULEENTRY32);
-
- // Walk the module list of the process and find the module we are
- // interested in. Then, copy the information to the buffer pointed to
- // by lpMe32 so that we can return it to the caller.
- if (pModule32First(hModuleSnap, &me32))
- {
- do
- {
- if (me32.th32ModuleID == dwModuleID)
- {
- CopyMemory (lpMe32, &me32, cbMe32);
- bFound = TRUE;
- }
- }
- while (!bFound && pModule32Next(hModuleSnap, &me32));
-
- bRet = bFound; // If this sets bRet to FALSE, then dwModuleID
- // no longer exsists in the specified process.
- }
- else
- bRet = FALSE; // Couldn't walk module list.
-
- // Don't forget to clean up the snapshot object...
- CloseHandle (hModuleSnap);
-
- return (bRet);
- }
-
-
- //
- // FUNCTION: KillProcess(DWORD)
- //
- // PURPOSE: To kills a specified process
- //
- // PARAMETERS:
- // dwPID - Process ID of the process to kill
- //
- // RETURN VALUE:
- // TRUE if the specified process was killed
- // FALSE if it wasn't killed.
- //
- // COMMENTS:
- // KillProcess does not return until the process is terminated.
- //
-
- BOOL KillProcess (DWORD dwPID)
- {
- BOOL bRet;
- HANDLE hProcess;
-
- // Open the process to obtain a handle to it. If we get a handle,
- // try to terminate the process. Wait until the process is really
- // dead before returning.
- hProcess = OpenProcess (PROCESS_TERMINATE, FALSE, dwPID);
- if (hProcess != NULL)
- {
- bRet = TerminateProcess (hProcess, 0xFFFFFFFF);
-
- // Don't want to wait if the terminate fails. If the
- // process is still running and we can't terminate it,
- // then waiting for it would cause this process to stop
- // execution.
- if (bRet)
- WaitForSingleObject(hProcess, INFINITE);
-
- CloseHandle (hProcess);
- }
- else
- bRet = FALSE;
-
- return (bRet);
- }
-
-
- //
- // FUNCTION: GetModuleNameFromExe(LPCSTR, LPSTR, WORD)
- //
- // PURPOSE: Retrieves the module name of a Win16 app or DLL from its
- // excutable file.
- //
- // PARAMETERS:
- // szFileName - Executable file (.EXE or .DLL) from which to retrieve
- // module name
- // szModuleName - Points to buffer that receives the module name
- // cbLen - Specifies maximum length of szModuleName including NULL
- //
- // RETURN VALUE:
- // TRUE if the module name was succesfully copied into szModuleName.
- // FALSE if it wasn't killed.
- //
- // COMMENTS:
- // Works for Win16 New Executable files only.
- //
-
- BOOL GetModuleNameFromExe (LPCSTR szFileName, LPSTR szModuleName, WORD cbLen)
- {
- BOOL bResult;
- HANDLE hFile = NULL;
- HANDLE hFileMapping = NULL;
- PIMAGE_OS2_HEADER pNEHdr;
- PIMAGE_DOS_HEADER pDosExeHdr = NULL;
-
- // Open the file as read-only. (This file may be opened already by the
- // system if it is an application or DLL that is currently loaded.)
- // Create a read-only file mapping and map a read-only view of the file.
- // If we can't open the file for some reason, then return FALSE.
-
- hFile = CreateFile(szFileName,
- GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE)
- return FALSE;
-
- hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
- if (hFileMapping == NULL)
- {
- CloseHandle(hFile);
- return FALSE;
- }
-
- pDosExeHdr = (PIMAGE_DOS_HEADER)MapViewOfFile (hFileMapping,
- FILE_MAP_READ,
- 0,
- 0,
- 0);
- if (!pDosExeHdr)
- {
- CloseHandle(hFileMapping);
- CloseHandle(hFile);
- return FALSE;
- }
-
- __try
- {
- // Go to the beginning of the NE header.
- pNEHdr =
- (PIMAGE_OS2_HEADER)((LPSTR)pDosExeHdr + pDosExeHdr -> e_lfanew);
-
- // Check to make sure that the file has DOS and NE EXE headers
- if (pDosExeHdr -> e_magic == IMAGE_DOS_SIGNATURE
- && pNEHdr -> ne_magic == IMAGE_OS2_SIGNATURE)
- {
- lstrcpyn (szModuleName, (LPSTR)pNEHdr + pNEHdr -> ne_restab +1,
- min((BYTE)*((LPSTR)pNEHdr + pNEHdr -> ne_restab) + 1,
- cbLen));
- bResult = TRUE;
- }
- else
- bResult = FALSE;
-
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- // If an access violation occurs in the try block, we know the file
- // is not a NE file because it is too small to have a NE header, or
- // the offset of the NE header isn't close to being correct.
- bResult = FALSE;
- }
-
- // Clean up file mapping, all views of file mapping, and close the
- // file.
- UnmapViewOfFile(pDosExeHdr);
- CloseHandle(hFileMapping);
- CloseHandle(hFile);
-
- return bResult;
- }
-
-