// BandDialog.cpp : Implementation of CBandDialog
#include "stdafx.h"
#include "resource.h"
#include "BandDialog.h"
/////////////////////////////////////////////////////////////////////////////
// Message handlers
BOOL CBandDialog::OnInitDialog ( HWND hwndFocus, LPARAM lParam )
{
DlgResize_Init ( false, false );
DoDataExchange();
m_uRegisteredMsg1 = RegisterWindowMessage ( REGISTERED_MSG1_NAME );
m_uRegisteredMsg2 = RegisterWindowMessage ( REGISTERED_MSG2_NAME );
m_cLog.InsertColumn ( 0, _T(""), LVCFMT_LEFT, 0, 0 );
// Print a log message that shows whether PM is on.
HRESULT hr;
BOOL bProtectedMode;
hr = IEIsProtectedModeProcess ( &bProtectedMode );
if ( SUCCEEDED(hr) )
{
if ( bProtectedMode )
Log("IE is running in protected mode");
else
Log("IE is not running in protected mode");
}
else
Log("IEIsProtectedModeProcess() failed, error: %s", _E(hr));
return TRUE; // Let the system set the focus
}
/////////////////////////////////////////////////////////////////////////////
// Command handlers
void CBandDialog::OnOpenMutex1 ( UINT uCode, int nID, HWND hwndCtrl )
{
CHandle hMutex;
// Try to open mutex #1. If DemoApp.exe is running, the OpenMutex()
// call will fail if IE is running in protected mode, because the mutex
// is at medium integrity and this code is running at low integrity, so
// it can't access the mutex which is at a higher integrity level.
Log("Opening Mutex1 (this will fail in protected mode)");
hMutex.Attach ( OpenMutex ( MUTEX_ALL_ACCESS, false, MUTEX1_NAME ) );
if ( !hMutex )
Log("OpenMutex() failed, error: %s", _E(GetLastError()));
else
Log("OpenMutex() succeeded, the EXE is running");
}
void CBandDialog::OnOpenMutex2 ( UINT uCode, int nID, HWND hwndCtrl )
{
CHandle hMutex;
// Try to open mutex #2. If DemoApp.exe is running, the OpenMutex()
// call will succeed even in protected mode, because the EXE sets the
// mutex's integrity level to low..
Log("Opening Mutex2");
hMutex.Attach ( OpenMutex ( MUTEX_ALL_ACCESS, false, MUTEX2_NAME ) );
if ( !hMutex )
Log("OpenMutex() failed, error: %s", _E(GetLastError()));
else
Log("OpenMutex() succeeded, the EXE is running");
}
void CBandDialog::OnRunExe1 ( UINT uCode, int nID, HWND hwndCtrl )
{
// The magic number that the EXE will look for to check that the data came from us.
#ifdef UNICODE
int sig = 'CP!W';
#else
int sig = 'CP!A';
#endif
// Build a string with the current time.
SYSTEMTIME st = {0};
TCHAR szTime[128] = {0};
CString sData;
DWORD cbyData;
GetLocalTime ( &st );
GetTimeFormat ( LOCALE_USER_DEFAULT, 0, &st, NULL, szTime, _countof(szTime) );
sData.Format ( _T("Running EXE at %s"), szTime );
cbyData = (1 + sData.GetLength()) * sizeof(TCHAR) + sizeof(sig);
// Put that string into shared memory.
CHandle hMapping;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
sa.bInheritHandle = TRUE;
hMapping.Attach ( CreateFileMapping ( INVALID_HANDLE_VALUE, &sa,
PAGE_READWRITE, 0, cbyData, NULL ) );
if ( !hMapping )
{
Log("CreateFileMapping() failed, error: %s", _E(GetLastError()));
return;
}
void* pv = MapViewOfFile ( hMapping, FILE_MAP_WRITE, 0, 0, 0 );
BYTE* pbyData = (BYTE*) pv;
if ( NULL == pv )
{
Log("MapViewOfFile() failed, error: %s", _E(GetLastError()));
return;
}
memcpy ( pbyData, &sig, sizeof(sig) );
pbyData += sizeof(sig);
memcpy ( pbyData, (LPCTSTR) sData, cbyData-sizeof(sig) );
UnmapViewOfFile ( pv );
// Run the EXE and pass it the shared memory handle. In protected mode,
// the process is actually started by the broker process IEUser.exe, which
// means that DemoApp.exe can't inherit the handle from us.
TCHAR szExeDir[MAX_PATH] = {0};
CString sCommandLine;
BOOL bSuccess;
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi = {0};
GetModuleFileName ( _Module.GetModuleInstance(), szExeDir, _countof(szExeDir) );
PathRemoveFileSpec ( szExeDir );
PathAddBackslash ( szExeDir );
sCommandLine.Format ( _T("\"%sDemoApp.exe\" /h:%p"), szExeDir,
(DWORD_PTR)(HANDLE) hMapping );
Log("Running command line: %s", (LPCTSTR) sCommandLine);
bSuccess = CreateProcess ( NULL, sCommandLine.GetBuffer(0), NULL, NULL, TRUE,
NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi );
if ( bSuccess )
{
Log("CreateProcess() succeeded");
CloseHandle ( pi.hProcess );
CloseHandle ( pi.hThread );
}
else
Log("CreateProcess() failed, error: %s", _E(GetLastError()));
}
void CBandDialog::OnRunExe2 ( UINT uCode, int nID, HWND hwndCtrl )
{
// The magic number that the EXE will look for to check that the data came from us.
#ifdef UNICODE
int sig = 'CP!W';
#else
int sig = 'CP!A';
#endif
// Build a string with the current time.
SYSTEMTIME st = {0};
TCHAR szTime[128] = {0};
CString sData;
DWORD cbyData;
GetLocalTime ( &st );
GetTimeFormat ( LOCALE_USER_DEFAULT, 0, &st, NULL, szTime, _countof(szTime) );
sData.Format ( _T("Running EXE at %s"), szTime );
cbyData = (1 + sData.GetLength()) * sizeof(TCHAR) + sizeof(sig);
// Get a GUID that we'll use as the name of the shared memory object.
GUID guid = {0};
WCHAR wszGuid[64] = {0};
CString sMappingName;
HRESULT hr;
hr = CoCreateGuid ( &guid );
if ( FAILED(hr) )
{
Log("CoCreateGuid() failed, error: %s", _E(hr));
return;
}
if ( 0 == StringFromGUID2 ( guid, wszGuid, _countof(wszGuid) ))
{
Log("StringFromGUID2() failed, error: %s", _E(GetLastError()));
return;
}
sMappingName = wszGuid;
// Put that string into shared memory.
CHandle hMapping;
hMapping.Attach ( CreateFileMapping ( INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, cbyData, sMappingName ) );
if ( !hMapping )
{
Log("CreateFileMapping() failed, error: %s", _E(GetLastError()));
return;
}
void* pv = MapViewOfFile ( hMapping, FILE_MAP_WRITE, 0, 0, 0 );
BYTE* pbyData = (BYTE*) pv;
if ( NULL == pv )
{
Log("MapViewOfFile() failed, error: %s", _E(GetLastError()));
return;
}
memcpy ( pbyData, &sig, sizeof(sig) );
pbyData += sizeof(sig);
memcpy ( pbyData, (LPCTSTR) sData, cbyData-sizeof(sig) );
UnmapViewOfFile ( pv );
// Run the EXE and pass it the name of the file mapping object.
// This works even in protected mode, because DemoApp.exe can access
// the object via its name.
TCHAR szExeDir[MAX_PATH] = {0};
CString sCommandLine;
BOOL bSuccess;
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi = {0};
GetModuleFileName ( _Module.GetModuleInstance(), szExeDir, _countof(szExeDir) );
PathRemoveFileSpec ( szExeDir );
PathAddBackslash ( szExeDir );
sCommandLine.Format ( _T("\"%sDemoApp.exe\" /n:%s"), szExeDir, (LPCTSTR) sMappingName );
Log("Running command line: %s", (LPCTSTR) sCommandLine);
bSuccess = CreateProcess ( NULL, sCommandLine.GetBuffer(0), NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi );
if ( bSuccess )
{
Log("CreateProcess() succeeded");
// Note that we have to wait for the EXE to go idle, so the file mapping
// object stays around until the EXE has had a chance to access it.
WaitForInputIdle ( pi.hProcess, 10000 );
CloseHandle ( pi.hProcess );
CloseHandle ( pi.hThread );
}
else
Log("CreateProcess() failed, error: %s", _E(GetLastError()));
}
void CBandDialog::OnSendMessage1 ( UINT uCode, int nID, HWND hwndCtrl )
{
HWND hwndDlg = FindWindow ( _T("#32770"), _T("DemoApp Main Dialog") );
if ( NULL == hwndDlg )
Log("Didn't find the DemoApp window");
else
{
// Send the EXE registered message #1. This will fail in protected
// mode because we are prevented from sending a message to a window
// in a process that's at a higher integrity level.
LRESULT lRes = ::SendMessage ( hwndDlg, m_uRegisteredMsg1, 0, 0 );
Log("Sent registered message #1, expecting retval %ld, actual retval: %ld", MSG1_RETVAL, lRes);
}
}
void CBandDialog::OnSendMessage2 ( UINT uCode, int nID, HWND hwndCtrl )
{
HWND hwndDlg = FindWindow ( _T("#32770"), _T("DemoApp Main Dialog") );
if ( NULL == hwndDlg )
Log("Didn't find the DemoApp window");
else
{
// Send the EXE registered message #2. This will work in protected
// mode because DemoApp.exe explicitly allows this message to be
// sent from lower integrity levels by calling ChangeWindowMessageFilter().
LRESULT lRes = ::SendMessage ( hwndDlg, m_uRegisteredMsg2, 0, 0 );
Log("Sent registered message #2, expecting retval %ld, actual retval: %ld", MSG2_RETVAL, lRes);
}
}
void CBandDialog::OnClearLog ( UINT uCode, int nID, HWND hwndCtrl )
{
m_cLog.DeleteAllItems();
}
void CBandDialog::OnSaveLog ( UINT uCode, int nID, HWND hwndCtrl )
{
HRESULT hr;
HANDLE hState;
LPWSTR pwszSelectedFilename = NULL;
const DWORD dwSaveFlags = OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT;
// Call IEShowSaveFileDialog() to get a filename from the user.
hr = IEShowSaveFileDialog ( m_hWnd, L"Saved log.txt", NULL, L"Text files|*.txt|All files|*.*|",
L"txt", 1, dwSaveFlags, &pwszSelectedFilename, &hState );
if ( S_OK == hr )
{
LPWSTR pwszCacheDir = NULL;
TCHAR szTempFile[MAX_PATH] = {0};
// Get the path to the IE cache dir, which is a dir that we're allowed
// to write to in protected mode.
hr = IEGetWriteableFolderPath ( FOLDERID_InternetCache, &pwszCacheDir );
if ( SUCCEEDED(hr) )
{
// Get a temp file name in that dir.
GetTempFileName ( CW2CT(pwszCacheDir), _T("bob"), 0, szTempFile );
CoTaskMemFree ( pwszCacheDir );
// Write our data to that temp file.
hr = WriteLogFile ( szTempFile );
}
if ( SUCCEEDED(hr) )
{
// If we wrote the file successfully, have IE save that data to
// the file that the user chose.
hr = IESaveFile ( hState, T2CW(szTempFile) );
// Clean up our temp file.
DeleteFile ( szTempFile );
}
else
{
// We couldn't complete the save operation, so cancel it.
IECancelSaveFile ( hState );
}
if ( FAILED(hr) )
{
CString sMsg;
sMsg.Format ( _T("Error saving file: %s"), _E(hr));
::MessageBox ( GetTopLevelParent(), sMsg, _T("IE PM Demo Extension"), MB_ICONERROR );
}
else
Log("Log file saved to: %ls", pwszSelectedFilename);
CoTaskMemFree ( pwszSelectedFilename );
}
else
{
if ( S_FALSE == hr )
Log("Save file dialog cancelled by the user");
else
Log("IEShowSaveFileDialog() failed, error: %s", _E(hr));
}
}
/////////////////////////////////////////////////////////////////////////////
// Other methods
void CBandDialog::Log ( LPCSTR szFormat, ... )
{
va_list va;
CString s;
int nIdx;
va_start ( va, szFormat );
s.FormatV ( CA2CT(szFormat), va );
nIdx = m_cLog.InsertItem ( m_cLog.GetItemCount(), s );
m_cLog.EnsureVisible ( nIdx, false );
m_cLog.SetColumnWidth ( 0, LVSCW_AUTOSIZE );
}
HRESULT CBandDialog::WriteLogFile ( LPCTSTR szFilename )
{
CHandle hFile ( CreateFile ( szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL ) );
if ( INVALID_HANDLE_VALUE == hFile )
return E_FAIL;
for ( int i = 0; i < m_cLog.GetItemCount(); i++ )
{
CString sLine;
DWORD cbyToWrite, cbyWritten = 0;
m_cLog.GetItemText ( i, 0, sLine );
sLine += _T("\r\n");
cbyToWrite = sLine.GetLength() * sizeof(TCHAR);
if ( !WriteFile ( hFile, (LPCTSTR) sLine, cbyToWrite, &cbyWritten, NULL ) )
return E_FAIL;
}
return S_OK;
}