Vanara/PInvoke/WcmApi/WcmApi.cs

1007 lines
41 KiB
C#

using System;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace Vanara.PInvoke
{
/// <summary>Functions, structures and constants from wcmapi.h.</summary>
public static partial class WcmApi
{
/// <summary>The highest version of the Wi-Fi Direct API the client supports.</summary>
public const uint WCM_UNKNOWN_DATAPLAN_STATUS = uint.MaxValue;
/// <summary>The <c>WCM_CONNECTION_COST</c> enumerated type determines the connection cost type and flags.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ne-wcmapi-wcm_connection_cost typedef enum _WCM_CONNECTION_COST {
// WCM_CONNECTION_COST_UNKNOWN, WCM_CONNECTION_COST_UNRESTRICTED, WCM_CONNECTION_COST_FIXED, WCM_CONNECTION_COST_VARIABLE,
// WCM_CONNECTION_COST_OVERDATALIMIT, WCM_CONNECTION_COST_CONGESTED, WCM_CONNECTION_COST_ROAMING,
// WCM_CONNECTION_COST_APPROACHINGDATALIMIT } WCM_CONNECTION_COST, *PWCM_CONNECTION_COST;
[PInvokeData("wcmapi.h", MSDNShortId = "1ab36082-3394-42e3-aee3-01df5e211ba7")]
[Flags]
public enum WCM_CONNECTION_COST
{
/// <summary>Connection cost information is not available.</summary>
WCM_CONNECTION_COST_UNKNOWN = 0x0,
/// <summary>The connection is unlimited and has unrestricted usage constraints.</summary>
WCM_CONNECTION_COST_UNRESTRICTED = 0x1,
/// <summary>Usage counts toward a fixed allotment of data which the user has already paid for (or agreed to pay for).</summary>
WCM_CONNECTION_COST_FIXED = 0x2,
/// <summary>The connection cost is on a per-byte basis.</summary>
WCM_CONNECTION_COST_VARIABLE = 0x4,
/// <summary>The connection has exceeded its data limit.</summary>
WCM_CONNECTION_COST_OVERDATALIMIT = 0x10000,
/// <summary>The connection is throttled due to high traffic.</summary>
WCM_CONNECTION_COST_CONGESTED = 0x20000,
/// <summary>The connection is outside of the home network.</summary>
WCM_CONNECTION_COST_ROAMING = 0x40000,
/// <summary>The connection is approaching its data limit.</summary>
WCM_CONNECTION_COST_APPROACHINGDATALIMIT = 0x80000,
}
/// <summary>The <c>WCM_CONNECTION_COST_SOURCE</c> enumerated type specifies the source that provides connection cost information.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ne-wcmapi-wcm_connection_cost_source typedef enum
// _WCM_CONNECTION_COST_SOURCE { WCM_CONNECTION_COST_SOURCE_DEFAULT, WCM_CONNECTION_COST_SOURCE_GP, WCM_CONNECTION_COST_SOURCE_USER,
// WCM_CONNECTION_COST_SOURCE_OPERATOR } WCM_CONNECTION_COST_SOURCE, *PWCM_CONNECTION_COST_SOURCE;
[PInvokeData("wcmapi.h", MSDNShortId = "cd9e5562-dd50-46fc-be11-0ea89e6933c0")]
public enum WCM_CONNECTION_COST_SOURCE
{
/// <summary>Default source.</summary>
WCM_CONNECTION_COST_SOURCE_DEFAULT,
/// <summary>The source for the connection cost is Group Policy.</summary>
WCM_CONNECTION_COST_SOURCE_GP,
/// <summary>The source for the connection cost is the user.</summary>
WCM_CONNECTION_COST_SOURCE_USER,
/// <summary>The source for the connection cost is the operator.</summary>
WCM_CONNECTION_COST_SOURCE_OPERATOR,
}
/// <summary>The <c>WCM_MEDIA_TYPE</c> enumerated type specifies the type of media for a connection.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ne-wcmapi-wcm_media_type typedef enum _WCM_MEDIA_TYPE {
// wcm_media_unknown, wcm_media_ethernet, wcm_media_wlan, wcm_media_mbn, wcm_media_invalid, wcm_media_max } WCM_MEDIA_TYPE, *PWCM_MEDIA_TYPE;
[PInvokeData("wcmapi.h", MSDNShortId = "76617f35-c7a1-49ff-a630-482f2fe45dd7")]
public enum WCM_MEDIA_TYPE
{
/// <summary>Unknown media.</summary>
wcm_media_unknown,
/// <summary>Ethernet.</summary>
wcm_media_ethernet,
/// <summary>WLAN.</summary>
wcm_media_wlan,
/// <summary>Mobile broadband.</summary>
wcm_media_mbn,
/// <summary>Invalid type.</summary>
wcm_media_invalid,
/// <summary>Maximum value for testing purposes.</summary>
wcm_media_max,
}
/// <summary>The <c>WCM_PROPERTY</c> enumerated type specifies a property of a connection.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ne-wcmapi-wcm_property typedef enum _WCM_PROPERTY {
// wcm_global_property_domain_policy, wcm_global_property_minimize_policy, wcm_global_property_roaming_policy,
// wcm_global_property_powermanagement_policy, wcm_intf_property_connection_cost, wcm_intf_property_dataplan_status,
// wcm_intf_property_hotspot_profile } WCM_PROPERTY, *PWCM_PROPERTY;
[PInvokeData("wcmapi.h", MSDNShortId = "4cb5f7aa-2f06-4a8a-814d-f8e01b496fb9")]
public enum WCM_PROPERTY
{
/// <summary>Domain policy.</summary>
[CorrespondingType(typeof(WCM_POLICY_VALUE))]
wcm_global_property_domain_policy,
/// <summary>Minimize policy.</summary>
[CorrespondingType(typeof(WCM_POLICY_VALUE))]
wcm_global_property_minimize_policy,
/// <summary>Roaming policy.</summary>
[CorrespondingType(typeof(WCM_POLICY_VALUE))]
wcm_global_property_roaming_policy,
/// <summary>Power management policy.</summary>
[CorrespondingType(typeof(WCM_POLICY_VALUE))]
wcm_global_property_powermanagement_policy,
/// <summary>The cost level and flags for the connection</summary>
[CorrespondingType(typeof(WCM_CONNECTION_COST_DATA))]
wcm_intf_property_connection_cost,
/// <summary>The plan data associated with the new cost.</summary>
[CorrespondingType(typeof(WCM_DATAPLAN_STATUS))]
wcm_intf_property_dataplan_status,
/// <summary>The hotspot profile.</summary>
[CorrespondingType(typeof(string))]
wcm_intf_property_hotspot_profile,
}
/// <summary>The <c>WcmFreeMemory</c> function is used to release memory resources allocated by the WCM functions.</summary>
/// <param name="pMemory">Pointer to the memory to be freed.</param>
/// <returns>This function does not return a value.</returns>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmfreememory void WcmFreeMemory( __deallocate(Mem)PVOID
// pMemory );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "43377f58-9702-472d-874a-898f29b743d8")]
public static extern void WcmFreeMemory(IntPtr pMemory);
/// <summary>
/// The <c>WcmGetProfileList</c> function retrieves a list of profiles in preferred order, descending from the most preferred to the
/// least preferred. The list includes all WCM-managed auto-connect profiles across all WCM-managed media types.
/// </summary>
/// <param name="pReserved">
/// <para>Type: <c>PVOID</c></para>
/// <para>Reserved.</para>
/// </param>
/// <param name="ppProfileList">
/// <para>Type: <c>PWCM_PROFILE_INFO_LIST*</c></para>
/// <para>The list of profiles.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmgetprofilelist DWORD WcmGetProfileList( PVOID pReserved,
// WCM_PROFILE_INFO_LIST **ppProfileList );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "ceef4e74-3c67-4267-a82a-9912c039f41c")]
public static extern Win32Error WcmGetProfileList([Optional] IntPtr pReserved,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(WcmMarshaler<WCM_PROFILE_INFO_LIST>))] out WCM_PROFILE_INFO_LIST ppProfileList);
/// <summary>The <c>WcmQueryProperty</c> function retrieves the value of a specified WCM property.</summary>
/// <param name="pInterface">
/// <para>Type: <c>const GUID*</c></para>
/// <para>The interface to query. For global properties, this parameter is NULL.</para>
/// </param>
/// <param name="strProfileName">
/// <para>Type: <c>LPCWSTR</c></para>
/// <para>
/// The name of the profile. If querying a non-global property ( <c>connection_cost</c>, <c>dataplan_status</c>, or
/// <c>hotspot_profile</c>), the profile must be specified or the call will fail.
/// </para>
/// </param>
/// <param name="Property">
/// <para>Type: <c>WCM_PROPERTY</c></para>
/// <para>The WCM property to query.</para>
/// </param>
/// <param name="pReserved">
/// <para>Type: <c>PVOID</c></para>
/// <para>Reserved.</para>
/// </param>
/// <param name="pdwDataSize">
/// <para>Type: <c>PDWORD</c></para>
/// <para>The size of the returned property value.</para>
/// </param>
/// <param name="ppData">
/// <para>Type: <c>PBYTE*</c></para>
/// <para>The returned property value.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
/// <remarks>
/// <para>
/// The type of data stored in the ppData parameter will vary, depending on which property is being queried. This table shows the
/// data type of each property.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property name</term>
/// <term>Data type</term>
/// </listheader>
/// <item>
/// <term>wcm_global_property_domain_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_minimize_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_roaming_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_powermanagement_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_connection_cost</term>
/// <term>WCM_CONNECTION_COST_DATA</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_dataplan_status</term>
/// <term>WCM_DATAPLAN_STATUS</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_hotspot_profile</term>
/// <term>Contains zero-length output.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmqueryproperty DWORD WcmQueryProperty( const GUID
// *pInterface, LPCWSTR strProfileName, WCM_PROPERTY Property, PVOID pReserved, PDWORD pdwDataSize, PBYTE *ppData );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "07c0993e-2892-4908-be3f-d24210ccc300")]
public static extern Win32Error WcmQueryProperty(in Guid pInterface, [Optional, MarshalAs(UnmanagedType.LPWStr)] string strProfileName,
WCM_PROPERTY Property, [Optional] IntPtr pReserved, out uint pdwDataSize, out SafeWcmMemory ppData);
/// <summary>The <c>WcmQueryProperty</c> function retrieves the value of a specified WCM property.</summary>
/// <param name="pInterface">
/// <para>Type: <c>const GUID*</c></para>
/// <para>The interface to query. For global properties, this parameter is NULL.</para>
/// </param>
/// <param name="strProfileName">
/// <para>Type: <c>LPCWSTR</c></para>
/// <para>
/// The name of the profile. If querying a non-global property ( <c>connection_cost</c>, <c>dataplan_status</c>, or
/// <c>hotspot_profile</c>), the profile must be specified or the call will fail.
/// </para>
/// </param>
/// <param name="Property">
/// <para>Type: <c>WCM_PROPERTY</c></para>
/// <para>The WCM property to query.</para>
/// </param>
/// <param name="pReserved">
/// <para>Type: <c>PVOID</c></para>
/// <para>Reserved.</para>
/// </param>
/// <param name="pdwDataSize">
/// <para>Type: <c>PDWORD</c></para>
/// <para>The size of the returned property value.</para>
/// </param>
/// <param name="ppData">
/// <para>Type: <c>PBYTE*</c></para>
/// <para>The returned property value.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
/// <remarks>
/// <para>
/// The type of data stored in the ppData parameter will vary, depending on which property is being queried. This table shows the
/// data type of each property.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property name</term>
/// <term>Data type</term>
/// </listheader>
/// <item>
/// <term>wcm_global_property_domain_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_minimize_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_roaming_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_powermanagement_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_connection_cost</term>
/// <term>WCM_CONNECTION_COST_DATA</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_dataplan_status</term>
/// <term>WCM_DATAPLAN_STATUS</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_hotspot_profile</term>
/// <term>Contains zero-length output.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmqueryproperty DWORD WcmQueryProperty( const GUID
// *pInterface, LPCWSTR strProfileName, WCM_PROPERTY Property, PVOID pReserved, PDWORD pdwDataSize, PBYTE *ppData );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "07c0993e-2892-4908-be3f-d24210ccc300")]
public static extern Win32Error WcmQueryProperty([Optional] IntPtr pInterface, [Optional] IntPtr strProfileName,
WCM_PROPERTY Property, [Optional] IntPtr pReserved, out uint pdwDataSize, out SafeWcmMemory ppData);
/// <summary>The <c>WcmQueryProperty</c> function retrieves the value of a specified WCM property.</summary>
/// <typeparam name="T">The type of the requested property.</typeparam>
/// <param name="pInterface">
/// <para>Type: <c>const GUID*</c></para>
/// <para>The interface to query. For global properties, this parameter is NULL.</para>
/// </param>
/// <param name="strProfileName">
/// <para>Type: <c>LPCWSTR</c></para>
/// <para>
/// The name of the profile. If querying a non-global property ( <c>connection_cost</c>, <c>dataplan_status</c>, or
/// <c>hotspot_profile</c>), the profile must be specified or the call will fail.
/// </para>
/// </param>
/// <param name="Property">
/// <para>Type: <c>WCM_PROPERTY</c></para>
/// <para>The WCM property to query.</para>
/// </param>
/// <param name="ppData">The returned property value.</param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
/// <remarks>
/// <para>
/// The type of data stored in the ppData parameter will vary, depending on which property is being queried. This table shows the
/// data type of each property.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property name</term>
/// <term>Data type</term>
/// </listheader>
/// <item>
/// <term>wcm_global_property_domain_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_minimize_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_roaming_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_powermanagement_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_connection_cost</term>
/// <term>WCM_CONNECTION_COST_DATA</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_dataplan_status</term>
/// <term>WCM_DATAPLAN_STATUS</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_hotspot_profile</term>
/// <term>Contains zero-length output.</term>
/// </item>
/// </list>
/// </remarks>
[PInvokeData("wcmapi.h", MSDNShortId = "07c0993e-2892-4908-be3f-d24210ccc300")]
public static Win32Error WcmQueryProperty<T>(WCM_PROPERTY Property, [Optional] Guid? pInterface, [Optional] string strProfileName, out T ppData)
{
ppData = default;
if (!CorrespondingTypeAttribute.CanGet(Property, typeof(T)))
return Win32Error.ERROR_DATATYPE_MISMATCH;
SafeWcmMemory mem;
uint sz;
Win32Error res;
if (pInterface.HasValue)
res = WcmQueryProperty(pInterface.Value, strProfileName, Property, default, out sz, out mem);
else
res = WcmQueryProperty(IntPtr.Zero, IntPtr.Zero, Property, default, out sz, out mem);
using (mem)
{
if (res.Succeeded)
{
if (typeof(T).IsValueType)
ppData = mem.ToStructure<T>(sz);
else if (typeof(T) == typeof(string))
ppData = (T)(object)mem.ToString(sz);
else
return Win32Error.ERROR_DATATYPE_MISMATCH;
}
}
return res;
}
/// <summary>The <c>WcmSetProfileList</c> function reorders a profile list or a subset of a profile list.</summary>
/// <param name="pProfileList">
/// <para>Type: <c>WCM_PROFILE_INFO_LIST*</c></para>
/// <para>
/// The list of profiles to be reordered, provided in the preferred order (descending from the most preferred to the least preferred).
/// </para>
/// </param>
/// <param name="dwPosition">
/// <para>Type: <c>DWORD</c></para>
/// <para>Specifies the position in the list to start the reorder.</para>
/// </param>
/// <param name="fIgnoreUnknownProfiles">
/// <para>Type: <c>BOOL</c></para>
/// <para>
/// True if any profiles in pProfileList which do not exist should be ignored; the call will proceed with the remainder of the list.
/// False if the call should fail without modifying the profile order if any profiles in pProfileList do not exist.
/// </para>
/// </param>
/// <param name="pReserved">
/// <para>Type: <c>PVOID</c></para>
/// <para>Reserved.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmsetprofilelist DWORD WcmSetProfileList(
// WCM_PROFILE_INFO_LIST *pProfileList, DWORD dwPosition, BOOL fIgnoreUnknownProfiles, PVOID pReserved );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "c5efb2e8-c4c4-4e13-9f7a-ea2a40744655")]
public static extern Win32Error WcmSetProfileList([In] WCM_PROFILE_INFO_LIST pProfileList, uint dwPosition,
[MarshalAs(UnmanagedType.Bool)] bool fIgnoreUnknownProfiles, [Optional] IntPtr pReserved);
/// <summary>The <c>WcmSetProperty</c> function sets the value of a WCM property.</summary>
/// <param name="pInterface">
/// <para>Type: <c>const GUID*</c></para>
/// <para>The interface to set. For global properties, this parameter is NULL.</para>
/// </param>
/// <param name="strProfileName">
/// <para>Type: <c>LPCWSTR</c></para>
/// <para>The profile name.</para>
/// </param>
/// <param name="Property">
/// <para>Type: <c>WCM_PROPERTY</c></para>
/// <para>The WCM property to set.</para>
/// </param>
/// <param name="pReserved">
/// <para>Type: <c>PVOID</c></para>
/// <para>Reserved.</para>
/// </param>
/// <param name="dwDataSize">
/// <para>Type: <c>DWORD</c></para>
/// <para>The size of the new property value.</para>
/// </param>
/// <param name="pbData">
/// <para>Type: <c>const BYTE*</c></para>
/// <para>The new property value.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
/// <remarks>
/// <para>
/// The type of data stored in the pbData parameter will vary, depending on which property is being set. This table shows the data
/// type of each property.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property name</term>
/// <term>Data type</term>
/// </listheader>
/// <item>
/// <term>wcm_global_property_domain_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_minimize_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_roaming_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_powermanagement_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_connection_cost</term>
/// <term>WCM_CONNECTION_COST_DATA</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_dataplan_status</term>
/// <term>WCM_DATAPLAN_STATUS</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_hotspot_profile</term>
/// <term>Variable-length XML string. See the HotSpotProfile schema for more information.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmsetproperty DWORD WcmSetProperty( const GUID *pInterface,
// LPCWSTR strProfileName, WCM_PROPERTY Property, PVOID pReserved, DWORD dwDataSize, const BYTE *pbData );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "79985d5e-a6a1-447c-b12e-11c6022c19a6")]
public static extern Win32Error WcmSetProperty(in Guid pInterface, [Optional, MarshalAs(UnmanagedType.LPWStr)] string strProfileName,
WCM_PROPERTY Property, [Optional] IntPtr pReserved, uint dwDataSize, [In, Optional] IntPtr pbData);
/// <summary>The <c>WcmSetProperty</c> function sets the value of a WCM property.</summary>
/// <param name="pInterface">
/// <para>Type: <c>const GUID*</c></para>
/// <para>The interface to set. For global properties, this parameter is NULL.</para>
/// </param>
/// <param name="strProfileName">
/// <para>Type: <c>LPCWSTR</c></para>
/// <para>The profile name.</para>
/// </param>
/// <param name="Property">
/// <para>Type: <c>WCM_PROPERTY</c></para>
/// <para>The WCM property to set.</para>
/// </param>
/// <param name="pReserved">
/// <para>Type: <c>PVOID</c></para>
/// <para>Reserved.</para>
/// </param>
/// <param name="dwDataSize">
/// <para>Type: <c>DWORD</c></para>
/// <para>The size of the new property value.</para>
/// </param>
/// <param name="pbData">
/// <para>Type: <c>const BYTE*</c></para>
/// <para>The new property value.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
/// <remarks>
/// <para>
/// The type of data stored in the pbData parameter will vary, depending on which property is being set. This table shows the data
/// type of each property.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property name</term>
/// <term>Data type</term>
/// </listheader>
/// <item>
/// <term>wcm_global_property_domain_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_minimize_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_roaming_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_powermanagement_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_connection_cost</term>
/// <term>WCM_CONNECTION_COST_DATA</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_dataplan_status</term>
/// <term>WCM_DATAPLAN_STATUS</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_hotspot_profile</term>
/// <term>Variable-length XML string. See the HotSpotProfile schema for more information.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/nf-wcmapi-wcmsetproperty DWORD WcmSetProperty( const GUID *pInterface,
// LPCWSTR strProfileName, WCM_PROPERTY Property, PVOID pReserved, DWORD dwDataSize, const BYTE *pbData );
[DllImport(Lib.Wcmapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wcmapi.h", MSDNShortId = "79985d5e-a6a1-447c-b12e-11c6022c19a6")]
public static extern Win32Error WcmSetProperty([Optional] IntPtr pInterface, [Optional, MarshalAs(UnmanagedType.LPWStr)] string strProfileName,
WCM_PROPERTY Property, [Optional] IntPtr pReserved, uint dwDataSize, [In, Optional] IntPtr pbData);
/// <summary>The <c>WcmSetProperty</c> function sets the value of a WCM property.</summary>
/// <typeparam name="T">The type of the value to set.</typeparam>
/// <param name="pInterface">
/// <para>Type: <c>const GUID*</c></para>
/// <para>The interface to set. For global properties, this parameter is NULL.</para>
/// </param>
/// <param name="strProfileName">
/// <para>Type: <c>LPCWSTR</c></para>
/// <para>The profile name.</para>
/// </param>
/// <param name="Property">
/// <para>Type: <c>WCM_PROPERTY</c></para>
/// <para>The WCM property to set.</para>
/// </param>
/// <param name="data">
/// <para>Type: <c>const BYTE*</c></para>
/// <para>The new property value.</para>
/// </param>
/// <returns>
/// <para>Type: <c>DWORD</c></para>
/// <para>Returns ERROR_SUCCESS if successful, or an error value otherwise.</para>
/// </returns>
/// <remarks>
/// <para>
/// The type of data stored in the pbData parameter will vary, depending on which property is being set. This table shows the data
/// type of each property.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property name</term>
/// <term>Data type</term>
/// </listheader>
/// <item>
/// <term>wcm_global_property_domain_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_minimize_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_roaming_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_global_property_powermanagement_policy</term>
/// <term>WCM_POLICY_VALUE</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_connection_cost</term>
/// <term>WCM_CONNECTION_COST_DATA</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_dataplan_status</term>
/// <term>WCM_DATAPLAN_STATUS</term>
/// </item>
/// <item>
/// <term>wcm_intf_property_hotspot_profile</term>
/// <term>Variable-length XML string. See the HotSpotProfile schema for more information.</term>
/// </item>
/// </list>
/// </remarks>
[PInvokeData("wcmapi.h", MSDNShortId = "79985d5e-a6a1-447c-b12e-11c6022c19a6")]
public static Win32Error WcmSetProperty<T>(WCM_PROPERTY Property, [Optional] Guid? pInterface, [Optional] string strProfileName, in T data)
{
using var mem = data is string s ? new SafeCoTaskMemHandle(s) : SafeCoTaskMemHandle.CreateFromStructure(data);
if (pInterface.HasValue)
return WcmSetProperty(pInterface.Value, strProfileName, Property, default, mem.Size, mem);
return WcmSetProperty(IntPtr.Zero, strProfileName, Property, default, mem.Size, mem);
}
/// <summary>The <c>WCM_BILLING_CYCLE_INFO</c> structure specifies information about the billing cycle.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_billing_cycle_info typedef struct WCM_BILLING_CYCLE_INFO
// { FILETIME StartDate; WCM_TIME_INTERVAL Duration; BOOL Reset; } WCM_BILLING_CYCLE_INFO;
[PInvokeData("wcmapi.h", MSDNShortId = "5cfcdfb7-aa33-4582-ba17-e1a305b830f5")]
[StructLayout(LayoutKind.Sequential)]
public struct WCM_BILLING_CYCLE_INFO
{
/// <summary>
/// <para>Type: <c>FILETIME</c></para>
/// <para>Specifies the start date of the cycle.</para>
/// </summary>
public FILETIME StartDate;
/// <summary>
/// <para>Type: <c>WCM_TIME_INTERVAL</c></para>
/// <para>Specifies the billing cycle duration.</para>
/// </summary>
public WCM_TIME_INTERVAL Duration;
/// <summary>
/// <para>Type: <c>BOOL</c></para>
/// <para>
/// True if at the end of the billing cycle, a new billing cycle of the same duration will start. False if the service will
/// terminate at the end of the billing cycle.
/// </para>
/// </summary>
[MarshalAs(UnmanagedType.Bool)] public bool Reset;
}
/// <summary>The <c>WCM_CONNECTION_COST_DATA</c> structure specifies information about a connection cost.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_connection_cost_data typedef struct
// _WCM_CONNECTION_COST_DATA { DWORD ConnectionCost; WCM_CONNECTION_COST_SOURCE CostSource; } WCM_CONNECTION_COST_DATA, *PWCM_CONNECTION_COST_DATA;
[PInvokeData("wcmapi.h", MSDNShortId = "18fcc708-74b1-408f-a7ee-64455742324d")]
[StructLayout(LayoutKind.Sequential)]
public struct WCM_CONNECTION_COST_DATA
{
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Specifies the connection cost type.</para>
/// <para>This must include one (and only one) of the following flags:</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>WCM_CONNECTION_COST_UNKNOWN 0x0</term>
/// <term>Connection cost information is not available.</term>
/// </item>
/// <item>
/// <term>WCM_CONNECTION_COST_UNRESTRICTED 0x1</term>
/// <term>The connection is unlimited and has unrestricted usage constraints.</term>
/// </item>
/// <item>
/// <term>WCM_CONNECTION_COST_FIXED 0x2</term>
/// <term>Usage counts toward a fixed allotment of data which the user has already paid for (or agreed to pay for).</term>
/// </item>
/// <item>
/// <term>WCM_CONNECTION_COST_VARIABLE 0x4</term>
/// <term>The connection cost is on a per-byte basis.</term>
/// </item>
/// </list>
/// <para>And may include any combination of the following flags:</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>WCM_CONNECTION_COST_OVERDATALIMIT 0x10000</term>
/// <term>The connection has exceeded its data limit.</term>
/// </item>
/// <item>
/// <term>WCM_CONNECTION_COST_CONGESTED 0x20000</term>
/// <term>The connection is throttled due to high traffic.</term>
/// </item>
/// <item>
/// <term>WCM_CONNECTION_COST_ROAMING 0x40000</term>
/// <term>The connection is outside of the home network.</term>
/// </item>
/// </list>
/// </summary>
public WCM_CONNECTION_COST ConnectionCost;
/// <summary>
/// <para>Type: <c>WCM_CONNECTION_COST_SOURCE</c></para>
/// <para>Specifies the cost source.</para>
/// </summary>
public WCM_CONNECTION_COST_SOURCE CostSource;
}
/// <summary>The <c>WCM_DATAPLAN_STATUS</c> structure specifies subscription information for a network connection.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_dataplan_status typedef struct _WCM_DATAPLAN_STATUS {
// WCM_USAGE_DATA UsageData; DWORD DataLimitInMegabytes; DWORD InboundBandwidthInKbps; DWORD OutboundBandwidthInKbps;
// WCM_BILLING_CYCLE_INFO BillingCycle; DWORD MaxTransferSizeInMegabytes; DWORD Reserved; } WCM_DATAPLAN_STATUS, *PWCM_DATAPLAN_STATUS;
[PInvokeData("wcmapi.h", MSDNShortId = "6ed0f05c-a9f8-49bb-9fb0-b91af8594d76")]
[StructLayout(LayoutKind.Sequential)]
public struct WCM_DATAPLAN_STATUS
{
/// <summary>
/// <para>Type: <c>WCM_USAGE_DATA</c></para>
/// <para>Contains usage data.</para>
/// </summary>
public WCM_USAGE_DATA UsageData;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Specifies the data limit, in megabytes.</para>
/// </summary>
public uint DataLimitInMegabytes;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Specifies the inbound bandwidth, in kilobits per second.</para>
/// </summary>
public uint InboundBandwidthInKbps;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Specifies the outbound bandwidth, in kilobits per second.</para>
/// </summary>
public uint OutboundBandwidthInKbps;
/// <summary>
/// <para>Type: <c>WCM_BILLING_CYCLE_INFO</c></para>
/// <para>Contains information about the billing cycle.</para>
/// </summary>
public WCM_BILLING_CYCLE_INFO BillingCycle;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Specifies the maximum size of a file that can be transferred, in megabytes.</para>
/// </summary>
public uint MaxTransferSizeInMegabytes;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Reserved.</para>
/// </summary>
public uint Reserved;
}
/// <summary>The <c>WCM_POLICY_VALUE</c> structure contains information about the current value of a policy.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_policy_value typedef struct _WCM_POLICY_VALUE { BOOL
// fValue; BOOL fIsGroupPolicy; } WCM_POLICY_VALUE, *PWCM_POLICY_VALUE;
[PInvokeData("wcmapi.h", MSDNShortId = "0f259661-723b-4c76-8652-c86e0b8c9ebf")]
[StructLayout(LayoutKind.Sequential)]
public struct WCM_POLICY_VALUE
{
/// <summary>
/// <para>Type: <c>BOOL</c></para>
/// <para>True if the policy is enabled; otherwise, false.</para>
/// </summary>
[MarshalAs(UnmanagedType.Bool)] public bool fValue;
/// <summary>
/// <para>Type: <c>BOOL</c></para>
/// <para>True if the current value was provided by Group Policy; otherwise, false.</para>
/// </summary>
[MarshalAs(UnmanagedType.Bool)] public bool fIsGroupPolicy;
}
/// <summary>The <c>WCM_PROFILE_INFO</c> structure contains information about a specific profile.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_profile_info typedef struct _WCM_PROFILE_INFO { WCHAR
// strProfileName[WCM_MAX_PROFILE_NAME]; GUID AdapterGUID; WCM_MEDIA_TYPE Media; } WCM_PROFILE_INFO, *PWCM_PROFILE_INFO;
[PInvokeData("wcmapi.h", MSDNShortId = "bf917afa-c6c5-408a-bd34-b4a4c7b991b9")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WCM_PROFILE_INFO
{
/// <summary>
/// <para>Type: <c>WCHAR[WCM_MAX_PROFILE_NAME]</c></para>
/// <para>The profile name.</para>
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string strProfileName;
/// <summary>
/// <para>Type: <c>GUID</c></para>
/// <para>The GUID of the adapter.</para>
/// </summary>
public Guid AdapterGUID;
/// <summary>
/// <para>Type: <c>WCM_MEDIA_TYPE</c></para>
/// <para>The media type for the profile.</para>
/// </summary>
public WCM_MEDIA_TYPE Media;
}
/// <summary>The <c>WCM_PROFILE_INFO_LIST</c> structure contains a list of profiles in preferred order.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_profile_info_list typedef struct _WCM_PROFILE_INFO_LIST {
// DWORD dwNumberOfItems; #if ... WCM_PROFILE_INFO *ProfileInfo[]; #else WCM_PROFILE_INFO ProfileInfo[1]; #endif }
// WCM_PROFILE_INFO_LIST, *PWCM_PROFILE_INFO_LIST;
[PInvokeData("wcmapi.h", MSDNShortId = "73ddb610-233a-470b-900d-ae62a1e7121a")]
[VanaraMarshaler(typeof(SafeAnysizeStructMarshaler<WCM_PROFILE_INFO_LIST>), nameof(dwNumberOfItems))]
[StructLayout(LayoutKind.Sequential)]
public class WCM_PROFILE_INFO_LIST
{
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>The number of profiles in the list.</para>
/// </summary>
public uint dwNumberOfItems;
/// <summary>
/// <para>Type: <c>WCM_PROFILE_INFO[1]</c></para>
/// <para>Information about each profile.</para>
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public WCM_PROFILE_INFO[] ProfileInfo;
}
/// <summary>The <c>WCM_TIME_INTERVAL</c> structure defines a time interval.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_time_interval typedef struct _WCM_TIME_INTERVAL { WORD
// wYear; WORD wMonth; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } WCM_TIME_INTERVAL;
[PInvokeData("wcmapi.h", MSDNShortId = "7744a577-5f3d-4cdd-b74d-a1430ea20b37")]
[StructLayout(LayoutKind.Sequential)]
public struct WCM_TIME_INTERVAL
{
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Years.</para>
/// </summary>
public ushort wYear;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Months.</para>
/// </summary>
public ushort wMonth;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Days.</para>
/// </summary>
public ushort wDay;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Hours.</para>
/// </summary>
public ushort wHour;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Minutes.</para>
/// </summary>
public ushort wMinute;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Seconds.</para>
/// </summary>
public ushort wSecond;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>Milliseconds.</para>
/// </summary>
public ushort wMilliseconds;
}
/// <summary>The <c>WCM_USAGE_DATA</c> structure contains information related to connection usage.</summary>
// https://docs.microsoft.com/en-us/windows/win32/api/wcmapi/ns-wcmapi-wcm_usage_data typedef struct _WCM_USAGE_DATA { DWORD
// UsageInMegabytes; FILETIME LastSyncTime; } WCM_USAGE_DATA, *PWCM_USAGE_DATA;
[PInvokeData("wcmapi.h", MSDNShortId = "c6a483cf-d392-495f-854d-ccc782b30aa5")]
[StructLayout(LayoutKind.Sequential)]
public struct WCM_USAGE_DATA
{
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>The connection usage, in megabytes.</para>
/// </summary>
public uint UsageInMegabytes;
/// <summary>
/// <para>Type: <c>FILETIME</c></para>
/// <para>Specifies the last time that usage information was reconciled with the carrier's billing system.</para>
/// </summary>
public FILETIME LastSyncTime;
}
/// <summary>Provides a <see cref="SafeHandle"/> for WCM memory that is disposed using <see cref="WcmFreeMemory"/>.</summary>
public class SafeWcmMemory : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeWcmMemory"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeWcmMemory(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeWcmMemory"/> class.</summary>
private SafeWcmMemory() : base() { }
/// <summary>Converts this memory to a string value.</summary>
/// <param name="allocatedBytes">If known, the total number of bytes allocated to the native memory.</param>
/// <returns>A <see cref="string"/> that represents this instance.</returns>
public string ToString(SizeT allocatedBytes) => StringHelper.GetString(handle, CharSet.Unicode, allocatedBytes);
/// <summary>
/// Marshals data from an unmanaged block of memory to a newly allocated managed object of the type specified by a generic type parameter.
/// </summary>
/// <typeparam name="T">The type of the object to which the data is to be copied. This must be a structure.</typeparam>
/// <param name="allocatedBytes">If known, the total number of bytes allocated to the native memory.</param>
/// <returns>A managed object that contains the requested data.</returns>
public T ToStructure<T>(SizeT allocatedBytes = default) => handle.ToStructure<T>(allocatedBytes);
/// <summary>Performs an implicit conversion from <see cref="SafeWcmMemory"/> to <see cref="IntPtr"/>.</summary>
/// <param name="mem">The memory.</param>
/// <returns>The resulting <see cref="IntPtr"/> instance from the conversion.</returns>
public static implicit operator IntPtr(SafeWcmMemory mem) => mem.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() { WcmFreeMemory(handle); return true; }
}
internal class WcmMarshaler<T> : ICustomMarshaler
{
private WcmMarshaler(string _)
{
}
/// <summary>Gets the instance.</summary>
/// <param name="cookie">The cookie.</param>
/// <returns></returns>
public static ICustomMarshaler GetInstance(string cookie) => new WcmMarshaler<T>(cookie);
void ICustomMarshaler.CleanUpManagedData(object ManagedObj) => throw new NotImplementedException();
void ICustomMarshaler.CleanUpNativeData(IntPtr pNativeData) => WcmFreeMemory(pNativeData);
int ICustomMarshaler.GetNativeDataSize() => -1;
IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException();
object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData) => typeof(T) == typeof(string) ? StringHelper.GetString(pNativeData, CharSet.Unicode) : (object)pNativeData.ToStructure<T>();
}
}
}