📄 stafprocess.cpp
字号:
/*****************************************************************************//* Software Testing Automation Framework (STAF) *//* (C) Copyright IBM Corp. 2001 *//* *//* This software is licensed under the Common Public License (CPL) V1.0. *//*****************************************************************************/#include "STAF.h"#include "STAFProcess.h"#include "STAF_iostream.h"#include "STAFThread.h"#include "STAFMutexSem.h"#include "STAFEventSem.h"#include "STAFException.h"#include "STAFTrace.h"#include "STAFUtilWin32.h"#include "STAFInternalProcess.h"#include <deque>#include <map>#include <aclapi.h> // For CreateProcessAsUser()#include <errno.h> // For EACCES#define _WIN32_WINNT 0x400//F or some reason, winuser.h doesn't define these useful aliases#ifndef WINSTA_ALL_ACCESS#define WINSTA_ALL_ACCESS 0x0000037F#endif#ifndef DESKTOP_ALL_ACCESS#define DESKTOP_ALL_ACCESS 0x00001FF#endiftypedef struct PROFILEINFOIMPL { DWORD dwSize; // Must be set to sizeof(PROFILEINFO) DWORD dwFlags; // See flags above LPTSTR lpUserName; // User name (required) LPTSTR lpProfilePath; // Roaming profile path LPTSTR lpDefaultPath; // Default user profile path LPTSTR lpServerName; // Validating DC name in netbios format LPTSTR lpPolicyPath; // Path to the NT4 style policy file HANDLE hProfile; // Registry key handle - filled by function} PROFILEINFO, FAR * LPPROFILEINFO;// Typedefs for function pointers in USERENV.DLLtypedef BOOL (STDMETHODCALLTYPE FAR * LPFNLOADUSERPROFILE) ( HANDLE hToken, // user token LPPROFILEINFO lpProfileInfo // user profile information);typedef BOOL (STDMETHODCALLTYPE FAR * LPFNUNLOADUSERPROFILE) ( HANDLE hToken, // user token HANDLE hProfile // user profile handle);typedef BOOL (STDMETHODCALLTYPE FAR * LPFNCREATEENVBLOCK) ( LPVOID *lpEnvironment, // environment block HANDLE hToken, // user token BOOL bInherit // inheritance);typedef BOOL (STDMETHODCALLTYPE FAR * LPFNDESTROYENVBLOCK) ( LPVOID lpEnvironment // environment block);HMODULE sUserEnvLib = NULL;LPFNLOADUSERPROFILE sLoadUserProfileFunc = NULL;LPFNUNLOADUSERPROFILE sUnloadUserProfileFunc = NULL;LPFNCREATEENVBLOCK sCreateEnvironmentBlockFunc = NULL;LPFNDESTROYENVBLOCK sDestroyEnvironmentBlockFunc = NULL;HANDLE sProcessHeap = GetProcessHeap();// End of definitions for CreateUserAsProcess() stuff// Typedefs for function pointers in ADVAPI32.DLLtypedef BOOL (STDMETHODCALLTYPE FAR * LPFNSETSECURITYINFO) ( HANDLE hToken, // user token SE_OBJECT_TYPE ObjectType, // type of object SECURITY_INFORMATION SecurityInfo, // type of security information to set PSID psidOwner, // pointer to the new owner SID PSID psidGroup, // pointer to the new primary group SID PACL pDacl, // pointer to the new DACL PACL pSacl // pointer to the new SACL);HMODULE sAdvApi32Lib = NULL;LPFNSETSECURITYINFO sSetSecurityInfoFunc = NULL;// End of definitions for SetSecurityInfo() stuffstruct ProcessMonitorInfo{ ProcessMonitorInfo(STAFProcessHandle_t aHandle = 0, STAFProcessID_t aPID = 0, STAFProcessEndCallbackLevel1 aCallback = STAFProcessEndCallbackLevel1(), HANDLE aUsrToken = 0, HANDLE aUsrProfile = 0) : handle(aHandle), pid(aPID), callback(aCallback), hUsrToken(aUsrToken), hUsrProfile(aUsrProfile) { /* Do Nothing */ } STAFProcessHandle_t handle; STAFProcessID_t pid; STAFProcessEndCallbackLevel1 callback; unsigned int callbackLevel; HANDLE hUsrToken; HANDLE hUsrProfile;};typedef std::deque<ProcessMonitorInfo> ProcessMonitorList;typedef std::map<STAFProcessHandle_t, ProcessMonitorList> ProcessMonitorMap;struct ProcessMonitorThreadData{ HANDLE monitorWakeUp; ProcessMonitorMap monitorMap;};typedef STAFRefPtr<ProcessMonitorThreadData> ProcessMonitorThreadDataPtr;typedef std::deque<ProcessMonitorThreadDataPtr> ProcessMonitorThreadList;// Prototypesstatic BOOL InitUserEnv();static BOOL InitAdvApi32();static void GetPrivilegeError(HANDLE handle, STAFString &errorMsg);static int GrantAccessToWinsta(HANDLE hUsrToken, bool bGrant, STAFString &errorMsg);static void DeleteMatchingAces(ACL* pdacl, void* psid);static unsigned int ProcessMonitorThread(void *);static unsigned int UserAuthenticate(STAFUserID_t &hUsrToken, STAFString &username, STAFString &password, bool mustValidate, unsigned int *osRC, STAFString &errorMsg);// Static datastatic STAFMutexSem sMonitorDataSem;static STAFEventSem sThreadSyncSem;static ProcessMonitorThreadDataPtr sTempThreadData;static ProcessMonitorThreadList sThreadList;// Substitution characters valid for a shell command on Windowschar *gSTAFProcessShellSubstitutionChars = "cCpPtTuUwWxX%";/*****************************************************************************//* Helper APIs *//*****************************************************************************/// Writes trace warning with GetLastError()static void WriteTraceWarning(const STAFString &msg){ STAFTrace::trace(kSTAFTraceWarning, STAFString(msg) + " in STAFProcess::startProcess, OS_RC: " + GetLastError());}// Writes trace error with GetLastError()static void WriteTraceError(const STAFString &msg){ STAFTrace::trace(kSTAFTraceError, STAFString(msg) + " in STAFProcess::startProcess, OS_RC: " + GetLastError());}// Writes trace error with GetLastError()static void WriteTraceError2(const STAFString &msg){ STAFTrace::trace(kSTAFTraceError, STAFString(msg) + ", OS_RC: " + GetLastError());}// Writes trace error without GetLastError()static void WriteTraceError3(const STAFString &msg){ STAFTrace::trace(kSTAFTraceError, msg);}void InitProcessManager(){ static STAFMutexSem initSem; static bool alreadyInited = false; if (alreadyInited) return; STAFMutexSemLock initLock(initSem); if (alreadyInited) return; if (STAFUtilWin32GetWinType() & kSTAFWinNTPlus) { // Set USERENV.DLL function pointers for CreateUserAsProcess() // if running on Windows NT/2000/XP or above. int rc = InitUserEnv(); if (rc != TRUE) WriteTraceError2("InitUserEnv() failed in InitProcessManager()"); // Set ADVAPI32.DLL function pointers for SetSecurityInfo() // if running on Windows NT/2000/XP or above. rc = InitAdvApi32(); if (rc != TRUE) WriteTraceError2("InitAdvApi32() failed in InitProcessManager()"); } alreadyInited = true;}unsigned int ProcessMonitorThread(void *){ try { ProcessMonitorThreadDataPtr threadData = sTempThreadData; threadData->monitorWakeUp = CreateEvent(0, TRUE, FALSE, 0); sThreadSyncSem.post(); HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 }; unsigned int signaledHandleIndex = 0; ProcessMonitorMap::iterator iter = threadData->monitorMap.begin(); for(unsigned int numHandles = 0;; numHandles = 0) { // Use a nested block to ease lock usage { STAFMutexSemLock lock(sMonitorDataSem); for(iter = threadData->monitorMap.begin(); iter != threadData->monitorMap.end(); iter++) { if (numHandles == (MAXIMUM_WAIT_OBJECTS - 1)) break; handles[numHandles++] = iter->first; } handles[numHandles++] = threadData->monitorWakeUp; } DWORD rc = WaitForMultipleObjects(numHandles, handles, FALSE, INFINITE); if ((rc >= WAIT_OBJECT_0) && (rc <= (WAIT_OBJECT_0 + numHandles - 1))) { signaledHandleIndex = (unsigned int)(rc - WAIT_OBJECT_0); } else if ((rc >= WAIT_ABANDONED_0) && (rc <= (WAIT_ABANDONED_0 + numHandles - 1))) { signaledHandleIndex = (unsigned int)(rc - WAIT_ABANDONED_0); } else { // We either got WAIT_FAILED, WAIT_TIMEOUT or some other return // code which we weren't expecting, so spit out an error // message and continue if (rc == WAIT_FAILED) { WriteTraceError2("Got WAIT_FAILED from " "WaitForMultipleObjects() in " "ProcessMonitorThread()"); } else if (rc == WAIT_TIMEOUT) { STAFTrace::trace(kSTAFTraceError, "Got WAIT_TIMEOUT " "from WaitForMultipleObjects() " "in ProcessMonitorThread()"); } else { STAFTrace::trace(kSTAFTraceError, "Unexpected RC, " + STAFString(rc) + ", from WaitForMultipleObjects() " "in processMonitorThread()"); } } if (signaledHandleIndex != (numHandles - 1)) { unsigned int retCode = 0; // Get the process return code and then free the handle GetExitCodeProcess(handles[signaledHandleIndex], (LPDWORD)&retCode); CloseHandle(handles[signaledHandleIndex]); // Now lock the list while we search for the appropriate // entry and call the callback sMonitorDataSem.request(); for(iter = threadData->monitorMap.begin(); iter != threadData->monitorMap.end() && (iter->first != handles[signaledHandleIndex]); iter++) { /* Do Nothing */ } if (iter != threadData->monitorMap.end()) { ProcessMonitorList monitorList = iter->second; threadData->monitorMap.erase(iter->first); sMonitorDataSem.release(); for (ProcessMonitorList::iterator monitorIter = monitorList.begin(); monitorIter != monitorList.end(); ++monitorIter) { ProcessMonitorInfo &processMonitorInfo = *monitorIter; if (processMonitorInfo.hUsrToken != 0) { // Perform cleanup for CreateProcessAsUser() // Unload the user profile if (processMonitorInfo.hUsrProfile != 0) { if (!sUnloadUserProfileFunc( processMonitorInfo.hUsrToken, processMonitorInfo.hUsrProfile)) { WriteTraceError2("UnloadUserProfile() " "failed in ProcessMonitor" "Thread()"); } } // Clean up the interactive winsta/desktop DACLs STAFString errorMsg; GrantAccessToWinsta(processMonitorInfo.hUsrToken, FALSE, errorMsg); CloseHandle(processMonitorInfo.hUsrToken); } if (processMonitorInfo.callback.callback != 0) { processMonitorInfo.callback.callback( processMonitorInfo.pid, processMonitorInfo.handle, retCode, processMonitorInfo.callback.data); } } } else { // We shouldn't have been waiting on an object that is // no longer in our list. Spit out an error and continue. // Move along ... Nothing to see here. STAFTrace::trace(kSTAFTraceError, "Signaled object from " "WaitForMultipleObjects() not in list in " "processMonitorThread()"); sMonitorDataSem.release(); } } // end if we were not awoken by our event semaphore else ResetEvent(threadData->monitorWakeUp); } // end of endless for loop } catch (STAFException &se) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -