diff --git a/src/Files.App.CsWin32/NativeMethods.txt b/src/Files.App.CsWin32/NativeMethods.txt index aee2e82f99b3..729798e9ee8b 100644 --- a/src/Files.App.CsWin32/NativeMethods.txt +++ b/src/Files.App.CsWin32/NativeMethods.txt @@ -226,3 +226,7 @@ _SICHINTF RoGetAgileReference IQueryInfo QITIPF_FLAGS +CancelIoEx +OVERLAPPED +CreateEvent +ReadDirectoryChangesW diff --git a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs index 9af7345111ec..41120863b440 100644 --- a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs +++ b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs @@ -115,17 +115,6 @@ public static extern bool GetOverlappedResult( bool bWait ); - [DllImport("api-ms-win-core-io-l1-1-1.dll")] - public static extern bool CancelIo( - IntPtr hFile - ); - - [DllImport("api-ms-win-core-io-l1-1-1.dll")] - public static extern bool CancelIoEx( - IntPtr hFile, - IntPtr lpOverlapped - ); - [DllImport("api-ms-win-core-synch-l1-2-0.dll")] public static extern uint WaitForMultipleObjectsEx( uint nCount, diff --git a/src/Files.App/ViewModels/ShellViewModel.cs b/src/Files.App/ViewModels/ShellViewModel.cs index 68472561dc36..6e3212e6a6dd 100644 --- a/src/Files.App/ViewModels/ShellViewModel.cs +++ b/src/Files.App/ViewModels/ShellViewModel.cs @@ -14,6 +14,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Vanara.Windows.Shell; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.Storage.FileSystem; using Windows.Foundation; using Windows.Storage; using Windows.Storage.FileProperties; @@ -23,6 +26,8 @@ using FileAttributes = System.IO.FileAttributes; using ByteSize = ByteSizeLib.ByteSize; using Windows.Win32.System.SystemServices; +using FINDEX_SEARCH_OPS = Windows.Win32.Storage.FileSystem.FINDEX_SEARCH_OPS; +using FINDEX_INFO_LEVELS = Windows.Win32.Storage.FileSystem.FINDEX_INFO_LEVELS; namespace Files.App.ViewModels { @@ -1748,7 +1753,7 @@ await DialogDisplayHelper.ShowDialogAsync( var findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoBasic; var additionalFlags = FIND_FIRST_EX_LARGE_FETCH; - IntPtr hFileTsk = FindFirstFileExFromApp( + IntPtr hFileTsk = PInvoke.FindFirstFileEx( path + "\\*.*", findInfoLevel, out WIN32_FIND_DATA findDataTsk, @@ -2101,7 +2106,7 @@ await dispatcherQueue.EnqueueOrInvokeAsync(() => }); } - private void WatchForDirectoryChanges(string path, CloudDriveSyncStatus syncStatus) + private unsafe void WatchForDirectoryChanges(string path, CloudDriveSyncStatus syncStatus) { Debug.WriteLine($"WatchForDirectoryChanges: {path}"); var hWatchDir = Win32PInvoke.CreateFileFromApp(path, 1, 1 | 2 | 4, @@ -2206,23 +2211,27 @@ private void WatchForDirectoryChanges(string path, CloudDriveSyncStatus syncStat Debug.WriteLine("watcher canceled"); } - CancelIoEx(hWatchDir, IntPtr.Zero); - CloseHandle(hWatchDir); + PInvoke.CancelIoEx((HANDLE)hWatchDir); + PInvoke.CloseHandle((HANDLE)hWatchDir); }); } - private void WatchForGitChanges() + private unsafe void WatchForGitChanges() { - var hWatchDir = Win32PInvoke.CreateFileFromApp( - GitDirectory!, - 1, - 1 | 2 | 4, - IntPtr.Zero, - 3, - (uint)Win32PInvoke.File_Attributes.BackupSemantics | (uint)Win32PInvoke.File_Attributes.Overlapped, - IntPtr.Zero); + HANDLE hWatchDir; - if (hWatchDir.ToInt64() == -1) + fixed (char* gitDir = GitDirectory) + { + hWatchDir = PInvoke.CreateFile( + gitDir!, + 1, + FILE_SHARE_MODE.FILE_SHARE_READ | FILE_SHARE_MODE.FILE_SHARE_WRITE | FILE_SHARE_MODE.FILE_SHARE_DELETE, + dwCreationDisposition: FILE_CREATION_DISPOSITION.OPEN_EXISTING, + dwFlagsAndAttributes: FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_OVERLAPPED, + hTemplateFile: (HANDLE)null); + } + + if (hWatchDir.IsNull) return; gitProcessQueueAction ??= Task.Factory.StartNew(() => ProcessGitChangesQueueAsync(watcherCTS.Token), default, @@ -2234,8 +2243,8 @@ private void WatchForGitChanges() var rand = Guid.NewGuid(); var notifyFilters = FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_CREATION; - var overlapped = new OVERLAPPED(); - overlapped.hEvent = CreateEvent(IntPtr.Zero, false, false, null); + var overlapped = new Overlapped(); + overlapped.EventHandleIntPtr = PInvoke.CreateEvent((bManualReset: false, bInitialState: false, lpName: null); const uint INFINITE = 0xFFFFFFFF; while (x.Status != AsyncStatus.Canceled) @@ -2248,15 +2257,16 @@ private void WatchForGitChanges() if (x.Status == AsyncStatus.Canceled) break; - ReadDirectoryChangesW(hWatchDir, pBuff, + PInvoke.ReadDirectoryChanges(hWatchDir, pBuff, 4096, true, - notifyFilters, null, - ref overlapped, null); + notifyFilters, + lpOverlapped: ref overlapped, + lpCompletionRoutine: null); if (x.Status == AsyncStatus.Canceled) break; - var rc = WaitForSingleObjectEx(overlapped.hEvent, INFINITE, true); + var rc = WaitForSingleObjectEx(overlapped.EventHandleIntPtr, INFINITE, true); uint offset = 0; ref var notifyInfo = ref Unsafe.As(ref buff[offset]); @@ -2280,7 +2290,7 @@ private void WatchForGitChanges() } } - CloseHandle(overlapped.hEvent); + PInvoke.CloseHandle((HANDLE)overlapped.EventHandleIntPtr); gitChangesQueue.Clear(); }); @@ -2294,7 +2304,7 @@ private void WatchForGitChanges() gitWatcherAction = null; } - CancelIoEx(hWatchDir, IntPtr.Zero); + PInvoke.CancelIoEx(hWatchDir); CloseHandle(hWatchDir); }); }