class SaferRaiiWrapper {
public:
explicit SaferRaiiWrapper(const DWORD dwScopeIdIn = SAFER_LEVELID_NORMALUSER, const HANDLE hTokenIn = NULL)
: hToken(hTokenIn), LevelHandle(NULL), dwScopeId(dwScopeIdIn)
{/* throws std::logic_error on failure */
if(!::SaferCreateLevel(SAFER_SCOPEID_USER, this->dwScopeId, SAFER_LEVEL_OPEN, &LevelHandle, NULL))
{/* The API will translate NULL into our process token */
throw std::logic_error("Could not create software restriction policy");
}
if(!::SaferComputeTokenFromLevel(this->get_LevelHandle(), NULL, &hToken, NULL, NULL))
{
throw std::logic_error("Error occurred creating restricted policy");
}
} ;
virtual PROCESS_INFORMATION CreateProcessAsUser(const std::basic_string<TCHAR> &lpCommandLine,
STARTUPINFO *lpStartupInfoIn = NULL, DWORD dwCreationFlags = CREATE_NEW_CONSOLE,
const std::basic_string<TCHAR> &lpApplicationName = _T(""),
const std::basic_string<TCHAR> &lpCurrentDirectory = _T(""),
LPVOID lpEnvironment = NULL, BOOL bInheritHandles = FALSE,
SECURITY_ATTRIBUTES *lpProcessAttributes = NULL, SECURITY_ATTRIBUTES *lpThreadAttributes = NULL)
{
STARTUPINFO StartupInfoAlt = {0};
LPSTARTUPINFO lpStartupInfoActual = (lpStartupInfoIn != NULL) ? lpStartupInfoIn : &StartupInfoAlt;
PROCESS_INFORMATION Result = {0};
/* The child class may want to edit the startup params, so let them have that opportunity. */
std::basic_string<TCHAR> sCmdLine = lpCommandLine;
std::basic_string<TCHAR> sAppName = lpApplicationName;
std::basic_string<TCHAR> sCurDir = lpCurrentDirectory;
TCHAR *lpCmdLineWritable = new TCHAR[sCmdLine.capacity() + 1];
/* The command line needs to be writable. So make a writable one. */
try {
sCmdLine.copy(lpCmdLineWritable, sCmdLine.size());
lpCmdLineWritable[sCmdLine.size()] = _T('\0');
lpStartupInfoActual->cb = sizeof(STARTUPINFO);
lpStartupInfoActual->lpDesktop = NULL;
DoRunAs(this->hToken, (sAppName.empty() ? NULL : sAppName.c_str()),
lpCmdLineWritable, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags,
lpEnvironment, (sCurDir.empty() ? NULL : sCurDir.c_str()), lpStartupInfoActual, &Result);
} catch (...) {/* finally */
delete [] lpCmdLineWritable; lpCmdLineWritable = NULL;
throw;
}
delete [] lpCmdLineWritable; lpCmdLineWritable = NULL;
return Result;
} ;
HANDLE get_hToken(void) const
{
return hToken;
} ;
virtual ~SaferRaiiWrapper()
{
if(this->hToken != NULL || this->hToken != INVALID_HANDLE_VALUE)
::CloseHandle(this->hToken);
if(LevelHandle != NULL)
::SaferCloseLevel(this->LevelHandle);
} ;
virtual SaferRaiiWrapper &operator=(const SaferRaiiWrapper &OldClass)
{
if(this == &OldClass) return *this;
this->hToken = OldClass.get_hToken();
/* We need our own safer handle */
if(!::SaferCreateLevel(SAFER_SCOPEID_USER, this->dwScopeId, SAFER_LEVEL_OPEN, &LevelHandle, NULL))
{
throw std::logic_error("Could not create software restriction policy");
}
if(!::SaferComputeTokenFromLevel(this->get_LevelHandle(), NULL, &hToken, NULL, NULL))
{
throw std::logic_error("Error occurred creating restricted policy");
}
return *this;
} ;
protected:
virtual bool DoRunAs(HANDLE hTokenIn, LPCTSTR lpApplicationName,
LPTSTR lpCommandLine, SECURITY_ATTRIBUTES *lpProcessAttributes, SECURITY_ATTRIBUTES *lpThreadAttributes,
BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory,
STARTUPINFO *lpStartupInfoIn, PROCESS_INFORMATION *ProcessInformation)
{
/* For inheritors: This is your chance to stop any process creation from occurring. */
::CreateProcessAsUser(hTokenIn, lpApplicationName,
lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags,
lpEnvironment, lpCurrentDirectory, lpStartupInfoIn, ProcessInformation);
::CloseHandle(ProcessInformation->hProcess); ProcessInformation->hProcess = NULL;
::CloseHandle(ProcessInformation->hThread); ProcessInformation->hThread = NULL;
return true;
} ;
const SAFER_LEVEL_HANDLE &get_LevelHandle(void) const
{
return LevelHandle;
} ;
void set_LevelHandle(const SAFER_LEVEL_HANDLE &LevelHandleIn)
{
this->LevelHandle = LevelHandleIn;
} ;
void set_hToken(const HANDLE hToken)
{
this->hToken = hToken;
} ;
private:
HANDLE hToken;
SAFER_LEVEL_HANDLE LevelHandle;
const DWORD dwScopeId;
} ;