/////////////////////////////////////////////////////////////////////////////
// Double Agent - Copyright 2009-2010 Cinnamon Software Inc.
/////////////////////////////////////////////////////////////////////////////
/*
This file is part of the Double Agent Server.
The Double Agent Server is free software:
you can redistribute it and/or modify it under the terms of the
GNU Lesser Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
Double Agent 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 Lesser Public License for more details.
You should have received a copy of the GNU Lesser Public License
along with Double Agent. If not, see .
*/
/////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include
#include
#include "DaShell.h"
#include "DaCore.h"
#include "PropSheetCpl.h"
#include "Registry.h"
#include "GuidStr.h"
#include "UiState.h"
#include "Localize.h"
#include "StringArrayEx.h"
#include "ThreadSecurity.h"
#include "UserSecurity.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifdef _DEBUG
//#define _DEBUG_APPLET LogNormal
#endif
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#define _LOG_LEVEL_DEBUG LogNormal
#endif
#define _LOG_ROOT_PATH _T("Software\\")_T(_DOUBLEAGENT_NAME)_T("\\")
#define _LOG_SECTION_NAME _T(_SHELL_REGNAME)
#define _LOG_DEF_LOGNAME _T(_DOUBLEAGENT_NAME) _T(".log")
#define _LOG_PREFIX _T("Shel ")
static tPtr sLogCriticalSection = new CCriticalSection;
#define _LOG_CRITICAL_SECTION (!sLogCriticalSection?NULL:(CRITICAL_SECTION*)(*sLogCriticalSection))
#include "LogAccess.inl"
#include "Log.inl"
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC (CDaShellApp, CWinApp)
CDaShellApp gApp;
CDaShellApp::CDaShellApp()
: CWinApp (_T(_DOUBLEAGENT_NAME))
{
SetRegistryKeyEx (_T(_DOUBLEAGENT_NAME), _T(_SHELL_REGNAME));
}
CDaShellApp::~CDaShellApp()
{
}
/////////////////////////////////////////////////////////////////////////////
BOOL CDaShellApp::InitInstance()
{
#if ISOLATION_AWARE_ENABLED
IsolationAwareInit ();
#endif
#ifdef _DEBUG
LogStart (GetProfileDebugInt(_T("LogRestart"))!=0);
LogDebugRuntime ();
#else
LogStart (false);
#endif
LogProcessUser (GetCurrentProcess(), LogIfActive);
LogProcessOwner (GetCurrentProcess(), LogIfActive);
LogProcessIntegrity (GetCurrentProcess(), LogIfActive);
#ifdef _DEBUG
CDaCoreApp::InitLogging (gLogFileName, gLogLevel);
#endif
COleObjectFactory::RegisterAll();
return TRUE;
}
int CDaShellApp::ExitInstance()
{
SafeFreeSafePtr (mCplPropSheet);
CLocalize::FreeMuiModules ();
#if ISOLATION_AWARE_ENABLED
IsolationAwareCleanup ();
#endif
LogStop (LogIfActive);
return CWinApp::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CDaShellApp, CWinApp)
//{{AFX_MSG_MAP(CDaShellApp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
#pragma page()
/////////////////////////////////////////////////////////////////////////////
LONG APIENTRY CPlApplet (HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
{
LONG lRet = 0;
#ifdef _DEBUG_APPLET
CString lMsgName;
switch (uMsg)
{
case CPL_INIT: lMsgName = _T("CL_INIT"); break;
case CPL_EXIT: lMsgName = _T("CPL_EXIT"); break;
case CPL_GETCOUNT: lMsgName = _T("CPL_GETCOUNT"); break;
case CPL_INQUIRE: lMsgName = _T("CPL_INQUIRE"); break;
case CPL_NEWINQUIRE: lMsgName = _T("CPL_NEWINQUIRE"); break;
case CPL_STARTWPARMS: lMsgName = _T("CPL_STARTWPARMS"); break;
case CPL_DBLCLK: lMsgName = _T("CPL_DBLCLK"); break;
case CPL_STOP: lMsgName = _T("CPL_STOP"); break;
case CPL_SETUP: lMsgName = _T("CPL_SETUP"); break;
}
LogMessage (_DEBUG_APPLET, _T("CPlApplet [%p] [%u] [%s]"), hwndCPl, uMsg, lMsgName);
#endif
switch (uMsg)
{
case CPL_INIT:
{
CDaShellApp * lApp = TheShellApp;
if (!lApp->mCplPropSheet)
{
lApp->mCplPropSheet = new CPropSheetCpl;
}
lRet = TRUE;
} break;
case CPL_EXIT:
{
CDaShellApp * lApp = TheShellApp;
SafeFreeSafePtr (lApp->mCplPropSheet);
} break;
case CPL_GETCOUNT:
{
lRet = 1;
} break;
case CPL_INQUIRE:
{
CDaShellApp * lApp = TheShellApp;
UINT lAppNum = (UINT)lParam1;
LPCPLINFO lInfo = (LPCPLINFO) lParam2;
lInfo->idIcon = IDI_CPL;
lInfo->idName = IDS_CPL_NAME;
lInfo->idInfo = IDS_CPL_DESC;
lInfo->lData = (LONG_PTR)lApp->mCplPropSheet.Ptr();
} break;
case CPL_STARTWPARMS:
{
CDaShellApp * lApp = TheShellApp;
UINT lAppNum = (UINT)lParam1;
lApp->mCplStartPage = (LPCTSTR)lParam2;
#ifdef _DEBUG_APPLET
LogMessage (_DEBUG_APPLET, _T(" [%u] [%s]"), lParam1, (LPCTSTR)lParam2);
#endif
} break;
case CPL_DBLCLK:
{
CDaShellApp * lApp = TheShellApp;
UINT lAppNum = (UINT)lParam1;
bool lElevatedPages = (lApp->mCplStartPage.CompareNoCase (CPropSheetCpl::mPageNameRegistry) == 0);
if (lApp->mCplPropSheet)
{
lApp->mCplPropSheet->SetModalParent (CWnd::FromHandle (hwndCPl));
if (lApp->mCplPropSheet->InitPages (lElevatedPages))
{
lApp->mCplPropSheet->SetStartPage (lApp->mCplStartPage);
lApp->mCplPropSheet->DoModal ();
}
}
} break;
case CPL_STOP:
{
CDaShellApp * lApp = TheShellApp;
UINT lAppNum = (UINT)lParam1;
if (lApp->mCplPropSheet->GetSafeHwnd())
{
}
} break;
}
#ifdef _DEBUG_APPLET
LogMessage (_DEBUG_APPLET, _T("Return [%d]"), lRet);
#endif
return lRet;
}
/////////////////////////////////////////////////////////////////////////////
#pragma page()
/////////////////////////////////////////////////////////////////////////////
void CDaShellApp::RegisterCpl ()
{
CString lModuleName;
GetModuleFileName (AfxGetInstanceHandle(), lModuleName.GetBuffer(MAX_PATH), MAX_PATH);
lModuleName.ReleaseBuffer ();
if (LogIsActive ())
{
LogMessage (LogIfActive, _T("==> RegisterCpl [%s]"), lModuleName);
}
if (IsWindowsVista_AtLeast())
{
CRegKey lCplRoot (HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace"), false);
CRegKey lCplIdKey (lCplRoot, (CString)CGuidStr(__uuidof(CDaShellApp)), false, true);
CRegString lCplName (lCplIdKey, (LPCTSTR)NULL, true);
CRegKey lClassIdRoot (HKEY_CLASSES_ROOT, _T("CLSID"), false);
CRegKey lClassIdKey (lClassIdRoot, (CString)CGuidStr(__uuidof(CDaShellApp)), false, true);
CRegKey lClassIconKey (lClassIdKey, _T("DefaultIcon"), false, true);
CRegString lClassIcon (lClassIconKey, (LPCTSTR)NULL, true);
CRegString lClassName (lClassIdKey, (LPCTSTR)NULL, true);
CRegString lClassNameLocal (lClassIdKey, _T("LocalizedString"), true);
CRegString lClassTip (lClassIdKey, _T("InfoTip"), true);
CRegString lClassApp (lClassIdKey, _T("System.ApplicationName"), true);
CRegString lClassCat (lClassIdKey, _T("System.ControlPanel.Category"), true);
CRegString lClassTasks (lClassIdKey, _T("System.Software.TasksFileUrl"), true);
CRegKey lShellKey (lClassIdKey, _T("Shell"), false, true);
CRegKey lOpenKey (lShellKey, _T("Open"), false, true);
CRegKey lCommandKey (lOpenKey, _T("Command"), false, true);
CRegString lCommand (lCommandKey, (LPCTSTR)NULL, true);
lCplName.Value().LoadString (IDS_CPL_NAME);
lCplName.Update();
lClassName.Value().LoadString (IDS_CPL_NAME);
lClassName.Update();
lClassNameLocal.Value().Format (_T("@%s,-%d"), lModuleName, IDS_CPL_NAME);
lClassNameLocal.Update();
lClassTip.Value().Format (_T("@%s,-%d"), lModuleName, IDS_CPL_DESC);
lClassTip.Update();
lClassIcon.Value().Format (_T("%s,-%d"), lModuleName, IDI_CPL);
lClassIcon.Update();
lClassApp.Update (_T(_CPL_CANONICAL_NAME));
lClassCat.Update (_T("1,7"));
// Save for later with a full namespace extension
// lClassTasks.Value().Format (_T("%s,-%d"), lModuleName, IDR_CPL_TASKS);
// lClassTasks.Update();
PathRemoveFileSpec (lModuleName.GetBuffer (MAX_PATH));
PathAppend (lModuleName.GetBuffer (MAX_PATH), _T(_SERVER_FILENAME) _T(".exe"));
lModuleName.ReleaseBuffer ();
lCommand.Value().Format (_T("%s /settings"), lModuleName);
lCommand.Update ();
}
else
{
CRegKey lRootKey (HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel"), true);
CRegKey lCplsKey (lRootKey, _T("Cpls"), false, true);
CRegKey lExtendedKey (lRootKey, _T("Extended Properties"), false, true);
CRegString lCplPath (lCplsKey, _T(_CPL_NAME), true);
CRegKey lAppCatKey (lExtendedKey, _T("{305CA226-D286-468e-B848-2B2E8E697B74} 2"), false, true);
CRegDWord lCplAppCat (lAppCatKey, lModuleName, true);
lCplPath.Update (lModuleName);
lCplAppCat.SetValue(1).Update();
}
if (IsWindowsXp_AtMost())
{
CRegKey lEnvironment (HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\Session Manager\\Environment"), false);
CRegString lPath (lEnvironment, _T("Path"));
CString lPathLower;
CString lModuleLower;
PathRemoveFileSpec (lModuleName.GetBuffer(MAX_PATH));
lModuleName.ReleaseBuffer ();
if (lPath.IsValid ())
{
lPathLower = lPath.Value();
lModuleLower = lModuleName;
lPathLower.MakeLower ();
lModuleLower.MakeLower ();
if (_tcsstr (lPathLower, lModuleLower) == NULL)
{
if (LogIsActive ())
{
LogMessage (LogIfActive, _T("Environment [%s]"), lPath.Value());
}
lPath.Value().TrimRight ();
lPath.Value().TrimRight (_T(';'));
lPath.Value() += _T(';');
lPath.Value() += lModuleName;
lPath.Update ();
if (LogIsActive ())
{
CRegString lPathVerify (lEnvironment, _T("Path"));
LogMessage (LogIfActive, _T(" Updated [%s]"), lPath.Value());
LogMessage (LogIfActive, _T(" Verify [%s]"), lPathVerify.Value());
}
try
{
DWORD lRecipients = BSM_ALLCOMPONENTS;
if (BroadcastSystemMessage (BSF_FORCEIFHUNG, &lRecipients, WM_SETTINGCHANGE, 0, (LPARAM)_T("Environment")) < 0)
{
LogWinErr (LogIfActive, GetLastError());
}
}
catch AnyExceptionSilent
}
}
}
}
void CDaShellApp::UnregisterCpl ()
{
CString lModuleName;
GetModuleFileName (AfxGetInstanceHandle(), lModuleName.GetBuffer(MAX_PATH), MAX_PATH);
lModuleName.ReleaseBuffer ();
if (LogIsActive ())
{
LogMessage (LogIfActive, _T("==> UnregisterCpl [%s]"), lModuleName);
}
if (IsWindowsVista_AtLeast())
{
CRegKey lCplRoot (HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace"), false);
CRegKey lCplIdKey (lCplRoot, (CString)CGuidStr(__uuidof(CDaShellApp)), false, true);
CRegKey lClassIdRoot (HKEY_CLASSES_ROOT, _T("CLSID"), false);
CRegKey lClassIdKey (lClassIdRoot, (CString)CGuidStr(__uuidof(CDaShellApp)), false, true);
lCplIdKey.Delete ();
lClassIdKey.Delete ();
}
else
{
CRegKey lRootKey (HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel"), true);
CRegKey lCplsKey (lRootKey, _T("Cpls"), false);
CRegKey lExtendedKey (lRootKey, _T("Extended Properties"), false);
CRegString lCplPath (lCplsKey, _T(_CPL_NAME));
CRegKey lAppCatKey (lExtendedKey, _T("{305CA226-D286-468e-B848-2B2E8E697B74} 2"), false);
CRegDWord lCplAppCat (lAppCatKey, lModuleName);
lCplPath.Delete ();
lCplAppCat.Delete ();
}
if (IsWindowsXp_AtMost())
{
CRegKey lEnvironment (HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\Session Manager\\Environment"), false);
CRegString lPath (lEnvironment, _T("Path"));
CString lPathLower;
CString lModuleLower;
LPCTSTR lModuleFound;
int lModulePos;
PathRemoveFileSpec (lModuleName.GetBuffer(MAX_PATH));
lModuleName.ReleaseBuffer ();
if (lPath.IsValid ())
{
lPathLower = lPath.Value();
lModuleLower = lModuleName;
lPathLower.MakeLower ();
lModuleLower.MakeLower ();
if (lModuleFound = _tcsstr (lPathLower, lModuleLower))
{
if (LogIsActive())
{
LogMessage (LogIfActive, _T("Environment [%s]"), lPath.Value());
}
lModulePos = (int)(lModuleFound - (LPCTSTR)lPathLower);
lPath.Value().Delete (lModulePos, lModuleLower.GetLength());
if (
(lModulePos > 0)
&& (lModulePos < lPath.Value().GetLength())
&& (lPath.Value() [lModulePos] == _T(';'))
&& (lPath.Value() [lModulePos-1] == _T(';'))
)
{
lPath.Value().Delete (lModulePos);
}
lPath.Value().TrimRight (_T(';'));
lPath.Update ();
if (LogIsActive())
{
CRegString lPathVerify (lEnvironment, _T("Path"));
LogMessage (LogIfActive, _T(" Updated [%s]"), lPath.Value());
LogMessage (LogIfActive, _T(" Verify [%s]"), lPathVerify.Value());
}
try
{
DWORD lRecipients = BSM_ALLCOMPONENTS;
if (BroadcastSystemMessage (BSF_FORCEIFHUNG, &lRecipients, WM_SETTINGCHANGE, 0, (LPARAM)_T("Environment")) < 0)
{
LogWinErr (LogIfActive, GetLastError());
}
}
catch AnyExceptionSilent
}
}
}
}
/////////////////////////////////////////////////////////////////////////////
#pragma page()
/////////////////////////////////////////////////////////////////////////////
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AfxDllGetClassObject(rclsid, riid, ppv);
}
STDAPI DllCanUnloadNow(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AfxDllCanUnloadNow();
}
STDAPI DllRegisterServer(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
LogStart (false);
if (
(IsWindowsXp_AtMost ())
|| (CUserSecurity::IsUserAdministrator ())
)
{
DllUnregisterServer ();
if (COleObjectFactory::UpdateRegistryAll(TRUE))
{
try
{
CDaShellApp::RegisterCpl ();
}
catch AnyExceptionSilent
}
else
{
return SELFREG_E_CLASS;
}
}
else
{
return HRESULT_FROM_WIN32 (ERROR_ELEVATION_REQUIRED);
}
return S_OK;
}
STDAPI DllUnregisterServer(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
LogStart (false);
if (
(IsWindowsXp_AtMost ())
|| (CUserSecurity::IsUserAdministrator ())
)
{
try
{
CDaShellApp::UnregisterCpl ();
}
catch AnyExceptionSilent
if (!COleObjectFactory::UpdateRegistryAll(FALSE))
{
return SELFREG_E_CLASS;
}
}
else
{
return HRESULT_FROM_WIN32 (ERROR_ELEVATION_REQUIRED);
}
return S_OK;
}