From 5a4f6f4eb64ad62e171aba9d42c08b738d0b5655 Mon Sep 17 00:00:00 2001 From: SadPencil Date: Tue, 10 Sep 2024 04:19:34 +0800 Subject: [PATCH] Unblock Internet files on startup (#15) --- NativeConstants.cs | 10 ++++++++++ NativeMethods.cs | 13 +++++++++++++ Program.cs | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 NativeConstants.cs create mode 100644 NativeMethods.cs diff --git a/NativeConstants.cs b/NativeConstants.cs new file mode 100644 index 0000000..727cfd1 --- /dev/null +++ b/NativeConstants.cs @@ -0,0 +1,10 @@ +namespace CnCNet.LauncherStub; + +internal static class NativeConstants +{ + /// ERROR_FILE_NOT_FOUND -> 2L + public const int ERROR_FILE_NOT_FOUND = 2; + + /// ERROR_ACCESS_DENIED -> 5L + public const int ERROR_ACCESS_DENIED = 5; +} diff --git a/NativeMethods.cs b/NativeMethods.cs new file mode 100644 index 0000000..1d49f9b --- /dev/null +++ b/NativeMethods.cs @@ -0,0 +1,13 @@ +namespace CnCNet.LauncherStub; + +using System.Runtime.InteropServices; + +internal static class NativeMethods +{ + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] +#if NET45_OR_GREATER || NETSTANDARD || NET + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] +#endif + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DeleteFile(string name); +} diff --git a/Program.cs b/Program.cs index bfd06bc..9ecc882 100644 --- a/Program.cs +++ b/Program.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using Microsoft.Win32; internal sealed class Program @@ -87,6 +88,21 @@ private static void RequireDotNetFramework() [STAThread] private static void Main(string[] args) { + try + { + RemoveZoneIdentifer(CurrentDirectory); + } + catch (Exception ex) + { + bool ignoreUnblocking = AdvancedMessageBoxHelper.ShowYesNoMessageBox( + "An error occured when the launcher tried to unblock files. Re-running the launcher with administrator privileges might help.\n\n" + ex.ToString(), + "Client Launcher Warning", + yesText: "Continue", noText: "Exit"); + + if (!ignoreUnblocking) + Environment.Exit(1); + } + try { foreach (string arg in args) @@ -163,6 +179,37 @@ private static void RunDialogTest() msgbox.ShowDialog(); } + private static void RemoveZoneIdentifer(string directory) + { + // https://stackoverflow.com/a/6375373 + + List failedMessages = []; + + // Enumerate all files recursively + string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories); + string[] directories = Directory.GetDirectories(directory, "*", SearchOption.AllDirectories); + + // For each file or directory, remove the Zone.Identifier alternate data stream + foreach (string file in files.Concat(directories)) + { + string zoneIdentifier = file + ":Zone.Identifier"; + bool success = NativeMethods.DeleteFile(zoneIdentifier); + if (!success) + { + int error = Marshal.GetLastWin32Error(); + if (error == NativeConstants.ERROR_FILE_NOT_FOUND) + continue; + + string errorMessage = new Win32Exception(error).Message; + + failedMessages.Add($"{file}: {errorMessage}"); + } + } + + if (failedMessages.Count > 0) + throw new Exception("Failed to remove Zone.Identifier from the following files:\n" + string.Join("\n", failedMessages)); + } + private static void RunXNA() { RequireXna();