CDirectoryWatcher::CDirectoryWatcher(void) : m_bRunning(TRUE) , m_bCleaned(FALSE) , m_FolderCrawler(NULL) , blockTickCount(0) { // enable the required privileges for this process LPCTSTR arPrivelegeNames[] = { SE_BACKUP_NAME, SE_RESTORE_NAME, SE_CHANGE_NOTIFY_NAME }; for (int i=0; i<(sizeof(arPrivelegeNames)/sizeof(LPCTSTR)); ++i) { CAutoGeneralHandle hToken; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken.GetPointer())) { TOKEN_PRIVILEGES tp = { 1 }; if (LookupPrivilegeValue(NULL, arPrivelegeNames[i], &tp.Privileges[0].Luid)) { tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); } } } unsigned int threadId = 0; m_hThread = (HANDLE)_beginthreadex(NULL,0,ThreadEntry,this,0,&threadId); }
DWORD CRemoteCacheLink::GetProcessIntegrityLevel() const { DWORD dwIntegrityLevel = SECURITY_MANDATORY_MEDIUM_RID; CAutoGeneralHandle hProcess = GetCurrentProcess(); CAutoGeneralHandle hToken; if (OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_QUERY_SOURCE, hToken.GetPointer())) { // Get the Integrity level. DWORD dwLengthNeeded; if (!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwLengthNeeded)) { DWORD dwError = GetLastError(); if (dwError == ERROR_INSUFFICIENT_BUFFER) { PTOKEN_MANDATORY_LABEL pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwLengthNeeded); if (pTIL != NULL) { if (GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwLengthNeeded, &dwLengthNeeded)) { dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid)-1)); } LocalFree(pTIL); } } } } return dwIntegrityLevel; }
CString GetCacheID() { CAutoGeneralHandle token; DWORD len; BOOL result = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, token.GetPointer()); if(result) { GetTokenInformation(token, TokenStatistics, NULL, 0, &len); LPBYTE data = new BYTE[len]; GetTokenInformation(token, TokenStatistics, data, len, &len); LUID uid = ((PTOKEN_STATISTICS)data)->AuthenticationId; delete [ ] data; CString t; t.Format(_T("-%08x%08x"), uid.HighPart, uid.LowPart); return t; } return _T(""); }
CString GetCacheID() { CString t; CAutoGeneralHandle token; BOOL result = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, token.GetPointer()); if(result) { DWORD len = 0; GetTokenInformation(token, TokenStatistics, NULL, 0, &len); if (len >= sizeof (TOKEN_STATISTICS)) { std::unique_ptr<BYTE[]> data (new BYTE[len]); GetTokenInformation(token, TokenStatistics, data.get(), len, &len); LUID uid = ((PTOKEN_STATISTICS)data.get())->AuthenticationId; t.Format(_T("-%08x%08x"), uid.HighPart, uid.LowPart); } } return t; }
//static function, Share with SyncDialog UINT CProgressDlg::RunCmdList(CWnd* pWnd, STRING_VECTOR& cmdlist, STRING_VECTOR& dirlist, bool bShowCommand, CString* pfilename, volatile bool* bAbort, CGitGuardedByteArray* pdata, CGit* git) { UINT ret=0; std::vector<std::unique_ptr<CBlockCacheForPath>> cacheBlockList; std::vector<std::unique_ptr<CGit>> gitList; if (dirlist.empty()) cacheBlockList.push_back(std::make_unique<CBlockCacheForPath>(git->m_CurrentDir)); else { for (const auto& dir : dirlist) { auto pGit = std::make_unique<CGit>(); pGit->m_CurrentDir = dir; gitList.push_back(std::move(pGit)); cacheBlockList.push_back(std::make_unique<CBlockCacheForPath>(dir)); } } EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_START, 0); if(pdata) pdata->clear(); for (size_t i = 0; i < cmdlist.size(); ++i) { if(cmdlist[i].IsEmpty()) continue; if (bShowCommand) { CStringA str; if (gitList.empty() || gitList.size() == 1 && gitList[0]->m_CurrentDir == git->m_CurrentDir) str = CUnicodeUtils::GetMulti(cmdlist[i].Trim() + _T("\r\n\r\n"), CP_UTF8); else str = CUnicodeUtils::GetMulti((i > 0 ? _T("\r\n") : _T("")) + gitList[i]->m_CurrentDir + _T("\r\n") + cmdlist[i].Trim() + _T("\r\n\r\n"), CP_UTF8); for (int j = 0; j < str.GetLength(); ++j) { if(pdata) { pdata->m_critSec.Lock(); pdata->push_back(str[j]); pdata->m_critSec.Unlock(); } else pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]); } if(pdata) pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0); } PROCESS_INFORMATION pi; CAutoGeneralHandle hRead; int runAsyncRet = -1; if (gitList.empty()) runAsyncRet = git->RunAsync(cmdlist[i].Trim(), &pi, hRead.GetPointer(), nullptr, pfilename); else runAsyncRet = gitList[i]->RunAsync(cmdlist[i].Trim(), &pi, hRead.GetPointer(), nullptr, pfilename); if (runAsyncRet) { EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_FAILED, -1 * runAsyncRet); return runAsyncRet; } CAutoGeneralHandle piProcess(pi.hProcess); CAutoGeneralHandle piThread(pi.hThread); DWORD readnumber; char lastByte = '\0'; char byte; CString output; while (ReadFile(hRead, &byte, 1, &readnumber, nullptr)) { if(pdata) { if(byte == 0) byte = '\n'; pdata->m_critSec.Lock(); if (byte == '\n' && lastByte != '\r') pdata->push_back('\r'); pdata->push_back( byte); lastByte = byte; pdata->m_critSec.Unlock(); if(byte == '\r' || byte == '\n') pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0); } else pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,byte); } if (pdata) { pdata->m_critSec.Lock(); bool post = !pdata->empty(); pdata->m_critSec.Unlock(); if (post) EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_RUN, 0); } CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": waiting for process to finish (%s), aborted: %d\n"), (LPCTSTR)cmdlist[i], *bAbort); WaitForSingleObject(pi.hProcess, INFINITE); DWORD status=0; if(!GetExitCodeProcess(pi.hProcess,&status) || *bAbort) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": process %s finished, status code could not be fetched, (error %d; %s), aborted: %d\n"), (LPCTSTR)cmdlist[i], GetLastError(), (LPCTSTR)CFormatMessageWrapper(), *bAbort); EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_FAILED, status); return TGIT_GIT_ERROR_GET_EXIT_CODE; } CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": process %s finished with code %d\n"), (LPCTSTR)cmdlist[i], status); ret |= status; } EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_END, ret); return ret; }
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*cmdShow*/) { SetDllDirectory(L""); CAutoGeneralHandle hReloadProtection = ::CreateMutex(NULL, FALSE, GetCacheMutexName()); if ((!hReloadProtection) || (GetLastError() == ERROR_ALREADY_EXISTS)) { // An instance of TGitCache is already running ATLTRACE("TGitCache ignoring restart\n"); return 0; } CGitStatusCache::Create(); CGitStatusCache::Instance().Init(); SecureZeroMemory(szCurrentCrawledPath, sizeof(szCurrentCrawledPath)); DWORD dwThreadId; MSG msg; TCHAR szWindowClass[] = {TGIT_CACHE_WINDOW_NAME}; // create a hidden window to receive window messages. WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = 0; wcex.hCursor = 0; wcex.hbrBackground = 0; wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = 0; RegisterClassEx(&wcex); hWnd = CreateWindow(TGIT_CACHE_WINDOW_NAME, TGIT_CACHE_WINDOW_NAME, WS_CAPTION, 0, 0, 800, 300, NULL, 0, hInstance, 0); hTrayWnd = hWnd; if (hWnd == NULL) { return 0; } if (CRegStdDWORD(_T("Software\\TortoiseGit\\CacheTrayIcon"), FALSE)==TRUE) { SecureZeroMemory(&niData,sizeof(NOTIFYICONDATA)); DWORD dwMajor = 0; DWORD dwMinor = 0; GetShellVersion(&dwMajor, &dwMinor); DWORD dwVersion = PACKVERSION(dwMajor, dwMinor); if (dwVersion >= PACKVERSION(6,0)) niData.cbSize = sizeof(NOTIFYICONDATA); else if (dwVersion >= PACKVERSION(5,0)) niData.cbSize = NOTIFYICONDATA_V2_SIZE; else niData.cbSize = NOTIFYICONDATA_V1_SIZE; niData.uID = TRAY_ID; // own tray icon ID niData.hWnd = hWnd; niData.uFlags = NIF_ICON|NIF_MESSAGE; // load the icon niData.hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_TGITCACHE), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); // set the message to send // note: the message value should be in the // range of WM_APP through 0xBFFF niData.uCallbackMessage = TRAY_CALLBACK; Shell_NotifyIcon(NIM_ADD,&niData); // free icon handle if(niData.hIcon && DestroyIcon(niData.hIcon)) niData.hIcon = NULL; } // Create a thread which waits for incoming pipe connections CAutoGeneralHandle hPipeThread = CreateThread( NULL, // no security attribute 0, // default stack size PipeThread, (LPVOID) &bRun, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if (!hPipeThread) { //OutputDebugStringA("TSVNCache: Could not create pipe thread\n"); //DebugOutputLastError(); return 0; } else hPipeThread.CloseHandle(); // Create a thread which waits for incoming pipe connections CAutoGeneralHandle hCommandWaitThread = CreateThread( NULL, // no security attribute 0, // default stack size CommandWaitThread, (LPVOID) &bRun, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if (!hCommandWaitThread) { //OutputDebugStringA("TSVNCache: Could not create command wait thread\n"); //DebugOutputLastError(); return 0; } // loop to handle window messages. BOOL bLoopRet; while (bRun) { bLoopRet = GetMessage(&msg, NULL, 0, 0); if ((bLoopRet != -1)&&(bLoopRet != 0)) { DispatchMessage(&msg); } } bRun = false; Shell_NotifyIcon(NIM_DELETE,&niData); CGitStatusCache::Destroy(); return 0; }