|
From: <co...@us...> - 2008-05-16 00:24:13
|
Update of /cvsroot/aolserver/knutil/include In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv6393/include Added Files: knexportlibraryknutilmodule.h knkillprocess_win32.h Log Message: Added this library to the AOLServer.com repository. It contains a number of C/C++ utilities, some of which integrate into AOLServer, and many of which standalone. A portion of the library is required for the knregistration module, which will be checked in next. I believe this compiles fine in "native" AOLServer, but it has not been tested recently. --- NEW FILE: knexportlibraryknutilmodule.h --- /* /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ * Defines this modules as part of the knutil.dll. * See knexportlibraryknutil.h for more details. */ #define EXPORT_LIBRARY_KNUTIL_MODULE #include "knutil/knexportlibraryknutil.h" --- NEW FILE: knkillprocess_win32.h --- /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ /* * This code is from http://www.codeproject.com/threads/killprocess.asp * knprocmgr uses it to kill processes on windows given the process name since * processes are spawned using cmd.exe and the process id available is only * that of the cmd.exe. */ #include <tlhelp32.h> #include "windows.h" typedef LONG NTSTATUS; typedef LONG KPRIORITY; #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define SystemProcessesAndThreadsInformation 5 typedef struct _CLIENT_ID { DWORD UniqueProcess; DWORD UniqueThread; } CLIENT_ID; typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING; typedef struct _VM_COUNTERS { SIZE_T PeakVirtualSize; SIZE_T VirtualSize; ULONG PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; } VM_COUNTERS; typedef struct _SYSTEM_THREADS { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; LONG State; LONG WaitReason; } SYSTEM_THREADS, * PSYSTEM_THREADS; // Note that the size of the SYSTEM_PROCESSES structure is // different on NT 4 and Win2K, but we don't care about it, // since we don't access neither IoCounters member nor //Threads array typedef struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved1[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; #if _WIN32_WINNT >= 0x500 IO_COUNTERS IoCounters; #endif SYSTEM_THREADS Threads[1]; } SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; class CKillProcess { private: //Functions loaded from Kernel32 typedef HANDLE (WINAPI *PFCreateToolhelp32Snapshot)( DWORD dwFlags, DWORD th32ProcessID ); typedef BOOL (WINAPI *PFProcess32First)( HANDLE hSnapshot, LPPROCESSENTRY32 lppe ); typedef BOOL (WINAPI *PFProcess32Next)( HANDLE hSnapshot, LPPROCESSENTRY32 lppe ); // Native NT API Definitions typedef NTSTATUS (WINAPI * PFZwQuerySystemInformation) (UINT, PVOID, ULONG, PULONG); typedef HANDLE (WINAPI* PFGetProcessHeap)(VOID); typedef LPVOID (WINAPI* PFHeapAlloc) (HANDLE,DWORD,SIZE_T); typedef BOOL (WINAPI* PFHeapFree)(HANDLE,DWORD,LPVOID); public: CKillProcess() : FCreateToolhelp32Snapshot(NULL), FProcess32First(NULL), FProcess32Next(NULL), m_hKernelLib(NULL), m_hNTLib(NULL) { m_hKernelLib = ::LoadLibraryA("Kernel32"); if (m_hKernelLib) { // Find ToolHelp functions FCreateToolhelp32Snapshot = (PFCreateToolhelp32Snapshot) ::GetProcAddress(m_hKernelLib, "CreateToolhelp32Snapshot"); FProcess32First = (PFProcess32First) ::GetProcAddress(m_hKernelLib, "Process32First"); FProcess32Next = (PFProcess32Next) ::GetProcAddress(m_hKernelLib, "Process32Next"); } if(!FCreateToolhelp32Snapshot || !FProcess32First || !FProcess32Next) { // i.e. we couldn't find the ToolHelp functions, //so we must be on NT4. Let's load the // undocumented one instead. if(!m_hKernelLib) return; // can't do anything at all without //the kernel. m_hNTLib = ::LoadLibraryA("ntdll.dll"); if(m_hNTLib) { FQuerySysInfo = (PFZwQuerySystemInformation) ::GetProcAddress(m_hNTLib, "ZwQuerySystemInformation"); // load some support funcs from the kernel FGetProcessHeap = (PFGetProcessHeap) ::GetProcAddress(m_hKernelLib, "GetProcessHeap"); FHeapAlloc = (PFHeapAlloc) ::GetProcAddress(m_hKernelLib, "HeapAlloc"); FHeapFree = (PFHeapFree) ::GetProcAddress(m_hKernelLib, "HeapFree"); } } } ~CKillProcess() { if(m_hKernelLib) FreeLibrary(m_hKernelLib); if(m_hNTLib) FreeLibrary(m_hNTLib); } bool KillProcess(IN const char* pstrProcessName, OUT int *exitcode) { DWORD dwId; HANDLE hProcess = FindProcess(pstrProcessName, dwId); BOOL bResult; if(!hProcess) return true; // TerminateAppEnum() posts WM_CLOSE to all windows whose PID // matches your process's. ::EnumWindows((WNDENUMPROC) CKillProcess::TerminateAppEnum, (LPARAM) dwId); // Wait on the handle. If it signals, great. //If it times out, then you kill it. if(WaitForSingleObject(hProcess, 5000) !=WAIT_OBJECT_0) bResult = TerminateProcess(hProcess,static_cast<UINT>(-1)); else bResult = TRUE; CloseHandle(hProcess); if (exitcode) *exitcode = -1; return bResult == TRUE; } HANDLE FindProcess(IN const char* pstrProcessName, OUT DWORD& dwId) { if(!m_hKernelLib) return NULL; if(FCreateToolhelp32Snapshot && FProcess32First && FProcess32Next) // use toolhelpapi return THFindProcess(pstrProcessName, dwId); if(FQuerySysInfo && FHeapAlloc && FGetProcessHeap && FHeapFree) // use NT api return NTFindProcess(pstrProcessName, dwId); // neither one got loaded. Strange. return NULL; } private: HANDLE THFindProcess(IN const char* pstrProcessName, OUT DWORD& dwId) { HANDLE hSnapShot=NULL; HANDLE hResult = NULL; PROCESSENTRY32 processInfo; char* pstrExeName; bool bFirst = true; ::ZeroMemory(&processInfo, sizeof(PROCESSENTRY32)); processInfo.dwSize = sizeof(PROCESSENTRY32); hSnapShot = FCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0); if(hSnapShot == INVALID_HANDLE_VALUE) return NULL; // ok now let's iterate with Process32Next until we // match up the name of our process while((bFirst ? FProcess32First(hSnapShot, &processInfo) : FProcess32Next(hSnapShot, &processInfo))) { bFirst = false; // we need to check for path... and extract // just the exe name pstrExeName = strrchr(processInfo.szExeFile, '\\'); if(!pstrExeName) pstrExeName = processInfo.szExeFile; else pstrExeName++; // skip the \ // ok now compare against our process name if(stricmp(pstrExeName, pstrProcessName) == 0) // wee weee we found it { // let's get a HANDLE on it hResult=OpenProcess( SYNCHRONIZE|PROCESS_TERMINATE, TRUE, processInfo.th32ProcessID); dwId = processInfo.th32ProcessID; break; } } // while(Process32Next(hSnapShot, &processInfo){ if(hSnapShot) CloseHandle(hSnapShot); return hResult; } HANDLE NTFindProcess(IN const char* pstrProcessName, OUT DWORD& dwId) { HANDLE hHeap = FGetProcessHeap(); NTSTATUS Status; ULONG cbBuffer = 0x8000; PVOID pBuffer = NULL; HANDLE hResult = NULL; // it is difficult to say a priory which size of // the buffer will be enough to retrieve all // information, so we startwith 32K buffer and // increase its size until we get the // information successfully do { pBuffer = HeapAlloc(hHeap, 0, cbBuffer); if (pBuffer == NULL) return SetLastError( ERROR_NOT_ENOUGH_MEMORY), NULL; Status = FQuerySysInfo( SystemProcessesAndThreadsInformation, pBuffer, cbBuffer, NULL); if (Status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(hHeap, 0, pBuffer); cbBuffer *= 2; } else if (!NT_SUCCESS(Status)) { HeapFree(hHeap, 0, pBuffer); return SetLastError(Status), NULL; } } while (Status == STATUS_INFO_LENGTH_MISMATCH); PSYSTEM_PROCESSES pProcesses = (PSYSTEM_PROCESSES)pBuffer; for (;;) { PCWSTR pszProcessName = pProcesses->ProcessName.Buffer; if (pszProcessName == NULL) pszProcessName = L"Idle"; CHAR szProcessName[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, pszProcessName, -1,szProcessName, MAX_PATH, NULL, NULL); if(stricmp(szProcessName, pstrProcessName) == 0) // found it { hResult=OpenProcess( SYNCHRONIZE|PROCESS_TERMINATE, TRUE, pProcesses->ProcessId); dwId = pProcesses->ProcessId; break; } if (pProcesses->NextEntryDelta == 0) break; // find the address of the next process // structure pProcesses = (PSYSTEM_PROCESSES)( ((LPBYTE)pProcesses) + pProcesses->NextEntryDelta); } HeapFree(hHeap, 0, pBuffer); return hResult; } // callback function for window enumeration static BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) { DWORD dwID ; GetWindowThreadProcessId(hwnd, &dwID) ; if(dwID == (DWORD)lParam) { PostMessage(hwnd, WM_CLOSE, 0, 0) ; } return TRUE ; } HMODULE m_hNTLib; HMODULE m_hKernelLib; // ToolHelp related functions PFCreateToolhelp32Snapshot FCreateToolhelp32Snapshot; PFProcess32First FProcess32First; PFProcess32Next FProcess32Next; // native NT api functions PFZwQuerySystemInformation FQuerySysInfo; PFGetProcessHeap FGetProcessHeap; PFHeapAlloc FHeapAlloc; PFHeapFree FHeapFree; }; |