Commit 5a1a4d96 authored by Jason Williams's avatar Jason Williams Committed by GitHub
Browse files

Merge pull request #122 from WilliamsJason/master

Re-adding TestAppXbox as Samples/XboxWdpDriver
parents 05bfd5fd 6e8688de
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
</configuration>
 No newline at end of file
+204 −0
Original line number Diff line number Diff line
//----------------------------------------------------------------------------------------------
// <copyright file="DevicePortalConnection.cs" company="Microsoft Corporation">
//     Licensed under the MIT License. See LICENSE.TXT in the project root license information.
// </copyright>
//----------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using Microsoft.Tools.WindowsDevicePortal;
using Windows.Security.Credentials;
using static Microsoft.Tools.WindowsDevicePortal.DevicePortal;

namespace XboxWdpDriver
{
    /// <summary>
    /// IDevicePortalConnection implementation for Xbox test project
    /// </summary>
    public class DevicePortalConnection : IDevicePortalConnection
    {
        /// <summary>
        /// Device Certificate
        /// </summary>
        private X509Certificate2 deviceCertificate = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalConnection"/> class.
        /// </summary>
        /// <param name="address">The ip address or hostname of the device we are connecting to.</param>
        /// <param name="userName">The WDP username.</param>
        /// <param name="password">The WDP password.</param>
        public DevicePortalConnection(
            string address,
            string userName,
            string password)
        {
            this.Connection = new Uri(string.Format("https://{0}:11443", address));
            this.Credentials = new NetworkCredential(userName, password);

            PasswordVault vault = new PasswordVault();

            try
            {
                // Remove any existing stored creds for this address and add these ones.
                foreach (var cred in vault.FindAllByResource(address))
                {
                    vault.Remove(cred);
                }
            }
            catch (Exception)
            {
                // Do nothing. This is expected if no credentials have been previously stored
            }

            vault.Add(new PasswordCredential(address, userName, password));
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalConnection"/> class.
        /// This version of the contructor can be used if WDP credentials are not provided,
        /// and should be used if they were previously persisted or are not needed.
        /// </summary>
        /// <param name="address">The ip address or hostname of the device we are connecting to.</param>
        public DevicePortalConnection(
            string address)
        {
            this.Connection = new Uri(string.Format("https://{0}:11443", address));

            try
            {
                PasswordVault vault = new PasswordVault();
                // Set the first stored cred as our network creds.
                IReadOnlyList<PasswordCredential> creds = vault.FindAllByResource(address);
                if (creds != null && creds.Count > 0)
                {
                    creds[0].RetrievePassword();
                    this.Credentials = new NetworkCredential(creds[0].UserName, creds[0].Password);
                }
            }
            catch (Exception)
            {
                // Do nothing. No credentials were stored. If they are needed, REST calls will fail with Unauthorized.
            }
        }

        /// <summary>
        /// Gets Connection property
        /// </summary>
        public Uri Connection
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets Web Socket Connection property
        /// </summary>
        public Uri WebSocketConnection
        {
            get
            {
                if (this.Connection == null)
                {
                    return null;
                }

                string absoluteUri = this.Connection.AbsoluteUri;

                if (absoluteUri.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    return new Uri(Regex.Replace(absoluteUri, "https", "wss", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));
                }
                else
                {
                    return new Uri(Regex.Replace(absoluteUri, "http", "ws", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));
                }
            }
        }

        /// <summary>
        /// Gets Credentials property
        /// </summary>
        public NetworkCredential Credentials
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets device family
        /// </summary>
        public string Family
        { 
            get; 
            set;
        }

        /// <summary>
        /// Gets or sets the device name
        /// </summary>
        public string Name
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets device OS Info
        /// </summary>
        public OperatingSystemInformation OsInfo
        {
            get;
            set;
        }

        /// <summary>
        /// Returns certificate data
        /// </summary>
        /// <returns>certificate data</returns>
        public byte[] GetDeviceCertificateData()
        {
            return this.deviceCertificate.GetRawCertData();
        }

        /// <summary>
        /// Validates and sets the device certificate.
        /// </summary>
        /// <param name="certificate">The device's root certificate.</param>
        public void SetDeviceCertificate(X509Certificate2 certificate)
        {
            if (!certificate.IssuerName.Name.Contains(DevicePortalCertificateIssuer))
            {
                throw new DevicePortalException(
                    (HttpStatusCode)0,
                    "Invalid certificate issuer",
                    null,
                    "Failed to download device certificate");
            }

            this.deviceCertificate = certificate;
        }

        /// <summary>
        /// Xbox will never update the connection.
        /// </summary>
        /// <param name="requiresHttps">https required</param>
        public void UpdateConnection(bool requiresHttps)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///  Xbox will never update the connection.
        /// </summary>
        /// <param name="ipConfig">IP info</param>
        /// <param name="requiresHttps">https required</param>
        public void UpdateConnection(IpConfiguration ipConfig, bool requiresHttps)
        {
            throw new NotImplementedException();
        }
    }
}
+140 −0
Original line number Diff line number Diff line
//----------------------------------------------------------------------------------------------
// <copyright file="NetworkShare.cs" company="Microsoft Corporation">
//     Licensed under the MIT License. See LICENSE.TXT in the project root license information.
// </copyright>
//----------------------------------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;

namespace XboxWdpDriver
{
    /// <summary>
    /// Helper class for connecting to Network Shares
    /// </summary>
    public static class NetworkShare
    {
        /// <summary>
        /// Resource type constant value.
        /// </summary>
        private const int ResourceTypeDisk = 0x00000001;

        /// <summary>
        /// Connects to the remote share
        /// </summary>
        /// <param name="uri">The URI for the network share.</param>
        /// <param name="username">The username for accessing the share.</param>
        /// <param name="password">The password for accessing the share.</param>
        /// <returns>Result of the connection, 0 for success.</returns>
        public static int ConnectToShare(string uri, string username, string password)
        {
            //Create netresource and point it at the share
            NETRESOURCE nr;

            nr.Scope = 0;
            nr.Type = ResourceTypeDisk;
            nr.DisplayType = 0;
            nr.Usage = 0;
            nr.LocalName = string.Empty;
            nr.RemoteName = uri;
            nr.Comment = string.Empty;
            nr.Provider = string.Empty;

            // Create the share
            return WNetUseConnection(IntPtr.Zero, ref nr, password, username, 0, null, null, null);
        }

        /// <summary>
        /// Remove the share from cache.
        /// </summary>
        /// <param name="uri">The URI for the network share.</param>
        /// <param name="force">Whether to force the disconnect.</param>
        /// <returns>Result of the connection, 0 for success.</returns>
        public static int DisconnectFromShare(string uri, bool force)
        {
            //remove the share
            return WNetCancelConnection(uri, force);
        }

        /// <summary>
        /// Makes a connection to a network resource.
        /// </summary>
        /// <param name="handleToOwner">Handle to a window that the provider of network resources can use as an owner window for dialog boxes.</param>
        /// <param name="netResource">Pointer to a NETRESOURCE structure that specifies details of the proposed connection. </param>
        /// <param name="password">Pointer to a constant null-terminated string that specifies a password to be used in making the network connection. </param>
        /// <param name="userName">Pointer to a constant null-terminated string that specifies a user name for making the connection. </param>
        /// <param name="flags">Set of bit flags describing the connection.</param>
        /// <param name="accessName">Pointer to a buffer that receives system requests on the connection.</param>
        /// <param name="bufferSize">Pointer to a variable that specifies the size of the lpAccessName buffer, in characters.</param>
        /// <param name="result">Pointer to a variable that receives additional information about the connection.</param>
        /// <returns>If the function succeeds, the return value is 0.</returns>
        [DllImport("Mpr.dll")]
        private static extern int WNetUseConnection(
            IntPtr handleToOwner,
            ref NETRESOURCE netResource,
            string password,
            string userName,
            int flags,
            string accessName,
            string bufferSize,
            string result);

        /// <summary>
        /// Cancels an existing network connection.
        /// </summary>
        /// <param name="uri">Pointer to a constant null-terminated string that specifies the name of either the redirected local device or the remote network resource to disconnect from. </param>
        /// <param name="shouldForce">Specifies whether or not the disconnection should occur if there are open files or jobs on the connection.</param>
        /// <returns>If the function succeeds, the return value is 0.</returns>
        [DllImport("Mpr.dll")]
        private static extern int WNetCancelConnection(
            string uri,
            bool shouldForce);

        /// <summary>
        /// Specifies details of a proposed network connection.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct NETRESOURCE
        {
            /// <summary>
            /// Specifies the scope of the resource to connect to. Unused in the wrapper.
            /// </summary>
            public int Scope;

            /// <summary>
            /// Specifies the type of resource to connect to.
            /// </summary>
            public int Type;

            /// <summary>
            /// Specifies the display type of resource to connect to. Unused in the wrapper.
            /// </summary>
            public int DisplayType;

            /// <summary>
            /// Specifies the usage of resource to connect to. Unused in the wrapper.
            /// </summary>
            public int Usage;

            /// <summary>
            /// Specifies the local name of resource to connect to. Unused in the wrapper.
            /// </summary>
            public string LocalName;

            /// <summary>
            /// Specifies the remote name of resource to connect to.
            /// </summary>
            public string RemoteName;

            /// <summary>
            /// Specifies a comment about the connection. Unused in the wrapper.
            /// </summary>
            public string Comment;

            /// <summary>
            /// Specifies the provider. Unused in the wrapper.
            /// </summary>
            public string Provider;
        }
    }
}
 No newline at end of file
+77 −0
Original line number Diff line number Diff line
//----------------------------------------------------------------------------------------------
// <copyright file="ConfigOperation.cs" company="Microsoft Corporation">
//     Licensed under the MIT License. See LICENSE.TXT in the project root license information.
// </copyright>
//----------------------------------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using Microsoft.Tools.WindowsDevicePortal;
using static Microsoft.Tools.WindowsDevicePortal.DevicePortal;

namespace XboxWdpDriver
{
    /// <summary>
    /// Helper for Config related operations
    /// </summary>
    public class ConfigOperation
    {
        /// <summary>
        /// Usage message for this operation
        /// </summary>
        private const string ConfigUsageMessage = "Usage:\n" +
            "  [/setting:<setting name> [/value:<setting value>]]\n" +
            "        Gets current settings and their values. If\n" +
            "        /setting is specified, only returns that value.\n" +
            "        If /value is also specified, sets the settting to\n" +
            "        that value instead of returning the current\n" +
            "        value.\n";

        /// <summary>
        /// Main entry point for handling a Config operation
        /// </summary>
        /// <param name="portal">DevicePortal reference for communicating with the device.</param>
        /// <param name="parameters">Parsed command line parameters.</param>
        public static void HandleOperation(DevicePortal portal, ParameterHelper parameters)
        {
            if (parameters.HasFlag(ParameterHelper.HelpFlag))
            {
                Console.WriteLine(ConfigUsageMessage);
                return;
            }

            string desiredSetting = parameters.GetParameterValue("setting");
            string desiredValue = parameters.GetParameterValue("value");

            // Determine if this is for all settings or a single setting.
            if (string.IsNullOrWhiteSpace(desiredSetting))
            {
                Task<XboxSettingList> getSettingsTask = portal.GetXboxSettings();
                getSettingsTask.Wait();

                Console.WriteLine(getSettingsTask.Result);
            }
            else
            {
                if (string.IsNullOrWhiteSpace(desiredValue))
                {
                    Task<XboxSetting> getSettingTask = portal.GetXboxSetting(desiredSetting);
                    getSettingTask.Wait();

                    Console.WriteLine(getSettingTask.Result);
                }
                else
                {
                    XboxSetting setting = new XboxSetting();
                    setting.Name = desiredSetting;
                    setting.Value = desiredValue;

                    Task<XboxSetting> setSettingTask = portal.UpdateXboxSetting(setting);
                    setSettingTask.Wait();

                    Console.WriteLine(setSettingTask.Result);
                }
            }
        }
    }
}
 No newline at end of file
+114 −0
Original line number Diff line number Diff line
//----------------------------------------------------------------------------------------------
// <copyright file="FiddlerOperation.cs" company="Microsoft Corporation">
//     Licensed under the MIT License. See LICENSE.TXT in the project root license information.
// </copyright>
//----------------------------------------------------------------------------------------------

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Tools.WindowsDevicePortal;

namespace XboxWdpDriver
{
    /// <summary>
    /// Helper for Fiddler related operations
    /// </summary>
    public class FiddlerOperation
    {
        /// <summary>
        /// Usage message for this operation
        /// </summary>
        private const string FiddlerUsageMessage = "Usage:\n" +
            "  /state:<on or off> [/reboot] [/proxyaddress:<proxy address> /proxyport:<proxy port> /certpath:<path to cert file>]\n" +
            "        Whether to enable or disable Fiddler. Enabling and disabling Fiddler\n" +
            "        requires a reboot. You can specify the /reboot flag to do the reboot\n" +
            "        automatically. If Fiddler is being enabled, proxyaddress and proxyport\n" +
            "        are both required. If Fiddler has not been configured on this console\n" +
            "        previously, then the cert file is also required.";

        /// <summary>
        /// Main entry point for handling a Fiddler operation
        /// </summary>
        /// <param name="portal">DevicePortal reference for communicating with the device.</param>
        /// <param name="parameters">Parsed command line parameters.</param>
        public static void HandleOperation(DevicePortal portal, ParameterHelper parameters)
        {
            if (parameters.HasFlag(ParameterHelper.HelpFlag))
            {
                Console.WriteLine(FiddlerUsageMessage);
                return;
            }

            string state = parameters.GetParameterValue("state");

            if (string.IsNullOrEmpty(state))
            {
                Console.WriteLine("/state parameter is required.");
                Console.WriteLine();
                Console.WriteLine(FiddlerUsageMessage);
                return;
            }

            try
            {
                if (string.Equals(state, "on", StringComparison.OrdinalIgnoreCase))
                {
                    string proxyAddress = parameters.GetParameterValue("proxyaddress");
                    string proxyPort = parameters.GetParameterValue("proxyport");

                    if (string.IsNullOrEmpty(proxyAddress) || string.IsNullOrEmpty(proxyPort))
                    {
                        Console.WriteLine("/proxyaddress and /proxyport are required for enabling Fiddler.");
                        Console.WriteLine();
                        Console.WriteLine(FiddlerUsageMessage);
                        return;
                    }

                    Task fiddlerEnableTask = portal.EnableFiddlerTracing(proxyAddress, proxyPort, parameters.GetParameterValue("certpath"));
                    fiddlerEnableTask.Wait();
                    Console.WriteLine("Fiddler enabled.");
                }
                else if (string.Equals(state, "off", StringComparison.OrdinalIgnoreCase))
                {
                    Task fiddlerDisableTask = portal.DisableFiddlerTracing();
                    fiddlerDisableTask.Wait();
                    Console.WriteLine("Fiddler disabled.");
                }
                else
                {
                    Console.WriteLine("Unknown state parameter: {0}. Must be 'on' or 'off'.", state);
                    Console.WriteLine();
                    Console.WriteLine(FiddlerUsageMessage);
                    return;
                }

                if (parameters.HasFlag("reboot"))
                {
                    Task rebootTask = portal.Reboot();
                    rebootTask.Wait();
                    Console.WriteLine("Console rebooting...");
                }
                else
                {
                    Console.WriteLine("A reboot is required before this takes effect.");
                }
            }
            catch (AggregateException e)
            {
                if (e.InnerException is DevicePortalException)
                {
                    DevicePortalException innerException = e.InnerException as DevicePortalException;

                    Console.WriteLine(string.Format("Exception encountered: {0}, hr = 0x{1:X} : {2}", innerException.StatusCode, innerException.HResult, innerException.Reason));
                }
                else
                {
                    Console.WriteLine(string.Format("Unexpected exception encountered: {0}", e.Message));
                }

                return;
            }
        }
    }
}
 No newline at end of file
Loading