Switched to resources file; Added OptionsUI to Webservices Mod

This commit is contained in:
Yoshi Askharoun
2021-08-04 23:02:07 -05:00
parent f4eee476c2
commit ba28eb7ef7
7 changed files with 325 additions and 80 deletions
+73
View File
@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ZuneModCore {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ModResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ModResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ZuneModCore.ModResources", typeof(ModResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] WMVCORE {
get {
object obj = ResourceManager.GetObject("WMVCORE", resourceCulture);
return ((byte[])(obj));
}
}
}
}
+124
View File
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="WMVCORE" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\WMVCORE.DLL;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
+18 -16
View File
@@ -28,27 +28,27 @@ namespace ZuneModCore.Mods
// The ID is the name of the registry key, the label is the display name
new AbstractBooleanUIElement("Apps", "Apps"),
//new AbstractBooleanUIElement("Art", "Art"),
new AbstractBooleanUIElement("Art", "Art"),
new AbstractBooleanUIElement("Channels", "Channels"),
//new AbstractBooleanUIElement("FirstLaunchIntroVideo", "First Launch Intro Video"),
new AbstractBooleanUIElement("FirstLaunchIntroVideo", "First Launch Intro Video"),
new AbstractBooleanUIElement("Games", "Games"),
new AbstractBooleanUIElement("Marketplace", "Marketplace"),
//new AbstractBooleanUIElement("MBRPreview", "MBRPreview"),
//new AbstractBooleanUIElement("MBRPurchase", "MBRPurchase"),
//new AbstractBooleanUIElement("MBRRental", "MBRRental"),
new AbstractBooleanUIElement("MBRPreview", "[Marketplace] Media Preview"),
new AbstractBooleanUIElement("MBRPurchase", "[Marketplace] Media Purchase"),
new AbstractBooleanUIElement("MBRRental", "[Marketplace] Media Rental"),
new AbstractBooleanUIElement("Music", "Music"),
new AbstractBooleanUIElement("MusicVideos", "MusicVideos"),
new AbstractBooleanUIElement("MusicVideos", "Music Videos"),
new AbstractBooleanUIElement("Nowplaying", "Now Playing"),
//new AbstractBooleanUIElement("NowplayingArt", "Now Playing Art"),
new AbstractBooleanUIElement("NowplayingArt", "Now Playing Art"),
new AbstractBooleanUIElement("Picks", "Picks"),
new AbstractBooleanUIElement("Podcasts", "Podcasts"),
new AbstractBooleanUIElement("QuickMixLocal", "Quick Mix (Local)"),
//new AbstractBooleanUIElement("QuickMixZMP", "Quick Mix (ZMP)"),
new AbstractBooleanUIElement("QuickMixZMP", "Quick Mix (ZMP)"),
new AbstractBooleanUIElement("Quickplay", "Quickplay"),
//new AbstractBooleanUIElement("Sign In Available", "Sign In"),
new AbstractBooleanUIElement("Sign In Available", "Sign In"),
new AbstractBooleanUIElement("Social", "Social"),
//new AbstractBooleanUIElement("SocialMarketplace", "Social Marketplace"),
//new AbstractBooleanUIElement("SubscriptionFreeTracks", "Subscription Free Tracks"),
new AbstractBooleanUIElement("SocialMarketplace", "Social Marketplace"),
new AbstractBooleanUIElement("SubscriptionFreeTracks", "Subscription Free Tracks"),
new AbstractBooleanUIElement("Videos", "Videos"),
}
};
@@ -69,12 +69,14 @@ namespace ZuneModCore.Mods
return Task.CompletedTask;
}
public override async Task<string?> Apply()
public override async Task<string?> Apply() => await Apply(false);
public async Task<string?> Apply(bool applyAll = false)
{
// TODO: Use user choices from AbstractUI
// Use user choices from AbstractUI
foreach (AbstractUIElement uiElem in OptionsUI.Items)
{
if (uiElem is AbstractBooleanUIElement boolElem)// && boolElem.State)
if (uiElem is AbstractBooleanUIElement boolElem && (boolElem.State || applyAll))
{
bool isSuccess = SetFeatureOverride(boolElem.Id, true);
if (!isSuccess)
@@ -96,13 +98,13 @@ namespace ZuneModCore.Mods
return null;
}
public override Task<string?> Reset()
public override async Task<string?> Reset()
{
foreach (AbstractUIElement uiElem in OptionsUI.Items)
if (uiElem is AbstractBooleanUIElement boolElem)
ResetFeatureOverride(boolElem.Id);
return Task.FromResult<string?>(null);
return null;
}
public static bool SetFeatureOverride(string feature, bool value) =>
+8 -8
View File
@@ -26,7 +26,7 @@ namespace ZuneModCore.Mods
public override AbstractUIElementGroup? OptionsUI => null;
#pragma warning disable CA1416 // Validate platform compatibility
public override Task<string?> Apply()
public override async Task<string?> Apply()
{
// Make a backup of the original file
FileVersionInfo wmvDllVersionInfo = FileVersionInfo.GetVersionInfo(WMVCORE_PATH);
@@ -34,7 +34,7 @@ namespace ZuneModCore.Mods
File.Copy(WMVCORE_PATH, Path.Combine(StorageDirectory, "WMVCORE.original.dll"), true);
// Get the working WMVCORE.dll
string sourcePath = Path.Combine(AppContext.BaseDirectory, "Resources\\WMVCORE.dll");
byte[] wmvDllAniv = ModResources.WMVCORE;
// Get the original WMVCORE.dll
FileInfo wmvDllInfo = new(WMVCORE_PATH);
@@ -50,7 +50,7 @@ namespace ZuneModCore.Mods
FileSecurity security = wmvDllInfo.GetAccessControl();
SecurityIdentifier? cu = WindowsIdentity.GetCurrent().User;
if (cu == null)
return Task.FromResult<string?>("Failed to set permissions on WMVCORE.dll, current user was null");
return "Failed to set permissions on WMVCORE.dll, current user was null.";
// Set owner to current user
security.SetOwner(cu);
@@ -59,18 +59,18 @@ namespace ZuneModCore.Mods
// Update the Access Control on the original WMVCORE.dll
wmvDllInfo.SetAccessControl(security);
// Copy the pre-Anniversary Update WMVCORE.dll
File.Copy(sourcePath, WMVCORE_PATH, true);
// Replace with pre-Anniversary Update WMVCORE.dll
await File.WriteAllBytesAsync(wmvDllInfo.FullName, wmvDllAniv);
return Task.FromResult<string?>(null);
return null;
}
catch (IOException)
{
return Task.FromResult<string?>($"Unable to replace '{wmvDllInfo.FullName}'. Verify that Zune and Windows Media Player are not running and try again.");
return $"Unable to replace '{wmvDllInfo.FullName}'. Verify that Zune and Windows Media Player are not running and try again.";
}
catch (Exception ex)
{
return Task.FromResult(ex.Message)!;
return ex.Message;
}
}
#pragma warning restore CA1416 // Validate platform compatibility
+54 -16
View File
@@ -21,17 +21,28 @@ namespace ZuneModCore.Mods
public override string Author => "Joshua \"Yoshi\" Askharoun";
public override AbstractUIElementGroup? OptionsUI => null;
public override AbstractUIElementGroup? OptionsUI => new(nameof(FeaturesOverrideMod))
{
Title = string.Empty,
Items =
{
new AbstractTextBox("hostBox", "zunes.tk", "zune.net")
{
Title = "Host",
TooltipText = "The host where the replacement servers are located. Must be the same length as \"zune.net\"."
}
}
};
public override IReadOnlyList<Type>? DependentMods => null;
public override Task<string?> Apply()
public override async Task<string?> Apply()
{
// Verify that ZuneServices.dll exists
FileInfo zsDllInfo = new(Path.Combine(ZuneInstallDir, "ZuneService.dll"));
if (!zsDllInfo.Exists)
{
return Task.FromResult<string?>($"The file '{zsDllInfo.FullName}' does not exist.");
return $"The file '{zsDllInfo.FullName}' does not exist.";
}
// Make a backup if it doesn't already exist
@@ -53,17 +64,30 @@ namespace ZuneModCore.Mods
var versionBytes = zsDllReader.ReadBytes(6);
if (versionBytes[0] != '4' || versionBytes[2] != '.' || versionBytes[4] != '8')
{
return Task.FromResult<string?>("This mod has not been tested on versions earlier than 4.8.");
return "This mod has not been tested on versions earlier than 4.8.";
}
// Patch ZuneServices.dll to use zunes.tk instead of zune.net
// Get and validate replacement host
string oldHost = "zune.net";
string newHost = ((AbstractTextBox)OptionsUI!.Items[0]).Value;
if (newHost.Length != oldHost.Length)
{
return $"The new host (\"{newHost}\") must have the same length as \"{oldHost}\".";
}
var ping = await new System.Net.NetworkInformation.Ping().SendPingAsync(newHost);
if (ping.Status != System.Net.NetworkInformation.IPStatus.Success)
{
return $"Failed to reach \"{newHost}\". Ping status: {ping.Status}";
}
// Patch ZuneServices.dll to use the new host instead of zune.net
zsDllReader.BaseStream.Position = ZUNESERVICES_ENDPOINTS_BLOCK_OFFSET;
string endpointBlock = System.Text.Encoding.Unicode.GetString(zsDllReader.ReadBytes(ZUNESERVICES_ENDPOINTS_BLOCK_LENGTH));
endpointBlock = endpointBlock.Replace("zune.net", "zunes.tk");
endpointBlock = endpointBlock.Replace(oldHost, newHost);
byte[] endpointBytes = System.Text.Encoding.Unicode.GetBytes(endpointBlock);
if (endpointBytes.Length != ZUNESERVICES_ENDPOINTS_BLOCK_LENGTH)
{
return Task.FromResult<string?>("Failed to safely overwrite strings in DLL.");
return "Failed to safely overwrite strings in DLL.";
}
zsDllWriter.Seek(ZUNESERVICES_ENDPOINTS_BLOCK_OFFSET, SeekOrigin.Begin);
zsDllWriter.Write(endpointBytes);
@@ -75,29 +99,36 @@ namespace ZuneModCore.Mods
setOverrideSuccess &= SetFeatureOverride("Channels", true);
setOverrideSuccess &= SetFeatureOverride("Games", true);
setOverrideSuccess &= SetFeatureOverride("Marketplace", true);
setOverrideSuccess &= SetFeatureOverride("MBRPreview", true);
setOverrideSuccess &= SetFeatureOverride("MBRPurchase", true);
setOverrideSuccess &= SetFeatureOverride("MBRRental", true);
setOverrideSuccess &= SetFeatureOverride("Music", true);
setOverrideSuccess &= SetFeatureOverride("MusicVideos", true);
setOverrideSuccess &= SetFeatureOverride("Picks", true);
setOverrideSuccess &= SetFeatureOverride("Podcasts", true);
setOverrideSuccess &= SetFeatureOverride("Sign In Available", true);
setOverrideSuccess &= SetFeatureOverride("Social", true);
setOverrideSuccess &= SetFeatureOverride("SocialMarketplace", true);
setOverrideSuccess &= SetFeatureOverride("SubscriptionFreeTracks", true);
setOverrideSuccess &= SetFeatureOverride("Videos", true);
if (setOverrideSuccess != true)
{
return Task.FromResult<string?>("Unable to set feature overrides. The mod was successful, but you may not be able to see it in the Zune Software.");
return "Unable to set feature overrides. The mod was successful, but you may not be able to see it in the Zune Software.";
}
return Task.FromResult<string?>(null);
return null;
}
catch (IOException)
{
return Task.FromResult<string?>($"Unable to replace '{zsDllInfo.FullName}'. Verify that the Zune software is not running and try again.");
return $"Unable to replace '{zsDllInfo.FullName}'. Verify that the Zune software is not running and try again.";
}
catch (Exception ex)
{
return Task.FromResult<string?>(ex.Message);
return ex.Message;
}
}
public override Task<string?> Reset()
public override async Task<string?> Reset()
{
string zsDllPath = Path.Combine(ZuneInstallDir, "ZuneService.dll");
try
@@ -111,25 +142,32 @@ namespace ZuneModCore.Mods
setOverrideSuccess &= SetFeatureOverride("Channels", false);
setOverrideSuccess &= SetFeatureOverride("Games", false);
setOverrideSuccess &= SetFeatureOverride("Marketplace", false);
setOverrideSuccess &= SetFeatureOverride("MBRPreview", false);
setOverrideSuccess &= SetFeatureOverride("MBRPurchase", false);
setOverrideSuccess &= SetFeatureOverride("MBRRental", false);
setOverrideSuccess &= SetFeatureOverride("Music", false);
setOverrideSuccess &= SetFeatureOverride("MusicVideos", false);
setOverrideSuccess &= SetFeatureOverride("Picks", false);
setOverrideSuccess &= SetFeatureOverride("Podcasts", false);
setOverrideSuccess &= SetFeatureOverride("Sign In Available", false);
setOverrideSuccess &= SetFeatureOverride("Social", false);
setOverrideSuccess &= SetFeatureOverride("SocialMarketplace", false);
setOverrideSuccess &= SetFeatureOverride("SubscriptionFreeTracks", false);
setOverrideSuccess &= SetFeatureOverride("Videos", false);
if (setOverrideSuccess != true)
{
return Task.FromResult<string?>("Unable to reset feature overrides. The mod was successfully removed, but you may still be able to see it in the Zune Software.");
return "Unable to reset feature overrides. The mod was successfully removed, but you may still be able to see it in the Zune Software.";
}
return Task.FromResult<string?>(null);
return null;
}
catch (IOException)
{
return Task.FromResult<string?>($"Unable to replace '{zsDllPath}'. Verify that the Zune software is not running and try again.");
return $"Unable to replace '{zsDllPath}'. Verify that the Zune software is not running and try again.";
}
catch (Exception ex)
{
return Task.FromResult<string?>(ex.Message);
return ex.Message;
}
}
}
+16 -5
View File
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
@@ -9,15 +9,26 @@
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="OwlCore" Version="0.0.6" />
<PackageReference Include="OwlCore" Version="0.0.21" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="TagLibSharp" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="Resources\WMVCORE.DLL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<EmbeddedResource Update="ModResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ModResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="ModResources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ModResources.resx</DependentUpon>
</Compile>
<None Update="Resources\WMVCORE.DLL">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>