Added initial version of Win11 driver fix

This commit is contained in:
Yoshi Askharoun
2022-08-16 12:27:48 -05:00
parent df45dba6e6
commit 6de33b4e84
3 changed files with 172 additions and 13 deletions
+2 -2
View File
@@ -3,7 +3,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using ZuneModCore.Mods;
namespace ZuneModCore
@@ -15,8 +14,9 @@ namespace ZuneModCore
/// </summary>
public static readonly IReadOnlyList<Mod> AvailableMods = new List<Mod>
{
new FeaturesOverrideMod(),
new VideoSyncMod(),
new Win11DriverMod(),
new FeaturesOverrideMod(),
new WebservicesMod(),
new BackgroundImageMod(),
new MbidLocatorMod(),
+153
View File
@@ -0,0 +1,153 @@
using CommunityToolkit.Diagnostics;
using OwlCore.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace ZuneModCore.Mods
{
public class Win11DriverMod : Mod
{
public override string Id => nameof(Win11DriverMod);
public override string Title => "Fix Zune Drivers for Windows 11";
public override string Description => "Resolves the \"This operation requires an interactive window station\" error " +
"when attempting to install the Zune device drivers on Windows 11.";
public override string Author => "ส็็็Codix#4833 and Joshua \"Yoshi\" Askharoun";
public override IReadOnlyList<ModDependency>? DependentMods => null;
protected override async Task<string?> ApplyCore()
{
if (Environment.OSVersion.Platform != PlatformID.Win32NT
|| Environment.OSVersion.Version < new Version(10, 0, 22000, 0))
return "This mod is intended only for Windows 11 or later.";
const string MuiFilename = "ZuneCoInst.dll.mui";
string srcDriverDir = Path.Combine(ModManager.ZuneInstallDir, "Drivers", "Zune");
string driverFilePath = Path.Combine(srcDriverDir, "Zune.inf");
string dstDriverRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "System32");
string installScriptPath = Path.Combine(StorageDirectory, "install.bat");
try
{
// Remove the old broken driver, if it was installed
ProcessStartInfo startInfo = new("pnputil", "/enum-drivers")
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
};
Process enumProc = new()
{
StartInfo = startInfo
};
// Redirect standard output to get data
string? zuneInfPublishedName = null;
string? enumDriversPreviousLine = null;
Regex rx = new(@"^\s*[\w ]+:\s+zune\.inf$", RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
enumProc.Start();
while (!enumProc.StandardOutput.EndOfStream)
{
string? currentLine = await enumProc.StandardOutput.ReadLineAsync();
Debug.WriteLine(currentLine);
if (enumDriversPreviousLine != null && currentLine != null
&& rx.IsMatch(currentLine) && enumDriversPreviousLine.EndsWith(".inf"))
{
// Found the "Published Name" and "Original Name" lines
int idx = enumDriversPreviousLine.LastIndexOf(' ');
zuneInfPublishedName = enumDriversPreviousLine[idx..].Trim();
}
enumDriversPreviousLine = currentLine;
}
await enumProc.WaitForExitAsync();
//if (zuneInfPublishedName != null)
//{
// // There may be a corrupted driver from previous attempts,
// // removing it before installing brings better results
// startInfo.Arguments = $"/delete-driver {zuneInfPublishedName} /uninstall";
// Process deleteProc = new()
// {
// StartInfo = startInfo
// };
// deleteProc.Start();
// while (!deleteProc.StandardOutput.EndOfStream)
// {
// string? currentLine = await deleteProc.StandardOutput.ReadLineAsync();
// Debug.WriteLine(currentLine);
// }
// await deleteProc.WaitForExitAsync();
//}
// Copy all .dll.mui files, then install the driver.
// This loop generates a batch script that can run as TrustedInstaller
// to copy all the necessary files to System32. If we don't run this
// as TI, we'll still get the "interactive window station" error
// when attempting to install the driver.
using (var installScript = File.CreateText(installScriptPath))
{
await installScript.WriteLineAsync($"pnputil /delete-driver {zuneInfPublishedName} /uninstall");
foreach (string localeDir in Directory.GetDirectories(srcDriverDir))
{
string locale = Path.GetFileName(localeDir);
if (locale == null || locale.Length != 5 || locale[2] != '-')
continue;
FileInfo srcDriver = new(Path.Combine(localeDir, MuiFilename));
FileInfo dstDriver = new(Path.Combine(dstDriverRoot, locale, MuiFilename));
await installScript.WriteLineAsync($"del \"{dstDriver.FullName}\"");
await installScript.WriteLineAsync($"copy \"{srcDriver.FullName}\" \"{dstDriver.FullName}\"");
}
await installScript.WriteLineAsync($"pnputil /add-driver \"{driverFilePath}\" /install");
await installScript.WriteLineAsync("echo \"Script complete. If there are any errors reported above, " +
"please note them and file a report at https://github.com/ZuneDev/ZuneModdingHelper/issues/new\"");
}
// Set up ExecTI
var tiSvc = Win32.ExecTI.StartTrustedInstallerService();
// Manually copy files and install the driver
string? installErrorMsg = null;
using (var procInfo = Win32.ExecTI.CreateProcessAsTrustedInstaller(tiSvc, $"cmd /k {installScriptPath}"))
{
Debug.WriteLine(procInfo.hProcess.DangerousGetHandle().ToString("X"));
Process installProc = Process.GetProcessById(unchecked((int)procInfo!.dwProcessId));
await installProc.WaitForExitAsync();
if (Vanara.PInvoke.Kernel32.GetExitCodeProcess(procInfo.hProcess, out var exitCode)
&& (exitCode != 0 || exitCode != 0xc000013A))
installErrorMsg = "An unknown error occurred while attempting to install driver.";
//Vanara.PInvoke.Kernel32.CloseHandle(procInfo.hProcess.DangerousGetHandle());
}
return installErrorMsg;
}
catch (Exception ex)
{
return ex.ToString();
}
}
protected override Task<string?> ResetCore()
{
throw new NotImplementedException();
}
}
}
+17 -11
View File
@@ -34,17 +34,17 @@ namespace ZuneModCore.Win32
}
else
{
CloseHandle(hSnapshot.DangerousGetHandle());
CloseHandle(hSnapshot.DangerousGetHandle(), nameof(hSnapshot));
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
if (unchecked((int)pid) == -1)
{
CloseHandle(hSnapshot.DangerousGetHandle());
CloseHandle(hSnapshot.DangerousGetHandle(), nameof(hSnapshot));
throw new Exception("Process not found: " + processName);
}
CloseHandle(hSnapshot.DangerousGetHandle());
CloseHandle(hSnapshot.DangerousGetHandle(), nameof(hSnapshot));
return pid;
}
@@ -120,7 +120,7 @@ namespace ZuneModCore.Win32
(TokenAccess)MAXIMUM_ALLOWED,
out var hSystemToken))
{
CloseHandle(hSystemProcess.DangerousGetHandle());
CloseHandle(hSystemProcess.DangerousGetHandle(), nameof(hSystemProcess));
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
@@ -137,19 +137,19 @@ namespace ZuneModCore.Win32
TOKEN_TYPE.TokenImpersonation,
out var hDupToken))
{
CloseHandle(hSystemToken.DangerousGetHandle());
CloseHandle(hSystemToken.DangerousGetHandle(), nameof(hSystemToken));
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
if (!ImpersonateLoggedOnUser(hDupToken))
{
CloseHandle(hDupToken.DangerousGetHandle());
CloseHandle(hSystemToken.DangerousGetHandle());
CloseHandle(hDupToken.DangerousGetHandle(), nameof(hDupToken));
CloseHandle(hSystemToken.DangerousGetHandle(), nameof(hSystemToken));
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
CloseHandle(hDupToken.DangerousGetHandle());
CloseHandle(hSystemToken.DangerousGetHandle());
CloseHandle(hDupToken.DangerousGetHandle(), nameof(hDupToken));
CloseHandle(hSystemToken.DangerousGetHandle(), nameof(hSystemToken));
}
public static SafePROCESS_INFORMATION? CreateProcessAsTrustedInstaller(uint pid, string commandLine)
@@ -170,7 +170,7 @@ namespace ZuneModCore.Win32
TokenAccess.TOKEN_ALL_ACCESS,
out var hTIToken))
{
CloseHandle(hTIProcess.DangerousGetHandle());
CloseHandle(hTIProcess.DangerousGetHandle(), nameof(hTIProcess));
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
@@ -187,7 +187,7 @@ namespace ZuneModCore.Win32
TOKEN_TYPE.TokenImpersonation,
out var hDupToken))
{
CloseHandle(hTIToken.DangerousGetHandle());
CloseHandle(hTIToken.DangerousGetHandle(), nameof(hTIToken));
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
@@ -211,5 +211,11 @@ namespace ZuneModCore.Win32
return processInfo;
}
private static void CloseHandle(IntPtr hObject, string name)
{
System.Diagnostics.Debug.WriteLine($"{name} = {hObject:X}");
Kernel32.CloseHandle(hObject);
}
}
}