diff --git a/src/Files.App.CsWin32/NativeMethods.txt b/src/Files.App.CsWin32/NativeMethods.txt index ce5524f6885e..7443354bbeda 100644 --- a/src/Files.App.CsWin32/NativeMethods.txt +++ b/src/Files.App.CsWin32/NativeMethods.txt @@ -225,3 +225,8 @@ QITIPF_FLAGS GetKeyboardState MapVirtualKey GetKeyboardLayout +CreateEvent +SetEvent +CoWaitForMultipleObjects +CWMO_FLAGS +INFINITE diff --git a/src/Files.App.Storage/Storables/WindowsStorage/STATask.cs b/src/Files.App.Storage/Storables/WindowsStorage/STATask.cs index 29a4a6819e61..357487b875d1 100644 --- a/src/Files.App.Storage/Storables/WindowsStorage/STATask.cs +++ b/src/Files.App.Storage/Storables/WindowsStorage/STATask.cs @@ -2,6 +2,9 @@ // Licensed under the MIT License. using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.System.Com; +using Windows.Win32.Security; namespace Files.App.Storage { @@ -143,5 +146,46 @@ public static Task Run(Func func) return tcs.Task; } + + public unsafe static Task RunAsSync(Action action) + { + Debug.Assert(Thread.CurrentThread.GetApartmentState() is ApartmentState.STA); + + HANDLE hEventHandle = PInvoke.CreateEvent((SECURITY_ATTRIBUTES*)null, true, false, default); + + var tcs = new TaskCompletionSource(); + + Task.Run(() => + { + try + { + action(); + tcs.SetResult(); + } + catch (Exception ex) + { + tcs.SetException(ex); + } + finally + { + PInvoke.SetEvent(hEventHandle); + } + }); + + HANDLE* pEventHandles = stackalloc HANDLE[1]; + pEventHandles[0] = hEventHandle; + uint dwIndex = 0u; + + PInvoke.CoWaitForMultipleObjects( + (uint)CWMO_FLAGS.CWMO_DEFAULT, + PInvoke.INFINITE, + 1u, + pEventHandles, + &dwIndex); + + PInvoke.CloseHandle(hEventHandle); + + return tcs.Task; + } } } diff --git a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs index 5d700736a2fa..8a76af7f988c 100644 --- a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs +++ b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs @@ -69,15 +69,6 @@ public static extern bool SetEvent( IntPtr hEvent ); - [DllImport("ole32.dll")] - public static extern uint CoWaitForMultipleObjects( - uint dwFlags, - uint dwMilliseconds, - ulong nHandles, - IntPtr[] pHandles, - out uint dwIndex - ); - [DllImport("shell32.dll")] public static extern IntPtr SHBrowseForFolder( ref BROWSEINFO lpbi diff --git a/src/Files.App/Program.cs b/src/Files.App/Program.cs index 6d7807095797..96b16b3af2d0 100644 --- a/src/Files.App/Program.cs +++ b/src/Files.App/Program.cs @@ -9,7 +9,6 @@ using System.Text; using Windows.ApplicationModel.Activation; using Windows.Storage; -using static Files.App.Helpers.Win32PInvoke; namespace Files.App { @@ -21,9 +20,6 @@ namespace Files.App /// internal sealed class Program { - private const uint CWMO_DEFAULT = 0; - private const uint INFINITE = 0xFFFFFFFF; - public static Semaphore? Pool { get; set; } static Program() @@ -250,20 +246,10 @@ private static async void OnActivated(object? sender, AppActivationArguments arg /// public static void RedirectActivationTo(AppInstance keyInstance, AppActivationArguments args) { - IntPtr eventHandle = CreateEvent(IntPtr.Zero, true, false, null); - - Task.Run(() => + STATask.RunAsSync(() => { keyInstance.RedirectActivationToAsync(args).AsTask().Wait(); - SetEvent(eventHandle); }); - - _ = CoWaitForMultipleObjects( - CWMO_DEFAULT, - INFINITE, - 1, - [eventHandle], - out uint handleIndex); } public static void OpenShellCommandInExplorer(string shellCommand, int pid) @@ -273,20 +259,10 @@ public static void OpenShellCommandInExplorer(string shellCommand, int pid) public static void OpenFileFromTile(string filePath) { - IntPtr eventHandle = CreateEvent(IntPtr.Zero, true, false, null); - - Task.Run(() => + STATask.RunAsSync(() => { LaunchHelper.LaunchAppAsync(filePath, null, null).Wait(); - SetEvent(eventHandle); }); - - _ = CoWaitForMultipleObjects( - CWMO_DEFAULT, - INFINITE, - 1, - [eventHandle], - out uint handleIndex); } } }