├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── COPYING ├── KeePass └── README.md ├── KeePassRDP.sln ├── KeePassRDP.ver ├── KeePassRDP.ver.gz ├── KeePassRDP ├── Commands │ ├── Command.cs │ ├── CommandArgumentAttribute.cs │ ├── CustomCommand.cs │ ├── FreeRdpCommand.cs │ └── MstscCommand.cs ├── Extensions.cs ├── GaussianBlur.cs ├── Generator │ ├── KprRdpFileForm.Designer.cs │ ├── KprRdpFileForm.cs │ ├── KprRdpFileForm.resx │ ├── RdpFile.cs │ ├── RdpFile_JsonSerializer.cs │ ├── RdpFile_Settings.cs │ ├── RdpSettingAttribute.cs │ ├── RdpSignscopeAttribute.cs │ └── SelfSignedCertificate.cs ├── KeePassRDP.cs ├── KeePassRDP.csproj ├── KeePassRDPexe.tt ├── KprConfig.cs ├── KprConfig_Executable.cs ├── KprConfig_Integration.cs ├── KprConfig_Picker.cs ├── KprConnectionManager.cs ├── KprCredential.cs ├── KprCredentialManager.cs ├── KprCredentialPicker.cs ├── KprCredentialPickerForm.Designer.cs ├── KprCredentialPickerForm.cs ├── KprCredentialPickerForm.resx ├── KprEntrySettings.cs ├── KprEntrySettingsTab.Designer.cs ├── KprEntrySettingsTab.cs ├── KprEntrySettingsTab.resx ├── KprHotkeyBox.cs ├── KprImageList.cs ├── KprMenu.cs ├── KprOptionsForm.Designer.cs ├── KprOptionsForm.cs ├── KprOptionsForm.resx ├── KprOptionsForm_Executable.cs ├── KprOptionsForm_Integration.cs ├── KprOptionsForm_Picker.cs ├── KprOptionsForm_Vault.cs ├── KprPictureBox.Designer.cs ├── KprPictureBox.cs ├── KprResourceManager.cs ├── KprSecureBackgroundForm.cs ├── KprSecureDesktopAppBar.cs ├── KprSecureDesktopToolBar.Designer.cs ├── KprSecureDesktopToolBar.cs ├── KprSecureDesktopToolBar.resx ├── KprSecureLockScreen.cs ├── KprSecureShellWindow.cs ├── KprSessionListForm.Designer.cs ├── KprSessionListForm.cs ├── KprSessionListForm.resx ├── KprSettingsControl.Designer.cs ├── KprSettingsControl.cs ├── KprSettingsControl.resx ├── KprToolStripDropDownButton.cs ├── KprToolTip.cs ├── KprVersion.tt ├── MessageFilter.cs ├── NativeCredentials.cs ├── NativeMethods.cs ├── Properties │ └── AssemblyInfo.cs ├── ReadOnlySet.cs ├── SecureDesktop.cs ├── SecureProcess.cs ├── ShadowSession.cs └── Utils.cs ├── KeePassRDPResources ├── KeePassRDPResources.csproj ├── Properties │ └── AssemblyInfo.cs ├── Resources.de.resx ├── Resources.resx └── Resources │ ├── Add.png │ ├── Cancel.png │ ├── Certificate.png │ ├── Checkmark.png │ ├── Disconnect.png │ ├── Expander.png │ ├── FileDestination.png │ ├── KeyVault.png │ ├── ListMembers.png │ ├── LoginScreen.png │ ├── ModalPopup.png │ ├── OpenFile.png │ ├── PowerShellProject.png │ ├── Refresh.png │ ├── RemoteDesktop.png │ ├── Remove.png │ ├── StatusHelpOutline.png │ ├── SwitchSourceOrTarget.png │ ├── User.png │ ├── UserFeedback.png │ └── Visual Studio 2022 Image Library EULA.rtf ├── KeePassRDPResourcesWriter ├── KeePassRDPResourcesWriter.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── KeePassRDPSetup ├── KeePassRDPSetup.csproj ├── Setup.cs ├── WixUI_de-de.wxl ├── WixUI_en-us.wxl └── winget │ ├── KeePassRDP.KeePassRDP.installer.tt │ ├── KeePassRDP.KeePassRDP.locale.en-US.tt │ └── KeePassRDP.KeePassRDP.tt ├── KeePassRDPUnmanaged ├── 32.ico ├── KeePassRDPUnmanaged.cpp ├── KeePassRDPUnmanaged.filters ├── KeePassRDPUnmanaged.rc ├── KeePassRDPUnmanaged.vcxproj ├── framework.h ├── pch.cpp ├── pch.h └── resource.h ├── README.md ├── doc ├── build_project.jpg ├── context_menu.jpg ├── credential_picker.jpg ├── credential_picker_regex.jpg ├── credential_picker_settings.jpg ├── credential_settings.jpg ├── customer_entries.jpg ├── db_structure.jpg ├── entry_settings.jpg ├── executable_settings.jpg ├── jumphost_entry.jpg ├── keyboard_shortcuts.jpg ├── rdp_file.jpg ├── rdp_subgroup.jpg ├── rdp_subgroup_entries.jpg ├── secure_desktop.jpg ├── self_signing.jpg ├── session_shadowing.jpg └── visibility_settings.jpg ├── make_release.ps1 └── make_winget.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | *.rtf linguist-documentation 7 | 8 | *.sln text eol=crlf 9 | *.csproj text eol=crlf 10 | *.vbproj text eol=crlf 11 | *.vcxproj text eol=crlf 12 | *.vcproj text eol=crlf 13 | *.dbproj text eol=crlf 14 | *.fsproj text eol=crlf 15 | *.lsproj text eol=crlf 16 | *.wixproj text eol=crlf 17 | *.modelproj text eol=crlf 18 | *.sqlproj text eol=crlf 19 | *.wwaproj text eol=crlf 20 | 21 | *.xproj text eol=crlf 22 | *.props text eol=crlf 23 | *.filters text eol=crlf 24 | *.vcxitems text eol=crlf 25 | 26 | *.ps1 text eol=crlf 27 | *.ps1x text eol=crlf 28 | *.psm1 text eol=crlf 29 | *.psd1 text eol=crlf 30 | *.ps1xml text eol=crlf 31 | *.pssc text eol=crlf 32 | *.psrc text eol=crlf 33 | *.cdxml text eol=crlf 34 | 35 | COPYING text eol=crlf 36 | 37 | ############################################################################### 38 | # Set default behavior for command prompt diff. 39 | # 40 | # This is need for earlier builds of msysgit that does not have it on by 41 | # default for csharp files. 42 | # Note: This is only used by command line 43 | ############################################################################### 44 | #*.cs diff=csharp 45 | 46 | ############################################################################### 47 | # Set the merge driver for project and solution files 48 | # 49 | # Merging from the command prompt will add diff markers to the files if there 50 | # are conflicts (Merging from VS is not affected by the settings below, in VS 51 | # the diff markers are never inserted). Diff markers may cause the following 52 | # file extensions to fail to load in VS. An alternative would be to treat 53 | # these files as binary and thus will always conflict and require user 54 | # intervention with every merge. To do so, just uncomment the entries below 55 | ############################################################################### 56 | #*.sln merge=binary 57 | #*.csproj merge=binary 58 | #*.vbproj merge=binary 59 | #*.vcxproj merge=binary 60 | #*.vcproj merge=binary 61 | #*.dbproj merge=binary 62 | #*.fsproj merge=binary 63 | #*.lsproj merge=binary 64 | #*.wixproj merge=binary 65 | #*.modelproj merge=binary 66 | #*.sqlproj merge=binary 67 | #*.wwaproj merge=binary 68 | 69 | ############################################################################### 70 | # behavior for image files 71 | # 72 | # image files are treated as binary by default. 73 | ############################################################################### 74 | #*.jpg binary 75 | #*.png binary 76 | #*.gif binary 77 | 78 | ############################################################################### 79 | # diff behavior for common document formats 80 | # 81 | # Convert binary document formats to text before diffing them. This feature 82 | # is only available from the command line. Turn it on by uncommenting the 83 | # entries below. 84 | ############################################################################### 85 | #*.doc diff=astextplain 86 | #*.DOC diff=astextplain 87 | #*.docx diff=astextplain 88 | #*.DOCX diff=astextplain 89 | #*.dot diff=astextplain 90 | #*.DOT diff=astextplain 91 | #*.pdf diff=astextplain 92 | #*.PDF diff=astextplain 93 | #*.rtf diff=astextplain 94 | #*.RTF diff=astextplain 95 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore generated content. 2 | /KeePassRDP/KeePassRDPexe.SED 3 | /KeePassRDP/KprVersion.cs 4 | /KeePassRDPResources/Resources.Designer.cs 5 | /KeePassRDPSetup/winget/KeePassRDP.KeePassRDP.installer.yaml 6 | /KeePassRDPSetup/winget/KeePassRDP.KeePassRDP.locale.en-US.yaml 7 | /KeePassRDPSetup/winget/KeePassRDP.KeePassRDP.yaml 8 | README.tt 9 | 10 | # Ignore version signing key. 11 | KeePassRDP.ver.private 12 | KeePassRDP.ver.public 13 | 14 | # Ignore files not needed for rebuilding. 15 | *.snk 16 | *.exe 17 | *.kdbx 18 | *.plgx 19 | *.zip 20 | *.msi 21 | /KeePass/KeePass.exe 22 | 23 | ## Ignore Visual Studio temporary files, build results, and 24 | ## files generated by popular Visual Studio add-ons. 25 | 26 | # Auto-generated files 27 | *.g.wxs 28 | 29 | # User-specific files 30 | *.suo 31 | *.user 32 | *.userosscache 33 | *.sln.docstates 34 | 35 | # User-specific files (MonoDevelop/Xamarin Studio) 36 | *.userprefs 37 | 38 | # Build results 39 | [Dd]ebug/ 40 | [Dd]ebugPublic/ 41 | [Rr]elease/ 42 | [Rr]eleases/ 43 | x64/ 44 | x86/ 45 | bld/ 46 | [Bb]in/ 47 | [Oo]bj/ 48 | [Ll]og/ 49 | 50 | # Visual Studio 2015 cache/options directory 51 | .vs/ 52 | # Uncomment if you have tasks that create the project's static files in wwwroot 53 | #wwwroot/ 54 | 55 | # MSTest test Results 56 | [Tt]est[Rr]esult*/ 57 | [Bb]uild[Ll]og.* 58 | 59 | # NUNIT 60 | *.VisualState.xml 61 | TestResult.xml 62 | 63 | # Build Results of an ATL Project 64 | [Dd]ebugPS/ 65 | [Rr]eleasePS/ 66 | dlldata.c 67 | 68 | # DNX 69 | project.lock.json 70 | project.fragment.lock.json 71 | artifacts/ 72 | 73 | *_i.c 74 | *_p.c 75 | *_i.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.pch 80 | *.pdb 81 | *.pgc 82 | *.pgd 83 | *.rsp 84 | *.sbr 85 | *.tlb 86 | *.tli 87 | *.tlh 88 | *.tmp 89 | *.tmp_proj 90 | *.log 91 | *.vspscc 92 | *.vssscc 93 | .builds 94 | *.pidb 95 | *.svclog 96 | *.scc 97 | 98 | # Chutzpah Test files 99 | _Chutzpah* 100 | 101 | # Visual C++ cache files 102 | ipch/ 103 | *.aps 104 | *.ncb 105 | *.opendb 106 | *.opensdf 107 | *.sdf 108 | *.cachefile 109 | *.VC.db 110 | *.VC.VC.opendb 111 | 112 | # Visual Studio profiler 113 | *.psess 114 | *.vsp 115 | *.vspx 116 | *.sap 117 | 118 | # TFS 2012 Local Workspace 119 | $tf/ 120 | 121 | # Guidance Automation Toolkit 122 | *.gpState 123 | 124 | # ReSharper is a .NET coding add-in 125 | _ReSharper*/ 126 | *.[Rr]e[Ss]harper 127 | *.DotSettings.user 128 | 129 | # JustCode is a .NET coding add-in 130 | .JustCode 131 | 132 | # TeamCity is a build add-in 133 | _TeamCity* 134 | 135 | # DotCover is a Code Coverage Tool 136 | *.dotCover 137 | 138 | # NCrunch 139 | _NCrunch_* 140 | .*crunch*.local.xml 141 | nCrunchTemp_* 142 | 143 | # MightyMoose 144 | *.mm.* 145 | AutoTest.Net/ 146 | 147 | # Web workbench (sass) 148 | .sass-cache/ 149 | 150 | # Installshield output folder 151 | [Ee]xpress/ 152 | 153 | # DocProject is a documentation generator add-in 154 | DocProject/buildhelp/ 155 | DocProject/Help/*.HxT 156 | DocProject/Help/*.HxC 157 | DocProject/Help/*.hhc 158 | DocProject/Help/*.hhk 159 | DocProject/Help/*.hhp 160 | DocProject/Help/Html2 161 | DocProject/Help/html 162 | 163 | # Click-Once directory 164 | publish/ 165 | 166 | # Publish Web Output 167 | *.[Pp]ublish.xml 168 | *.azurePubxml 169 | # TODO: Comment the next line if you want to checkin your web deploy settings 170 | # but database connection strings (with potential passwords) will be unencrypted 171 | #*.pubxml 172 | *.publishproj 173 | 174 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 175 | # checkin your Azure Web App publish settings, but sensitive information contained 176 | # in these scripts will be unencrypted 177 | PublishScripts/ 178 | 179 | # NuGet Packages 180 | *.nupkg 181 | # The packages folder can be ignored because of Package Restore 182 | **/packages/* 183 | # except build/, which is used as an MSBuild target. 184 | !**/packages/build/ 185 | # Uncomment if necessary however generally it will be regenerated when needed 186 | #!**/packages/repositories.config 187 | # NuGet v3's project.json files produces more ignoreable files 188 | *.nuget.props 189 | *.nuget.targets 190 | 191 | # Microsoft Azure Build Output 192 | csx/ 193 | *.build.csdef 194 | 195 | # Microsoft Azure Emulator 196 | ecf/ 197 | rcf/ 198 | 199 | # Windows Store app package directories and files 200 | AppPackages/ 201 | BundleArtifacts/ 202 | Package.StoreAssociation.xml 203 | _pkginfo.txt 204 | 205 | # Visual Studio cache files 206 | # files ending in .cache can be ignored 207 | *.[Cc]ache 208 | # but keep track of directories ending in .cache 209 | !*.[Cc]ache/ 210 | 211 | # Others 212 | ClientBin/ 213 | ~$* 214 | *~ 215 | *.dbmdl 216 | *.dbproj.schemaview 217 | *.jfm 218 | *.pfx 219 | *.publishsettings 220 | node_modules/ 221 | orleans.codegen.cs 222 | 223 | # Since there are multiple workflows, uncomment next line to ignore bower_components 224 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 225 | #bower_components/ 226 | 227 | # RIA/Silverlight projects 228 | Generated_Code/ 229 | 230 | # Backup & report files from converting an old project file 231 | # to a newer Visual Studio version. Backup files are not needed, 232 | # because we have git ;-) 233 | _UpgradeReport_Files/ 234 | Backup*/ 235 | UpgradeLog*.XML 236 | UpgradeLog*.htm 237 | 238 | # SQL Server files 239 | *.mdf 240 | *.ldf 241 | 242 | # Business Intelligence projects 243 | *.rdl.data 244 | *.bim.layout 245 | *.bim_*.settings 246 | 247 | # Microsoft Fakes 248 | FakesAssemblies/ 249 | 250 | # GhostDoc plugin setting file 251 | *.GhostDoc.xml 252 | 253 | # Node.js Tools for Visual Studio 254 | .ntvs_analysis.dat 255 | 256 | # Visual Studio 6 build log 257 | *.plg 258 | 259 | # Visual Studio 6 workspace options file 260 | *.opt 261 | 262 | # Visual Studio LightSwitch build output 263 | **/*.HTMLClient/GeneratedArtifacts 264 | **/*.DesktopClient/GeneratedArtifacts 265 | **/*.DesktopClient/ModelManifest.xml 266 | **/*.Server/GeneratedArtifacts 267 | **/*.Server/ModelManifest.xml 268 | _Pvt_Extensions 269 | 270 | # Paket dependency manager 271 | .paket/paket.exe 272 | paket-files/ 273 | 274 | # FAKE - F# Make 275 | .fake/ 276 | 277 | # JetBrains Rider 278 | .idea/ 279 | *.sln.iml 280 | 281 | # CodeRush 282 | .cr/ 283 | 284 | # Python Tools for Visual Studio (PTVS) 285 | __pycache__/ 286 | *.pyc 287 | -------------------------------------------------------------------------------- /KeePass/README.md: -------------------------------------------------------------------------------- 1 | Place a copy of KeePass.exe here before building KeePassRDP. -------------------------------------------------------------------------------- /KeePassRDP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32929.385 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassRDP", "KeePassRDP\KeePassRDP.csproj", "{CD6E2D26-2B40-4433-879D-2B07D159356C}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1} = {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1} 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassRDPResources", "KeePassRDPResources\KeePassRDPResources.csproj", "{8286969C-231B-4E96-98AC-E95E13B09DF0}" 12 | ProjectSection(ProjectDependencies) = postProject 13 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3} = {F4890E0E-3F01-4B34-87FB-A260A324B7C3} 14 | EndProjectSection 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassRDPResourcesWriter", "KeePassRDPResourcesWriter\KeePassRDPResourcesWriter.csproj", "{F4890E0E-3F01-4B34-87FB-A260A324B7C3}" 17 | EndProject 18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeePassRDPUnmanaged", "KeePassRDPUnmanaged\KeePassRDPUnmanaged.vcxproj", "{64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KeePassRDPSetup", "KeePassRDPSetup\KeePassRDPSetup.csproj", "{AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|Any CPU = Debug|Any CPU 25 | Debug|x64 = Debug|x64 26 | Debug|x86 = Debug|x86 27 | DebugPLGX|Any CPU = DebugPLGX|Any CPU 28 | DebugPLGX|x64 = DebugPLGX|x64 29 | DebugPLGX|x86 = DebugPLGX|x86 30 | Release|Any CPU = Release|Any CPU 31 | Release|x64 = Release|x64 32 | Release|x86 = Release|x86 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Debug|x64.ActiveCfg = Debug|Any CPU 38 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Debug|x64.Build.0 = Debug|Any CPU 39 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Debug|x86.ActiveCfg = Debug|Any CPU 40 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Debug|x86.Build.0 = Debug|Any CPU 41 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.DebugPLGX|Any CPU.ActiveCfg = DebugPLGX|Any CPU 42 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.DebugPLGX|Any CPU.Build.0 = DebugPLGX|Any CPU 43 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.DebugPLGX|x64.ActiveCfg = DebugPLGX|Any CPU 44 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.DebugPLGX|x64.Build.0 = DebugPLGX|Any CPU 45 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.DebugPLGX|x86.ActiveCfg = DebugPLGX|Any CPU 46 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.DebugPLGX|x86.Build.0 = DebugPLGX|Any CPU 47 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Release|x64.ActiveCfg = Release|Any CPU 50 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Release|x64.Build.0 = Release|Any CPU 51 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Release|x86.ActiveCfg = Release|Any CPU 52 | {CD6E2D26-2B40-4433-879D-2B07D159356C}.Release|x86.Build.0 = Release|Any CPU 53 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Debug|x64.ActiveCfg = Debug|Any CPU 56 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Debug|x64.Build.0 = Debug|Any CPU 57 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Debug|x86.ActiveCfg = Debug|Any CPU 58 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Debug|x86.Build.0 = Debug|Any CPU 59 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.DebugPLGX|Any CPU.ActiveCfg = Debug|Any CPU 60 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.DebugPLGX|Any CPU.Build.0 = Debug|Any CPU 61 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.DebugPLGX|x64.ActiveCfg = Debug|Any CPU 62 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.DebugPLGX|x64.Build.0 = Debug|Any CPU 63 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.DebugPLGX|x86.ActiveCfg = Debug|Any CPU 64 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.DebugPLGX|x86.Build.0 = Debug|Any CPU 65 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Release|Any CPU.ActiveCfg = Release|Any CPU 66 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Release|Any CPU.Build.0 = Release|Any CPU 67 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Release|x64.ActiveCfg = Release|Any CPU 68 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Release|x64.Build.0 = Release|Any CPU 69 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Release|x86.ActiveCfg = Release|Any CPU 70 | {8286969C-231B-4E96-98AC-E95E13B09DF0}.Release|x86.Build.0 = Release|Any CPU 71 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 72 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Debug|Any CPU.Build.0 = Debug|Any CPU 73 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Debug|x64.ActiveCfg = Debug|Any CPU 74 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Debug|x64.Build.0 = Debug|Any CPU 75 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Debug|x86.ActiveCfg = Debug|Any CPU 76 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Debug|x86.Build.0 = Debug|Any CPU 77 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.DebugPLGX|Any CPU.ActiveCfg = Debug|Any CPU 78 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.DebugPLGX|Any CPU.Build.0 = Debug|Any CPU 79 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.DebugPLGX|x64.ActiveCfg = Debug|Any CPU 80 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.DebugPLGX|x64.Build.0 = Debug|Any CPU 81 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.DebugPLGX|x86.ActiveCfg = Debug|Any CPU 82 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.DebugPLGX|x86.Build.0 = Debug|Any CPU 83 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Release|Any CPU.ActiveCfg = Release|Any CPU 84 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Release|Any CPU.Build.0 = Release|Any CPU 85 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Release|x64.ActiveCfg = Release|Any CPU 86 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Release|x64.Build.0 = Release|Any CPU 87 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Release|x86.ActiveCfg = Release|Any CPU 88 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3}.Release|x86.Build.0 = Release|Any CPU 89 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Debug|Any CPU.ActiveCfg = Debug|x64 90 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Debug|Any CPU.Build.0 = Debug|x64 91 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Debug|x64.ActiveCfg = Debug|x64 92 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Debug|x64.Build.0 = Debug|x64 93 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Debug|x86.ActiveCfg = Debug|Win32 94 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Debug|x86.Build.0 = Debug|Win32 95 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.DebugPLGX|Any CPU.ActiveCfg = Debug|x64 96 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.DebugPLGX|Any CPU.Build.0 = Debug|x64 97 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.DebugPLGX|x64.ActiveCfg = Debug|x64 98 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.DebugPLGX|x64.Build.0 = Debug|x64 99 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.DebugPLGX|x86.ActiveCfg = Debug|Win32 100 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.DebugPLGX|x86.Build.0 = Debug|Win32 101 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Release|Any CPU.ActiveCfg = Release|x64 102 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Release|Any CPU.Build.0 = Release|x64 103 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Release|x64.ActiveCfg = Release|x64 104 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Release|x64.Build.0 = Release|x64 105 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Release|x86.ActiveCfg = Release|Win32 106 | {64E5239E-4E0E-4C9A-BA76-FC1775B22CC1}.Release|x86.Build.0 = Release|Win32 107 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 108 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Debug|Any CPU.Build.0 = Debug|Any CPU 109 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Debug|x64.ActiveCfg = Debug|Any CPU 110 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Debug|x64.Build.0 = Debug|Any CPU 111 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Debug|x86.ActiveCfg = Debug|Any CPU 112 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Debug|x86.Build.0 = Debug|Any CPU 113 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.DebugPLGX|Any CPU.ActiveCfg = Debug|Any CPU 114 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.DebugPLGX|Any CPU.Build.0 = Debug|Any CPU 115 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.DebugPLGX|x64.ActiveCfg = Debug|Any CPU 116 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.DebugPLGX|x64.Build.0 = Debug|Any CPU 117 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.DebugPLGX|x86.ActiveCfg = Debug|Any CPU 118 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.DebugPLGX|x86.Build.0 = Debug|Any CPU 119 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Release|Any CPU.ActiveCfg = Release|Any CPU 120 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Release|Any CPU.Build.0 = Release|Any CPU 121 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Release|x64.ActiveCfg = Release|Any CPU 122 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Release|x64.Build.0 = Release|Any CPU 123 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Release|x86.ActiveCfg = Release|Any CPU 124 | {AF1F7F12-A267-4D94-9AD3-C16C6D2D5F99}.Release|x86.Build.0 = Release|Any CPU 125 | EndGlobalSection 126 | GlobalSection(SolutionProperties) = preSolution 127 | HideSolutionNode = FALSE 128 | EndGlobalSection 129 | GlobalSection(ExtensibilityGlobals) = postSolution 130 | SolutionGuid = {4766F9A5-4040-4C80-9F70-632299622F5A} 131 | EndGlobalSection 132 | EndGlobal 133 | -------------------------------------------------------------------------------- /KeePassRDP.ver: -------------------------------------------------------------------------------- 1 | : 2 | KeePassRDP:2.3 3 | : -------------------------------------------------------------------------------- /KeePassRDP.ver.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDP.ver.gz -------------------------------------------------------------------------------- /KeePassRDP/Commands/Command.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePassRDP.Extensions; 22 | using System; 23 | using System.Collections.Concurrent; 24 | using System.Collections.ObjectModel; 25 | using System.IO; 26 | using System.Linq; 27 | using System.Reflection; 28 | using System.Text; 29 | 30 | namespace KeePassRDP.Commands 31 | { 32 | internal interface ICommand 33 | { 34 | string Executable { get; } 35 | string ToString(); 36 | } 37 | 38 | internal abstract class Command : ICommand 39 | { 40 | private static readonly ConcurrentDictionary _fileExistsCache = new ConcurrentDictionary(2, 0); 41 | private static readonly ConcurrentDictionary>> _propertyCache = new ConcurrentDictionary>>(2, 0); 42 | 43 | internal static ICommand CreateInstance(string inputString) 44 | { 45 | var commandString = inputString.Split(new[] { ':' }, 2); 46 | var typeName = commandString.FirstOrDefault(); 47 | 48 | if (IsKnownCommand(typeName)) 49 | { 50 | var commandType = Type.GetType(string.Format("{0}.{1}", typeof(Command).Namespace, typeName)); 51 | var icommand = Activator.CreateInstance(commandType, new[] { commandString.Skip(1).FirstOrDefault() }) as ICommand; 52 | 53 | if (icommand is CustomCommand) 54 | icommand = (icommand as CustomCommand).Command; 55 | 56 | return icommand; 57 | } 58 | 59 | return null; 60 | } 61 | 62 | protected static bool IsKnownCommand(string typeName) 63 | { 64 | switch (typeName) 65 | { 66 | case "MstscCommand": 67 | case "FreeRdpCommand": 68 | case "CustomCommand": 69 | return true; 70 | } 71 | 72 | return false; 73 | } 74 | 75 | public virtual string Executable { get { return _executable; } } 76 | 77 | protected readonly string _executable; 78 | 79 | protected Command(string executable) 80 | { 81 | if (string.IsNullOrWhiteSpace(executable)) 82 | throw new ArgumentNullException("Command"); 83 | 84 | if (IsKnownCommand(executable)) 85 | { 86 | _executable = string.Empty; 87 | return; 88 | } 89 | 90 | if (!_fileExistsCache.AddOrUpdate(Path.GetFullPath(Environment.ExpandEnvironmentVariables(executable)), x => File.Exists(x), (x, y) => y ? y : File.Exists(x))) 91 | throw new FileNotFoundException(executable); 92 | 93 | _executable = executable; 94 | } 95 | 96 | public override string ToString() 97 | { 98 | var argumentsBuilder = new StringBuilder(); 99 | 100 | foreach (var prop in _propertyCache.GetOrAdd(GetType(), t => t 101 | .GetProperties(BindingFlags.Instance | BindingFlags.Public) 102 | .Select(x => 103 | { 104 | var commandArgumentAttribute = x.GetCustomAttributes(false).OfType().FirstOrDefault(); 105 | if (commandArgumentAttribute == null) 106 | return null; 107 | return new Tuple(x, commandArgumentAttribute); 108 | }) 109 | .Where(x => x != null && x.Item2 != null) 110 | .OrderBy(x => x.Item2.Position) 111 | .ToArray() 112 | .AsReadOnly()) 113 | .Select(x => new { Value = x.Item1.GetValue(this, null), Attribute = x.Item2 }) 114 | .Where(x => x.Value != null)) 115 | { 116 | var value = prop.Value; 117 | var attribute = prop.Attribute; 118 | 119 | if (value != null && (!(value is bool) || (bool)value == true)) 120 | { 121 | if (!string.IsNullOrEmpty(attribute.Parameter)) 122 | { 123 | argumentsBuilder.Append(attribute.Prefix); 124 | argumentsBuilder.Append(attribute.Parameter); 125 | if (attribute.Delimiter != char.MinValue) 126 | { 127 | var stringValue = value.ToString(); 128 | if (!string.IsNullOrEmpty(stringValue)) 129 | { 130 | argumentsBuilder.Append(attribute.Delimiter); 131 | argumentsBuilder.Append(stringValue); 132 | } 133 | } 134 | argumentsBuilder.Append(' '); 135 | } 136 | else 137 | { 138 | var stringValue = value.ToString(); 139 | if (!string.IsNullOrEmpty(stringValue)) 140 | { 141 | argumentsBuilder.Append('"'); 142 | argumentsBuilder.Append(stringValue); 143 | argumentsBuilder.Append('"'); 144 | argumentsBuilder.Append(' '); 145 | } 146 | } 147 | } 148 | } 149 | 150 | return argumentsBuilder.Length > 0 ? argumentsBuilder.ToString() : string.Empty; 151 | } 152 | } 153 | 154 | internal abstract class Command : Command where T : new() 155 | { 156 | protected Command(string executable) : base(executable) 157 | { 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /KeePassRDP/Commands/CommandArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | 23 | namespace KeePassRDP.Commands 24 | { 25 | [AttributeUsage(AttributeTargets.Property)] 26 | internal class CommandArgumentAttribute : Attribute 27 | { 28 | public int Position { get; set; } 29 | public string Parameter { get; set; } 30 | public char Delimiter { get; set; } 31 | public char Prefix { get; set; } 32 | 33 | public CommandArgumentAttribute() : this('/') { } 34 | 35 | public CommandArgumentAttribute(char prefix) 36 | { 37 | Position = int.MaxValue; 38 | Parameter = string.Empty; 39 | Delimiter = char.MinValue; 40 | Prefix = prefix; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /KeePassRDP/Commands/CustomCommand.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | using System.Collections.Generic; 23 | using System.IO; 24 | using System.Linq; 25 | 26 | namespace KeePassRDP.Commands 27 | { 28 | internal class CustomCommand : Command 29 | { 30 | public override string Executable { get { return Path.GetFullPath(Environment.ExpandEnvironmentVariables(_executable)); } } 31 | 32 | public ICommand Command { get { return _command; } } 33 | 34 | private readonly ICommand _command; 35 | 36 | public CustomCommand(string inputString) : this(inputString.Split(new[] { ':' }, 3).Skip(1)) 37 | { 38 | } 39 | 40 | private CustomCommand(IEnumerable commandString) : base(commandString.FirstOrDefault()) 41 | { 42 | _command = CreateInstance(string.Join(":", commandString)) ?? this; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /KeePassRDP/Commands/FreeRdpCommand.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePass.App.Configuration; 22 | using System.IO; 23 | 24 | namespace KeePassRDP.Commands 25 | { 26 | internal class FreeRdpCommand : Command, IMstscCommand 27 | { 28 | [CommandArgument(Position = 1)] 29 | public string Filename { get; set; } 30 | 31 | [CommandArgument(Parameter = "v", Delimiter = ':')] 32 | public string HostPort { get; set; } 33 | 34 | [CommandArgument(Parameter = "gateway:g", Delimiter = ':')] 35 | public string Gateway { get; set; } 36 | 37 | [CommandArgument(Parameter = "admin", Prefix = '+')] 38 | public bool? Admin { get; set; } 39 | 40 | [CommandArgument(Parameter = "f", Prefix = '+')] 41 | public bool? Fullscreen { get; set; } 42 | 43 | [CommandArgument(Parameter = "w", Delimiter = ':')] 44 | public int? Width { get; set; } 45 | 46 | [CommandArgument(Parameter = "h", Delimiter = ':')] 47 | public int? Height { get; set; } 48 | 49 | [CommandArgument(Parameter = "span", Prefix = '+')] 50 | public bool? Span { get; set; } 51 | 52 | [CommandArgument(Parameter = "multimon")] 53 | public bool? Multimon { get; set; } 54 | 55 | [CommandArgument(Parameter = "restricted-admin", Prefix = '+')] 56 | public bool? RestrictedAdmin { get; set; } 57 | 58 | public bool? Public { get; set; } 59 | public bool? RemoteGuard { get; set; } 60 | public string Shadow { get; set; } 61 | public bool? Control { get; set; } 62 | public bool? NoConsentPrompt { get; set; } 63 | 64 | public FreeRdpCommand() : this(null) 65 | { 66 | } 67 | 68 | public FreeRdpCommand(string executable) : base(string.IsNullOrWhiteSpace(executable) ? Path.Combine(AppConfigSerializer.AppDataDirectory, "wfreerdp.exe") : executable) 69 | { 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /KeePassRDP/Commands/MstscCommand.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | namespace KeePassRDP.Commands 22 | { 23 | interface IMstscCommand 24 | { 25 | string Filename { get; set; } 26 | string HostPort { get; set; } 27 | string Gateway { get; set; } 28 | bool? Admin { get; set; } 29 | bool? Fullscreen { get; set; } 30 | int? Width { get; set; } 31 | int? Height { get; set; } 32 | bool? Public { get; set; } 33 | bool? Span { get; set; } 34 | bool? Multimon { get; set; } 35 | bool? RestrictedAdmin { get; set; } 36 | bool? RemoteGuard { get; set; } 37 | string Shadow { get; set; } 38 | bool? Control { get; set; } 39 | bool? NoConsentPrompt { get; set; } 40 | } 41 | 42 | internal class MstscCommand : Command, IMstscCommand 43 | { 44 | [CommandArgument(Position = 1)] 45 | public string Filename { get; set; } 46 | 47 | [CommandArgument(Parameter = "v", Delimiter = ':')] 48 | public string HostPort { get; set; } 49 | 50 | [CommandArgument(Parameter = "g", Delimiter = ':')] 51 | public string Gateway { get; set; } 52 | 53 | [CommandArgument(Parameter = "admin")] 54 | public bool? Admin { get; set; } 55 | 56 | [CommandArgument(Parameter = "f")] 57 | public bool? Fullscreen { get; set; } 58 | 59 | [CommandArgument(Parameter = "w", Delimiter = ':')] 60 | public int? Width { get; set; } 61 | 62 | [CommandArgument(Parameter = "h", Delimiter = ':')] 63 | public int? Height { get; set; } 64 | 65 | [CommandArgument(Parameter = "public")] 66 | public bool? Public { get; set; } 67 | 68 | [CommandArgument(Parameter = "span")] 69 | public bool? Span { get; set; } 70 | 71 | [CommandArgument(Parameter = "multimon")] 72 | public bool? Multimon { get; set; } 73 | 74 | [CommandArgument(Parameter = "restrictedAdmin")] 75 | public bool? RestrictedAdmin { get; set; } 76 | 77 | [CommandArgument(Parameter = "remoteGuard")] 78 | public bool? RemoteGuard { get; set; } 79 | 80 | [CommandArgument(Parameter = "shadow", Delimiter = ':')] 81 | public string Shadow { get; set; } 82 | 83 | [CommandArgument(Parameter = "control")] 84 | public bool? Control { get; set; } 85 | 86 | [CommandArgument(Parameter = "noConsentPrompt")] 87 | public bool? NoConsentPrompt { get; set; } 88 | 89 | public MstscCommand() : this(null) 90 | { 91 | } 92 | 93 | public MstscCommand(string executable) : base(string.IsNullOrWhiteSpace(executable) ? KeePassRDPExt.MstscPath : executable) 94 | { 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /KeePassRDP/GaussianBlur.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | using System.Drawing; 23 | using System.Drawing.Imaging; 24 | using System.Runtime.CompilerServices; 25 | using System.Runtime.InteropServices; 26 | using System.Threading; 27 | using System.Threading.Tasks; 28 | 29 | namespace KeePassRDP 30 | { 31 | public static class GaussianBlur 32 | { 33 | private static readonly ParallelOptions _pOptions = new ParallelOptions 34 | { 35 | MaxDegreeOfParallelism = 16, 36 | TaskScheduler = TaskScheduler.Default 37 | }; 38 | 39 | // Based on https://github.com/mdymel/superfastblur 40 | public static void Process(Image image, int radial = 4, CancellationToken? cancellationToken = null) 41 | { 42 | var bitmap = image as Bitmap; 43 | if (bitmap == null) 44 | return; 45 | 46 | _pOptions.CancellationToken = cancellationToken ?? CancellationToken.None; 47 | 48 | var rct = new Rectangle(Point.Empty, bitmap.Size); 49 | var width = rct.Width; 50 | var height = rct.Height; 51 | var wh = width * height; 52 | 53 | var data = new int[wh]; 54 | var bits = bitmap.LockBits(rct, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 55 | Marshal.Copy(bits.Scan0, data, 0, data.Length); 56 | 57 | var alpha = new int[wh]; 58 | var red = new int[wh]; 59 | var green = new int[wh]; 60 | var blue = new int[wh]; 61 | 62 | Parallel.For(0, data.Length, _pOptions, i => 63 | { 64 | alpha[i] = (int)((data[i] & 0xff000000) >> 24); 65 | red[i] = (data[i] & 0xff0000) >> 16; 66 | green[i] = (data[i] & 0x00ff00) >> 8; 67 | blue[i] = (data[i] & 0x0000ff); 68 | }); 69 | 70 | int[] newAlpha = null, newRed = null, newGreen = null, newBlue = null; 71 | 72 | Parallel.Invoke( 73 | _pOptions, 74 | () => GaussBlur_4(ref alpha, out newAlpha, width, height, radial), 75 | () => GaussBlur_4(ref red, out newRed, width, height, radial), 76 | () => GaussBlur_4(ref green, out newGreen, width, height, radial), 77 | () => GaussBlur_4(ref blue, out newBlue, width, height, radial)); 78 | 79 | Parallel.For(0, data.Length, _pOptions, i => 80 | { 81 | var iAlpha = Math.Max(0, Math.Min(255, newAlpha[i])); 82 | var iRed = Math.Max(0, Math.Min(255, newRed[i])); 83 | var iGreen = Math.Max(0, Math.Min(255, newGreen[i])); 84 | var iBlue = Math.Max(0, Math.Min(255, newBlue[i])); 85 | 86 | data[i] = (int)((uint)(iAlpha << 24) | (uint)(iRed << 16) | (uint)(iGreen << 8) | (uint)iBlue); 87 | }); 88 | 89 | newAlpha = newRed = newGreen = newBlue = null; 90 | 91 | Marshal.Copy(data, 0, bits.Scan0, data.Length); 92 | bitmap.UnlockBits(bits); 93 | 94 | data = null; 95 | 96 | GC.Collect(GC.MaxGeneration); 97 | } 98 | 99 | [MethodImpl(256)] //MethodImplOptions.AggressiveInlining 100 | private static void GaussBlur_4(ref int[] source, out int [] dest, int w, int h, int r) 101 | { 102 | dest = new int[w * h]; 103 | 104 | var bxs = BoxesForGauss(r, 3); 105 | BoxBlur_4(ref source, ref dest, w, h, (bxs[0] - 1) / 2); 106 | BoxBlur_4(ref dest, ref source, w, h, (bxs[1] - 1) / 2); 107 | BoxBlur_4(ref source, ref dest, w, h, (bxs[2] - 1) / 2); 108 | } 109 | 110 | [MethodImpl(256)] //MethodImplOptions.AggressiveInlining 111 | private static int[] BoxesForGauss(int sigma, int n) 112 | { 113 | var ss = Math.Pow(sigma, 2); 114 | var wIdeal = Math.Sqrt((12d * ss / n) + 1d); 115 | var wl = (int)Math.Floor(wIdeal); 116 | //if (wl % 2 == 0) wl--; 117 | if ((wl & 1) == 0) wl--; 118 | var wu = wl + 2; 119 | 120 | var nwl = n * wl; 121 | var mIdeal = (12d * ss - nwl * wl - 4d * nwl - 3d * n) / (-4d * wl - 4d); 122 | var m = Math.Round(mIdeal); 123 | 124 | var sizes = new int[n]; 125 | for (var i = 0; i < n; i++) 126 | sizes[i] = i < m ? wl : wu; 127 | return sizes; 128 | } 129 | 130 | [MethodImpl(256)] //MethodImplOptions.AggressiveInlining 131 | private static void BoxBlur_4(ref int[] source, ref int[] dest, int w, int h, int r) 132 | { 133 | Buffer.BlockCopy(source, 0, dest, 0, source.Length * sizeof(int)); 134 | BoxBlurH_4(dest, source, w, h, r); 135 | BoxBlurT_4(source, dest, w, h, r); 136 | } 137 | 138 | [MethodImpl(256)] //MethodImplOptions.AggressiveInlining 139 | private static void BoxBlurH_4(int[] source, int[] dest, int w, int h, int r) 140 | { 141 | var iar = 1d / (r + r + 1); 142 | Parallel.For(0, h, _pOptions, i => 143 | { 144 | var ti = i * w; 145 | var li = ti; 146 | var ri = ti + r; 147 | var fv = source[ti]; 148 | var lv = source[ti + w - 1]; 149 | var val = (r + 1) * fv; 150 | for (var j = 0; j < r; j++) val += source[ti + j]; 151 | for (var j = 0; j <= r; j++) 152 | { 153 | val += source[ri++] - fv; 154 | dest[ti++] = (int)Math.Round(val * iar); 155 | } 156 | for (int j = r + 1, k = w - r; j < k; j++) 157 | { 158 | val += source[ri++] - source[li++]; 159 | dest[ti++] = (int)Math.Round(val * iar); 160 | } 161 | for (var j = w - r; j < w; j++) 162 | { 163 | val += lv - source[li++]; 164 | dest[ti++] = (int)Math.Round(val * iar); 165 | } 166 | }); 167 | } 168 | 169 | [MethodImpl(256)] //MethodImplOptions.AggressiveInlining 170 | private static void BoxBlurT_4(int[] source, int[] dest, int w, int h, int r) 171 | { 172 | var iar = (double)1 / (r + r + 1); 173 | Parallel.For(0, w, _pOptions, i => 174 | { 175 | var ti = i; 176 | var li = ti; 177 | var ri = ti + r * w; 178 | var fv = source[ti]; 179 | var lv = source[ti + w * (h - 1)]; 180 | var val = (r + 1) * fv; 181 | for (var j = 0; j < r; j++) 182 | val += source[ti + j * w]; 183 | for (var j = 0; j <= r; j++) 184 | { 185 | val += source[ri] - fv; 186 | dest[ti] = (int)Math.Round(val * iar); 187 | ri += w; 188 | ti += w; 189 | } 190 | for (int j = r + 1, k = h - r; j < k; j++) 191 | { 192 | val += source[ri] - source[li]; 193 | dest[ti] = (int)Math.Round(val * iar); 194 | li += w; 195 | ri += w; 196 | ti += w; 197 | } 198 | for (var j = h - r; j < h; j++) 199 | { 200 | val += lv - source[li]; 201 | dest[ti] = (int)Math.Round(val * iar); 202 | li += w; 203 | ti += w; 204 | } 205 | }); 206 | } 207 | } 208 | } -------------------------------------------------------------------------------- /KeePassRDP/Generator/KprRdpFileForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 128, 17 122 | 123 | 124 | 250, 17 125 | 126 | 127 | 352, 17 128 | 129 | -------------------------------------------------------------------------------- /KeePassRDP/Generator/RdpSettingAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | 23 | namespace KeePassRDP.Generator 24 | { 25 | [AttributeUsage(AttributeTargets.Property)] 26 | public class RdpSettingAttribute : Attribute 27 | { 28 | public string Template { get; private set; } 29 | public SettingCategory Category { get; set; } 30 | 31 | public RdpSettingAttribute(string template) 32 | { 33 | Template = template; 34 | Category = SettingCategory.General; 35 | } 36 | 37 | public enum SettingCategory 38 | { 39 | General = 0, 40 | Authentication, 41 | Network, 42 | Display, 43 | Redirect, 44 | AudioVideo, 45 | RemoteApp 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /KeePassRDP/Generator/RdpSignscopeAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | 23 | namespace KeePassRDP.Generator 24 | { 25 | [AttributeUsage(AttributeTargets.Property)] 26 | public class RdpSignscopeAttribute : Attribute 27 | { 28 | public string Scope { get; private set; } 29 | 30 | public RdpSignscopeAttribute(string scope) 31 | { 32 | Scope = scope; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /KeePassRDP/KeePassRDPexe.tt: -------------------------------------------------------------------------------- 1 | <#@ template compilerOptions="optimize+" hostspecific="true" language="C#" #> 2 | <#@ output extension=".SED" encoding="us-ascii" #> 3 | <#@ assembly name="EnvDTE" #> 4 | <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="System.Text" #> 7 | <#@ import namespace="System.Text.RegularExpressions" #> 8 | <# 9 | var directory = Path.GetDirectoryName(Host.TemplateFile); 10 | var className = Path.GetFileNameWithoutExtension(Host.TemplateFile); 11 | var namespaceString = Path.GetFileNameWithoutExtension(directory); 12 | var parent = Directory.GetParent(directory).FullName; 13 | 14 | var buildDate = DateTime.UtcNow; 15 | var informationalVersion = string.Empty; 16 | var assemblyVersion = string.Empty; 17 | var copyright = string.Empty; 18 | 19 | var assemblyInfo = File.ReadAllText(Path.Combine(directory, @"Properties\AssemblyInfo.cs")); 20 | var match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyInformationalVersion\\(\"([^\"]+)\"\\)\\]"); 21 | if (match.Success) 22 | informationalVersion = match.Groups[1].Value; 23 | 24 | match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyVersion\\(\"([^\"]+)\"\\)\\]"); 25 | if (match.Success) 26 | { 27 | assemblyVersion = match.Groups[1].Value; 28 | if (string.IsNullOrEmpty(informationalVersion)) 29 | informationalVersion = assemblyVersion; 30 | } 31 | 32 | /* 33 | // Build time. 34 | var configName = Host.ResolveParameterValue("-", "-", "Configuration"); 35 | if (string.IsNullOrWhiteSpace(configName)) 36 | { 37 | try 38 | { 39 | // Design time. 40 | var serviceProvider = (IServiceProvider)Host; 41 | var dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE)); 42 | configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name; 43 | } 44 | catch (Exception ex) 45 | { 46 | configName = ex.Message; 47 | } 48 | } 49 | 50 | if (configName == "Debug") 51 | informationalVersion = informationalVersion + ".debug"; 52 | */ 53 | 54 | var configName = "Release"; 55 | var sourceFiles = Path.Combine(directory, "bin", configName); 56 | #> 57 | [Version] 58 | Class=IEXPRESS 59 | SEDVersion=3 60 | [Options] 61 | PackagePurpose=ExtractOnly 62 | ShowInstallProgramWindow=0 63 | HideExtractAnimation=0 64 | UseLongFileName=1 65 | InsideCompressed=0 66 | CAB_FixedSize=0 67 | CAB_ResvCodeSigning=0 68 | RebootMode=N 69 | InstallPrompt=%InstallPrompt% 70 | DisplayLicense=%DisplayLicense% 71 | FinishMessage=%FinishMessage% 72 | TargetName=%TargetName% 73 | FriendlyName=%FriendlyName% 74 | AppLaunched=%AppLaunched% 75 | PostInstallCmd=%PostInstallCmd% 76 | AdminQuietInstCmd=%AdminQuietInstCmd% 77 | UserQuietInstCmd=%UserQuietInstCmd% 78 | SourceFiles=SourceFiles 79 | VersionInfo=VersionInfo 80 | [Strings] 81 | InstallPrompt= 82 | DisplayLicense=<#= parent #>\COPYING 83 | FinishMessage= 84 | TargetName=<#= parent #>\KeePassRDP_v<#= informationalVersion #>.exe 85 | FriendlyName=KeePassRDP v<#= informationalVersion #> 86 | AppLaunched= 87 | PostInstallCmd= 88 | AdminQuietInstCmd= 89 | UserQuietInstCmd= 90 | FILE0="KeePassRDP.plgx" 91 | [SourceFiles] 92 | SourceFiles0=<#= sourceFiles #>\ 93 | [SourceFiles0] 94 | %FILE0%= 95 | [VersionInfo] 96 | FromFile=<#= sourceFiles #>\KeePassRDP.dll -------------------------------------------------------------------------------- /KeePassRDP/KprCredential.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePass.Resources; 22 | using KeePass.UI; 23 | using KeePassLib.Security; 24 | using KeePassRDP.Utils; 25 | using System; 26 | using System.Collections.Generic; 27 | using System.ComponentModel; 28 | using System.Security; 29 | 30 | namespace KeePassRDP 31 | { 32 | /// 33 | /// Extends for consumption by 34 | /// 35 | internal sealed class KprCredential : NativeCredentials.Credential, IKprCredential 36 | { 37 | public const string CredentialComment = Util.KeePassRDP; 38 | 39 | public Guid GUID { get { return _guid; } } 40 | //public DateTimeOffset ValidUntil { get { return _validUntil; } } 41 | public bool IsValid { get { return _validUntil + _increase >= DateTimeOffset.UtcNow; } } 42 | 43 | private readonly Guid _guid; 44 | private readonly TimeSpan _ttl; 45 | private TimeSpan _increase; 46 | private DateTimeOffset _validUntil; 47 | 48 | internal KprCredential(ProtectedString username, SecureString password, string targetName, NativeCredentials.CRED_TYPE type, int ttl = 0) : base() 49 | { 50 | if (string.IsNullOrEmpty(targetName)) 51 | throw new ArgumentNullException("targetName"); 52 | 53 | _guid = Guid.NewGuid(); 54 | _ttl = ttl > 0 ? TimeSpan.FromSeconds(ttl) : TimeSpan.Zero; 55 | _increase = TimeSpan.Zero; 56 | _validUntil = _ttl.TotalMilliseconds > 0 ? DateTimeOffset.UtcNow + _ttl : DateTimeOffset.MaxValue; 57 | 58 | var usernameString = string.Empty; 59 | if (!username.IsEmpty) 60 | { 61 | var usernameChars = username.ReadChars(); 62 | usernameString = new string(usernameChars); 63 | MemoryUtil.SecureZeroMemory(usernameChars); 64 | } 65 | 66 | Type = type; 67 | TargetName = targetName; 68 | UserName = usernameString; 69 | //CredentialBlob = password.IsEmpty ? string.Empty : new string(password.ReadChars()); 70 | CredentialBlob = password.Copy(); 71 | Persist = NativeCredentials.CRED_PERSIST.SESSION; 72 | Attributes = new Dictionary 73 | { 74 | { "ValidUntil", _validUntil } 75 | }; 76 | Comment = CredentialComment; 77 | } 78 | 79 | internal KprCredential(NativeCredentials.Credential credential) : base() 80 | { 81 | _guid = Guid.NewGuid(); 82 | _ttl = TimeSpan.Zero; 83 | _increase = TimeSpan.Zero; 84 | if (credential.Attributes.ContainsKey("ValidUntil")) 85 | _validUntil = (DateTimeOffset)credential.Attributes["ValidUntil"]; 86 | 87 | Flags = credential.Flags; 88 | Type = credential.Type; 89 | TargetName = credential.TargetName; 90 | UserName = credential.UserName; 91 | CredentialBlob = credential.CredentialBlob != null && credential.CredentialBlob.Length > 0 ? credential.CredentialBlob.Copy() : null; 92 | Persist = credential.Persist; 93 | Attributes = credential.Attributes; 94 | Comment = credential.Comment; 95 | } 96 | 97 | public void IncreaseTTL(TimeSpan ttl) 98 | { 99 | if (ttl == TimeSpan.MaxValue) 100 | { 101 | _increase = TimeSpan.Zero; 102 | _validUntil = DateTimeOffset.MaxValue; 103 | 104 | return; 105 | } 106 | 107 | if (ttl.TotalMilliseconds > 0) 108 | _increase += ttl; 109 | } 110 | 111 | public void IncreaseTTL(int seconds) 112 | { 113 | if (seconds > 0) 114 | IncreaseTTL(TimeSpan.FromSeconds(seconds)); 115 | } 116 | 117 | public void DecreaseTTL(TimeSpan ttl) 118 | { 119 | if (ttl == TimeSpan.MaxValue) 120 | { 121 | _increase = TimeSpan.Zero; 122 | _validUntil = DateTimeOffset.MinValue; 123 | 124 | return; 125 | } 126 | 127 | if (ttl.TotalMilliseconds > 0) 128 | _increase -= ttl; 129 | } 130 | 131 | public void DecreaseTTL(int seconds) 132 | { 133 | if (seconds > 0) 134 | DecreaseTTL(TimeSpan.FromSeconds(seconds)); 135 | } 136 | 137 | public void ResetTTL() 138 | { 139 | _increase = TimeSpan.Zero; 140 | } 141 | 142 | public void ResetValidUntil() 143 | { 144 | _validUntil = _ttl.TotalMilliseconds > 0 ? DateTimeOffset.UtcNow + _ttl : DateTimeOffset.MaxValue; 145 | ResetTTL(); 146 | } 147 | 148 | /// 149 | /// Writes to Windows vault. 150 | /// 151 | /// Force overwriting of existing credentials. 152 | public void Write(bool force = false) 153 | { 154 | NativeCredentials.Credential cred = null; 155 | 156 | try 157 | { 158 | if (force || 159 | !NativeCredentials.CredRead(TargetName, Type, out cred) || 160 | cred == null || 161 | (cred.Persist == Persist && 162 | cred.Comment == Comment && 163 | (DateTimeOffset)cred.Attributes["ValidUntil"] < _validUntil)) 164 | NativeCredentials.CredWrite(this); 165 | } 166 | catch (Win32Exception ex) 167 | { 168 | VistaTaskDialog.ShowMessageBoxEx( 169 | string.Format(KprResourceManager.Instance["Failed to store credentials in vault: {0}"], ex.Message), 170 | null, 171 | Util.KeePassRDP + " - " + KPRes.Warning, 172 | VtdIcon.Warning, 173 | null, null, 0, null, 0); 174 | } 175 | finally 176 | { 177 | if (cred != null) 178 | cred.ZeroMemory(); 179 | } 180 | } 181 | 182 | public void Dispose() 183 | { 184 | NativeCredentials.Credential cred = null; 185 | 186 | try 187 | { 188 | if (NativeCredentials.CredRead(TargetName, Type, out cred) && 189 | cred != null && 190 | cred.Persist == Persist && 191 | cred.Comment == Comment && 192 | (DateTimeOffset)cred.Attributes["ValidUntil"] == _validUntil) 193 | NativeCredentials.CredDelete(TargetName, Type); 194 | } 195 | catch (Win32Exception) { } 196 | 197 | if (cred != null) 198 | cred.ZeroMemory(); 199 | 200 | ZeroMemory(); 201 | 202 | if (CredentialBlob != null) 203 | CredentialBlob.Dispose(); 204 | 205 | _validUntil = DateTimeOffset.MinValue; 206 | ResetTTL(); 207 | } 208 | } 209 | 210 | public interface IKprCredential : IDisposable 211 | { 212 | Guid GUID { get; } 213 | bool IsValid { get; } 214 | void Write(bool force = false); 215 | void ZeroMemory(); 216 | } 217 | } -------------------------------------------------------------------------------- /KeePassRDP/KprCredentialManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePass.Resources; 22 | using KeePass.UI; 23 | using KeePassRDP.Utils; 24 | using System; 25 | using System.Collections; 26 | using System.Collections.Generic; 27 | using System.ComponentModel; 28 | using System.Linq; 29 | using System.Timers; 30 | 31 | namespace KeePassRDP 32 | { 33 | /// 34 | /// Manager for adding and removing from Windows vault. 35 | /// 36 | /// 37 | /// Type of managed credentials. Needs to implement . 38 | /// 39 | internal class KprCredentialManager : IList where T : IKprCredential 40 | { 41 | private const int _interval = 1000; 42 | 43 | private enum Action : byte 44 | { 45 | Add, 46 | Remove 47 | } 48 | 49 | /// 50 | /// Interval in milliseconds to check for and remove invalid credentials. 51 | /// 52 | public double Interval 53 | { 54 | get { return _timer.Interval; } 55 | set { _timer.Interval = value; } 56 | } 57 | 58 | /// 59 | /// Switch to enable/disable checking for invalid credentials. 60 | /// 61 | public bool Enabled 62 | { 63 | get { return _timer.Enabled; } 64 | set { _timer.Enabled = value; } 65 | } 66 | 67 | /// 68 | public int Count 69 | { 70 | get { return _credentials.Count; } 71 | } 72 | 73 | /// 74 | public bool IsReadOnly 75 | { 76 | get { return false; } 77 | } 78 | 79 | /// 80 | public T this[int index] 81 | { 82 | get 83 | { 84 | return _credentials[index]; 85 | } 86 | 87 | set 88 | { 89 | throw new NotImplementedException(); 90 | } 91 | } 92 | 93 | private readonly List _credentials; 94 | private readonly Timer _timer; 95 | private readonly KprConfig _config; 96 | 97 | public KprCredentialManager(KprConfig config) : this(null, config) 98 | { 99 | } 100 | 101 | public KprCredentialManager(IEnumerable credentials, KprConfig config) 102 | { 103 | _config = config; 104 | _credentials = credentials == null ? new List() : new List(credentials); 105 | _timer = new Timer(_interval); 106 | _timer.Elapsed += OnTimer_Elapsed; 107 | 108 | if (!NativeCredentials.CredCanPersist(_config.CredVaultUseWindows ? NativeCredentials.CRED_TYPE.DOMAIN_PASSWORD : NativeCredentials.CRED_TYPE.GENERIC)) 109 | VistaTaskDialog.ShowMessageBoxEx( 110 | KprResourceManager.Instance["Unable to persist credentials in Windows vault."], 111 | null, 112 | string.Format("{0} - {1}", Util.KeePassRDP, KPRes.Error), 113 | VtdIcon.Error, 114 | null, null, 0, null, 0); 115 | 116 | try 117 | { 118 | NativeCredentials.Credential[] ncredentials; 119 | if (NativeCredentials.CredEnumerate(null, out ncredentials) && ncredentials.Length > 0) 120 | { 121 | _credentials.AddRange(ncredentials.Where(cred => cred.Comment == KprCredential.CredentialComment).Select(cred => new KprCredential(cred)).Cast()); 122 | foreach (var ncred in ncredentials.Where(cred => cred.Comment != KprCredential.CredentialComment)) 123 | ncred.ZeroMemory(); 124 | } 125 | } 126 | catch (Win32Exception) { } // Do not fail when vault is empty. 127 | 128 | if (_credentials.Count > 0) 129 | ManageTimer(Action.Add); 130 | } 131 | 132 | /// 133 | public void Add(T credential) 134 | { 135 | credential.Write(_config.CredVaultOverwriteExisting); 136 | credential.ZeroMemory(); 137 | 138 | _credentials.Add(credential); 139 | 140 | ManageTimer(Action.Add); 141 | } 142 | 143 | /// 144 | public void Insert(int index, T credential) 145 | { 146 | credential.Write(_config.CredVaultOverwriteExisting); 147 | credential.ZeroMemory(); 148 | 149 | _credentials.Insert(index, credential); 150 | 151 | ManageTimer(Action.Add); 152 | } 153 | 154 | /// 155 | public void AddRange(IEnumerable credentials) 156 | { 157 | if (!credentials.Any()) 158 | return; 159 | 160 | foreach (var credential in credentials) 161 | { 162 | credential.Write(_config.CredVaultOverwriteExisting); 163 | credential.ZeroMemory(); 164 | _credentials.Add(credential); 165 | } 166 | 167 | ManageTimer(Action.Add); 168 | } 169 | 170 | /// 171 | public bool Remove(Guid credentialGuid) 172 | { 173 | var result = false; 174 | 175 | foreach (var credential in _credentials.FindAll(x => x.GUID == credentialGuid)) 176 | using (credential) 177 | if (_credentials.Remove(credential)) 178 | result = true; 179 | 180 | if (result) 181 | ManageTimer(Action.Remove); 182 | 183 | return result; 184 | } 185 | 186 | /// 187 | public bool Remove(T credential) 188 | { 189 | using (credential) 190 | if (_credentials.Remove(credential)) 191 | { 192 | ManageTimer(Action.Remove); 193 | return true; 194 | } 195 | 196 | return false; 197 | } 198 | 199 | /// 200 | public int RemoveAll(Predicate match) 201 | { 202 | var count = 0; 203 | 204 | foreach (var credential in _credentials.FindAll(match)) 205 | { 206 | using (credential) 207 | if (_credentials.Remove(credential)) 208 | count++; 209 | } 210 | 211 | if (count > 0) 212 | ManageTimer(Action.Remove); 213 | 214 | return count; 215 | } 216 | 217 | /// 218 | public void RemoveAt(int index) 219 | { 220 | using (_credentials[index]) 221 | _credentials.RemoveAt(index); 222 | 223 | ManageTimer(Action.Remove); 224 | } 225 | 226 | /// 227 | public void Clear() 228 | { 229 | foreach (var credential in _credentials) 230 | credential.Dispose(); 231 | 232 | _credentials.Clear(); 233 | 234 | ManageTimer(Action.Remove); 235 | } 236 | 237 | /// 238 | public int IndexOf(T item) 239 | { 240 | return _credentials.IndexOf(item); 241 | } 242 | 243 | /// 244 | public bool Contains(T item) 245 | { 246 | return _credentials.Contains(item); 247 | } 248 | 249 | /// 250 | public List FindAll(Predicate match) 251 | { 252 | return _credentials.FindAll(match); 253 | } 254 | 255 | /// 256 | public void CopyTo(T[] array, int arrayIndex) 257 | { 258 | _credentials.CopyTo(array, arrayIndex); 259 | } 260 | 261 | /// 262 | public IEnumerator GetEnumerator() 263 | { 264 | return _credentials.GetEnumerator(); 265 | } 266 | 267 | /// 268 | IEnumerator IEnumerable.GetEnumerator() 269 | { 270 | return GetEnumerator(); 271 | } 272 | 273 | private void OnTimer_Elapsed(object sender, ElapsedEventArgs e) 274 | { 275 | RemoveAll(x => !x.IsValid); 276 | } 277 | 278 | private void ManageTimer(Action action) 279 | { 280 | Enabled = action == Action.Add || Count > 0; 281 | } 282 | } 283 | } -------------------------------------------------------------------------------- /KeePassRDP/KprCredentialPickerForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 412, 17 122 | 123 | 124 | 128, 17 125 | 126 | 127 | 250, 17 128 | 129 | -------------------------------------------------------------------------------- /KeePassRDP/KprEntrySettings.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePassRDP.Extensions; 22 | using KeePassRDP.Generator; 23 | using KeePassRDP.Utils; 24 | using Newtonsoft.Json; 25 | using System; 26 | using System.Collections.Generic; 27 | using System.ComponentModel; 28 | using System.Text.RegularExpressions; 29 | using System.Windows.Forms; 30 | 31 | namespace KeePassRDP 32 | { 33 | /// 34 | /// KeePassRDP settings for a single . 35 | /// 36 | public class KprEntrySettings : IDisposable 37 | { 38 | public static readonly KprEntrySettings Empty = new KprEntrySettings(true); 39 | 40 | public enum Inheritance 41 | { 42 | // Hide all settings from children 43 | Hide = CheckState.Unchecked, 44 | // Force all settings on children 45 | Force = CheckState.Checked, 46 | // Allow inheritance from parent settings 47 | Default = CheckState.Indeterminate 48 | } 49 | 50 | [JsonIgnore] 51 | public bool IsReadOnly { get { return _isReadOnly; } } 52 | 53 | [DefaultValue(false)] 54 | public bool Ignore { get { return _ignore; } set { if (_isReadOnly) throw new InvalidOperationException(); _ignore = value; } } 55 | 56 | [DefaultValue(true)] 57 | public bool UseCredpicker { get { return _useCredpicker; } set { if (_isReadOnly) throw new InvalidOperationException(); _useCredpicker = value; } } 58 | 59 | [DefaultValue(null)] 60 | public RdpFile RdpFile { get { return _rdpFile; } set { if (_isReadOnly) throw new InvalidOperationException(); _rdpFile = value; } } 61 | public bool ShouldSerializeRdpFile() { return _rdpFile != null && !_rdpFile.IsEmpty; } 62 | 63 | [DefaultValue(true)] 64 | public bool CpRecurseGroups { get { return _cpRecurseGroups; } set { if (_isReadOnly) throw new InvalidOperationException(); _cpRecurseGroups = value; } } 65 | 66 | [DefaultValue(true)] 67 | public bool CpIncludeDefaultRegex { get { return _cpIncludeDefaultRegex; } set { if (_isReadOnly) throw new InvalidOperationException(); _cpIncludeDefaultRegex = value; } } 68 | 69 | [DefaultValue(true)] 70 | public bool IncludeDefaultParameters { get { return _includeDefaultParameters; } set { if (_isReadOnly) throw new InvalidOperationException(); _includeDefaultParameters = value; } } 71 | 72 | [DefaultValue(false)] 73 | public bool ForceLocalUser { get { return _forceLocalUser; } set { if (_isReadOnly) throw new InvalidOperationException(); _forceLocalUser = value; } } 74 | 75 | [DefaultValue(false)] 76 | public bool ForceUpn { get { return _forceUpn; } set { if (_isReadOnly) throw new InvalidOperationException(); _forceUpn = value; } } 77 | 78 | [DefaultValue(false)] 79 | public bool RetryOnce { get { return _retryOnce; } set { if (_isReadOnly) throw new InvalidOperationException(); _retryOnce = value; } } 80 | 81 | [DefaultValue(Inheritance.Default)] 82 | public Inheritance Inherit { get { return _inherit; } set { if (_isReadOnly) throw new InvalidOperationException(); _inherit = value; } } 83 | 84 | public ICollection CpGroupUUIDs 85 | { 86 | get { return _isReadOnly && !_cpGroupUUIDs.IsReadOnly ? _cpGroupUUIDs.AsReadOnly() : _cpGroupUUIDs; } 87 | set { if (_isReadOnly) throw new InvalidOperationException(); _cpGroupUUIDs = new HashSet(value, StringComparer.OrdinalIgnoreCase); } 88 | } 89 | 90 | public ICollection CpExcludedGroupUUIDs 91 | { 92 | get { return _isReadOnly && !_cpExcludedGroupUUIDs.IsReadOnly ? _cpExcludedGroupUUIDs.AsReadOnly() : _cpExcludedGroupUUIDs; } 93 | set { if (_isReadOnly) throw new InvalidOperationException(); _cpGroupUUIDs = new HashSet(value, StringComparer.OrdinalIgnoreCase); } 94 | } 95 | 96 | public ICollection CpRegExPatterns 97 | { 98 | get { return _isReadOnly && !_cpRegExPatterns.IsReadOnly ? _cpRegExPatterns.AsReadOnly() : _cpRegExPatterns; } 99 | set { if (_isReadOnly) throw new InvalidOperationException(); _cpRegExPatterns = new List(value); } 100 | } 101 | 102 | public ICollection MstscParameters 103 | { 104 | get { return _isReadOnly && !_mstscParameters.IsReadOnly ? _mstscParameters.AsReadOnly() : _mstscParameters; } 105 | set { if (_isReadOnly) throw new InvalidOperationException(); _mstscParameters = new List(value); } 106 | } 107 | 108 | public bool ShouldSerializeCpGroupUUIDs() { return _cpGroupUUIDs != null && _cpGroupUUIDs.Count > 0; } 109 | public bool ShouldSerializeCpExcludedGroupUUIDs() { return _cpExcludedGroupUUIDs != null && _cpExcludedGroupUUIDs.Count > 0; } 110 | public bool ShouldSerializeCpRegExPatterns() { return _cpRegExPatterns != null && _cpRegExPatterns.Count > 0; } 111 | public bool ShouldSerializeMstscParameters() { return _mstscParameters != null && _mstscParameters.Count > 0; } 112 | 113 | private ISet _cpGroupUUIDs; 114 | private ISet _cpExcludedGroupUUIDs; 115 | private IList _cpRegExPatterns; 116 | private IList _mstscParameters; 117 | 118 | private bool _isReadOnly; 119 | private bool _ignore; 120 | private bool _useCredpicker; 121 | private RdpFile _rdpFile; 122 | private bool _cpRecurseGroups; 123 | private bool _cpIncludeDefaultRegex; 124 | private bool _includeDefaultParameters; 125 | private bool _forceLocalUser; 126 | private bool _forceUpn; 127 | private bool _retryOnce; 128 | private Inheritance _inherit; 129 | 130 | public KprEntrySettings() 131 | { 132 | _isReadOnly = false; 133 | _cpGroupUUIDs = new HashSet(StringComparer.OrdinalIgnoreCase); 134 | _cpExcludedGroupUUIDs = new HashSet(StringComparer.OrdinalIgnoreCase); 135 | _cpRegExPatterns = new List(); 136 | _mstscParameters = new List(); 137 | _ignore = false; 138 | _useCredpicker = true; 139 | _rdpFile = null; 140 | _cpRecurseGroups = true; 141 | _cpIncludeDefaultRegex = true; 142 | _includeDefaultParameters = true; 143 | _forceLocalUser = false; 144 | _forceUpn = false; 145 | _retryOnce = false; 146 | _inherit = Inheritance.Default; 147 | } 148 | 149 | private KprEntrySettings(bool readOnly) : this() 150 | { 151 | if (readOnly) 152 | { 153 | _isReadOnly = true; 154 | _cpGroupUUIDs = _cpGroupUUIDs.AsReadOnly(); 155 | _cpExcludedGroupUUIDs = _cpExcludedGroupUUIDs.AsReadOnly(); 156 | _cpRegExPatterns = _cpRegExPatterns.AsReadOnly(); 157 | _mstscParameters = _mstscParameters.AsReadOnly(); 158 | } 159 | } 160 | 161 | internal KprEntrySettings(KprEntrySettings kprEntrySettings, bool readOnly = false) 162 | { 163 | _isReadOnly = readOnly; 164 | _cpGroupUUIDs = new HashSet(kprEntrySettings._cpGroupUUIDs, StringComparer.OrdinalIgnoreCase); 165 | _cpExcludedGroupUUIDs = new HashSet(kprEntrySettings._cpExcludedGroupUUIDs, StringComparer.OrdinalIgnoreCase); 166 | _cpRegExPatterns = new List(kprEntrySettings._cpRegExPatterns); 167 | _mstscParameters = new List(kprEntrySettings._mstscParameters); 168 | if (readOnly) 169 | { 170 | _cpGroupUUIDs = _cpGroupUUIDs.AsReadOnly(); 171 | _cpExcludedGroupUUIDs = _cpExcludedGroupUUIDs.AsReadOnly(); 172 | _cpRegExPatterns = _cpRegExPatterns.AsReadOnly(); 173 | _mstscParameters = _mstscParameters.AsReadOnly(); 174 | } 175 | _ignore = kprEntrySettings._ignore; 176 | _useCredpicker = kprEntrySettings._useCredpicker; 177 | _rdpFile = kprEntrySettings._rdpFile; 178 | _cpRecurseGroups = kprEntrySettings._cpRecurseGroups; 179 | _cpIncludeDefaultRegex = kprEntrySettings._cpIncludeDefaultRegex; 180 | _includeDefaultParameters = kprEntrySettings._includeDefaultParameters; 181 | _forceLocalUser = kprEntrySettings._forceLocalUser; 182 | _forceUpn = kprEntrySettings._forceUpn; 183 | _retryOnce = kprEntrySettings._retryOnce; 184 | _inherit = kprEntrySettings._inherit; 185 | } 186 | 187 | public KprEntrySettings AsReadOnly() 188 | { 189 | if (_isReadOnly) 190 | return this; 191 | return new KprEntrySettings(this, true); 192 | } 193 | 194 | public void Clear() 195 | { 196 | if (!_cpGroupUUIDs.IsReadOnly) 197 | _cpGroupUUIDs.Clear(); 198 | if (!_cpExcludedGroupUUIDs.IsReadOnly) 199 | _cpExcludedGroupUUIDs.Clear(); 200 | if (!_cpRegExPatterns.IsReadOnly) 201 | _cpRegExPatterns.Clear(); 202 | if (!_mstscParameters.IsReadOnly) 203 | _mstscParameters.Clear(); 204 | } 205 | 206 | public void Dispose() 207 | { 208 | Clear(); 209 | if (_rdpFile != null) 210 | _rdpFile.Dispose(); 211 | } 212 | 213 | public override string ToString() 214 | { 215 | if (_rdpFile != null && _rdpFile.IsEmpty) 216 | { 217 | using (_rdpFile) 218 | _rdpFile = null; 219 | } 220 | 221 | return Regex.Replace( 222 | JsonConvert.SerializeObject(this, Util.JsonSerializerSettings), 223 | "^{}$", 224 | string.Empty, 225 | RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); 226 | } 227 | 228 | public static implicit operator string(KprEntrySettings kprEntrySettings) 229 | { 230 | return kprEntrySettings.ToString(); 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /KeePassRDP/KprEntrySettingsTab.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | False 122 | 123 | 124 | False 125 | 126 | 127 | 250, 17 128 | 129 | 130 | 128, 17 131 | 132 | 133 | False 134 | 135 | 136 | False 137 | 138 | 139 | False 140 | 141 | 142 | 352, 17 143 | 144 | 145 | 479, 17 146 | 147 | -------------------------------------------------------------------------------- /KeePassRDP/KprMenu.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | using System.Collections.ObjectModel; 23 | using System.Linq; 24 | using System.Windows.Forms; 25 | 26 | namespace KeePassRDP 27 | { 28 | public static class KprMenu 29 | { 30 | #region Constants 31 | public const Keys DefaultOpenRdpConnectionShortcut = Keys.Control | Keys.M; //131149; 32 | public const Keys DefaultOpenRdpConnectionAdminShortcut = Keys.Control | Keys.Shift | Keys.M; //393293; 33 | 34 | public const MenuItem DefaultToolbarItems = MenuItem.OpenRdpConnection | MenuItem.OpenRdpConnectionNoCred; 35 | //public const MenuItem DefaultContextMenuItems = DefaultToolbarItems | MenuItem.OpenRdpConnectionAdmin | MenuItem.OpenRdpConnectionNoCredAdmin | MenuItem.IgnoreCredentials; 36 | public const MenuItem DefaultContextMenuItems = DefaultToolbarItems | MenuItem.ShadowSession | MenuItem.IgnoreCredentials; 37 | #endregion 38 | 39 | internal static readonly ReadOnlyCollection MenuItemValues = Enum.GetValues(typeof(MenuItem)) 40 | .Cast() 41 | .Where(menu => menu > MenuItem.Empty && menu < MenuItem.Options).ToList().AsReadOnly(); 42 | 43 | [Flags] 44 | public enum MenuItem : byte 45 | { 46 | Empty = 0, 47 | OpenRdpConnection = 1, 48 | OpenRdpConnectionAdmin = 2, 49 | OpenRdpConnectionNoCred = 4, 50 | OpenRdpConnectionNoCredAdmin = 8, 51 | ShadowSession = 16, 52 | ShadowSessionNoCred = 32, 53 | IgnoreCredentials = 64, 54 | Options = byte.MaxValue 55 | } 56 | 57 | public static string GetText(this MenuItem menuItem) 58 | { 59 | switch (menuItem) 60 | { 61 | case MenuItem.OpenRdpConnection: 62 | return KprResourceManager.Instance["Open RDP connection"]; 63 | case MenuItem.OpenRdpConnectionAdmin: 64 | return KprResourceManager.Instance["Open RDP connection (/admin)"]; 65 | case MenuItem.OpenRdpConnectionNoCred: 66 | return KprResourceManager.Instance["Open RDP connection without credentials"]; 67 | case MenuItem.OpenRdpConnectionNoCredAdmin: 68 | return KprResourceManager.Instance["Open RDP connection without credentials (/admin)"]; 69 | case MenuItem.ShadowSession: 70 | return KprResourceManager.Instance["Shadow session over RDP connection (/shadow)"]; 71 | case MenuItem.ShadowSessionNoCred: 72 | return KprResourceManager.Instance["Shadow session over RDP connection without credentials (/shadow)"]; 73 | case MenuItem.IgnoreCredentials: 74 | return KprResourceManager.Instance["Ignore entry credentials"]; 75 | case MenuItem.Options: 76 | return KprResourceManager.Instance["KeePassRDP Options"]; 77 | default: 78 | return string.Empty; 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /KeePassRDP/KprOptionsForm_Integration.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePassRDP.Utils; 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Drawing; 25 | using System.Threading; 26 | using System.Threading.Tasks; 27 | using System.Windows.Forms; 28 | 29 | namespace KeePassRDP 30 | { 31 | public partial class KprOptionsForm 32 | { 33 | private void Init_TabIntegration() 34 | { 35 | if (!_tabIntegrationInitialized) 36 | { 37 | _tabIntegrationInitialized = true; 38 | 39 | kprSettingsControl.UseWaitCursor = true; 40 | tabIntegration.UseWaitCursor = true; 41 | tabIntegration.AutoScroll = false; 42 | tabIntegration.SuspendLayout(); 43 | tblIntegration.SuspendLayout(); 44 | kprSettingsControl.SuspendLayout(); 45 | 46 | KprOptionsForm_ResizeBegin(null, EventArgs.Empty); 47 | 48 | Task.Factory.StartNew(() => 49 | { 50 | var invoke = BeginInvoke(new Action(() => 51 | { 52 | KprResourceManager.Instance.TranslateMany( 53 | grpCredentialOptions, 54 | grpEntryOptions, 55 | grpHotkeyOptions, 56 | lblCredVaultTtl, 57 | chkCredVaultUseWindows, 58 | chkCredVaultOverwriteExisting, 59 | chkCredVaultRemoveOnExit, 60 | chkCredVaultAdaptiveTtl, 61 | chkKeePassConnectToAll, 62 | chkKeePassAlwaysConfirm, 63 | chkKeePassDefaultEntryAction, 64 | chkKeePassContextMenuOnScreen, 65 | chkKeePassHotkeysRegisterLast, 66 | chkKeePassConfirmOnClose 67 | ); 68 | 69 | if (Util.CheckCredentialGuard()) 70 | chkCredVaultUseWindows.ForeColor = Color.Gray; 71 | 72 | Config_TabIntegration(); 73 | 74 | tblIntegration.ResumeLayout(false); 75 | tabIntegration.ResumeLayout(false); 76 | tabIntegration.AutoScroll = true; 77 | tabIntegration.UseWaitCursor = false; 78 | 79 | if (!tabIntegration.Created) 80 | tabIntegration.CreateControl(); 81 | })); 82 | 83 | if (!invoke.IsCompleted) 84 | Task.Factory.FromAsync( 85 | invoke, 86 | endinvoke => EndInvoke(endinvoke), 87 | TaskCreationOptions.AttachedToParent, 88 | TaskScheduler.Default); 89 | else 90 | EndInvoke(invoke); 91 | }, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default); 92 | } 93 | else 94 | { 95 | if (tabIntegration.VerticalScroll.Visible) 96 | tabIntegration.AutoScrollPosition = Point.Empty; 97 | 98 | kprSettingsControl.Visible = true; 99 | } 100 | } 101 | 102 | private void Config_TabIntegration() 103 | { 104 | // Set form elements to match previously saved options. 105 | chkCredVaultUseWindows.Checked = _config.CredVaultUseWindows; 106 | chkCredVaultOverwriteExisting.Checked = _config.CredVaultOverwriteExisting; 107 | chkCredVaultRemoveOnExit.Checked = _config.CredVaultRemoveOnExit; 108 | chkCredVaultAdaptiveTtl.Checked = _config.CredVaultAdaptiveTtl; 109 | 110 | numCredVaultTtl.Value = Math.Max(Math.Min(_config.CredVaultTtl, numCredVaultTtl.Maximum), numCredVaultTtl.Minimum); 111 | _config.CredVaultTtl = (int)numCredVaultTtl.Value; 112 | 113 | chkKeePassConnectToAll.Checked = _config.KeePassConnectToAll; 114 | chkKeePassAlwaysConfirm.Checked = _config.KeePassAlwaysConfirm; 115 | chkKeePassDefaultEntryAction.Checked = _config.KeePassDefaultEntryAction; 116 | chkKeePassContextMenuOnScreen.Checked = _config.KeePassContextMenuOnScreen; 117 | chkKeePassHotkeysRegisterLast.Checked = _config.KeePassHotkeysRegisterLast; 118 | chkKeePassConfirmOnClose.Checked = _config.KeePassConfirmOnClose; 119 | 120 | Task.Factory.StartNew(() => 121 | { 122 | var items = new Dictionary(); 123 | 124 | foreach (var menuItem in KprMenu.MenuItemValues) 125 | { 126 | Image image = null; 127 | ToolStripItem temp = null; 128 | if (_toolbarItems.TryGetValue(menuItem, out temp)) 129 | image = temp.Image; 130 | items[menuItem] = new KprSettingsControl.MenuItemSettings 131 | { 132 | ContextMenuChecked = _config.KeePassContextMenuItems.HasFlag(menuItem), 133 | ToolbarChecked = _config.KeePassToolbarItems.HasFlag(menuItem), 134 | Hotkey = _config.GetShortcut(menuItem), 135 | Image = image 136 | }; 137 | } 138 | 139 | if (!kprSettingsControl.ControlsCreated.IsSet) 140 | if (!kprSettingsControl.ControlsCreated.Wait(TimeSpan.FromSeconds(5))) 141 | throw new TimeoutException(); 142 | 143 | Task.Factory.FromAsync(BeginInvoke(new Action(() => 144 | { 145 | kprSettingsControl.BeginUpdate(); 146 | foreach (var kv in items) 147 | kprSettingsControl[kv.Key] = kv.Value; 148 | kprSettingsControl.EndUpdate(); 149 | kprSettingsControl.ResumeLayout(false); 150 | kprSettingsControl.UseWaitCursor = false; 151 | kprSettingsControl.Visible = true; 152 | 153 | KprOptionsForm_ResizeEnd(null, EventArgs.Empty); 154 | })), endInvoke => EndInvoke(endInvoke), TaskCreationOptions.AttachedToParent, TaskScheduler.Default); 155 | }, CancellationToken.None, TaskCreationOptions.PreferFairness | TaskCreationOptions.AttachedToParent, TaskScheduler.Default); 156 | } 157 | 158 | private void numCredVaultTtl_ValueChanged(object sender, EventArgs e) 159 | { 160 | chkCredVaultAdaptiveTtl.Enabled = numCredVaultTtl.Value > 0; 161 | } 162 | 163 | private void tabIntegration_Resize(object sender, EventArgs e) 164 | { 165 | if (!_tabIntegrationInitialized || tabIntegration.UseWaitCursor) 166 | return; 167 | 168 | var minHeight = Math.Max(tabIntegration.Height, _tblIntegrationMinHeight); 169 | if (tblIntegration.MinimumSize.Height != minHeight) 170 | { 171 | tblIntegration.SuspendLayout(); 172 | tblIntegration.MinimumSize = new Size(0, minHeight); 173 | tblIntegration.ResumeLayout(true); 174 | } 175 | } 176 | } 177 | } -------------------------------------------------------------------------------- /KeePassRDP/KprPictureBox.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace KeePassRDP 2 | { 3 | partial class KprPictureBox 4 | { 5 | /// 6 | /// Erforderliche Designervariable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | #region Vom Komponenten-Designer generierter Code 11 | 12 | /// 13 | /// Erforderliche Methode für die Designerunterstützung. 14 | /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. 15 | /// 16 | private void InitializeComponent() 17 | { 18 | components = new System.ComponentModel.Container(); 19 | } 20 | 21 | #endregion 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /KeePassRDP/KprResourceManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePass; 22 | using KeePass.App.Configuration; 23 | using KeePassRDP.Utils; 24 | using System; 25 | using System.Collections.Concurrent; 26 | using System.Globalization; 27 | using System.IO; 28 | using System.Resources; 29 | using System.Threading; 30 | using System.Windows.Forms; 31 | 32 | namespace KeePassRDP 33 | { 34 | internal interface IKprResourceManager 35 | { 36 | string this[string key] { get; } 37 | void Translate(Control control); 38 | void TranslateMany(params Control[] controls); 39 | void Translate(ToolStripItem item); 40 | void TranslateMany(params ToolStripItem[] items); 41 | void ClearCache(); 42 | } 43 | 44 | internal class KprResourceManager : IKprResourceManager, IDisposable 45 | { 46 | private static readonly Lazy _instance = new Lazy(() => 47 | { 48 | try 49 | { 50 | Resources.Resources.Culture = CultureInfo.CreateSpecificCulture(Program.Translation.Properties.Iso6391Code); 51 | } 52 | catch 53 | { 54 | Resources.Resources.Culture = CultureInfo.CreateSpecificCulture("en"); 55 | } 56 | 57 | return new KprResourceManager(); 58 | }, LazyThreadSafetyMode.ExecutionAndPublication); 59 | 60 | private class EmptyKprResourceManager : IKprResourceManager 61 | { 62 | public string this[string key] 63 | { 64 | get 65 | { 66 | return key; 67 | } 68 | } 69 | 70 | public void ClearCache() 71 | { 72 | } 73 | 74 | public void Translate(Control control) 75 | { 76 | } 77 | 78 | public void Translate(ToolStripItem item) 79 | { 80 | } 81 | 82 | public void TranslateMany(params Control[] controls) 83 | { 84 | } 85 | 86 | public void TranslateMany(params ToolStripItem[] items) 87 | { 88 | } 89 | } 90 | 91 | private static readonly EmptyKprResourceManager _emptyInstance = new EmptyKprResourceManager(); 92 | 93 | public static IKprResourceManager Instance { get { return !KeePassRDPExt.Initialized.IsSet ? _emptyInstance : _instance.Value; } } 94 | 95 | private readonly ConcurrentDictionary _cache; 96 | private readonly Lazy _fileBasedResourceManager; 97 | 98 | public string this[string key] 99 | { 100 | get 101 | { 102 | if (!KeePassRDPExt.Initialized.IsSet) 103 | return key; 104 | 105 | return _cache.GetOrAdd(key, k => 106 | { 107 | string text = null; 108 | try 109 | { 110 | text = _fileBasedResourceManager.Value != null ? _fileBasedResourceManager.Value.GetString(k, Resources.Resources.Culture) : null; 111 | } 112 | catch 113 | { 114 | } 115 | return text ?? 116 | Resources.Resources.ResourceManager.GetString(k, Resources.Resources.Culture) ?? 117 | null; 118 | }) ?? key; 119 | } 120 | } 121 | 122 | private KprResourceManager() 123 | { 124 | _cache = new ConcurrentDictionary(4, 0, StringComparer.OrdinalIgnoreCase); 125 | _fileBasedResourceManager = new Lazy(() => 126 | Resources.Resources.Culture != null && 127 | File.Exists(Path.Combine(AppConfigSerializer.AppDataDirectory, string.Format("{0}.{1}.resources", Util.KeePassRDP, Resources.Resources.Culture.Name))) ? 128 | ResourceManager.CreateFileBasedResourceManager( 129 | Util.KeePassRDP, 130 | AppConfigSerializer.AppDataDirectory, 131 | null) : 132 | null, 133 | LazyThreadSafetyMode.ExecutionAndPublication); 134 | } 135 | 136 | public void Translate(Control control) 137 | { 138 | control.SuspendLayout(); 139 | control.Text = this[control.Text]; 140 | control.ResumeLayout(false); 141 | } 142 | 143 | public void TranslateMany(params Control[] controls) 144 | { 145 | foreach (var control in controls) 146 | Translate(control); 147 | } 148 | 149 | public void Translate(ToolStripItem item) 150 | { 151 | item.Text = this[item.Text]; 152 | } 153 | 154 | public void TranslateMany(params ToolStripItem[] items) 155 | { 156 | foreach (var item in items) 157 | Translate(item); 158 | } 159 | 160 | public void ClearCache() 161 | { 162 | _cache.Clear(); 163 | } 164 | 165 | public void Dispose() 166 | { 167 | ClearCache(); 168 | Resources.Resources.ResourceManager.ReleaseAllResources(); 169 | if (_fileBasedResourceManager.IsValueCreated && _fileBasedResourceManager.Value != null) 170 | _fileBasedResourceManager.Value.ReleaseAllResources(); 171 | } 172 | } 173 | } -------------------------------------------------------------------------------- /KeePassRDP/KprSecureBackgroundForm.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using KeePass; 22 | using System; 23 | using System.ComponentModel; 24 | using System.Drawing; 25 | using System.Drawing.Drawing2D; 26 | using System.Windows.Forms; 27 | 28 | namespace KeePassRDP 29 | { 30 | internal class KprSecureBackgroundForm : Form 31 | { 32 | protected override CreateParams CreateParams 33 | { 34 | get 35 | { 36 | var cp = base.CreateParams; 37 | 38 | cp.ExStyle |= NativeMethods.WS_EX_TOOLWINDOW | NativeMethods.WS_EX_NOINHERITLAYOUT | NativeMethods.WS_EX_NOPARENTNOTIFY; 39 | cp.ExStyle &= ~NativeMethods.WS_EX_APPWINDOW; 40 | 41 | cp.ClassStyle |= NativeMethods.CS_PARENTDC; 42 | 43 | return cp; 44 | } 45 | } 46 | 47 | protected override bool ShowWithoutActivation 48 | { 49 | get 50 | { 51 | return true; 52 | } 53 | } 54 | 55 | private readonly bool _isPrimary; 56 | 57 | public KprSecureBackgroundForm(Bitmap bmpBackground) : this(bmpBackground, Screen.PrimaryScreen) 58 | { } 59 | 60 | public KprSecureBackgroundForm(Bitmap bmpBackground, Screen sc) 61 | { 62 | var screen = sc ?? Screen.PrimaryScreen; 63 | _isPrimary = screen.Primary; 64 | TopLevel = true; 65 | ControlBox = false; 66 | MinimizeBox = false; 67 | MaximizeBox = false; 68 | ShowIcon = false; 69 | ShowInTaskbar = false; 70 | FormBorderStyle = FormBorderStyle.None; 71 | StartPosition = FormStartPosition.Manual; 72 | Location = screen.Bounds.Location; 73 | Size = screen.Bounds.Size; 74 | DoubleBuffered = true; 75 | BackColor = Color.Black; 76 | BackgroundImageLayout = ImageLayout.None; 77 | if (bmpBackground != null) 78 | BackgroundImage = bmpBackground; 79 | } 80 | 81 | protected override void OnPaint(PaintEventArgs e) 82 | { } 83 | 84 | protected override void OnPaintBackground(PaintEventArgs e) 85 | { 86 | var bgImage = BackgroundImage; 87 | if (bgImage != null) 88 | { 89 | var rect = e.ClipRectangle; 90 | e.Graphics.DrawImage(bgImage, rect, 0, 0, rect.Width, rect.Height, GraphicsUnit.Pixel); 91 | return; 92 | } 93 | 94 | if (_isPrimary) 95 | { 96 | var state = e.Graphics.Save(); 97 | 98 | e.Graphics.SmoothingMode = SmoothingMode.None; 99 | e.Graphics.PixelOffsetMode = PixelOffsetMode.None; 100 | e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor; 101 | e.Graphics.CompositingQuality = CompositingQuality.HighSpeed; 102 | 103 | var s = Screen.FromControl(this); 104 | var bounds = s.Bounds; 105 | using (var b = new Bitmap(bounds.Width + bounds.Left, bounds.Height + bounds.Top, e.Graphics)) 106 | { 107 | using (var g = Graphics.FromImage(b)) 108 | { 109 | g.SetClip(bounds, CombineMode.Replace); 110 | 111 | /*g.SmoothingMode = SmoothingMode.None; 112 | g.PixelOffsetMode = PixelOffsetMode.None; 113 | g.InterpolationMode = InterpolationMode.NearestNeighbor; 114 | g.CompositingQuality = CompositingQuality.HighQuality;*/ 115 | 116 | var h = g.GetHdc(); 117 | if (Program.MainForm.InvokeRequired) 118 | Program.MainForm.Invoke(new Action(() => NativeMethods.PaintDesktop(h))); 119 | else 120 | NativeMethods.PaintDesktop(h); 121 | g.ReleaseHdc(h); 122 | 123 | using (var brush = new SolidBrush(Color.FromArgb(192, Color.Black))) 124 | g.FillRectangle(brush, e.ClipRectangle); 125 | } 126 | 127 | e.Graphics.DrawImage(b, -bounds.Left, -bounds.Top); 128 | } 129 | 130 | e.Graphics.Restore(state); 131 | } 132 | } 133 | 134 | protected override void OnFormClosing(FormClosingEventArgs e) 135 | { 136 | if (Visible && e.CloseReason == CloseReason.UserClosing) 137 | e.Cancel = true; 138 | 139 | base.OnFormClosing(e); 140 | } 141 | 142 | protected override void Dispose(bool disposing) 143 | { 144 | if (disposing) 145 | { 146 | if (BackgroundImage != null) 147 | { 148 | BackgroundImage.Dispose(); 149 | BackgroundImage = null; 150 | } 151 | } 152 | 153 | base.Dispose(disposing); 154 | } 155 | 156 | public new void Hide() 157 | { 158 | base.Hide(); 159 | 160 | DestroyHandle(); 161 | if (Container != null) 162 | Container.Remove(this); 163 | } 164 | 165 | public new void BringToFront() 166 | { 167 | NativeMethods.SetWindowPos(Handle, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOREDRAW | NativeMethods.SWP_NOACTIVATE); 168 | Application.DoEvents(); 169 | } 170 | 171 | public new void SendToBack() 172 | { 173 | NativeMethods.SetWindowPos(Handle, NativeMethods.HWND_BOTTOM, 0, 0, 0, 0, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOREDRAW | NativeMethods.SWP_NOACTIVATE); 174 | Application.DoEvents(); 175 | } 176 | 177 | public new object Invoke(Delegate method) 178 | { 179 | return Invoke(method, null); 180 | } 181 | 182 | public new object Invoke(Delegate method, params object[] args) 183 | { 184 | return Program.MainForm.InvokeRequired ? Program.MainForm.Invoke(method, args) : base.Invoke(method, args); 185 | } 186 | 187 | [EditorBrowsable(EditorBrowsableState.Advanced)] 188 | public new IAsyncResult BeginInvoke(Delegate method) 189 | { 190 | return BeginInvoke(method, null); 191 | } 192 | 193 | [EditorBrowsable(EditorBrowsableState.Advanced)] 194 | public new IAsyncResult BeginInvoke(Delegate method, params object[] args) 195 | { 196 | return Program.MainForm.InvokeRequired ? Program.MainForm.BeginInvoke(method, args) : base.BeginInvoke(method, args); 197 | } 198 | 199 | [EditorBrowsable(EditorBrowsableState.Advanced)] 200 | public new object EndInvoke(IAsyncResult asyncResult) 201 | { 202 | return Program.MainForm.InvokeRequired ? Program.MainForm.EndInvoke(asyncResult) : base.EndInvoke(asyncResult); 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /KeePassRDP/KprSecureDesktopToolBar.Designer.cs: -------------------------------------------------------------------------------- 1 | using KeePass.UI; 2 | 3 | namespace KeePassRDP 4 | { 5 | partial class KprSecureDesktopToolBar 6 | { 7 | /// 8 | /// Required designer variable. 9 | /// 10 | private System.ComponentModel.IContainer components = null; 11 | 12 | #region Windows Form Designer generated code 13 | 14 | /// 15 | /// Required method for Designer support - do not modify 16 | /// the contents of this method with the code editor. 17 | /// 18 | private void InitializeComponent() 19 | { 20 | this.components = new System.ComponentModel.Container(); 21 | this.kprImageList = new KeePassRDP.KprImageList(this.components); 22 | this.imageList1 = ((System.Windows.Forms.ImageList)(this.kprImageList)); 23 | this.toolStrip1 = new KeePass.UI.CustomToolStripEx(); 24 | this.toolStripLabel1 = new System.Windows.Forms.ToolStripTextBox(); 25 | this.toolStripButton1 = new System.Windows.Forms.ToolStripButton(); 26 | this.toolTip1 = new KeePassRDP.KprToolTip(this.components); 27 | this.toolStrip1.SuspendLayout(); 28 | this.SuspendLayout(); 29 | // 30 | // toolStrip1 31 | // 32 | this.toolStrip1.Dock = System.Windows.Forms.DockStyle.Fill; 33 | this.toolStrip1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 34 | this.toolStrip1.GripMargin = new System.Windows.Forms.Padding(0); 35 | this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; 36 | this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 37 | this.toolStripLabel1, 38 | this.toolStripButton1}); 39 | this.toolStrip1.Location = new System.Drawing.Point(0, 0); 40 | this.toolStrip1.Name = "toolStrip1"; 41 | this.toolStrip1.Padding = new System.Windows.Forms.Padding(0); 42 | this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional; 43 | this.toolStrip1.ShowItemToolTips = false; 44 | this.toolStrip1.Size = new System.Drawing.Size(300, 25); 45 | this.toolStrip1.TabIndex = 0; 46 | this.toolStrip1.Text = "toolStrip1"; 47 | // 48 | // toolStripLabel1 49 | // 50 | this.toolStripLabel1.BackColor = System.Drawing.SystemColors.Control; 51 | this.toolStripLabel1.BorderStyle = System.Windows.Forms.BorderStyle.None; 52 | this.toolStripLabel1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 53 | this.toolStripLabel1.ForeColor = System.Drawing.Color.Silver; 54 | this.toolStripLabel1.Margin = new System.Windows.Forms.Padding(0, 0, 4, 0); 55 | this.toolStripLabel1.Name = "toolStripLabel1"; 56 | this.toolStripLabel1.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; 57 | this.toolStripLabel1.ReadOnly = true; 58 | this.toolStripLabel1.ShortcutsEnabled = false; 59 | this.toolStripLabel1.Size = new System.Drawing.Size(72, 25); 60 | this.toolStripLabel1.Text = "KeePassRDP"; 61 | this.toolStripLabel1.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Right; 62 | // 63 | // toolStripButton1 64 | // 65 | this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 66 | this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta; 67 | this.toolStripButton1.Margin = new System.Windows.Forms.Padding(1, 1, 0, 2); 68 | this.toolStripButton1.Name = "toolStripButton1"; 69 | this.toolStripButton1.Size = new System.Drawing.Size(23, 22); 70 | this.toolStripButton1.Click += new System.EventHandler(this.toolStripButton1_Click); 71 | this.toolStripButton1.MouseEnter += new System.EventHandler(this.ToolStripItem_MouseEnter); 72 | this.toolStripButton1.MouseLeave += new System.EventHandler(this.ToolStripItem_MouseLeave); 73 | // 74 | // toolTip1 75 | // 76 | this.toolTip1.Active = false; 77 | this.toolTip1.UseAnimation = false; 78 | this.toolTip1.UseFading = false; 79 | // 80 | // KprSecureDesktopToolBar 81 | // 82 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 83 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 84 | this.AutoSize = true; 85 | this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 86 | this.ClientSize = new System.Drawing.Size(300, 25); 87 | this.ControlBox = false; 88 | this.Controls.Add(this.toolStrip1); 89 | this.DoubleBuffered = true; 90 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 91 | this.MaximizeBox = false; 92 | this.MinimizeBox = false; 93 | this.Name = "KprSecureDesktopToolBar"; 94 | this.Opacity = 0.5D; 95 | this.ShowIcon = false; 96 | this.ShowInTaskbar = false; 97 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 98 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 99 | this.TopMost = true; 100 | this.Activated += new System.EventHandler(this.KprSecureDesktopToolBar_Activated); 101 | this.Deactivate += new System.EventHandler(this.KprSecureDesktopToolBar_Deactivate); 102 | this.Load += new System.EventHandler(this.KprSecureDesktopToolBar_Load); 103 | this.Shown += new System.EventHandler(this.KprSecureDesktopToolBar_Shown); 104 | this.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.KprSecureDesktopToolBar_PreviewKeyDown); 105 | this.toolStrip1.ResumeLayout(false); 106 | this.toolStrip1.PerformLayout(); 107 | this.ResumeLayout(false); 108 | this.PerformLayout(); 109 | 110 | } 111 | 112 | #endregion 113 | 114 | private CustomToolStripEx toolStrip1; 115 | private System.Windows.Forms.ToolStripButton toolStripButton1; 116 | private System.Windows.Forms.ToolStripTextBox toolStripLabel1; 117 | private System.Windows.Forms.ImageList imageList1; 118 | private KprImageList kprImageList; 119 | private KprToolTip toolTip1; 120 | } 121 | } -------------------------------------------------------------------------------- /KeePassRDP/KprSecureDesktopToolBar.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 128, 17 122 | 123 | 124 | 250, 17 125 | 126 | 127 | 355, 17 128 | 129 | -------------------------------------------------------------------------------- /KeePassRDP/KprSessionListForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 128, 17 122 | 123 | 124 | 405, 17 125 | 126 | 127 | 405, 17 128 | 129 | 130 | 250, 17 131 | 132 | -------------------------------------------------------------------------------- /KeePassRDP/KprSettingsControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | False 122 | 123 | 124 | 250, 17 125 | 126 | 127 | 128, 17 128 | 129 | 130 | False 131 | 132 | -------------------------------------------------------------------------------- /KeePassRDP/KprToolStripDropDownButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System.Drawing; 22 | using System.Reflection; 23 | using System.Windows.Forms; 24 | 25 | namespace KeePassRDP 26 | { 27 | [ToolboxBitmap(typeof(ToolStripDropDown))] 28 | public class KprToolStripDropDownButton : ToolStripDropDownButton 29 | { 30 | /*public bool ClickThrough { get; set; } 31 | 32 | private const uint MA_ACTIVATE = 1; 33 | private const uint MA_ACTIVATEANDEAT = 2; 34 | 35 | protected override void WndProc(ref Message m) 36 | { 37 | base.WndProc(ref m); 38 | if (ClickThrough && m.Msg == NativeMethods.WM_MOUSEACTIVATE && m.Result == (IntPtr)MA_ACTIVATEANDEAT) 39 | m.Result = (IntPtr)MA_ACTIVATE; 40 | }*/ 41 | 42 | protected override Point DropDownLocation 43 | { 44 | get 45 | { 46 | if (Parent == null || !HasDropDownItems) 47 | { 48 | return Point.Empty; 49 | } 50 | 51 | return GetDropDownBounds(DropDownDirection).Location; 52 | } 53 | } 54 | 55 | private static readonly MethodInfo TranslatePoint = typeof(ToolStripItem).GetMethod("TranslatePoint", BindingFlags.Instance | BindingFlags.NonPublic); 56 | 57 | private Rectangle GetDropDownBounds(ToolStripDropDownDirection dropDownDirection) 58 | { 59 | var dropDownBounds = DropDownDirectionToDropDownBounds(dropDownDirection, new Rectangle(Point.Empty, DropDown.AutoSize ? DropDown.GetPreferredSize(Size.Empty) : DropDown.Size)); 60 | var b = new Rectangle((Point)TranslatePoint.Invoke(this, new object[] { Point.Empty, ToolStripPointType.ToolStripItemCoords, ToolStripPointType.ScreenCoords }), Size); 61 | if (Rectangle.Intersect(dropDownBounds, b).Height > 1) 62 | { 63 | var flag = RightToLeft == RightToLeft.Yes; 64 | if (Rectangle.Intersect(dropDownBounds, b).Width > 1) 65 | { 66 | dropDownBounds = DropDownDirectionToDropDownBounds((!flag) ? ToolStripDropDownDirection.Right : ToolStripDropDownDirection.Left, dropDownBounds); 67 | } 68 | 69 | if (Rectangle.Intersect(dropDownBounds, b).Width > 1) 70 | { 71 | dropDownBounds = DropDownDirectionToDropDownBounds((!flag) ? ToolStripDropDownDirection.Left : ToolStripDropDownDirection.Right, dropDownBounds); 72 | } 73 | } 74 | 75 | return dropDownBounds; 76 | } 77 | 78 | private Rectangle DropDownDirectionToDropDownBounds(ToolStripDropDownDirection dropDownDirection, Rectangle dropDownBounds) 79 | { 80 | var empty = Point.Empty; 81 | switch (dropDownDirection) 82 | { 83 | case ToolStripDropDownDirection.AboveLeft: 84 | empty.X = -dropDownBounds.Width + Width; 85 | empty.Y = -dropDownBounds.Height + 1; 86 | break; 87 | case ToolStripDropDownDirection.AboveRight: 88 | empty.Y = -dropDownBounds.Height + 1; 89 | break; 90 | case ToolStripDropDownDirection.BelowRight: 91 | empty.Y = Height - 1; 92 | break; 93 | case ToolStripDropDownDirection.BelowLeft: 94 | empty.X = -dropDownBounds.Width + Width; 95 | empty.Y = Height - 1; 96 | break; 97 | case ToolStripDropDownDirection.Right: 98 | empty.X = Width; 99 | if (!IsOnDropDown) 100 | { 101 | empty.X--; 102 | } 103 | 104 | break; 105 | case ToolStripDropDownDirection.Left: 106 | empty.X = -dropDownBounds.Width; 107 | break; 108 | } 109 | var point = (Point)TranslatePoint.Invoke(this, new object[] { Point.Empty, ToolStripPointType.ToolStripItemCoords, ToolStripPointType.ScreenCoords }); 110 | dropDownBounds.Location = new Point(point.X + empty.X, point.Y + empty.Y); 111 | //dropDownBounds = WindowsFormsUtils.ConstrainToScreenWorkingAreaBounds(dropDownBounds); 112 | return dropDownBounds; 113 | } 114 | 115 | internal enum ToolStripPointType 116 | { 117 | ToolStripCoords, 118 | ScreenCoords, 119 | ToolStripItemCoords 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /KeePassRDP/KprToolTip.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System.ComponentModel; 22 | using System.Drawing; 23 | using System.Windows.Forms; 24 | 25 | namespace KeePassRDP 26 | { 27 | [ToolboxBitmap(typeof(ToolTip))] 28 | internal class KprToolTip : ToolTip 29 | { 30 | new public string ToolTipTitle 31 | { 32 | get 33 | { 34 | return base.ToolTipTitle; 35 | } 36 | set 37 | { 38 | base.ToolTipTitle = KprResourceManager.Instance[value]; 39 | } 40 | } 41 | 42 | public KprToolTip(IContainer container) : base(container) 43 | { 44 | } 45 | 46 | public KprToolTip() : base() 47 | { 48 | } 49 | 50 | new public void SetToolTip(Control control, string caption) 51 | { 52 | base.SetToolTip(control, KprResourceManager.Instance[caption]); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /KeePassRDP/KprVersion.tt: -------------------------------------------------------------------------------- 1 | <#@ template compilerOptions="optimize+" hostspecific="true" language="C#" #> 2 | <#@ output extension=".cs" #> 3 | <#@ assembly name="EnvDTE" #> 4 | <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="System.IO.Compression" #> 7 | <#@ import namespace="System.Security.Cryptography" #> 8 | <#@ import namespace="System.Text" #> 9 | <#@ import namespace="System.Text.RegularExpressions" #> 10 | <# 11 | var directory = Path.GetDirectoryName(Host.TemplateFile); 12 | var className = Path.GetFileNameWithoutExtension(Host.TemplateFile); 13 | var namespaceString = Path.GetFileNameWithoutExtension(directory); 14 | var parent = Directory.GetParent(directory).FullName; 15 | 16 | var buildDate = DateTime.UtcNow; 17 | var informationalVersion = string.Empty; 18 | var assemblyVersion = string.Empty; 19 | var copyright = string.Empty; 20 | 21 | var assemblyInfo = File.ReadAllText(Path.Combine(directory, @"Properties\AssemblyInfo.cs")); 22 | var match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyInformationalVersion\\(\"([^\"]+)\"\\)\\]"); 23 | if (match.Success) 24 | informationalVersion = match.Groups[1].Value; 25 | 26 | match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyVersion\\(\"([^\"]+)\"\\)\\]"); 27 | if (match.Success) 28 | { 29 | assemblyVersion = match.Groups[1].Value; 30 | if (string.IsNullOrEmpty(informationalVersion)) 31 | informationalVersion = assemblyVersion; 32 | } 33 | 34 | /* 35 | // Build time. 36 | var configName = Host.ResolveParameterValue("-", "-", "Configuration"); 37 | if (string.IsNullOrWhiteSpace(configName)) 38 | { 39 | try 40 | { 41 | // Design time. 42 | var serviceProvider = (IServiceProvider)Host; 43 | var dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE)); 44 | configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name; 45 | } 46 | catch (Exception ex) 47 | { 48 | configName = ex.Message; 49 | } 50 | } 51 | 52 | if (configName == "Debug") 53 | informationalVersion = informationalVersion + ".debug"; 54 | */ 55 | 56 | match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyCopyright\\(\"([^\"]+)\"\\)\\]"); 57 | if (match.Success) 58 | copyright += match.Groups[1].Value; 59 | 60 | /*match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyCompany\\(\"([^\"]+)\"\\)\\]"); 61 | if (match.Success) 62 | copyright += (!string.IsNullOrEmpty(copyright) ? " " : "") + match.Groups[1].Value;*/ 63 | 64 | var pubKey = string.Empty; 65 | using (var rsa = new RSACryptoServiceProvider(4096) 66 | { 67 | PersistKeyInCsp = false 68 | }) 69 | { 70 | var versionFile = Path.Combine(parent, "KeePassRDP.ver"); 71 | 72 | var pubKeyFile = versionFile + ".public"; 73 | if (!File.Exists(pubKeyFile)) 74 | File.WriteAllText(pubKeyFile, pubKey = rsa.ToXmlString(false)); 75 | else 76 | pubKey = File.ReadAllText(pubKeyFile); 77 | 78 | var privKeyFile = versionFile + ".private"; 79 | if (File.Exists(privKeyFile)) 80 | { 81 | rsa.FromXmlString(File.ReadAllText(privKeyFile)); 82 | rsa.PersistKeyInCsp = false; 83 | } 84 | else 85 | File.WriteAllText(privKeyFile, rsa.ToXmlString(true)); 86 | 87 | if (!File.Exists(versionFile) || !File.Exists(versionFile + ".gz") || File.ReadAllLines(versionFile)[1].Split(':')[1] != assemblyVersion) 88 | { 89 | var versionInfo = string.Format(@": 90 | KeePassRDP:{0} 91 | :", assemblyVersion); 92 | 93 | File.WriteAllText(versionFile, versionInfo, Encoding.UTF8); 94 | 95 | using (var sha512 = SHA512.Create()) 96 | { 97 | var signed = Convert.ToBase64String(rsa.SignData(Encoding.UTF8.GetBytes(versionInfo.Replace("\r\n", "\n")), sha512)); 98 | using (var compressedFileStream = File.Create(versionFile + ".gz")) 99 | using (var compressor = new GZipStream(compressedFileStream, CompressionMode.Compress)) 100 | { 101 | var buffer = Encoding.UTF8.GetBytes(signed + Environment.NewLine + versionInfo); 102 | compressor.Write(buffer, 0, buffer.Length); 103 | } 104 | } 105 | } 106 | } 107 | #> 108 | /* 109 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 110 | * 111 | * This file is part of KeePassRDP. 112 | * 113 | * KeePassRDP is free software: you can redistribute it and/or modify 114 | * it under the terms of the GNU General Public License as published by 115 | * the Free Software Foundation, either version 3 of the License, or 116 | * (at your option) any later version. 117 | * 118 | * KeePassRDP is distributed in the hope that it will be useful, 119 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 120 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 121 | * GNU General Public License for more details. 122 | * 123 | * You should have received a copy of the GNU General Public License 124 | * along with KeePassRDP. If not, see . 125 | * 126 | */ 127 | 128 | namespace <#= namespaceString #>.Resources 129 | { 130 | public static class <#= className #> 131 | { 132 | public const string Copyright = "<#= copyright #>"; 133 | 134 | public const string Revision = "r<#= buildDate.ToString("yyyyMMddHHmmss").Substring(2, "yyyyMMddHHmmss".Length - 3) #>0"; 135 | 136 | public const string Version = 137 | #if DEBUG 138 | "v<#= informationalVersion #>.debug"; 139 | #else 140 | "v<#= informationalVersion #>"; 141 | #endif 142 | 143 | internal const string FileSigKey = "<#= pubKey #>"; 144 | } 145 | } -------------------------------------------------------------------------------- /KeePassRDP/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System.Reflection; 22 | using System.Resources; 23 | using System.Runtime.InteropServices; 24 | 25 | // General Information 26 | [assembly: AssemblyTitle("KeePassRDP")] 27 | [assembly: AssemblyDescription("A plugin for KeePass to conveniently connect to RDP.")] 28 | [assembly: AssemblyConfiguration("")] 29 | [assembly: AssemblyCompany("iSnackyCracky")] 30 | [assembly: AssemblyProduct("KeePass Plugin")] 31 | [assembly: AssemblyCopyright("Copyright © 2018 - 2025")] 32 | [assembly: AssemblyTrademark("")] 33 | [assembly: AssemblyCulture("")] 34 | 35 | [assembly: ComVisible(false)] 36 | [assembly: Guid("404935cb-8f30-4801-a3e6-6a88ad963544")] 37 | 38 | [assembly: SatelliteContractVersion("1.0.0.0")] 39 | 40 | // Version information 41 | [assembly: AssemblyVersion("2.3")] 42 | [assembly: AssemblyFileVersion("2.3")] 43 | [assembly: AssemblyInformationalVersion("2.3")] -------------------------------------------------------------------------------- /KeePassRDP/ReadOnlySet.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | using System.Collections; 23 | using System.Collections.Generic; 24 | 25 | namespace KeePassRDP 26 | { 27 | /// 28 | /// Represents which doesn't allow for items addition. 29 | /// 30 | /// 31 | /// Type of items in the set. 32 | /// 33 | public interface IReadOnlySet : ICollection, ISet 34 | { 35 | } 36 | 37 | /// 38 | /// Wrapper for an which allows lookup only. 39 | /// 40 | /// 41 | /// Type of items in the set. 42 | /// 43 | public class ReadOnlySet : IReadOnlySet 44 | { 45 | /// 46 | public int Count { get { return _set.Count; } } 47 | 48 | /// 49 | public bool IsReadOnly { get { return true; } } 50 | 51 | private readonly ISet _set; 52 | 53 | /// 54 | /// Creates new wrapper instance for given . 55 | /// 56 | public ReadOnlySet(ISet set) 57 | { 58 | _set = set; 59 | } 60 | 61 | /// 62 | public bool Contains(T i) 63 | { 64 | return _set.Contains(i); 65 | } 66 | 67 | /// 68 | public IEnumerator GetEnumerator() 69 | { 70 | return _set.GetEnumerator(); 71 | } 72 | 73 | /// 74 | IEnumerator IEnumerable.GetEnumerator() 75 | { 76 | return GetEnumerator(); 77 | } 78 | 79 | public void Add(T item) 80 | { 81 | throw new NotImplementedException(); 82 | } 83 | 84 | public void Clear() 85 | { 86 | throw new NotImplementedException(); 87 | } 88 | 89 | /// 90 | public void CopyTo(T[] array, int arrayIndex) 91 | { 92 | _set.CopyTo(array, arrayIndex); 93 | } 94 | 95 | public bool Remove(T item) 96 | { 97 | throw new NotImplementedException(); 98 | } 99 | 100 | bool ISet.Add(T item) 101 | { 102 | throw new NotImplementedException(); 103 | } 104 | 105 | public void UnionWith(IEnumerable other) 106 | { 107 | throw new NotImplementedException(); 108 | } 109 | 110 | public void IntersectWith(IEnumerable other) 111 | { 112 | throw new NotImplementedException(); 113 | } 114 | 115 | public void ExceptWith(IEnumerable other) 116 | { 117 | throw new NotImplementedException(); 118 | } 119 | 120 | public void SymmetricExceptWith(IEnumerable other) 121 | { 122 | throw new NotImplementedException(); 123 | } 124 | 125 | /// 126 | public bool IsSubsetOf(IEnumerable other) 127 | { 128 | return _set.IsSubsetOf(other); 129 | } 130 | 131 | /// 132 | public bool IsSupersetOf(IEnumerable other) 133 | { 134 | return _set.IsSupersetOf(other); 135 | } 136 | 137 | /// 138 | public bool IsProperSupersetOf(IEnumerable other) 139 | { 140 | return _set.IsProperSupersetOf(other); 141 | } 142 | 143 | /// 144 | public bool IsProperSubsetOf(IEnumerable other) 145 | { 146 | return _set.IsProperSubsetOf(other); 147 | } 148 | 149 | /// 150 | public bool Overlaps(IEnumerable other) 151 | { 152 | return _set.Overlaps(other); 153 | } 154 | 155 | /// 156 | public bool SetEquals(IEnumerable other) 157 | { 158 | return _set.SetEquals(other); 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /KeePassRDPResources/KeePassRDPResources.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8286969C-231B-4E96-98AC-E95E13B09DF0} 8 | Library 9 | Properties 10 | KeePassRDP.Resources 11 | KeePassRDP.resources 12 | en-US 13 | v4.0 14 | 512 15 | 5 16 | 3.5 17 | 18 | true 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | true 39 | 40 | 41 | KeePassRDPResources.snk 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | True 58 | True 59 | Resources.resx 60 | 61 | 62 | 63 | 64 | PublicResXFileCodeGenerator 65 | 69 | Designer 70 | Resources.Designer.cs 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | "$(SolutionDir)KeePassRDPResourcesWriter\bin\$(ConfigurationName)\KeePassRDPResourcesWriter.exe" "\"$(ProjectDir)\"" 110 | 111 | -------------------------------------------------------------------------------- /KeePassRDPResources/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: InternalsVisibleTo("KeePassRDP, PublicKey=002400000480000094000000060200000024000052534131000400000100010089cafd7bbfe3c66355abb52933913d2f4bfb6badad56d0bab96b7abe1f6b483c5fa8c966e56d366f10186945ed44784343e5162e1e5cf00af6fabac3cdc4b9606f8e71447f05bc97a775b9595f7d58f08d3d5a2d0fc5510f331050bb167cc86654b0d2bc07789ff52b98efeb491ce8656389fcac21986fa31d0ef461c6d485ad")] 6 | 7 | // General Information 8 | [assembly: AssemblyTitle("KeePassRDPResources")] 9 | [assembly: AssemblyDescription("Resources for KeePassRDP.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("KeePassRDP")] 12 | [assembly: AssemblyProduct("KeePassRDP Resources")] 13 | [assembly: AssemblyCopyright("Copyright © 2025")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | [assembly: ComVisible(false)] 18 | [assembly: Guid("8286969c-231b-4e96-98ac-e95e13b09df0")] 19 | 20 | // Version information 21 | [assembly: AssemblyVersion("1.0")] 22 | [assembly: AssemblyFileVersion("1.0")] 23 | [assembly: AssemblyInformationalVersion("1.0")] 24 | -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Add.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Cancel.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Certificate.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Checkmark.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Disconnect.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Expander.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Expander.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/FileDestination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/FileDestination.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/KeyVault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/KeyVault.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/ListMembers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/ListMembers.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/LoginScreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/LoginScreen.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/ModalPopup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/ModalPopup.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/OpenFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/OpenFile.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/PowerShellProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/PowerShellProject.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Refresh.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/RemoteDesktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/RemoteDesktop.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/Remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/Remove.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/StatusHelpOutline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/StatusHelpOutline.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/SwitchSourceOrTarget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/SwitchSourceOrTarget.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/User.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/User.png -------------------------------------------------------------------------------- /KeePassRDPResources/Resources/UserFeedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPResources/Resources/UserFeedback.png -------------------------------------------------------------------------------- /KeePassRDPResourcesWriter/KeePassRDPResourcesWriter.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F4890E0E-3F01-4B34-87FB-A260A324B7C3} 8 | Exe 9 | Properties 10 | KeePassRDP.ResourcesWriter 11 | KeePassRDPResourcesWriter 12 | en-US 13 | v4.0 14 | 512 15 | 5 16 | 3.5 17 | 18 | true 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /KeePassRDPResourcesWriter/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | using System; 22 | using System.Drawing; 23 | using System.IO; 24 | using System.Linq; 25 | using System.Resources; 26 | using System.Windows.Forms; 27 | 28 | namespace KeePassRDP.ResourcesWriter 29 | { 30 | internal class Program 31 | { 32 | static void Main(string[] args) 33 | { 34 | var path = args.Length > 0 ? args[0].Trim('"') : string.Empty; 35 | 36 | if (string.IsNullOrWhiteSpace(path)) 37 | path = Environment.CurrentDirectory; 38 | 39 | using (var imageList = new ImageList 40 | { 41 | ColorDepth = ColorDepth.Depth32Bit, 42 | ImageSize = SystemInformation.SmallIconSize, 43 | TransparentColor = Color.Transparent 44 | }) 45 | { 46 | foreach (var fi in new DirectoryInfo(Path.Combine(path, "Resources")).EnumerateFiles("*.png")) 47 | { 48 | if (!fi.Exists) 49 | continue; 50 | imageList.Images.Add( 51 | Path.GetFileNameWithoutExtension(fi.Name), 52 | Image.FromFile(fi.FullName)); 53 | } 54 | 55 | if (imageList.Images.Keys.Count > 0) 56 | Console.WriteLine("KeePassRDPResources -> " + string.Join(", ", imageList.Images.Keys.Cast())); 57 | 58 | using (var writer = new ResXResourceWriter(Path.Combine(path, "Resources.resx"), type => 59 | { 60 | return type.ToString(); 61 | })) 62 | { 63 | writer.AddResource(new ResXDataNode("imageList1.ImageStream", imageList.ImageStream, type => 64 | { 65 | return type.ToString(); 66 | })); 67 | writer.AddResource(new ResXDataNode("imageList1.ImageKeys", imageList.Images.Keys.Cast().ToArray(), type => 68 | { 69 | return type.ToString(); 70 | })); 71 | writer.Generate(); 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /KeePassRDPResourcesWriter/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information 5 | [assembly: AssemblyTitle("KeePassRDPResourcesWriter")] 6 | [assembly: AssemblyDescription("Prepares resources for KeePassRDP.")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("KeePassRDP")] 9 | [assembly: AssemblyProduct("KeePassRDP ResourcesWriter")] 10 | [assembly: AssemblyCopyright("Copyright © 2025")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | [assembly: Guid("f4890e0e-3f01-4b34-87fb-a260a324b7c3")] 16 | 17 | // Version information 18 | [assembly: AssemblyVersion("1.0")] 19 | [assembly: AssemblyFileVersion("1.0")] 20 | [assembly: AssemblyInformationalVersion("1.0")] 21 | -------------------------------------------------------------------------------- /KeePassRDPSetup/KeePassRDPSetup.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net472 6 | KeePassRDP 7 | AnyCPU 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | TextTemplatingFileGenerator 33 | KeePassRDP.KeePassRDP.installer.yaml 34 | 35 | 36 | True 37 | True 38 | KeePassRDP.KeePassRDP.installer.tt 39 | 40 | 41 | TextTemplatingFileGenerator 42 | KeePassRDP.KeePassRDP.locale.en-US.yaml 43 | 44 | 45 | True 46 | True 47 | KeePassRDP.KeePassRDP.locale.en-US.tt 48 | 49 | 50 | TextTemplatingFileGenerator 51 | KeePassRDP.KeePassRDP.yaml 52 | 53 | 54 | True 55 | True 56 | KeePassRDP.KeePassRDP.tt 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /KeePassRDPSetup/WixUI_de-de.wxl: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /KeePassRDPSetup/WixUI_en-us.wxl: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /KeePassRDPSetup/winget/KeePassRDP.KeePassRDP.installer.tt: -------------------------------------------------------------------------------- 1 | <#@ template compilerOptions="optimize+" hostspecific="true" language="C#" #> 2 | <#@ output extension=".yaml" encoding="utf-8" #> 3 | <#@ assembly name="EnvDTE" #> 4 | <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="System.Text" #> 7 | <#@ import namespace="System.Text.RegularExpressions" #> 8 | <# 9 | var directory = Path.GetDirectoryName(Host.TemplateFile); 10 | var parent = Path.GetDirectoryName(Path.GetDirectoryName(directory)); 11 | 12 | var buildDate = DateTime.UtcNow; 13 | var informationalVersion = string.Empty; 14 | var assemblyVersion = string.Empty; 15 | 16 | var assemblyInfo = File.ReadAllText(Path.Combine(parent, @"KeePassRDP\Properties\AssemblyInfo.cs")); 17 | var match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyInformationalVersion\\(\"([^\"]+)\"\\)\\]"); 18 | if (match.Success) 19 | informationalVersion = match.Groups[1].Value; 20 | 21 | match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyVersion\\(\"([^\"]+)\"\\)\\]"); 22 | if (match.Success) 23 | { 24 | assemblyVersion = match.Groups[1].Value; 25 | if (string.IsNullOrEmpty(informationalVersion)) 26 | informationalVersion = assemblyVersion; 27 | } 28 | #> 29 | PackageIdentifier: KeePassRDP.KeePassRDP 30 | PackageVersion: <#= informationalVersion #> 31 | MinimumOSVersion: 10.0.0.0 32 | InstallerType: wix 33 | UpgradeBehavior: install 34 | InstallerSwitches: 35 | InstallLocation: KEEPASS="" 36 | InstallModes: 37 | - interactive 38 | - silent 39 | - silentWithProgress 40 | ElevationRequirement: elevatesSelf 41 | Dependencies: 42 | PackageDependencies: 43 | - PackageIdentifier: DominikReichl.KeePass 44 | AppsAndFeaturesEntries: 45 | - ProductCode: "{9EAFF850-2B28-4AF1-AE41-056F319393B5}" 46 | UpgradeCode: "{9EAFF850-2B28-4AF1-AE41-056F319393B5}" 47 | Installers: 48 | - Architecture: x64 49 | InstallerUrl: https://github.com/iSnackyCracky/KeePassRDP/releases/download/v<#= informationalVersion #>/KeePassRDP_v<#= informationalVersion #>.msi 50 | InstallerSha256: ###FILE_HASH### 51 | ProductCode: "{9EAFF850-2B28-4AF1-AE41-056F319393B5}" 52 | ReleaseDate: <#= buildDate.ToString("yyyy-MM-dd") #> 53 | ManifestType: installer 54 | ManifestVersion: 1.6.0 -------------------------------------------------------------------------------- /KeePassRDPSetup/winget/KeePassRDP.KeePassRDP.locale.en-US.tt: -------------------------------------------------------------------------------- 1 | <#@ template compilerOptions="optimize+" hostspecific="true" language="C#" #> 2 | <#@ output extension=".yaml" encoding="utf-8" #> 3 | <#@ assembly name="EnvDTE" #> 4 | <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="System.Text" #> 7 | <#@ import namespace="System.Text.RegularExpressions" #> 8 | <# 9 | var directory = Path.GetDirectoryName(Host.TemplateFile); 10 | var parent = Path.GetDirectoryName(Path.GetDirectoryName(directory)); 11 | 12 | var informationalVersion = string.Empty; 13 | var assemblyVersion = string.Empty; 14 | 15 | var assemblyInfo = File.ReadAllText(Path.Combine(parent, @"KeePassRDP\Properties\AssemblyInfo.cs")); 16 | var match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyInformationalVersion\\(\"([^\"]+)\"\\)\\]"); 17 | if (match.Success) 18 | informationalVersion = match.Groups[1].Value; 19 | 20 | match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyVersion\\(\"([^\"]+)\"\\)\\]"); 21 | if (match.Success) 22 | { 23 | assemblyVersion = match.Groups[1].Value; 24 | if (string.IsNullOrEmpty(informationalVersion)) 25 | informationalVersion = assemblyVersion; 26 | } 27 | #> 28 | PackageIdentifier: KeePassRDP.KeePassRDP 29 | PackageVersion: <#= informationalVersion #> 30 | PackageLocale: en-US 31 | Publisher: KeePassRDP 32 | PublisherUrl: https://github.com/iSnackyCracky/KeePassRDP 33 | PublisherSupportUrl: https://github.com/iSnackyCracky/KeePassRDP/issues 34 | Author: KeePassRDP 35 | PackageName: KeePassRDP 36 | PackageUrl: https://github.com/iSnackyCracky/KeePassRDP 37 | License: GPL-3.0 38 | LicenseUrl: https://github.com/iSnackyCracky/KeePassRDP/blob/master/COPYING 39 | Copyright: Copyright (C) 2018 - 2025 40 | CopyrightUrl: https://github.com/iSnackyCracky/KeePassRDP/blob/master/COPYING 41 | ShortDescription: KeePassRDP is a plugin for KeePass 2.x that adds useful options to connect to the URL of an entry with RDP. 42 | Moniker: keepassrdp 43 | Tags: 44 | - keepass 45 | - rdp 46 | ManifestType: defaultLocale 47 | ManifestVersion: 1.6.0 -------------------------------------------------------------------------------- /KeePassRDPSetup/winget/KeePassRDP.KeePassRDP.tt: -------------------------------------------------------------------------------- 1 | <#@ template compilerOptions="optimize+" hostspecific="true" language="C#" #> 2 | <#@ output extension=".yaml" encoding="utf-8" #> 3 | <#@ assembly name="EnvDTE" #> 4 | <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="System.Text" #> 7 | <#@ import namespace="System.Text.RegularExpressions" #> 8 | <# 9 | var directory = Path.GetDirectoryName(Host.TemplateFile); 10 | var parent = Path.GetDirectoryName(Path.GetDirectoryName(directory)); 11 | 12 | var informationalVersion = string.Empty; 13 | var assemblyVersion = string.Empty; 14 | 15 | var assemblyInfo = File.ReadAllText(Path.Combine(parent, @"KeePassRDP\Properties\AssemblyInfo.cs")); 16 | var match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyInformationalVersion\\(\"([^\"]+)\"\\)\\]"); 17 | if (match.Success) 18 | informationalVersion = match.Groups[1].Value; 19 | 20 | match = Regex.Match(assemblyInfo, "\\[assembly: AssemblyVersion\\(\"([^\"]+)\"\\)\\]"); 21 | if (match.Success) 22 | { 23 | assemblyVersion = match.Groups[1].Value; 24 | if (string.IsNullOrEmpty(informationalVersion)) 25 | informationalVersion = assemblyVersion; 26 | } 27 | #> 28 | PackageIdentifier: KeePassRDP.KeePassRDP 29 | PackageVersion: <#= informationalVersion #> 30 | DefaultLocale: en-US 31 | ManifestType: version 32 | ManifestVersion: 1.6.0 -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPUnmanaged/32.ico -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/KeePassRDPUnmanaged.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | * 4 | * This file is part of KeePassRDP. 5 | * 6 | * KeePassRDP is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * KeePassRDP is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with KeePassRDP. If not, see . 18 | * 19 | */ 20 | 21 | #include "pch.h" 22 | 23 | #ifndef DECLSPEC_EXPORT 24 | #define DECLSPEC_EXPORT __declspec(dllexport) 25 | #endif // !DECLSPEC_DLLEXPORT 26 | 27 | EXTERN_C DECLSPEC_EXPORT DECLSPEC_NOINLINE STDMETHODIMP_(PVOID) KprSecureZeroMemory(_In_ PVOID __restrict ptr, _In_ SIZE_T cnt) 28 | { 29 | return SecureZeroMemory(ptr, cnt); 30 | } 31 | 32 | EXTERN_C DECLSPEC_EXPORT STDMETHODIMP KprDoDefaultAction(_In_ PVOID __restrict ptr) 33 | { 34 | IUIAutomation* uiAutomation = NULL; 35 | IUIAutomationElement* parent = NULL; 36 | IUIAutomationLegacyIAccessiblePattern* pattern = NULL; 37 | HRESULT result = S_OK; 38 | 39 | if (FAILED(CoCreateInstance(__uuidof(CUIAutomation8), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&uiAutomation))) || uiAutomation == NULL) 40 | { 41 | if (uiAutomation != NULL) 42 | uiAutomation->Release(); 43 | return E_FAIL; 44 | } 45 | 46 | if (FAILED(uiAutomation->ElementFromHandle(ptr, &parent)) || parent == NULL) 47 | { 48 | if (parent != NULL) 49 | parent->Release(); 50 | uiAutomation->Release(); 51 | return E_FAIL; 52 | } 53 | 54 | if (FAILED(parent->GetCurrentPatternAs(UIA_LegacyIAccessiblePatternId, IID_PPV_ARGS(&pattern))) || pattern == NULL) 55 | { 56 | if (pattern != NULL) 57 | pattern->Release(); 58 | parent->Release(); 59 | uiAutomation->Release(); 60 | return E_FAIL; 61 | } 62 | 63 | if (FAILED(pattern->DoDefaultAction())) 64 | result = E_FAIL; 65 | 66 | pattern->Release(); 67 | parent->Release(); 68 | uiAutomation->Release(); 69 | 70 | return result; 71 | } 72 | 73 | /*EXTERN_C DECLSPEC_EXPORT STDMETHODIMP KprDoDefaultAction(_In_ PVOID ptr, _In_ PWSTR automationId) 74 | { 75 | IUIAutomation* uiAutomation = NULL; 76 | if (FAILED(CoCreateInstance(__uuidof(CUIAutomation8), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&uiAutomation))) || uiAutomation == NULL) 77 | return E_FAIL; 78 | 79 | IUIAutomationElement* parent = NULL; 80 | if (FAILED(uiAutomation->ElementFromHandle(ptr, &parent)) || parent == NULL) 81 | return E_FAIL; 82 | 83 | IUIAutomationCondition* condition = NULL; 84 | VARIANT variant{}; 85 | variant.vt = VT_LPWSTR; 86 | variant.bstrVal = automationId; 87 | if (FAILED(uiAutomation->CreatePropertyCondition(UIA_AutomationIdPropertyId, variant, &condition)) || condition == NULL) 88 | return E_FAIL; 89 | 90 | IUIAutomationElement* child = NULL; 91 | if (FAILED(parent->FindFirst(TreeScope_Children, condition, &child)) || child == NULL) 92 | return E_FAIL; 93 | 94 | IUIAutomationLegacyIAccessiblePattern* pattern = NULL; 95 | if (FAILED(child->GetCurrentPatternAs(UIA_LegacyIAccessiblePatternId, IID_PPV_ARGS(&pattern))) || pattern == NULL) 96 | return E_FAIL; 97 | 98 | if (FAILED(pattern->DoDefaultAction())) 99 | return E_FAIL; 100 | 101 | pattern->Release(); 102 | child->Release(); 103 | parent->Release(); 104 | uiAutomation->Release(); 105 | 106 | return S_OK; 107 | }*/ 108 | 109 | #pragma comment(linker, "/SECTION:.SHARED,RWS") 110 | #pragma data_seg(".SHARED") 111 | HWND g_hwnd = NULL; 112 | HHOOK g_hook = NULL; 113 | #pragma data_seg() 114 | 115 | HMODULE g_hModule = NULL; 116 | 117 | LRESULT CALLBACK WhCbtHookProc(int nCode, WPARAM wParam, LPARAM lParam) 118 | { 119 | if (nCode < 0) 120 | { 121 | return CallNextHookEx(g_hook, nCode, wParam, lParam); 122 | } 123 | 124 | if (g_hwnd != NULL) 125 | { 126 | switch (nCode) 127 | { 128 | case HCBT_MINMAX: 129 | SendMessage(g_hwnd, WM_USER + 1, wParam, lParam); 130 | break; 131 | } 132 | } 133 | 134 | return CallNextHookEx(g_hook, nCode, wParam, lParam); 135 | } 136 | 137 | EXTERN_C DECLSPEC_EXPORT STDMETHODIMP KprSetCbtHwnd(_In_ HWND __restrict hwnd) 138 | { 139 | if (g_hModule == NULL) 140 | return -1; 141 | 142 | if (g_hook != NULL) 143 | { 144 | UnhookWindowsHookEx(g_hook); 145 | g_hook = NULL; 146 | } 147 | 148 | g_hwnd = hwnd; 149 | 150 | if (g_hwnd != NULL) 151 | { 152 | g_hook = SetWindowsHookEx(WH_CBT, WhCbtHookProc, g_hModule, 0); 153 | } 154 | 155 | return S_OK; 156 | } 157 | 158 | EXTERN_C BOOL APIENTRY DllMain(HMODULE hModule, 159 | DWORD ul_reason_for_call, 160 | LPVOID lpReserved 161 | ) 162 | { 163 | switch (ul_reason_for_call) 164 | { 165 | case DLL_PROCESS_ATTACH: 166 | g_hModule = hModule; 167 | DisableThreadLibraryCalls(hModule); 168 | break; 169 | case DLL_THREAD_ATTACH: 170 | case DLL_THREAD_DETACH: 171 | case DLL_PROCESS_DETACH: 172 | break; 173 | } 174 | return TRUE; 175 | } -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/KeePassRDPUnmanaged.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Headerdateien 20 | 21 | 22 | Headerdateien 23 | 24 | 25 | Headerdateien 26 | 27 | 28 | 29 | 30 | Quelldateien 31 | 32 | 33 | Quelldateien 34 | 35 | 36 | -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/KeePassRDPUnmanaged.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/KeePassRDPUnmanaged/KeePassRDPUnmanaged.rc -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Selten verwendete Komponenten aus Windows-Headern ausschließen 4 | // Windows-Headerdateien 5 | #include 6 | #include 7 | #include 8 | -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: Quelldatei, die dem vorkompilierten Header entspricht 2 | 3 | #include "pch.h" 4 | 5 | // Bei der Verwendung vorkompilierter Header ist diese Quelldatei für eine erfolgreiche Kompilierung erforderlich. 6 | -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: Dies ist eine vorkompilierte Headerdatei. 2 | // Die unten aufgeführten Dateien werden nur einmal kompiliert, um die Buildleistung für zukünftige Builds zu verbessern. 3 | // Dies wirkt sich auch auf die IntelliSense-Leistung aus, Codevervollständigung und viele Features zum Durchsuchen von Code eingeschlossen. 4 | // Die hier aufgeführten Dateien werden jedoch ALLE neu kompiliert, wenn mindestens eine davon zwischen den Builds aktualisiert wird. 5 | // Fügen Sie hier keine Dateien hinzu, die häufig aktualisiert werden sollen, da sich so der Leistungsvorteil ins Gegenteil verkehrt. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // Fügen Sie hier Header hinzu, die vorkompiliert werden sollen. 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /KeePassRDPUnmanaged/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by KeePassRDPUnmanaged.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /doc/build_project.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/build_project.jpg -------------------------------------------------------------------------------- /doc/context_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/context_menu.jpg -------------------------------------------------------------------------------- /doc/credential_picker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/credential_picker.jpg -------------------------------------------------------------------------------- /doc/credential_picker_regex.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/credential_picker_regex.jpg -------------------------------------------------------------------------------- /doc/credential_picker_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/credential_picker_settings.jpg -------------------------------------------------------------------------------- /doc/credential_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/credential_settings.jpg -------------------------------------------------------------------------------- /doc/customer_entries.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/customer_entries.jpg -------------------------------------------------------------------------------- /doc/db_structure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/db_structure.jpg -------------------------------------------------------------------------------- /doc/entry_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/entry_settings.jpg -------------------------------------------------------------------------------- /doc/executable_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/executable_settings.jpg -------------------------------------------------------------------------------- /doc/jumphost_entry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/jumphost_entry.jpg -------------------------------------------------------------------------------- /doc/keyboard_shortcuts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/keyboard_shortcuts.jpg -------------------------------------------------------------------------------- /doc/rdp_file.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/rdp_file.jpg -------------------------------------------------------------------------------- /doc/rdp_subgroup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/rdp_subgroup.jpg -------------------------------------------------------------------------------- /doc/rdp_subgroup_entries.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/rdp_subgroup_entries.jpg -------------------------------------------------------------------------------- /doc/secure_desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/secure_desktop.jpg -------------------------------------------------------------------------------- /doc/self_signing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/self_signing.jpg -------------------------------------------------------------------------------- /doc/session_shadowing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/session_shadowing.jpg -------------------------------------------------------------------------------- /doc/visibility_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSnackyCracky/KeePassRDP/df0bf061e26efb6239014dc7ca98557a5b8cbfee/doc/visibility_settings.jpg -------------------------------------------------------------------------------- /make_release.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | # Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | # 4 | # This file is part of KeePassRDP. 5 | # 6 | # KeePassRDP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # KeePassRDP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with KeePassRDP. If not, see . 18 | # 19 | #> 20 | 21 | Add-Type -Assembly System.IO.Compression 22 | Add-Type -Assembly System.IO.Compression.FileSystem 23 | 24 | [System.Environment]::CurrentDirectory = (Get-Location).Path; 25 | 26 | $ver = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("KeePassRDP\bin\Release\KeePassRDP.dll"); 27 | $zipFile = [System.IO.File]::Open("KeePassRDP_v$($ver.ProductVersion).zip", [System.IO.FileMode]::Create); 28 | $archive = New-Object System.IO.Compression.ZipArchive($zipFile, [System.IO.Compression.ZipArchiveMode]::Create, $true); 29 | 30 | @("KeePassRDP\bin\Release\KeePassRDP.plgx", "COPYING") | %{ 31 | $archiveEntry = $archive.CreateEntry([System.IO.Path]::GetFileName($_)); 32 | $archiveEntryStream = $archiveEntry.Open(); 33 | $archiveFile = [System.IO.File]::Open($_, [System.IO.FileMode]::Open); 34 | $archiveFile.CopyTo($archiveEntryStream); 35 | $archiveFile.Dispose(); 36 | $archiveEntryStream.Dispose(); 37 | } 38 | 39 | $archive.Dispose(); 40 | $zipFile.Dispose(); 41 | 42 | Start-Sleep -Seconds 1 43 | & iexpress /n /q /m KeePassRDP\KeePassRDPexe.SED -------------------------------------------------------------------------------- /make_winget.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | # Copyright (C) 2018 - 2025 iSnackyCracky, NETertainer 3 | # 4 | # This file is part of KeePassRDP. 5 | # 6 | # KeePassRDP is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # KeePassRDP is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with KeePassRDP. If not, see . 18 | # 19 | #> 20 | 21 | [System.Environment]::CurrentDirectory = (Get-Location).Path; 22 | 23 | $Version = ([System.Diagnostics.FileVersionInfo]::GetVersionInfo("KeePassRDP\bin\Release\KeePassRDP.dll")).ProductVersion 24 | $FileHash = $(Get-FileHash -Algorithm SHA256 "KeePassRDPSetup\bin\Release\KeePassRDP_v$Version.msi").Hash 25 | $FilePath = "KeePassRDPSetup\winget\KeePassRDP.KeePassRDP.installer.yaml" 26 | $Content = Get-Content -Encoding UTF8 $FilePath 27 | $Content = $Content -replace "###FILE_HASH###", $FileHash 28 | Set-Content -Encoding Utf8 -Path $FilePath -Value $Content 29 | 30 | #.\wingetcreate.exe submit -p "KeePassRDP v$Version" -t "$env:WINGET_GH_TOKEN" "KeePassRDPSetup\winget" --------------------------------------------------------------------------------