Skip Menu |

This queue is for tickets about the Win32-Process CPAN distribution.

Report information
The Basics
Id: 12672
Status: open
Priority: 0/
Queue: Win32-Process

People
Owner: Nobody in particular
Requestors: rpirpag [...] gmx.at
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



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
This probably should be closed, based on the age alone. RT#46688 (https://rt.cpan.org/Ticket/Display.html?id=46688) is a related issue and the author of the ticket provided a patch. I've moved that patch into a PR: https://github.com/jandubois/win32-process/pull/6 -- Cheers, ZZ [ https://metacpan.org/author/ZOFFIX ]