Added WinHTTP assembly

pull/279/head
dahall 2022-02-22 19:41:15 -07:00
parent 0a7fe3d60e
commit a94476f5d1
9 changed files with 9430 additions and 0 deletions

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<ProjectExtensions>
<SupportedDlls>winhttp.dll</SupportedDlls>
</ProjectExtensions>
<PropertyGroup>
<Description>PInvoke API (methods, structures and constants) imported from Windows WinHTTP.dll.</Description>
<AssemblyTitle>$(AssemblyName)</AssemblyTitle>
<TargetFrameworks>net462;net48;net5.0;net6.0;netstandard2.0;netcoreapp3.1</TargetFrameworks>
<AssemblyName>Vanara.PInvoke.WinHTTP</AssemblyName>
<PackageId>$(AssemblyName)</PackageId>
<PackageTags>pinvoke;vanara;net-extensions;interop;WinHTTP</PackageTags>
<PackageReleaseNotes />
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Core\Vanara.Core.csproj" />
<ProjectReference Include="..\Shared\Vanara.PInvoke.Shared.csproj" />
<ProjectReference Include="..\Security\Vanara.PInvoke.Security.csproj" />
<ProjectReference Include="..\Ws2_32\Vanara.PInvoke.Ws2_32.csproj" />
</ItemGroup>
</Project>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
namespace Vanara.PInvoke
{
/// <summary>Items from the WinHTTP.dll.</summary>
public static partial class WinHTTP
{
/*
IWinHttpRequest implements WinHTTP methods that do not involve events.
IWinHttpRequestEvents implements WinHTTP events and event-based methods.
*/
}
}

File diff suppressed because it is too large Load Diff

2863
PInvoke/WinHTTP/WinHTTP.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>UnitTest.PInvoke.WinHTTP</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\PInvoke\WinHTTP\Vanara.PInvoke.WinHTTP.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,418 @@
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using System.Linq;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
using static Vanara.PInvoke.WinHTTP;
namespace Vanara.PInvoke.Tests
{
[TestFixture]
public class WinHTTPTests
{
private const string host = "www.microsoft.com";
private const string userAgent = "A WinHTTP Example Program/1.0";
[OneTimeSetUp]
public void _Setup()
{
}
[OneTimeTearDown]
public void _TearDown()
{
}
[Test]
public void WinHttpCheckPlatformTest() => Assert.That(WinHttpCheckPlatform(), Is.True);
[Test]
public void WinHttpCrackUrlTest()
{
const string url = "https://www.example.com/index.html?query1=value1&query2=value2#section";
WINHTTP_URL_COMPONENTS comps = new();
Assert.That(WinHttpCrackUrl(url, 0, 0, ref comps), ResultIs.Successful);
uint len = 0U;
Assert.That(WinHttpCreateUrl(comps, 0, null, ref len), ResultIs.Failure);
StringBuilder sb = new((int)len);
Assert.That(WinHttpCreateUrl(comps, 0, sb, ref len), ResultIs.Successful);
Assert.That(sb.ToString(), Is.EqualTo(url));
}
[Test]
public void WinHttpDetectAutoProxyConfigUrlTest()
{
Assert.That(WinHttpDetectAutoProxyConfigUrl(WINHTTP_AUTO_DETECT_TYPE.WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE.WINHTTP_AUTO_DETECT_TYPE_DNS_A, out SafeHGlobalHandle url), ResultIs.Successful);
TestContext.Write(url.ToString(-1));
}
[Test]
public void WinHttpGetDefaultProxyConfigurationTest()
{
Assert.That(WinHttpGetDefaultProxyConfiguration(out WINHTTP_PROXY_INFO pInfo), ResultIs.Successful);
pInfo.WriteValues();
}
[Test]
public void WinHttpGetIEProxyConfigForCurrentUserTest()
{
Assert.That(WinHttpGetIEProxyConfigForCurrentUser(out WINHTTP_CURRENT_USER_IE_PROXY_CONFIG prxCfg), ResultIs.Successful);
prxCfg.WriteValues();
}
[Test, RequiresThread]
public void WinHttpGetProxyForUrlExTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent, dwFlags: WINHTTP_OPEN_FLAG.WINHTTP_FLAG_ASYNC);
Assert.That(hSession, ResultIs.ValidHandle);
if (!WinHttpGetIEProxyConfigForCurrentUser(out WINHTTP_CURRENT_USER_IE_PROXY_CONFIG prxCfg))
{
Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_FILE_NOT_FOUND);
}
Assert.That(WinHttpCreateProxyResolver(hSession, out SafeHINTERNET hResolver), ResultIs.Successful);
using System.Threading.ManualResetEvent evt = new System.Threading.ManualResetEvent(false);
Win32Error cbErr = Win32Error.ERROR_SUCCESS;
IntPtr prevCb = WinHttpSetStatusCallback(hResolver, callback, WINHTTP_CALLBACK_FLAG.WINHTTP_CALLBACK_FLAG_REQUEST_ERROR | WINHTTP_CALLBACK_FLAG.WINHTTP_CALLBACK_FLAG_GETPROXYFORURL_COMPLETE);
Assert.That(prevCb, Is.Not.EqualTo(WINHTTP_INVALID_STATUS_CALLBACK));
WINHTTP_AUTOPROXY_OPTIONS opts;
if (prxCfg.fAutoDetect)
{
opts = new()
{
dwFlags = WINHTTP_AUTOPROXY.WINHTTP_AUTOPROXY_AUTO_DETECT,
dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE.WINHTTP_AUTO_DETECT_TYPE_DNS_A | WINHTTP_AUTO_DETECT_TYPE.WINHTTP_AUTO_DETECT_TYPE_DHCP,
fAutoLogonIfChallenged = true,
};
// Call WinHttpGetProxyForUrl with our target URL, then set the proxy info on the request handle.
Assert.That(WinHttpGetProxyForUrlEx(hResolver, "https://www.microsoft.com/ms.htm", opts), Is.EqualTo((Win32Error)Win32Error.ERROR_IO_PENDING));
}
evt.WaitOne(5000);
Assert.That(cbErr, ResultIs.Successful);
void callback(HINTERNET hInternet, IntPtr dwContext, WINHTTP_CALLBACK_STATUS dwInternetStatus, IntPtr lpvStatusInformation, uint dwStatusInformationLength)
{
if (dwInternetStatus == WINHTTP_CALLBACK_STATUS.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR)
{
WINHTTP_ASYNC_RESULT res = lpvStatusInformation.ToStructure<WINHTTP_ASYNC_RESULT>(dwStatusInformationLength);
if (res.dwResult != ASYNC_RESULT.API_GET_PROXY_FOR_URL)
{
return;
}
cbErr = res.dwError;
}
else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS.WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE)
{
cbErr = WinHttpGetProxyResult(hInternet, out WINHTTP_PROXY_RESULT proxyRes);
if (cbErr.Succeeded)
{
proxyRes.WriteValues();
WinHttpFreeProxyResult(ref proxyRes);
}
}
evt.Set();
}
}
[Test]
public void WinHttpGetProxyForUrlTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTP_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
// Create an HTTP request handle.
using SafeHINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET", "ms.htm", "HTTP/1.1");
Assert.That(hRequest, ResultIs.ValidHandle);
// Call WinHttpGetProxyForUrl with our target URL, then set the proxy info on the request handle.
WINHTTP_AUTOPROXY_OPTIONS opts = new()
{
dwFlags = WINHTTP_AUTOPROXY.WINHTTP_AUTOPROXY_AUTO_DETECT,
dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE.WINHTTP_AUTO_DETECT_TYPE_DNS_A | WINHTTP_AUTO_DETECT_TYPE.WINHTTP_AUTO_DETECT_TYPE_DHCP,
fAutoLogonIfChallenged = true,
};
Assert.That(WinHttpGetProxyForUrl(hSession, "https://www.microsoft.com/ms.htm", opts, out WINHTTP_PROXY_INFO info), ResultIs.Successful);
try
{
TestContext.WriteLine($"{info.dwAccessType}; {info.lpszProxy}; {info.lpszProxyBypass}");
// A proxy configuration was found, set it on the request handle.
Assert.That(WinHttpSetOption(hRequest, WINHTTP_OPTION.WINHTTP_OPTION_PROXY, info), ResultIs.Successful);
}
finally
{
info.FreeMemory();
}
// Send the request.
Assert.That(WinHttpSendRequest(hRequest), ResultIs.Successful);
// Wait for the response.
Assert.That(WinHttpReceiveResponse(hRequest), ResultIs.Successful);
}
[Test] // TODO: Need to find URL where this works
public void WinHttpQueryAuthSchemesTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, "drive.google.com", INTERNET_DEFAULT_HTTPS_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
// Create an HTTP request handle.
using SafeHINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET", "file/d/0ByJOdIdwOr5COHpTRTNFakgzSk0/view?usp=sharing&resourcekey=0-TUcpJ5N1-M9-Mw1DP4VT7A", dwFlags: WINHTTP_OPENREQ_FLAG.WINHTTP_FLAG_SECURE);
Assert.That(hRequest, ResultIs.ValidHandle);
// Send the request.
Assert.That(WinHttpSendRequest(hRequest), ResultIs.Successful);
// Wait for the response.
Assert.That(WinHttpReceiveResponse(hRequest), ResultIs.Successful);
var stat = WinHttpQueryHeaders<uint>(hRequest, WINHTTP_QUERY.WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY.WINHTTP_QUERY_STATUS_CODE);
Assert.That(stat, Is.EqualTo(401).Or.EqualTo(407));
Assert.That(WinHttpQueryAuthSchemes(hRequest, out var sch, out var first, out var target), ResultIs.Successful);
TestContext.Write($"Auth: {sch}, {first}, {target}");
}
//[Test] // Can't get this ever pass
public void WinHttpQueryConnectionGroupTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTPS_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
try
{
IntPtr res = default;
Assert.That(WinHttpQueryConnectionGroup(hConnect, default, 0, ref res), ResultIs.Successful);
WinHttpFreeQueryConnectionGroupResult(res);
}
finally
{
if (!hConnect.IsNull)
{
WinHttpCloseHandle(hSession);
}
if (!hSession.IsNull)
{
WinHttpCloseHandle(hSession);
}
}
}
[Test]
public void WinHttpQueryHeadersExTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTPS_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
// Create an HTTP request handle.
using SafeHINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET", dwFlags: WINHTTP_OPENREQ_FLAG.WINHTTP_FLAG_SECURE);
Assert.That(hRequest, ResultIs.ValidHandle);
// Add a request header.
WINHTTP_EXTENDED_HEADER[] hdr = new WINHTTP_EXTENDED_HEADER[] { ("If-Modified-Since", "Mon, 20 Nov 2000 20:00:00 GMT"), ("Accept-Charset", "utf-8") };
Assert.That(WinHttpAddRequestHeadersEx(hRequest, WINHTTP_ADDREQ_FLAG.WINHTTP_ADDREQ_FLAG_ADD,
WINHTTP_EXTENDED_HEADER_FLAG.WINHTTP_EXTENDED_HEADER_FLAG_UNICODE, 0, hdr.Length, hdr), ResultIs.Successful);
// Send a request.
Assert.That(WinHttpSendRequest(hRequest), ResultIs.Successful);
// End the request.
Assert.That(WinHttpReceiveResponse(hRequest), ResultIs.Successful);
// Get status header
uint sz = 256U;
using var pin = new SafeHGlobalHandle(sz);
Assert.That(WinHttpQueryHeadersEx(hRequest, WINHTTP_QUERY.WINHTTP_QUERY_CONNECTION, 0, 0,
default, default, pin, ref sz, out var hdrs, out var cHdrs), ResultIs.Successful);
Assert.That(sz, Is.GreaterThan(0));
Assert.That(cHdrs, Is.GreaterThan(0));
hdrs.ToArray<WINHTTP_EXTENDED_HEADER>((int)cHdrs)[0].WriteValues();
}
[Test]
public void WinHttpQueryHeadersTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTP_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
// Create an HTTP request handle.
using SafeHINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET");
Assert.That(hRequest, ResultIs.ValidHandle);
// Add a request header.
Assert.That(WinHttpAddRequestHeaders(hRequest, "If-Modified-Since: Mon, 20 Nov 2000 20:00:00 GMT\r\nAccept-Charset: utf-8", -1, WINHTTP_ADDREQ_FLAG.WINHTTP_ADDREQ_FLAG_ADD), ResultIs.Successful);
// Send a request.
Assert.That(WinHttpSendRequest(hRequest), ResultIs.Successful);
// End the request.
Assert.That(WinHttpReceiveResponse(hRequest), ResultIs.Successful);
Assert.That(WinHttpQueryHeaders<uint>(hRequest, WINHTTP_QUERY.WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY.WINHTTP_QUERY_STATUS_CODE), Is.GreaterThanOrEqualTo(200));
Assert.That(WinHttpQueryHeaders<SYSTEMTIME>(hRequest, WINHTTP_QUERY.WINHTTP_QUERY_FLAG_SYSTEMTIME | WINHTTP_QUERY.WINHTTP_QUERY_DATE).wYear, Is.EqualTo(DateTime.Today.Year));
//uint idx = 2;
//Assert.That(() => WinHttpQueryHeaders<string>(hRequest, WINHTTP_QUERY.WINHTTP_QUERY_RAW_HEADERS, null, ref idx), Throws.Nothing);
for (uint i = 0; i < 78; i++)
{
try
{
string hdrs = WinHttpQueryHeaders<string>(hRequest, (WINHTTP_QUERY)i);
TestContext.WriteLine($"{i}) {(WINHTTP_QUERY)i}: {hdrs}");
}
catch (System.ComponentModel.Win32Exception wex) when (wex.NativeErrorCode == 0x2f76) { }
catch (Exception ex)
{
TestContext.WriteLine($"{i}) {(WINHTTP_QUERY)i}: ERR: {ex.Message}");
}
}
}
[Test]
public void WinHttpQueryOptionTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
uint data = WinHttpQueryOption<uint>(hSession, WINHTTP_OPTION.WINHTTP_OPTION_CONNECT_TIMEOUT);
TestContext.Write($"Connection timeout: {data} ms\n");
}
[Test]
public void WinHttpQueryOptionTypeTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTPS_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
// Create an HTTP request handle.
using SafeHINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET", dwFlags: WINHTTP_OPENREQ_FLAG.WINHTTP_FLAG_SECURE);
Assert.That(hRequest, ResultIs.ValidHandle);
// Send a request.
Assert.That(WinHttpSendRequest(hRequest), ResultIs.Successful);
// End the request.
Assert.That(WinHttpReceiveResponse(hRequest), ResultIs.Successful);
foreach (WINHTTP_OPTION opt in Enum.GetValues(typeof(WINHTTP_OPTION)))
{
uint len = 0;
TestContext.Write($"{opt} ({(int)opt}): ");
var err = WinHttpQueryOption(hSession, opt, default, ref len) ? Win32Error.ERROR_SUCCESS : Win32Error.GetLastError();
if (err.Failed)
{
if (err == Win32Error.ERROR_INTERNET_INCORRECT_HANDLE_TYPE)
{
len = 0;
err = WinHttpQueryOption(hRequest, opt, default, ref len) ? Win32Error.ERROR_SUCCESS : Win32Error.GetLastError();
}
if (err == Win32Error.ERROR_INVALID_PARAMETER &&
CorrespondingTypeAttribute.GetAttrForEnum(opt, CorrespondingAction.Get).FirstOrDefault() is null)
{
TestContext.WriteLine("SET ONLY");
continue;
}
if (err != Win32Error.ERROR_INSUFFICIENT_BUFFER)
{
TestContext.WriteLine($"Err = {err}");
continue;
}
}
var type = CorrespondingTypeAttribute.GetCorrespondingTypes(opt).FirstOrDefault();
TestContext.WriteLine($"{type?.Name ?? "[Unk]"} = {len}");
if (type is not null && type.IsValueType && opt != WINHTTP_OPTION.WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST &&
opt != WINHTTP_OPTION.WINHTTP_OPTION_SELECTED_PROXY_CONFIG_INFO)
Assert.That((uint)InteropExtensions.SizeOf(type), Is.LessThanOrEqualTo(len));
}
}
[Test]
public void WinHttpReadDataTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
// Specify an HTTP server.
using SafeHINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTPS_PORT);
Assert.That(hConnect, ResultIs.ValidHandle);
// Create an HTTP request handle.
using SafeHINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET", dwFlags: WINHTTP_OPENREQ_FLAG.WINHTTP_FLAG_SECURE);
Assert.That(hRequest, ResultIs.ValidHandle);
// Send a request.
Assert.That(WinHttpSendRequest(hRequest), ResultIs.Successful);
// End the request.
Assert.That(WinHttpReceiveResponse(hRequest), ResultIs.Successful);
// Report data size
Assert.That(WinHttpQueryDataAvailable(hRequest, out uint bytes), ResultIs.Successful);
TestContext.Write($"Bytes in request: {bytes}");
Assert.That(bytes, Is.GreaterThan(0));
// Read from stream
using var mem = new SafeHGlobalHandle(bytes + 1);
Assert.That(WinHttpReadData(hRequest, mem, bytes, out var read), ResultIs.Successful);
Assert.That(read, Is.LessThanOrEqualTo((uint)mem.Size));
TestContext.WriteLine($", Bytes read: {read}");
TestContext.WriteLine(mem.ToString(-1, System.Runtime.InteropServices.CharSet.Ansi));
}
[Test]
public void WinHttpResetAutoProxyTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
Assert.That(hSession, ResultIs.ValidHandle);
Assert.That(WinHttpResetAutoProxy(hSession, WINHTTP_RESET.WINHTTP_RESET_STATE), ResultIs.Successful);
}
[Test]
public void WinHttpSetDefaultProxyConfigurationTest()
{
Assert.That(WinHttpGetDefaultProxyConfiguration(out WINHTTP_PROXY_INFO pInfo), ResultIs.Successful);
pInfo.WriteValues();
Assert.That(WinHttpSetDefaultProxyConfiguration(pInfo), ResultIs.Successful);
}
[Test]
public void WinHttpSetTimeoutsTest()
{
// Use WinHttpOpen to obtain a session handle.
using SafeHINTERNET hSession = WinHttpOpen(userAgent);
var rslv = WinHttpQueryOption<int>(hSession, WINHTTP_OPTION.WINHTTP_OPTION_RESOLVE_TIMEOUT);
var conn = WinHttpQueryOption<int>(hSession, WINHTTP_OPTION.WINHTTP_OPTION_CONNECT_TIMEOUT);
var send = WinHttpQueryOption<int>(hSession, WINHTTP_OPTION.WINHTTP_OPTION_SEND_TIMEOUT);
var recv = WinHttpQueryOption<int>(hSession, WINHTTP_OPTION.WINHTTP_OPTION_RECEIVE_TIMEOUT);
Assert.That(WinHttpSetTimeouts(hSession, rslv, conn, send, recv), ResultIs.Successful);
}
[Test]
public void WinHttpTimeFromSystemTimeTest()
{
var st = new SYSTEMTIME(2000, 2, 20, 14, 20, 2);
var sb = new StringBuilder(256);
Assert.That(WinHttpTimeFromSystemTime(st, sb), ResultIs.Successful);
Assert.That(sb.ToString(), Contains.Substring("2000"));
Assert.That(WinHttpTimeToSystemTime(sb.ToString(), out var st2), ResultIs.Successful);
Assert.That(st.Ticks, Is.EqualTo(st2.Ticks));
}
}
}

View File

@ -364,6 +364,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.AMSI", "PInv
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AMSI", "UnitTests\PInvoke\AMSI\AMSI.csproj", "{496DFA71-4C35-49AE-95C1-4B802DB91615}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WinHTTP", "PInvoke\WinHTTP\Vanara.PInvoke.WinHTTP.csproj", "{B8A58F84-9707-4B9C-9AE0-04DDE718E232}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinHTTP", "UnitTests\PInvoke\WinHTTP\WinHTTP.csproj", "{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -2289,6 +2293,40 @@ Global
{496DFA71-4C35-49AE-95C1-4B802DB91615}.Release|x64.Build.0 = Release|Any CPU
{496DFA71-4C35-49AE-95C1-4B802DB91615}.Release|x86.ActiveCfg = Release|Any CPU
{496DFA71-4C35-49AE-95C1-4B802DB91615}.Release|x86.Build.0 = Release|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Debug|x64.ActiveCfg = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Debug|x64.Build.0 = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Debug|x86.ActiveCfg = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Debug|x86.Build.0 = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.DebugNoTests|x64.ActiveCfg = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.DebugNoTests|x64.Build.0 = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.DebugNoTests|x86.ActiveCfg = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.DebugNoTests|x86.Build.0 = Debug|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Release|Any CPU.Build.0 = Release|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Release|x64.ActiveCfg = Release|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Release|x64.Build.0 = Release|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Release|x86.ActiveCfg = Release|Any CPU
{B8A58F84-9707-4B9C-9AE0-04DDE718E232}.Release|x86.Build.0 = Release|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Debug|x64.ActiveCfg = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Debug|x64.Build.0 = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Debug|x86.ActiveCfg = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Debug|x86.Build.0 = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.DebugNoTests|x64.ActiveCfg = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.DebugNoTests|x64.Build.0 = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.DebugNoTests|x86.ActiveCfg = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.DebugNoTests|x86.Build.0 = Debug|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Release|x64.ActiveCfg = Release|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Release|x64.Build.0 = Release|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Release|x86.ActiveCfg = Release|Any CPU
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2447,6 +2485,8 @@ Global
{E21DCE50-E36E-41B3-BE57-D908ACBE88E5} = {385CAD2D-0A5E-4F80-927B-D5499D126B90}
{129B31E3-1247-4D73-AA45-52D0B2B4C6FD} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90}
{496DFA71-4C35-49AE-95C1-4B802DB91615} = {385CAD2D-0A5E-4F80-927B-D5499D126B90}
{B8A58F84-9707-4B9C-9AE0-04DDE718E232} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90}
{20FB9D67-52BB-4C82-A5FE-BCA09B69CAC5} = {385CAD2D-0A5E-4F80-927B-D5499D126B90}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {543FAC75-2AF1-4EF1-9609-B242B63FEED4}