Sandboxie/Sandboxie/apps/control/MyApp.cpp

714 lines
18 KiB
C++

/*
* Copyright 2004-2020 Sandboxie Holdings, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// Application
//---------------------------------------------------------------------------
#include "stdafx.h"
#include "MyApp.h"
#include "MyFrame.h"
#include "Boxes.h"
#include "WindowTitleMap.h"
#include "UserSettings.h"
#include "SbieIni.h"
#include "InitWait.h"
#include "ShellDialog.h"
#include "AutoPlay.h"
#include "apps/common/MyMsgBox.h"
#include "apps/common/MyGdi.h"
#include "apps/common/CommonUtils.h"
#include "apps/common/RunStartExe.h"
#include "common/win32_ntddk.h"
#include "common/my_version.h"
#include "core/drv/api_defs.h"
//---------------------------------------------------------------------------
// Variables
//---------------------------------------------------------------------------
CMyApp theApp;
bool CMyApp::m_Windows2000 = false;
bool CMyApp::m_WindowsVista = false;
bool CMyApp::m_LayoutRTL = false;
HBRUSH CMyApp::m_background = NULL;
CFont CMyApp::m_fontFixed;
ATOM CMyApp::m_atom = NULL;
UINT CMyApp::m_TaskbarCreated = 0;
HWND CMyApp::m_hwndTray = NULL;
int CMyApp::m_modal = 0;
CString CMyApp::m_appTitle;
ULONG CMyApp::m_session_id = 0;
const CString _HideMessage(L"HideMessage");
const CString _GlobalSettings(L"GlobalSettings");
const CString _ExplorerExe(L"explorer.exe");
//---------------------------------------------------------------------------
// InitInstance
//---------------------------------------------------------------------------
BOOL CMyApp::InitInstance()
{
static const WCHAR *WindowClassName = SANDBOXIE_CONTROL L"WndClass";
BOOL ForceVisible = FALSE;
BOOL ForceSync = FALSE;
BOOL PostSetup = FALSE;
WCHAR *CommandLine = GetCommandLine();
if (CommandLine) {
if (wcsstr(CommandLine, L"/open"))
ForceVisible = TRUE;
if (wcsstr(CommandLine, L"/sync"))
ForceSync = TRUE;
if (wcsstr(CommandLine, L"/postsetup"))
PostSetup = TRUE;
if (wcsstr(CommandLine, L"/uninstall")) {
CShellDialog::Sync(TRUE);
return TRUE;
}
}
//
// abort early if the application mutex already exists
//
WCHAR *InstanceMutexName = SANDBOXIE L"_SingleInstanceMutex_Control";
HANDLE hInstanceMutex =
OpenMutex(MUTEX_ALL_ACCESS, FALSE, InstanceMutexName);
if (hInstanceMutex) {
if (ForceVisible) {
HWND hwnd = FindWindow(WindowClassName, NULL);
if (hwnd) {
ShowWindow(hwnd, SW_SHOWNORMAL);
SetForegroundWindow(hwnd);
}
}
return FALSE;
}
hInstanceMutex = CreateMutex(NULL, FALSE, InstanceMutexName);
if (! hInstanceMutex)
return FALSE;
//
// change to Sandboxie home directory
//
WCHAR *home_path = (WCHAR *)HeapAlloc(
GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, 1024 * sizeof(WCHAR));
SbieApi_GetHomePath(NULL, 0, home_path, 1020);
SetCurrentDirectory(home_path);
HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, home_path);
//
// check if Windows XP APIs are available
//
OSVERSIONINFO osvi;
memzero(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx((OSVERSIONINFO *)&osvi);
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
m_Windows2000 = true;
if (osvi.dwMajorVersion >= 6)
m_WindowsVista = true;
//
// initialize misc
//
CoInitialize(NULL);
// these have been deprecated
//#ifdef _AFXDLL
// Enable3dControls();
//#else
// Enable3dControlsStatic();
//#endif
BOOLEAN LayoutRTL;
SbieDll_GetLanguage(&LayoutRTL);
if (LayoutRTL)
m_LayoutRTL = true;
m_appTitle = CMyMsg(MSG_3301);
#if _MSC_VER != 1200 // if not Visual C++ 6.0
if (! ProcessIdToSessionId(GetCurrentProcessId(), &m_session_id))
m_session_id = 0;
#endif
SbieDll_GetDrivePath(-1);
//
// initialize graphical elements
//
MyGdi_Init();
m_background =
CreatePatternBrush(MyGdi_CreateFromResource(L"BACKGROUND"));
if (1) {
CFont font1;
LOGFONT data1;
font1.CreateStockObject(ANSI_FIXED_FONT);
if (font1.GetLogFont(&data1)) {
HDC hdc = GetDC(NULL);
LONG NewHeight =
-MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(NULL, hdc);
if (abs(NewHeight) > abs(data1.lfHeight)) {
data1.lfHeight = NewHeight;
data1.lfWidth = 0;
}
HDC hDC = ::GetDC(NULL);
int dpi = GetDeviceCaps(hDC, LOGPIXELSY);
if (dpi > 96)
data1.lfWeight = FW_BOLD;
::ReleaseDC(NULL, hDC);
m_fontFixed.CreateFontIndirect(&data1);
} else
m_fontFixed.CreateStockObject(ANSI_FIXED_FONT);
}
//
// register main window class
//
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = ::DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = AfxGetInstanceHandle();
wc.hIcon = ::LoadIcon(wc.hInstance, L"AAAPPICON");
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = WindowClassName;
wc.hIconSm = NULL;
m_atom = RegisterClassEx(&wc);
if (! m_atom)
return FALSE;
//
// register TaskbarCreated message
//
m_TaskbarCreated = RegisterWindowMessage(L"TaskbarCreated");
//
// wait for Sandboxie to finish initialization
//
CInitWait initwait(this);
//
// take over as the Sandboxie session leader
//
SbieApi_SessionLeader(0, NULL);
//
// refresh processes
//
CBoxes::GetInstance().RefreshProcesses();
//
// setup autoplay cancellation
//
CAutoPlay::Install();
//
// create main window
//
m_pMainWnd = new CMyFrame(ForceVisible, ForceSync, PostSetup);
m_pMainWnd->UpdateWindow();
return TRUE;
}
//---------------------------------------------------------------------------
// ExitInstance
//---------------------------------------------------------------------------
int CMyApp::ExitInstance()
{
CAutoPlay::Remove();
delete &CBoxes::GetInstance();
delete &CWindowTitleMap::GetInstance();
delete &CUserSettings::GetInstance();
delete &CSbieIni::GetInstance();
return 0;
}
//---------------------------------------------------------------------------
// RunStartExe
//---------------------------------------------------------------------------
void CMyApp::RunStartExe(
const CString &cmd, const CString &box, BOOL wait, BOOL inherit)
{
Common_RunStartExe(cmd, box, wait, inherit);
}
//---------------------------------------------------------------------------
// MsgBox
//---------------------------------------------------------------------------
int CMyApp::MsgBox(CWnd *pWnd, const WCHAR *text, UINT flags)
{
if (! pWnd)
pWnd = CBaseDialog::GetActiveWindow();
HWND hwnd = pWnd ? pWnd->m_hWnd : NULL;
CString caption;
if (hwnd)
pWnd->GetWindowText(caption);
else
caption = CMyApp::m_appTitle;
if (m_LayoutRTL)
flags |= MB_RTLREADING | MB_RIGHT;
return MessageBox(hwnd, text, caption, flags);
}
//---------------------------------------------------------------------------
// MsgBox
//---------------------------------------------------------------------------
int CMyApp::MsgBox(CWnd *pWnd, ULONG textid, UINT flags)
{
return MsgBox(pWnd, CMyMsg(textid), flags);
}
//---------------------------------------------------------------------------
// MsgCheckBox
//---------------------------------------------------------------------------
int CMyApp::MsgCheckBox(
CWnd *pWnd, const CString &text, ULONG checkid, UINT flags)
{
if (! pWnd)
pWnd = CBaseDialog::GetActiveWindow();
HWND hwnd = pWnd ? pWnd->m_hWnd : NULL;
CString caption;
if (hwnd)
pWnd->GetWindowText(caption);
else
caption = CMyApp::m_appTitle;
if (m_LayoutRTL)
flags |= MB_RTLREADING | MB_RIGHT;
CMyMsg check(checkid ? checkid : MSG_3306);
return MessageCheckBox(hwnd, text, caption, flags, check);
}
//---------------------------------------------------------------------------
// MsgCheckBox
//---------------------------------------------------------------------------
int CMyApp::MsgCheckBox(
CWnd *pWnd, ULONG textid, ULONG checkid, UINT flags)
{
CMyMsg textstr(textid);
return MsgCheckBox(pWnd, textstr, checkid, flags);
}
//---------------------------------------------------------------------------
// InputBox
//---------------------------------------------------------------------------
CString CMyApp::InputBox(CWnd *pWnd, ULONG textid)
{
ULONG flags = MB_OKCANCEL;
if (m_LayoutRTL)
flags |= MB_RTLREADING | MB_RIGHT;
if (! pWnd)
pWnd = CBaseDialog::GetActiveWindow();
HWND hwnd = pWnd ? pWnd->m_hWnd : NULL;
CMyMsg caption(textid);
WCHAR *edit = ::InputBox(hwnd, caption, flags, NULL);
CString retval;
if (edit) {
retval = edit;
LocalFree(edit);
}
return retval;
}
//---------------------------------------------------------------------------
// InputBox
//---------------------------------------------------------------------------
void CMyApp::InputBox(CWnd *pWnd, ULONG textid, CString &str)
{
ULONG flags = MB_OKCANCEL;
if (m_LayoutRTL)
flags |= MB_RTLREADING | MB_RIGHT;
if (! pWnd)
pWnd = CBaseDialog::GetActiveWindow();
HWND hwnd = pWnd ? pWnd->m_hWnd : NULL;
CMyMsg caption(textid);
WCHAR *edit = ::InputBox(hwnd, caption, flags, str);
if (edit) {
str = edit;
LocalFree(edit);
}
}
//---------------------------------------------------------------------------
// GetProgramFileName
//---------------------------------------------------------------------------
void CMyApp::GetProgramFileName(
CWnd *pParentWnd, CString &pgm1, CString &pgm2)
{
pgm1 = CString();
pgm2 = CString();
WCHAR buf[MAX_PATH + 8];
buf[0] = L'\0';
WCHAR filter[64];
wcscpy(filter, CMyMsg(MSG_3308));
while (1) {
WCHAR *ptr = wcsrchr(filter, L'#');
if (! ptr)
break;
*ptr = L'\0';
}
OPENFILENAME ofn;
memzero(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = pParentWnd->m_hWnd;
ofn.nFilterIndex = 1;
ofn.lpstrFilter = filter;
ofn.lpstrFile = buf;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_DONTADDTORECENT
| OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if (GetOpenFileName(&ofn)) {
pgm1 = buf;
int index = pgm1.ReverseFind(L'\\');
if (index != -1)
pgm1 = pgm1.Mid(index + 1);
pgm1.MakeLower();
DWORD retval = GetShortPathName(buf, buf, MAX_PATH + 4);
if (retval && retval <= MAX_PATH) {
pgm2 = buf;
index = pgm2.ReverseFind(L'\\');
if (index != -1) {
pgm2 = pgm2.Mid(index + 1);
pgm2.MakeLower();
}
if (index == -1 || pgm1 == pgm2)
pgm2 = CString();
}
}
}
//---------------------------------------------------------------------------
// MyLoadMenu
//---------------------------------------------------------------------------
CMenu *CMyApp::MyLoadMenu(const WCHAR *MenuResName)
{
CMenu *pMenu1;
MENUITEMINFO mii;
WCHAR text[128];
int i, j, k;
UINT id;
//
// create and load menu
//
pMenu1 = new CMenu();
pMenu1->LoadMenu(MenuResName);
//
// convert message IDs to localized text
//
for (i = 0; i < (int)pMenu1->GetMenuItemCount(); ++i) {
memzero(&mii, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_STRING | MIIM_SUBMENU;
mii.dwTypeData = text;
mii.cch = 120;
::GetMenuItemInfo(*pMenu1, i, TRUE, &mii);
id = _wtoi(text);
if (id) {
CMyMsg msg(id);
mii.dwTypeData = (WCHAR *)(const WCHAR *)msg;
::SetMenuItemInfo(*pMenu1, i, TRUE, &mii);
}
if (mii.hSubMenu) {
CMenu *pMenu2 = pMenu1->GetSubMenu(i);
for (j = 0; j < (int)pMenu2->GetMenuItemCount(); ++j) {
memzero(&mii, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_STRING | MIIM_SUBMENU;
mii.dwTypeData = text;
mii.cch = 120;
::GetMenuItemInfo(*pMenu2, j, TRUE, &mii);
id = _wtoi(text);
if (id) {
CMyMsg msg(id, L"\t");
mii.dwTypeData = (WCHAR *)(const WCHAR *)msg;
::SetMenuItemInfo(*pMenu2, j, TRUE, &mii);
}
if (mii.hSubMenu) {
CMenu *pMenu3 = pMenu2->GetSubMenu(j);
for (k = 0; k < (int)pMenu3->GetMenuItemCount(); ++k) {
memzero(&mii, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_STRING | MIIM_SUBMENU;
mii.dwTypeData = text;
mii.cch = 120;
::GetMenuItemInfo(*pMenu3, k, TRUE, &mii);
id = _wtoi(text);
if (id) {
CMyMsg msg(id, L"\t");
mii.dwTypeData = (WCHAR *)(const WCHAR *)msg;
::SetMenuItemInfo(*pMenu3, k, TRUE, &mii);
}
}
}
}
}
}
return pMenu1;
}
//---------------------------------------------------------------------------
// CopyListBoxToClipboard
//---------------------------------------------------------------------------
void CMyApp::CopyListBoxToClipboard(CWnd *wnd, int idListBox)
{
CListBox *listbox = (CListBox *)(wnd->GetDlgItem(idListBox));
ULONG count = listbox->GetCount();
ULONG len = 0;
ULONG i;
for (i = 0; i < count; ++i)
len += listbox->GetTextLen(i) + 2;
if (len) {
HANDLE hGlobal =
GlobalAlloc(GMEM_MOVEABLE, (len + 4) * sizeof(WCHAR));
if (hGlobal) {
WCHAR *mem_ptr = (WCHAR *)GlobalLock(hGlobal);
for (i = 0; i < count; ++i) {
len = listbox->GetTextLen(i);
listbox->GetText(i, mem_ptr);
mem_ptr += len;
*mem_ptr = L'\r';
++mem_ptr;
*mem_ptr = L'\n';
++mem_ptr;
}
*mem_ptr = L'\0';
GlobalUnlock(hGlobal);
if (wnd->OpenClipboard()) {
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hGlobal);
CloseClipboard();
} else
GlobalFree(hGlobal);
}
}
}
//---------------------------------------------------------------------------
// CreateTrayIcon
//---------------------------------------------------------------------------
void CMyApp::CreateTrayIcon(CWnd *pParentWnd, HICON hIcon, CString info)
{
m_hwndTray = pParentWnd->m_hWnd;
for (int retry = 0; retry < 60; ++retry) {
NOTIFYICONDATA nid;
memzero(&nid, sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = m_hwndTray;
nid.uID = 1;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = hIcon;
wcscpy(nid.szTip, CMyApp::m_appTitle);
wcscat(nid.szTip, info);
BOOL ok = Shell_NotifyIcon(NIM_ADD, &nid);
if (ok)
return;
Sleep(500);
}
}
//---------------------------------------------------------------------------
// ChangeTrayIcon
//---------------------------------------------------------------------------
void CMyApp::ChangeTrayIcon(HICON hIcon, CString info)
{
if (m_hwndTray) {
NOTIFYICONDATA nid;
memzero(&nid, sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = m_hwndTray;
nid.uID = 1;
nid.uFlags = NIF_ICON | NIF_TIP;
nid.hIcon = hIcon;
wcscpy(nid.szTip, CMyApp::m_appTitle);
wcscat(nid.szTip, info);
Shell_NotifyIcon(NIM_MODIFY, &nid);
}
}
//---------------------------------------------------------------------------
// BalloonTrayIcon
//---------------------------------------------------------------------------
void CMyApp::BalloonTrayIcon(CString text, ULONG timeout)
{
if (m_hwndTray) {
NOTIFYICONDATA nid;
memzero(&nid, sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = m_hwndTray;
nid.uID = 1;
nid.uFlags = NIF_INFO;
wcscpy(nid.szInfoTitle, CMyApp::m_appTitle);
wcscpy(nid.szInfo, text);
nid.dwInfoFlags = NIIF_NOSOUND;
nid.uTimeout = timeout * 1000;
Shell_NotifyIcon(NIM_MODIFY, &nid);
}
}
//---------------------------------------------------------------------------
// DeleteTrayIcon
//---------------------------------------------------------------------------
void CMyApp::DeleteTrayIcon()
{
if (m_hwndTray) {
NOTIFYICONDATA nid;
memzero(&nid, sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = m_hwndTray;
nid.uID = 1;
nid.uFlags = 0;
Shell_NotifyIcon(NIM_DELETE, &nid);
m_hwndTray = NULL;
}
}