#include "stdafx.h" #include "UAC_Thread.h" #include "Misc.h" #include "Options.h" #include "QPasteWnd.h" #include "cp_main.h" CUAC_Thread::CUAC_Thread(int processId) { m_processId = processId; AddEvent(UAC_PASTE, StrF(_T("Global\\UAC_PASTE_%d"), m_processId)); AddEvent(UAC_COPY, StrF(_T("Global\\UAC_COPY_%d"), m_processId)); AddEvent(UAC_CUT, StrF(_T("Global\\UAC_CUT_%d"), m_processId)); AddEvent(UAC_EXIT, StrF(_T("Global\\UAC_EXIT_%d"), m_processId)); m_waitTimeout = 30000; } CUAC_Thread::~CUAC_Thread(void) { } void CUAC_Thread::OnTimeOut(void *param) { bool close = false; DWORD exitCode = 0; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, m_processId); if(hProcess == NULL) { close = true; } else { if(GetExitCodeProcess(hProcess, &exitCode) == 0) { close = true; } else if(exitCode != STILL_ACTIVE) { close = true; } } if(close) { Log(StrF(_T("Found parent process id (%d) is not running, Exit Code %d closing uac aware app"), m_processId, exitCode)); this->CancelThread(); } CloseHandle(hProcess); } void CUAC_Thread::OnEvent(int eventId, void *param) { DWORD startTick = GetTickCount(); Log(StrF(_T("Start of OnEvent, eventId: %s"), EnumName((eUacThreadEvents)eventId))); switch((eUacThreadEvents)eventId) { case UAC_PASTE: theApp.m_activeWnd.SendPaste(false); break; case UAC_COPY: theApp.m_activeWnd.SendCopy(CopyReasonEnum::COPY_TO_UNKOWN); break; case UAC_CUT: theApp.m_activeWnd.SendCut(); break; case UAC_EXIT: this->CancelThread(); break; } DWORD length = GetTickCount() - startTick; Log(StrF(_T("End of OnEvent, eventId: %s, Time: %d(ms)"), EnumName((eUacThreadEvents)eventId), length)); } CString CUAC_Thread::EnumName(eUacThreadEvents e) { switch(e) { case UAC_PASTE: return _T("Paste Elevated"); case UAC_COPY: return _T("COPY Elevated"); case UAC_CUT: return _T("Cut Elevated"); case UAC_EXIT: return _T("Save Startup Elevated"); } return _T(""); } bool CUAC_Thread::UACPaste() { bool ret = StartProcess(); FirePaste(); return ret; } bool CUAC_Thread::UACCopy() { bool ret = StartProcess(); FireCopy(); return ret; } bool CUAC_Thread::UACCut() { bool ret = StartProcess(); FireCut(); return ret; } bool CUAC_Thread::StartProcess() { bool ret = true; CString mutexName; mutexName.Format(_T("DittoAdminPaste_%d"), GetCurrentProcessId()); HANDLE mutex = CreateMutex(NULL, FALSE, mutexName); DWORD dwError = GetLastError(); if(dwError == ERROR_ALREADY_EXISTS) { Log(_T("Paste uac admin exe is already running just signalling paste")); } else { wchar_t szPath[MAX_PATH]; if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) { // Launch itself as administrator. SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = L"runas"; sei.lpFile = szPath; CString csParam; csParam.Format(_T("/uacpaste:%d"), GetCurrentProcessId()); sei.lpParameters = csParam; sei.nShow = SW_NORMAL; if (!ShellExecuteEx(&sei)) { Log(_T("Failed to startup paste as admin app, we are not pasting using admin app")); ret = false; } else { Log(_T("Startup up ditto paste as admin app, this will send ctrl-v to the admin app")); } } } CloseHandle(mutex); return ret; }