From 2474e7344362cbbb9eee7329f1f4d2ef90e2805f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 16 Jun 2015 10:32:15 +0000 Subject: Miranda to remove any dlls from the root folder but the msvc runtime git-svn-id: http://svn.miranda-ng.org/main/trunk@14192 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/miranda32/src/checker.cpp | 210 ++++++++++++++++++++++++++++++++++++++++++ src/miranda32/src/miranda.cpp | 13 ++- src/miranda32/src/stdafx.h | 1 + 3 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 src/miranda32/src/checker.cpp (limited to 'src') diff --git a/src/miranda32/src/checker.cpp b/src/miranda32/src/checker.cpp new file mode 100644 index 0000000000..4e1a2a9b95 --- /dev/null +++ b/src/miranda32/src/checker.cpp @@ -0,0 +1,210 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "stdafx.h" + +static HANDLE hPipe = NULL; + +BOOL IsRunAsAdmin() +{ + BOOL bIsRunAsAdmin = FALSE; + DWORD dwError = ERROR_SUCCESS; + PSID pAdministratorsGroup = NULL; + + // Allocate and initialize a SID of the administrators group. + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsGroup)) { + dwError = GetLastError(); + goto Cleanup; + } + + // Determine whether the SID of administrators group is bEnabled in + // the primary access token of the process. + if (!CheckTokenMembership(NULL, pAdministratorsGroup, &bIsRunAsAdmin)) { + dwError = GetLastError(); + goto Cleanup; + } + +Cleanup: + // Centralized cleanup for all allocated resources. + if (pAdministratorsGroup) { + FreeSid(pAdministratorsGroup); + pAdministratorsGroup = NULL; + } + + return bIsRunAsAdmin; +} + +bool PrepareEscalation() +{ + // First try to create a file near Miranda32.exe + TCHAR szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, _countof(szPath)); + TCHAR *ext = _tcsrchr(szPath, '.'); + if (ext != NULL) + *ext = '\0'; + _tcscat(szPath, _T(".test")); + HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + // we are admins or UAC is disable, cool + CloseHandle(hFile); + DeleteFile(szPath); + return true; + } + + // Check the current process's "run as administrator" status. + if (IsRunAsAdmin()) + return true; + + // Elevate the process. Create a pipe for a stub first + TCHAR tszPipeName[MAX_PATH]; + _sntprintf(tszPipeName, _countof(tszPipeName), _T("\\\\.\\pipe\\Miranda_Pu_%d"), GetCurrentProcessId()); + hPipe = CreateNamedPipe(tszPipeName, PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL); + if (hPipe != INVALID_HANDLE_VALUE) { + TCHAR cmdLine[100], *p; + GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)); + if ((p = _tcsrchr(szPath, '\\')) != 0) + _tcscpy(p + 1, _T("pu_stub.exe")); + _sntprintf(cmdLine, _countof(cmdLine), _T("%d"), GetCurrentProcessId()); + + // Launch a stub + SHELLEXECUTEINFO sei = { 0 }; + sei.cbSize = sizeof(sei); + sei.lpVerb = L"runas"; + sei.lpFile = szPath; + sei.lpParameters = cmdLine; + sei.hwnd = NULL; + sei.nShow = SW_NORMAL; + if (ShellExecuteEx(&sei)) { + ConnectNamedPipe(hPipe, NULL); + return true; + } + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int TransactPipe(int opcode, const TCHAR *p1, const TCHAR *p2) +{ + BYTE buf[1024]; + DWORD l1 = lstrlen(p1), l2 = lstrlen(p2); + if (l1 > MAX_PATH || l2 > MAX_PATH) + return 0; + + *(DWORD*)buf = opcode; + TCHAR *dst = (TCHAR*)&buf[sizeof(DWORD)]; + lstrcpy(dst, p1); + dst += l1 + 1; + if (p2) { + lstrcpy(dst, p2); + dst += l2 + 1; + } + else *dst++ = 0; + + DWORD dwBytes = 0, dwError; + if (WriteFile(hPipe, buf, (DWORD)((BYTE*)dst - buf), &dwBytes, NULL) == 0) + return 0; + + dwError = 0; + if (ReadFile(hPipe, &dwError, sizeof(DWORD), &dwBytes, NULL) == 0) return 0; + if (dwBytes != sizeof(DWORD)) return 0; + + return dwError == ERROR_SUCCESS; +} + +int SafeCopyFile(const TCHAR *pSrc, const TCHAR *pDst) +{ + if (hPipe == NULL) + return CopyFile(pSrc, pDst, FALSE); + + return TransactPipe(1, pSrc, pDst); +} + +int SafeMoveFile(const TCHAR *pSrc, const TCHAR *pDst) +{ + if (hPipe == NULL) { + DeleteFile(pDst); + if (MoveFile(pSrc, pDst) == 0) // use copy on error + CopyFile(pSrc, pDst, FALSE); + DeleteFile(pSrc); + } + + return TransactPipe(2, pSrc, pDst); +} + +int SafeDeleteFile(const TCHAR *pFile) +{ + if (hPipe == NULL) + return DeleteFile(pFile); + + return TransactPipe(3, pFile, NULL); +} + +int SafeCreateDirectory(const TCHAR *pFolder) +{ + if (hPipe == NULL) + return CreateDirectory(pFolder, NULL); + + return TransactPipe(4, pFolder, NULL); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CheckDlls(const TCHAR *ptszPath) +{ + // ptszPath - slash-terminated string + TCHAR tszSearchPath[MAX_PATH]; + _sntprintf(tszSearchPath, _countof(tszSearchPath), _T("*.dll"), ptszPath); + + WIN32_FIND_DATA findData; + HANDLE hSearch = FindFirstFile(tszSearchPath, &findData); + if (hSearch == INVALID_HANDLE_VALUE) // no dlls? why bother + return true; + + bool bInit = false; + do { + // skip Visual Studio runtime if present + if (!_tcsnicmp(findData.cFileName, _T("msvc"), 4)) + continue; + + // there's smth to delete. init UAC + if (!bInit) { + // failed? then we need UAC + if (!PrepareEscalation()) { +LBL_Error: MessageBox(NULL, _T("Miranda failed to delete the obsolete file. Do it manually"), findData.cFileName, MB_ICONEXCLAMATION | MB_OK); + return false; + } + + bInit = true; + } + + if (!SafeDeleteFile(findData.cFileName)) + goto LBL_Error; + } + while (FindNextFile(hSearch, &findData)); + + return true; +} diff --git a/src/miranda32/src/miranda.cpp b/src/miranda32/src/miranda.cpp index 029c56562f..0f09be31b2 100644 --- a/src/miranda32/src/miranda.cpp +++ b/src/miranda32/src/miranda.cpp @@ -30,9 +30,18 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR cmdLine, int) GetModuleFileName(hInstance, tszPath, _countof(tszPath)); TCHAR *p = _tcsrchr(tszPath, '\\'); - if (p) - p[1] = 0; + if (p == NULL) + return 4; + // if current dir isn't set + *p = 0; + SetCurrentDirectory(tszPath); + + // all dlls must be moved to libs + if (!CheckDlls(tszPath)) + return 3; + + *p = '\\'; p[1] = 0; _tcsncat(tszPath, _T("libs"), _TRUNCATE); DWORD cbPath = (DWORD)_tcslen(tszPath); diff --git a/src/miranda32/src/stdafx.h b/src/miranda32/src/stdafx.h index 4d29d7be51..043f60eda2 100644 --- a/src/miranda32/src/stdafx.h +++ b/src/miranda32/src/stdafx.h @@ -26,3 +26,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +bool CheckDlls(const TCHAR *ptszPath); -- cgit v1.2.3