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.Diagnostics; 22 using System.IO; 23 using System.Runtime.InteropServices; 24 using System.Text; 25 26 using KeePassLib.Utility; 27 28 namespace KeePassLib.Native 29 { 30 internal static partial class NativeMethods 31 { 32 internal const int MAX_PATH = 260; 33 34 internal const long INVALID_HANDLE_VALUE = -1; 35 36 internal const uint MOVEFILE_REPLACE_EXISTING = 0x00000001; 37 internal const uint MOVEFILE_COPY_ALLOWED = 0x00000002; 38 39 internal const uint FILE_SUPPORTS_TRANSACTIONS = 0x00200000; 40 internal const int MAX_TRANSACTION_DESCRIPTION_LENGTH = 64; 41 42 internal static readonly Guid FOLDERID_SkyDrive = new Guid( 43 "A52BBA46-E9E1-435F-B3D9-28DAA648C0F6"); 44 45 // internal const uint TF_SFT_SHOWNORMAL = 0x00000001; 46 // internal const uint TF_SFT_HIDDEN = 0x00000008; 47 48 /* [DllImport("KeePassNtv32.dll", EntryPoint = "TransformKey")] 49 [return: MarshalAs(UnmanagedType.Bool)] 50 private static extern bool TransformKey32(IntPtr pBuf256, 51 IntPtr pKey256, UInt64 uRounds); 52 53 [DllImport("KeePassNtv64.dll", EntryPoint = "TransformKey")] 54 [return: MarshalAs(UnmanagedType.Bool)] 55 private static extern bool TransformKey64(IntPtr pBuf256, 56 IntPtr pKey256, UInt64 uRounds); 57 58 internal static bool TransformKey(IntPtr pBuf256, IntPtr pKey256, 59 UInt64 uRounds) 60 { 61 if(IntPtr.Size == 4) 62 return TransformKey32(pBuf256, pKey256, uRounds); 63 return TransformKey64(pBuf256, pKey256, uRounds); 64 } 65 66 [DllImport("KeePassNtv32.dll", EntryPoint = "TransformKeyTimed")] 67 [return: MarshalAs(UnmanagedType.Bool)] 68 private static extern bool TransformKeyTimed32(IntPtr pBuf256, 69 IntPtr pKey256, ref UInt64 puRounds, UInt32 uSeconds); 70 71 [DllImport("KeePassNtv64.dll", EntryPoint = "TransformKeyTimed")] 72 [return: MarshalAs(UnmanagedType.Bool)] 73 private static extern bool TransformKeyTimed64(IntPtr pBuf256, 74 IntPtr pKey256, ref UInt64 puRounds, UInt32 uSeconds); 75 76 internal static bool TransformKeyTimed(IntPtr pBuf256, IntPtr pKey256, 77 ref UInt64 puRounds, UInt32 uSeconds) 78 { 79 if(IntPtr.Size == 4) 80 return TransformKeyTimed32(pBuf256, pKey256, ref puRounds, uSeconds); 81 return TransformKeyTimed64(pBuf256, pKey256, ref puRounds, uSeconds); 82 } */ 83 84 #if !KeePassUAP 85 [DllImport("KeePassLibC32.dll", EntryPoint = "TransformKey256")] 86 [return: MarshalAs(UnmanagedType.Bool)] TransformKey32(IntPtr pBuf256, IntPtr pKey256, UInt64 uRounds)87 private static extern bool TransformKey32(IntPtr pBuf256, 88 IntPtr pKey256, UInt64 uRounds); 89 90 [DllImport("KeePassLibC64.dll", EntryPoint = "TransformKey256")] 91 [return: MarshalAs(UnmanagedType.Bool)] TransformKey64(IntPtr pBuf256, IntPtr pKey256, UInt64 uRounds)92 private static extern bool TransformKey64(IntPtr pBuf256, 93 IntPtr pKey256, UInt64 uRounds); 94 TransformKey(IntPtr pBuf256, IntPtr pKey256, UInt64 uRounds)95 internal static bool TransformKey(IntPtr pBuf256, IntPtr pKey256, 96 UInt64 uRounds) 97 { 98 if(IntPtr.Size == 4) 99 return TransformKey32(pBuf256, pKey256, uRounds); 100 return TransformKey64(pBuf256, pKey256, uRounds); 101 } 102 103 [DllImport("KeePassLibC32.dll", EntryPoint = "TransformKeyBenchmark256")] TransformKeyBenchmark32(UInt32 uTimeMs)104 private static extern UInt64 TransformKeyBenchmark32(UInt32 uTimeMs); 105 106 [DllImport("KeePassLibC64.dll", EntryPoint = "TransformKeyBenchmark256")] TransformKeyBenchmark64(UInt32 uTimeMs)107 private static extern UInt64 TransformKeyBenchmark64(UInt32 uTimeMs); 108 TransformKeyBenchmark(UInt32 uTimeMs)109 internal static UInt64 TransformKeyBenchmark(UInt32 uTimeMs) 110 { 111 if(IntPtr.Size == 4) 112 return TransformKeyBenchmark32(uTimeMs); 113 return TransformKeyBenchmark64(uTimeMs); 114 } 115 #endif 116 117 /* [DllImport("KeePassLibC32.dll", EntryPoint = "TF_ShowLangBar")] 118 [return: MarshalAs(UnmanagedType.Bool)] 119 private static extern bool TF_ShowLangBar32(UInt32 dwFlags); 120 121 [DllImport("KeePassLibC64.dll", EntryPoint = "TF_ShowLangBar")] 122 [return: MarshalAs(UnmanagedType.Bool)] 123 private static extern bool TF_ShowLangBar64(UInt32 dwFlags); 124 125 internal static bool TfShowLangBar(uint dwFlags) 126 { 127 if(IntPtr.Size == 4) return TF_ShowLangBar32(dwFlags); 128 return TF_ShowLangBar64(dwFlags); 129 } */ 130 131 [DllImport("KeePassLibC32.dll", EntryPoint = "ProtectProcessWithDacl")] ProtectProcessWithDacl32()132 private static extern void ProtectProcessWithDacl32(); 133 134 [DllImport("KeePassLibC64.dll", EntryPoint = "ProtectProcessWithDacl")] ProtectProcessWithDacl64()135 private static extern void ProtectProcessWithDacl64(); 136 ProtectProcessWithDacl()137 internal static void ProtectProcessWithDacl() 138 { 139 try 140 { 141 if(NativeLib.IsUnix()) return; 142 143 if(IntPtr.Size == 4) ProtectProcessWithDacl32(); 144 else ProtectProcessWithDacl64(); 145 } 146 catch(Exception) { Debug.Assert(false); } 147 } 148 149 [DllImport("Kernel32.dll", SetLastError = true)] 150 [return: MarshalAs(UnmanagedType.Bool)] CloseHandle(IntPtr hObject)151 internal static extern bool CloseHandle(IntPtr hObject); 152 153 [DllImport("Kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false, 154 SetLastError = true)] 155 [return: MarshalAs(UnmanagedType.Bool)] GetVolumeInformation(string lpRootPathName, StringBuilder lpVolumeNameBuffer, UInt32 nVolumeNameSize, ref UInt32 lpVolumeSerialNumber, ref UInt32 lpMaximumComponentLength, ref UInt32 lpFileSystemFlags, StringBuilder lpFileSystemNameBuffer, UInt32 nFileSystemNameSize)156 internal static extern bool GetVolumeInformation(string lpRootPathName, 157 StringBuilder lpVolumeNameBuffer, UInt32 nVolumeNameSize, 158 ref UInt32 lpVolumeSerialNumber, ref UInt32 lpMaximumComponentLength, 159 ref UInt32 lpFileSystemFlags, StringBuilder lpFileSystemNameBuffer, 160 UInt32 nFileSystemNameSize); 161 162 [DllImport("Kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false, 163 SetLastError = true)] 164 [return: MarshalAs(UnmanagedType.Bool)] MoveFileEx(string lpExistingFileName, string lpNewFileName, UInt32 dwFlags)165 internal static extern bool MoveFileEx(string lpExistingFileName, 166 string lpNewFileName, UInt32 dwFlags); 167 168 [DllImport("KtmW32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, 169 SetLastError = true)] CreateTransaction(IntPtr lpTransactionAttributes, IntPtr lpUOW, UInt32 dwCreateOptions, UInt32 dwIsolationLevel, UInt32 dwIsolationFlags, UInt32 dwTimeout, string lpDescription)170 internal static extern IntPtr CreateTransaction(IntPtr lpTransactionAttributes, 171 IntPtr lpUOW, UInt32 dwCreateOptions, UInt32 dwIsolationLevel, 172 UInt32 dwIsolationFlags, UInt32 dwTimeout, string lpDescription); 173 174 [DllImport("KtmW32.dll", SetLastError = true)] 175 [return: MarshalAs(UnmanagedType.Bool)] CommitTransaction(IntPtr hTransaction)176 internal static extern bool CommitTransaction(IntPtr hTransaction); 177 178 [DllImport("Kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false, 179 SetLastError = true)] 180 [return: MarshalAs(UnmanagedType.Bool)] MoveFileTransacted(string lpExistingFileName, string lpNewFileName, IntPtr lpProgressRoutine, IntPtr lpData, UInt32 dwFlags, IntPtr hTransaction)181 internal static extern bool MoveFileTransacted(string lpExistingFileName, 182 string lpNewFileName, IntPtr lpProgressRoutine, IntPtr lpData, 183 UInt32 dwFlags, IntPtr hTransaction); 184 185 [DllImport("Shell32.dll")] SHGetKnownFolderPath(ref Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath)186 private static extern int SHGetKnownFolderPath(ref Guid rfid, uint dwFlags, 187 IntPtr hToken, out IntPtr ppszPath); 188 189 #if (!KeePassLibSD && !KeePassUAP) 190 [DllImport("ShlWApi.dll", CharSet = CharSet.Auto)] 191 [return: MarshalAs(UnmanagedType.Bool)] PathRelativePathTo([Out] StringBuilder pszPath, [In] string pszFrom, uint dwAttrFrom, [In] string pszTo, uint dwAttrTo)192 internal static extern bool PathRelativePathTo([Out] StringBuilder pszPath, 193 [In] string pszFrom, uint dwAttrFrom, [In] string pszTo, uint dwAttrTo); 194 195 [DllImport("ShlWApi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] StrCmpLogicalW(string x, string y)196 private static extern int StrCmpLogicalW(string x, string y); 197 198 private static bool? m_obSupportsLogicalCmp = null; 199 TestNaturalComparisonsSupport()200 private static void TestNaturalComparisonsSupport() 201 { 202 try 203 { 204 StrCmpLogicalW("0", "0"); // Throws exception if unsupported 205 m_obSupportsLogicalCmp = true; 206 } 207 catch(Exception) { m_obSupportsLogicalCmp = false; } 208 } 209 #endif 210 211 internal static bool SupportsStrCmpNaturally 212 { 213 get 214 { 215 #if (!KeePassLibSD && !KeePassUAP) 216 if(!m_obSupportsLogicalCmp.HasValue) 217 TestNaturalComparisonsSupport(); 218 219 return m_obSupportsLogicalCmp.Value; 220 #else 221 return false; 222 #endif 223 } 224 } 225 StrCmpNaturally(string x, string y)226 internal static int StrCmpNaturally(string x, string y) 227 { 228 #if (!KeePassLibSD && !KeePassUAP) 229 if(!NativeMethods.SupportsStrCmpNaturally) 230 { 231 Debug.Assert(false); 232 return string.Compare(x, y, true); 233 } 234 235 return StrCmpLogicalW(x, y); 236 #else 237 Debug.Assert(false); 238 return string.Compare(x, y, true); 239 #endif 240 } 241 GetUserRuntimeDir()242 internal static string GetUserRuntimeDir() 243 { 244 #if KeePassLibSD 245 return Path.GetTempPath(); 246 #else 247 #if KeePassUAP 248 string strRtDir = EnvironmentExt.AppDataLocalFolderPath; 249 #else 250 string strRtDir = Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR"); 251 if(string.IsNullOrEmpty(strRtDir)) 252 strRtDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 253 if(string.IsNullOrEmpty(strRtDir)) 254 { 255 Debug.Assert(false); 256 return Path.GetTempPath(); // Not UrlUtil (otherwise cyclic) 257 } 258 #endif 259 260 strRtDir = UrlUtil.EnsureTerminatingSeparator(strRtDir, false); 261 strRtDir += PwDefs.ShortProductName; 262 263 return strRtDir; 264 #endif 265 } 266 GetKnownFolderPath(Guid g)267 internal static string GetKnownFolderPath(Guid g) 268 { 269 if(Marshal.SystemDefaultCharSize != 2) { Debug.Assert(false); return string.Empty; } 270 271 IntPtr pszPath = IntPtr.Zero; 272 try 273 { 274 if(SHGetKnownFolderPath(ref g, 0, IntPtr.Zero, out pszPath) == 0) 275 { 276 if(pszPath != IntPtr.Zero) 277 return Marshal.PtrToStringUni(pszPath); 278 else { Debug.Assert(false); } 279 } 280 } 281 catch(Exception) { Debug.Assert(false); } 282 finally 283 { 284 try { if(pszPath != IntPtr.Zero) Marshal.FreeCoTaskMem(pszPath); } 285 catch(Exception) { Debug.Assert(false); } 286 } 287 288 return string.Empty; 289 } 290 } 291 } 292