/***************************************************************** * nsProcess NSIS plugin v1.5 * * * * 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru) * * * * Source function FIND_PROC_BY_NAME based * * upon the Ravi Kochhar (kochhar@physiology.wisc.edu) code * * Thanks iceman_k (FindProcDLL plugin) and * * DITMan (KillProcDLL plugin) for point me up * *****************************************************************/ #define UNICODE #define _UNICODE #define WIN32_LEAN_AND_MEAN #include #include #include "ConvFunc.h" /* Defines */ #define NSIS_MAX_STRLEN 1024 #define SystemProcessInformation 5 #define STATUS_SUCCESS 0x00000000L #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004L typedef struct _SYSTEM_THREAD_INFO { FILETIME ftCreationTime; DWORD dwUnknown1; DWORD dwStartAddress; DWORD dwOwningPID; DWORD dwThreadID; DWORD dwCurrentPriority; DWORD dwBasePriority; DWORD dwContextSwitches; DWORD dwThreadState; DWORD dwUnknown2; DWORD dwUnknown3; DWORD dwUnknown4; DWORD dwUnknown5; DWORD dwUnknown6; DWORD dwUnknown7; } SYSTEM_THREAD_INFO; typedef struct _SYSTEM_PROCESS_INFO { DWORD dwOffset; DWORD dwThreadCount; DWORD dwUnkown1[6]; FILETIME ftCreationTime; DWORD dwUnkown2; DWORD dwUnkown3; DWORD dwUnkown4; DWORD dwUnkown5; DWORD dwUnkown6; WCHAR *pszProcessName; DWORD dwBasePriority; DWORD dwProcessID; DWORD dwParentProcessID; DWORD dwHandleCount; DWORD dwUnkown7; DWORD dwUnkown8; DWORD dwVirtualBytesPeak; DWORD dwVirtualBytes; DWORD dwPageFaults; DWORD dwWorkingSetPeak; DWORD dwWorkingSet; DWORD dwUnkown9; DWORD dwPagedPool; DWORD dwUnkown10; DWORD dwNonPagedPool; DWORD dwPageFileBytesPeak; DWORD dwPageFileBytes; DWORD dwPrivateBytes; DWORD dwUnkown11; DWORD dwUnkown12; DWORD dwUnkown13; DWORD dwUnkown14; SYSTEM_THREAD_INFO ati[ANYSIZE_ARRAY]; } SYSTEM_PROCESS_INFO; /* Include conversion functions */ #ifdef UNICODE #define xatoiW #define xitoaW #else #define xatoi #define xitoa #endif #include "ConvFunc.h" /* NSIS stack structure */ typedef struct _stack_t { struct _stack_t *next; TCHAR text[1]; } stack_t; stack_t **g_stacktop; TCHAR *g_variables; unsigned int g_stringsize; #define EXDLL_INIT() \ { \ g_stacktop=stacktop; \ g_variables=variables; \ g_stringsize=string_size; \ } /* Global variables */ TCHAR szBuf[NSIS_MAX_STRLEN]; /* Funtions prototypes and macros */ int FIND_PROC_BY_NAME(TCHAR *szProcessName, BOOL bTerminate); int popinteger(); void pushinteger(int integer); int popstring(TCHAR *str, int len); void pushstring(const TCHAR *str, int len); /* NSIS functions code */ void __declspec(dllexport) _FindProcess(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { EXDLL_INIT(); { int nError; popstring(szBuf, NSIS_MAX_STRLEN); nError=FIND_PROC_BY_NAME(szBuf, FALSE); pushinteger(nError); } } void __declspec(dllexport) _KillProcess(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { EXDLL_INIT(); { int nError; popstring(szBuf, NSIS_MAX_STRLEN); nError=FIND_PROC_BY_NAME(szBuf, TRUE); pushinteger(nError); } } void __declspec(dllexport) _Unload(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { } BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { return TRUE; } int FIND_PROC_BY_NAME(TCHAR *szProcessName, BOOL bTerminate) // Find the process "szProcessName" if it is currently running. // This works for Win95/98/ME and also WinNT/2000/XP. // The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE" // will both work. If bTerminate is TRUE, then process will be terminated. // // Return codes are as follows: // 0 = Success // 601 = No permission to terminate process // 602 = Not all processes terminated successfully // 603 = Process was not currently running // 604 = Unable to identify system type // 605 = Unsupported OS // 606 = Unable to load NTDLL.DLL // 607 = Unable to get procedure address from NTDLL.DLL // 608 = NtQuerySystemInformation failed // 609 = Unable to load KERNEL32.DLL // 610 = Unable to get procedure address from KERNEL32.DLL // 611 = CreateToolhelp32Snapshot failed // // Change history: // created 06/23/2000 - Ravi Kochhar (kochhar@physiology.wisc.edu) // http://www.neurophys.wisc.edu/ravi/software/ // modified 03/08/2002 - Ravi Kochhar (kochhar@physiology.wisc.edu) // - Borland-C compatible if BORLANDC is defined as // suggested by Bob Christensen // modified 03/10/2002 - Ravi Kochhar (kochhar@physiology.wisc.edu) // - Removed memory leaks as suggested by // Jonathan Richard-Brochu (handles to Proc and Snapshot // were not getting closed properly in some cases) // modified 14/11/2005 - Shengalts Aleksander aka Instructor (Shengalts@mail.ru): // - Combine functions FIND_PROC_BY_NAME and KILL_PROC_BY_NAME // - Code has been optimized // - Now kill all processes with specified name (not only one) // - Cosmetic improvements // - Removed error 632 (Invalid process name) // - Changed error 602 (Unable to terminate process for some other reason) // - BORLANDC define not needed // modified 04/01/2006 - Shengalts Aleksander aka Instructor (Shengalts@mail.ru): // - Removed CRT dependency // modified 21/04/2006 - Shengalts Aleksander aka Instructor (Shengalts@mail.ru): // - Removed memory leak as suggested by {_trueparuex^} // (handle to hSnapShot was not getting closed properly in some cases) // modified 21/04/2006 - Shengalts Aleksander aka Instructor (Shengalts@mail.ru): // - Removed memory leak as suggested by {_trueparuex^} // (handle to hSnapShot was not getting closed properly in some cases) // modified 19/07/2006 - Shengalts Aleksander aka Instructor (Shengalts@mail.ru): // - Code for WinNT/2000/XP has been rewritten // - Changed error codes // modified 31/08/2006 - Shengalts Aleksander aka Instructor (Shengalts@mail.ru): // - Removed memory leak as suggested by Daniel Vanesse { #ifndef UNICODE char szName[MAX_PATH]; #endif OSVERSIONINFO osvi; HMODULE hLib; HANDLE hProc; ULONG uError; BOOL bFound=FALSE; BOOL bSuccess=FALSE; BOOL bFailed=FALSE; // First check what version of Windows we're in osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); if (!GetVersionEx(&osvi)) return 604; if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT && osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) return 605; if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { // WinNT/2000/XP SYSTEM_PROCESS_INFO *spi; SYSTEM_PROCESS_INFO *spiCount; DWORD dwSize=0x4000; DWORD dwData; ULONG (WINAPI *NtQuerySystemInformationPtr)(ULONG, PVOID, LONG, PULONG); if (hLib=LoadLibraryA("NTDLL.DLL")) { NtQuerySystemInformationPtr=(ULONG(WINAPI *)(ULONG, PVOID, LONG, PULONG))GetProcAddress(hLib, "NtQuerySystemInformation"); if (NtQuerySystemInformationPtr) { while (1) { if (spi=LocalAlloc(LMEM_FIXED, dwSize)) { uError=(*NtQuerySystemInformationPtr)(SystemProcessInformation, spi, dwSize, &dwData); if (uError == STATUS_SUCCESS) break; LocalFree(spi); if (uError != STATUS_INFO_LENGTH_MISMATCH) { uError=608; break; } } else { uError=608; break; } dwSize*=2; } } else uError=607; FreeLibrary(hLib); } else uError=606; if (uError != STATUS_SUCCESS) return uError; spiCount=spi; while (1) { if (spiCount->pszProcessName) { #ifdef UNICODE if (!lstrcmpi(spiCount->pszProcessName, szProcessName)) #else WideCharToMultiByte(CP_ACP, 0, spiCount->pszProcessName, -1, szName, MAX_PATH, NULL, NULL); if (!lstrcmpi(szName, szProcessName)) #endif { // Process found bFound=TRUE; if (bTerminate == TRUE) { // Open for termination if (hProc=OpenProcess(PROCESS_TERMINATE, FALSE, spiCount->dwProcessID)) { if (TerminateProcess(hProc, 0)) bSuccess=TRUE; else bFailed=TRUE; CloseHandle(hProc); } } else break; } } if (spiCount->dwOffset == 0) break; spiCount=(SYSTEM_PROCESS_INFO *)((char *)spiCount + spiCount->dwOffset); } LocalFree(spi); } else { // Win95/98/ME PROCESSENTRY32 pe; TCHAR *pName; HANDLE hSnapShot; BOOL bResult; HANDLE (WINAPI *CreateToolhelp32SnapshotPtr)(DWORD, DWORD); BOOL (WINAPI *Process32FirstPtr)(HANDLE, LPPROCESSENTRY32); BOOL (WINAPI *Process32NextPtr)(HANDLE, LPPROCESSENTRY32); if (hLib=LoadLibraryA("KERNEL32.DLL")) { CreateToolhelp32SnapshotPtr=(HANDLE(WINAPI *)(DWORD, DWORD)) GetProcAddress(hLib, "CreateToolhelp32Snapshot"); Process32FirstPtr=(BOOL(WINAPI *)(HANDLE, LPPROCESSENTRY32)) GetProcAddress(hLib, "Process32First"); Process32NextPtr=(BOOL(WINAPI *)(HANDLE, LPPROCESSENTRY32)) GetProcAddress(hLib, "Process32Next"); if (CreateToolhelp32SnapshotPtr && Process32NextPtr && Process32FirstPtr) { // Get a handle to a Toolhelp snapshot of all the systems processes. if ((hSnapShot=(*CreateToolhelp32SnapshotPtr)(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE) { // Get the first process' information. pe.dwSize=sizeof(PROCESSENTRY32); bResult=(*Process32FirstPtr)(hSnapShot, &pe); // While there are processes, keep looping and checking. while (bResult) { //Get file name for (pName=pe.szExeFile + lstrlen(pe.szExeFile) - 1; *pName != '\\' && *pName != '\0'; --pName); if (!lstrcmpi(++pName, szProcessName)) { // Process found bFound=TRUE; if (bTerminate == TRUE) { // Open for termination if (hProc=OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID)) { if (TerminateProcess(hProc, 0)) bSuccess=TRUE; else bFailed=TRUE; CloseHandle(hProc); } } else break; } //Keep looking bResult=(*Process32NextPtr)(hSnapShot, &pe); } CloseHandle(hSnapShot); } else uError=611; } else uError=610; FreeLibrary(hLib); } else uError=609; } if (bFound == FALSE) return 603; if (bTerminate == TRUE) { if (bSuccess == FALSE) return 601; if (bFailed == TRUE) return 602; } return 0; } int popinteger() { TCHAR szInt[32]; popstring(szInt, 32); #ifdef UNICODE return xatoiW(szInt); #else return xatoi(szInt); #endif } void pushinteger(int integer) { TCHAR szInt[32]; #ifdef UNICODE xitoaW(integer, szInt, 0); #else xitoa(integer, szInt, 0); #endif pushstring(szInt, 32); } //Function: Removes the element from the top of the NSIS stack and puts it in the buffer int popstring(TCHAR *str, int len) { stack_t *th; if (!g_stacktop || !*g_stacktop) return 1; th=(*g_stacktop); lstrcpyn(str, th->text, len); *g_stacktop=th->next; GlobalFree((HGLOBAL)th); return 0; } //Function: Adds an element to the top of the NSIS stack void pushstring(const TCHAR *str, int len) { stack_t *th; if (!g_stacktop) return; th=(stack_t*)GlobalAlloc(GPTR, sizeof(stack_t) + len); lstrcpyn(th->text, str, len); th->next=*g_stacktop; *g_stacktop=th; }