* Copyright (c) 2007-2008 VMware, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#include "stdafx.h"
#include <assert.h>
#include <commdlg.h>
#include <imagehlp.h>
#include <direct.h>
#include "DynamoRIO.h"
#include "DynamoRIODoc.h"
#include "ShellInterface.h"
#include "CmdlineDlg.h"
#ifdef _DEBUG
# define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define INJECTOR_SUBPATH _T("\\bin\\drinject.exe")
IMPLEMENT_DYNCREATE(CDynamoRIODoc, CDocument)
BEGIN_MESSAGE_MAP(CDynamoRIODoc, CDocument)
END_MESSAGE_MAP()
CDynamoRIODoc::CDynamoRIODoc()
{
#ifndef DRSTATS_DEMO
InitPaths();
CShellInterface::Initialize();
#endif
SetModifiedFlag(TRUE);
}
#ifndef DRSTATS_DEMO
void
CDynamoRIODoc::InitPaths()
{
int len = GetEnvironmentVariable(_T("DYNAMORIO_HOME"), m_dynamorio_home, _MAX_DIR);
assert(len <= _MAX_DIR && len + _tcslen(INJECTOR_SUBPATH) < MAX_PATH);
if (len == 0 || len > _MAX_DIR)
m_dynamorio_home[0] = _T('\0');
else
NULL_TERMINATE_BUFFER(m_dynamorio_home);
_stprintf(m_injector_path, _T("%s%s"), m_dynamorio_home, INJECTOR_SUBPATH);
# if 0
_stprintf(m_logs_dir, _T("%s\\logs"), m_dynamorio_home);
# else
TCHAR userprof[MAX_PATH];
CString profile_dir;
len = GetEnvironmentVariable(_T("USERPROFILE"), userprof, MAX_PATH);
assert(len <= MAX_PATH);
if (len == 0 || len > MAX_PATH) {
len = GetEnvironmentVariable(_T("SYSTEMROOT"), userprof, MAX_PATH);
assert(len > 0 && len < MAX_PATH);
profile_dir.Format(_T("%s\\Profiles"), userprof);
} else {
profile_dir.Format(_T("%s"), userprof);
}
_stprintf(m_logs_dir, _T("%s\\Application Data\\DynamoRIO"), profile_dir);
if (!SetCurrentDirectory(m_logs_dir)) {
if (!CreateDirectory(m_logs_dir, NULL)) {
_stprintf(userprof, _T("Cannot create default working directory %s"),
m_logs_dir);
MessageBox(NULL, userprof, _T("Error"), MB_OK | MYMBFLAGS);
_stprintf(m_logs_dir, _T("c:\\"));
}
}
# endif
}
#endif
CDynamoRIODoc::~CDynamoRIODoc()
{
#ifndef DRSTATS_DEMO
CShellInterface::Uninitialize();
#endif
}
BOOL
CDynamoRIODoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
SetTitle(_T(""));
return TRUE;
}
BOOL
CDynamoRIODoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
return TRUE;
}
#ifndef DRSTATS_DEMO
BOOL
CDynamoRIODoc::RunApplication(LPCTSTR lpszPathName)
{
TCHAR app_name[MAX_PATH];
TCHAR rundir[_MAX_DIR];
TCHAR app_cmdline[MAX_PATH * 2];
TCHAR msg[MAX_PATH * 3];
TCHAR default_rundir[_MAX_DIR];
_stprintf(default_rundir, _T("%s"), m_logs_dir);
CString app_args;
int len = _tcslen(lpszPathName);
TCHAR *last4 = (TCHAR *)lpszPathName + len - 4;
if (_tcscmp(last4, _T(".lnk")) == 0) {
TCHAR params[MAX_PATH];
if (CShellInterface::ResolveLinkFile((TCHAR *)lpszPathName, app_name, params,
rundir,
CDynamoRIOApp::GetActiveView()->m_hWnd)) {
_stprintf(msg, _T("Resolved link file to %s %s\nin directory %s\n"), app_name,
params, rundir);
MessageBox(NULL, msg, _T("Link File"), MB_OK | MYMBFLAGS);
app_args.Format(_T("%s"), params);
} else {
_stprintf(msg, _T("Failed to resolve link file"));
MessageBox(NULL, msg, _T("Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
} else {
_stprintf(app_name, _T("%s"), lpszPathName);
CString defwdir(default_rundir);
CCmdlineDlg dlg(defwdir);
int res = dlg.DoModal();
if (res == IDCANCEL)
return FALSE;
CString wdir = dlg.GetWorkingDir();
_tcscpy(rundir, wdir.GetBuffer(0));
app_args = dlg.GetArguments();
}
if (CDynamoRIOApp::SystemwideSet()) {
_stprintf(app_cmdline, _T("%s %s"), app_name, app_args);
} else {
_stprintf(app_cmdline, _T("\"%s\" %s"), app_name, app_args);
}
CString dir(rundir);
CString realdir(_T(""));
int start = dir.Find(_T('%'));
int old_end = 0;
while (start != -1) {
realdir += dir.Mid(old_end, start - old_end);
int end = dir.Find(_T('%'), start + 1);
if (end == -1) {
realdir += dir.Right(dir.GetLength() - start);
break;
}
# if 0
_stprintf(msg, _T("from %d to %d"), start, end);
MessageBox(NULL, msg, _T("env var value"), MB_OK);
# endif
CString name = dir.Mid(start + 1, end - start - 1);
# if 0
MessageBox(NULL, name.GetBuffer(0), _T("env var name"), MB_OK);
# endif
int len = GetEnvironmentVariable(name.GetBuffer(0), msg, MAX_PATH);
assert(len <= MAX_PATH);
if (len == 0 || len > MAX_PATH)
msg[0] = _T('\0');
# if 0
MessageBox(NULL, msg, _T("env var value"), MB_OK);
# endif
realdir += msg;
old_end = end + 1;
start = dir.Find(_T('%'), end + 1);
}
if (!realdir.IsEmpty())
_stprintf(rundir, _T("%s"), realdir.GetBuffer(0));
if (rundir[0] == _T('\0'))
_tcscpy(rundir, default_rundir);
CFile check;
if (!check.Open(app_name, CFile::modeRead | CFile::shareDenyNone)) {
_stprintf(msg, _T("Application %s does not exist"), app_name);
MessageBox(NULL, msg, _T("Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
check.Close();
if (!SetCurrentDirectory(rundir)) {
_stprintf(msg, _T("Error changing to working directory %s"), rundir);
MessageBox(NULL, msg, _T("Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
TCHAR *launch_name;
TCHAR launch_cmdline[MAX_PATH * 2];
if (CDynamoRIOApp::SystemwideSet()) {
launch_name = app_name;
_tcscpy(launch_cmdline, app_cmdline);
} else {
launch_name = m_injector_path;
TCHAR *dll_path = CDynamoRIOApp::GetDllPath();
_stprintf(launch_cmdline, _T("\"%s\" \"%s\" %s"), m_injector_path, dll_path,
app_cmdline);
if (!check.Open(m_injector_path, CFile::modeRead | CFile::shareDenyNone)) {
_stprintf(msg, _T("DynamoRIO injector %s does not exist"), m_injector_path);
MessageBox(NULL, msg, _T("DynamoRIO Configuration Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
check.Close();
if (!check.Open(dll_path, CFile::modeRead | CFile::shareDenyNone)) {
_stprintf(msg, _T("DynamoRIO library %s does not exist"), dll_path);
MessageBox(NULL, msg, _T("DynamoRIO Configuration Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
check.Close();
}
assert(_tcslen(rundir) + _tcslen(launch_cmdline) + _tcslen(_T("\nin directory\n")) <
MAX_PATH * 2);
# if 0
_stprintf(msg, _T("%s\nin directory\n%s"), launch_cmdline, rundir);
MessageBox(NULL, msg, _T("About to run"), MB_OK | MB_TOPMOST);
# endif
# if 0
PLOADED_IMAGE li;
# ifdef UNICODE
char ansi_launch_name[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, launch_name, _tcslen(launch_name),
ansi_launch_name, MAX_PATH, NULL, NULL);
if (li = ImageLoad(ansi_launch_name, NULL))
# else
if (li = ImageLoad(launch_name, NULL))
# endif
{
ImageUnload(li);
} else {
_stprintf(msg, _T("Failed to load %s"), launch_name);
MessageBox(NULL, msg, _T("Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
# endif
STARTUPINFO si;
PROCESS_INFORMATION pi;
STARTUPINFO mysi;
GetStartupInfo(&mysi);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = mysi.hStdInput;
si.hStdOutput = mysi.hStdOutput;
si.hStdError = mysi.hStdError;
if (!CreateProcess(launch_name, launch_cmdline, NULL, NULL, TRUE,
DETACHED_PROCESS,
NULL, NULL, &si, &pi)) {
_stprintf(msg, _T("Failed to load %s"), app_name);
MessageBox(NULL, msg, _T("Error"), MB_OK | MYMBFLAGS);
return FALSE;
}
# if 0
if (!CDynamoRIOApp::GetActiveView()->SelectProcess(pi.dwProcessId))
MessageBox(NULL, _T("Failed to select"), _T("Error"), MB_OK | MYMBFLAGS);
# endif
int i = 0;
while (i < 200) {
if (CDynamoRIOApp::GetActiveView()->UpdateProcessList())
break;
Sleep(10);
i++;
}
return TRUE;
}
#endif
void
CDynamoRIODoc::Serialize(CArchive &ar)
{
if (ar.IsStoring()) {
} else {
}
}
#ifdef _DEBUG
void
CDynamoRIODoc::AssertValid() const
{
CDocument::AssertValid();
}
void
CDynamoRIODoc::Dump(CDumpContext &dc) const
{
CDocument::Dump(dc);
}
#endif
BOOL
CDynamoRIODoc::SaveModified()
{
#ifndef DRSTATS_DEMO
CDynamoRIOApp::AboutToExit();
#endif
return CDocument::SaveModified();
}