├── .github └── workflows │ └── msbuild.yml ├── LICENSE ├── README.md ├── RunAsTI.cpp ├── RunAsTI.rc ├── RunAsTI.sln ├── RunAsTI.vcxproj ├── ShellExtension ├── Resource.h ├── RunAsTIShell.cpp ├── RunAsTIShell.h ├── RunAsTIShellExtension.cpp ├── RunAsTIShellExtension.def ├── RunAsTIShellExtension.idl ├── RunAsTIShellExtension.rc ├── RunAsTIShellExtension.rgs ├── RunAsTIShellExtension.vcxproj ├── RunAsTIShellExtensionps.def ├── dlldata.c ├── dllmain.cpp ├── dllmain.h ├── framework.h ├── pch.cpp ├── pch.h └── targetver.h ├── Utils.cpp ├── Utils.h └── resource.h /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: MSBuild 7 | 8 | on: 9 | workflow_dispatch: 10 | 11 | env: 12 | # Path to the solution file relative to the root of the project. 13 | SOLUTION_FILE_PATH: RunAsTI.sln 14 | 15 | # Configuration type to build. 16 | # You can convert this to a build matrix if you need coverage of multiple configuration types. 17 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 18 | BUILD_CONFIGURATION: Release 19 | 20 | permissions: 21 | contents: read 22 | 23 | jobs: 24 | build: 25 | runs-on: windows-latest 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | 30 | - name: Add MSBuild to PATH 31 | uses: microsoft/setup-msbuild@v1.0.2 32 | 33 | - name: Build 34 | working-directory: ${{env.GITHUB_WORKSPACE}} 35 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 36 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 37 | run: msbuild /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} 38 | 39 | - name: Upload 40 | uses: actions/upload-artifact@v4 41 | with: 42 | name: assets 43 | path: ${{github.workspace}}/x64/Release 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2024 mbcdev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RunAsTrustedInstaller 2 | 3 | A Windows command-line utility and Explorer extension to run programs with TrustedInstaller privileges. 4 | 5 | ## Description 6 | 7 | On Windows, TrustedInstaller privileges can sometimes be helpful for modifying or deleting criticial system files and folders that are protected by the OS. 8 | Likewise, there may be a need to deal with certain registry keys that are protected by an ACL that restricts access to the TrustedInstaller account. 9 | The utility was developed as a standalone executable and does not require any installation. 10 | 11 | Starting with Release 0.2, a Shell Extension Handler can optionally be installed, which provides an additional **"Run as TrustedInstaller"** context menu entry for `.exe` files in Windows Explorer. Note that both `RunAsTIShellExtension.dll` and `RunAsTI.exe` need to reside in the same directory. 12 | 13 | ## Getting Started 14 | 15 | ### Compilation 16 | 17 | ```text 18 | MSBuild RunAsTI.sln 19 | ``` 20 | 21 | Alternatively, you can simply open the `RunAsTI.sln` Solution File in Visual Studio and compile from there. 22 | 23 | ### Usage Examples 24 | 25 | Delete a file that cannot be deleted the regular way: 26 | 27 | ```text 28 | RunAsTI.exe cmd.exe /c del C:\Windows\system32\foobar.dat 29 | ``` 30 | 31 | Open the Registry Editor to view/modify/delete registry keys/values which are not accessible in normal operation mode: 32 | 33 | ```text 34 | RunAsTI.exe C:\Windows\regedit.exe 35 | ``` 36 | 37 | Install Shell Extension Handler: 38 | 39 | ```text 40 | RunAsTI.exe /install 41 | ``` 42 | 43 | Uninstall Shell Extension Handler: 44 | 45 | ```text 46 | RunAsTI.exe /uninstall 47 | ``` 48 | 49 | ## Version History 50 | 51 | * 0.2 52 | * Added Shell Extension Handler support 53 | * 0.1 54 | * Initial Release 55 | 56 | ## License 57 | 58 | This project is licensed under the MIT License. 59 | -------------------------------------------------------------------------------- /RunAsTI.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Utils.h" 5 | 6 | BOOL ExecuteCommand(std::wstring& appName, std::wstring& cmdArgs); 7 | 8 | int main() 9 | { 10 | int nArgs; 11 | int ret = 1; 12 | LPWSTR* lpArgs = CommandLineToArgvW(GetCommandLineW(), &nArgs); 13 | 14 | if (lpArgs != NULL) 15 | { 16 | if (nArgs == 2 && !_wcsicmp(lpArgs[1], L"/install")) { 17 | ShellExecute(NULL, L"open", L"regsvr32.exe", L"/i RunAsTIShellExtension.dll", NULL, SW_SHOWNORMAL); 18 | } 19 | else if (nArgs == 2 && !_wcsicmp(lpArgs[1], L"/uninstall")) { 20 | ShellExecute(NULL, L"open", L"regsvr32.exe", L"/u RunAsTIShellExtension.dll", NULL, SW_SHOWNORMAL); 21 | } 22 | else if (nArgs > 1) 23 | { 24 | std::wstring cmdApp; 25 | std::wstring cmdArgs; 26 | LPWSTR* lpCommandLine = (lpArgs + 1); 27 | cmdApp = *lpCommandLine; 28 | lpCommandLine++; 29 | while (*lpCommandLine != NULL) { 30 | if (!cmdArgs.empty()) cmdArgs += L" "; 31 | cmdArgs += *lpCommandLine; 32 | lpCommandLine++; 33 | } 34 | 35 | if (nArgs > 2) { 36 | std::wcout << "Executing '" << cmdApp.c_str() << "' with args '" << cmdArgs.c_str() << "'..." << std::endl; 37 | } 38 | else { 39 | std::wcout << "Executing '" << cmdApp.c_str() << "'..." << std::endl; 40 | } 41 | 42 | if (ExecuteCommand(cmdApp, cmdArgs)) 43 | { 44 | std::wcout << "SUCCESS!" << std::endl; 45 | ret = 0; 46 | } 47 | else { 48 | std::wcout << "FAILED!" << std::endl; 49 | } 50 | } 51 | else { 52 | std::wstring exeName = *lpArgs; 53 | PathStripPath(&exeName[0]); 54 | std::wcout << "Usage: " << exeName.c_str() << " Executes with TrustedInstaller privileges." << std::endl; 55 | std::wcout << " " << exeName.c_str() << " /install Installs Shell Extension Handler." << std::endl; 56 | std::wcout << " " << exeName.c_str() << " /uninstall Uninstalls Shell Extension Handler." << std::endl; 57 | } 58 | LocalFree(lpArgs); 59 | } 60 | 61 | return ret; 62 | } 63 | 64 | BOOL ExecuteCommand(std::wstring& appName, std::wstring& cmdArgs) 65 | { 66 | BOOL success = FALSE; 67 | 68 | if (!Utils::ImpersonateAsSystem()) 69 | { 70 | return FALSE; 71 | } 72 | 73 | DWORD dwPID = Utils::StartTIServiceAndGetPID(); 74 | if (dwPID == 0) 75 | { 76 | return FALSE; 77 | } 78 | 79 | HANDLE hToken = Utils::CreateAccessTokenFromPID(dwPID); 80 | if (hToken != INVALID_HANDLE_VALUE) 81 | { 82 | STARTUPINFO si; 83 | PROCESS_INFORMATION pi; 84 | 85 | GetStartupInfo(&si); 86 | success = CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, (LPWSTR)appName.c_str(), (LPWSTR)cmdArgs.c_str(), CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi); 87 | if (!success) { 88 | std::cout << "CreateProcessWithTokenW: " << std::system_category().message(GetLastError()) << std::endl; 89 | } 90 | } 91 | CloseHandle(hToken); 92 | 93 | return success; 94 | } 95 | 96 | 97 | -------------------------------------------------------------------------------- /RunAsTI.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #define APSTUDIO_HIDDEN_SYMBOLS 11 | #include "windows.h" 12 | #undef APSTUDIO_HIDDEN_SYMBOLS 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | #undef APSTUDIO_READONLY_SYMBOLS 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // English (United States) resources 20 | 21 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 22 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 23 | #pragma code_page(1252) 24 | 25 | #ifdef APSTUDIO_INVOKED 26 | ///////////////////////////////////////////////////////////////////////////// 27 | // 28 | // TEXTINCLUDE 29 | // 30 | 31 | 1 TEXTINCLUDE 32 | BEGIN 33 | "resource.h\0" 34 | END 35 | 36 | 2 TEXTINCLUDE 37 | BEGIN 38 | "\0" 39 | END 40 | 41 | 3 TEXTINCLUDE 42 | BEGIN 43 | "\r\n" 44 | "\0" 45 | END 46 | 47 | #endif // APSTUDIO_INVOKED 48 | 49 | 50 | ///////////////////////////////////////////////////////////////////////////// 51 | // 52 | // Version 53 | // 54 | 55 | VS_VERSION_INFO VERSIONINFO 56 | FILEVERSION 0,2,0,0 57 | PRODUCTVERSION 0,2,0,0 58 | FILEFLAGSMASK 0x3fL 59 | #ifdef _DEBUG 60 | FILEFLAGS 0x1L 61 | #else 62 | FILEFLAGS 0x0L 63 | #endif 64 | FILEOS 0x40004L 65 | FILETYPE 0x0L 66 | FILESUBTYPE 0x0L 67 | BEGIN 68 | BLOCK "StringFileInfo" 69 | BEGIN 70 | BLOCK "040904b0" 71 | BEGIN 72 | VALUE "CompanyName", "mbcdev" 73 | VALUE "FileDescription", "RunAsTrustedInstaller" 74 | VALUE "FileVersion", "0.2.0.0" 75 | VALUE "InternalName", "RunAsTI.exe" 76 | VALUE "LegalCopyright", "Copyright (c) 2023-2024 mbcdev" 77 | VALUE "OriginalFilename", "RunAsTI.exe" 78 | VALUE "ProductName", "RunAsTrustedInstaller" 79 | VALUE "ProductVersion", "0.2.0.0" 80 | END 81 | END 82 | BLOCK "VarFileInfo" 83 | BEGIN 84 | VALUE "Translation", 0x409, 1200 85 | END 86 | END 87 | 88 | #endif // English (United States) resources 89 | ///////////////////////////////////////////////////////////////////////////// 90 | 91 | 92 | 93 | #ifndef APSTUDIO_INVOKED 94 | ///////////////////////////////////////////////////////////////////////////// 95 | // 96 | // Generated from the TEXTINCLUDE 3 resource. 97 | // 98 | 99 | 100 | ///////////////////////////////////////////////////////////////////////////// 101 | #endif // not APSTUDIO_INVOKED 102 | 103 | -------------------------------------------------------------------------------- /RunAsTI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35506.116 d17.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RunAsTI", "RunAsTI.vcxproj", "{A39C5F40-DD2B-3A32-B8B5-5FD7CA1DF167}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {4B847C33-2D23-410A-8A48-FBE9F0EEA96E} = {4B847C33-2D23-410A-8A48-FBE9F0EEA96E} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RunAsTIShellExtension", "ShellExtension\RunAsTIShellExtension.vcxproj", "{4B847C33-2D23-410A-8A48-FBE9F0EEA96E}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {A39C5F40-DD2B-3A32-B8B5-5FD7CA1DF167}.Debug|x64.ActiveCfg = Debug|x64 20 | {A39C5F40-DD2B-3A32-B8B5-5FD7CA1DF167}.Debug|x64.Build.0 = Debug|x64 21 | {A39C5F40-DD2B-3A32-B8B5-5FD7CA1DF167}.Release|x64.ActiveCfg = Release|x64 22 | {A39C5F40-DD2B-3A32-B8B5-5FD7CA1DF167}.Release|x64.Build.0 = Release|x64 23 | {4B847C33-2D23-410A-8A48-FBE9F0EEA96E}.Debug|x64.ActiveCfg = Debug|x64 24 | {4B847C33-2D23-410A-8A48-FBE9F0EEA96E}.Debug|x64.Build.0 = Debug|x64 25 | {4B847C33-2D23-410A-8A48-FBE9F0EEA96E}.Release|x64.ActiveCfg = Release|x64 26 | {4B847C33-2D23-410A-8A48-FBE9F0EEA96E}.Release|x64.Build.0 = Release|x64 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {4F263B2A-4489-35EE-915B-91872F54CF5C} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /RunAsTI.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {A39C5F40-DD2B-3A32-B8B5-5FD7CA1DF167} 15 | Win32Proj 16 | x64 17 | RunAsTI 18 | 10.0 19 | 20 | 21 | 22 | Application 23 | Unicode 24 | v143 25 | 26 | 27 | Application 28 | Unicode 29 | v143 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | <_ProjectFileVersion>10.0.20506.1 40 | RunAsTI 41 | .exe 42 | true 43 | RunAsTI 44 | .exe 45 | true 46 | 47 | 48 | 49 | NotUsing 50 | MultiThreadedDebugDLL 51 | 52 | 53 | %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE 54 | 55 | 56 | %(AdditionalIncludeDirectories) 57 | $(ProjectDir)/$(IntDir) 58 | %(Filename).h 59 | %(Filename).tlb 60 | %(Filename)_i.c 61 | %(Filename)_p.c 62 | 63 | 64 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;shlwapi.lib 65 | %(AdditionalOptions) /machine:x64 66 | true 67 | %(IgnoreSpecificDefaultLibraries) 68 | Console 69 | RequireAdministrator 70 | false 71 | 72 | 73 | 74 | 75 | 76 | NotUsing 77 | MultiThreadedDLL 78 | 79 | 80 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;UNICODE;_UNICODE 81 | 82 | 83 | %(AdditionalIncludeDirectories) 84 | $(ProjectDir)/$(IntDir) 85 | %(Filename).h 86 | %(Filename).tlb 87 | %(Filename)_i.c 88 | %(Filename)_p.c 89 | 90 | 91 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;shlwapi.lib 92 | %(AdditionalOptions) /machine:x64 93 | true 94 | %(IgnoreSpecificDefaultLibraries) 95 | Console 96 | RequireAdministrator 97 | false 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /ShellExtension/Resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by RunAsTIShellExtension.rc 4 | // 5 | 6 | #define IDS_PROJNAME 100 7 | #define IDR_RUNASTISHELLEXTENSION 101 8 | 9 | // Next default values for new objects 10 | // 11 | #ifdef APSTUDIO_INVOKED 12 | #ifndef APSTUDIO_READONLY_SYMBOLS 13 | #define _APS_NEXT_RESOURCE_VALUE 201 14 | #define _APS_NEXT_COMMAND_VALUE 32768 15 | #define _APS_NEXT_CONTROL_VALUE 201 16 | #define _APS_NEXT_SYMED_VALUE 106 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShell.cpp: -------------------------------------------------------------------------------- 1 | // RunAsTIShell.cpp : Implementation of CRunAsTIShell 2 | 3 | #include "pch.h" 4 | #include "RunAsTIShell.h" 5 | 6 | #include 7 | 8 | // CRunAsTIShell 9 | 10 | CRunAsTIShell::CRunAsTIShell() 11 | { 12 | m_pIDFolder = NULL; 13 | ZeroMemory(m_szFile, sizeof(m_szFile)); 14 | m_pDataObj = NULL; 15 | ZeroMemory(m_pszVerb, sizeof(m_pszVerb)); 16 | ZeroMemory(m_pwszVerb, sizeof(m_pwszVerb)); 17 | 18 | m_hShieldBitmap = NULL; 19 | CreateIconBitmaps(); 20 | 21 | ZeroMemory(m_runAsTIPath, sizeof(m_runAsTIPath)); 22 | CreateRunAsTIExecutablePath(); 23 | } 24 | 25 | CRunAsTIShell::~CRunAsTIShell() 26 | { 27 | DeleteObject(m_hShieldBitmap); 28 | } 29 | 30 | void CRunAsTIShell::CreateIconBitmaps() 31 | { 32 | SHSTOCKICONINFO ssii = {}; 33 | ssii.cbSize = sizeof(ssii); 34 | 35 | HRESULT hres = SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &ssii); 36 | 37 | if (hres == S_OK && ssii.hIcon != NULL) 38 | { 39 | ICONINFOEX iconInfo = {}; 40 | iconInfo.cbSize = sizeof(iconInfo); 41 | if (GetIconInfoEx(ssii.hIcon, &iconInfo) && iconInfo.hbmColor != NULL) 42 | { 43 | m_hShieldBitmap = (HBITMAP)CopyImage(iconInfo.hbmColor, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 44 | } 45 | } 46 | 47 | if (ssii.hIcon != NULL) 48 | { 49 | DestroyIcon(ssii.hIcon); 50 | } 51 | } 52 | 53 | void CRunAsTIShell::CreateRunAsTIExecutablePath() 54 | { 55 | HKEY hKey; 56 | DWORD dwBufferSize = sizeof(m_runAsTIPath); 57 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID\\{3357a0e4-15a5-42fa-b591-10039a6c02a6}\\InprocServer32", 0, KEY_READ, &hKey) == ERROR_SUCCESS) 58 | { 59 | if (RegQueryValueEx(hKey, L"", 0, NULL, (LPBYTE)m_runAsTIPath, &dwBufferSize) == ERROR_SUCCESS) 60 | { 61 | PathRemoveFileSpec(m_runAsTIPath); 62 | PathAddBackslash(m_runAsTIPath); 63 | PathAppend(m_runAsTIPath, L"RunAsTI.exe"); 64 | } 65 | 66 | RegCloseKey(hKey); 67 | } 68 | } 69 | 70 | HRESULT CRunAsTIShell::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) 71 | { 72 | // If Initialize has already been called, release the old PIDL 73 | ILFree(m_pIDFolder); 74 | m_pIDFolder = nullptr; 75 | 76 | // Store the new PIDL. 77 | if (pidlFolder) 78 | { 79 | m_pIDFolder = ILClone(pidlFolder); 80 | } 81 | 82 | // If Initialize has already been called, release the old 83 | // IDataObject pointer. 84 | if (m_pDataObj) 85 | { 86 | m_pDataObj->Release(); 87 | } 88 | 89 | // If a data object pointer was passed in, save it and 90 | // extract the file name. 91 | if (pdtobj) 92 | { 93 | m_pDataObj = pdtobj; 94 | pdtobj->AddRef(); 95 | 96 | STGMEDIUM medium; 97 | FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; 98 | UINT uCount; 99 | 100 | if (SUCCEEDED(m_pDataObj->GetData(&fe, &medium))) 101 | { 102 | // Get the count of files dropped. 103 | uCount = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0); 104 | 105 | // Get the first file name from the CF_HDROP. 106 | if (uCount) 107 | { 108 | DragQueryFile((HDROP)medium.hGlobal, 0, m_szFile, sizeof(m_szFile) / sizeof(TCHAR)); 109 | } 110 | 111 | ReleaseStgMedium(&medium); 112 | } 113 | } 114 | 115 | // Duplicate the registry handle. 116 | if (hkeyProgID) 117 | { 118 | RegOpenKeyEx(hkeyProgID, nullptr, 0L, MAXIMUM_ALLOWED, &m_hRegKey); 119 | } 120 | 121 | return S_OK; 122 | } 123 | 124 | #define IDM_RUNASTI 0 125 | 126 | HRESULT CRunAsTIShell::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 127 | { 128 | HRESULT hr; 129 | 130 | if (!(CMF_DEFAULTONLY & uFlags)) 131 | { 132 | InsertMenu(hmenu, indexMenu, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_RUNASTI, _T("&Run as TrustedInstaller")); 133 | 134 | if (m_hShieldBitmap != nullptr) 135 | { 136 | SetMenuItemBitmaps(hmenu, indexMenu, MF_BYPOSITION, m_hShieldBitmap, m_hShieldBitmap); 137 | } 138 | 139 | hr = StringCbCopyA(m_pszVerb, sizeof(m_pszVerb), "RunAsTI"); 140 | hr = StringCbCopyW(m_pwszVerb, sizeof(m_pwszVerb), L"RunAsTI"); 141 | 142 | return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_RUNASTI + 1)); 143 | } 144 | 145 | return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0)); 146 | } 147 | 148 | HRESULT CRunAsTIShell::InvokeCommand(CMINVOKECOMMANDINFO* pici) 149 | { 150 | BOOL fEx = FALSE; 151 | BOOL fUnicode = FALSE; 152 | 153 | if (pici->cbSize == sizeof(CMINVOKECOMMANDINFOEX)) 154 | { 155 | fEx = TRUE; 156 | if ((pici->fMask & CMIC_MASK_UNICODE)) 157 | { 158 | fUnicode = TRUE; 159 | } 160 | } 161 | 162 | if (!fUnicode && HIWORD(pici->lpVerb)) 163 | { 164 | if (StrCmpIA(pici->lpVerb, m_pszVerb)) 165 | { 166 | return E_FAIL; 167 | } 168 | } 169 | else if (fUnicode && HIWORD(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW)) 170 | { 171 | if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, m_pwszVerb)) 172 | { 173 | return E_FAIL; 174 | } 175 | } 176 | else if (LOWORD(pici->lpVerb) != IDM_RUNASTI) 177 | { 178 | return E_FAIL; 179 | } 180 | else 181 | { 182 | if (PathFileExists(m_runAsTIPath)) 183 | { 184 | PathQuoteSpaces(m_szFile); 185 | ShellExecute(pici->hwnd, NULL, m_runAsTIPath, m_szFile, NULL, SW_SHOWNORMAL); 186 | } 187 | else 188 | { 189 | MessageBox(pici->hwnd, L"File not found.", L"RunAsTI", MB_OK | MB_ICONERROR); 190 | } 191 | } 192 | 193 | return S_OK; 194 | } 195 | 196 | HRESULT CRunAsTIShell::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, CHAR* pszName, UINT cchMax) 197 | { 198 | HRESULT hr = E_INVALIDARG; 199 | 200 | if (idCmd == IDM_RUNASTI) 201 | { 202 | switch (uType) 203 | { 204 | case GCS_HELPTEXTW: 205 | // Only useful for pre-Vista versions of Windows that 206 | // have a Status bar. 207 | hr = StringCchCopyW(reinterpret_cast(pszName), cchMax, L"Run as TrustedInstaller"); 208 | break; 209 | 210 | case GCS_VERBW: 211 | // GCS_VERBW is an optional feature that enables a caller 212 | // to discover the canonical name for the verb that is passed in 213 | // through idCommand. 214 | hr = StringCchCopyW(reinterpret_cast(pszName), cchMax, L"RunAsTI"); 215 | break; 216 | } 217 | } 218 | return hr; 219 | } 220 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShell.h: -------------------------------------------------------------------------------- 1 | // RunAsTIShell.h : Declaration of the CRunAsTIShell 2 | 3 | #pragma once 4 | #include "resource.h" // main symbols 5 | 6 | #include "RunAsTIShellExtension_i.h" 7 | 8 | #include 9 | 10 | #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) 11 | #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms." 12 | #endif 13 | 14 | using namespace ATL; 15 | 16 | 17 | // CRunAsTIShell 18 | 19 | class ATL_NO_VTABLE CRunAsTIShell : 20 | public CComObjectRootEx, 21 | public CComCoClass, 22 | public IDispatchImpl, 23 | public IShellExtInit, 24 | public IContextMenu 25 | { 26 | public: 27 | CRunAsTIShell(); 28 | virtual ~CRunAsTIShell(); 29 | 30 | DECLARE_REGISTRY_RESOURCEID(IDR_RUNASTISHELLEXTENSION) 31 | 32 | BEGIN_COM_MAP(CRunAsTIShell) 33 | COM_INTERFACE_ENTRY(IRunAsTIShell) 34 | COM_INTERFACE_ENTRY(IDispatch) 35 | COM_INTERFACE_ENTRY(IShellExtInit) 36 | COM_INTERFACE_ENTRY(IContextMenu) 37 | END_COM_MAP() 38 | 39 | DECLARE_PROTECT_FINAL_CONSTRUCT() 40 | 41 | HRESULT FinalConstruct() 42 | { 43 | return S_OK; 44 | } 45 | 46 | void FinalRelease() 47 | { 48 | } 49 | 50 | public: 51 | // Inherited via IShellExtInit 52 | HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID); 53 | 54 | // Inherited via IContextMenu 55 | HRESULT STDMETHODCALLTYPE QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); 56 | HRESULT STDMETHODCALLTYPE InvokeCommand(CMINVOKECOMMANDINFO* pici); 57 | HRESULT STDMETHODCALLTYPE GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, CHAR* pszName, UINT cchMax); 58 | 59 | private: 60 | LPITEMIDLIST m_pIDFolder; 61 | wchar_t m_szFile[MAX_PATH]; 62 | IDataObject* m_pDataObj; 63 | HKEY m_hRegKey; 64 | 65 | char m_pszVerb[128]; 66 | wchar_t m_pwszVerb[128]; 67 | 68 | HBITMAP m_hShieldBitmap; 69 | wchar_t m_runAsTIPath[512]; 70 | 71 | void CreateIconBitmaps(); 72 | void CreateRunAsTIExecutablePath(); 73 | }; 74 | 75 | OBJECT_ENTRY_AUTO(__uuidof(RunAsTIShell), CRunAsTIShell) 76 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtension.cpp: -------------------------------------------------------------------------------- 1 | // RunAsTIShellExtension.cpp : Implementation of DLL Exports. 2 | 3 | 4 | #include "pch.h" 5 | #include "framework.h" 6 | #include "resource.h" 7 | #include "RunAsTIShellExtension_i.h" 8 | #include "dllmain.h" 9 | 10 | 11 | using namespace ATL; 12 | 13 | // Used to determine whether the DLL can be unloaded by OLE. 14 | _Use_decl_annotations_ 15 | STDAPI DllCanUnloadNow(void) 16 | { 17 | return _AtlModule.DllCanUnloadNow(); 18 | } 19 | 20 | // Returns a class factory to create an object of the requested type. 21 | _Use_decl_annotations_ 22 | STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv) 23 | { 24 | return _AtlModule.DllGetClassObject(rclsid, riid, ppv); 25 | } 26 | 27 | // DllRegisterServer - Adds entries to the system registry. 28 | _Use_decl_annotations_ 29 | STDAPI DllRegisterServer(void) 30 | { 31 | // registers object, typelib and all interfaces in typelib 32 | HRESULT hr = _AtlModule.DllRegisterServer(); 33 | return hr; 34 | } 35 | 36 | // DllUnregisterServer - Removes entries from the system registry. 37 | _Use_decl_annotations_ 38 | STDAPI DllUnregisterServer(void) 39 | { 40 | HRESULT hr = _AtlModule.DllUnregisterServer(); 41 | return hr; 42 | } 43 | 44 | // DllInstall - Adds/Removes entries to the system registry per user per machine. 45 | STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine) 46 | { 47 | HRESULT hr = E_FAIL; 48 | static const wchar_t szUserSwitch[] = L"user"; 49 | 50 | if (pszCmdLine != nullptr) 51 | { 52 | if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) 53 | { 54 | ATL::AtlSetPerUserRegistration(true); 55 | } 56 | } 57 | 58 | if (bInstall) 59 | { 60 | hr = DllRegisterServer(); 61 | if (FAILED(hr)) 62 | { 63 | DllUnregisterServer(); 64 | } 65 | } 66 | else 67 | { 68 | hr = DllUnregisterServer(); 69 | } 70 | 71 | return hr; 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtension.def: -------------------------------------------------------------------------------- 1 | ; RunAsTIShellExtension.def : Declares the module parameters. 2 | 3 | LIBRARY 4 | 5 | EXPORTS 6 | DllCanUnloadNow PRIVATE 7 | DllGetClassObject PRIVATE 8 | DllRegisterServer PRIVATE 9 | DllUnregisterServer PRIVATE 10 | DllInstall PRIVATE 11 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtension.idl: -------------------------------------------------------------------------------- 1 | // RunAsTIShellExtension.idl : IDL source for RunAsTIShellExtension 2 | // 3 | 4 | // This file will be processed by the MIDL tool to 5 | // produce the type library (RunAsTIShellExtension.tlb) and marshalling code. 6 | 7 | import "oaidl.idl"; 8 | import "ocidl.idl"; 9 | 10 | [ 11 | object, 12 | uuid(7e288a16-2316-4895-ae2c-015cc952622c), 13 | dual, 14 | nonextensible, 15 | pointer_default(unique), 16 | helpstring("IRunAsTIShell Interface") 17 | ] 18 | interface IRunAsTIShell : IDispatch 19 | { 20 | }; 21 | [ 22 | uuid(f11bfb86-3b2a-4346-bf4f-f6b3182c8812), 23 | version(1.0), 24 | helpstring("RunAsTIShellExtension 1.0 Type Library") 25 | ] 26 | library RunAsTIShellExtensionLib 27 | { 28 | importlib("stdole2.tlb"); 29 | [ 30 | uuid(3357a0e4-15a5-42fa-b591-10039a6c02a6), 31 | helpstring("RunAsTIShellExtension") 32 | ] 33 | coclass RunAsTIShell 34 | { 35 | [default] interface IRunAsTIShell; 36 | }; 37 | }; 38 | 39 | import "shobjidl.idl"; 40 | 41 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtension.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbcdev/RunAsTrustedInstaller/899440c0a8ba9a05031814b9608a6304bb78f4a1/ShellExtension/RunAsTIShellExtension.rc -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtension.rgs: -------------------------------------------------------------------------------- 1 | HKCR 2 | { 3 | RunAsTI.Shell.1 = s 'RunAsTIShell Class' 4 | { 5 | CLSID = s '{3357a0e4-15a5-42fa-b591-10039a6c02a6}' 6 | } 7 | RunAsTI.Shell = s 'RunAsTIShell Class' 8 | { 9 | CLSID = s '{3357a0e4-15a5-42fa-b591-10039a6c02a6}' 10 | CurVer = s 'RunAsTI.Shell.1' 11 | } 12 | NoRemove CLSID 13 | { 14 | ForceRemove {3357a0e4-15a5-42fa-b591-10039a6c02a6} = s 'RunAsTIShell Class' 15 | { 16 | ProgID = s 'RunAsTI.Shell.1' 17 | VersionIndependentProgID = s 'RunAsTI.Shell' 18 | ForceRemove Programmable 19 | InprocServer32 = s '%MODULE%' 20 | { 21 | val ThreadingModel = s 'Apartment' 22 | } 23 | TypeLib = s '{f11bfb86-3b2a-4346-bf4f-f6b3182c8812}' 24 | Version = s '1.0' 25 | } 26 | } 27 | NoRemove exefile 28 | { 29 | NoRemove ShellEx 30 | { 31 | NoRemove ContextMenuHandlers 32 | { 33 | ForceRemove RunAsTI = s '{3357a0e4-15a5-42fa-b591-10039a6c02a6}' 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtension.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 17.0 15 | {4B847C33-2D23-410A-8A48-FBE9F0EEA96E} 16 | AtlProj 17 | 10.0 18 | 19 | 20 | 21 | DynamicLibrary 22 | true 23 | v143 24 | Unicode 25 | 26 | 27 | DynamicLibrary 28 | false 29 | v143 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | true 46 | true 47 | RunAsTIShellExtension 48 | 49 | 50 | true 51 | false 52 | RunAsTIShellExtension 53 | 54 | 55 | 56 | Use 57 | Level3 58 | Disabled 59 | _WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions) 60 | pch.h 61 | true 62 | 63 | 64 | false 65 | _DEBUG;%(PreprocessorDefinitions) 66 | RunAsTIShellExtension_i.h 67 | RunAsTIShellExtension_i.c 68 | RunAsTIShellExtension_p.c 69 | true 70 | $(IntDir)RunAsTIShellExtension.tlb 71 | 72 | true 73 | 74 | 75 | 0x0409 76 | $(IntDir);%(AdditionalIncludeDirectories) 77 | _DEBUG;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | .\RunAsTIShellExtension.def 82 | false 83 | 84 | 85 | 86 | 87 | Use 88 | Level3 89 | MaxSpeed 90 | _WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions) 91 | pch.h 92 | true 93 | 94 | 95 | false 96 | NDEBUG;%(PreprocessorDefinitions) 97 | RunAsTIShellExtension_i.h 98 | RunAsTIShellExtension_i.c 99 | RunAsTIShellExtension_p.c 100 | true 101 | $(IntDir)RunAsTIShellExtension.tlb 102 | 103 | true 104 | 105 | 106 | 0x0409 107 | $(IntDir);%(AdditionalIncludeDirectories) 108 | NDEBUG;%(PreprocessorDefinitions) 109 | 110 | 111 | Windows 112 | .\RunAsTIShellExtension.def 113 | true 114 | true 115 | false 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | false 130 | false 131 | 132 | 133 | 134 | 135 | 136 | 137 | Create 138 | Create 139 | 140 | 141 | 142 | 143 | false 144 | false 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /ShellExtension/RunAsTIShellExtensionps.def: -------------------------------------------------------------------------------- 1 | 2 | LIBRARY 3 | 4 | EXPORTS 5 | DllGetClassObject PRIVATE 6 | DllCanUnloadNow PRIVATE 7 | DllRegisterServer PRIVATE 8 | DllUnregisterServer PRIVATE 9 | -------------------------------------------------------------------------------- /ShellExtension/dlldata.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | DllData file -- generated by MIDL compiler 3 | 4 | DO NOT ALTER THIS FILE 5 | 6 | This file is regenerated by MIDL on every IDL file compile. 7 | 8 | To completely reconstruct this file, delete it and rerun MIDL 9 | on all the IDL files in this DLL, specifying this file for the 10 | /dlldata command line option 11 | 12 | *********************************************************/ 13 | 14 | #define PROXY_DELEGATION 15 | 16 | #include 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | EXTERN_PROXY_FILE( RunAsTIShellExtension ) 23 | 24 | 25 | PROXYFILE_LIST_START 26 | /* Start of list */ 27 | REFERENCE_PROXY_FILE( RunAsTIShellExtension ), 28 | /* End of list */ 29 | PROXYFILE_LIST_END 30 | 31 | 32 | DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID ) 33 | 34 | #ifdef __cplusplus 35 | } /*extern "C" */ 36 | #endif 37 | 38 | /* end of generated dlldata file */ 39 | -------------------------------------------------------------------------------- /ShellExtension/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Implementation of DllMain. 2 | 3 | #include "pch.h" 4 | #include "framework.h" 5 | #include "resource.h" 6 | #include "RunAsTIShellExtension_i.h" 7 | #include "dllmain.h" 8 | 9 | CRunAsTIShellExtensionModule _AtlModule; 10 | 11 | // DLL Entry Point 12 | extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 13 | { 14 | hInstance; 15 | return _AtlModule.DllMain(dwReason, lpReserved); 16 | } 17 | -------------------------------------------------------------------------------- /ShellExtension/dllmain.h: -------------------------------------------------------------------------------- 1 | // dllmain.h : Declaration of module class. 2 | 3 | class CRunAsTIShellExtensionModule : public ATL::CAtlDllModuleT< CRunAsTIShellExtensionModule > 4 | { 5 | public : 6 | DECLARE_LIBID(LIBID_RunAsTIShellExtensionLib) 7 | DECLARE_REGISTRY_APPID_RESOURCEID(IDR_RUNASTISHELLEXTENSION, "{43e7ea1a-d008-4548-8a87-352cf109537c}") 8 | }; 9 | 10 | extern class CRunAsTIShellExtensionModule _AtlModule; 11 | -------------------------------------------------------------------------------- /ShellExtension/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef STRICT 4 | #define STRICT 5 | #endif 6 | 7 | #include "targetver.h" 8 | 9 | #define _ATL_APARTMENT_THREADED 10 | 11 | #define _ATL_NO_AUTOMATIC_NAMESPACE 12 | 13 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 14 | 15 | 16 | #define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW 17 | 18 | #include "resource.h" 19 | #include 20 | #include 21 | #include 22 | -------------------------------------------------------------------------------- /ShellExtension/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /ShellExtension/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /ShellExtension/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace Utils { 7 | HANDLE CreateAccessTokenFromPID(DWORD dwProcessId) 8 | { 9 | HANDLE hDupToken = INVALID_HANDLE_VALUE; 10 | HANDLE hProc = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId); 11 | if (hProc) 12 | { 13 | HANDLE hToken = INVALID_HANDLE_VALUE; 14 | if (OpenProcessToken(hProc, TOKEN_DUPLICATE, &hToken)) 15 | { 16 | SECURITY_ATTRIBUTES attrs = { 17 | sizeof(SECURITY_ATTRIBUTES), 18 | NULL, 19 | FALSE, 20 | }; 21 | 22 | if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, &attrs, SecurityImpersonation, TokenImpersonation, &hDupToken)) 23 | { 24 | std::cout << "DuplicateTokenEx: " << std::system_category().message(GetLastError()) << std::endl; 25 | hDupToken = INVALID_HANDLE_VALUE; 26 | } 27 | } 28 | else { 29 | std::cout << "OpenProcessToken: " << std::system_category().message(GetLastError()) << std::endl; 30 | } 31 | CloseHandle(hToken); 32 | CloseHandle(hProc); 33 | } 34 | else { 35 | std::cout << "OpenProcess: " << std::system_category().message(GetLastError()) << std::endl; 36 | } 37 | 38 | return hDupToken; 39 | } 40 | 41 | DWORD GetPIDFromProcessName(LPCWSTR lpProcessName) 42 | { 43 | PROCESSENTRY32 pe32 = {}; 44 | DWORD pid = 0; 45 | 46 | HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 47 | if (hSnap != INVALID_HANDLE_VALUE) 48 | { 49 | pe32.dwSize = sizeof(PROCESSENTRY32); 50 | 51 | if (Process32First(hSnap, &pe32)) 52 | { 53 | do 54 | { 55 | if (!_wcsicmp(lpProcessName, pe32.szExeFile)) 56 | { 57 | pid = pe32.th32ProcessID; 58 | break; 59 | } 60 | } while (Process32Next(hSnap, &pe32)); 61 | } 62 | CloseHandle(hSnap); 63 | } 64 | else { 65 | std::cout << "CreateToolhelp32Snapshot: " << std::system_category().message(GetLastError()) << std::endl; 66 | } 67 | 68 | return pid; 69 | } 70 | 71 | BOOL ImpersonateAsSystem() 72 | { 73 | BOOL success = FALSE; 74 | 75 | DWORD dwPID = GetPIDFromProcessName(L"winlogon.exe"); 76 | if (dwPID != 0) 77 | { 78 | HANDLE hToken = CreateAccessTokenFromPID(dwPID); 79 | if (hToken != INVALID_HANDLE_VALUE) 80 | { 81 | success = ImpersonateLoggedOnUser(hToken); 82 | if (!success) { 83 | std::cout << "ImpersonateLoggedOnUser: " << std::system_category().message(GetLastError()) << std::endl; 84 | } 85 | CloseHandle(hToken); 86 | } 87 | } 88 | else { 89 | std::cout << "Impersonation Helper Process could not be found!" << std::endl; 90 | } 91 | 92 | return success; 93 | } 94 | 95 | DWORD StartTIServiceAndGetPID() 96 | { 97 | const DWORD SLEEP_INTERVAL = 100; 98 | DWORD dwLoopCount = 50; //50 * 100ms = 5s 99 | DWORD dwPID = 0; 100 | 101 | SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 102 | if (hSCM) 103 | { 104 | SC_HANDLE hService = OpenService(hSCM, L"TrustedInstaller", SERVICE_START | SERVICE_QUERY_STATUS); 105 | if (hService) 106 | { 107 | SERVICE_STATUS_PROCESS ssp = {}; 108 | DWORD dwBytesNeeded; 109 | 110 | do 111 | { 112 | if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) 113 | { 114 | if (ssp.dwCurrentState == SERVICE_RUNNING) 115 | { 116 | dwPID = ssp.dwProcessId; 117 | break; 118 | } 119 | else if (ssp.dwCurrentState == SERVICE_STOPPED) 120 | { 121 | if (!StartService(hService, 0, NULL)) 122 | { 123 | std::cout << "StartService: " << std::system_category().message(GetLastError()) << std::endl; 124 | break; 125 | } 126 | } 127 | } 128 | else { 129 | std::cout << "QueryServiceStatusEx: " << std::system_category().message(GetLastError()) << std::endl; 130 | } 131 | Sleep(SLEEP_INTERVAL); 132 | } while (--dwLoopCount > 0); 133 | 134 | CloseServiceHandle(hService); 135 | } 136 | else { 137 | std::cout << "OpenService: " << std::system_category().message(GetLastError()) << std::endl; 138 | } 139 | CloseServiceHandle(hSCM); 140 | } 141 | else { 142 | std::cout << "OpenSCManager: " << std::system_category().message(GetLastError()) << std::endl; 143 | } 144 | 145 | return dwPID; 146 | } 147 | } -------------------------------------------------------------------------------- /Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Utils { 6 | HANDLE CreateAccessTokenFromPID(DWORD dwProcessId); 7 | DWORD GetPIDFromProcessName(LPCWSTR lpProcessName); 8 | BOOL ImpersonateAsSystem(); 9 | DWORD StartTIServiceAndGetPID(); 10 | } 11 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by RunAsTI.rc 4 | // 5 | #define IDR_SHELL_EXTENSION_DLL 102 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 103 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | --------------------------------------------------------------------------------