2020-06-08 16:17:37 +01:00
# include "stdafx.h"
# include "SbieUtils.h"
# include <QCoreApplication>
# include <ntstatus.h>
# define WIN32_NO_STATUS
typedef long NTSTATUS ;
# include <windows.h>
# include "SbieDefs.h"
# include "..\..\Sandboxie\common\win32_ntddk.h"
int GetServiceStatus ( const wchar_t * name )
{
SC_HANDLE scm = OpenSCManager ( nullptr , nullptr , SC_MANAGER_ENUMERATE_SERVICE ) ;
if ( ! scm )
return - 1 ;
SC_HANDLE service = OpenService ( scm , name , SERVICE_QUERY_STATUS ) ;
if ( ! service ) {
CloseServiceHandle ( scm ) ;
return 0 ;
}
DWORD dwBytesNeeded ;
SERVICE_STATUS_PROCESS sStatus ;
BOOL result = QueryServiceStatusEx ( service , SC_STATUS_PROCESS_INFO , ( LPBYTE ) & sStatus , sizeof ( SERVICE_STATUS_PROCESS ) , & dwBytesNeeded ) ;
CloseServiceHandle ( service ) ;
CloseServiceHandle ( scm ) ;
if ( result = = 0 )
return - 1 ;
return sStatus . dwCurrentState ;
}
bool IsProcessElevatd ( )
{
ULONG returnLength ;
TOKEN_ELEVATION elevation ;
if ( NT_SUCCESS ( NtQueryInformationToken ( /*NtCurrentProcessToken()*/ ( ( HANDLE ) ( LONG_PTR ) - 4 ) , TokenElevation , & elevation , sizeof ( TOKEN_ELEVATION ) , & returnLength ) ) )
return ! ! elevation . TokenIsElevated ;
return false ;
}
SB_STATUS CSbieUtils : : DoAssist ( )
{
QStringList Args = QCoreApplication : : arguments ( ) ;
int AssistPos = Args . indexOf ( " -assist " ) ;
if ( AssistPos = = - 1 )
return SB_OK ;
SB_STATUS Status = ExecOps ( Args . mid ( AssistPos + 1 ) ) ;
if ( Status . IsError ( ) )
return Status ;
return SB_ERR ( " OK " , ERROR_OK ) ;
}
SB_STATUS CSbieUtils : : Start ( EComponent Component )
{
QStringList Ops ;
2020-07-04 11:07:36 +01:00
if ( ! IsInstalled ( Component ) )
Install ( Component , Ops ) ;
2020-06-08 16:17:37 +01:00
Start ( Component , Ops ) ;
return ElevateOps ( Ops ) ;
}
void CSbieUtils : : Start ( EComponent Component , QStringList & Ops )
{
if ( ( Component & eDriver ) ! = 0 & & GetServiceStatus ( SBIEDRV ) ! = SERVICE_RUNNING )
2020-07-04 11:07:36 +01:00
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|start| " SBIEDRV ) ) ;
2020-06-08 16:17:37 +01:00
if ( ( Component & eService ) ! = 0 & & GetServiceStatus ( SBIESVC ) ! = SERVICE_RUNNING )
2020-07-04 11:07:36 +01:00
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|start| " SBIESVC ) ) ;
2020-06-08 16:17:37 +01:00
}
SB_STATUS CSbieUtils : : Stop ( EComponent Component )
{
QStringList Ops ;
Stop ( Component , Ops ) ;
return ElevateOps ( Ops ) ;
}
void CSbieUtils : : Stop ( EComponent Component , QStringList & Ops )
{
if ( ( Component & eService ) ! = 0 & & GetServiceStatus ( SBIESVC ) ! = SERVICE_STOPPED )
2020-07-04 11:07:36 +01:00
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|stop| " SBIESVC ) ) ;
2020-06-08 16:17:37 +01:00
if ( ( Component & eDriver ) ! = 0 & & GetServiceStatus ( SBIEDRV ) ! = SERVICE_STOPPED )
2020-07-04 11:07:36 +01:00
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|stop| " SBIEDRV ) ) ;
2020-06-08 16:17:37 +01:00
}
bool CSbieUtils : : IsRunning ( EComponent Component )
{
if ( ( Component & eDriver ) ! = 0 & & GetServiceStatus ( SBIEDRV ) ! = SERVICE_RUNNING )
return false ;
if ( ( Component & eService ) ! = 0 & & GetServiceStatus ( SBIESVC ) ! = SERVICE_RUNNING )
return false ;
return true ;
}
SB_STATUS CSbieUtils : : Install ( EComponent Component )
{
QStringList Ops ;
Install ( Component , Ops ) ;
return ElevateOps ( Ops ) ;
}
void CSbieUtils : : Install ( EComponent Component , QStringList & Ops )
{
QString HomePath = QCoreApplication : : applicationDirPath ( ) . replace ( " / " , " \\ " ) ; // "C:\\Program Files\\Sandboxie "
2020-09-12 09:09:24 +01:00
if ( ( Component & eDriver ) ! = 0 & & GetServiceStatus ( SBIEDRV ) = = 0 ) // todo: why when we are admin we need \??\ and else not and why knd util from console as admin also does not need that???
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|install| " SBIEDRV L " | " ) + " \" \\ ?? \\ " + HomePath + " \\ " + QString : : fromWCharArray ( SBIEDRV_SYS ) + " \" " + " |type=kernel|start=demand|altitude=86900 " ) ;
2020-07-04 11:07:36 +01:00
if ( ( Component & eService ) ! = 0 & & GetServiceStatus ( SBIESVC ) = = 0 ) {
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|install| " SBIESVC L " | " ) + " \" " + HomePath + " \\ " + QString : : fromWCharArray ( SBIESVC_EXE ) + " \" " + " |type=own|start=auto|display= \" Sandboxie Service \" |group=UIGroup " ) ;
2020-09-05 16:45:39 +01:00
Ops . append ( " reg.exe|ADD|HKLM \\ SYSTEM \\ ControlSet001 \\ Services \\ SbieSvc|/v|PreferExternalManifest|/t|REG_DWORD|/d|1|/f " ) ;
2020-07-04 11:07:36 +01:00
}
2020-06-08 16:17:37 +01:00
}
SB_STATUS CSbieUtils : : Uninstall ( EComponent Component )
{
QStringList Ops ;
Stop ( Component , Ops ) ;
Uninstall ( Component , Ops ) ;
return ElevateOps ( Ops ) ;
}
void CSbieUtils : : Uninstall ( EComponent Component , QStringList & Ops )
{
if ( ( Component & eService ) ! = 0 & & GetServiceStatus ( SBIESVC ) ! = 0 )
2020-07-04 11:07:36 +01:00
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|delete| " SBIESVC ) ) ;
2020-06-08 16:17:37 +01:00
if ( ( Component & eDriver ) ! = 0 & & GetServiceStatus ( SBIEDRV ) ! = 0 )
2020-07-04 11:07:36 +01:00
Ops . append ( QString : : fromWCharArray ( L " kmdutil.exe|delete| " SBIEDRV ) ) ;
2020-06-08 16:17:37 +01:00
}
bool CSbieUtils : : IsInstalled ( EComponent Component )
{
if ( ( Component & eDriver ) ! = 0 & & GetServiceStatus ( SBIEDRV ) = = 0 )
return false ;
if ( ( Component & eService ) ! = 0 & & GetServiceStatus ( SBIESVC ) = = 0 )
return false ;
return true ;
}
SB_STATUS CSbieUtils : : ElevateOps ( const QStringList & Ops )
{
if ( Ops . isEmpty ( ) )
return SB_OK ;
if ( IsProcessElevatd ( ) )
return ExecOps ( Ops ) ;
wstring path = QCoreApplication : : applicationFilePath ( ) . toStdWString ( ) ;
wstring params = L " -assist " + Ops . join ( " " ) . toStdWString ( ) ;
SHELLEXECUTEINFO shex ;
memset ( & shex , 0 , sizeof ( SHELLEXECUTEINFO ) ) ;
shex . cbSize = sizeof ( SHELLEXECUTEINFO ) ;
shex . fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI ;
shex . hwnd = NULL ;
shex . lpFile = path . c_str ( ) ;
shex . lpParameters = params . c_str ( ) ;
shex . nShow = SW_SHOWNORMAL ;
shex . lpVerb = L " runas " ;
if ( ! ShellExecuteEx ( & shex ) )
return SB_ERR ( " Admin rights required " ) ;
return SB_ERR ( OP_ASYNC ) ;
}
SB_STATUS CSbieUtils : : ExecOps ( const QStringList & Ops )
{
foreach ( const QString & Op , Ops )
{
QStringList Args = Op . split ( " | " ) ;
2020-07-04 11:07:36 +01:00
QString Prog = Args . takeFirst ( ) ;
2020-06-08 16:17:37 +01:00
QProcess Proc ;
2020-07-04 11:07:36 +01:00
Proc . execute ( Prog , Args ) ;
2020-06-08 16:17:37 +01:00
Proc . waitForFinished ( ) ;
int ret = Proc . exitCode ( ) ;
if ( ret ! = 0 )
return SB_ERR ( " Failed to execute: " + Args . join ( " " ) ) ;
}
return SB_OK ;
2020-09-12 09:09:24 +01:00
}
//////////////////////////////////////////////////////////////////////////////
// Shell integration
int CSbieUtils : : IsContextMenu ( )
{
if ( ! CheckRegValue ( L " Software \\ Classes \\ * \\ shell \\ sandbox \\ command " ) )
return 0 ;
if ( ! CheckRegValue ( L " software \\ classes \\ folder \\ shell \\ sandbox \\ command " ) )
return 1 ;
return 2 ;
}
bool CSbieUtils : : CheckRegValue ( const wchar_t * key )
{
HKEY hkey ;
LONG rc = RegOpenKeyEx ( HKEY_CURRENT_USER , key , 0 , KEY_READ , & hkey ) ;
if ( rc ! = 0 )
return false ;
ULONG type ;
WCHAR path [ 512 ] ;
ULONG path_len = sizeof ( path ) - sizeof ( WCHAR ) * 4 ;
rc = RegQueryValueEx ( hkey , NULL , NULL , & type , ( BYTE * ) path , & path_len ) ;
RegCloseKey ( hkey ) ;
if ( rc ! = 0 )
return false ;
return true ;
}
void CSbieUtils : : AddContextMenu ( const QString & StartPath )
{
wstring start_path = L " \" " + StartPath . toStdWString ( ) + L " \" " ;
CreateShellEntry ( L " * " , L " Run &Sandboxed " , start_path , start_path + L " /box:__ask__ \" %1 \" %* " ) ;
wstring explorer_path ( 512 , L ' \0 ' ) ;
HKEY hkeyWinlogon ;
LONG rc = RegOpenKeyEx ( HKEY_LOCAL_MACHINE , L " software \\ microsoft \\ windows nt \\ currentversion \\ winlogon " , 0 , KEY_READ , & hkeyWinlogon ) ;
if ( rc = = 0 )
{
ULONG path_len = explorer_path . size ( ) * sizeof ( WCHAR ) ;
ULONG type ;
rc = RegQueryValueEx ( hkeyWinlogon , L " Shell " , NULL , & type , ( BYTE * ) explorer_path . c_str ( ) , & path_len ) ;
if ( rc = = 0 & & ( type = = REG_SZ | | type = = REG_EXPAND_SZ ) )
explorer_path . resize ( path_len / sizeof ( WCHAR ) ) ;
RegCloseKey ( hkeyWinlogon ) ;
}
// get default explorer path
if ( * explorer_path . c_str ( ) = = L ' \0 ' | | _wcsicmp ( explorer_path . c_str ( ) , L " explorer.exe " ) = = 0 )
{
GetWindowsDirectory ( ( wchar_t * ) explorer_path . c_str ( ) , MAX_PATH ) ;
ULONG path_len = wcslen ( explorer_path . c_str ( ) ) ;
explorer_path . resize ( path_len ) ;
explorer_path . append ( L " \\ explorer.exe " ) ;
}
CreateShellEntry ( L " Folder " , L " Explore &Sandboxed " , start_path , start_path + L " /box:__ask__ " + explorer_path + L " \" %1 \" " ) ;
}
void CSbieUtils : : CreateShellEntry ( const wstring & classname , const wstring & cmdtext , const wstring & iconpath , const wstring & startcmd )
{
HKEY hkey ;
LONG rc = RegCreateKeyEx ( HKEY_CURRENT_USER , ( L " software \\ classes \\ " + classname + L " \\ shell \\ sandbox " ) . c_str ( ) , 0 , NULL , 0 , KEY_WRITE , NULL , & hkey , NULL ) ;
if ( rc ! = 0 )
return ;
RegSetValueEx ( hkey , NULL , 0 , REG_SZ , ( BYTE * ) cmdtext . c_str ( ) , ( cmdtext . length ( ) + 1 ) * sizeof ( WCHAR ) ) ;
RegSetValueEx ( hkey , L " Icon " , 0 , REG_SZ , ( BYTE * ) iconpath . c_str ( ) , ( iconpath . length ( ) + 1 ) * sizeof ( WCHAR ) ) ;
RegCloseKey ( hkey ) ;
if ( rc ! = 0 )
return ;
rc = RegCreateKeyEx ( HKEY_CURRENT_USER , ( L " software \\ classes \\ " + classname + L " \\ shell \\ sandbox \\ command " ) . c_str ( ) , 0 , NULL , 0 , KEY_WRITE , NULL , & hkey , NULL ) ;
if ( rc ! = 0 )
return ;
RegSetValueEx ( hkey , NULL , 0 , REG_SZ , ( BYTE * ) startcmd . c_str ( ) , ( startcmd . length ( ) + 1 ) * sizeof ( WCHAR ) ) ;
RegCloseKey ( hkey ) ;
}
void CSbieUtils : : RemoveContextMenu ( )
{
RegDeleteTreeW ( HKEY_CURRENT_USER , L " software \\ classes \\ * \\ shell \\ sandbox " ) ;
RegDeleteTreeW ( HKEY_CURRENT_USER , L " software \\ classes \\ folder \\ shell \\ sandbox " ) ;
}