1 /* 2 KeePass Password Safe - The Open-Source Password Manager 3 Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 using System; 21 using System.Collections.Generic; 22 using System.Text; 23 using System.Runtime.InteropServices; 24 using System.Runtime.InteropServices.ComTypes; 25 using System.Diagnostics; 26 27 using KeePassLib.Utility; 28 29 namespace KeePass.Native 30 { 31 internal sealed class ShellLinkEx 32 { 33 private string m_strPath = null; 34 public string Path 35 { 36 get { return m_strPath; } 37 set { m_strPath = value; } 38 } 39 40 private string m_strArgs = null; 41 public string Arguments 42 { 43 get { return m_strArgs; } 44 set { m_strArgs = value; } 45 } 46 47 private string m_strDesc = null; 48 public string Description 49 { 50 get { return m_strDesc; } 51 set 52 { 53 if((value != null) && (value.Length >= NativeMethods.INFOTIPSIZE)) 54 { 55 Debug.Assert(false); 56 m_strDesc = StrUtil.CompactString3Dots(value, 57 NativeMethods.INFOTIPSIZE - 1); 58 } 59 else m_strDesc = value; 60 } 61 } 62 ShellLinkEx()63 public ShellLinkEx() 64 { 65 } 66 ShellLinkEx(string strPath, string strArgs, string strDesc)67 public ShellLinkEx(string strPath, string strArgs, string strDesc) 68 { 69 m_strPath = strPath; 70 m_strArgs = strArgs; 71 this.Description = strDesc; // Shortens description if necessary 72 } 73 Load(string strLnkFilePath)74 public static ShellLinkEx Load(string strLnkFilePath) 75 { 76 try 77 { 78 CShellLink csl = new CShellLink(); 79 80 IShellLinkW sl = (csl as IShellLinkW); 81 if(sl == null) { Debug.Assert(false); return null; } 82 IPersistFile pf = (csl as IPersistFile); 83 if(pf == null) { Debug.Assert(false); return null; } 84 85 pf.Load(strLnkFilePath, (int)(NativeMethods.STGM.Read | 86 NativeMethods.STGM.ShareDenyWrite)); 87 88 const int ccMaxPath = KeePassLib.Native.NativeMethods.MAX_PATH; 89 const int ccInfoTip = NativeMethods.INFOTIPSIZE; 90 91 ShellLinkEx r = new ShellLinkEx(); 92 93 StringBuilder sb = new StringBuilder(ccMaxPath + 1); 94 sl.GetPath(sb, sb.Capacity, IntPtr.Zero, 0); 95 r.Path = sb.ToString(); 96 97 sb = new StringBuilder(ccInfoTip + 1); 98 sl.GetArguments(sb, sb.Capacity); 99 r.Arguments = sb.ToString(); 100 101 sb = new StringBuilder(ccInfoTip + 1); 102 sl.GetDescription(sb, sb.Capacity); 103 r.Description = sb.ToString(); 104 105 return r; 106 } 107 catch(Exception) { Debug.Assert(false); } 108 109 return null; 110 } 111 Save(string strLnkFilePath)112 public bool Save(string strLnkFilePath) 113 { 114 try 115 { 116 CShellLink csl = new CShellLink(); 117 118 IShellLinkW sl = (csl as IShellLinkW); 119 if(sl == null) { Debug.Assert(false); return false; } 120 IPersistFile pf = (csl as IPersistFile); 121 if(pf == null) { Debug.Assert(false); return false; } 122 123 if(!string.IsNullOrEmpty(m_strPath)) 124 sl.SetPath(m_strPath); 125 if(!string.IsNullOrEmpty(m_strArgs)) 126 sl.SetArguments(m_strArgs); 127 if(!string.IsNullOrEmpty(m_strDesc)) 128 sl.SetDescription(m_strDesc); 129 130 pf.Save(strLnkFilePath, true); 131 return true; 132 } 133 catch(Exception) { Debug.Assert(false); } 134 135 return false; 136 } 137 } 138 139 [ComImport] 140 [Guid("000214F9-0000-0000-C000-000000000046")] 141 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 142 internal interface IShellLinkW 143 { GetPath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cch, IntPtr pfd, uint fFlags)144 void GetPath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, 145 int cch, IntPtr pfd, uint fFlags); 146 GetIDList(out IntPtr ppidl)147 void GetIDList(out IntPtr ppidl); SetIDList(IntPtr pidl)148 void SetIDList(IntPtr pidl); 149 GetDescription([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cch)150 void GetDescription([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, 151 int cch); SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName)152 void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); 153 GetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cch)154 void GetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, 155 int cch); SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir)156 void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); 157 GetArguments([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cch)158 void GetArguments([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cch); SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs)159 void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); 160 GetHotkey(out ushort pwHotkey)161 void GetHotkey(out ushort pwHotkey); SetHotkey(ushort wHotkey)162 void SetHotkey(ushort wHotkey); 163 GetShowCmd(out int piShowCmd)164 void GetShowCmd(out int piShowCmd); SetShowCmd(int iShowCmd)165 void SetShowCmd(int iShowCmd); 166 GetIconLocation([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cch, out int piIcon)167 void GetIconLocation([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, 168 int cch, out int piIcon); SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon)169 void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, 170 int iIcon); 171 SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved)172 void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, 173 uint dwReserved); 174 Resolve(IntPtr hwnd, uint fFlags)175 void Resolve(IntPtr hwnd, uint fFlags); 176 SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile)177 void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); 178 } 179 180 [ComImport] 181 [Guid("00021401-0000-0000-C000-000000000046")] 182 internal class CShellLink { } 183 } 184