Subject: | Win32::Process Changes |
Hello,
Some Details: OS: Windows XP prof., Activestate Perl v5.6.1.
Module: libwin32-0.24
I made a change in the Process.xs because on my XP I had to add the privilege
SE_DEBUG_NAME to kill a process. With the original version I got allways access denied message. The process was a CGI script which was handled by the IIS.
The affected function is KillProcess. The function now calls EnablePrivilege() to get the correct access rights for the process who want to kill an other process.
I also added a function to get the elapsed time a process was running. I named it TimeRunning().
It is only a fast hack to make the Killprocess() working for me. Maybe it can be handled otherwise.
regards
Reinhard
#include <stdlib.h> // avoid BCC-5.0 brainmelt
#include <math.h> // avoid VC-5.0 brainmelt
#include "Process.hpp"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#if defined(__cplusplus)
#include <stdlib.h>
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.H"
#include "../ppport.h"
BOOL
EnablePrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable)
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, szPrivName, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
return((GetLastError() == ERROR_SUCCESS));
}
static BOOL
Create(cProcess* &cP, char* szAppName, char* szCommLine, DWORD Inherit,
DWORD CreateFlags, char* szCurrDir)
{
BOOL bRetVal;
void *env = NULL;
#if PERL_VERSION > 5
env = PerlEnv_get_childenv();
#endif
cP = NULL;
try {
cP = (cProcess*)new cProcess(szAppName,szCommLine,Inherit,CreateFlags,
env,szCurrDir);
bRetVal = cP->bRetVal;
}
catch (...) {
bRetVal = FALSE;
}
#if PERL_VERSION > 5
PerlEnv_free_childenv(env);
#endif
return bRetVal;
}
static BOOL
CreateW(cProcess* &cP,WCHAR* szAppName,WCHAR* szCommLine,DWORD Inherit,DWORD CreateFlags,WCHAR* szCurrDir)
{
// XXX environment will *not* be correctly inherited.
// Alas, we don't have corresponding Unicode accessor
// functions for the hosts environment.
cP = NULL;
try {
cP =(cProcess *) new cProcess(szAppName,szCommLine,Inherit,CreateFlags,szCurrDir);
}
catch (...) {
return(FALSE);
}
return(cP->bRetVal);
}
static BOOL
Open_(cProcess * &cP, DWORD pid, DWORD Inherit)
{
cP = NULL;
try {
cP = (cProcess *) new cProcess(pid, Inherit);
}
catch (...) {
return(FALSE);
}
return(cP->bRetVal);
}
static double
constant(char* name)
{
errno = 0;
switch (*name) {
case 'A':
break;
case 'B':
break;
case 'C':
if (strEQ(name, "CREATE_DEFAULT_ERROR_MODE"))
#ifdef CREATE_DEFAULT_ERROR_MODE
return CREATE_DEFAULT_ERROR_MODE;
#else
goto not_there;
#endif
if (strEQ(name, "CREATE_NEW_CONSOLE"))
#ifdef CREATE_NEW_CONSOLE
return CREATE_NEW_CONSOLE;
#else
goto not_there;
#endif
if (strEQ(name, "CREATE_NEW_PROCESS_GROUP"))
#ifdef CREATE_NEW_PROCESS_GROUP
return CREATE_NEW_PROCESS_GROUP;
#else
goto not_there;
#endif
if (strEQ(name, "CREATE_NO_WINDOW"))
#ifdef CREATE_NO_WINDOW
return CREATE_NO_WINDOW;
#else
goto not_there;
#endif
if (strEQ(name, "CREATE_SEPARATE_WOW_VDM"))
#ifdef CREATE_SEPARATE_WOW_VDM
return CREATE_SEPARATE_WOW_VDM;
#else
goto not_there;
#endif
if (strEQ(name, "CREATE_SUSPENDED"))
#ifdef CREATE_SUSPENDED
return CREATE_SUSPENDED;
#else
goto not_there;
#endif
if (strEQ(name, "CREATE_UNICODE_ENVIRONMENT"))
#ifdef CREATE_UNICODE_ENVIRONMENT
return CREATE_UNICODE_ENVIRONMENT;
#else
goto not_there;
#endif
break;
case 'D':
if (strEQ(name, "DEBUG_ONLY_THIS_PROCESS"))
#ifdef DEBUG_ONLY_THIS_PROCESS
return DEBUG_ONLY_THIS_PROCESS;
#else
goto not_there;
#endif
if (strEQ(name, "DEBUG_PROCESS"))
#ifdef DEBUG_PROCESS
return DEBUG_PROCESS;
#else
goto not_there;
#endif
if (strEQ(name, "DETACHED_PROCESS"))
#ifdef DETACHED_PROCESS
return DETACHED_PROCESS;
#else
goto not_there;
#endif
break;
case 'E':
break;
case 'F':
break;
case 'G':
break;
case 'H':
if (strEQ(name, "HIGH_PRIORITY_CLASS"))
#ifdef HIGH_PRIORITY_CLASS
return HIGH_PRIORITY_CLASS;
#else
goto not_there;
#endif
break;
case 'I':
if (strEQ(name, "IDLE_PRIORITY_CLASS"))
#ifdef IDLE_PRIORITY_CLASS
return IDLE_PRIORITY_CLASS;
#else
goto not_there;
#endif
if (strEQ(name, "INFINITE"))
#ifdef INFINITE
return INFINITE;
#else
goto not_there;
#endif
break;
case 'J':
break;
case 'K':
break;
case 'L':
break;
case 'M':
break;
case 'N':
if (strEQ(name, "NORMAL_PRIORITY_CLASS"))
#ifdef NORMAL_PRIORITY_CLASS
return NORMAL_PRIORITY_CLASS;
#else
goto not_there;
#endif
break;
case 'O':
break;
case 'P':
break;
case 'Q':
break;
case 'R':
if (strEQ(name, "REALTIME_PRIORITY_CLASS"))
#ifdef REALTIME_PRIORITY_CLASS
return REALTIME_PRIORITY_CLASS;
#else
goto not_there;
#endif
break;
case 'S':
break;
case 'T':
if (strEQ(name, "THREAD_PRIORITY_ABOVE_NORMAL"))
#ifdef THREAD_PRIORITY_ABOVE_NORMAL
return THREAD_PRIORITY_ABOVE_NORMAL;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_BELOW_NORMAL"))
#ifdef THREAD_PRIORITY_BELOW_NORMAL
return THREAD_PRIORITY_BELOW_NORMAL;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_ERROR_RETURN"))
#ifdef THREAD_PRIORITY_ERROR_RETURN
return THREAD_PRIORITY_ERROR_RETURN;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_HIGHEST"))
#ifdef THREAD_PRIORITY_HIGHEST
return THREAD_PRIORITY_HIGHEST;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_IDLE"))
#ifdef THREAD_PRIORITY_IDLE
return THREAD_PRIORITY_IDLE;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_LOWEST"))
#ifdef THREAD_PRIORITY_LOWEST
return THREAD_PRIORITY_LOWEST;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_NORMAL"))
#ifdef THREAD_PRIORITY_NORMAL
return THREAD_PRIORITY_NORMAL;
#else
goto not_there;
#endif
if (strEQ(name, "THREAD_PRIORITY_TIME_CRITICAL"))
#ifdef THREAD_PRIORITY_TIME_CRITICAL
return THREAD_PRIORITY_TIME_CRITICAL;
#else
goto not_there;
#endif
break;
case 'U':
break;
case 'V':
break;
case 'W':
break;
case 'X':
break;
case 'Y':
break;
case 'Z':
break;
}
errno = EINVAL;
return 0;
not_there:
errno = ENOENT;
return 0;
}
#if defined(__cplusplus)
}
#endif
MODULE = Win32::Process PACKAGE = Win32::Process
PROTOTYPES: DISABLE
BOOL
Create(cP,appname,cmdline,inherit,flags,curdir)
cProcess *cP = NULL;
char *appname
char *cmdline
BOOL inherit
DWORD flags
char *curdir
CODE:
if (USING_WIDE()) {
WCHAR wappname[MAX_PATH+1];
WCHAR wcmdline[MAX_PATH+1];
WCHAR wcurdir[MAX_PATH+1];
A2WHELPER(appname, wappname, sizeof(wappname));
A2WHELPER(cmdline, wcmdline, sizeof(wcmdline));
A2WHELPER(curdir, wcurdir, sizeof(wcurdir));
RETVAL = CreateW(cP, wappname, wcmdline, inherit, flags, wcurdir);
}
else {
RETVAL = Create(cP, appname, cmdline, inherit, flags, curdir);
}
OUTPUT:
cP
RETVAL
BOOL
Open(cP,pid,inherit)
cProcess *cP = NULL;
DWORD pid
BOOL inherit
CODE:
RETVAL = Open_(cP, pid, inherit);
OUTPUT:
cP
RETVAL
double
constant(name)
char *name
BOOL
Kill(cP,exitcode)
cProcess *cP
unsigned int exitcode
CODE:
RETVAL = cP->Kill(exitcode);
OUTPUT:
RETVAL
BOOL
Suspend(cP)
cProcess *cP
CODE:
RETVAL = cP->Suspend();
OUTPUT:
RETVAL
BOOL
Resume(cP)
cProcess *cP
CODE:
RETVAL = cP->Resume();
OUTPUT:
RETVAL
BOOL
GetPriorityClass(cP,priorityclass)
cProcess *cP
DWORD priorityclass = NO_INIT
CODE:
RETVAL = cP->GetPriorityClass(&priorityclass);
OUTPUT:
priorityclass
RETVAL
BOOL
SetPriorityClass(cP,priorityclass)
cProcess *cP
DWORD priorityclass
CODE:
RETVAL = cP->SetPriorityClass(priorityclass);
OUTPUT:
RETVAL
BOOL
GetProcessAffinityMask(cP,processAffinityMask,systemAffinityMask)
cProcess *cP
DWORD_PTR processAffinityMask = NO_INIT
DWORD_PTR systemAffinityMask = NO_INIT
CODE:
RETVAL = cP->GetProcessAffinityMask(&processAffinityMask,&systemAffinityMask);
OUTPUT:
processAffinityMask
systemAffinityMask
RETVAL
BOOL
SetProcessAffinityMask(cP,processAffinityMask)
cProcess *cP
DWORD processAffinityMask
CODE:
RETVAL = cP->SetProcessAffinityMask(processAffinityMask);
OUTPUT:
RETVAL
BOOL
GetExitCode(cP,exitcode)
cProcess *cP
DWORD exitcode = NO_INIT
CODE:
RETVAL = cP->GetExitCode(&exitcode);
OUTPUT:
exitcode
RETVAL
void
DESTROY(cP)
cProcess *cP
CODE:
delete cP;
BOOL
Wait(cP,timeout)
cProcess *cP
DWORD timeout
CODE:
RETVAL = (cP->Wait(timeout) == WAIT_OBJECT_0);
OUTPUT:
RETVAL
IV
get_process_handle(cP)
cProcess *cP
CODE:
RETVAL = reinterpret_cast<IV>(cP->GetProcessHandle());
OUTPUT:
RETVAL
DWORD
GetProcessID(cP)
cProcess *cP
CODE:
RETVAL = cP->GetProcessID();
OUTPUT:
RETVAL
BOOL
KillProcess(pid, OUT exitcode)
DWORD pid
int exitcode
PREINIT:
HANDLE ph;
DWORD dwExitCode;
HANDLE hToken;
int ret;
CODE:
{
exitcode = 1;
ret = 2;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
if(!EnablePrivilege(hToken, SE_DEBUG_NAME, TRUE))
{
ret = GetLastError();
exitcode = 0;
} else
{
ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!ph) {
ret = GetLastError();
printf("Process (%d) could not opened. Errorcode: %d\n", pid, RETVAL);
exitcode = 0;
} else
{
//printf("Trying to kill process..\n"); //for debug only
GetExitCodeProcess(ph, &dwExitCode);
if((ret = TerminateProcess(ph, dwExitCode)) == 0)
{
exitcode = 0;
} //else //for debug only
//{
//printf("Process %d was killed now\n", pid);
//}
CloseHandle(ph);
}
}
} else
{
ret = GetLastError();
exitcode = 0;
}
RETVAL = ret;
}
OUTPUT:
RETVAL
long
TimeRunning(pid, OUT exitcode, OUT elapsed)
DWORD pid
int exitcode
long elapsed;
PREINIT:
HANDLE ph;
FILETIME lpCreationTime;
FILETIME lpExitTime;
FILETIME lpKernelTime;
FILETIME lpUserTime;
SYSTEMTIME lpSystemTime;
long secs;
DWORD dwStart;
HANDLE hToken;
int ret;
CODE:
{
// Description:
// returns the creation time in seconds and the elapsed time in the 3th parameter
exitcode = 0;
RETVAL = 0;
elapsed = 0;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
if(!EnablePrivilege(hToken, SE_DEBUG_NAME, TRUE))
{
RETVAL = GetLastError();
} else
{
ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!ph)
{
RETVAL = GetLastError();
} else
{
if(GetProcessTimes(ph, &lpCreationTime, &lpExitTime, &lpKernelTime, &lpUserTime) == 0)
{
RETVAL = GetLastError();
} else
{
if(FileTimeToSystemTime(&lpCreationTime, &lpSystemTime)==0)
{
RETVAL = GetLastError();
} else
{
// time in seconds the process was created
secs = (long)(lpSystemTime.wHour*3600 + lpSystemTime.wMinute*60 + lpSystemTime.wSecond);
GetSystemTime(&lpSystemTime);
// calculate the difference between the current system time and the process creation time
elapsed = (long)(lpSystemTime.wHour*3600 + lpSystemTime.wMinute*60 + lpSystemTime.wSecond) - secs;
RETVAL = secs;
exitcode = 1;
}
}
}
}
CloseHandle(ph);
} else
{
RETVAL = GetLastError();
}
} // end CODE
OUTPUT:
RETVAL