add files
This commit is contained in:
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/.signature.p7s
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/.signature.p7s
vendored
Normal file
Binary file not shown.
27
packages/Microsoft.Web.WebView2.1.0.961.33/LICENSE.txt
vendored
Normal file
27
packages/Microsoft.Web.WebView2.1.0.961.33/LICENSE.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* The name of Microsoft Corporation, or the names of its contributors
|
||||
may not be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/Microsoft.Web.WebView2.1.0.961.33.nupkg
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/Microsoft.Web.WebView2.1.0.961.33.nupkg
vendored
Normal file
Binary file not shown.
5178
packages/Microsoft.Web.WebView2.1.0.961.33/WebView2.idl
vendored
Normal file
5178
packages/Microsoft.Web.WebView2.1.0.961.33/WebView2.idl
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/WebView2.tlb
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/WebView2.tlb
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/Common.targets
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/Common.targets
vendored
Normal file
Binary file not shown.
23
packages/Microsoft.Web.WebView2.1.0.961.33/build/Microsoft.Web.WebView2.targets
vendored
Normal file
23
packages/Microsoft.Web.WebView2.1.0.961.33/build/Microsoft.Web.WebView2.targets
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- This build/.targets file is used by managed VS projects including win32
|
||||
apps and UWP apps. -->
|
||||
|
||||
<PropertyGroup>
|
||||
<WebView2ProjectKind>managed</WebView2ProjectKind>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- The managed targets file is under build
|
||||
so the root is one path segment up. -->
|
||||
<NugetRoot>$(MSBuildThisFileDirectory)..\</NugetRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Example logging
|
||||
<Target Name="WebView2ManagedEntryLog" BeforeTargets="Build">
|
||||
<Message Text="WebView2 managed .targets file. $(NugetRoot)" Importance="high"/>
|
||||
</Target>
|
||||
-->
|
||||
|
||||
<Import Project="$(NugetRoot)\build\Common.targets"/>
|
||||
</Project>
|
||||
22
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/Microsoft.Web.WebView2.targets
vendored
Normal file
22
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/Microsoft.Web.WebView2.targets
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- This build\native\.targets file is used by native (C++) VS projects including win32 and UWP. -->
|
||||
|
||||
<PropertyGroup>
|
||||
<WebView2ProjectKind>native</WebView2ProjectKind>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- The native targets file is under build\native
|
||||
so the root is two path segments up. -->
|
||||
<NugetRoot>$(MSBuildThisFileDirectory)..\..\</NugetRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Example logging
|
||||
<Target Name="WebView2NativeEntryLog" BeforeTargets="Build">
|
||||
<Message Text="WebView2 native .targets file. $(NugetRoot)" Importance="high"/>
|
||||
</Target>
|
||||
-->
|
||||
|
||||
<Import Project="$(NugetRoot)\build\Common.targets"/>
|
||||
</Project>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2Loader.dll
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2Loader.dll.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2Loader.dll.lib
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2LoaderStatic.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2LoaderStatic.lib
vendored
Normal file
Binary file not shown.
16558
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include/WebView2.h
vendored
Normal file
16558
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include/WebView2.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
144
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include/WebView2EnvironmentOptions.h
vendored
Normal file
144
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include/WebView2EnvironmentOptions.h
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef __core_webview2_environment_options_h__
|
||||
#define __core_webview2_environment_options_h__
|
||||
|
||||
#include <objbase.h>
|
||||
#include <wrl/implements.h>
|
||||
|
||||
#include "webview2.h"
|
||||
#define CORE_WEBVIEW_TARGET_PRODUCT_VERSION L"93.0.961.33"
|
||||
|
||||
#define COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(p) \
|
||||
public: \
|
||||
HRESULT STDMETHODCALLTYPE get_##p(LPWSTR* value) override { \
|
||||
if (!value) \
|
||||
return E_POINTER; \
|
||||
*value = m_##p.Copy(); \
|
||||
if ((*value == nullptr) && (m_##p.Get() != nullptr)) \
|
||||
return HRESULT_FROM_WIN32(GetLastError()); \
|
||||
return S_OK; \
|
||||
} \
|
||||
HRESULT STDMETHODCALLTYPE put_##p(LPCWSTR value) override { \
|
||||
LPCWSTR result = m_##p.Set(value); \
|
||||
if ((result == nullptr) && (value != nullptr)) \
|
||||
return HRESULT_FROM_WIN32(GetLastError()); \
|
||||
return S_OK; \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
AutoCoMemString m_##p;
|
||||
|
||||
#define COREWEBVIEW2ENVIRONMENTOPTIONS_BOOL_PROPERTY(p) \
|
||||
public: \
|
||||
HRESULT STDMETHODCALLTYPE get_##p(BOOL* value) override { \
|
||||
if (!value) \
|
||||
return E_POINTER; \
|
||||
*value = m_##p; \
|
||||
return S_OK; \
|
||||
} \
|
||||
HRESULT STDMETHODCALLTYPE put_##p(BOOL value) override { \
|
||||
m_##p = value; \
|
||||
return S_OK; \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
BOOL m_##p = FALSE;
|
||||
|
||||
// This is a base COM class that implements ICoreWebView2EnvironmentOptions.
|
||||
template <typename allocate_fn_t,
|
||||
allocate_fn_t allocate_fn,
|
||||
typename deallocate_fn_t,
|
||||
deallocate_fn_t deallocate_fn>
|
||||
class CoreWebView2EnvironmentOptionsBase
|
||||
: public Microsoft::WRL::Implements<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
ICoreWebView2EnvironmentOptions> {
|
||||
public:
|
||||
CoreWebView2EnvironmentOptionsBase() {
|
||||
// Initialize the target compatible browser version value to the version of
|
||||
// the browser binaries corresponding to this version of the SDK.
|
||||
m_TargetCompatibleBrowserVersion.Set(CORE_WEBVIEW_TARGET_PRODUCT_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
~CoreWebView2EnvironmentOptionsBase(){};
|
||||
|
||||
class AutoCoMemString {
|
||||
public:
|
||||
AutoCoMemString() {}
|
||||
~AutoCoMemString() { Release(); }
|
||||
void Release() {
|
||||
if (m_string) {
|
||||
deallocate_fn(m_string);
|
||||
m_string = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LPCWSTR Set(LPCWSTR str) {
|
||||
Release();
|
||||
if (str) {
|
||||
m_string = MakeCoMemString(str);
|
||||
}
|
||||
return m_string;
|
||||
}
|
||||
LPCWSTR Get() { return m_string; }
|
||||
LPWSTR Copy() {
|
||||
if (m_string)
|
||||
return MakeCoMemString(m_string);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
LPWSTR MakeCoMemString(LPCWSTR source) {
|
||||
const size_t length = wcslen(source);
|
||||
const size_t bytes = (length + 1) * sizeof(*source);
|
||||
// Ensure we didn't overflow during our size calculation.
|
||||
if (bytes <= length) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wchar_t* result = reinterpret_cast<wchar_t*>(allocate_fn(bytes));
|
||||
if (result)
|
||||
memcpy(result, source, bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LPWSTR m_string = nullptr;
|
||||
};
|
||||
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(AdditionalBrowserArguments)
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(Language)
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(TargetCompatibleBrowserVersion)
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_BOOL_PROPERTY(
|
||||
AllowSingleSignOnUsingOSPrimaryAccount)
|
||||
};
|
||||
|
||||
template <typename allocate_fn_t,
|
||||
allocate_fn_t allocate_fn,
|
||||
typename deallocate_fn_t,
|
||||
deallocate_fn_t deallocate_fn>
|
||||
class CoreWebView2EnvironmentOptionsBaseClass
|
||||
: public Microsoft::WRL::RuntimeClass<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
CoreWebView2EnvironmentOptionsBase<allocate_fn_t,
|
||||
allocate_fn,
|
||||
deallocate_fn_t,
|
||||
deallocate_fn>> {
|
||||
public:
|
||||
CoreWebView2EnvironmentOptionsBaseClass() {}
|
||||
|
||||
protected:
|
||||
~CoreWebView2EnvironmentOptionsBaseClass() override{};
|
||||
};
|
||||
|
||||
typedef CoreWebView2EnvironmentOptionsBaseClass<decltype(&::CoTaskMemAlloc),
|
||||
::CoTaskMemAlloc,
|
||||
decltype(&::CoTaskMemFree),
|
||||
::CoTaskMemFree>
|
||||
CoreWebView2EnvironmentOptions;
|
||||
|
||||
#endif // __core_webview2_environment_options_h__
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll.lib
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2LoaderStatic.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2LoaderStatic.lib
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2Loader.dll
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2Loader.dll.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2Loader.dll.lib
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2LoaderStatic.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2LoaderStatic.lib
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/Microsoft.Web.WebView2.Core.winmd
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/Microsoft.Web.WebView2.Core.winmd
vendored
Normal file
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Core.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Core.dll
vendored
Normal file
Binary file not shown.
4456
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Core.xml
vendored
Normal file
4456
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Core.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.WinForms.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.WinForms.dll
vendored
Normal file
Binary file not shown.
375
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.WinForms.xml
vendored
Normal file
375
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.WinForms.xml
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.WinForms</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> during implicit initialization.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.WebView2">
|
||||
<summary>
|
||||
Control to embed WebView2 in WinForms.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.#ctor">
|
||||
<summary>
|
||||
Create a new WebView2 WinForms control.
|
||||
After construction the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property is <c>null</c>.
|
||||
Call <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> to initialize the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the WebView2 COM API, which you can find documentation for here: https://aka.ms/webview2
|
||||
You can directly access the underlying ICoreWebView2 interface and all of its functionality by accessing the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property.
|
||||
Some of the most common COM functionality is also accessible directly through wrapper methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's CoreWebView2 property will be null.
|
||||
This is because creating the CoreWebView2 is an expensive operation which involves things like launching Edge browser processes.
|
||||
There are two ways to cause the CoreWebView2 to be created:
|
||||
1) Call the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is referred to as explicit initialization.
|
||||
2) Set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property. This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to EnsureCoreWebView2Async or set the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> property prior to initialization.
|
||||
|
||||
When initialization has finished (regardless of how it was triggered) then the following things will occur, in this order:
|
||||
1) The control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked. If you need to perform one time setup operations on the CoreWebView2 prior to its use then you should do so in a handler for that event.
|
||||
2) If a Uri has been set to the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property then the control will start navigating to it in the background (i.e. these steps will continue without waiting for the navigation to finish).
|
||||
3) The Task returned from <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will complete.
|
||||
|
||||
For more details about any of the methods/properties/events involved in the initialization process, see its specific documentation.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
You should avoid doing a lot of work in these handlers.
|
||||
</item>
|
||||
<item>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
Cleans up any resources being used.
|
||||
</summary>
|
||||
<param name="disposing"><c>true</c> if managed resources should be disposed; otherwise, <c>false</c>.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnPaint(System.Windows.Forms.PaintEventArgs)">
|
||||
<summary>
|
||||
Overrides the base OnPaint event to have custom actions
|
||||
in designer mode
|
||||
</summary>
|
||||
<param name="e">The graphics devices which is the source</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.WndProc(System.Windows.Forms.Message@)">
|
||||
<summary>
|
||||
Overrides the base WndProc events to handle specific window messages.
|
||||
</summary>
|
||||
<param name="m">The Message object containing the HWND window message and parameters</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
This property cannot be modified (an exception will be thrown) after initialization of the control's CoreWebView2 has started.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if initialization of the control's CoreWebView2 has already started.</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly trigger initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is initialized.
|
||||
If you pass <c>null</c> (the default value) then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes
|
||||
or on exceptions.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if this instance of <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is already disposed, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
This is the private function which implements the actual background initialization task.
|
||||
Cannot be called if the control is already initialized or has been disposed.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
The environment to use to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/>.
|
||||
If that is null then a default environment is created with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and its default parameters.
|
||||
</param>
|
||||
<returns>A task representing the background initialization process.</returns>
|
||||
<remarks>All the event handlers added here need to be removed in <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)"/>.</remarks>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreateParams">
|
||||
<summary>
|
||||
Protected CreateParams property. Used to set custom window styles to the forms HWND.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnVisibleChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected VisibilityChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnSizeChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected SizeChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Select(System.Boolean,System.Boolean)">
|
||||
<summary>
|
||||
Protected Select method: override this to capture tab direction when WebView control is activated
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnGotFocus(System.EventArgs)">
|
||||
<summary>
|
||||
Protected OnGotFocus handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.IsInitialized">
|
||||
<summary>
|
||||
True if initialization finished successfully and the control is not disposed yet.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GetSitedParentSite(System.Windows.Forms.Control)">
|
||||
<summary>
|
||||
Recursive retrieval of the parent control
|
||||
</summary>
|
||||
<param name="control">The control to get the parent for</param>
|
||||
<returns>The root parent control</returns>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
The underlying CoreWebView2. Use this property to perform more operations on the WebView2 content than is exposed
|
||||
on the WebView2. This value is null until it is initialized and the object itself has undefined behaviour once the control is disposed.
|
||||
You can force the underlying CoreWebView2 to
|
||||
initialize via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.</exception>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.Source">
|
||||
<summary>
|
||||
The Source property is the URI of the top level document of the
|
||||
WebView2. Setting the Source is equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>.
|
||||
Setting the Source will trigger initialization of the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>, if not already initialized.
|
||||
The default value of Source is <c>null</c>, indicating that the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.
|
||||
</summary>
|
||||
<exception cref="T:System.ArgumentException">Specified value is not an absolute <see cref="T:System.Uri"/>.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Specified value is <c>null</c> and the control is initialized.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns true if the webview can navigate to a next page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the webview can navigate to a previous page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes the provided script in the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates to the next page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates to the previous page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Renders the provided HTML as the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Stop">
|
||||
<summary>
|
||||
Stops any in progress navigation in the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either 1) when the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> has finished being initialized (regardless of how it was triggered or whether it succeeded) but before it is used for anything
|
||||
OR 2) the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the CoreWebView2 which you want to affect all of its usages
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the WebView2 control, whose CoreWebView2 property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is true.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
NavigationStarting dispatches before a new navigate starts for the top
|
||||
level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
NavigationCompleted dispatches after a navigate of the top level
|
||||
document completes rendering either successfully or not.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
WebMessageReceived dispatches after web content sends a message to the
|
||||
app host via <c>chrome.webview.postMessage</c>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.SourceChanged">
|
||||
<summary>
|
||||
SourceChanged dispatches after the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property changes. This may happen
|
||||
during a navigation or if otherwise the script in the page changes the
|
||||
URI of the document.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ContentLoading">
|
||||
<summary>
|
||||
ContentLoading dispatches after a navigation begins to a new URI and the
|
||||
content of that URI begins to render.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
ZoomFactorChanged dispatches when the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor"/> property changes.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.WinForms.WebView2.components">
|
||||
<summary>
|
||||
Required designer variable.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitializeComponent">
|
||||
<summary>
|
||||
Required method for Designer support - do not modify
|
||||
the contents of this method with the code editor.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Wpf.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Wpf.dll
vendored
Normal file
Binary file not shown.
800
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Wpf.xml
vendored
Normal file
800
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Wpf.xml
vendored
Normal file
@ -0,0 +1,800 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.Wpf</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> during implicit initialization.
|
||||
It is also a nice WPF integration utility which allows commonly used environment parameters to be dependency properties and be created and used in markup.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.LanguageProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.WebView2">
|
||||
<summary>
|
||||
A control to embed web content in a WPF application.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the [WebView2 COM
|
||||
API](https://aka.ms/webview2). You can directly access the underlying
|
||||
ICoreWebView2 interface and all of its functionality by accessing the
|
||||
<see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property. Some of the most common COM
|
||||
functionality is also accessible directly through wrapper
|
||||
methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be
|
||||
<c>null</c>. This is because creating the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is an
|
||||
expensive operation which involves things like launching Edge browser
|
||||
processes. There are two ways to cause the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to
|
||||
be created:
|
||||
<list type="bullet">
|
||||
<item><description>
|
||||
Call the <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is
|
||||
referred to as explicit initialization.
|
||||
</description></item>
|
||||
<item><description>
|
||||
Set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property (which could be done from
|
||||
markup, for example). This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return
|
||||
back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass
|
||||
your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> or set the control's <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property prior to initialization.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
When initialization has finished (regardless of how it was triggered or
|
||||
whether it succeeded) then the following things will occur, in this
|
||||
order:
|
||||
<list type="number">
|
||||
<item><description>
|
||||
The control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event
|
||||
will be invoked. If you need to perform one time setup operations on
|
||||
the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> prior to its use then you should
|
||||
do so in a handler for that event.
|
||||
</description></item>
|
||||
<item><description>
|
||||
If initialization was successful and a Uri has been set to the <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property then the control will start navigating to it in
|
||||
the background (i.e. these steps will continue without waiting for the
|
||||
navigation to finish).
|
||||
</description></item>
|
||||
<item><description>
|
||||
The Task returned from <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will
|
||||
complete.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
For more details about any of the methods/properties/events involved in
|
||||
the initialization process, see its specific documentation.
|
||||
|
||||
Because the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is a very heavyweight
|
||||
object (potentially responsible for multiple running processes and
|
||||
megabytes of disk space) the control implements <see
|
||||
cref="T:System.IDisposable"/> to provide an explicit means to free it.
|
||||
Calling <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> will release the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>
|
||||
and its underlying resources (except any that are also being used by other
|
||||
WebViews), and reset <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to <c>null</c>. After <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has been called the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> cannot be
|
||||
re-initialized, and any attempt to use functionality which requires it
|
||||
will throw an <see cref="T:System.ObjectDisposedException"/>.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
<description>You should avoid doing a lot of work in these handlers.</description>
|
||||
</item>
|
||||
<item><description>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</description></item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
|
||||
Note that this control extends <see cref="T:System.Windows.Interop.HwndHost"/> in order to embed
|
||||
windows which live outside of the WPF ecosystem. This has some
|
||||
implications regarding the control's input and output behavior as well as
|
||||
the functionality it "inherits" from <see cref="T:System.Windows.UIElement"/> and <see
|
||||
cref="T:System.Windows.FrameworkElement"/>.
|
||||
See the <see cref="T:System.Windows.Interop.HwndHost"/> and [WPF/Win32
|
||||
interop](https://docs.microsoft.com/dotnet/framework/wpf/advanced/wpf-and-win32-interoperation#hwnds-inside-wpf)
|
||||
documentation for more information.
|
||||
</remarks>
|
||||
<seealso cref="T:System.Windows.Interop.HwndHost"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of a WebView2 control.
|
||||
Note that the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> will be null until initialized.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CreationPropertiesProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
</summary>
|
||||
<seealso cref="T:System.Windows.DependencyProperty"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
Setting this property will not work after initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has started (the old value will be retained).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BuildWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to create our HWND.
|
||||
</summary>
|
||||
<param name="hwndParent">The HWND that we should use as the parent of the one we create.</param>
|
||||
<returns>The HWND that we created.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.BuildWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to destroy our HWND.
|
||||
</summary>
|
||||
<param name="hwnd">Our HWND that we need to destroy.</param>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to provide us with Win32 messages that are sent to our hwnd.
|
||||
</summary>
|
||||
<param name="hwnd">Window receiving the message (should always match our <see cref="P:System.Windows.Interop.HwndHost.Handle"/>).</param>
|
||||
<param name="msg">Indicates the message being received. See Win32 documentation for WM_* constant values.</param>
|
||||
<param name="wParam">The "wParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="lParam">The "lParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="handled">If true then the message will not be forwarded to any (more) <see cref="E:System.Windows.Interop.HwndHost.MessageHook"/> handlers.</param>
|
||||
<returns>Return value varies by message.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnRender(System.Windows.Media.DrawingContext)">
|
||||
<summary>
|
||||
Override for painting to draw
|
||||
</summary>
|
||||
<param name="dc">The tools to handle the drawing via <see cref="T:System.Windows.Media.DrawingContext"/>.</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
Accesses the complete functionality of the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> COM API.
|
||||
Returns <c>null</c> until initialization has completed.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either
|
||||
1) when the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has finished being initialized (regardless of how initialization was triggered) but before it is used for anything, or
|
||||
2) if the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> which you want to affect all of its usages.
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whose <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is <c>true</c>.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly triggers initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> is initialized.
|
||||
If you pass an environment to this method then it will override any settings specified on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
If you pass <c>null</c> (the default value) and no value has been set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
Note that even though this method is asynchronous and returns a Task, it still must be called on the UI thread like most public functionality of most UI controls.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
This is called by our base class according to the typical implementation of the <see cref="T:System.IDisposable"/> pattern.
|
||||
We implement it by releasing all of our underlying COM resources, including our <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="disposing">True if a caller is explicitly calling Dispose, false if we're being finalized.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ProcessFailed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ProcessFailedEvent
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Prevents the control from implicitly initializing its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> until <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit"/> is called.
|
||||
Does *not* prevent explicit initialization of the CoreWebView2 (i.e. <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>).
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
Note that the "Initialize" in ISupportInitialize and the "Init" in BeginInit/EndInit mean
|
||||
something different and more general than this control's specific concept of initializing
|
||||
its CoreWebView2 (explicitly or implicitly). This ISupportInitialize pattern is a general
|
||||
way to set batches of properties on the control to their initial values without triggering
|
||||
any dependent side effects until all of the values are set (i.e. until EndInit is called).
|
||||
In the case of this control, a specific side effect to be avoided is triggering implicit
|
||||
initialization of the CoreWebView2 when setting the Source property.
|
||||
For example, normally if you set <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> after you've already set Source,
|
||||
the data set to CreationProperties is ignored because implicit initialization has already started.
|
||||
However, if you set the two properties (in the same order) in between calls to BeginInit and
|
||||
EndInit then the implicit initialization of the CoreWebView2 is delayed until EndInit, so the data
|
||||
set to CreationProperties is still used even though it was set after Source.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Invokes any functionality that has been delayed since the corresponding call to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/>.
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
See the documentation of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/> for more information.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WhenInit_Source(System.Action)">
|
||||
<summary>
|
||||
Specifies a Source-related action to be invoked but which must be delayed if BeginInit has already been called but EndInit hasn't.
|
||||
If the control is currently between BeginInit/EndInit calls then the action will be invoked during EndInit.
|
||||
Otherwise the action will be invoked immediately.
|
||||
If this is called multiple times between BeginInit/EndInit then the action passed to the last call is the only one that will be invoked during EndInit.
|
||||
</summary>
|
||||
<param name="action">The Source-related action to invoke, delayed until EndInit if necessary.</param>
|
||||
<remarks>
|
||||
In the future if we need this delayed-invoke functionality for actions unrelated to Source,
|
||||
then we should generalize _initAction_Source to a list and generalize this method to take a list index along with the action.
|
||||
Then we can just assign each index to a different potential action (e.g. 0 for Source), and potentially use constants to name the indices.
|
||||
For now it didn't seem worth dynamically allocating a list for one thing,
|
||||
but I still wanted to keep the delay-or-not logic abstracted away from the Source setter.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SetCurrentValueFromCore(System.Windows.DependencyProperty,System.Object)">
|
||||
<summary>
|
||||
Updates one of our dependency properties to match a new value from the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
It both sets the value and remembers (in _propertyChangingFromCore) that it came from the CoreWebView2 rather than the caller,
|
||||
allowing the property's "on changed" handler to alter its behavior based on where the new value came from.
|
||||
It's only intended to be called in a CoreWebView2 event handler that's informing us of a new property value.
|
||||
It's basically just a wrapper around the inherited SetCurrentValue which also maintains _propertyChangingFromCore.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
One more thing worth explicitly stating is that it wraps SetCurrentValue rather than SetValue,
|
||||
in order to avoid overwriting any OneWay bindings that are set on the specified properties.
|
||||
Check the link https://stackoverflow.com/q/4230698 for more information about the difference between SetValue and SetCurrentValue.
|
||||
</summary>
|
||||
<param name="property">The property to change due to an equivalent change in the CoreWebView2.</param>
|
||||
<param name="value">The new value from the CoreWebView2.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)">
|
||||
<summary>
|
||||
Checks if a given property is currently being updated to match an equivalent change in the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
This method should only be called from a property's "on changed" handler; it has no meaning at any other time.
|
||||
It is used to determine if the property is changing to match the CoreWebView2 or because the caller set it.
|
||||
Usually this is used in order to decide if the new value needs to be propagated down to the CoreWebView2.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
</summary>
|
||||
<param name="property">The property to check.</param>
|
||||
<returns>True if the property is changing to match the CoreWebView2, or false if the property was changed by the caller.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ReparentController(System.IntPtr,System.Boolean)">
|
||||
<summary>
|
||||
Changes our controller's ParentWindow to the given HWND, along with any other necessary associated work.
|
||||
</summary>
|
||||
<param name="hwnd">The new HWND to set as the controller's parent. IntPtr.Zero means that the controller will have no parent and the CoreWebView2 will be hidden.</param>
|
||||
<param name="sync">Whether or not to call <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow"/> as required. Defaults to true. If you pass false then you should call it yourself if required.</param>
|
||||
<remarks>
|
||||
Reparenting the controller isn't necessarily as simple as changing its ParentWindow property,
|
||||
and this method exists to ensure that any other work that needs to be done at the same time gets done.
|
||||
The reason that SyncControllerWithParentWindow isn't baked directly into this method is because
|
||||
sometimes we want to call the Sync functionality without necessarily reparenting (e.g. during initialization).
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow">
|
||||
<summary>
|
||||
Syncs visual/windowing information between the controller and its parent HWND.
|
||||
This should be called any time a new, non-null HWND is set as the controller's parent,
|
||||
including when the controller is first created.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.UIElement_IsVisibleChanged(System.Object,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a handler for our base UIElement's IsVisibleChanged event.
|
||||
It's predictably fired whenever IsVisible changes, and IsVisible reflects the actual current visibility status of the control.
|
||||
We just need to pass this info through to our CoreWebView2Controller so it can save some effort when the control isn't visible.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnWindowPositionChanged(System.Windows.Rect)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and called when our control's location has changed.
|
||||
The HwndHost takes care of updating the HWND we created.
|
||||
What we need to do is move our CoreWebView2 to match the new location.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.SourceProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.Source">
|
||||
<summary>
|
||||
The top-level <see cref="T:System.Uri"/> which the WebView is currently displaying (or will display once initialization of its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is finished).
|
||||
Generally speaking, getting this property is equivalent to getting the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.Source"/> property and setting this property (to a different value) is equivalent to calling the <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/> method.
|
||||
</summary>
|
||||
<remarks>
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last Uri which was set to it, or null (the default) if none has been.
|
||||
Setting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will cause initialization to start in the background (if not already in progress), after which the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> will navigate to the specified <see cref="T:System.Uri"/>.
|
||||
This property can never be set back to null or to a relative <see cref="T:System.Uri"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Thrown if the property is set to <c>null</c>.</exception>
|
||||
<exception cref="T:System.ArgumentException">Thrown if the property is set to a relative <see cref="T:System.Uri"/> (i.e. a <see cref="T:System.Uri"/> whose <see cref="P:System.Uri.IsAbsoluteUri"/> property is <c>false</c>).</exception>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyValid(System.Object)">
|
||||
<summary>
|
||||
This is a callback that WPF calls to validate a potential new Source value.
|
||||
</summary>
|
||||
<returns>
|
||||
True if the value is valid, false if it is not.
|
||||
If we return false then WPF should respond by throwing an <see cref="T:System.ArgumentException"/>.
|
||||
</returns>
|
||||
<remarks>
|
||||
Note that we unfortunately can't treat null as invalid here because null is valid prior to initialization.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when the WPF Source property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set Source to programmatically trigger a navigation.
|
||||
2) The CoreWebView changed its own source and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.SourceChanged">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_SourceChanged(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2SourceChangedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's SourceChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2's source URI has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The CoreWebView2 was told to navigate programmatically (potentially by us, see SourcePropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. clicked a link.
|
||||
In either of the above cases, this event might trigger several times due to e.g. redirection.
|
||||
Aside from propagating to our own event, we just need to update our WPF Source property to match the CoreWebView2's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationStarting(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationStarting event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationCompleted(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationCompleted event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_HistoryChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's HistoryChanged event.
|
||||
We're handling it in order to update our WPF CanGoBack and CanGoForward properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBackProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a previous page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForwardProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a next page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.TabIntoCore(System.Windows.Input.TraversalRequest)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to inform us that tabbing has caused the focus to move into our control/window.
|
||||
Since WPF can't manage the transition of focus to a non-WPF HWND, it delegates the transition to us here.
|
||||
So our job is just to place the focus in our external HWND.
|
||||
</summary>
|
||||
<param name="request">Information about how the focus is moving.</param>
|
||||
<returns><c>true</c> to indicate that we handled the navigation, or <c>false</c> to indicate that we didn't.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and is called to inform us when we receive the keyboard focus.
|
||||
We handle this by passing the keyboard focus on to the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
We never want to land in a state where our window (this.Handle) actually has the keyboard focus.
|
||||
</summary>
|
||||
<param name="e">Arguments from the underlying GotKeyboardFocus event.</param>
|
||||
<remarks>
|
||||
Note that it's actually possible for us to receive keyboard focus without this method being called.
|
||||
One known case where that happens is when our parent window is deactivated while we have focus, then reactivated.
|
||||
We handle that case in <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>.
|
||||
</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_MoveFocusRequested(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2MoveFocusRequestedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's MoveFocusRequested event.
|
||||
It fires when the CoreWebView2Controller has focus but wants to move it elsewhere in the app.
|
||||
E.g. this happens when the user tabs past the last item in the CoreWebView2 and focus needs to return to some other app control.
|
||||
So our job is just to tell WPF to move the focus on to the next control.
|
||||
Note that we don't propagate this event outward as a standard WPF routed event because we've implemented its purpose here.
|
||||
If users of the control want to track focus shifting in/out of the control, they should use standard WPF events.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_GotFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's GotFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_LostFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's LostFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_AcceleratorKeyPressed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2AcceleratorKeyPressedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's AcceleratorKeyPressed event.
|
||||
This is called to inform us about key presses that are likely to have special behavior (e.g. esc, return, Function keys, letters with modifier keys).
|
||||
WPF can't detect this input because Windows sends it directly to the Win32 CoreWebView2Controller control.
|
||||
We implement this by generating standard WPF key input events, allowing callers to handle the input in the usual WPF way if they want.
|
||||
If nobody handles the WPF key events then we'll allow the default CoreWebView2Controller logic (if any) to handle it.
|
||||
Of the possible options, this implementation should provide the most flexibility to callers.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and called to allow us to handle key press input.
|
||||
WPF should never actually call this in response to keyboard events because we're hosting a non-WPF window.
|
||||
When our window has focus Windows will send the input directly to it rather than to WPF's top-level window and input system.
|
||||
This override should only be called when we're explicitly forwarding accelerator key input from the CoreWebView2 to WPF (in CoreWebView2Controller_AcceleratorKeyPressed).
|
||||
Even then, this KeyDownEvent is only triggered because our PreviewKeyDownEvent implementation explicitly triggers it, matching WPF's usual system.
|
||||
So the process is:
|
||||
<list type="number">
|
||||
<item><description>CoreWebView2Controller_AcceleratorKeyPressed</description></item>
|
||||
<item><description>PreviewKeyDownEvent</description></item>
|
||||
<item><description>KeyDownEvent</description></item>
|
||||
<item><description>OnKeyDown</description></item>
|
||||
</list>
|
||||
.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is the "Preview" (i.e. tunneling) version of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>, so it actually happens first.
|
||||
Like OnKeyDown, this will only ever be called if we're explicitly forwarding key presses from the CoreWebView2.
|
||||
In order to mimic WPF's standard input handling, when we receive this we turn around and fire off the standard bubbling KeyDownEvent.
|
||||
That way others in the WPF tree see the same standard pair of input events that WPF itself would have triggered if it were handling the key press.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last value which was set to it, or <c>1.0</c> (the default) if none has been.
|
||||
The most recent value set to this property before the CoreWebView2 has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF ZoomFactor property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set ZoomFactor to change the zoom of the CoreWebView2.
|
||||
2) The CoreWebView2 changed its own ZoomFactor and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
The event is raised when the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property changes.
|
||||
This event directly exposes <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_ZoomFactorChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's ZoomFactorChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2Controller's ZoomFactor has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The value was changed programmatically (potentially by us, see ZoomFactorPropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. CTRL + Mouse Wheel.
|
||||
Aside from propagating to our own event, we just need to update our WPF ZoomFactor property to match the CoreWebView2Controller's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.DefaultBackgroundColor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/> has been initialized will retrieve the last value which was
|
||||
set to it, or <c>Color.White</c> (the default) if none has been.
|
||||
The most recent value set to this property before CoreWebView2Controller has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF DefaultBackgroundColor property's value changes.
|
||||
Since CoreWebView2Controller does not update this property itself, this is only triggered by the
|
||||
caller setting DefaultBackgroundColor.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor">
|
||||
<summary>
|
||||
The foreground color to be used in design mode.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates the WebView to the previous page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates the WebView to the next page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the current page.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Stop">
|
||||
<summary>
|
||||
Stops all navigations and pending resource fetches.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Initiates a navigation to htmlContent as source HTML of a new document.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ContentLoading">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ContentLoading(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ContentLoadingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ContentLoading event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes JavaScript code from the javaScript parameter in the current top level document rendered in the WebView.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_WebMessageReceived(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's WebMessageReceived event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.IsInDesignMode">
|
||||
<summary>
|
||||
True when we're in design mode and shouldn't create an underlying CoreWebView2.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Core.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Core.dll
vendored
Normal file
Binary file not shown.
4456
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Core.xml
vendored
Normal file
4456
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Core.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.WinForms.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.WinForms.dll
vendored
Normal file
Binary file not shown.
375
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.WinForms.xml
vendored
Normal file
375
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.WinForms.xml
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.WinForms</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> during implicit initialization.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.WebView2">
|
||||
<summary>
|
||||
Control to embed WebView2 in WinForms.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.#ctor">
|
||||
<summary>
|
||||
Create a new WebView2 WinForms control.
|
||||
After construction the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property is <c>null</c>.
|
||||
Call <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> to initialize the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the WebView2 COM API, which you can find documentation for here: https://aka.ms/webview2
|
||||
You can directly access the underlying ICoreWebView2 interface and all of its functionality by accessing the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property.
|
||||
Some of the most common COM functionality is also accessible directly through wrapper methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's CoreWebView2 property will be null.
|
||||
This is because creating the CoreWebView2 is an expensive operation which involves things like launching Edge browser processes.
|
||||
There are two ways to cause the CoreWebView2 to be created:
|
||||
1) Call the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is referred to as explicit initialization.
|
||||
2) Set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property. This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to EnsureCoreWebView2Async or set the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> property prior to initialization.
|
||||
|
||||
When initialization has finished (regardless of how it was triggered) then the following things will occur, in this order:
|
||||
1) The control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked. If you need to perform one time setup operations on the CoreWebView2 prior to its use then you should do so in a handler for that event.
|
||||
2) If a Uri has been set to the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property then the control will start navigating to it in the background (i.e. these steps will continue without waiting for the navigation to finish).
|
||||
3) The Task returned from <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will complete.
|
||||
|
||||
For more details about any of the methods/properties/events involved in the initialization process, see its specific documentation.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
You should avoid doing a lot of work in these handlers.
|
||||
</item>
|
||||
<item>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
Cleans up any resources being used.
|
||||
</summary>
|
||||
<param name="disposing"><c>true</c> if managed resources should be disposed; otherwise, <c>false</c>.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnPaint(System.Windows.Forms.PaintEventArgs)">
|
||||
<summary>
|
||||
Overrides the base OnPaint event to have custom actions
|
||||
in designer mode
|
||||
</summary>
|
||||
<param name="e">The graphics devices which is the source</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.WndProc(System.Windows.Forms.Message@)">
|
||||
<summary>
|
||||
Overrides the base WndProc events to handle specific window messages.
|
||||
</summary>
|
||||
<param name="m">The Message object containing the HWND window message and parameters</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
This property cannot be modified (an exception will be thrown) after initialization of the control's CoreWebView2 has started.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if initialization of the control's CoreWebView2 has already started.</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly trigger initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is initialized.
|
||||
If you pass <c>null</c> (the default value) then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes
|
||||
or on exceptions.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if this instance of <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is already disposed, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
This is the private function which implements the actual background initialization task.
|
||||
Cannot be called if the control is already initialized or has been disposed.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
The environment to use to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/>.
|
||||
If that is null then a default environment is created with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and its default parameters.
|
||||
</param>
|
||||
<returns>A task representing the background initialization process.</returns>
|
||||
<remarks>All the event handlers added here need to be removed in <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)"/>.</remarks>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreateParams">
|
||||
<summary>
|
||||
Protected CreateParams property. Used to set custom window styles to the forms HWND.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnVisibleChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected VisibilityChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnSizeChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected SizeChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Select(System.Boolean,System.Boolean)">
|
||||
<summary>
|
||||
Protected Select method: override this to capture tab direction when WebView control is activated
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnGotFocus(System.EventArgs)">
|
||||
<summary>
|
||||
Protected OnGotFocus handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.IsInitialized">
|
||||
<summary>
|
||||
True if initialization finished successfully and the control is not disposed yet.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GetSitedParentSite(System.Windows.Forms.Control)">
|
||||
<summary>
|
||||
Recursive retrieval of the parent control
|
||||
</summary>
|
||||
<param name="control">The control to get the parent for</param>
|
||||
<returns>The root parent control</returns>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
The underlying CoreWebView2. Use this property to perform more operations on the WebView2 content than is exposed
|
||||
on the WebView2. This value is null until it is initialized and the object itself has undefined behaviour once the control is disposed.
|
||||
You can force the underlying CoreWebView2 to
|
||||
initialize via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.</exception>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.Source">
|
||||
<summary>
|
||||
The Source property is the URI of the top level document of the
|
||||
WebView2. Setting the Source is equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>.
|
||||
Setting the Source will trigger initialization of the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>, if not already initialized.
|
||||
The default value of Source is <c>null</c>, indicating that the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.
|
||||
</summary>
|
||||
<exception cref="T:System.ArgumentException">Specified value is not an absolute <see cref="T:System.Uri"/>.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Specified value is <c>null</c> and the control is initialized.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns true if the webview can navigate to a next page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the webview can navigate to a previous page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes the provided script in the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates to the next page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates to the previous page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Renders the provided HTML as the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Stop">
|
||||
<summary>
|
||||
Stops any in progress navigation in the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either 1) when the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> has finished being initialized (regardless of how it was triggered or whether it succeeded) but before it is used for anything
|
||||
OR 2) the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the CoreWebView2 which you want to affect all of its usages
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the WebView2 control, whose CoreWebView2 property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is true.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
NavigationStarting dispatches before a new navigate starts for the top
|
||||
level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
NavigationCompleted dispatches after a navigate of the top level
|
||||
document completes rendering either successfully or not.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
WebMessageReceived dispatches after web content sends a message to the
|
||||
app host via <c>chrome.webview.postMessage</c>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.SourceChanged">
|
||||
<summary>
|
||||
SourceChanged dispatches after the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property changes. This may happen
|
||||
during a navigation or if otherwise the script in the page changes the
|
||||
URI of the document.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ContentLoading">
|
||||
<summary>
|
||||
ContentLoading dispatches after a navigation begins to a new URI and the
|
||||
content of that URI begins to render.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
ZoomFactorChanged dispatches when the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor"/> property changes.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.WinForms.WebView2.components">
|
||||
<summary>
|
||||
Required designer variable.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitializeComponent">
|
||||
<summary>
|
||||
Required method for Designer support - do not modify
|
||||
the contents of this method with the code editor.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Wpf.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Wpf.dll
vendored
Normal file
Binary file not shown.
800
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Wpf.xml
vendored
Normal file
800
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Wpf.xml
vendored
Normal file
@ -0,0 +1,800 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.Wpf</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> during implicit initialization.
|
||||
It is also a nice WPF integration utility which allows commonly used environment parameters to be dependency properties and be created and used in markup.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.LanguageProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.WebView2">
|
||||
<summary>
|
||||
A control to embed web content in a WPF application.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the [WebView2 COM
|
||||
API](https://aka.ms/webview2). You can directly access the underlying
|
||||
ICoreWebView2 interface and all of its functionality by accessing the
|
||||
<see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property. Some of the most common COM
|
||||
functionality is also accessible directly through wrapper
|
||||
methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be
|
||||
<c>null</c>. This is because creating the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is an
|
||||
expensive operation which involves things like launching Edge browser
|
||||
processes. There are two ways to cause the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to
|
||||
be created:
|
||||
<list type="bullet">
|
||||
<item><description>
|
||||
Call the <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is
|
||||
referred to as explicit initialization.
|
||||
</description></item>
|
||||
<item><description>
|
||||
Set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property (which could be done from
|
||||
markup, for example). This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return
|
||||
back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass
|
||||
your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> or set the control's <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property prior to initialization.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
When initialization has finished (regardless of how it was triggered or
|
||||
whether it succeeded) then the following things will occur, in this
|
||||
order:
|
||||
<list type="number">
|
||||
<item><description>
|
||||
The control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event
|
||||
will be invoked. If you need to perform one time setup operations on
|
||||
the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> prior to its use then you should
|
||||
do so in a handler for that event.
|
||||
</description></item>
|
||||
<item><description>
|
||||
If initialization was successful and a Uri has been set to the <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property then the control will start navigating to it in
|
||||
the background (i.e. these steps will continue without waiting for the
|
||||
navigation to finish).
|
||||
</description></item>
|
||||
<item><description>
|
||||
The Task returned from <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will
|
||||
complete.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
For more details about any of the methods/properties/events involved in
|
||||
the initialization process, see its specific documentation.
|
||||
|
||||
Because the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is a very heavyweight
|
||||
object (potentially responsible for multiple running processes and
|
||||
megabytes of disk space) the control implements <see
|
||||
cref="T:System.IDisposable"/> to provide an explicit means to free it.
|
||||
Calling <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> will release the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>
|
||||
and its underlying resources (except any that are also being used by other
|
||||
WebViews), and reset <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to <c>null</c>. After <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has been called the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> cannot be
|
||||
re-initialized, and any attempt to use functionality which requires it
|
||||
will throw an <see cref="T:System.ObjectDisposedException"/>.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
<description>You should avoid doing a lot of work in these handlers.</description>
|
||||
</item>
|
||||
<item><description>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</description></item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
|
||||
Note that this control extends <see cref="T:System.Windows.Interop.HwndHost"/> in order to embed
|
||||
windows which live outside of the WPF ecosystem. This has some
|
||||
implications regarding the control's input and output behavior as well as
|
||||
the functionality it "inherits" from <see cref="T:System.Windows.UIElement"/> and <see
|
||||
cref="T:System.Windows.FrameworkElement"/>.
|
||||
See the <see cref="T:System.Windows.Interop.HwndHost"/> and [WPF/Win32
|
||||
interop](https://docs.microsoft.com/dotnet/framework/wpf/advanced/wpf-and-win32-interoperation#hwnds-inside-wpf)
|
||||
documentation for more information.
|
||||
</remarks>
|
||||
<seealso cref="T:System.Windows.Interop.HwndHost"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of a WebView2 control.
|
||||
Note that the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> will be null until initialized.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CreationPropertiesProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
</summary>
|
||||
<seealso cref="T:System.Windows.DependencyProperty"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
Setting this property will not work after initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has started (the old value will be retained).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BuildWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to create our HWND.
|
||||
</summary>
|
||||
<param name="hwndParent">The HWND that we should use as the parent of the one we create.</param>
|
||||
<returns>The HWND that we created.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.BuildWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to destroy our HWND.
|
||||
</summary>
|
||||
<param name="hwnd">Our HWND that we need to destroy.</param>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to provide us with Win32 messages that are sent to our hwnd.
|
||||
</summary>
|
||||
<param name="hwnd">Window receiving the message (should always match our <see cref="P:System.Windows.Interop.HwndHost.Handle"/>).</param>
|
||||
<param name="msg">Indicates the message being received. See Win32 documentation for WM_* constant values.</param>
|
||||
<param name="wParam">The "wParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="lParam">The "lParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="handled">If true then the message will not be forwarded to any (more) <see cref="E:System.Windows.Interop.HwndHost.MessageHook"/> handlers.</param>
|
||||
<returns>Return value varies by message.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnRender(System.Windows.Media.DrawingContext)">
|
||||
<summary>
|
||||
Override for painting to draw
|
||||
</summary>
|
||||
<param name="dc">The tools to handle the drawing via <see cref="T:System.Windows.Media.DrawingContext"/>.</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
Accesses the complete functionality of the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> COM API.
|
||||
Returns <c>null</c> until initialization has completed.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either
|
||||
1) when the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has finished being initialized (regardless of how initialization was triggered) but before it is used for anything, or
|
||||
2) if the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> which you want to affect all of its usages.
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whose <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is <c>true</c>.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly triggers initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> is initialized.
|
||||
If you pass an environment to this method then it will override any settings specified on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
If you pass <c>null</c> (the default value) and no value has been set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
Note that even though this method is asynchronous and returns a Task, it still must be called on the UI thread like most public functionality of most UI controls.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
This is called by our base class according to the typical implementation of the <see cref="T:System.IDisposable"/> pattern.
|
||||
We implement it by releasing all of our underlying COM resources, including our <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="disposing">True if a caller is explicitly calling Dispose, false if we're being finalized.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ProcessFailed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ProcessFailedEvent
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Prevents the control from implicitly initializing its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> until <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit"/> is called.
|
||||
Does *not* prevent explicit initialization of the CoreWebView2 (i.e. <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>).
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
Note that the "Initialize" in ISupportInitialize and the "Init" in BeginInit/EndInit mean
|
||||
something different and more general than this control's specific concept of initializing
|
||||
its CoreWebView2 (explicitly or implicitly). This ISupportInitialize pattern is a general
|
||||
way to set batches of properties on the control to their initial values without triggering
|
||||
any dependent side effects until all of the values are set (i.e. until EndInit is called).
|
||||
In the case of this control, a specific side effect to be avoided is triggering implicit
|
||||
initialization of the CoreWebView2 when setting the Source property.
|
||||
For example, normally if you set <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> after you've already set Source,
|
||||
the data set to CreationProperties is ignored because implicit initialization has already started.
|
||||
However, if you set the two properties (in the same order) in between calls to BeginInit and
|
||||
EndInit then the implicit initialization of the CoreWebView2 is delayed until EndInit, so the data
|
||||
set to CreationProperties is still used even though it was set after Source.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Invokes any functionality that has been delayed since the corresponding call to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/>.
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
See the documentation of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/> for more information.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WhenInit_Source(System.Action)">
|
||||
<summary>
|
||||
Specifies a Source-related action to be invoked but which must be delayed if BeginInit has already been called but EndInit hasn't.
|
||||
If the control is currently between BeginInit/EndInit calls then the action will be invoked during EndInit.
|
||||
Otherwise the action will be invoked immediately.
|
||||
If this is called multiple times between BeginInit/EndInit then the action passed to the last call is the only one that will be invoked during EndInit.
|
||||
</summary>
|
||||
<param name="action">The Source-related action to invoke, delayed until EndInit if necessary.</param>
|
||||
<remarks>
|
||||
In the future if we need this delayed-invoke functionality for actions unrelated to Source,
|
||||
then we should generalize _initAction_Source to a list and generalize this method to take a list index along with the action.
|
||||
Then we can just assign each index to a different potential action (e.g. 0 for Source), and potentially use constants to name the indices.
|
||||
For now it didn't seem worth dynamically allocating a list for one thing,
|
||||
but I still wanted to keep the delay-or-not logic abstracted away from the Source setter.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SetCurrentValueFromCore(System.Windows.DependencyProperty,System.Object)">
|
||||
<summary>
|
||||
Updates one of our dependency properties to match a new value from the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
It both sets the value and remembers (in _propertyChangingFromCore) that it came from the CoreWebView2 rather than the caller,
|
||||
allowing the property's "on changed" handler to alter its behavior based on where the new value came from.
|
||||
It's only intended to be called in a CoreWebView2 event handler that's informing us of a new property value.
|
||||
It's basically just a wrapper around the inherited SetCurrentValue which also maintains _propertyChangingFromCore.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
One more thing worth explicitly stating is that it wraps SetCurrentValue rather than SetValue,
|
||||
in order to avoid overwriting any OneWay bindings that are set on the specified properties.
|
||||
Check the link https://stackoverflow.com/q/4230698 for more information about the difference between SetValue and SetCurrentValue.
|
||||
</summary>
|
||||
<param name="property">The property to change due to an equivalent change in the CoreWebView2.</param>
|
||||
<param name="value">The new value from the CoreWebView2.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)">
|
||||
<summary>
|
||||
Checks if a given property is currently being updated to match an equivalent change in the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
This method should only be called from a property's "on changed" handler; it has no meaning at any other time.
|
||||
It is used to determine if the property is changing to match the CoreWebView2 or because the caller set it.
|
||||
Usually this is used in order to decide if the new value needs to be propagated down to the CoreWebView2.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
</summary>
|
||||
<param name="property">The property to check.</param>
|
||||
<returns>True if the property is changing to match the CoreWebView2, or false if the property was changed by the caller.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ReparentController(System.IntPtr,System.Boolean)">
|
||||
<summary>
|
||||
Changes our controller's ParentWindow to the given HWND, along with any other necessary associated work.
|
||||
</summary>
|
||||
<param name="hwnd">The new HWND to set as the controller's parent. IntPtr.Zero means that the controller will have no parent and the CoreWebView2 will be hidden.</param>
|
||||
<param name="sync">Whether or not to call <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow"/> as required. Defaults to true. If you pass false then you should call it yourself if required.</param>
|
||||
<remarks>
|
||||
Reparenting the controller isn't necessarily as simple as changing its ParentWindow property,
|
||||
and this method exists to ensure that any other work that needs to be done at the same time gets done.
|
||||
The reason that SyncControllerWithParentWindow isn't baked directly into this method is because
|
||||
sometimes we want to call the Sync functionality without necessarily reparenting (e.g. during initialization).
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow">
|
||||
<summary>
|
||||
Syncs visual/windowing information between the controller and its parent HWND.
|
||||
This should be called any time a new, non-null HWND is set as the controller's parent,
|
||||
including when the controller is first created.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.UIElement_IsVisibleChanged(System.Object,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a handler for our base UIElement's IsVisibleChanged event.
|
||||
It's predictably fired whenever IsVisible changes, and IsVisible reflects the actual current visibility status of the control.
|
||||
We just need to pass this info through to our CoreWebView2Controller so it can save some effort when the control isn't visible.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnWindowPositionChanged(System.Windows.Rect)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and called when our control's location has changed.
|
||||
The HwndHost takes care of updating the HWND we created.
|
||||
What we need to do is move our CoreWebView2 to match the new location.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.SourceProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.Source">
|
||||
<summary>
|
||||
The top-level <see cref="T:System.Uri"/> which the WebView is currently displaying (or will display once initialization of its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is finished).
|
||||
Generally speaking, getting this property is equivalent to getting the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.Source"/> property and setting this property (to a different value) is equivalent to calling the <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/> method.
|
||||
</summary>
|
||||
<remarks>
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last Uri which was set to it, or null (the default) if none has been.
|
||||
Setting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will cause initialization to start in the background (if not already in progress), after which the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> will navigate to the specified <see cref="T:System.Uri"/>.
|
||||
This property can never be set back to null or to a relative <see cref="T:System.Uri"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Thrown if the property is set to <c>null</c>.</exception>
|
||||
<exception cref="T:System.ArgumentException">Thrown if the property is set to a relative <see cref="T:System.Uri"/> (i.e. a <see cref="T:System.Uri"/> whose <see cref="P:System.Uri.IsAbsoluteUri"/> property is <c>false</c>).</exception>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyValid(System.Object)">
|
||||
<summary>
|
||||
This is a callback that WPF calls to validate a potential new Source value.
|
||||
</summary>
|
||||
<returns>
|
||||
True if the value is valid, false if it is not.
|
||||
If we return false then WPF should respond by throwing an <see cref="T:System.ArgumentException"/>.
|
||||
</returns>
|
||||
<remarks>
|
||||
Note that we unfortunately can't treat null as invalid here because null is valid prior to initialization.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when the WPF Source property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set Source to programmatically trigger a navigation.
|
||||
2) The CoreWebView changed its own source and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.SourceChanged">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_SourceChanged(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2SourceChangedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's SourceChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2's source URI has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The CoreWebView2 was told to navigate programmatically (potentially by us, see SourcePropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. clicked a link.
|
||||
In either of the above cases, this event might trigger several times due to e.g. redirection.
|
||||
Aside from propagating to our own event, we just need to update our WPF Source property to match the CoreWebView2's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationStarting(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationStarting event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationCompleted(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationCompleted event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_HistoryChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's HistoryChanged event.
|
||||
We're handling it in order to update our WPF CanGoBack and CanGoForward properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBackProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a previous page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForwardProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a next page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.TabIntoCore(System.Windows.Input.TraversalRequest)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to inform us that tabbing has caused the focus to move into our control/window.
|
||||
Since WPF can't manage the transition of focus to a non-WPF HWND, it delegates the transition to us here.
|
||||
So our job is just to place the focus in our external HWND.
|
||||
</summary>
|
||||
<param name="request">Information about how the focus is moving.</param>
|
||||
<returns><c>true</c> to indicate that we handled the navigation, or <c>false</c> to indicate that we didn't.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and is called to inform us when we receive the keyboard focus.
|
||||
We handle this by passing the keyboard focus on to the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
We never want to land in a state where our window (this.Handle) actually has the keyboard focus.
|
||||
</summary>
|
||||
<param name="e">Arguments from the underlying GotKeyboardFocus event.</param>
|
||||
<remarks>
|
||||
Note that it's actually possible for us to receive keyboard focus without this method being called.
|
||||
One known case where that happens is when our parent window is deactivated while we have focus, then reactivated.
|
||||
We handle that case in <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>.
|
||||
</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_MoveFocusRequested(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2MoveFocusRequestedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's MoveFocusRequested event.
|
||||
It fires when the CoreWebView2Controller has focus but wants to move it elsewhere in the app.
|
||||
E.g. this happens when the user tabs past the last item in the CoreWebView2 and focus needs to return to some other app control.
|
||||
So our job is just to tell WPF to move the focus on to the next control.
|
||||
Note that we don't propagate this event outward as a standard WPF routed event because we've implemented its purpose here.
|
||||
If users of the control want to track focus shifting in/out of the control, they should use standard WPF events.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_GotFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's GotFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_LostFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's LostFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_AcceleratorKeyPressed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2AcceleratorKeyPressedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's AcceleratorKeyPressed event.
|
||||
This is called to inform us about key presses that are likely to have special behavior (e.g. esc, return, Function keys, letters with modifier keys).
|
||||
WPF can't detect this input because Windows sends it directly to the Win32 CoreWebView2Controller control.
|
||||
We implement this by generating standard WPF key input events, allowing callers to handle the input in the usual WPF way if they want.
|
||||
If nobody handles the WPF key events then we'll allow the default CoreWebView2Controller logic (if any) to handle it.
|
||||
Of the possible options, this implementation should provide the most flexibility to callers.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and called to allow us to handle key press input.
|
||||
WPF should never actually call this in response to keyboard events because we're hosting a non-WPF window.
|
||||
When our window has focus Windows will send the input directly to it rather than to WPF's top-level window and input system.
|
||||
This override should only be called when we're explicitly forwarding accelerator key input from the CoreWebView2 to WPF (in CoreWebView2Controller_AcceleratorKeyPressed).
|
||||
Even then, this KeyDownEvent is only triggered because our PreviewKeyDownEvent implementation explicitly triggers it, matching WPF's usual system.
|
||||
So the process is:
|
||||
<list type="number">
|
||||
<item><description>CoreWebView2Controller_AcceleratorKeyPressed</description></item>
|
||||
<item><description>PreviewKeyDownEvent</description></item>
|
||||
<item><description>KeyDownEvent</description></item>
|
||||
<item><description>OnKeyDown</description></item>
|
||||
</list>
|
||||
.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is the "Preview" (i.e. tunneling) version of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>, so it actually happens first.
|
||||
Like OnKeyDown, this will only ever be called if we're explicitly forwarding key presses from the CoreWebView2.
|
||||
In order to mimic WPF's standard input handling, when we receive this we turn around and fire off the standard bubbling KeyDownEvent.
|
||||
That way others in the WPF tree see the same standard pair of input events that WPF itself would have triggered if it were handling the key press.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last value which was set to it, or <c>1.0</c> (the default) if none has been.
|
||||
The most recent value set to this property before the CoreWebView2 has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF ZoomFactor property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set ZoomFactor to change the zoom of the CoreWebView2.
|
||||
2) The CoreWebView2 changed its own ZoomFactor and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
The event is raised when the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property changes.
|
||||
This event directly exposes <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_ZoomFactorChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's ZoomFactorChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2Controller's ZoomFactor has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The value was changed programmatically (potentially by us, see ZoomFactorPropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. CTRL + Mouse Wheel.
|
||||
Aside from propagating to our own event, we just need to update our WPF ZoomFactor property to match the CoreWebView2Controller's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.DefaultBackgroundColor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/> has been initialized will retrieve the last value which was
|
||||
set to it, or <c>Color.White</c> (the default) if none has been.
|
||||
The most recent value set to this property before CoreWebView2Controller has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF DefaultBackgroundColor property's value changes.
|
||||
Since CoreWebView2Controller does not update this property itself, this is only triggered by the
|
||||
caller setting DefaultBackgroundColor.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor">
|
||||
<summary>
|
||||
The foreground color to be used in design mode.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates the WebView to the previous page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates the WebView to the next page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the current page.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Stop">
|
||||
<summary>
|
||||
Stops all navigations and pending resource fetches.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Initiates a navigation to htmlContent as source HTML of a new document.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ContentLoading">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ContentLoading(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ContentLoadingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ContentLoading event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes JavaScript code from the javaScript parameter in the current top level document rendered in the WebView.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_WebMessageReceived(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's WebMessageReceived event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.IsInDesignMode">
|
||||
<summary>
|
||||
True when we're in design mode and shouldn't create an underlying CoreWebView2.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-arm64/native/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-arm64/native/WebView2Loader.dll
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-x64/native/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-x64/native/WebView2Loader.dll
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-x86/native/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-x86/native/WebView2Loader.dll
vendored
Normal file
Binary file not shown.
Binary file not shown.
12
packages/Microsoft.Web.WebView2.1.0.961.33/tools/VisualStudioToolsManifest.xml
vendored
Normal file
12
packages/Microsoft.Web.WebView2.1.0.961.33/tools/VisualStudioToolsManifest.xml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<FileList>
|
||||
<File Reference = "Microsoft.Web.WebView2.Wpf.dll" >
|
||||
<ToolboxItems UIFramework="WPF" VSCategory="WebView2" BlendCategory="WebView2">
|
||||
<Item Type="Microsoft.Web.WebView2.Wpf.WebView2" />
|
||||
</ToolboxItems>
|
||||
</File>
|
||||
<File Reference = "Microsoft.Web.WebView2.WinForms.dll" >
|
||||
<ToolboxItems UIFramework="WinForms" VSCategory="WebView2">
|
||||
<Item Type="Microsoft.Web.WebView2.WinForms.WebView2" />
|
||||
</ToolboxItems>
|
||||
</File>
|
||||
</FileList>
|
||||
BIN
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/.signature.p7s
vendored
Normal file
BIN
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/.signature.p7s
vendored
Normal file
Binary file not shown.
21
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/LICENSE
vendored
Normal file
21
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
Binary file not shown.
60
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/ThirdPartyNotices.txt
vendored
Normal file
60
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/ThirdPartyNotices.txt
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
THIRD PARTY SOFTWARE NOTICES AND INFORMATION
|
||||
Do Not Translate or Localize
|
||||
|
||||
This software incorporates material from third parties. Microsoft makes certain open source code available at http://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including the product name, the open source component name, and version number, to:
|
||||
|
||||
Source Code Compliance Team
|
||||
Microsoft Corporation
|
||||
One Microsoft Way
|
||||
Redmond, WA 98052
|
||||
USA
|
||||
|
||||
Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License.
|
||||
|
||||
Libc++
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Catch2
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
2832
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/com.h
vendored
Normal file
2832
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/com.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
748
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/common.h
vendored
Normal file
748
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/common.h
vendored
Normal file
@ -0,0 +1,748 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_COMMON_INCLUDED
|
||||
#define __WIL_COMMON_INCLUDED
|
||||
|
||||
#if defined(_KERNEL_MODE ) && !defined(__WIL_MIN_KERNEL)
|
||||
// This define indicates that the WIL usage is in a kernel mode context where
|
||||
// a high degree of WIL functionality is desired.
|
||||
//
|
||||
// Use (sparingly) to change behavior based on whether WIL is being used in kernel
|
||||
// mode or user mode.
|
||||
#define WIL_KERNEL_MODE
|
||||
#endif
|
||||
|
||||
// Defining WIL_HIDE_DEPRECATED will hide everything deprecated.
|
||||
// Each wave of deprecation will add a new WIL_HIDE_DEPRECATED_YYMM number that can be used to lock deprecation at
|
||||
// a particular point, allowing components to avoid backslide and catch up to the current independently.
|
||||
#ifdef WIL_HIDE_DEPRECATED
|
||||
#define WIL_HIDE_DEPRECATED_1809
|
||||
#endif
|
||||
#ifdef WIL_HIDE_DEPRECATED_1809
|
||||
#define WIL_HIDE_DEPRECATED_1612
|
||||
#endif
|
||||
#ifdef WIL_HIDE_DEPRECATED_1612
|
||||
#define WIL_HIDE_DEPRECATED_1611
|
||||
#endif
|
||||
|
||||
// Implementation side note: ideally the deprecation would be done with the function-level declspec
|
||||
// as it allows you to utter the error text when used. The declspec works, but doing it selectively with
|
||||
// a macro makes intellisense deprecation comments not work. So we just use the #pragma deprecation.
|
||||
#ifdef WIL_WARN_DEPRECATED
|
||||
#define WIL_WARN_DEPRECATED_1809
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1809
|
||||
#define WIL_WARN_DEPRECATED_1612
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1612
|
||||
#define WIL_WARN_DEPRECATED_1611
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1809
|
||||
#define WIL_WARN_DEPRECATED_1809_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
|
||||
#else
|
||||
#define WIL_WARN_DEPRECATED_1809_PRAGMA(...)
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1611
|
||||
#define WIL_WARN_DEPRECATED_1611_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
|
||||
#else
|
||||
#define WIL_WARN_DEPRECATED_1611_PRAGMA(...)
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1612
|
||||
#define WIL_WARN_DEPRECATED_1612_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
|
||||
#else
|
||||
#define WIL_WARN_DEPRECATED_1612_PRAGMA(...)
|
||||
#endif
|
||||
|
||||
#if defined(_MSVC_LANG)
|
||||
#define __WI_SUPPRESS_4127_S __pragma(warning(push)) __pragma(warning(disable:4127)) __pragma(warning(disable:26498)) __pragma(warning(disable:4245))
|
||||
#define __WI_SUPPRESS_4127_E __pragma(warning(pop))
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress:28285)) __pragma(warning(suppress:6504))
|
||||
#define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress:26495))
|
||||
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress:26439))
|
||||
#else
|
||||
#define __WI_SUPPRESS_4127_S
|
||||
#define __WI_SUPPRESS_4127_E
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS
|
||||
#define __WI_SUPPRESS_NONINIT_ANALYSIS
|
||||
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS
|
||||
#endif
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
// Some SAL remapping / decoration to better support Doxygen. Macros that look like function calls can
|
||||
// confuse Doxygen when they are used to decorate a function or variable. We simplify some of these to
|
||||
// basic macros without the function for common use cases.
|
||||
/// @cond
|
||||
#define _Success_return_ _Success_(return)
|
||||
#define _Success_true_ _Success_(true)
|
||||
#define __declspec_noinline_ __declspec(noinline)
|
||||
#define __declspec_selectany_ __declspec(selectany)
|
||||
/// @endcond
|
||||
|
||||
//! @defgroup macrobuilding Macro Composition
|
||||
//! The following macros are building blocks primarily intended for authoring other macros.
|
||||
//! @{
|
||||
|
||||
//! Re-state a macro value (indirection for composition)
|
||||
#define WI_FLATTEN(...) __VA_ARGS__
|
||||
|
||||
/// @cond
|
||||
#define __WI_PASTE_imp(a, b) a##b
|
||||
/// @endcond
|
||||
|
||||
//! This macro is for use in other macros to paste two tokens together, such as a constant and the __LINE__ macro.
|
||||
#define WI_PASTE(a, b) __WI_PASTE_imp(a, b)
|
||||
|
||||
/// @cond
|
||||
#define __WI_HAS_VA_OPT_IMPL(F, T, ...) T
|
||||
#define __WI_HAS_VA_OPT_(...) __WI_HAS_VA_OPT_IMPL(__VA_OPT__(0,) 1, 0)
|
||||
/// @endcond
|
||||
|
||||
//! Evaluates to '1' when support for '__VA_OPT__' is available, else '0'
|
||||
#define WI_HAS_VA_OPT __WI_HAS_VA_OPT_(unused)
|
||||
|
||||
/// @cond
|
||||
#define __WI_ARGS_COUNT1(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, \
|
||||
A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, \
|
||||
A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77, A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, \
|
||||
A90, A91, A92, A93, A94, A95, A96, A97, A98, A99, count, ...) count
|
||||
#define __WI_ARGS_COUNT0(...) WI_FLATTEN(__WI_ARGS_COUNT1(__VA_ARGS__, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
|
||||
79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
|
||||
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
#define __WI_ARGS_COUNT_PREFIX(...) 0, __VA_ARGS__
|
||||
/// @endcond
|
||||
|
||||
//! This variadic macro returns the number of arguments passed to it (up to 99).
|
||||
#if WI_HAS_VA_OPT
|
||||
#define WI_ARGS_COUNT(...) __WI_ARGS_COUNT0(0 __VA_OPT__(, __VA_ARGS__))
|
||||
#else
|
||||
#define WI_ARGS_COUNT(...) __WI_ARGS_COUNT0(__WI_ARGS_COUNT_PREFIX(__VA_ARGS__))
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#define __WI_FOR_imp0( fn)
|
||||
#define __WI_FOR_imp1( fn, arg) fn(arg)
|
||||
#define __WI_FOR_imp2( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp1(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp3( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp2(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp4( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp3(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp5( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp4(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp6( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp5(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp7( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp6(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp8( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp7(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp9( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp8(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp10(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp9(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp11(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp10(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp12(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp11(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp13(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp12(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp14(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp13(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp15(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp14(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp16(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp15(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp17(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp16(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp18(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp17(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp19(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp18(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp20(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp19(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp21(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp20(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp22(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp21(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp23(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp22(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp24(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp23(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp25(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp24(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp26(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp25(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp27(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp26(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp28(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp27(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp29(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp28(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp30(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp29(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp31(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp30(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp32(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp31(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp33(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp32(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp34(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp33(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp35(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp34(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp36(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp35(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp37(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp36(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp38(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp37(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp39(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp38(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp40(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp39(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp41(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp40(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp42(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp41(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp43(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp42(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp44(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp43(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp45(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp44(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp46(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp45(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp47(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp46(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp48(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp47(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp49(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp48(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp50(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp49(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp51(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp50(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp52(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp51(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp53(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp52(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp54(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp53(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp55(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp54(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp56(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp55(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp57(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp56(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp58(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp57(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp59(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp58(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp60(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp59(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp61(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp60(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp62(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp61(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp63(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp62(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp64(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp63(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp65(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp64(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp66(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp65(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp67(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp66(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp68(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp67(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp69(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp68(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp70(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp69(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp71(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp70(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp72(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp71(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp73(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp72(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp74(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp73(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp75(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp74(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp76(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp75(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp77(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp76(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp78(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp77(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp79(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp78(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp80(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp79(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp81(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp80(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp82(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp81(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp83(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp82(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp84(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp83(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp85(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp84(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp86(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp85(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp87(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp86(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp88(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp87(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp89(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp88(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp90(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp89(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp91(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp90(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp92(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp91(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp93(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp92(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp94(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp93(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp95(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp94(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp96(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp95(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp97(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp96(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp98(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp97(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp99(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp98(fn, __VA_ARGS__))
|
||||
|
||||
#define __WI_FOR_imp(n, fnAndArgs) WI_PASTE(__WI_FOR_imp, n) fnAndArgs
|
||||
/// @endcond
|
||||
|
||||
//! Iterates through each of the given arguments invoking the specified macro against each one.
|
||||
#define WI_FOREACH(fn, ...) __WI_FOR_imp(WI_ARGS_COUNT(__VA_ARGS__), (fn, ##__VA_ARGS__))
|
||||
|
||||
//! Dispatches a single macro name to separate macros based on the number of arguments passed to it.
|
||||
#define WI_MACRO_DISPATCH(name, ...) WI_PASTE(WI_PASTE(name, WI_ARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
|
||||
|
||||
//! @} // Macro composition helpers
|
||||
|
||||
#if !defined(__cplusplus) || defined(__WIL_MIN_KERNEL)
|
||||
|
||||
#define WI_ODR_PRAGMA(NAME, TOKEN)
|
||||
#define WI_NOEXCEPT
|
||||
|
||||
#else
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4714) // __forceinline not honored
|
||||
|
||||
// DO NOT add *any* further includes to this file -- there should be no dependencies from its usage
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
//! This macro inserts ODR violation protection; the macro allows it to be compatible with straight "C" code
|
||||
#define WI_ODR_PRAGMA(NAME, TOKEN) __pragma(detect_mismatch("ODR_violation_" NAME "_mismatch", TOKEN))
|
||||
|
||||
#ifdef WIL_KERNEL_MODE
|
||||
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "1")
|
||||
#else
|
||||
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "0")
|
||||
#endif
|
||||
|
||||
#if defined(_CPPUNWIND) && !defined(WIL_SUPPRESS_EXCEPTIONS)
|
||||
/** This define is automatically set when exceptions are enabled within wil.
|
||||
It is automatically defined when your code is compiled with exceptions enabled (via checking for the built-in
|
||||
_CPPUNWIND flag) unless you explicitly define WIL_SUPPRESS_EXCEPTIONS ahead of including your first wil
|
||||
header. All exception-based WIL methods and classes are included behind:
|
||||
~~~~
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
// code
|
||||
#endif
|
||||
~~~~
|
||||
This enables exception-free code to directly include WIL headers without worrying about exception-based
|
||||
routines suddenly becoming available. */
|
||||
#define WIL_ENABLE_EXCEPTIONS
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
#if defined(WIL_EXCEPTION_MODE)
|
||||
static_assert(WIL_EXCEPTION_MODE <= 2, "Invalid exception mode");
|
||||
#elif !defined(WIL_LOCK_EXCEPTION_MODE)
|
||||
#define WIL_EXCEPTION_MODE 0 // default, can link exception-based and non-exception based libraries together
|
||||
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "0")
|
||||
#elif defined(WIL_ENABLE_EXCEPTIONS)
|
||||
#define WIL_EXCEPTION_MODE 1 // new code optimization: ONLY support linking libraries together that have exceptions enabled
|
||||
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "1")
|
||||
#else
|
||||
#define WIL_EXCEPTION_MODE 2 // old code optimization: ONLY support linking libraries that are NOT using exceptions
|
||||
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "2")
|
||||
#endif
|
||||
|
||||
#if WIL_EXCEPTION_MODE == 1 && !defined(WIL_ENABLE_EXCEPTIONS)
|
||||
#error Must enable exceptions when WIL_EXCEPTION_MODE == 1
|
||||
#endif
|
||||
|
||||
// block for documentation only
|
||||
#if defined(WIL_DOXYGEN)
|
||||
/** This define can be explicitly set to disable exception usage within wil.
|
||||
Normally this define is never needed as the WIL_ENABLE_EXCEPTIONS macro is enabled automatically by looking
|
||||
at _CPPUNWIND. If your code compiles with exceptions enabled, but does not want to enable the exception-based
|
||||
classes and methods from WIL, define this macro ahead of including the first WIL header. */
|
||||
#define WIL_SUPPRESS_EXCEPTIONS
|
||||
|
||||
/** This define can be explicitly set to lock the process exception mode to WIL_ENABLE_EXCEPTIONS.
|
||||
Locking the exception mode provides optimizations to exception barriers, staging hooks and DLL load costs as it eliminates the need to
|
||||
do copy-on-write initialization of various function pointers and the necessary indirection that's done within WIL to avoid ODR violations
|
||||
when linking libraries together with different exception handling semantics. */
|
||||
#define WIL_LOCK_EXCEPTION_MODE
|
||||
|
||||
/** This define explicit sets the exception mode for the process to control optimizations.
|
||||
Three exception modes are available:
|
||||
0) This is the default. This enables a binary to link both exception-based and non-exception based libraries together that
|
||||
use WIL. This adds overhead to exception barriers, DLL copy on write pages and indirection through function pointers to avoid ODR
|
||||
violations when linking libraries together with different exception handling semantics.
|
||||
1) Prefer this setting when it can be used. This locks the binary to only supporting libraries which were built with exceptions enabled.
|
||||
2) This locks the binary to libraries built without exceptions. */
|
||||
#define WIL_EXCEPTION_MODE
|
||||
#endif
|
||||
|
||||
#if (__cplusplus >= 201703) || (_MSVC_LANG >= 201703)
|
||||
#define WIL_HAS_CXX_17 1
|
||||
#else
|
||||
#define WIL_HAS_CXX_17 0
|
||||
#endif
|
||||
|
||||
// Until we'll have C++17 enabled in our code base, we're falling back to SAL
|
||||
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE
|
||||
|
||||
#define __R_ENABLE_IF_IS_CLASS(ptrType) wistd::enable_if_t<wistd::is_class<ptrType>::value, void*> = (void*)0
|
||||
#define __R_ENABLE_IF_IS_NOT_CLASS(ptrType) wistd::enable_if_t<!wistd::is_class<ptrType>::value, void*> = (void*)0
|
||||
|
||||
//! @defgroup bitwise Bitwise Inspection and Manipulation
|
||||
//! Bitwise helpers to improve readability and reduce the error rate of bitwise operations.
|
||||
//! Several macros have been constructed to assist with bitwise inspection and manipulation. These macros exist
|
||||
//! for two primary purposes:
|
||||
//!
|
||||
//! 1. To improve the readability of bitwise comparisons and manipulation.
|
||||
//!
|
||||
//! The macro names are the more concise, readable form of what's being done and do not require that any flags
|
||||
//! or variables be specified multiple times for the comparisons.
|
||||
//!
|
||||
//! 2. To reduce the error rate associated with bitwise operations.
|
||||
//!
|
||||
//! The readability improvements naturally lend themselves to this by cutting down the number of concepts.
|
||||
//! Using `WI_IsFlagSet(var, MyEnum::Flag)` rather than `((var & MyEnum::Flag) == MyEnum::Flag)` removes the comparison
|
||||
//! operator and repetition in the flag value.
|
||||
//!
|
||||
//! Additionally, these macros separate single flag operations (which tend to be the most common) from multi-flag
|
||||
//! operations so that compile-time errors are generated for bitwise operations which are likely incorrect,
|
||||
//! such as: `WI_IsFlagSet(var, MyEnum::None)` or `WI_IsFlagSet(var, MyEnum::ValidMask)`.
|
||||
//!
|
||||
//! Note that the single flag helpers should be used when a compile-time constant single flag is being manipulated. These
|
||||
//! helpers provide compile-time errors on misuse and should be preferred over the multi-flag helpers. The multi-flag helpers
|
||||
//! should be used when multiple flags are being used simultaneously or when the flag values are not compile-time constants.
|
||||
//!
|
||||
//! Common example usage (manipulation of flag variables):
|
||||
//! ~~~~
|
||||
//! WI_SetFlag(m_flags, MyFlags::Foo); // Set a single flag in the given variable
|
||||
//! WI_SetAllFlags(m_flags, MyFlags::Foo | MyFlags::Bar); // Set one or more flags
|
||||
//! WI_ClearFlagIf(m_flags, MyFlags::Bar, isBarClosed); // Conditionally clear a single flag based upon a bool
|
||||
//! WI_ClearAllFlags(m_flags, MyFlags::Foo | MyFlags::Bar); // Clear one or more flags from the given variable
|
||||
//! WI_ToggleFlag(m_flags, MyFlags::Foo); // Toggle (change to the opposite value) a single flag
|
||||
//! WI_UpdateFlag(m_flags, MyFlags::Bar, isBarClosed); // Sets or Clears a single flag from the given variable based upon a bool value
|
||||
//! WI_UpdateFlagsInMask(m_flags, flagsMask, newFlagValues); // Sets or Clears the flags in flagsMask to the masked values from newFlagValues
|
||||
//! ~~~~
|
||||
//! Common example usage (inspection of flag variables):
|
||||
//! ~~~~
|
||||
//! if (WI_IsFlagSet(m_flags, MyFlags::Foo)) // Is a single flag set in the given variable?
|
||||
//! if (WI_IsAnyFlagSet(m_flags, MyFlags::Foo | MyFlags::Bar)) // Is at least one flag from the given mask set?
|
||||
//! if (WI_AreAllFlagsClear(m_flags, MyFlags::Foo | MyFlags::Bar)) // Are all flags in the given list clear?
|
||||
//! if (WI_IsSingleFlagSet(m_flags)) // Is *exactly* one flag set in the given variable?
|
||||
//! ~~~~
|
||||
//! @{
|
||||
|
||||
//! Returns the unsigned type of the same width and numeric value as the given enum
|
||||
#define WI_EnumValue(val) static_cast<::wil::integral_from_enum<decltype(val)>>(val)
|
||||
//! Validates that exactly ONE bit is set in compile-time constant `flag`
|
||||
#define WI_StaticAssertSingleBitSet(flag) static_cast<decltype(flag)>(::wil::details::verify_single_flag_helper<static_cast<unsigned long long>(WI_EnumValue(flag))>::value)
|
||||
|
||||
//! @name Bitwise manipulation macros
|
||||
//! @{
|
||||
|
||||
//! Set zero or more bitflags specified by `flags` in the variable `var`.
|
||||
#define WI_SetAllFlags(var, flags) ((var) |= (flags))
|
||||
//! Set a single compile-time constant `flag` in the variable `var`.
|
||||
#define WI_SetFlag(var, flag) WI_SetAllFlags(var, WI_StaticAssertSingleBitSet(flag))
|
||||
//! Conditionally sets a single compile-time constant `flag` in the variable `var` only if `condition` is true.
|
||||
#define WI_SetFlagIf(var, flag, condition) do { if (wil::verify_bool(condition)) { WI_SetFlag(var, flag); } } while ((void)0, 0)
|
||||
|
||||
//! Clear zero or more bitflags specified by `flags` from the variable `var`.
|
||||
#define WI_ClearAllFlags(var, flags) ((var) &= ~(flags))
|
||||
//! Clear a single compile-time constant `flag` from the variable `var`.
|
||||
#define WI_ClearFlag(var, flag) WI_ClearAllFlags(var, WI_StaticAssertSingleBitSet(flag))
|
||||
//! Conditionally clear a single compile-time constant `flag` in the variable `var` only if `condition` is true.
|
||||
#define WI_ClearFlagIf(var, flag, condition) do { if (wil::verify_bool(condition)) { WI_ClearFlag(var, flag); } } while ((void)0, 0)
|
||||
|
||||
//! Changes a single compile-time constant `flag` in the variable `var` to be set if `isFlagSet` is true or cleared if `isFlagSet` is false.
|
||||
#define WI_UpdateFlag(var, flag, isFlagSet) (wil::verify_bool(isFlagSet) ? WI_SetFlag(var, flag) : WI_ClearFlag(var, flag))
|
||||
//! Changes only the flags specified by `flagsMask` in the variable `var` to match the corresponding flags in `newFlags`.
|
||||
#define WI_UpdateFlagsInMask(var, flagsMask, newFlags) wil::details::UpdateFlagsInMaskHelper(var, flagsMask, newFlags)
|
||||
|
||||
//! Toggles (XOR the value) of multiple bitflags specified by `flags` in the variable `var`.
|
||||
#define WI_ToggleAllFlags(var, flags) ((var) ^= (flags))
|
||||
//! Toggles (XOR the value) of a single compile-time constant `flag` in the variable `var`.
|
||||
#define WI_ToggleFlag(var, flag) WI_ToggleAllFlags(var, WI_StaticAssertSingleBitSet(flag))
|
||||
//! @} // bitwise manipulation macros
|
||||
|
||||
//! @name Bitwise inspection macros
|
||||
//! @{
|
||||
|
||||
//! Evaluates as true if every bitflag specified in `flags` is set within `val`.
|
||||
#define WI_AreAllFlagsSet(val, flags) wil::details::AreAllFlagsSetHelper(val, flags)
|
||||
//! Evaluates as true if one or more bitflags specified in `flags` are set within `val`.
|
||||
#define WI_IsAnyFlagSet(val, flags) (static_cast<decltype((val) & (flags))>(WI_EnumValue(val) & WI_EnumValue(flags)) != static_cast<decltype((val) & (flags))>(0))
|
||||
//! Evaluates as true if a single compile-time constant `flag` is set within `val`.
|
||||
#define WI_IsFlagSet(val, flag) WI_IsAnyFlagSet(val, WI_StaticAssertSingleBitSet(flag))
|
||||
|
||||
//! Evaluates as true if every bitflag specified in `flags` is clear within `val`.
|
||||
#define WI_AreAllFlagsClear(val, flags) (static_cast<decltype((val) & (flags))>(WI_EnumValue(val) & WI_EnumValue(flags)) == static_cast<decltype((val) & (flags))>(0))
|
||||
//! Evaluates as true if one or more bitflags specified in `flags` are clear within `val`.
|
||||
#define WI_IsAnyFlagClear(val, flags) (!wil::details::AreAllFlagsSetHelper(val, flags))
|
||||
//! Evaluates as true if a single compile-time constant `flag` is clear within `val`.
|
||||
#define WI_IsFlagClear(val, flag) WI_AreAllFlagsClear(val, WI_StaticAssertSingleBitSet(flag))
|
||||
|
||||
//! Evaluates as true if exactly one bit (any bit) is set within `val`.
|
||||
#define WI_IsSingleFlagSet(val) wil::details::IsSingleFlagSetHelper(val)
|
||||
//! Evaluates as true if exactly one bit from within the specified `mask` is set within `val`.
|
||||
#define WI_IsSingleFlagSetInMask(val, mask) wil::details::IsSingleFlagSetHelper((val) & (mask))
|
||||
//! Evaluates as true if exactly one bit (any bit) is set within `val` or if there are no bits set within `val`.
|
||||
#define WI_IsClearOrSingleFlagSet(val) wil::details::IsClearOrSingleFlagSetHelper(val)
|
||||
//! Evaluates as true if exactly one bit from within the specified `mask` is set within `val` or if there are no bits from `mask` set within `val`.
|
||||
#define WI_IsClearOrSingleFlagSetInMask(val, mask) wil::details::IsClearOrSingleFlagSetHelper((val) & (mask))
|
||||
//! @}
|
||||
|
||||
#if defined(WIL_DOXYGEN)
|
||||
/** This macro provides a C++ header with a guaranteed initialization function.
|
||||
Normally, were a global object's constructor used for this purpose, the optimizer/linker might throw
|
||||
the object away if it's unreferenced (which throws away the side-effects that the initialization function
|
||||
was trying to achieve). Using this macro forces linker inclusion of a variable that's initialized by the
|
||||
provided function to elide that optimization.
|
||||
//!
|
||||
This functionality is primarily provided as a building block for header-based libraries (such as WIL)
|
||||
to be able to layer additional functionality into other libraries by their mere inclusion. Alternative models
|
||||
of initialization should be used whenever they are available.
|
||||
~~~~
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
WI_HEADER_INITITALIZATION_FUNCTION(InitializeDesktopFamilyApis, []
|
||||
{
|
||||
g_pfnGetModuleName = GetCurrentModuleName;
|
||||
g_pfnFailFastInLoaderCallout = FailFastInLoaderCallout;
|
||||
return 1;
|
||||
});
|
||||
#endif
|
||||
~~~~
|
||||
The above example is used within WIL to decide whether or not the library containing WIL is allowed to use
|
||||
desktop APIs. Building this functionality as #IFDEFs within functions would create ODR violations, whereas
|
||||
doing it with global function pointers and header initialization allows a runtime determination. */
|
||||
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn)
|
||||
#elif defined(_M_IX86)
|
||||
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn) \
|
||||
extern "C" { __declspec(selectany) unsigned char g_header_init_ ## name = static_cast<unsigned char>(fn()); } \
|
||||
__pragma(comment(linker, "/INCLUDE:_g_header_init_" #name))
|
||||
#elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64)
|
||||
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn) \
|
||||
extern "C" { __declspec(selectany) unsigned char g_header_init_ ## name = static_cast<unsigned char>(fn()); } \
|
||||
__pragma(comment(linker, "/INCLUDE:g_header_init_" #name))
|
||||
#else
|
||||
#error linker pragma must include g_header_init variation
|
||||
#endif
|
||||
|
||||
|
||||
/** All Windows Implementation Library classes and functions are located within the "wil" namespace.
|
||||
The 'wil' namespace is an intentionally short name as the intent is for code to be able to reference
|
||||
the namespace directly (example: `wil::srwlock lock;`) without a using statement. Resist adding a using
|
||||
statement for wil to avoid introducing potential name collisions between wil and other namespaces. */
|
||||
namespace wil
|
||||
{
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <typename T>
|
||||
class pointer_range
|
||||
{
|
||||
public:
|
||||
pointer_range(T begin_, T end_) : m_begin(begin_), m_end(end_) {}
|
||||
T begin() const { return m_begin; }
|
||||
T end() const { return m_end; }
|
||||
private:
|
||||
T m_begin;
|
||||
T m_end;
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Enables using range-based for between a begin and end object pointer.
|
||||
~~~~
|
||||
for (auto& obj : make_range(objPointerBegin, objPointerEnd)) { }
|
||||
~~~~ */
|
||||
template <typename T>
|
||||
details::pointer_range<T> make_range(T begin, T end)
|
||||
{
|
||||
return details::pointer_range<T>(begin, end);
|
||||
}
|
||||
|
||||
/** Enables using range-based for on a range when given the base pointer and the number of objects in the range.
|
||||
~~~~
|
||||
for (auto& obj : make_range(objPointer, objCount)) { }
|
||||
~~~~ */
|
||||
template <typename T>
|
||||
details::pointer_range<T> make_range(T begin, size_t count)
|
||||
{
|
||||
return details::pointer_range<T>(begin, begin + count);
|
||||
}
|
||||
|
||||
|
||||
//! @defgroup outparam Output Parameters
|
||||
//! Improve the conciseness of assigning values to optional output parameters.
|
||||
//! @{
|
||||
|
||||
/** Assign the given value to an optional output parameter.
|
||||
Makes code more concise by removing trivial `if (outParam)` blocks. */
|
||||
template <typename T>
|
||||
inline void assign_to_opt_param(_Out_opt_ T *outParam, T val)
|
||||
{
|
||||
if (outParam != nullptr)
|
||||
{
|
||||
*outParam = val;
|
||||
}
|
||||
}
|
||||
|
||||
/** Assign NULL to an optional output pointer parameter.
|
||||
Makes code more concise by removing trivial `if (outParam)` blocks. */
|
||||
template <typename T>
|
||||
inline void assign_null_to_opt_param(_Out_opt_ T *outParam)
|
||||
{
|
||||
if (outParam != nullptr)
|
||||
{
|
||||
*outParam = nullptr;
|
||||
}
|
||||
}
|
||||
//! @} // end output parameter helpers
|
||||
|
||||
/** Performs a logical or of the given variadic template parameters allowing indirect compile-time boolean evaluation.
|
||||
Example usage:
|
||||
~~~~
|
||||
template <unsigned int... Rest>
|
||||
struct FeatureRequiredBy
|
||||
{
|
||||
static const bool enabled = wil::variadic_logical_or<WilFeature<Rest>::enabled...>::value;
|
||||
};
|
||||
~~~~ */
|
||||
template <bool...> struct variadic_logical_or;
|
||||
/// @cond
|
||||
template <> struct variadic_logical_or<> : wistd::false_type { };
|
||||
template <bool... Rest> struct variadic_logical_or<true, Rest...> : wistd::true_type { };
|
||||
template <bool... Rest> struct variadic_logical_or<false, Rest...> : variadic_logical_or<Rest...>::type { };
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <unsigned long long flag>
|
||||
struct verify_single_flag_helper
|
||||
{
|
||||
static_assert((flag != 0) && ((flag & (flag - 1)) == 0), "Single flag expected, zero or multiple flags found");
|
||||
static const unsigned long long value = flag;
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
|
||||
//! @defgroup typesafety Type Validation
|
||||
//! Helpers to validate variable types to prevent accidental, but allowed type conversions.
|
||||
//! These helpers are most useful when building macros that accept a particular type. Putting these functions around the types accepted
|
||||
//! prior to pushing that type through to a function (or using it within the macro) allows the macro to add an additional layer of type
|
||||
//! safety that would ordinarily be stripped away by C++ implicit conversions. This system is extensively used in the error handling helper
|
||||
//! macros to validate the types given to various macro parameters.
|
||||
//! @{
|
||||
|
||||
/** Verify that `val` can be evaluated as a logical bool.
|
||||
Other types will generate an intentional compilation error. Allowed types for a logical bool are bool, BOOL,
|
||||
boolean, BOOLEAN, and classes with an explicit bool cast.
|
||||
@param val The logical bool expression
|
||||
@return A C++ bool representing the evaluation of `val`. */
|
||||
template <typename T, __R_ENABLE_IF_IS_CLASS(T)>
|
||||
_Post_satisfies_(return == static_cast<bool>(val))
|
||||
__forceinline constexpr bool verify_bool(const T& val)
|
||||
{
|
||||
return static_cast<bool>(val);
|
||||
}
|
||||
|
||||
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)>
|
||||
__forceinline constexpr bool verify_bool(T /*val*/)
|
||||
{
|
||||
static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == val)
|
||||
__forceinline constexpr bool verify_bool<bool>(bool val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == (val != 0))
|
||||
__forceinline constexpr bool verify_bool<int>(int val)
|
||||
{
|
||||
return (val != 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == !!val)
|
||||
__forceinline constexpr bool verify_bool<unsigned char>(unsigned char val)
|
||||
{
|
||||
return !!val;
|
||||
}
|
||||
|
||||
/** Verify that `val` is a Win32 BOOL value.
|
||||
Other types (including other logical bool expressions) will generate an intentional compilation error. Note that this will
|
||||
accept any `int` value as long as that is the underlying typedef behind `BOOL`.
|
||||
@param val The Win32 BOOL returning expression
|
||||
@return A Win32 BOOL representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == val)
|
||||
__forceinline constexpr int verify_BOOL(T val)
|
||||
{
|
||||
// Note: Written in terms of 'int' as BOOL is actually: typedef int BOOL;
|
||||
static_assert((wistd::is_same<T, int>::value), "Wrong Type: BOOL expected");
|
||||
return val;
|
||||
}
|
||||
|
||||
/** Verify that `hr` is an HRESULT value.
|
||||
Other types will generate an intentional compilation error. Note that this will accept any `long` value as that is the
|
||||
underlying typedef behind HRESULT.
|
||||
//!
|
||||
Note that occasionally you might run into an HRESULT which is directly defined with a #define, such as:
|
||||
~~~~
|
||||
#define UIA_E_NOTSUPPORTED 0x80040204
|
||||
~~~~
|
||||
Though this looks like an `HRESULT`, this is actually an `unsigned long` (the hex specification forces this). When
|
||||
these are encountered and they are NOT in the public SDK (have not yet shipped to the public), then you should change
|
||||
their definition to match the manner in which `HRESULT` constants are defined in winerror.h:
|
||||
~~~~
|
||||
#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L)
|
||||
~~~~
|
||||
When these are encountered in the public SDK, their type should not be changed and you should use a static_cast
|
||||
to use this value in a macro that utilizes `verify_hresult`, for example:
|
||||
~~~~
|
||||
RETURN_HR_IF(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (patternId != UIA_DragPatternId));
|
||||
~~~~
|
||||
@param val The HRESULT returning expression
|
||||
@return An HRESULT representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == hr)
|
||||
inline constexpr long verify_hresult(T hr)
|
||||
{
|
||||
// Note: Written in terms of 'int' as HRESULT is actually: typedef _Return_type_success_(return >= 0) long HRESULT
|
||||
static_assert(wistd::is_same<T, long>::value, "Wrong Type: HRESULT expected");
|
||||
return hr;
|
||||
}
|
||||
/// @} // end type validation routines
|
||||
|
||||
/// @cond
|
||||
// Implementation details for macros and helper functions... do not use directly.
|
||||
namespace details
|
||||
{
|
||||
// Use size-specific casts to avoid sign extending numbers -- avoid warning C4310: cast truncates constant value
|
||||
#define __WI_MAKE_UNSIGNED(val) \
|
||||
(__pragma(warning(push)) __pragma(warning(disable: 4310 4309)) (sizeof(val) == 1 ? static_cast<unsigned char>(val) : \
|
||||
sizeof(val) == 2 ? static_cast<unsigned short>(val) : \
|
||||
sizeof(val) == 4 ? static_cast<unsigned long>(val) : \
|
||||
static_cast<unsigned long long>(val)) __pragma(warning(pop)))
|
||||
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val) - 1)))
|
||||
#define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
|
||||
|
||||
template <typename TVal, typename TFlags>
|
||||
__forceinline constexpr bool AreAllFlagsSetHelper(TVal val, TFlags flags)
|
||||
{
|
||||
return ((val & flags) == static_cast<decltype(val & flags)>(flags));
|
||||
}
|
||||
|
||||
template <typename TVal>
|
||||
__forceinline constexpr bool IsSingleFlagSetHelper(TVal val)
|
||||
{
|
||||
return __WI_IS_SINGLE_FLAG_SET(val);
|
||||
}
|
||||
|
||||
template <typename TVal>
|
||||
__forceinline constexpr bool IsClearOrSingleFlagSetHelper(TVal val)
|
||||
{
|
||||
return ((val == static_cast<wistd::remove_reference_t<TVal>>(0)) || IsSingleFlagSetHelper(val));
|
||||
}
|
||||
|
||||
template <typename TVal, typename TMask, typename TFlags>
|
||||
__forceinline constexpr void UpdateFlagsInMaskHelper(_Inout_ TVal& val, TMask mask, TFlags flags)
|
||||
{
|
||||
val = static_cast<wistd::remove_reference_t<TVal>>((val & ~mask) | (flags & mask));
|
||||
}
|
||||
|
||||
template <long>
|
||||
struct variable_size;
|
||||
|
||||
template <>
|
||||
struct variable_size<1>
|
||||
{
|
||||
typedef unsigned char type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variable_size<2>
|
||||
{
|
||||
typedef unsigned short type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variable_size<4>
|
||||
{
|
||||
typedef unsigned long type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variable_size<8>
|
||||
{
|
||||
typedef unsigned long long type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct variable_size_mapping
|
||||
{
|
||||
typedef typename variable_size<sizeof(T)>::type type;
|
||||
};
|
||||
} // details
|
||||
/// @endcond
|
||||
|
||||
/** Defines the unsigned type of the same width (1, 2, 4, or 8 bytes) as the given type.
|
||||
This allows code to generically convert any enum class to it's corresponding underlying type. */
|
||||
template <typename T>
|
||||
using integral_from_enum = typename details::variable_size_mapping<T>::type;
|
||||
} // wil
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // __WIL_COMMON_INCLUDED
|
||||
251
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/cppwinrt.h
vendored
Normal file
251
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/cppwinrt.h
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_CPPWINRT_INCLUDED
|
||||
#define __WIL_CPPWINRT_INCLUDED
|
||||
|
||||
#include "common.h"
|
||||
#include <windows.h>
|
||||
#include <unknwn.h>
|
||||
#include <hstring.h>
|
||||
|
||||
// WIL and C++/WinRT use two different exception types for communicating HRESULT failures. Thus, both libraries need to
|
||||
// understand how to translate these exception types into the correct HRESULT values at the ABI boundary. Prior to
|
||||
// C++/WinRT "2.0" this was accomplished by injecting the WINRT_EXTERNAL_CATCH_CLAUSE macro - that WIL defines below -
|
||||
// into its exception handler (winrt::to_hresult). Starting with C++/WinRT "2.0" this mechanism has shifted to a global
|
||||
// function pointer - winrt_to_hresult_handler - that WIL sets automatically when this header is included and
|
||||
// 'CPPWINRT_SUPPRESS_STATIC_INITIALIZERS' is not defined.
|
||||
|
||||
/// @cond
|
||||
namespace wil::details
|
||||
{
|
||||
// Since the C++/WinRT version macro is a string...
|
||||
inline constexpr int major_version_from_string(const char* versionString)
|
||||
{
|
||||
int result = 0;
|
||||
auto str = versionString;
|
||||
while ((*str >= '0') && (*str <= '9'))
|
||||
{
|
||||
result = result * 10 + (*str - '0');
|
||||
++str;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
#ifdef CPPWINRT_VERSION
|
||||
// Prior to C++/WinRT "2.0" this header needed to be included before 'winrt/base.h' so that our definition of
|
||||
// 'WINRT_EXTERNAL_CATCH_CLAUSE' would get picked up in the implementation of 'winrt::to_hresult'. This is no longer
|
||||
// problematic, so only emit an error when using a version of C++/WinRT prior to 2.0
|
||||
static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
|
||||
"Please include wil/cppwinrt.h before including any C++/WinRT headers");
|
||||
#endif
|
||||
|
||||
// NOTE: Will eventually be removed once C++/WinRT 2.0 use can be assumed
|
||||
#ifdef WINRT_EXTERNAL_CATCH_CLAUSE
|
||||
#define __WI_CONFLICTING_WINRT_EXTERNAL_CATCH_CLAUSE 1
|
||||
#else
|
||||
#define WINRT_EXTERNAL_CATCH_CLAUSE \
|
||||
catch (const wil::ResultException& e) \
|
||||
{ \
|
||||
return winrt::hresult_error(e.GetErrorCode(), winrt::to_hstring(e.what())).to_abi(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "result_macros.h"
|
||||
#include <winrt/base.h>
|
||||
|
||||
#if __WI_CONFLICTING_WINRT_EXTERNAL_CATCH_CLAUSE
|
||||
static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
|
||||
"C++/WinRT external catch clause already defined outside of WIL");
|
||||
#endif
|
||||
|
||||
// In C++/WinRT 2.0 and beyond, this function pointer exists. In earlier versions it does not. It's much easier to avoid
|
||||
// linker errors than it is to SFINAE on variable existence, so we declare the variable here, but are careful not to
|
||||
// use it unless the version of C++/WinRT is high enough
|
||||
extern std::int32_t(__stdcall* winrt_to_hresult_handler)(void*) noexcept;
|
||||
|
||||
/// @cond
|
||||
namespace wil::details
|
||||
{
|
||||
inline void MaybeGetExceptionString(
|
||||
const winrt::hresult_error& exception,
|
||||
_Out_writes_opt_(debugStringChars) PWSTR debugString,
|
||||
_When_(debugString != nullptr, _Pre_satisfies_(debugStringChars > 0)) size_t debugStringChars)
|
||||
{
|
||||
if (debugString)
|
||||
{
|
||||
StringCchPrintfW(debugString, debugStringChars, L"winrt::hresult_error: %ls", exception.message().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
inline HRESULT __stdcall ResultFromCaughtException_CppWinRt(
|
||||
_Inout_updates_opt_(debugStringChars) PWSTR debugString,
|
||||
_When_(debugString != nullptr, _Pre_satisfies_(debugStringChars > 0)) size_t debugStringChars,
|
||||
_Inout_ bool* isNormalized) noexcept
|
||||
{
|
||||
if (g_pfnResultFromCaughtException)
|
||||
{
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (const ResultException& exception)
|
||||
{
|
||||
*isNormalized = true;
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.GetErrorCode();
|
||||
}
|
||||
catch (const winrt::hresult_error& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.to_abi();
|
||||
}
|
||||
catch (const std::bad_alloc& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch (const std::out_of_range& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_BOUNDS;
|
||||
}
|
||||
catch (const std::invalid_argument& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
auto hr = RecognizeCaughtExceptionFromCallback(debugString, debugStringChars);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (const ResultException& exception)
|
||||
{
|
||||
*isNormalized = true;
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.GetErrorCode();
|
||||
}
|
||||
catch (const winrt::hresult_error& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.to_abi();
|
||||
}
|
||||
catch (const std::bad_alloc& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch (const std::out_of_range& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_BOUNDS;
|
||||
}
|
||||
catch (const std::invalid_argument& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Fall through to returning 'S_OK' below
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the caller that we were unable to map the exception by succeeding...
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
namespace wil
|
||||
{
|
||||
inline std::int32_t __stdcall winrt_to_hresult(void* returnAddress) noexcept
|
||||
{
|
||||
// C++/WinRT only gives us the return address (caller), so pass along an empty 'DiagnosticsInfo' since we don't
|
||||
// have accurate file/line/etc. information
|
||||
return static_cast<std::int32_t>(details::ReportFailure_CaughtException<FailureType::Return>(__R_DIAGNOSTICS_RA(DiagnosticsInfo{}, returnAddress)));
|
||||
}
|
||||
|
||||
inline void WilInitialize_CppWinRT()
|
||||
{
|
||||
details::g_pfnResultFromCaughtException_CppWinRt = details::ResultFromCaughtException_CppWinRt;
|
||||
if constexpr (details::major_version_from_string(CPPWINRT_VERSION) >= 2)
|
||||
{
|
||||
WI_ASSERT(winrt_to_hresult_handler == nullptr);
|
||||
winrt_to_hresult_handler = winrt_to_hresult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
#ifndef CPPWINRT_SUPPRESS_STATIC_INITIALIZERS
|
||||
WI_ODR_PRAGMA("CPPWINRT_SUPPRESS_STATIC_INITIALIZERS", "0")
|
||||
WI_HEADER_INITITALIZATION_FUNCTION(WilInitialize_CppWinRT, []
|
||||
{
|
||||
::wil::WilInitialize_CppWinRT();
|
||||
return 1;
|
||||
});
|
||||
#else
|
||||
WI_ODR_PRAGMA("CPPWINRT_SUPPRESS_STATIC_INITIALIZERS", "1")
|
||||
#endif
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
// Provides an overload of verify_hresult so that the WIL macros can recognize winrt::hresult as a valid "hresult" type.
|
||||
inline long verify_hresult(winrt::hresult hr) noexcept
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Provides versions of get_abi and put_abi for genericity that directly use HSTRING for convenience.
|
||||
template <typename T>
|
||||
auto get_abi(T const& object) noexcept
|
||||
{
|
||||
return winrt::get_abi(object);
|
||||
}
|
||||
|
||||
inline auto get_abi(winrt::hstring const& object) noexcept
|
||||
{
|
||||
return static_cast<HSTRING>(winrt::get_abi(object));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto put_abi(T& object) noexcept
|
||||
{
|
||||
return winrt::put_abi(object);
|
||||
}
|
||||
|
||||
inline auto put_abi(winrt::hstring& object) noexcept
|
||||
{
|
||||
return reinterpret_cast<HSTRING*>(winrt::put_abi(object));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __WIL_CPPWINRT_INCLUDED
|
||||
963
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/filesystem.h
vendored
Normal file
963
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/filesystem.h
vendored
Normal file
@ -0,0 +1,963 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_FILESYSTEM_INCLUDED
|
||||
#define __WIL_FILESYSTEM_INCLUDED
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#error This header is not supported in kernel-mode.
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
#include <combaseapi.h> // Needed for CoTaskMemFree() used in output of some helpers.
|
||||
#include <winbase.h> // LocalAlloc
|
||||
#include <PathCch.h>
|
||||
#include "result.h"
|
||||
#include "win32_helpers.h"
|
||||
#include "resource.h"
|
||||
|
||||
namespace wil
|
||||
{
|
||||
//! Determines if a path is an extended length path that can be used to access paths longer than MAX_PATH.
|
||||
inline bool is_extended_length_path(_In_ PCWSTR path)
|
||||
{
|
||||
return wcsncmp(path, L"\\\\?\\", 4) == 0;
|
||||
}
|
||||
|
||||
//! Find the last segment of a path. Matches the behavior of shlwapi!PathFindFileNameW()
|
||||
//! note, does not support streams being specified like PathFindFileNameW(), is that a bug or a feature?
|
||||
inline PCWSTR find_last_path_segment(_In_ PCWSTR path)
|
||||
{
|
||||
auto const pathLength = wcslen(path);
|
||||
// If there is a trailing slash ignore that in the search.
|
||||
auto const limitedLength = ((pathLength > 0) && (path[pathLength - 1] == L'\\')) ? (pathLength - 1) : pathLength;
|
||||
|
||||
PCWSTR result;
|
||||
auto const offset = FindStringOrdinal(FIND_FROMEND, path, static_cast<int>(limitedLength), L"\\", 1, TRUE);
|
||||
if (offset == -1)
|
||||
{
|
||||
result = path + pathLength; // null terminator
|
||||
}
|
||||
else
|
||||
{
|
||||
result = path + offset + 1; // just past the slash
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Determine if the file name is one of the special "." or ".." names.
|
||||
inline bool path_is_dot_or_dotdot(_In_ PCWSTR fileName)
|
||||
{
|
||||
return ((fileName[0] == L'.') &&
|
||||
((fileName[1] == L'\0') || ((fileName[1] == L'.') && (fileName[2] == L'\0'))));
|
||||
}
|
||||
|
||||
//! Returns the drive number, if it has one. Returns true if there is a drive number, false otherwise. Supports regular and extended length paths.
|
||||
inline bool try_get_drive_letter_number(_In_ PCWSTR path, _Out_ int* driveNumber)
|
||||
{
|
||||
if (path[0] == L'\\' && path[1] == L'\\' && path[2] == L'?' && path[3] == L'\\')
|
||||
{
|
||||
path += 4;
|
||||
}
|
||||
if (path[0] && (path[1] == L':'))
|
||||
{
|
||||
if ((path[0] >= L'a') && (path[0] <= L'z'))
|
||||
{
|
||||
*driveNumber = path[0] - L'a';
|
||||
return true;
|
||||
}
|
||||
else if ((path[0] >= L'A') && (path[0] <= L'Z'))
|
||||
{
|
||||
*driveNumber = path[0] - L'A';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*driveNumber = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
// PathCch.h APIs are only in desktop API for now.
|
||||
|
||||
// Compute the substring in the input value that is the parent folder path.
|
||||
// returns:
|
||||
// true + parentPathLength - path has a parent starting at the beginning path and of parentPathLength length.
|
||||
// false, no parent path, the input is a root path.
|
||||
inline bool try_get_parent_path_range(_In_ PCWSTR path, _Out_ size_t* parentPathLength)
|
||||
{
|
||||
*parentPathLength = 0;
|
||||
bool hasParent = false;
|
||||
PCWSTR rootEnd;
|
||||
if (SUCCEEDED(PathCchSkipRoot(path, &rootEnd)) && (*rootEnd != L'\0'))
|
||||
{
|
||||
auto const lastSegment = find_last_path_segment(path);
|
||||
*parentPathLength = lastSegment - path;
|
||||
hasParent = (*parentPathLength != 0);
|
||||
}
|
||||
return hasParent;
|
||||
}
|
||||
|
||||
// Creates directories for the specified path, creating parent paths
|
||||
// as needed.
|
||||
inline HRESULT CreateDirectoryDeepNoThrow(PCWSTR path) WI_NOEXCEPT
|
||||
{
|
||||
if (::CreateDirectoryW(path, nullptr) == FALSE)
|
||||
{
|
||||
DWORD const lastError = ::GetLastError();
|
||||
if (lastError == ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
size_t parentLength;
|
||||
if (try_get_parent_path_range(path, &parentLength))
|
||||
{
|
||||
wistd::unique_ptr<wchar_t[]> parent(new (std::nothrow) wchar_t[parentLength + 1]);
|
||||
RETURN_IF_NULL_ALLOC(parent.get());
|
||||
RETURN_IF_FAILED(StringCchCopyNW(parent.get(), parentLength + 1, path, parentLength));
|
||||
CreateDirectoryDeepNoThrow(parent.get()); // recurs
|
||||
}
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::CreateDirectoryW(path, nullptr));
|
||||
}
|
||||
else if (lastError != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
RETURN_WIN32(lastError);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
inline void CreateDirectoryDeep(PCWSTR path)
|
||||
{
|
||||
THROW_IF_FAILED(CreateDirectoryDeepNoThrow(path));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
//! A strongly typed version of the Win32 API GetFullPathNameW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
//! Optionally return the pointer to the file name part.
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetFullPathNameW(PCWSTR file, string_type& path, _Outptr_opt_ PCWSTR* filePart = nullptr)
|
||||
{
|
||||
wil::assign_null_to_opt_param(filePart);
|
||||
const auto hr = AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT
|
||||
{
|
||||
// Note that GetFullPathNameW() is not limited to MAX_PATH
|
||||
// but it does take a fixed size buffer.
|
||||
*valueLengthNeededWithNull = ::GetFullPathNameW(file, static_cast<DWORD>(valueLength), value, nullptr);
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
if (SUCCEEDED(hr) && filePart)
|
||||
{
|
||||
*filePart = wil::find_last_path_segment(details::string_maker<string_type>::get(path));
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! A strongly typed version of the Win32 API of GetFullPathNameW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
//! Optionally return the pointer to the file name part.
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type GetFullPathNameW(PCWSTR file, _Outptr_opt_ PCWSTR* filePart = nullptr)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((GetFullPathNameW<string_type, stackBufferLength>(file, result, filePart)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum class RemoveDirectoryOptions
|
||||
{
|
||||
None = 0,
|
||||
KeepRootDirectory = 0x1
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(RemoveDirectoryOptions);
|
||||
|
||||
namespace details
|
||||
{
|
||||
// Reparse points should not be traversed in most recursive walks of the file system,
|
||||
// unless allowed through the appropriate reparse tag.
|
||||
inline bool CanRecurseIntoDirectory(const FILE_ATTRIBUTE_TAG_INFO& info)
|
||||
{
|
||||
return (WI_IsFlagSet(info.FileAttributes, FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
(WI_IsFlagClear(info.FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) ||
|
||||
(IsReparseTagDirectory(info.ReparseTag) || (info.ReparseTag == IO_REPARSE_TAG_WCI))));
|
||||
}
|
||||
|
||||
// Retrieve a handle to a directory only if it is safe to recurse into.
|
||||
inline wil::unique_hfile TryCreateFileCanRecurseIntoDirectory(PCWSTR path, PWIN32_FIND_DATAW fileFindData)
|
||||
{
|
||||
wil::unique_hfile result(CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr));
|
||||
if (result)
|
||||
{
|
||||
FILE_ATTRIBUTE_TAG_INFO fati;
|
||||
if (GetFileInformationByHandleEx(result.get(), FileAttributeTagInfo, &fati, sizeof(fati)) &&
|
||||
CanRecurseIntoDirectory(fati))
|
||||
{
|
||||
if (fileFindData)
|
||||
{
|
||||
// Refresh the found file's data now that we have secured the directory from external manipulation.
|
||||
fileFindData->dwFileAttributes = fati.FileAttributes;
|
||||
fileFindData->dwReserved0 = fati.ReparseTag;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.reset();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// If inputPath is a non-normalized name be sure to pass an extended length form to ensure
|
||||
// it can be addressed and deleted.
|
||||
inline HRESULT RemoveDirectoryRecursiveNoThrow(PCWSTR inputPath, RemoveDirectoryOptions options = RemoveDirectoryOptions::None) WI_NOEXCEPT
|
||||
{
|
||||
wil::unique_hlocal_string path;
|
||||
PATHCCH_OPTIONS combineOptions = PATHCCH_NONE;
|
||||
|
||||
if (is_extended_length_path(inputPath))
|
||||
{
|
||||
path = wil::make_hlocal_string_nothrow(inputPath);
|
||||
RETURN_IF_NULL_ALLOC(path);
|
||||
// PathAllocCombine will convert extended length paths to regular paths if shorter than
|
||||
// MAX_PATH, avoid that behavior to provide access inputPath with non-normalized names.
|
||||
combineOptions = PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For regular paths normalize here to get consistent results when searching and deleting.
|
||||
RETURN_IF_FAILED(wil::GetFullPathNameW(inputPath, path));
|
||||
combineOptions = PATHCCH_ALLOW_LONG_PATHS;
|
||||
}
|
||||
|
||||
wil::unique_hlocal_string searchPath;
|
||||
RETURN_IF_FAILED(::PathAllocCombine(path.get(), L"*", combineOptions, &searchPath));
|
||||
|
||||
WIN32_FIND_DATAW fd;
|
||||
wil::unique_hfind findHandle(::FindFirstFileW(searchPath.get(), &fd));
|
||||
RETURN_LAST_ERROR_IF(!findHandle);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// skip "." and ".."
|
||||
if (!(WI_IsFlagSet(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY) && path_is_dot_or_dotdot(fd.cFileName)))
|
||||
{
|
||||
// Need to form an extended length path to provide the ability to delete paths > MAX_PATH
|
||||
// and files with non-normalized names (dots or spaces at the end).
|
||||
wil::unique_hlocal_string pathToDelete;
|
||||
RETURN_IF_FAILED(::PathAllocCombine(path.get(), fd.cFileName,
|
||||
PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH | PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, &pathToDelete));
|
||||
if (WI_IsFlagSet(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
// Get a handle to the directory to delete, preventing it from being replaced to prevent writes which could be used
|
||||
// to bypass permission checks, and verify that it is not a name surrogate (e.g. symlink, mount point, etc).
|
||||
wil::unique_hfile recursivelyDeletableDirectoryHandle = details::TryCreateFileCanRecurseIntoDirectory(pathToDelete.get(), &fd);
|
||||
if (recursivelyDeletableDirectoryHandle)
|
||||
{
|
||||
RemoveDirectoryOptions localOptions = options;
|
||||
RETURN_IF_FAILED(RemoveDirectoryRecursiveNoThrow(pathToDelete.get(), WI_ClearFlag(localOptions, RemoveDirectoryOptions::KeepRootDirectory)));
|
||||
}
|
||||
else if (WI_IsFlagSet(fd.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
{
|
||||
// This is a directory reparse point that should not be recursed. Delete it without traversing into it.
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::RemoveDirectoryW(pathToDelete.get()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to grab a handle to the file or to read its attributes. This is not safe to recurse.
|
||||
RETURN_WIN32(::GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// note: if pathToDelete is read-only this will fail, consider adding
|
||||
// RemoveDirectoryOptions::RemoveReadOnly to enable this behavior.
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::DeleteFileW(pathToDelete.get()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!::FindNextFileW(findHandle.get(), &fd))
|
||||
{
|
||||
auto const err = ::GetLastError();
|
||||
if (err == ERROR_NO_MORE_FILES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
RETURN_WIN32(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (WI_IsFlagClear(options, RemoveDirectoryOptions::KeepRootDirectory))
|
||||
{
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::RemoveDirectoryW(path.get()));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
inline void RemoveDirectoryRecursive(PCWSTR path, RemoveDirectoryOptions options = RemoveDirectoryOptions::None)
|
||||
{
|
||||
THROW_IF_FAILED(RemoveDirectoryRecursiveNoThrow(path, options));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
// Range based for that supports Win32 structures that use NextEntryOffset as the basis of traversing
|
||||
// a result buffer that contains data. This is used in the following FileIO calls:
|
||||
// FileStreamInfo, FILE_STREAM_INFO
|
||||
// FileIdBothDirectoryInfo, FILE_ID_BOTH_DIR_INFO
|
||||
// FileFullDirectoryInfo, FILE_FULL_DIR_INFO
|
||||
// FileIdExtdDirectoryInfo, FILE_ID_EXTD_DIR_INFO
|
||||
// ReadDirectoryChangesW, FILE_NOTIFY_INFORMATION
|
||||
|
||||
template <typename T>
|
||||
struct next_entry_offset_iterator
|
||||
{
|
||||
// Fulfill std::iterator_traits requirements
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = T;
|
||||
using pointer = const T*;
|
||||
using reference = const T&;
|
||||
#ifdef _XUTILITY_
|
||||
using iterator_category = ::std::forward_iterator_tag;
|
||||
#endif
|
||||
|
||||
next_entry_offset_iterator(T *iterable = __nullptr) : current_(iterable) {}
|
||||
|
||||
// range based for requires operator!=, operator++ and operator* to do its work
|
||||
// on the type returned from begin() and end(), provide those here.
|
||||
bool operator!=(const next_entry_offset_iterator& other) const { return current_ != other.current_; }
|
||||
|
||||
next_entry_offset_iterator& operator++()
|
||||
{
|
||||
current_ = (current_->NextEntryOffset != 0) ?
|
||||
reinterpret_cast<T *>(reinterpret_cast<unsigned char*>(current_) + current_->NextEntryOffset) :
|
||||
__nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
next_entry_offset_iterator operator++(int)
|
||||
{
|
||||
auto copy = *this;
|
||||
++(*this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
reference operator*() const WI_NOEXCEPT { return *current_; }
|
||||
pointer operator->() const WI_NOEXCEPT { return current_; }
|
||||
|
||||
next_entry_offset_iterator<T> begin() { return *this; }
|
||||
next_entry_offset_iterator<T> end() { return next_entry_offset_iterator<T>(); }
|
||||
|
||||
T* current_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
next_entry_offset_iterator<T> create_next_entry_offset_iterator(T* p)
|
||||
{
|
||||
return next_entry_offset_iterator<T>(p);
|
||||
}
|
||||
|
||||
#pragma region Folder Watcher
|
||||
// Example use in exception based code:
|
||||
// auto watcher = wil::make_folder_watcher(folder.Path().c_str(), true, wil::allChangeEvents, []()
|
||||
// {
|
||||
// // respond
|
||||
// });
|
||||
//
|
||||
// Example use in result code based code:
|
||||
// wil::unique_folder_watcher watcher;
|
||||
// THROW_IF_FAILED(watcher.create(folder, true, wil::allChangeEvents, []()
|
||||
// {
|
||||
// // respond
|
||||
// }));
|
||||
|
||||
enum class FolderChangeEvent : DWORD
|
||||
{
|
||||
ChangesLost = 0, // requies special handling, reset state as events were lost
|
||||
Added = FILE_ACTION_ADDED,
|
||||
Removed = FILE_ACTION_REMOVED,
|
||||
Modified = FILE_ACTION_MODIFIED,
|
||||
RenameOldName = FILE_ACTION_RENAMED_OLD_NAME,
|
||||
RenameNewName = FILE_ACTION_RENAMED_NEW_NAME,
|
||||
};
|
||||
|
||||
enum class FolderChangeEvents : DWORD
|
||||
{
|
||||
None = 0,
|
||||
FileName = FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||
DirectoryName = FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||
Attributes = FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||
FileSize = FILE_NOTIFY_CHANGE_SIZE,
|
||||
LastWriteTime = FILE_NOTIFY_CHANGE_LAST_WRITE,
|
||||
Security = FILE_NOTIFY_CHANGE_SECURITY,
|
||||
All = FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
FILE_NOTIFY_CHANGE_SIZE |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_SECURITY
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(FolderChangeEvents);
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
struct folder_watcher_state
|
||||
{
|
||||
folder_watcher_state(wistd::function<void()> &&callback) : m_callback(wistd::move(callback))
|
||||
{
|
||||
}
|
||||
wistd::function<void()> m_callback;
|
||||
// Order is important, need to close the thread pool wait before the change handle.
|
||||
unique_hfind_change m_findChangeHandle;
|
||||
unique_threadpool_wait m_threadPoolWait;
|
||||
};
|
||||
|
||||
inline void delete_folder_watcher_state(_In_opt_ folder_watcher_state *storage) { delete storage; }
|
||||
|
||||
typedef resource_policy<folder_watcher_state *, decltype(&details::delete_folder_watcher_state),
|
||||
details::delete_folder_watcher_state, details::pointer_access_none> folder_watcher_state_resource_policy;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <typename storage_t, typename err_policy = err_exception_policy>
|
||||
class folder_watcher_t : public storage_t
|
||||
{
|
||||
public:
|
||||
// forward all base class constructors...
|
||||
template <typename... args_t>
|
||||
explicit folder_watcher_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
|
||||
|
||||
// HRESULT or void error handling...
|
||||
typedef typename err_policy::result result;
|
||||
|
||||
// Exception-based constructors
|
||||
folder_watcher_t(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
|
||||
result create(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
return err_policy::HResult(create_common(folderToWatch, isRecursive, filter, wistd::move(callback)));
|
||||
}
|
||||
private:
|
||||
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
|
||||
// to __stdcall
|
||||
static void __stdcall callback(PTP_CALLBACK_INSTANCE /*Instance*/, void *context, TP_WAIT *pThreadPoolWait, TP_WAIT_RESULT /*result*/)
|
||||
{
|
||||
auto watcherState = static_cast<details::folder_watcher_state *>(context);
|
||||
watcherState->m_callback();
|
||||
|
||||
// Rearm the wait. Should not fail with valid parameters.
|
||||
FindNextChangeNotification(watcherState->m_findChangeHandle.get());
|
||||
SetThreadpoolWait(pThreadPoolWait, watcherState->m_findChangeHandle.get(), __nullptr);
|
||||
}
|
||||
|
||||
// This function exists to avoid template expansion of this code based on err_policy.
|
||||
HRESULT create_common(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
wistd::unique_ptr<details::folder_watcher_state> watcherState(new(std::nothrow) details::folder_watcher_state(wistd::move(callback)));
|
||||
RETURN_IF_NULL_ALLOC(watcherState);
|
||||
|
||||
watcherState->m_findChangeHandle.reset(FindFirstChangeNotificationW(folderToWatch, isRecursive, static_cast<DWORD>(filter)));
|
||||
RETURN_LAST_ERROR_IF(!watcherState->m_findChangeHandle);
|
||||
|
||||
watcherState->m_threadPoolWait.reset(CreateThreadpoolWait(&folder_watcher_t::callback, watcherState.get(), __nullptr));
|
||||
RETURN_LAST_ERROR_IF(!watcherState->m_threadPoolWait);
|
||||
this->reset(watcherState.release()); // no more failures after this, pass ownership
|
||||
SetThreadpoolWait(this->get()->m_threadPoolWait.get(), this->get()->m_findChangeHandle.get(), __nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unique_any_t<folder_watcher_t<details::unique_storage<details::folder_watcher_state_resource_policy>, err_returncode_policy>> unique_folder_watcher_nothrow;
|
||||
|
||||
inline unique_folder_watcher_nothrow make_folder_watcher_nothrow(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_folder_watcher_nothrow watcher;
|
||||
watcher.create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
typedef unique_any_t<folder_watcher_t<details::unique_storage<details::folder_watcher_state_resource_policy>, err_exception_policy>> unique_folder_watcher;
|
||||
|
||||
inline unique_folder_watcher make_folder_watcher(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
return unique_folder_watcher(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Folder Reader
|
||||
|
||||
// Example use for throwing:
|
||||
// auto reader = wil::make_folder_change_reader(folder.Path().c_str(), true, wil::FolderChangeEvents::All,
|
||||
// [](wil::FolderChangeEvent event, PCWSTR fileName)
|
||||
// {
|
||||
// switch (event)
|
||||
// {
|
||||
// case wil::FolderChangeEvent::ChangesLost: break;
|
||||
// case wil::FolderChangeEvent::Added: break;
|
||||
// case wil::FolderChangeEvent::Removed: break;
|
||||
// case wil::FolderChangeEvent::Modified: break;
|
||||
// case wil::FolderChangeEvent::RenamedOldName: break;
|
||||
// case wil::FolderChangeEvent::RenamedNewName: break;
|
||||
// });
|
||||
//
|
||||
// Example use for non throwing:
|
||||
// wil::unique_folder_change_reader_nothrow reader;
|
||||
// THROW_IF_FAILED(reader.create(folder, true, wil::FolderChangeEvents::All,
|
||||
// [](wil::FolderChangeEvent event, PCWSTR fileName)
|
||||
// {
|
||||
// // handle changes
|
||||
// }));
|
||||
//
|
||||
|
||||
// @cond
|
||||
namespace details
|
||||
{
|
||||
struct folder_change_reader_state
|
||||
{
|
||||
folder_change_reader_state(bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
: m_callback(wistd::move(callback)), m_isRecursive(isRecursive), m_filter(filter)
|
||||
{
|
||||
}
|
||||
|
||||
~folder_change_reader_state()
|
||||
{
|
||||
if (m_tpIo != __nullptr)
|
||||
{
|
||||
TP_IO *tpIo = m_tpIo;
|
||||
|
||||
// Indicate to the callback function that this object is being torn
|
||||
// down.
|
||||
|
||||
{
|
||||
auto autoLock = m_cancelLock.lock_exclusive();
|
||||
m_tpIo = __nullptr;
|
||||
}
|
||||
|
||||
// Cancel IO to terminate the file system monitoring operation.
|
||||
|
||||
if (m_folderHandle)
|
||||
{
|
||||
CancelIoEx(m_folderHandle.get(), &m_overlapped);
|
||||
}
|
||||
|
||||
// Wait for callbacks to complete.
|
||||
//
|
||||
// N.B. This is a blocking call and must not be made within a
|
||||
// callback or within a lock which is taken inside the
|
||||
// callback.
|
||||
|
||||
WaitForThreadpoolIoCallbacks(tpIo, TRUE);
|
||||
CloseThreadpoolIo(tpIo);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT StartIo()
|
||||
{
|
||||
// Unfortunately we have to handle ref-counting of IOs on behalf of the
|
||||
// thread pool.
|
||||
StartThreadpoolIo(m_tpIo);
|
||||
HRESULT hr = ReadDirectoryChangesW(m_folderHandle.get(), m_readBuffer, sizeof(m_readBuffer),
|
||||
m_isRecursive, static_cast<DWORD>(m_filter), __nullptr, &m_overlapped, __nullptr) ?
|
||||
S_OK : HRESULT_FROM_WIN32(::GetLastError());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// This operation does not have the usual semantic of returning
|
||||
// ERROR_IO_PENDING.
|
||||
// WI_ASSERT(hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING));
|
||||
|
||||
// If the operation failed for whatever reason, ensure the TP
|
||||
// ref counts are accurate.
|
||||
|
||||
CancelThreadpoolIo(m_tpIo);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// void (wil::FolderChangeEvent event, PCWSTR fileName)
|
||||
wistd::function<void(FolderChangeEvent, PCWSTR)> m_callback;
|
||||
unique_handle m_folderHandle;
|
||||
BOOL m_isRecursive = FALSE;
|
||||
FolderChangeEvents m_filter = FolderChangeEvents::None;
|
||||
OVERLAPPED m_overlapped{};
|
||||
TP_IO *m_tpIo = __nullptr;
|
||||
srwlock m_cancelLock;
|
||||
char m_readBuffer[4096]; // Consider alternative buffer sizes. With 512 byte buffer i was not able to observe overflow.
|
||||
};
|
||||
|
||||
inline void delete_folder_change_reader_state(_In_opt_ folder_change_reader_state *storage) { delete storage; }
|
||||
|
||||
typedef resource_policy<folder_change_reader_state *, decltype(&details::delete_folder_change_reader_state),
|
||||
details::delete_folder_change_reader_state, details::pointer_access_none> folder_change_reader_state_resource_policy;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <typename storage_t, typename err_policy = err_exception_policy>
|
||||
class folder_change_reader_t : public storage_t
|
||||
{
|
||||
public:
|
||||
// forward all base class constructors...
|
||||
template <typename... args_t>
|
||||
explicit folder_change_reader_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
|
||||
|
||||
// HRESULT or void error handling...
|
||||
typedef typename err_policy::result result;
|
||||
|
||||
// Exception-based constructors
|
||||
folder_change_reader_t(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
|
||||
result create(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
return err_policy::HResult(create_common(folderToWatch, isRecursive, filter, wistd::move(callback)));
|
||||
}
|
||||
|
||||
wil::unique_hfile& folder_handle() { return this->get()->m_folderHandle; }
|
||||
|
||||
private:
|
||||
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
|
||||
// to __stdcall
|
||||
static void __stdcall callback(PTP_CALLBACK_INSTANCE /* Instance */, void *context, void * /*overlapped*/,
|
||||
ULONG result, ULONG_PTR /* BytesTransferred */, TP_IO * /* Io */)
|
||||
{
|
||||
auto readerState = static_cast<details::folder_change_reader_state *>(context);
|
||||
// WI_ASSERT(overlapped == &readerState->m_overlapped);
|
||||
|
||||
bool requeue = true;
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
for (auto const& info : create_next_entry_offset_iterator(reinterpret_cast<FILE_NOTIFY_INFORMATION *>(readerState->m_readBuffer)))
|
||||
{
|
||||
wchar_t realtiveFileName[MAX_PATH];
|
||||
StringCchCopyNW(realtiveFileName, ARRAYSIZE(realtiveFileName), info.FileName, info.FileNameLength / sizeof(info.FileName[0]));
|
||||
|
||||
readerState->m_callback(static_cast<FolderChangeEvent>(info.Action), realtiveFileName);
|
||||
}
|
||||
}
|
||||
else if (result == ERROR_NOTIFY_ENUM_DIR)
|
||||
{
|
||||
readerState->m_callback(FolderChangeEvent::ChangesLost, __nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
requeue = false;
|
||||
}
|
||||
|
||||
if (requeue)
|
||||
{
|
||||
// If the lock is held non-shared or the TP IO is nullptr, this
|
||||
// structure is being torn down. Otherwise, monitor for further
|
||||
// changes.
|
||||
auto autoLock = readerState->m_cancelLock.try_lock_shared();
|
||||
if (autoLock && readerState->m_tpIo)
|
||||
{
|
||||
readerState->StartIo(); // ignoring failure here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function exists to avoid template expansion of this code based on err_policy.
|
||||
HRESULT create_common(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
wistd::unique_ptr<details::folder_change_reader_state> readerState(new(std::nothrow) details::folder_change_reader_state(
|
||||
isRecursive, filter, wistd::move(callback)));
|
||||
RETURN_IF_NULL_ALLOC(readerState);
|
||||
|
||||
readerState->m_folderHandle.reset(CreateFileW(folderToWatch,
|
||||
FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
|
||||
__nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, __nullptr));
|
||||
RETURN_LAST_ERROR_IF(!readerState->m_folderHandle);
|
||||
|
||||
readerState->m_tpIo = CreateThreadpoolIo(readerState->m_folderHandle.get(), &folder_change_reader_t::callback, readerState.get(), __nullptr);
|
||||
RETURN_LAST_ERROR_IF_NULL(readerState->m_tpIo);
|
||||
RETURN_IF_FAILED(readerState->StartIo());
|
||||
this->reset(readerState.release());
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unique_any_t<folder_change_reader_t<details::unique_storage<details::folder_change_reader_state_resource_policy>, err_returncode_policy>> unique_folder_change_reader_nothrow;
|
||||
|
||||
inline unique_folder_change_reader_nothrow make_folder_change_reader_nothrow(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter,
|
||||
wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_folder_change_reader_nothrow watcher;
|
||||
watcher.create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
typedef unique_any_t<folder_change_reader_t<details::unique_storage<details::folder_change_reader_state_resource_policy>, err_exception_policy>> unique_folder_change_reader;
|
||||
|
||||
inline unique_folder_change_reader make_folder_change_reader(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter,
|
||||
wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
return unique_folder_change_reader(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
#pragma endregion
|
||||
|
||||
//! Dos and VolumeGuid paths are always extended length paths with the \\?\ prefix.
|
||||
enum class VolumePrefix
|
||||
{
|
||||
Dos = VOLUME_NAME_DOS, // Extended Dos Device path form, e.g. \\?\C:\Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
VolumeGuid = VOLUME_NAME_GUID, // \\?\Volume{588fb606-b95b-4eae-b3cb-1e49861aaf18}\Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
// The following are special paths which can't be used with Win32 APIs, but are useful in other scenarios.
|
||||
None = VOLUME_NAME_NONE, // Path without the volume root, e.g. \Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
NtObjectName = VOLUME_NAME_NT, // Unique name used by Object Manager, e.g. \Device\HarddiskVolume4\Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
};
|
||||
enum class PathOptions
|
||||
{
|
||||
Normalized = FILE_NAME_NORMALIZED,
|
||||
Opened = FILE_NAME_OPENED,
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(PathOptions);
|
||||
|
||||
/** A strongly typed version of the Win32 API GetFinalPathNameByHandleW.
|
||||
Get the full path name in different forms
|
||||
Use this instead + VolumePrefix::None instead of GetFileInformationByHandleEx(FileNameInfo) to
|
||||
get that path form. */
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetFinalPathNameByHandleW(HANDLE fileHandle, string_type& path,
|
||||
wil::VolumePrefix volumePrefix = wil::VolumePrefix::Dos, wil::PathOptions options = wil::PathOptions::Normalized)
|
||||
{
|
||||
return AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNull = ::GetFinalPathNameByHandleW(fileHandle, value, static_cast<DWORD>(valueLength),
|
||||
static_cast<DWORD>(volumePrefix) | static_cast<DWORD>(options));
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** A strongly typed version of the Win32 API GetFinalPathNameByHandleW.
|
||||
Get the full path name in different forms. Use this + VolumePrefix::None
|
||||
instead of GetFileInformationByHandleEx(FileNameInfo) to get that path form. */
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type GetFinalPathNameByHandleW(HANDLE fileHandle,
|
||||
wil::VolumePrefix volumePrefix = wil::VolumePrefix::Dos, wil::PathOptions options = wil::PathOptions::Normalized)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((GetFinalPathNameByHandleW<string_type, stackBufferLength>(fileHandle, result, volumePrefix, options)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//! A strongly typed version of the Win32 API of GetCurrentDirectoryW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetCurrentDirectoryW(string_type& path)
|
||||
{
|
||||
return AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNull = ::GetCurrentDirectoryW(static_cast<DWORD>(valueLength), value);
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! A strongly typed version of the Win32 API of GetCurrentDirectoryW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type GetCurrentDirectoryW()
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((GetCurrentDirectoryW<string_type, stackBufferLength>(result)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: add support for these and other similar APIs.
|
||||
// GetShortPathNameW()
|
||||
// GetLongPathNameW()
|
||||
// GetWindowsDirectory()
|
||||
// GetTempDirectory()
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass> struct MapInfoClassToInfoStruct; // failure to map is a usage error caught by the compiler
|
||||
#define MAP_INFOCLASS_TO_STRUCT(InfoClass, InfoStruct, IsFixed, Extra) \
|
||||
template <> struct MapInfoClassToInfoStruct<InfoClass> \
|
||||
{ \
|
||||
typedef InfoStruct type; \
|
||||
static bool const isFixed = IsFixed; \
|
||||
static size_t const extraSize = Extra; \
|
||||
};
|
||||
|
||||
MAP_INFOCLASS_TO_STRUCT(FileBasicInfo, FILE_BASIC_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileStandardInfo, FILE_STANDARD_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileNameInfo, FILE_NAME_INFO, false, 32);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileRenameInfo, FILE_RENAME_INFO, false, 32);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileDispositionInfo, FILE_DISPOSITION_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileAllocationInfo, FILE_ALLOCATION_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileEndOfFileInfo, FILE_END_OF_FILE_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileStreamInfo, FILE_STREAM_INFO, false, 32);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileCompressionInfo, FILE_COMPRESSION_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileAttributeTagInfo, FILE_ATTRIBUTE_TAG_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdBothDirectoryInfo, FILE_ID_BOTH_DIR_INFO, false, 4096);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdBothDirectoryRestartInfo, FILE_ID_BOTH_DIR_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIoPriorityHintInfo, FILE_IO_PRIORITY_HINT_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileRemoteProtocolInfo, FILE_REMOTE_PROTOCOL_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileFullDirectoryInfo, FILE_FULL_DIR_INFO, false, 4096);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileFullDirectoryRestartInfo, FILE_FULL_DIR_INFO, true, 0);
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
||||
MAP_INFOCLASS_TO_STRUCT(FileStorageInfo, FILE_STORAGE_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileAlignmentInfo, FILE_ALIGNMENT_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdInfo, FILE_ID_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdExtdDirectoryInfo, FILE_ID_EXTD_DIR_INFO, false, 4096);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdExtdDirectoryRestartInfo, FILE_ID_EXTD_DIR_INFO, true, 0);
|
||||
#endif
|
||||
|
||||
// Type unsafe version used in the implementation to avoid template bloat.
|
||||
inline HRESULT GetFileInfo(HANDLE fileHandle, FILE_INFO_BY_HANDLE_CLASS infoClass, size_t allocationSize,
|
||||
_Outptr_result_nullonfailure_ void **result)
|
||||
{
|
||||
*result = nullptr;
|
||||
|
||||
wistd::unique_ptr<char[]> resultHolder(new(std::nothrow) char[allocationSize]);
|
||||
RETURN_IF_NULL_ALLOC(resultHolder);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (GetFileInformationByHandleEx(fileHandle, infoClass, resultHolder.get(), static_cast<DWORD>(allocationSize)))
|
||||
{
|
||||
*result = resultHolder.release();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD const lastError = ::GetLastError();
|
||||
if (lastError == ERROR_MORE_DATA)
|
||||
{
|
||||
allocationSize *= 2;
|
||||
resultHolder.reset(new(std::nothrow) char[allocationSize]);
|
||||
RETURN_IF_NULL_ALLOC(resultHolder);
|
||||
}
|
||||
else if (lastError == ERROR_NO_MORE_FILES) // for folder enumeration cases
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (lastError == ERROR_INVALID_PARAMETER) // operation not supported by file system
|
||||
{
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_WIN32(lastError);
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Get file information for a variable sized structure, returns an HRESULT.
|
||||
~~~
|
||||
wistd::unique_ptr<FILE_NAME_INFO> fileNameInfo;
|
||||
RETURN_IF_FAILED(GetFileInfoNoThrow<FileNameInfo>(fileHandle, fileNameInfo));
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<!details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
HRESULT GetFileInfoNoThrow(HANDLE fileHandle, wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type> &result) WI_NOEXCEPT
|
||||
{
|
||||
void *rawResult;
|
||||
HRESULT hr = details::GetFileInfo(fileHandle, infoClass,
|
||||
sizeof(typename details::MapInfoClassToInfoStruct<infoClass>::type) + details::MapInfoClassToInfoStruct<infoClass>::extraSize,
|
||||
&rawResult);
|
||||
result.reset(static_cast<typename details::MapInfoClassToInfoStruct<infoClass>::type*>(rawResult));
|
||||
RETURN_HR_IF_EXPECTED(hr, hr == E_INVALIDARG); // operation not supported by file system
|
||||
RETURN_IF_FAILED(hr);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Get file information for a fixed sized structure, returns an HRESULT.
|
||||
~~~
|
||||
FILE_BASIC_INFO fileBasicInfo;
|
||||
RETURN_IF_FAILED(GetFileInfoNoThrow<FileBasicInfo>(fileHandle, &fileBasicInfo));
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
HRESULT GetFileInfoNoThrow(HANDLE fileHandle, _Out_ typename details::MapInfoClassToInfoStruct<infoClass>::type *result) WI_NOEXCEPT
|
||||
{
|
||||
const HRESULT hr = GetFileInformationByHandleEx(fileHandle, infoClass, result, sizeof(*result)) ?
|
||||
S_OK : HRESULT_FROM_WIN32(::GetLastError());
|
||||
RETURN_HR_IF_EXPECTED(hr, hr == E_INVALIDARG); // operation not supported by file system
|
||||
RETURN_IF_FAILED(hr);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef _CPPUNWIND
|
||||
/** Get file information for a fixed sized structure, throws on failure.
|
||||
~~~
|
||||
auto fileBasicInfo = GetFileInfo<FileBasicInfo>(fileHandle);
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
typename details::MapInfoClassToInfoStruct<infoClass>::type GetFileInfo(HANDLE fileHandle)
|
||||
{
|
||||
typename details::MapInfoClassToInfoStruct<infoClass>::type result;
|
||||
THROW_IF_FAILED(GetFileInfoNoThrow<infoClass>(fileHandle, &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Get file information for a variable sized structure, throws on failure.
|
||||
~~~
|
||||
auto fileBasicInfo = GetFileInfo<FileNameInfo>(fileHandle);
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<!details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type> GetFileInfo(HANDLE fileHandle)
|
||||
{
|
||||
wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type> result;
|
||||
THROW_IF_FAILED(GetFileInfoNoThrow<infoClass>(fileHandle, result));
|
||||
return result;
|
||||
}
|
||||
#endif // _CPPUNWIND
|
||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
}
|
||||
|
||||
#endif // __WIL_FILESYSTEM_INCLUDED
|
||||
277
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/registry.h
vendored
Normal file
277
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/registry.h
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_REGISTRY_INCLUDED
|
||||
#define __WIL_REGISTRY_INCLUDED
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#error This header is not supported in kernel-mode.
|
||||
#endif
|
||||
|
||||
#include <winreg.h>
|
||||
#include <new.h> // new(std::nothrow)
|
||||
#include "resource.h" // unique_hkey
|
||||
|
||||
namespace wil
|
||||
{
|
||||
//! The key name includes the absolute path of the key in the registry, always starting at a
|
||||
//! base key, for example, HKEY_LOCAL_MACHINE.
|
||||
size_t const max_registry_key_name_length = 255;
|
||||
|
||||
//! The maximum number of characters allowed in a registry value's name.
|
||||
size_t const max_registry_value_name_length = 16383;
|
||||
|
||||
// unique_registry_watcher/unique_registry_watcher_nothrow/unique_registry_watcher_failfast
|
||||
// These classes make it easy to execute a provided function when a
|
||||
// registry key changes (optionally recursively). Specify the key
|
||||
// either as a root key + path, or an open registry handle as wil::unique_hkey
|
||||
// or a raw HKEY value (that will be duplicated).
|
||||
//
|
||||
// Example use with exceptions base error handling:
|
||||
// auto watcher = wil::make_registry_watcher(HKEY_CURRENT_USER, L"Software\\MyApp", true, wil::RegistryChangeKind changeKind[]
|
||||
// {
|
||||
// if (changeKind == RegistryChangeKind::Delete)
|
||||
// {
|
||||
// watcher.reset();
|
||||
// }
|
||||
// // invalidate cached registry data here
|
||||
// });
|
||||
//
|
||||
// Example use with error code base error handling:
|
||||
// auto watcher = wil::make_registry_watcher_nothrow(HKEY_CURRENT_USER, L"Software\\MyApp", true, wil::RegistryChangeKind[]
|
||||
// {
|
||||
// // invalidate cached registry data here
|
||||
// });
|
||||
// RETURN_IF_NULL_ALLOC(watcher);
|
||||
|
||||
enum class RegistryChangeKind
|
||||
{
|
||||
Modify = 0,
|
||||
Delete = 1,
|
||||
};
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
struct registry_watcher_state
|
||||
{
|
||||
registry_watcher_state(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
: m_callback(wistd::move(callback)), m_keyToWatch(wistd::move(keyToWatch)), m_isRecursive(isRecursive)
|
||||
{
|
||||
}
|
||||
wistd::function<void(RegistryChangeKind)> m_callback;
|
||||
unique_hkey m_keyToWatch;
|
||||
unique_event_nothrow m_eventHandle;
|
||||
|
||||
// While not strictly needed since this is ref counted the thread pool wait
|
||||
// should be last to ensure that the other members are valid
|
||||
// when it is destructed as it will reference them.
|
||||
unique_threadpool_wait m_threadPoolWait;
|
||||
bool m_isRecursive;
|
||||
|
||||
volatile long m_refCount = 1;
|
||||
srwlock m_lock;
|
||||
|
||||
// Returns true if the refcount can be increased from a non zero value,
|
||||
// false it was zero impling that the object is in or on the way to the destructor.
|
||||
// In this case ReleaseFromCallback() should not be called.
|
||||
bool TryAddRef()
|
||||
{
|
||||
return ::InterlockedIncrement(&m_refCount) > 1;
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
auto lock = m_lock.lock_exclusive();
|
||||
if (0 == ::InterlockedDecrement(&m_refCount))
|
||||
{
|
||||
lock.reset(); // leave the lock before deleting it.
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseFromCallback(bool rearm)
|
||||
{
|
||||
auto lock = m_lock.lock_exclusive();
|
||||
if (0 == ::InterlockedDecrement(&m_refCount))
|
||||
{
|
||||
// Destroy the thread pool wait now to avoid the wait that would occur in the
|
||||
// destructor. That wait would cause a deadlock since we are doing this from the callback.
|
||||
::CloseThreadpoolWait(m_threadPoolWait.release());
|
||||
lock.reset(); // leave the lock before deleting it.
|
||||
delete this;
|
||||
// Sleep(1); // Enable for testing to find use after free bugs.
|
||||
}
|
||||
else if (rearm)
|
||||
{
|
||||
::SetThreadpoolWait(m_threadPoolWait.get(), m_eventHandle.get(), nullptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void delete_registry_watcher_state(_In_opt_ registry_watcher_state *watcherStorage) { watcherStorage->Release(); }
|
||||
|
||||
typedef resource_policy<registry_watcher_state *, decltype(&details::delete_registry_watcher_state),
|
||||
details::delete_registry_watcher_state, details::pointer_access_none> registry_watcher_state_resource_policy;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <typename storage_t, typename err_policy = err_exception_policy>
|
||||
class registry_watcher_t : public storage_t
|
||||
{
|
||||
public:
|
||||
// forward all base class constructors...
|
||||
template <typename... args_t>
|
||||
explicit registry_watcher_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
|
||||
|
||||
// HRESULT or void error handling...
|
||||
typedef typename err_policy::result result;
|
||||
|
||||
// Exception-based constructors
|
||||
registry_watcher_t(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
registry_watcher_t(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
// Pass a root key, sub key pair or use an empty string to use rootKey as the key to watch.
|
||||
result create(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
// Most use will want to create the key, consider adding an option for open as a future design change.
|
||||
unique_hkey keyToWatch;
|
||||
HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(rootKey, subKey, 0, nullptr, 0, KEY_NOTIFY, nullptr, &keyToWatch, nullptr));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return err_policy::HResult(hr);
|
||||
}
|
||||
return err_policy::HResult(create_common(wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
|
||||
}
|
||||
|
||||
result create(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return err_policy::HResult(create_common(wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
|
||||
}
|
||||
|
||||
private:
|
||||
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
|
||||
// to __stdcall
|
||||
static void __stdcall callback(PTP_CALLBACK_INSTANCE, void *context, TP_WAIT *, TP_WAIT_RESULT)
|
||||
{
|
||||
#ifndef __WIL_REGISTRY_CHANGE_CALLBACK_TEST
|
||||
#define __WIL_REGISTRY_CHANGE_CALLBACK_TEST
|
||||
#endif
|
||||
__WIL_REGISTRY_CHANGE_CALLBACK_TEST
|
||||
auto watcherState = static_cast<details::registry_watcher_state *>(context);
|
||||
if (watcherState->TryAddRef())
|
||||
{
|
||||
// using auto reset event so don't need to manually reset.
|
||||
|
||||
// failure here is a programming error.
|
||||
const LSTATUS error = RegNotifyChangeKeyValue(watcherState->m_keyToWatch.get(), watcherState->m_isRecursive,
|
||||
REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_THREAD_AGNOSTIC,
|
||||
watcherState->m_eventHandle.get(), TRUE);
|
||||
|
||||
// Call the client before re-arming to ensure that multiple callbacks don't
|
||||
// run concurrently.
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_SUCCESS:
|
||||
case ERROR_ACCESS_DENIED:
|
||||
// Normal modification: send RegistryChangeKind::Modify and re-arm.
|
||||
watcherState->m_callback(RegistryChangeKind::Modify);
|
||||
watcherState->ReleaseFromCallback(true);
|
||||
break;
|
||||
|
||||
case ERROR_KEY_DELETED:
|
||||
// Key deleted, send RegistryChangeKind::Delete, do not re-arm.
|
||||
watcherState->m_callback(RegistryChangeKind::Delete);
|
||||
watcherState->ReleaseFromCallback(false);
|
||||
break;
|
||||
|
||||
case ERROR_HANDLE_REVOKED:
|
||||
// Handle revoked. This can occur if the user session ends before
|
||||
// the watcher shuts-down. Disarm silently since there is generally no way to respond.
|
||||
watcherState->ReleaseFromCallback(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL_FAST_HR(HRESULT_FROM_WIN32(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function exists to avoid template expansion of this code based on err_policy.
|
||||
HRESULT create_common(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
wistd::unique_ptr<details::registry_watcher_state> watcherState(new(std::nothrow) details::registry_watcher_state(
|
||||
wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
|
||||
RETURN_IF_NULL_ALLOC(watcherState);
|
||||
RETURN_IF_FAILED(watcherState->m_eventHandle.create());
|
||||
RETURN_IF_WIN32_ERROR(RegNotifyChangeKeyValue(watcherState->m_keyToWatch.get(),
|
||||
watcherState->m_isRecursive, REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_THREAD_AGNOSTIC,
|
||||
watcherState->m_eventHandle.get(), TRUE));
|
||||
|
||||
watcherState->m_threadPoolWait.reset(CreateThreadpoolWait(®istry_watcher_t::callback, watcherState.get(), nullptr));
|
||||
RETURN_LAST_ERROR_IF(!watcherState->m_threadPoolWait);
|
||||
storage_t::reset(watcherState.release()); // no more failures after this, pass ownership
|
||||
SetThreadpoolWait(storage_t::get()->m_threadPoolWait.get(), storage_t::get()->m_eventHandle.get(), nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_returncode_policy>> unique_registry_watcher_nothrow;
|
||||
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_failfast_policy>> unique_registry_watcher_failfast;
|
||||
|
||||
inline unique_registry_watcher_nothrow make_registry_watcher_nothrow(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_registry_watcher_nothrow watcher;
|
||||
watcher.create(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
inline unique_registry_watcher_nothrow make_registry_watcher_nothrow(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_registry_watcher_nothrow watcher;
|
||||
watcher.create(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
inline unique_registry_watcher_failfast make_registry_watcher_failfast(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher_failfast(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
inline unique_registry_watcher_failfast make_registry_watcher_failfast(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher_failfast(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_exception_policy >> unique_registry_watcher;
|
||||
|
||||
inline unique_registry_watcher make_registry_watcher(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
inline unique_registry_watcher make_registry_watcher(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
} // namespace wil
|
||||
|
||||
#endif
|
||||
6014
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/resource.h
vendored
Normal file
6014
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/resource.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1275
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result.h
vendored
Normal file
1275
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5940
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result_macros.h
vendored
Normal file
5940
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result_macros.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
127
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result_originate.h
vendored
Normal file
127
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result_originate.h
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
// Note: When origination is enabled by including this file, origination is done as part of the RETURN_* and THROW_* macros. Before originating
|
||||
// a new error we will observe whether there is already an error payload associated with the current thread. If there is, and the HRESULTs match,
|
||||
// then a new error will not be originated. Otherwise we will overwrite it with a new origination. The ABI boundary for WinRT APIs will check the
|
||||
// per-thread error information. The act of checking the error clears it, so there should be minimal risk of failing to originate distinct errors
|
||||
// simply because the HRESULTs match.
|
||||
//
|
||||
// For THROW_ macros we will examine the thread-local error storage once per throw. So typically once, with additional calls if the exception is
|
||||
// caught and re-thrown.
|
||||
//
|
||||
// For RETURN_ macros we will have to examine the thread-local error storage once per frame as the call stack unwinds. Because error conditions
|
||||
// -should- be uncommon the performance impact of checking TLS should be minimal. The more expensive part is originating the error because it must
|
||||
// capture the entire stack and some additional data.
|
||||
|
||||
#ifndef __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
#define __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
|
||||
#include "result.h"
|
||||
#include <OleAuto.h> // RestrictedErrorInfo uses BSTRs :(
|
||||
#include "resource.h"
|
||||
#include "com.h"
|
||||
#include <roerrorapi.h>
|
||||
|
||||
#ifndef __cplusplus_winrt // The CX runtime likes to originate errors already so we would conflict with them.
|
||||
namespace wil
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
// Note: The name must begin with "Raise" so that the !analyze auto-bucketing will ignore this stack frame. Otherwise this line of code gets all the blame.
|
||||
inline void __stdcall RaiseRoOriginateOnWilExceptions(wil::FailureInfo const& failure) WI_NOEXCEPT
|
||||
{
|
||||
if ((failure.type == FailureType::Return) || (failure.type == FailureType::Exception))
|
||||
{
|
||||
bool shouldOriginate = true;
|
||||
|
||||
wil::com_ptr_nothrow<IRestrictedErrorInfo> restrictedErrorInformation;
|
||||
if (GetRestrictedErrorInfo(&restrictedErrorInformation) == S_OK)
|
||||
{
|
||||
// This thread already has an error origination payload. Don't originate again if it has the same HRESULT that we are
|
||||
// observing right now.
|
||||
wil::unique_bstr descriptionUnused;
|
||||
HRESULT existingHr = failure.hr;
|
||||
wil::unique_bstr restrictedDescriptionUnused;
|
||||
wil::unique_bstr capabilitySidUnused;
|
||||
if (SUCCEEDED(restrictedErrorInformation->GetErrorDetails(&descriptionUnused, &existingHr, &restrictedDescriptionUnused, &capabilitySidUnused)))
|
||||
{
|
||||
shouldOriginate = (failure.hr != existingHr);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldOriginate)
|
||||
{
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
wil::unique_hmodule errorModule;
|
||||
if (GetModuleHandleExW(0, L"api-ms-win-core-winrt-error-l1-1-1.dll", &errorModule))
|
||||
{
|
||||
auto pfn = reinterpret_cast<decltype(&::RoOriginateError)>(GetProcAddress(errorModule.get(), "RoOriginateError"));
|
||||
if (pfn != nullptr)
|
||||
{
|
||||
pfn(failure.hr, nullptr);
|
||||
}
|
||||
}
|
||||
#else // DESKTOP | SYSTEM
|
||||
::RoOriginateError(failure.hr, nullptr);
|
||||
#endif // DESKTOP | SYSTEM
|
||||
}
|
||||
else if (restrictedErrorInformation)
|
||||
{
|
||||
// GetRestrictedErrorInfo returns ownership of the error information. If we aren't originating, and an error was already present,
|
||||
// then we need to restore the error information for later observation.
|
||||
SetRestrictedErrorInfo(restrictedErrorInformation.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This method will check for the presence of stowed exception data on the current thread. If such data exists, and the HRESULT
|
||||
// matches the current failure, then we will call RoFailFastWithErrorContext. RoFailFastWithErrorContext in this situation will
|
||||
// result in -VASTLY- improved crash bucketing. It is hard to express just how much better. In other cases we just return and
|
||||
// the calling method fails fast the same way it always has.
|
||||
inline void __stdcall FailfastWithContextCallback(wil::FailureInfo const& failure) WI_NOEXCEPT
|
||||
{
|
||||
wil::com_ptr_nothrow<IRestrictedErrorInfo> restrictedErrorInformation;
|
||||
if (GetRestrictedErrorInfo(&restrictedErrorInformation) == S_OK)
|
||||
{
|
||||
wil::unique_bstr descriptionUnused;
|
||||
HRESULT existingHr = failure.hr;
|
||||
wil::unique_bstr restrictedDescriptionUnused;
|
||||
wil::unique_bstr capabilitySidUnused;
|
||||
if (SUCCEEDED(restrictedErrorInformation->GetErrorDetails(&descriptionUnused, &existingHr, &restrictedDescriptionUnused, &capabilitySidUnused)) &&
|
||||
(existingHr == failure.hr))
|
||||
{
|
||||
// GetRestrictedErrorInfo returns ownership of the error information. We want it to be available for RoFailFastWithErrorContext
|
||||
// so we must restore it via SetRestrictedErrorInfo first.
|
||||
SetRestrictedErrorInfo(restrictedErrorInformation.get());
|
||||
RoFailFastWithErrorContext(existingHr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The error didn't match the current failure. Put it back in thread-local storage even though we aren't failing fast
|
||||
// in this method, so it is available in the debugger just-in-case.
|
||||
SetRestrictedErrorInfo(restrictedErrorInformation.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace details
|
||||
} // namespace wil
|
||||
|
||||
// Automatically call RoOriginateError upon error origination by including this file
|
||||
WI_HEADER_INITITALIZATION_FUNCTION(ResultStowedExceptionInitialize, []
|
||||
{
|
||||
::wil::SetOriginateErrorCallback(::wil::details::RaiseRoOriginateOnWilExceptions);
|
||||
::wil::SetFailfastWithContextCallback(::wil::details::FailfastWithContextCallback);
|
||||
return 1;
|
||||
});
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
#endif // __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
206
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/rpc_helpers.h
vendored
Normal file
206
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/rpc_helpers.h
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_RPC_HELPERS_INCLUDED
|
||||
#define __WIL_RPC_HELPERS_INCLUDED
|
||||
|
||||
#include "result.h"
|
||||
#include "resource.h"
|
||||
#include "wistd_functional.h"
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
namespace wil
|
||||
{
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
// This call-adapter template converts a void-returning 'wistd::invoke' into
|
||||
// an HRESULT-returning 'wistd::invoke' that emits S_OK. It can be eliminated
|
||||
// with 'if constexpr' when C++17 is in wide use.
|
||||
template<typename TReturnType> struct call_adapter
|
||||
{
|
||||
template<typename... TArgs> static HRESULT call(TArgs&& ... args)
|
||||
{
|
||||
return wistd::invoke(wistd::forward<TArgs>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct call_adapter<void>
|
||||
{
|
||||
template<typename... TArgs> static HRESULT call(TArgs&& ... args)
|
||||
{
|
||||
wistd::invoke(wistd::forward<TArgs>(args)...);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Some RPC exceptions are already HRESULTs. Others are in the regular Win32
|
||||
// error space. If the incoming exception code isn't an HRESULT, wrap it.
|
||||
constexpr HRESULT map_rpc_exception(DWORD code)
|
||||
{
|
||||
return IS_ERROR(code) ? code : __HRESULT_FROM_WIN32(code);
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Invokes an RPC method, mapping structured exceptions to HRESULTs
|
||||
Failures encountered by the RPC infrastructure (such as server crashes, authentication
|
||||
errors, client parameter issues, etc.) are emitted by raising a structured exception from
|
||||
within the RPC machinery. This method wraps the requested call in the usual RpcTryExcept,
|
||||
RpcTryCatch, and RpcEndExcept sequence then maps the exceptions to HRESULTs for the usual
|
||||
flow control machinery to use.
|
||||
|
||||
Many RPC methods are defined as returning HRESULT themselves, where the HRESULT indicates
|
||||
the result of the _work_. HRESULTs returned by a successful completion of the _call_ are
|
||||
returned as-is.
|
||||
|
||||
RPC methods that have a return type of 'void' are mapped to returning S_OK when the _call_
|
||||
completes successfully.
|
||||
|
||||
For example, consider an RPC interface method defined in idl as:
|
||||
~~~
|
||||
HRESULT GetKittenState([in, ref, string] const wchar_t* name, [out, retval] KittenState** state);
|
||||
~~~
|
||||
To call this method, use:
|
||||
~~~
|
||||
wil::unique_rpc_binding binding = // typically gotten elsewhere;
|
||||
wil::unique_midl_ptr<KittenState> state;
|
||||
HRESULT hr = wil::invoke_rpc_nothrow(GetKittenState, binding.get(), L"fluffy", state.put());
|
||||
RETURN_IF_FAILED(hr);
|
||||
~~~
|
||||
*/
|
||||
template<typename... TCall> HRESULT invoke_rpc_nothrow(TCall&&... args) WI_NOEXCEPT
|
||||
{
|
||||
RpcTryExcept
|
||||
{
|
||||
// Note: this helper type can be removed with C++17 enabled via
|
||||
// 'if constexpr(wistd::is_same_v<void, result_t>)'
|
||||
using result_t = typename wistd::__invoke_of<TCall...>::type;
|
||||
RETURN_IF_FAILED(details::call_adapter<result_t>::call(wistd::forward<TCall>(args)...));
|
||||
return S_OK;
|
||||
}
|
||||
RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
|
||||
{
|
||||
RETURN_HR(details::map_rpc_exception(RpcExceptionCode()));
|
||||
}
|
||||
RpcEndExcept
|
||||
}
|
||||
|
||||
/** Invokes an RPC method, mapping structured exceptions to HRESULTs
|
||||
Failures encountered by the RPC infrastructure (such as server crashes, authentication
|
||||
errors, client parameter issues, etc.) are emitted by raising a structured exception from
|
||||
within the RPC machinery. This method wraps the requested call in the usual RpcTryExcept,
|
||||
RpcTryCatch, and RpcEndExcept sequence then maps the exceptions to HRESULTs for the usual
|
||||
flow control machinery to use.
|
||||
|
||||
Some RPC methods return results (such as a state enumeration or other value) directly in
|
||||
their signature. This adapter writes that result into a caller-provided object then
|
||||
returns S_OK.
|
||||
|
||||
For example, consider an RPC interface method defined in idl as:
|
||||
~~~
|
||||
GUID GetKittenId([in, ref, string] const wchar_t* name);
|
||||
~~~
|
||||
To call this method, use:
|
||||
~~~
|
||||
wil::unique_rpc_binding binding = // typically gotten elsewhere;
|
||||
GUID id;
|
||||
HRESULT hr = wil::invoke_rpc_result_nothrow(id, GetKittenId, binding.get(), L"fluffy");
|
||||
RETURN_IF_FAILED(hr);
|
||||
~~~
|
||||
*/
|
||||
template<typename TResult, typename... TCall> HRESULT invoke_rpc_result_nothrow(TResult& result, TCall&&... args) WI_NOEXCEPT
|
||||
{
|
||||
RpcTryExcept
|
||||
{
|
||||
result = wistd::invoke(wistd::forward<TCall>(args)...);
|
||||
return S_OK;
|
||||
}
|
||||
RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
|
||||
{
|
||||
RETURN_HR(details::map_rpc_exception(RpcExceptionCode()));
|
||||
}
|
||||
RpcEndExcept
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
// Provides an adapter around calling the context-handle-close method on an
|
||||
// RPC interface, which itself is an RPC call.
|
||||
template<typename TStorage, typename close_fn_t, close_fn_t close_fn>
|
||||
struct rpc_closer_t
|
||||
{
|
||||
static void Close(TStorage arg) WI_NOEXCEPT
|
||||
{
|
||||
LOG_IF_FAILED(invoke_rpc_nothrow(close_fn, &arg));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Manages explicit RPC context handles
|
||||
Explicit RPC context handles are used in many RPC interfaces. Most interfaces with
|
||||
context handles have an explicit `FooClose([in, out] CONTEXT*)` method that lets
|
||||
the server close out the context handle. As the close method itself is an RPC call,
|
||||
it can fail and raise a structured exception.
|
||||
|
||||
This type routes the context-handle-specific `Close` call through the `invoke_rpc_nothrow`
|
||||
helper, ensuring correct cleanup and lifecycle management.
|
||||
~~~
|
||||
// Assume the interface has two methods:
|
||||
// HRESULT OpenFoo([in] handle_t binding, [out] FOO_CONTEXT*);
|
||||
// HRESULT UseFoo([in] FOO_CONTEXT context;
|
||||
// void CloseFoo([in, out] PFOO_CONTEXT);
|
||||
using unique_foo_context = wil::unique_rpc_context_handle<FOO_CONTEXT, decltype(&CloseFoo), CloseFoo>;
|
||||
unique_foo_context context;
|
||||
RETURN_IF_FAILED(wil::invoke_rpc_nothrow(OpenFoo, m_binding.get(), context.put()));
|
||||
RETURN_IF_FAILED(wil::invoke_rpc_nothrow(UseFoo, context.get()));
|
||||
context.reset();
|
||||
~~~
|
||||
*/
|
||||
template<typename TContext, typename close_fn_t, close_fn_t close_fn>
|
||||
using unique_rpc_context_handle = unique_any<TContext, decltype(&details::rpc_closer_t<TContext, close_fn_t, close_fn>::Close), details::rpc_closer_t<TContext, close_fn_t, close_fn>::Close>;
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** Invokes an RPC method, mapping structured exceptions to C++ exceptions
|
||||
See `wil::invoke_rpc_nothrow` for additional information. Failures during the _call_
|
||||
and those returned by the _method_ are mapped to HRESULTs and thrown inside a
|
||||
wil::ResultException. Using the example RPC method provided above:
|
||||
~~~
|
||||
wil::unique_midl_ptr<KittenState> state;
|
||||
wil::invoke_rpc(GetKittenState, binding.get(), L"fluffy", state.put());
|
||||
// use 'state'
|
||||
~~~
|
||||
*/
|
||||
template<typename... TCall> void invoke_rpc(TCall&& ... args)
|
||||
{
|
||||
THROW_IF_FAILED(invoke_rpc_nothrow(wistd::forward<TCall>(args)...));
|
||||
}
|
||||
|
||||
/** Invokes an RPC method, mapping structured exceptions to C++ exceptions
|
||||
See `wil::invoke_rpc_result_nothrow` for additional information. Failures during the
|
||||
_call_ are mapped to HRESULTs and thrown inside a `wil::ResultException`. Using the
|
||||
example RPC method provided above:
|
||||
~~~
|
||||
GUID id = wil::invoke_rpc_result(GetKittenId, binding.get());
|
||||
// use 'id'
|
||||
~~~
|
||||
*/
|
||||
template<typename... TCall> auto invoke_rpc_result(TCall&& ... args)
|
||||
{
|
||||
using result_t = typename wistd::__invoke_of<TCall...>::type;
|
||||
result_t result{};
|
||||
THROW_IF_FAILED(invoke_rpc_result_nothrow(result, wistd::forward<TCall>(args)...));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
369
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/safecast.h
vendored
Normal file
369
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/safecast.h
vendored
Normal file
@ -0,0 +1,369 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_SAFECAST_INCLUDED
|
||||
#define __WIL_SAFECAST_INCLUDED
|
||||
|
||||
#include "result_macros.h"
|
||||
#include <intsafe.h>
|
||||
#include "wistd_config.h"
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
namespace wil
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
// Default error case for undefined conversions in intsafe.h
|
||||
template<typename OldT, typename NewT> constexpr wistd::nullptr_t intsafe_conversion = nullptr;
|
||||
|
||||
// is_known_safe_static_cast_v determines if a conversion is known to be safe or not. Known
|
||||
// safe conversions can be handled by static_cast, this includes conversions between the same
|
||||
// type, when the new type is larger than the old type but is not a signed to unsigned
|
||||
// conversion, and when the two types are the same size and signed/unsigned. All other
|
||||
// conversions will be assumed to be potentially unsafe, and the conversion must be handled
|
||||
// by intsafe and checked.
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_known_safe_static_cast_v =
|
||||
(sizeof(NewT) > sizeof(OldT) && !(wistd::is_signed_v<OldT> && wistd::is_unsigned_v<NewT>)) ||
|
||||
(sizeof(NewT) == sizeof(OldT) && ((wistd::is_signed_v<NewT> && wistd::is_signed_v<OldT>) || (wistd::is_unsigned_v<NewT> && wistd::is_unsigned_v<OldT>)));
|
||||
|
||||
// Helper template to determine that NewT and OldT are both integral types. The safe_cast
|
||||
// operation only supports conversions between integral types.
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool both_integral_v = wistd::is_integral<NewT>::value && wistd::is_integral<OldT>::value;
|
||||
|
||||
// Note on native wchar_t (__wchar_t):
|
||||
// Intsafe.h does not currently handle native wchar_t. When compiling with /Zc:wchar_t-, this is fine as wchar_t is
|
||||
// typedef'd to unsigned short. However, when compiling with /Zc:wchar_t or wchar_t as a native type, the lack of
|
||||
// support for native wchar_t in intsafe.h becomes an issue. To work around this, we treat native wchar_t as an
|
||||
// unsigned short when passing it to intsafe.h, because the two on the Windows platform are the same size and
|
||||
// share the same range according to MSDN. If the cast is to a native wchar_t, the result from intsafe.h is cast
|
||||
// to a native wchar_t.
|
||||
|
||||
// Intsafe does not have a defined conversion for native wchar_t
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool neither_native_wchar_v = !wistd::is_same<NewT, __wchar_t>::value && !wistd::is_same<OldT, __wchar_t>::value;
|
||||
|
||||
// Check to see if the cast is a conversion to native wchar_t
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_cast_to_wchar_v = wistd::is_same<NewT, __wchar_t>::value && !wistd::is_same<OldT, __wchar_t>::value;
|
||||
|
||||
// Check to see if the cast is a conversion from native wchar_t
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_cast_from_wchar_v = !wistd::is_same<NewT, __wchar_t>::value && wistd::is_same<OldT, __wchar_t>::value;
|
||||
|
||||
// Validate the conversion to be performed has a defined mapping to an intsafe conversion
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_supported_intsafe_cast_v = intsafe_conversion<OldT, NewT> != nullptr;
|
||||
|
||||
// True when the conversion is between integral types and can be handled by static_cast
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_supported_safe_static_cast_v = both_integral_v<NewT, OldT> && is_known_safe_static_cast_v<NewT, OldT>;
|
||||
|
||||
// True when the conversion is between integral types, does not involve native wchar, has
|
||||
// a mapped intsafe conversion, and is unsafe.
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_supported_unsafe_cast_no_wchar_v =
|
||||
both_integral_v<NewT, OldT> &&
|
||||
!is_known_safe_static_cast_v<NewT, OldT> &&
|
||||
neither_native_wchar_v<NewT, OldT> &&
|
||||
is_supported_intsafe_cast_v<NewT, OldT>;
|
||||
|
||||
// True when the conversion is between integral types, is a cast to native wchar_t, has
|
||||
// a mapped intsafe conversion, and is unsafe.
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_supported_unsafe_cast_to_wchar_v =
|
||||
both_integral_v<NewT, OldT> &&
|
||||
!is_known_safe_static_cast_v<NewT, OldT> &&
|
||||
is_cast_to_wchar_v<NewT, OldT> &&
|
||||
is_supported_intsafe_cast_v<unsigned short, OldT>;
|
||||
|
||||
// True when the conversion is between integral types, is a cast from native wchar_t, has
|
||||
// a mapped intsafe conversion, and is unsafe.
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_supported_unsafe_cast_from_wchar_v =
|
||||
both_integral_v<NewT, OldT> &&
|
||||
!is_known_safe_static_cast_v<NewT, OldT> &&
|
||||
is_cast_from_wchar_v<NewT, OldT> &&
|
||||
is_supported_intsafe_cast_v<NewT, unsigned short>;
|
||||
|
||||
// True when the conversion is supported and unsafe, and may or may not involve
|
||||
// native wchar_t.
|
||||
template <typename NewT, typename OldT>
|
||||
constexpr bool is_supported_unsafe_cast_v =
|
||||
is_supported_unsafe_cast_no_wchar_v<NewT, OldT> ||
|
||||
is_supported_unsafe_cast_to_wchar_v<NewT, OldT> ||
|
||||
is_supported_unsafe_cast_from_wchar_v<NewT, OldT>;
|
||||
|
||||
// True when T is any one of the primitive types that the variably sized types are defined as.
|
||||
template <typename T>
|
||||
constexpr bool is_potentially_variably_sized_type_v =
|
||||
wistd::is_same<T, int>::value ||
|
||||
wistd::is_same<T, unsigned int>::value ||
|
||||
wistd::is_same<T, long>::value ||
|
||||
wistd::is_same<T, unsigned long>::value ||
|
||||
wistd::is_same<T, __int64>::value ||
|
||||
wistd::is_same<T, unsigned __int64>::value;
|
||||
|
||||
// True when either type is potentialy variably sized (e.g. size_t, ptrdiff_t)
|
||||
template <typename OldT, typename NewT>
|
||||
constexpr bool is_potentially_variably_sized_cast_v =
|
||||
is_potentially_variably_sized_type_v<OldT> ||
|
||||
is_potentially_variably_sized_type_v<NewT>;
|
||||
|
||||
// Mappings of all conversions defined in intsafe.h to intsafe_conversion
|
||||
// Note: Uppercase types (UINT, DWORD, SIZE_T, etc) and architecture dependent types resolve
|
||||
// to the base types. The base types are used since they do not vary based on architecture.
|
||||
template<> constexpr auto intsafe_conversion<__int64, char> = LongLongToChar;
|
||||
template<> constexpr auto intsafe_conversion<__int64, int> = LongLongToInt;
|
||||
template<> constexpr auto intsafe_conversion<__int64, long> = LongLongToLong;
|
||||
template<> constexpr auto intsafe_conversion<__int64, short> = LongLongToShort;
|
||||
template<> constexpr auto intsafe_conversion<__int64, signed char> = LongLongToInt8;
|
||||
template<> constexpr auto intsafe_conversion<__int64, unsigned __int64> = LongLongToULongLong;
|
||||
template<> constexpr auto intsafe_conversion<__int64, unsigned char> = LongLongToUChar;
|
||||
template<> constexpr auto intsafe_conversion<__int64, unsigned int> = LongLongToUInt;
|
||||
template<> constexpr auto intsafe_conversion<__int64, unsigned long> = LongLongToULong;
|
||||
template<> constexpr auto intsafe_conversion<__int64, unsigned short> = LongLongToUShort;
|
||||
template<> constexpr auto intsafe_conversion<int, char> = IntToChar;
|
||||
template<> constexpr auto intsafe_conversion<int, short> = IntToShort;
|
||||
template<> constexpr auto intsafe_conversion<int, signed char> = IntToInt8;
|
||||
template<> constexpr auto intsafe_conversion<int, unsigned __int64> = IntToULongLong;
|
||||
template<> constexpr auto intsafe_conversion<int, unsigned char> = IntToUChar;
|
||||
template<> constexpr auto intsafe_conversion<int, unsigned int> = IntToUInt;
|
||||
template<> constexpr auto intsafe_conversion<int, unsigned long> = IntToULong;
|
||||
template<> constexpr auto intsafe_conversion<int, unsigned short> = IntToUShort;
|
||||
template<> constexpr auto intsafe_conversion<long, char> = LongToChar;
|
||||
template<> constexpr auto intsafe_conversion<long, int> = LongToInt;
|
||||
template<> constexpr auto intsafe_conversion<long, short> = LongToShort;
|
||||
template<> constexpr auto intsafe_conversion<long, signed char> = LongToInt8;
|
||||
template<> constexpr auto intsafe_conversion<long, unsigned __int64> = LongToULongLong;
|
||||
template<> constexpr auto intsafe_conversion<long, unsigned char> = LongToUChar;
|
||||
template<> constexpr auto intsafe_conversion<long, unsigned int> = LongToUInt;
|
||||
template<> constexpr auto intsafe_conversion<long, unsigned long> = LongToULong;
|
||||
template<> constexpr auto intsafe_conversion<long, unsigned short> = LongToUShort;
|
||||
template<> constexpr auto intsafe_conversion<short, char> = ShortToChar;
|
||||
template<> constexpr auto intsafe_conversion<short, signed char> = ShortToInt8;
|
||||
template<> constexpr auto intsafe_conversion<short, unsigned __int64> = ShortToULongLong;
|
||||
template<> constexpr auto intsafe_conversion<short, unsigned char> = ShortToUChar;
|
||||
template<> constexpr auto intsafe_conversion<short, unsigned int> = ShortToUInt;
|
||||
template<> constexpr auto intsafe_conversion<short, unsigned long> = ShortToULong;
|
||||
template<> constexpr auto intsafe_conversion<short, unsigned short> = ShortToUShort;
|
||||
template<> constexpr auto intsafe_conversion<signed char, unsigned __int64> = Int8ToULongLong;
|
||||
template<> constexpr auto intsafe_conversion<signed char, unsigned char> = Int8ToUChar;
|
||||
template<> constexpr auto intsafe_conversion<signed char, unsigned int> = Int8ToUInt;
|
||||
template<> constexpr auto intsafe_conversion<signed char, unsigned long> = Int8ToULong;
|
||||
template<> constexpr auto intsafe_conversion<signed char, unsigned short> = Int8ToUShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, __int64> = ULongLongToLongLong;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, char> = ULongLongToChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, int> = ULongLongToInt;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, long> = ULongLongToLong;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, short> = ULongLongToShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, signed char> = ULongLongToInt8;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned char> = ULongLongToUChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned int> = ULongLongToUInt;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned long> = ULongLongToULong;
|
||||
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned short> = ULongLongToUShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned char, char> = UInt8ToChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned char, signed char> = UIntToInt8;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, char> = UIntToChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, int> = UIntToInt;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, long> = UIntToLong;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, short> = UIntToShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, signed char> = UIntToInt8;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, unsigned char> = UIntToUChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned int, unsigned short> = UIntToUShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, char> = ULongToChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, int> = ULongToInt;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, long> = ULongToLong;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, short> = ULongToShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, signed char> = ULongToInt8;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, unsigned char> = ULongToUChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, unsigned int> = ULongToUInt;
|
||||
template<> constexpr auto intsafe_conversion<unsigned long, unsigned short> = ULongToUShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned short, char> = UShortToChar;
|
||||
template<> constexpr auto intsafe_conversion<unsigned short, short> = UShortToShort;
|
||||
template<> constexpr auto intsafe_conversion<unsigned short, signed char> = UShortToInt8;
|
||||
template<> constexpr auto intsafe_conversion<unsigned short, unsigned char> = UShortToUChar;
|
||||
}
|
||||
|
||||
// Unsafe conversion where failure results in fail fast.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_no_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast_failfast(const OldT var)
|
||||
{
|
||||
NewT newVar;
|
||||
FAIL_FAST_IF_FAILED((details::intsafe_conversion<OldT, NewT>(var, &newVar)));
|
||||
return newVar;
|
||||
}
|
||||
|
||||
// Unsafe conversion where failure results in fail fast.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_from_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast_failfast(const OldT var)
|
||||
{
|
||||
NewT newVar;
|
||||
FAIL_FAST_IF_FAILED((details::intsafe_conversion<unsigned short, NewT>(static_cast<unsigned short>(var), &newVar)));
|
||||
return newVar;
|
||||
}
|
||||
|
||||
// Unsafe conversion where failure results in fail fast.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_to_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast_failfast(const OldT var)
|
||||
{
|
||||
unsigned short newVar;
|
||||
FAIL_FAST_IF_FAILED((details::intsafe_conversion<OldT, unsigned short>(var, &newVar)));
|
||||
return static_cast<__wchar_t>(newVar);
|
||||
}
|
||||
|
||||
// This conversion is always safe, therefore a static_cast is fine.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast_failfast(const OldT var)
|
||||
{
|
||||
return static_cast<NewT>(var);
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
// Unsafe conversion where failure results in a thrown exception.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_no_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast(const OldT var)
|
||||
{
|
||||
NewT newVar;
|
||||
THROW_IF_FAILED((details::intsafe_conversion<OldT, NewT>(var, &newVar)));
|
||||
return newVar;
|
||||
}
|
||||
|
||||
// Unsafe conversion where failure results in a thrown exception.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_from_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast(const OldT var)
|
||||
{
|
||||
NewT newVar;
|
||||
THROW_IF_FAILED((details::intsafe_conversion<unsigned short, NewT>(static_cast<unsigned short>(var), &newVar)));
|
||||
return newVar;
|
||||
}
|
||||
|
||||
// Unsafe conversion where failure results in a thrown exception.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_to_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast(const OldT var)
|
||||
{
|
||||
unsigned short newVar;
|
||||
THROW_IF_FAILED((details::intsafe_conversion<OldT, unsigned short>(var, &newVar)));
|
||||
return static_cast<__wchar_t>(newVar);
|
||||
}
|
||||
|
||||
// This conversion is always safe, therefore a static_cast is fine.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast(const OldT var)
|
||||
{
|
||||
return static_cast<NewT>(var);
|
||||
}
|
||||
#endif
|
||||
|
||||
// This conversion is unsafe, therefore the two parameter version of safe_cast_nothrow must be used
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast_nothrow(const OldT /*var*/)
|
||||
{
|
||||
static_assert(!wistd::is_same_v<NewT, NewT>, "This cast has the potential to fail, use the two parameter safe_cast_nothrow instead");
|
||||
}
|
||||
|
||||
// This conversion is always safe, therefore a static_cast is fine.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
NewT safe_cast_nothrow(const OldT var)
|
||||
{
|
||||
return static_cast<NewT>(var);
|
||||
}
|
||||
|
||||
// Unsafe conversion where an HRESULT is returned. It is up to the callee to check and handle the HRESULT
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_no_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
|
||||
{
|
||||
return details::intsafe_conversion<OldT, NewT>(var, newTResult);
|
||||
}
|
||||
|
||||
// Unsafe conversion where an HRESULT is returned. It is up to the callee to check and handle the HRESULT
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_from_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
|
||||
{
|
||||
return details::intsafe_conversion<unsigned short, NewT>(static_cast<unsigned short>(var), newTResult);
|
||||
}
|
||||
|
||||
// Unsafe conversion where an HRESULT is returned. It is up to the callee to check and handle the HRESULT
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_unsafe_cast_to_wchar_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
|
||||
{
|
||||
return details::intsafe_conversion<OldT, unsigned short>(var, reinterpret_cast<unsigned short *>(newTResult));
|
||||
}
|
||||
|
||||
// This conversion is always safe, therefore a static_cast is fine. If it can be determined the conversion
|
||||
// does not involve a variably sized type, then the compilation will fail and say the single parameter version
|
||||
// of safe_cast_nothrow should be used instead.
|
||||
template <
|
||||
typename NewT,
|
||||
typename OldT,
|
||||
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
|
||||
>
|
||||
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
|
||||
{
|
||||
static_assert(details::is_potentially_variably_sized_cast_v<OldT, NewT>, "This cast is always safe; use safe_cast_nothrow<T>(value) to avoid unnecessary error handling.");
|
||||
*newTResult = static_cast<NewT>(var);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __WIL_SAFECAST_INCLUDED
|
||||
114
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/stl.h
vendored
Normal file
114
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/stl.h
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_STL_INCLUDED
|
||||
#define __WIL_STL_INCLUDED
|
||||
|
||||
#include "common.h"
|
||||
#include "resource.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(WIL_ENABLE_EXCEPTIONS)
|
||||
|
||||
namespace wil
|
||||
{
|
||||
/** Secure allocator for STL containers.
|
||||
The `wil::secure_allocator` allocator calls `SecureZeroMemory` before deallocating
|
||||
memory. This provides a mechanism for secure STL containers such as `wil::secure_vector`,
|
||||
`wil::secure_string`, and `wil::secure_wstring`. */
|
||||
template <typename T>
|
||||
struct secure_allocator
|
||||
: public std::allocator<T>
|
||||
{
|
||||
template<typename Other>
|
||||
struct rebind
|
||||
{
|
||||
typedef secure_allocator<Other> other;
|
||||
};
|
||||
|
||||
secure_allocator()
|
||||
: std::allocator<T>()
|
||||
{
|
||||
}
|
||||
|
||||
~secure_allocator() = default;
|
||||
|
||||
secure_allocator(const secure_allocator& a)
|
||||
: std::allocator<T>(a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
secure_allocator(const secure_allocator<U>& a)
|
||||
: std::allocator<T>(a)
|
||||
{
|
||||
}
|
||||
|
||||
T* allocate(size_t n)
|
||||
{
|
||||
return std::allocator<T>::allocate(n);
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_t n)
|
||||
{
|
||||
SecureZeroMemory(p, sizeof(T) * n);
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
//! `wil::secure_vector` will be securely zeroed before deallocation.
|
||||
template <typename Type>
|
||||
using secure_vector = std::vector<Type, secure_allocator<Type>>;
|
||||
//! `wil::secure_wstring` will be securely zeroed before deallocation.
|
||||
using secure_wstring = std::basic_string<wchar_t, std::char_traits<wchar_t>, wil::secure_allocator<wchar_t>>;
|
||||
//! `wil::secure_string` will be securely zeroed before deallocation.
|
||||
using secure_string = std::basic_string<char, std::char_traits<char>, wil::secure_allocator<char>>;
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template<> struct string_maker<std::wstring>
|
||||
{
|
||||
HRESULT make(_In_reads_opt_(length) PCWSTR source, size_t length) WI_NOEXCEPT try
|
||||
{
|
||||
m_value = source ? std::wstring(source, length) : std::wstring(length, L'\0');
|
||||
return S_OK;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
wchar_t* buffer() { return &m_value[0]; }
|
||||
|
||||
std::wstring release() { return std::wstring(std::move(m_value)); }
|
||||
|
||||
static PCWSTR get(const std::wstring& value) { return value.c_str(); }
|
||||
|
||||
private:
|
||||
std::wstring m_value;
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
// str_raw_ptr is an overloaded function that retrieves a const pointer to the first character in a string's buffer.
|
||||
// This is the overload for std::wstring. Other overloads available in resource.h.
|
||||
inline PCWSTR str_raw_ptr(const std::wstring& str)
|
||||
{
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
} // namespace wil
|
||||
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#endif // __WIL_STL_INCLUDED
|
||||
597
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/token_helpers.h
vendored
Normal file
597
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/token_helpers.h
vendored
Normal file
@ -0,0 +1,597 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_TOKEN_HELPERS_INCLUDED
|
||||
#define __WIL_TOKEN_HELPERS_INCLUDED
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#error This header is not supported in kernel-mode.
|
||||
#endif
|
||||
|
||||
#include "resource.h"
|
||||
#include <new>
|
||||
#include <lmcons.h> // for UNLEN and DNLEN
|
||||
#include <processthreadsapi.h>
|
||||
|
||||
// for GetUserNameEx()
|
||||
#define SECURITY_WIN32
|
||||
#include <Security.h>
|
||||
|
||||
namespace wil
|
||||
{
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
// Template specialization for TOKEN_INFORMATION_CLASS, add more mappings here as needed
|
||||
// TODO: The mapping should be reversed to be MapTokenInfoClassToStruct since there may
|
||||
// be an info class value that uses the same structure. That is the case for the file
|
||||
// system information.
|
||||
template<typename T> struct MapTokenStructToInfoClass;
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_ACCESS_INFORMATION> { static const TOKEN_INFORMATION_CLASS infoClass = TokenAccessInformation; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_APPCONTAINER_INFORMATION> { static const TOKEN_INFORMATION_CLASS infoClass = TokenAppContainerSid; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_DEFAULT_DACL> { static const TOKEN_INFORMATION_CLASS infoClass = TokenDefaultDacl; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_GROUPS_AND_PRIVILEGES> { static const TOKEN_INFORMATION_CLASS infoClass = TokenGroupsAndPrivileges; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_MANDATORY_LABEL> { static const TOKEN_INFORMATION_CLASS infoClass = TokenIntegrityLevel; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_OWNER> { static const TOKEN_INFORMATION_CLASS infoClass = TokenOwner; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_PRIMARY_GROUP> { static const TOKEN_INFORMATION_CLASS infoClass = TokenPrimaryGroup; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_PRIVILEGES> { static const TOKEN_INFORMATION_CLASS infoClass = TokenPrivileges; static const bool FixedSize = false; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_USER> { static const TOKEN_INFORMATION_CLASS infoClass = TokenUser; static const bool FixedSize = false; };
|
||||
|
||||
// fixed size cases
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_ELEVATION_TYPE> { static const TOKEN_INFORMATION_CLASS infoClass = TokenElevationType; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_MANDATORY_POLICY> { static const TOKEN_INFORMATION_CLASS infoClass = TokenMandatoryPolicy; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_ORIGIN> { static const TOKEN_INFORMATION_CLASS infoClass = TokenOrigin; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_SOURCE> { static const TOKEN_INFORMATION_CLASS infoClass = TokenSource; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_STATISTICS> { static const TOKEN_INFORMATION_CLASS infoClass = TokenStatistics; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_TYPE> { static const TOKEN_INFORMATION_CLASS infoClass = TokenType; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<SECURITY_IMPERSONATION_LEVEL> { static const TOKEN_INFORMATION_CLASS infoClass = TokenImpersonationLevel; static const bool FixedSize = true; };
|
||||
template<> struct MapTokenStructToInfoClass<TOKEN_ELEVATION> { static const TOKEN_INFORMATION_CLASS infoClass = TokenElevation; static const bool FixedSize = true; };
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
enum class OpenThreadTokenAs
|
||||
{
|
||||
Current,
|
||||
Self
|
||||
};
|
||||
|
||||
/** Open the active token.
|
||||
Opens either the current thread token (if impersonating) or the current process token. Returns a token the caller
|
||||
can use with methods like get_token_information<> below. By default, the token is opened for TOKEN_QUERY and as the
|
||||
effective user.
|
||||
|
||||
Consider using GetCurrentThreadEffectiveToken() instead of this method when eventually calling get_token_information.
|
||||
This method returns a real handle to the effective token, but GetCurrentThreadEffectiveToken() is a Pseudo-handle
|
||||
and much easier to manage.
|
||||
~~~~
|
||||
wil::unique_handle theToken;
|
||||
RETURN_IF_FAILED(wil::open_current_access_token_nothrow(&theToken));
|
||||
~~~~
|
||||
Callers who want more access to the token (such as to duplicate or modify the token) can pass
|
||||
any mask of the token rights.
|
||||
~~~~
|
||||
wil::unique_handle theToken;
|
||||
RETURN_IF_FAILED(wil::open_current_access_token_nothrow(&theToken, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES));
|
||||
~~~~
|
||||
Services impersonating their clients may need to request that the active token is opened on the
|
||||
behalf of the service process to perform certain operations. Opening a token for impersonation access
|
||||
or privilege-adjustment are examples of uses.
|
||||
~~~~
|
||||
wil::unique_handle callerToken;
|
||||
RETURN_IF_FAILED(wil::open_current_access_token_nothrow(&theToken, TOKEN_QUERY | TOKEN_IMPERSONATE, true));
|
||||
~~~~
|
||||
@param tokenHandle Receives the token opened during the operation. Must be CloseHandle'd by the caller, or
|
||||
(preferably) stored in a wil::unique_handle
|
||||
@param access Bits from the TOKEN_* access mask which are passed to OpenThreadToken/OpenProcessToken
|
||||
@param asSelf When true, and if the thread is impersonating, the thread token is opened using the
|
||||
process token's rights.
|
||||
*/
|
||||
inline HRESULT open_current_access_token_nothrow(_Out_ HANDLE* tokenHandle, unsigned long access = TOKEN_QUERY, OpenThreadTokenAs openAs = OpenThreadTokenAs::Current)
|
||||
{
|
||||
HRESULT hr = (OpenThreadToken(GetCurrentThread(), access, (openAs == OpenThreadTokenAs::Self), tokenHandle) ? S_OK : HRESULT_FROM_WIN32(::GetLastError()));
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_NO_TOKEN))
|
||||
{
|
||||
hr = (OpenProcessToken(GetCurrentProcess(), access, tokenHandle) ? S_OK : HRESULT_FROM_WIN32(::GetLastError()));
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//! Current thread or process token, consider using GetCurrentThreadEffectiveToken() instead.
|
||||
inline wil::unique_handle open_current_access_token_failfast(unsigned long access = TOKEN_QUERY, OpenThreadTokenAs openAs = OpenThreadTokenAs::Current)
|
||||
{
|
||||
HANDLE rawTokenHandle;
|
||||
FAIL_FAST_IF_FAILED(open_current_access_token_nothrow(&rawTokenHandle, access, openAs));
|
||||
return wil::unique_handle(rawTokenHandle);
|
||||
}
|
||||
|
||||
// Exception based function to open current thread/process access token and acquire pointer to it
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! Current thread or process token, consider using GetCurrentThreadEffectiveToken() instead.
|
||||
inline wil::unique_handle open_current_access_token(unsigned long access = TOKEN_QUERY, OpenThreadTokenAs openAs = OpenThreadTokenAs::Current)
|
||||
{
|
||||
HANDLE rawTokenHandle;
|
||||
THROW_IF_FAILED(open_current_access_token_nothrow(&rawTokenHandle, access, openAs));
|
||||
return wil::unique_handle(rawTokenHandle);
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
// Returns tokenHandle or the effective thread token if tokenHandle is null.
|
||||
// Note, this returns an token handle who's lifetime is managed independently
|
||||
// and it may be a pseudo token, don't free it!
|
||||
inline HANDLE GetCurrentThreadEffectiveTokenWithOverride(HANDLE tokenHandle)
|
||||
{
|
||||
return tokenHandle ? tokenHandle : GetCurrentThreadEffectiveToken();
|
||||
}
|
||||
|
||||
/** Fetches information about a token.
|
||||
See GetTokenInformation on MSDN for what this method can return. For variable sized structs the information
|
||||
is returned to the caller as a wistd::unique_ptr<T> (like TOKEN_ORIGIN, TOKEN_USER, TOKEN_ELEVATION, etc.). For
|
||||
fixed sized, the struct is returned directly.
|
||||
The caller must have access to read the information from the provided token. This method works with both real
|
||||
(e.g. OpenCurrentAccessToken) and pseudo (e.g. GetCurrentThreadToken) token handles.
|
||||
~~~~
|
||||
// Retrieve the TOKEN_USER structure for the current process
|
||||
wistd::unique_ptr<TOKEN_USER> user;
|
||||
RETURN_IF_FAILED(wil::get_token_information_nothrow(user, GetCurrentProcessToken()));
|
||||
RETURN_IF_FAILED(ConsumeSid(user->User.Sid));
|
||||
~~~~
|
||||
Not specifying the token handle is the same as specifying 'nullptr' and retrieves information about the effective token.
|
||||
~~~~
|
||||
wistd::unique_ptr<TOKEN_PRIVILEGES> privileges;
|
||||
RETURN_IF_FAILED(wil::get_token_information_nothrow(privileges));
|
||||
for (auto const& privilege : wil::GetRange(privileges->Privileges, privileges->PrivilegeCount))
|
||||
{
|
||||
RETURN_IF_FAILED(ConsumePrivilege(privilege));
|
||||
}
|
||||
~~~~
|
||||
@param tokenInfo Receives a pointer to a structure containing the results of GetTokenInformation for the requested
|
||||
type. The type of <T> selects which TOKEN_INFORMATION_CLASS will be used.
|
||||
@param tokenHandle Specifies which token will be queried. When nullptr, the thread's effective current token is used.
|
||||
@return S_OK on success, a FAILED hresult containing the win32 error from querying the token otherwise.
|
||||
*/
|
||||
|
||||
template <typename T, wistd::enable_if_t<!details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
|
||||
inline HRESULT get_token_information_nothrow(wistd::unique_ptr<T>& tokenInfo, HANDLE tokenHandle = nullptr)
|
||||
{
|
||||
tokenInfo.reset();
|
||||
tokenHandle = GetCurrentThreadEffectiveTokenWithOverride(tokenHandle);
|
||||
|
||||
DWORD tokenInfoSize = 0;
|
||||
const auto infoClass = details::MapTokenStructToInfoClass<T>::infoClass;
|
||||
RETURN_LAST_ERROR_IF(!((!GetTokenInformation(tokenHandle, infoClass, nullptr, 0, &tokenInfoSize)) &&
|
||||
(::GetLastError() == ERROR_INSUFFICIENT_BUFFER)));
|
||||
wistd::unique_ptr<char> tokenInfoClose(
|
||||
static_cast<char*>(operator new(tokenInfoSize, std::nothrow)));
|
||||
RETURN_IF_NULL_ALLOC(tokenInfoClose.get());
|
||||
RETURN_IF_WIN32_BOOL_FALSE(GetTokenInformation(tokenHandle, infoClass, tokenInfoClose.get(), tokenInfoSize, &tokenInfoSize));
|
||||
tokenInfo.reset(reinterpret_cast<T *>(tokenInfoClose.release()));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
template <typename T, wistd::enable_if_t<details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
|
||||
inline HRESULT get_token_information_nothrow(_Out_ T* tokenInfo, HANDLE tokenHandle = nullptr)
|
||||
{
|
||||
*tokenInfo = {};
|
||||
tokenHandle = GetCurrentThreadEffectiveTokenWithOverride(tokenHandle);
|
||||
|
||||
DWORD tokenInfoSize = sizeof(T);
|
||||
const auto infoClass = details::MapTokenStructToInfoClass<T>::infoClass;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(GetTokenInformation(tokenHandle, infoClass, tokenInfo, tokenInfoSize, &tokenInfoSize));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<typename T, typename policy, wistd::enable_if_t<!details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
|
||||
wistd::unique_ptr<T> GetTokenInfoWrap(HANDLE token = nullptr)
|
||||
{
|
||||
wistd::unique_ptr<T> temp;
|
||||
policy::HResult(get_token_information_nothrow(temp, token));
|
||||
return temp;
|
||||
}
|
||||
|
||||
template<typename T, typename policy, wistd::enable_if_t<details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
|
||||
T GetTokenInfoWrap(HANDLE token = nullptr)
|
||||
{
|
||||
T temp{};
|
||||
policy::HResult(get_token_information_nothrow(&temp, token));
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
//! A variant of get_token_information<T> that fails-fast on errors retrieving the token
|
||||
template <typename T>
|
||||
inline auto get_token_information_failfast(HANDLE token = nullptr)
|
||||
{
|
||||
return details::GetTokenInfoWrap<T, err_failfast_policy>(token);
|
||||
}
|
||||
|
||||
//! Overload of GetTokenInformationNoThrow that retrieves a token linked from the provided token
|
||||
inline HRESULT get_token_information_nothrow(unique_token_linked_token& tokenInfo, HANDLE tokenHandle = nullptr)
|
||||
{
|
||||
static_assert(sizeof(tokenInfo) == sizeof(TOKEN_LINKED_TOKEN), "confusing size mismatch");
|
||||
tokenHandle = GetCurrentThreadEffectiveTokenWithOverride(tokenHandle);
|
||||
|
||||
DWORD tokenInfoSize = 0;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::GetTokenInformation(tokenHandle, TokenLinkedToken,
|
||||
tokenInfo.reset_and_addressof(), sizeof(tokenInfo), &tokenInfoSize));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Retrieves the linked-token information for a token.
|
||||
Fails-fast if the link information cannot be retrieved.
|
||||
~~~~
|
||||
auto link = get_linked_token_information_failfast(GetCurrentThreadToken());
|
||||
auto tokenUser = get_token_information<TOKEN_USER>(link.LinkedToken);
|
||||
~~~~
|
||||
@param token Specifies the token to query. Pass nullptr to use the current effective thread token
|
||||
@return unique_token_linked_token containing a handle to the linked token
|
||||
*/
|
||||
inline unique_token_linked_token get_linked_token_information_failfast(HANDLE token = nullptr)
|
||||
{
|
||||
unique_token_linked_token tokenInfo;
|
||||
FAIL_FAST_IF_FAILED(get_token_information_nothrow(tokenInfo, token));
|
||||
return tokenInfo;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** Fetches information about a token.
|
||||
See get_token_information_nothrow for full details.
|
||||
~~~~
|
||||
auto user = wil::get_token_information<TOKEN_USER>(GetCurrentProcessToken());
|
||||
ConsumeSid(user->User.Sid);
|
||||
~~~~
|
||||
Pass 'nullptr' (or omit the parameter) as tokenHandle to retrieve information about the effective token.
|
||||
~~~~
|
||||
auto privs = wil::get_token_information<TOKEN_PRIVILEGES>(privileges);
|
||||
for (auto& priv : wil::make_range(privs->Privileges, privs->Privilieges + privs->PrivilegeCount))
|
||||
{
|
||||
if (priv.Attributes & SE_PRIVILEGE_ENABLED)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
@return A pointer to a structure containing the results of GetTokenInformation for the requested type. The type of
|
||||
<T> selects which TOKEN_INFORMATION_CLASS will be used.
|
||||
@param token Specifies which token will be queried. When nullptr or not set, the thread's effective current token is used.
|
||||
*/
|
||||
template <typename T>
|
||||
inline auto get_token_information(HANDLE token = nullptr)
|
||||
{
|
||||
return details::GetTokenInfoWrap<T, err_exception_policy>(token);
|
||||
}
|
||||
|
||||
/** Retrieves the linked-token information for a token.
|
||||
Throws an exception if the link information cannot be retrieved.
|
||||
~~~~
|
||||
auto link = get_linked_token_information(GetCurrentThreadToken());
|
||||
auto tokenUser = get_token_information<TOKEN_USER>(link.LinkedToken);
|
||||
~~~~
|
||||
@param token Specifies the token to query. Pass nullptr to use the current effective thread token
|
||||
@return unique_token_linked_token containing a handle to the linked token
|
||||
*/
|
||||
inline unique_token_linked_token get_linked_token_information(HANDLE token = nullptr)
|
||||
{
|
||||
unique_token_linked_token tokenInfo;
|
||||
THROW_IF_FAILED(get_token_information_nothrow(tokenInfo, token));
|
||||
return tokenInfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
inline void RevertImpersonateToken(_Pre_opt_valid_ _Frees_ptr_opt_ HANDLE oldToken)
|
||||
{
|
||||
FAIL_FAST_IMMEDIATE_IF(!::SetThreadToken(nullptr, oldToken));
|
||||
|
||||
if (oldToken)
|
||||
{
|
||||
::CloseHandle(oldToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
using unique_token_reverter = wil::unique_any<
|
||||
HANDLE,
|
||||
decltype(&details::RevertImpersonateToken),
|
||||
details::RevertImpersonateToken,
|
||||
details::pointer_access_none,
|
||||
HANDLE,
|
||||
INT_PTR,
|
||||
-1,
|
||||
HANDLE>;
|
||||
|
||||
/** Temporarily impersonates a token on this thread.
|
||||
This method sets a new token on a thread, restoring the current token when the returned object
|
||||
is destroyed. Useful for impersonating other tokens or running as 'self,' especially in services.
|
||||
~~~~
|
||||
HRESULT OpenFileAsSessionuser(PCWSTR filePath, DWORD session, _Out_ HANDLE* opened)
|
||||
{
|
||||
wil::unique_handle userToken;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(QueryUserToken(session, &userToken));
|
||||
|
||||
wil::unique_token_reverter reverter;
|
||||
RETURN_IF_FAILED(wil::impersonate_token_nothrow(userToken.get(), reverter));
|
||||
|
||||
wil::unique_hfile userFile(::CreateFile(filePath, ...));
|
||||
RETURN_LAST_ERROR_IF(!userFile && (::GetLastError() != ERROR_FILE_NOT_FOUND));
|
||||
|
||||
*opened = userFile.release();
|
||||
return S_OK;
|
||||
}
|
||||
~~~~
|
||||
@param token A token to impersonate, or 'nullptr' to run as the process identity.
|
||||
*/
|
||||
inline HRESULT impersonate_token_nothrow(HANDLE token, unique_token_reverter& reverter)
|
||||
{
|
||||
wil::unique_handle currentToken;
|
||||
|
||||
// Get the token for the current thread. If there wasn't one, the reset will clear it as well
|
||||
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, ¤tToken))
|
||||
{
|
||||
RETURN_LAST_ERROR_IF(::GetLastError() != ERROR_NO_TOKEN);
|
||||
}
|
||||
|
||||
// Update the current token
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::SetThreadToken(nullptr, token));
|
||||
|
||||
reverter.reset(currentToken.release()); // Ownership passed
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Temporarily clears any impersonation on this thread.
|
||||
This method resets the current thread's token to nullptr, indicating that it is not impersonating
|
||||
any user. Useful for elevating to whatever identity a service or higher-privilege process might
|
||||
be capable of running under.
|
||||
~~~~
|
||||
HRESULT DeleteFileRetryAsSelf(PCWSTR filePath)
|
||||
{
|
||||
if (!::DeleteFile(filePath))
|
||||
{
|
||||
RETURN_LAST_ERROR_IF(::GetLastError() != ERROR_ACCESS_DENIED);
|
||||
wil::unique_token_reverter reverter;
|
||||
RETURN_IF_FAILED(wil::run_as_self_nothrow(reverter));
|
||||
RETURN_IF_FAILED(TakeOwnershipOfFile(filePath));
|
||||
RETURN_IF_FAILED(GrantDeleteAccess(filePath));
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::DeleteFile(filePath));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
~~~~
|
||||
*/
|
||||
inline HRESULT run_as_self_nothrow(unique_token_reverter& reverter)
|
||||
{
|
||||
return impersonate_token_nothrow(nullptr, reverter);
|
||||
}
|
||||
|
||||
inline unique_token_reverter impersonate_token_failfast(HANDLE token)
|
||||
{
|
||||
unique_token_reverter oldToken;
|
||||
FAIL_FAST_IF_FAILED(impersonate_token_nothrow(token, oldToken));
|
||||
return oldToken;
|
||||
}
|
||||
|
||||
inline unique_token_reverter run_as_self_failfast()
|
||||
{
|
||||
return impersonate_token_failfast(nullptr);
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** Temporarily impersonates a token on this thread.
|
||||
This method sets a new token on a thread, restoring the current token when the returned object
|
||||
is destroyed. Useful for impersonating other tokens or running as 'self,' especially in services.
|
||||
~~~~
|
||||
wil::unique_hfile OpenFileAsSessionuser(_In_z_ const wchar_t* filePath, DWORD session)
|
||||
{
|
||||
wil::unique_handle userToken;
|
||||
THROW_IF_WIN32_BOOL_FALSE(QueryUserToken(session, &userToken));
|
||||
|
||||
auto priorToken = wil::impersonate_token(userToken.get());
|
||||
|
||||
wil::unique_hfile userFile(::CreateFile(filePath, ...));
|
||||
THROW_LAST_ERROR_IF(::GetLastError() != ERROR_FILE_NOT_FOUND);
|
||||
|
||||
return userFile;
|
||||
}
|
||||
~~~~
|
||||
@param token A token to impersonate, or 'nullptr' to run as the process identity.
|
||||
*/
|
||||
inline unique_token_reverter impersonate_token(HANDLE token = nullptr)
|
||||
{
|
||||
unique_token_reverter oldToken;
|
||||
THROW_IF_FAILED(impersonate_token_nothrow(token, oldToken));
|
||||
return oldToken;
|
||||
}
|
||||
|
||||
/** Temporarily clears any impersonation on this thread.
|
||||
This method resets the current thread's token to nullptr, indicating that it is not impersonating
|
||||
any user. Useful for elevating to whatever identity a service or higher-privilege process might
|
||||
be capable of running under.
|
||||
~~~~
|
||||
void DeleteFileRetryAsSelf(_In_z_ const wchar_t* filePath)
|
||||
{
|
||||
if (!::DeleteFile(filePath) && (::GetLastError() == ERROR_ACCESS_DENIED))
|
||||
{
|
||||
auto priorToken = wil::run_as_self();
|
||||
TakeOwnershipOfFile(filePath);
|
||||
GrantDeleteAccess(filePath);
|
||||
::DeleteFile(filePath);
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
*/
|
||||
inline unique_token_reverter run_as_self()
|
||||
{
|
||||
return impersonate_token(nullptr);
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<size_t AuthorityCount> struct static_sid_t
|
||||
{
|
||||
BYTE Revision;
|
||||
BYTE SubAuthorityCount;
|
||||
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
|
||||
DWORD SubAuthority[AuthorityCount];
|
||||
|
||||
PSID get()
|
||||
{
|
||||
return reinterpret_cast<PSID>(this);
|
||||
}
|
||||
|
||||
template<size_t other> static_sid_t& operator=(const static_sid_t<other>& source)
|
||||
{
|
||||
static_assert(other <= AuthorityCount, "Cannot assign from a larger static sid to a smaller one");
|
||||
|
||||
if (&this->Revision != &source.Revision)
|
||||
{
|
||||
memcpy(this, &source, sizeof(source));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Returns a structure containing a Revision 1 SID initialized with the authorities provided
|
||||
Replaces AllocateAndInitializeSid by constructing a structure laid out like a PSID, but
|
||||
returned like a value. The resulting object is suitable for use with any method taking PSID,
|
||||
passed by "&the_sid" or via "the_sid.get()"
|
||||
~~~~
|
||||
// Change the owner of the key to administrators
|
||||
auto systemSid = wil::make_static_sid(SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
|
||||
RETURN_IF_WIN32_ERROR(SetNamedSecurityInfo(keyPath, SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION, &systemSid, nullptr, nullptr, nullptr));
|
||||
~~~~
|
||||
*/
|
||||
template<typename... Ts> constexpr auto make_static_sid(const SID_IDENTIFIER_AUTHORITY& authority, Ts&&... subAuthorities)
|
||||
{
|
||||
using sid_t = details::static_sid_t<sizeof...(subAuthorities)>;
|
||||
|
||||
static_assert(sizeof...(subAuthorities) <= SID_MAX_SUB_AUTHORITIES, "too many sub authorities");
|
||||
static_assert(offsetof(sid_t, Revision) == offsetof(_SID, Revision), "layout mismatch");
|
||||
static_assert(offsetof(sid_t, SubAuthorityCount) == offsetof(_SID, SubAuthorityCount), "layout mismatch");
|
||||
static_assert(offsetof(sid_t, IdentifierAuthority) == offsetof(_SID, IdentifierAuthority), "layout mismatch");
|
||||
static_assert(offsetof(sid_t, SubAuthority) == offsetof(_SID, SubAuthority), "layout mismatch");
|
||||
|
||||
return sid_t { SID_REVISION, sizeof...(subAuthorities), authority, { static_cast<DWORD>(subAuthorities)... } };
|
||||
}
|
||||
|
||||
//! Variant of static_sid that defaults to the NT authority
|
||||
template<typename... Ts> constexpr auto make_static_nt_sid(Ts&& ... subAuthorities)
|
||||
{
|
||||
return make_static_sid(SECURITY_NT_AUTHORITY, wistd::forward<Ts>(subAuthorities)...);
|
||||
}
|
||||
|
||||
/** Determines whether a specified security identifier (SID) is enabled in an access token.
|
||||
This function determines whether a security identifier, described by a given set of subauthorities, is enabled
|
||||
in the given access token. Note that only up to eight subauthorities can be passed to this function.
|
||||
~~~~
|
||||
bool IsGuest()
|
||||
{
|
||||
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS));
|
||||
}
|
||||
~~~~
|
||||
@param result This will be set to true if and only if a security identifier described by the given set of subauthorities is enabled in the given access token.
|
||||
@param token A handle to an access token. The handle must have TOKEN_QUERY access to the token, and must be an impersonation token. If token is nullptr, test_token_membership
|
||||
uses the impersonation token of the calling thread. If the thread is not impersonating, the function duplicates the thread's primary token to create an impersonation token.
|
||||
@param sidAuthority A reference to a SID_IDENTIFIER_AUTHORITY structure. This structure provides the top-level identifier authority value to set in the SID.
|
||||
@param subAuthorities Up to 15 subauthority values to place in the SID (this is a systemwide limit)
|
||||
@return S_OK on success, a FAILED hresult containing the win32 error from creating the SID or querying the token otherwise.
|
||||
*/
|
||||
template<typename... Ts> HRESULT test_token_membership_nothrow(_Out_ bool* result, _In_opt_ HANDLE token,
|
||||
const SID_IDENTIFIER_AUTHORITY& sidAuthority, Ts&&... subAuthorities)
|
||||
{
|
||||
*result = false;
|
||||
auto tempSid = make_static_sid(sidAuthority, wistd::forward<Ts>(subAuthorities)...);
|
||||
BOOL isMember;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(CheckTokenMembership(token, &tempSid, &isMember));
|
||||
|
||||
*result = (isMember != FALSE);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Determine whether a token represents an app container
|
||||
This method uses the passed in token and emits a boolean indicating that
|
||||
whether TokenIsAppContainer is true.
|
||||
~~~~
|
||||
HRESULT OnlyIfAppContainer()
|
||||
{
|
||||
bool isAppContainer;
|
||||
RETURN_IF_FAILED(wil::get_token_is_app_container_nothrow(nullptr, isAppContainer));
|
||||
RETURN_HR_IF(E_ACCESSDENIED, !isAppContainer);
|
||||
RETURN_HR(...);
|
||||
}
|
||||
~~~~
|
||||
@param token A token to get info about, or 'nullptr' to run as the current thread.
|
||||
*/
|
||||
inline HRESULT get_token_is_app_container_nothrow(_In_opt_ HANDLE token, bool& value)
|
||||
{
|
||||
DWORD isAppContainer = 0;
|
||||
DWORD returnLength = 0;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::GetTokenInformation(
|
||||
token ? token : GetCurrentThreadEffectiveToken(),
|
||||
TokenIsAppContainer,
|
||||
&isAppContainer,
|
||||
sizeof(isAppContainer),
|
||||
&returnLength));
|
||||
|
||||
value = (isAppContainer != 0);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//! A variant of get_token_is_app_container_nothrow that fails-fast on errors retrieving the token information
|
||||
inline bool get_token_is_app_container_failfast(HANDLE token = nullptr)
|
||||
{
|
||||
bool value = false;
|
||||
FAIL_FAST_IF_FAILED(get_token_is_app_container_nothrow(token, value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! A variant of get_token_is_app_container_nothrow that throws on errors retrieving the token information
|
||||
inline bool get_token_is_app_container(HANDLE token = nullptr)
|
||||
{
|
||||
bool value = false;
|
||||
THROW_IF_FAILED(get_token_is_app_container_nothrow(token, value));
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
template<typename... Ts> bool test_token_membership_failfast(_In_opt_ HANDLE token,
|
||||
const SID_IDENTIFIER_AUTHORITY& sidAuthority, Ts&&... subAuthorities)
|
||||
{
|
||||
bool result;
|
||||
FAIL_FAST_IF_FAILED(test_token_membership_nothrow(&result, token, sidAuthority, wistd::forward<Ts>(subAuthorities)...));
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
template<typename... Ts> bool test_token_membership(_In_opt_ HANDLE token, const SID_IDENTIFIER_AUTHORITY& sidAuthority,
|
||||
Ts&&... subAuthorities)
|
||||
{
|
||||
bool result;
|
||||
THROW_IF_FAILED(test_token_membership_nothrow(&result, token, sidAuthority, wistd::forward<Ts>(subAuthorities)...));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
} //namespace wil
|
||||
|
||||
#endif // __WIL_TOKEN_HELPERS_INCLUDED
|
||||
563
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/win32_helpers.h
vendored
Normal file
563
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/win32_helpers.h
vendored
Normal file
@ -0,0 +1,563 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_WIN32_HELPERS_INCLUDED
|
||||
#define __WIL_WIN32_HELPERS_INCLUDED
|
||||
|
||||
#include <minwindef.h> // FILETIME, HINSTANCE
|
||||
#include <sysinfoapi.h> // GetSystemTimeAsFileTime
|
||||
#include <libloaderapi.h> // GetProcAddress
|
||||
#include <Psapi.h> // GetModuleFileNameExW (macro), K32GetModuleFileNameExW
|
||||
#include <PathCch.h>
|
||||
#include <objbase.h>
|
||||
|
||||
#include "result.h"
|
||||
#include "resource.h"
|
||||
#include "wistd_functional.h"
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
namespace wil
|
||||
{
|
||||
//! Strictly a function of the file system but this is the value for all known file system, NTFS, FAT.
|
||||
//! CDFs has a limit of 254.
|
||||
size_t const max_path_segment_length = 255;
|
||||
|
||||
//! Character length not including the null, MAX_PATH (260) includes the null.
|
||||
size_t const max_path_length = 259;
|
||||
|
||||
//! 32743 Character length not including the null. This is a system defined limit.
|
||||
//! The 24 is for the expansion of the roots from "C:" to "\Device\HarddiskVolume4"
|
||||
//! It will be 25 when there are more than 9 disks.
|
||||
size_t const max_extended_path_length = 0x7FFF - 24;
|
||||
|
||||
//! For {guid} string form. Includes space for the null terminator.
|
||||
size_t const guid_string_buffer_length = 39;
|
||||
|
||||
//! For {guid} string form. Not including the null terminator.
|
||||
size_t const guid_string_length = 38;
|
||||
|
||||
#pragma region FILETIME helpers
|
||||
// FILETIME duration values. FILETIME is in 100 nanosecond units.
|
||||
namespace filetime_duration
|
||||
{
|
||||
long long const one_millisecond = 10000LL;
|
||||
long long const one_second = 10000000LL;
|
||||
long long const one_minute = 10000000LL * 60; // 600000000 or 600000000LL
|
||||
long long const one_hour = 10000000LL * 60 * 60; // 36000000000 or 36000000000LL
|
||||
long long const one_day = 10000000LL * 60 * 60 * 24; // 864000000000 or 864000000000LL
|
||||
};
|
||||
|
||||
namespace filetime
|
||||
{
|
||||
inline unsigned long long to_int64(const FILETIME &ft)
|
||||
{
|
||||
// Cannot reinterpret_cast FILETIME* to unsigned long long*
|
||||
// due to alignment differences.
|
||||
return (static_cast<unsigned long long>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
|
||||
}
|
||||
|
||||
inline FILETIME from_int64(unsigned long long i64)
|
||||
{
|
||||
static_assert(sizeof(i64) == sizeof(FILETIME), "sizes don't match");
|
||||
static_assert(__alignof(unsigned long long) >= __alignof(FILETIME), "alignment not compatible with type pun");
|
||||
return *reinterpret_cast<FILETIME *>(&i64);
|
||||
}
|
||||
|
||||
inline FILETIME add(_In_ FILETIME const &ft, long long delta)
|
||||
{
|
||||
return from_int64(to_int64(ft) + delta);
|
||||
}
|
||||
|
||||
inline bool is_empty(const FILETIME &ft)
|
||||
{
|
||||
return (ft.dwHighDateTime == 0) && (ft.dwLowDateTime == 0);
|
||||
}
|
||||
|
||||
inline FILETIME get_system_time()
|
||||
{
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
return ft;
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
// Use to adapt Win32 APIs that take a fixed size buffer into forms that return
|
||||
// an allocated buffer. Supports many types of string representation.
|
||||
// See comments below on the expected behavior of the callback.
|
||||
// Adjust stackBufferLength based on typical result sizes to optimize use and
|
||||
// to test the boundary cases.
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT AdaptFixedSizeToAllocatedResult(string_type& result, wistd::function<HRESULT(PWSTR, size_t, size_t*)> callback)
|
||||
{
|
||||
details::string_maker<string_type> maker;
|
||||
|
||||
wchar_t value[stackBufferLength];
|
||||
value[0] = L'\0';
|
||||
size_t valueLengthNeededWithNull{}; // callback returns the number of characters needed including the null terminator.
|
||||
RETURN_IF_FAILED_EXPECTED(callback(value, ARRAYSIZE(value), &valueLengthNeededWithNull));
|
||||
WI_ASSERT(valueLengthNeededWithNull > 0);
|
||||
if (valueLengthNeededWithNull <= ARRAYSIZE(value))
|
||||
{
|
||||
// Success case as described above, make() adds the space for the null.
|
||||
RETURN_IF_FAILED(maker.make(value, valueLengthNeededWithNull - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Did not fit in the stack allocated buffer, need to do 2 phase construction.
|
||||
// valueLengthNeededWithNull includes the null so subtract that as make() will add space for it.
|
||||
RETURN_IF_FAILED(maker.make(nullptr, valueLengthNeededWithNull - 1));
|
||||
|
||||
size_t secondLength{};
|
||||
RETURN_IF_FAILED(callback(maker.buffer(), valueLengthNeededWithNull, &secondLength));
|
||||
|
||||
// Ensure callback produces consistent result.
|
||||
FAIL_FAST_IF(valueLengthNeededWithNull != secondLength);
|
||||
}
|
||||
result = maker.release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Expands the '%' quoted environment variables in 'input' using ExpandEnvironmentStringsW(); */
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT ExpandEnvironmentStringsW(_In_ PCWSTR input, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNul = ::ExpandEnvironmentStringsW(input, value, static_cast<DWORD>(valueLength));
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNul == 0);
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
|
||||
/** Searches for a specified file in a specified path using ExpandEnvironmentStringsW(); */
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT SearchPathW(_In_opt_ PCWSTR path, _In_ PCWSTR fileName, _In_opt_ PCWSTR extension, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNul = ::SearchPathW(path, fileName, extension, static_cast<DWORD>(valueLength), value, nullptr);
|
||||
|
||||
if (*valueLengthNeededWithNul == 0)
|
||||
{
|
||||
// ERROR_FILE_NOT_FOUND is an expected return value for SearchPathW
|
||||
const HRESULT searchResult = HRESULT_FROM_WIN32(::GetLastError());
|
||||
RETURN_HR_IF_EXPECTED(searchResult, searchResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
||||
RETURN_IF_FAILED(searchResult);
|
||||
}
|
||||
|
||||
// AdaptFixedSizeToAllocatedResult expects that the length will always include the NUL.
|
||||
// If the result is copied to the buffer, SearchPathW returns the length of copied string, WITHOUT the NUL.
|
||||
// If the buffer is too small to hold the result, SearchPathW returns the length of the required buffer WITH the nul.
|
||||
if (*valueLengthNeededWithNul < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNul)++; // It fit, account for the null.
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
// This function does not work beyond the default stack buffer size (255).
|
||||
// Needs to to retry in a loop similar to wil::GetModuleFileNameExW
|
||||
// These updates and unit tests are tracked by https://github.com/Microsoft/wil/issues/3
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT QueryFullProcessImageNameW(HANDLE processHandle, _In_ DWORD flags, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
|
||||
{
|
||||
DWORD lengthToUse = static_cast<DWORD>(valueLength);
|
||||
BOOL const success = ::QueryFullProcessImageNameW(processHandle, flags, value, &lengthToUse);
|
||||
RETURN_LAST_ERROR_IF((success == FALSE) && (::GetLastError() != ERROR_INSUFFICIENT_BUFFER));
|
||||
// On both success or insufficient buffer case, add +1 for the null-terminating character
|
||||
*valueLengthNeededWithNul = lengthToUse + 1;
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
/** Expands environment strings and checks path existence with SearchPathW */
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT ExpandEnvAndSearchPath(_In_ PCWSTR input, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
wil::unique_cotaskmem_string expandedName;
|
||||
RETURN_IF_FAILED((wil::ExpandEnvironmentStringsW<string_type, stackBufferLength>(input, expandedName)));
|
||||
|
||||
// ERROR_FILE_NOT_FOUND is an expected return value for SearchPathW
|
||||
const HRESULT searchResult = (wil::SearchPathW<string_type, stackBufferLength>(nullptr, expandedName.get(), nullptr, result));
|
||||
RETURN_HR_IF_EXPECTED(searchResult, searchResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
||||
RETURN_IF_FAILED(searchResult);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Looks up the environment variable 'key' and fails if it is not found.
|
||||
'key' should not have '%' prefix and suffix.
|
||||
Dangerous since environment variable generally are optional. */
|
||||
template <typename string_type>
|
||||
inline HRESULT GetEnvironmentVariableW(_In_ PCWSTR key, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
|
||||
{
|
||||
// If the function succeeds, the return value is the number of characters stored in the buffer
|
||||
// pointed to by lpBuffer, not including the terminating null character.
|
||||
//
|
||||
// If lpBuffer is not large enough to hold the data, the return value is the buffer size, in
|
||||
// characters, required to hold the string and its terminating null character and the contents of
|
||||
// lpBuffer are undefined.
|
||||
//
|
||||
// If the function fails, the return value is zero. If the specified environment variable was not
|
||||
// found in the environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND.
|
||||
|
||||
::SetLastError(ERROR_SUCCESS);
|
||||
|
||||
*valueLengthNeededWithNul = ::GetEnvironmentVariableW(key, value, static_cast<DWORD>(valueLength));
|
||||
RETURN_LAST_ERROR_IF_EXPECTED((*valueLengthNeededWithNul == 0) && (::GetLastError() != ERROR_SUCCESS));
|
||||
if (*valueLengthNeededWithNul < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNul)++; // It fit, account for the null.
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
/** Looks up the environment variable 'key' and returns null if it is not found.
|
||||
'key' should not have '%' prefix and suffix. */
|
||||
template <typename string_type>
|
||||
HRESULT TryGetEnvironmentVariableW(_In_ PCWSTR key, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
const auto hr = wil::GetEnvironmentVariableW<string_type>(key, result);
|
||||
RETURN_HR_IF(hr, FAILED(hr) && (hr != HRESULT_FROM_WIN32(ERROR_ENVVAR_NOT_FOUND)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Retrieves the fully qualified path for the file containing the specified module loaded
|
||||
by a given process. Note GetModuleFileNameExW is a macro.*/
|
||||
template <typename string_type, size_t initialBufferLength = 128>
|
||||
HRESULT GetModuleFileNameExW(_In_opt_ HANDLE process, _In_opt_ HMODULE module, string_type& path)
|
||||
{
|
||||
// initialBufferLength is a template parameter to allow for testing. It creates some waste for
|
||||
// shorter paths, but avoids iteration through the loop in common cases where paths are less
|
||||
// than 128 characters.
|
||||
// wil::max_extended_path_length + 1 (for the null char)
|
||||
// + 1 (to be certain GetModuleFileNameExW didn't truncate)
|
||||
size_t const ensureNoTrucation = (process != nullptr) ? 1 : 0;
|
||||
size_t const maxExtendedPathLengthWithNull = wil::max_extended_path_length + 1 + ensureNoTrucation;
|
||||
|
||||
details::string_maker<string_type> maker;
|
||||
|
||||
for (size_t lengthWithNull = initialBufferLength;
|
||||
lengthWithNull <= maxExtendedPathLengthWithNull;
|
||||
lengthWithNull = (wistd::min)(lengthWithNull * 2, maxExtendedPathLengthWithNull))
|
||||
{
|
||||
// make() adds space for the trailing null
|
||||
RETURN_IF_FAILED(maker.make(nullptr, lengthWithNull - 1));
|
||||
|
||||
DWORD copiedCount;
|
||||
bool copyFailed;
|
||||
bool copySucceededWithNoTruncation;
|
||||
|
||||
if (process != nullptr)
|
||||
{
|
||||
// GetModuleFileNameExW truncates and provides no error or other indication it has done so.
|
||||
// The only way to be sure it didn't truncate is if it didn't need the whole buffer.
|
||||
copiedCount = ::GetModuleFileNameExW(process, module, maker.buffer(), static_cast<DWORD>(lengthWithNull));
|
||||
copyFailed = (0 == copiedCount);
|
||||
copySucceededWithNoTruncation = !copyFailed && (copiedCount < lengthWithNull - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In cases of insufficient buffer, GetModuleFileNameW will return a value equal to lengthWithNull
|
||||
// and set the last error to ERROR_INSUFFICIENT_BUFFER.
|
||||
copiedCount = ::GetModuleFileNameW(module, maker.buffer(), static_cast<DWORD>(lengthWithNull));
|
||||
copyFailed = (0 == copiedCount);
|
||||
copySucceededWithNoTruncation = !copyFailed && (copiedCount < lengthWithNull);
|
||||
}
|
||||
|
||||
if (copyFailed)
|
||||
{
|
||||
RETURN_LAST_ERROR();
|
||||
}
|
||||
else if (copySucceededWithNoTruncation)
|
||||
{
|
||||
path = maker.release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
WI_ASSERT((process != nullptr) || (::GetLastError() == ERROR_INSUFFICIENT_BUFFER));
|
||||
|
||||
if (lengthWithNull == maxExtendedPathLengthWithNull)
|
||||
{
|
||||
// If we've reached this point, there's no point in trying a larger buffer size.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Any path should fit into the maximum max_extended_path_length. If we reached here, something went
|
||||
// terribly wrong.
|
||||
FAIL_FAST();
|
||||
}
|
||||
|
||||
/** Retrieves the fully qualified path for the file that contains the specified module.
|
||||
The module must have been loaded by the current process. The path returned will use the
|
||||
same format that was specified when the module was loaded. Therefore, the path can be a
|
||||
long or short file name, and can have the prefix '\\?\'. */
|
||||
template <typename string_type, size_t initialBufferLength = 128>
|
||||
HRESULT GetModuleFileNameW(HMODULE module, string_type& path)
|
||||
{
|
||||
return wil::GetModuleFileNameExW<string_type, initialBufferLength>(nullptr, module, path);
|
||||
}
|
||||
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetSystemDirectoryW(string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNul = ::GetSystemDirectoryW(value, static_cast<DWORD>(valueLength));
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNul == 0);
|
||||
if (*valueLengthNeededWithNul < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNul)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** Expands the '%' quoted environment variables in 'input' using ExpandEnvironmentStringsW(); */
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type ExpandEnvironmentStringsW(_In_ PCWSTR input)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((wil::ExpandEnvironmentStringsW<string_type, stackBufferLength>(input, result)));
|
||||
return result;
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
|
||||
/** Searches for a specified file in a specified path using SearchPathW*/
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type TrySearchPathW(_In_opt_ PCWSTR path, _In_ PCWSTR fileName, PCWSTR _In_opt_ extension)
|
||||
{
|
||||
string_type result;
|
||||
HRESULT searchHR = wil::SearchPathW<string_type, stackBufferLength>(path, fileName, extension, result);
|
||||
THROW_HR_IF(searchHR, FAILED(searchHR) && (searchHR != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Looks up the environment variable 'key' and fails if it is not found.
|
||||
'key' should not have '%' prefix and suffix.
|
||||
Dangerous since environment variable generally are optional. */
|
||||
template <typename string_type = wil::unique_cotaskmem_string>
|
||||
string_type GetEnvironmentVariableW(_In_ PCWSTR key)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED(wil::GetEnvironmentVariableW<string_type>(key, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Looks up the environment variable 'key' and returns null if it is not found.
|
||||
'key' should not have '%' prefix and suffix. */
|
||||
template <typename string_type = wil::unique_cotaskmem_string>
|
||||
string_type TryGetEnvironmentVariableW(_In_ PCWSTR key)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED(wil::TryGetEnvironmentVariableW<string_type>(key, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename string_type = wil::unique_cotaskmem_string>
|
||||
string_type GetModuleFileNameW(HMODULE module)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED(wil::GetModuleFileNameW(module, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename string_type = wil::unique_cotaskmem_string>
|
||||
string_type GetModuleFileNameExW(HANDLE process, HMODULE module)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED(wil::GetModuleFileNameExW(process, module, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Retrieve the HINSTANCE for the current DLL or EXE using this symbol that
|
||||
the linker provides for every module. This avoids the need for a global HINSTANCE variable
|
||||
and provides access to this value for static libraries. */
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
inline HINSTANCE GetModuleInstanceHandle() { return reinterpret_cast<HINSTANCE>(&__ImageBase); }
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
class init_once_completer
|
||||
{
|
||||
INIT_ONCE& m_once;
|
||||
unsigned long m_flags = INIT_ONCE_INIT_FAILED;
|
||||
public:
|
||||
init_once_completer(_In_ INIT_ONCE& once) : m_once(once)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // https://github.com/Microsoft/wil/issues/2
|
||||
void success()
|
||||
{
|
||||
m_flags = 0;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
~init_once_completer()
|
||||
{
|
||||
::InitOnceComplete(&m_once, m_flags, nullptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Performs one-time initialization
|
||||
Simplifies using the Win32 INIT_ONCE structure to perform one-time initialization. The provided `func` is invoked
|
||||
at most once.
|
||||
~~~~
|
||||
INIT_ONCE g_init{};
|
||||
ComPtr<IFoo> g_foo;
|
||||
HRESULT MyMethod()
|
||||
{
|
||||
bool winner = false;
|
||||
RETURN_IF_FAILED(wil::init_once_nothrow(g_init, []
|
||||
{
|
||||
ComPtr<IFoo> foo;
|
||||
RETURN_IF_FAILED(::CoCreateInstance(..., IID_PPV_ARGS(&foo));
|
||||
RETURN_IF_FAILED(foo->Startup());
|
||||
g_foo = foo;
|
||||
}, &winner);
|
||||
if (winner)
|
||||
{
|
||||
RETURN_IF_FAILED(g_foo->Another());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
~~~~
|
||||
See MSDN for more information on `InitOnceExecuteOnce`.
|
||||
@param initOnce The INIT_ONCE structure to use as context for initialization.
|
||||
@param func A function that will be invoked to perform initialization. If this fails, the init call
|
||||
fails and the once-init is not marked as initialized. A later caller could attempt to
|
||||
initialize it a second time.
|
||||
@param callerCompleted Set to 'true' if this was the call that caused initialization, false otherwise.
|
||||
*/
|
||||
template<typename T> HRESULT init_once_nothrow(_Inout_ INIT_ONCE& initOnce, T func, _Out_opt_ bool* callerCompleted = nullptr) WI_NOEXCEPT
|
||||
{
|
||||
BOOL pending = FALSE;
|
||||
wil::assign_to_opt_param(callerCompleted, false);
|
||||
|
||||
__WIL_PRIVATE_RETURN_IF_WIN32_BOOL_FALSE(InitOnceBeginInitialize(&initOnce, 0, &pending, nullptr));
|
||||
|
||||
if (pending)
|
||||
{
|
||||
details::init_once_completer completion(initOnce);
|
||||
__WIL_PRIVATE_RETURN_IF_FAILED(func());
|
||||
completion.success();
|
||||
wil::assign_to_opt_param(callerCompleted, true);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//! Similar to init_once_nothrow, but fails-fast if the initialization step failed. The 'callerComplete' value is
|
||||
//! returned to the caller instead of being an out-parameter.
|
||||
template<typename T> bool init_once_failfast(_Inout_ INIT_ONCE& initOnce, T&& func) WI_NOEXCEPT
|
||||
{
|
||||
bool callerCompleted;
|
||||
|
||||
FAIL_FAST_IF_FAILED(init_once_nothrow(initOnce, wistd::forward<T>(func), &callerCompleted));
|
||||
|
||||
return callerCompleted;
|
||||
};
|
||||
|
||||
//! Returns 'true' if this `init_once` structure has finished initialization, false otherwise.
|
||||
inline bool init_once_initialized(_Inout_ INIT_ONCE& initOnce) WI_NOEXCEPT
|
||||
{
|
||||
BOOL pending = FALSE;
|
||||
return ::InitOnceBeginInitialize(&initOnce, INIT_ONCE_CHECK_ONLY, &pending, nullptr) && !pending;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** Performs one-time initialization
|
||||
Simplifies using the Win32 INIT_ONCE structure to perform one-time initialization. The provided `func` is invoked
|
||||
at most once.
|
||||
~~~~
|
||||
INIT_ONCE g_init{};
|
||||
ComPtr<IFoo> g_foo;
|
||||
void MyMethod()
|
||||
{
|
||||
bool winner = wil::init_once(g_init, []
|
||||
{
|
||||
ComPtr<IFoo> foo;
|
||||
THROW_IF_FAILED(::CoCreateInstance(..., IID_PPV_ARGS(&foo));
|
||||
THROW_IF_FAILED(foo->Startup());
|
||||
g_foo = foo;
|
||||
});
|
||||
if (winner)
|
||||
{
|
||||
THROW_IF_FAILED(g_foo->Another());
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
See MSDN for more information on `InitOnceExecuteOnce`.
|
||||
@param initOnce The INIT_ONCE structure to use as context for initialization.
|
||||
@param func A function that will be invoked to perform initialization. If this fails, the init call
|
||||
fails and the once-init is not marked as initialized. A later caller could attempt to
|
||||
initialize it a second time.
|
||||
@returns 'true' if this was the call that caused initialization, false otherwise.
|
||||
*/
|
||||
template<typename T> bool init_once(_Inout_ INIT_ONCE& initOnce, T func)
|
||||
{
|
||||
BOOL pending = FALSE;
|
||||
|
||||
THROW_IF_WIN32_BOOL_FALSE(::InitOnceBeginInitialize(&initOnce, 0, &pending, nullptr));
|
||||
|
||||
if (pending)
|
||||
{
|
||||
details::init_once_completer completion(initOnce);
|
||||
func();
|
||||
completion.success();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
}
|
||||
|
||||
// Macro for calling GetProcAddress(), with type safety for C++ clients
|
||||
// using the type information from the specified function.
|
||||
// The return value is automatically cast to match the function prototype of the input function.
|
||||
//
|
||||
// Sample usage:
|
||||
//
|
||||
// auto sendMail = GetProcAddressByFunctionDeclaration(hinstMAPI, MAPISendMailW);
|
||||
// if (sendMail)
|
||||
// {
|
||||
// sendMail(0, 0, pmm, MAPI_USE_DEFAULT, 0);
|
||||
// }
|
||||
// Declaration
|
||||
#define GetProcAddressByFunctionDeclaration(hinst, fn) reinterpret_cast<decltype(::fn)*>(GetProcAddress(hinst, #fn))
|
||||
|
||||
#endif // __WIL_WIN32_HELPERS_INCLUDED
|
||||
2232
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/winrt.h
vendored
Normal file
2232
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/winrt.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
548
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_config.h
vendored
Normal file
548
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_config.h
vendored
Normal file
@ -0,0 +1,548 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- __config ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// STL common functionality
|
||||
//
|
||||
// Some aspects of STL are core language concepts that should be used from all C++ code, regardless
|
||||
// of whether exceptions are enabled in the component. Common library code that expects to be used
|
||||
// from exception-free components want these concepts, but including STL headers directly introduces
|
||||
// friction as it requires components not using STL to declare their STL version. Doing so creates
|
||||
// ambiguity around whether STL use is safe in a particular component and implicitly brings in
|
||||
// a long list of headers (including <new>) which can create further ambiguity around throwing new
|
||||
// support (some routines pulled in may expect it). Secondarily, pulling in these headers also has
|
||||
// the potential to create naming conflicts or other implied dependencies.
|
||||
//
|
||||
// To promote the use of these core language concepts outside of STL-based binaries, this file is
|
||||
// selectively pulling those concepts *directly* from corresponding STL headers. The corresponding
|
||||
// "std::" namespace STL functions and types should be preferred over these in code that is bound to
|
||||
// STL. The implementation and naming of all functions are taken directly from STL, instead using
|
||||
// "wistd" (Windows Implementation std) as the namespace.
|
||||
//
|
||||
// Routines in this namespace should always be considered a reflection of the *current* STL implementation
|
||||
// of those routines. Updates from STL should be taken, but no "bugs" should be fixed here.
|
||||
//
|
||||
// New, exception-based code should not use this namespace, but instead should prefer the std:: implementation.
|
||||
// Only code that is not exception-based and libraries that expect to be utilized across both exception
|
||||
// and non-exception based code should utilize this functionality.
|
||||
|
||||
// This header mimics libc++'s '__config' header to the extent necessary to get the wistd::* definitions compiling. Note
|
||||
// that this has a few key differences since libc++'s MSVC compatability is currently not functional and a bit behind
|
||||
|
||||
#ifndef _WISTD_CONFIG_H_
|
||||
#define _WISTD_CONFIG_H_
|
||||
|
||||
// DO NOT add *any* additional includes to this file -- there should be no dependencies from its usage
|
||||
#include <stddef.h> // For size_t and other necessary types
|
||||
|
||||
/// @cond
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# if !defined(__WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# define __WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define __WI_GNUC_VER (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
// The __WI_GNUC_VER_NEW macro better represents the new GCC versioning scheme
|
||||
// introduced in GCC 5.0.
|
||||
# define __WI_GNUC_VER_NEW (__WI_GNUC_VER * 10 + __GNUC_PATCHLEVEL__)
|
||||
#else
|
||||
# define __WI_GNUC_VER 0
|
||||
# define __WI_GNUC_VER_NEW 0
|
||||
#endif
|
||||
|
||||
// _MSVC_LANG is the more accurate way to get the C++ version in MSVC
|
||||
#if defined(_MSVC_LANG) && (_MSVC_LANG > __cplusplus)
|
||||
#define __WI_CPLUSPLUS _MSVC_LANG
|
||||
#else
|
||||
#define __WI_CPLUSPLUS __cplusplus
|
||||
#endif
|
||||
|
||||
#ifndef __WI_LIBCPP_STD_VER
|
||||
# if __WI_CPLUSPLUS <= 201103L
|
||||
# define __WI_LIBCPP_STD_VER 11
|
||||
# elif __WI_CPLUSPLUS <= 201402L
|
||||
# define __WI_LIBCPP_STD_VER 14
|
||||
# elif __WI_CPLUSPLUS <= 201703L
|
||||
# define __WI_LIBCPP_STD_VER 17
|
||||
# else
|
||||
# define __WI_LIBCPP_STD_VER 18 // current year, or date of c++2a ratification
|
||||
# endif
|
||||
#endif // __WI_LIBCPP_STD_VER
|
||||
|
||||
#if __WI_CPLUSPLUS < 201103L
|
||||
#define __WI_LIBCPP_CXX03_LANG
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__)
|
||||
# define __WI_LIBCPP_OBJECT_FORMAT_ELF 1
|
||||
#elif defined(__MACH__)
|
||||
# define __WI_LIBCPP_OBJECT_FORMAT_MACHO 1
|
||||
#elif defined(_WIN32)
|
||||
# define __WI_LIBCPP_OBJECT_FORMAT_COFF 1
|
||||
#elif defined(__wasm__)
|
||||
# define __WI_LIBCPP_OBJECT_FORMAT_WASM 1
|
||||
#else
|
||||
# error Unknown object file format
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# define __WI_LIBCPP_COMPILER_CLANG
|
||||
#elif defined(__GNUC__)
|
||||
# define __WI_LIBCPP_COMPILER_GCC
|
||||
#elif defined(_MSC_VER)
|
||||
# define __WI_LIBCPP_COMPILER_MSVC
|
||||
#elif defined(__IBMCPP__)
|
||||
# define __WI_LIBCPP_COMPILER_IBM
|
||||
#endif
|
||||
|
||||
// NOTE: MSVC, which is what we primarily target, is severly underrepresented in libc++ and checks such as
|
||||
// __has_feature(...) are always false for MSVC, even when the feature being tested _is_ present in MSVC. Therefore, we
|
||||
// instead modify all checks to be __WI_HAS_FEATURE_IS_UNION, etc., which provides the correct value for MSVC and falls
|
||||
// back to the __has_feature(...), etc. value otherwise. We intentionally leave '__has_feature', etc. undefined for MSVC
|
||||
// so that we don't accidentally use the incorrect behavior
|
||||
#ifndef __WI_LIBCPP_COMPILER_MSVC
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(__x) 0
|
||||
#endif
|
||||
|
||||
// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by
|
||||
// the compiler and '1' otherwise.
|
||||
#ifndef __is_identifier
|
||||
#define __is_identifier(__x) 1
|
||||
#endif
|
||||
|
||||
#ifndef __has_cpp_attribute
|
||||
#define __has_cpp_attribute(__x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(__x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(__x) 0
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_alignas)
|
||||
# define __WI_ALIGNAS_TYPE(x) alignas(x)
|
||||
# define __WI_ALIGNAS(x) alignas(x)
|
||||
#else
|
||||
# define __WI_ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x))))
|
||||
# define __WI_ALIGNAS(x) __attribute__((__aligned__(x)))
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) || \
|
||||
(!defined(__WI_LIBCPP_CXX03_LANG) && defined(__GNUC__)) // All supported GCC versions
|
||||
# define __WI_LIBCPP_EXPLICIT explicit
|
||||
#else
|
||||
# define __WI_LIBCPP_EXPLICIT
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_attributes)
|
||||
# define __WI_LIBCPP_NORETURN [[noreturn]]
|
||||
#else
|
||||
# define __WI_LIBCPP_NORETURN __attribute__ ((noreturn))
|
||||
#endif
|
||||
|
||||
#define __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
|
||||
#define __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS
|
||||
|
||||
// The __WI_LIBCPP_NODISCARD_ATTRIBUTE should only be used to define other
|
||||
// NODISCARD macros to the correct attribute.
|
||||
#if __has_cpp_attribute(nodiscard)
|
||||
# define __WI_LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]]
|
||||
#elif defined(__WI_LIBCPP_COMPILER_CLANG) && !defined(__WI_LIBCPP_CXX03_LANG)
|
||||
# define __WI_LIBCPP_NODISCARD_ATTRIBUTE [[clang::warn_unused_result]]
|
||||
#else
|
||||
// We can't use GCC's [[gnu::warn_unused_result]] and
|
||||
// __attribute__((warn_unused_result)), because GCC does not silence them via
|
||||
// (void) cast.
|
||||
# define __WI_LIBCPP_NODISCARD_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
#define __WI_HAS_FEATURE_IS_UNION __has_feature(is_union)
|
||||
#define __WI_HAS_FEATURE_IS_CLASS __has_feature(is_class)
|
||||
#define __WI_HAS_FEATURE_IS_ENUM __has_feature(is_enum)
|
||||
#define __WI_HAS_FEATURE_IS_CONVERTIBLE_TO __has_feature(is_convertible_to)
|
||||
#define __WI_HAS_FEATURE_IS_EMPTY __has_feature(is_empty)
|
||||
#define __WI_HAS_FEATURE_IS_POLYMORPHIC __has_feature(is_polymorphic)
|
||||
#define __WI_HAS_FEATURE_HAS_VIRTUAL_DESTRUCTOR __has_feature(has_virtual_destructor)
|
||||
#define __WI_HAS_FEATURE_REFERENCE_QUALIFIED_FUNCTIONS __has_feature(cxx_reference_qualified_functions)
|
||||
#define __WI_HAS_FEATURE_IS_CONSTRUCTIBLE __has_feature(is_constructible)
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIALLY_CONSTRUCTIBLE __has_feature(is_trivially_constructible)
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIALLY_ASSIGNABLE __has_feature(is_trivially_assignable)
|
||||
#define __WI_HAS_FEATURE_HAS_TRIVIAL_DESTRUCTOR __has_feature(has_trivial_destructor)
|
||||
#define __WI_HAS_FEATURE_NOEXCEPT __has_feature(cxx_noexcept)
|
||||
#define __WI_HAS_FEATURE_IS_POD __has_feature(is_pod)
|
||||
#define __WI_HAS_FEATURE_IS_STANDARD_LAYOUT __has_feature(is_standard_layout)
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIALLY_COPYABLE __has_feature(is_trivially_copyable)
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIAL __has_feature(is_trivial)
|
||||
#define __WI_HAS_FEATURE_HAS_TRIVIAL_CONSTRUCTOR __has_feature(has_trivial_constructor) || (__WI_GNUC_VER >= 403)
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_CONSTRUCTOR __has_feature(has_nothrow_constructor) || (__WI_GNUC_VER >= 403)
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_COPY __has_feature(has_nothrow_copy) || (__WI_GNUC_VER >= 403)
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_ASSIGN __has_feature(has_nothrow_assign) || (__WI_GNUC_VER >= 403)
|
||||
|
||||
#if !(__has_feature(cxx_noexcept))
|
||||
#define __WI_LIBCPP_HAS_NO_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#if !__is_identifier(__has_unique_object_representations) || __WI_GNUC_VER >= 700
|
||||
#define __WI_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(cxx_variadic_templates))
|
||||
#define __WI_LIBCPP_HAS_NO_VARIADICS
|
||||
#endif
|
||||
|
||||
#if __has_feature(is_literal) || __WI_GNUC_VER >= 407
|
||||
#define __WI_LIBCPP_IS_LITERAL(T) __is_literal(T)
|
||||
#endif
|
||||
|
||||
#if __has_feature(underlying_type) || __WI_GNUC_VER >= 407
|
||||
#define __WI_LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T)
|
||||
#endif
|
||||
|
||||
#if __has_feature(is_final) || __WI_GNUC_VER >= 407
|
||||
#define __WI_LIBCPP_HAS_IS_FINAL
|
||||
#endif
|
||||
|
||||
#if __has_feature(is_base_of) || defined(__GNUC__) && __WI_GNUC_VER >= 403
|
||||
#define __WI_LIBCPP_HAS_IS_BASE_OF
|
||||
#endif
|
||||
|
||||
#if __is_identifier(__is_aggregate) && (__WI_GNUC_VER_NEW < 7001)
|
||||
#define __WI_LIBCPP_HAS_NO_IS_AGGREGATE
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(cxx_rtti)) && !defined(__WI_LIBCPP_NO_RTTI)
|
||||
#define __WI_LIBCPP_NO_RTTI
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(cxx_variable_templates))
|
||||
#define __WI_LIBCPP_HAS_NO_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(cxx_relaxed_constexpr))
|
||||
#define __WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700
|
||||
#define __WI_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
|
||||
#endif
|
||||
|
||||
#if __has_attribute(__no_sanitize__) && !defined(__WI_LIBCPP_COMPILER_GCC)
|
||||
# define __WI_LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi")))
|
||||
#else
|
||||
# define __WI_LIBCPP_NO_CFI
|
||||
#endif
|
||||
|
||||
#define __WI_LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__))
|
||||
|
||||
#if __has_attribute(internal_linkage)
|
||||
# define __WI_LIBCPP_INTERNAL_LINKAGE __attribute__ ((internal_linkage))
|
||||
#else
|
||||
# define __WI_LIBCPP_INTERNAL_LINKAGE __WI_LIBCPP_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// NOTE: Much of the following assumes a decently recent version of MSVC. Past versions can be supported, but will need
|
||||
// to be updated to contain the proper _MSC_VER check
|
||||
#define __WI_ALIGNAS_TYPE(x) alignas(x)
|
||||
#define __WI_ALIGNAS(x) alignas(x)
|
||||
#define __alignof__ __alignof
|
||||
|
||||
#define __WI_LIBCPP_EXPLICIT explicit
|
||||
#define __WI_LIBCPP_NORETURN [[noreturn]]
|
||||
#define __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress:26495))
|
||||
#define __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress:26439))
|
||||
|
||||
|
||||
#if __WI_LIBCPP_STD_VER > 14
|
||||
#define __WI_LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]]
|
||||
#else
|
||||
#define __WI_LIBCPP_NODISCARD_ATTRIBUTE _Check_return_
|
||||
#endif
|
||||
|
||||
#define __WI_HAS_FEATURE_IS_UNION 1
|
||||
#define __WI_HAS_FEATURE_IS_CLASS 1
|
||||
#define __WI_HAS_FEATURE_IS_ENUM 1
|
||||
#define __WI_HAS_FEATURE_IS_CONVERTIBLE_TO 1
|
||||
#define __WI_HAS_FEATURE_IS_EMPTY 1
|
||||
#define __WI_HAS_FEATURE_IS_POLYMORPHIC 1
|
||||
#define __WI_HAS_FEATURE_HAS_VIRTUAL_DESTRUCTOR 1
|
||||
#define __WI_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
|
||||
#define __WI_HAS_FEATURE_REFERENCE_QUALIFIED_FUNCTIONS 1
|
||||
#define __WI_HAS_FEATURE_IS_CONSTRUCTIBLE 1
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIALLY_CONSTRUCTIBLE 1
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIALLY_ASSIGNABLE 1
|
||||
#define __WI_HAS_FEATURE_HAS_TRIVIAL_DESTRUCTOR 1
|
||||
#define __WI_HAS_FEATURE_NOEXCEPT 1
|
||||
#define __WI_HAS_FEATURE_IS_POD 1
|
||||
#define __WI_HAS_FEATURE_IS_STANDARD_LAYOUT 1
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIALLY_COPYABLE 1
|
||||
#define __WI_HAS_FEATURE_IS_TRIVIAL 1
|
||||
#define __WI_HAS_FEATURE_HAS_TRIVIAL_CONSTRUCTOR 1
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_CONSTRUCTOR 1
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_COPY 1
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_ASSIGN 1
|
||||
#define __WI_HAS_FEATURE_IS_DESTRUCTIBLE 1
|
||||
|
||||
#if !defined(_CPPRTTI) && !defined(__WI_LIBCPP_NO_RTTI)
|
||||
#define __WI_LIBCPP_NO_RTTI
|
||||
#endif
|
||||
|
||||
#define __WI_LIBCPP_IS_LITERAL(T) __is_literal_type(T)
|
||||
#define __WI_LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T)
|
||||
#define __WI_LIBCPP_HAS_IS_FINAL
|
||||
#define __WI_LIBCPP_HAS_IS_BASE_OF
|
||||
|
||||
#if __WI_LIBCPP_STD_VER < 14
|
||||
#define __WI_LIBCPP_HAS_NO_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
|
||||
#define __WI_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
|
||||
#define __WI_LIBCPP_NO_CFI
|
||||
|
||||
#define __WI_LIBCPP_ALWAYS_INLINE __forceinline
|
||||
#define __WI_LIBCPP_INTERNAL_LINKAGE
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
# if __LITTLE_ENDIAN__
|
||||
# define __WI_LIBCPP_LITTLE_ENDIAN
|
||||
# endif // __LITTLE_ENDIAN__
|
||||
#endif // __LITTLE_ENDIAN__
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
# if __BIG_ENDIAN__
|
||||
# define __WI_LIBCPP_BIG_ENDIAN
|
||||
# endif // __BIG_ENDIAN__
|
||||
#endif // __BIG_ENDIAN__
|
||||
|
||||
#ifdef __BYTE_ORDER__
|
||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define __WI_LIBCPP_LITTLE_ENDIAN
|
||||
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define __WI_LIBCPP_BIG_ENDIAN
|
||||
# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#endif // __BYTE_ORDER__
|
||||
|
||||
#if !defined(__WI_LIBCPP_LITTLE_ENDIAN) && !defined(__WI_LIBCPP_BIG_ENDIAN)
|
||||
# include <endian.h>
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define __WI_LIBCPP_LITTLE_ENDIAN
|
||||
# elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define __WI_LIBCPP_BIG_ENDIAN
|
||||
# else // __BYTE_ORDER == __BIG_ENDIAN
|
||||
# error unable to determine endian
|
||||
# endif
|
||||
#endif // !defined(__WI_LIBCPP_LITTLE_ENDIAN) && !defined(__WI_LIBCPP_BIG_ENDIAN)
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#define __WI_LIBCPP_LITTLE_ENDIAN
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef __WI_LIBCPP_HAS_NO_CONSTEXPR
|
||||
# define __WI_LIBCPP_CONSTEXPR
|
||||
#else
|
||||
# define __WI_LIBCPP_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
#if __WI_LIBCPP_STD_VER > 11 && !defined(__WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
|
||||
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX11 constexpr
|
||||
#else
|
||||
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
#endif
|
||||
|
||||
#if __WI_LIBCPP_STD_VER > 14 && !defined(__WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
|
||||
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX14 constexpr
|
||||
#else
|
||||
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
#endif
|
||||
|
||||
#if __WI_LIBCPP_STD_VER > 17 && !defined(__WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
|
||||
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX17 constexpr
|
||||
#else
|
||||
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
#endif
|
||||
|
||||
#if !defined(__WI_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17) && \
|
||||
(__WI_LIBCPP_STD_VER > 17 || defined(__WI_LIBCPP_ENABLE_NODISCARD))
|
||||
# define __WI_LIBCPP_NODISCARD_AFTER_CXX17 __WI_LIBCPP_NODISCARD_ATTRIBUTE
|
||||
#else
|
||||
# define __WI_LIBCPP_NODISCARD_AFTER_CXX17
|
||||
#endif
|
||||
|
||||
#if __WI_LIBCPP_STD_VER > 14 && defined(__cpp_inline_variables) && (__cpp_inline_variables >= 201606L)
|
||||
# define __WI_LIBCPP_INLINE_VAR inline
|
||||
#else
|
||||
# define __WI_LIBCPP_INLINE_VAR
|
||||
#endif
|
||||
|
||||
#ifdef __WI_LIBCPP_CXX03_LANG
|
||||
#define __WI_LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
#define __WI_LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif
|
||||
|
||||
#ifndef __SIZEOF_INT128__
|
||||
#define __WI_LIBCPP_HAS_NO_INT128
|
||||
#endif
|
||||
|
||||
#if !__WI_HAS_FEATURE_NOEXCEPT && !defined(__WI_LIBCPP_HAS_NO_NOEXCEPT)
|
||||
#define __WI_LIBCPP_HAS_NO_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#ifndef __WI_LIBCPP_HAS_NO_NOEXCEPT
|
||||
# define WI_NOEXCEPT noexcept
|
||||
# define __WI_NOEXCEPT_(x) noexcept(x)
|
||||
#else
|
||||
# define WI_NOEXCEPT throw()
|
||||
# define __WI_NOEXCEPT_(x)
|
||||
#endif
|
||||
|
||||
#if defined(__WI_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
#define __WI_LIBCPP_HIDDEN
|
||||
#define __WI_LIBCPP_TEMPLATE_VIS
|
||||
#endif // defined(__WI_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
|
||||
#ifndef __WI_LIBCPP_HIDDEN
|
||||
# if !defined(__WI_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
# define __WI_LIBCPP_HIDDEN __attribute__ ((__visibility__("hidden")))
|
||||
# else
|
||||
# define __WI_LIBCPP_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __WI_LIBCPP_TEMPLATE_VIS
|
||||
# if !defined(__WI_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && !defined(__WI_LIBCPP_COMPILER_MSVC)
|
||||
# if __has_attribute(__type_visibility__)
|
||||
# define __WI_LIBCPP_TEMPLATE_VIS __attribute__ ((__type_visibility__("default")))
|
||||
# else
|
||||
# define __WI_LIBCPP_TEMPLATE_VIS __attribute__ ((__visibility__("default")))
|
||||
# endif
|
||||
# else
|
||||
# define __WI_LIBCPP_TEMPLATE_VIS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_HIDDEN __WI_LIBCPP_INTERNAL_LINKAGE
|
||||
|
||||
namespace wistd // ("Windows Implementation" std)
|
||||
{
|
||||
typedef decltype(__nullptr) nullptr_t;
|
||||
|
||||
template <class _T1, class _T2 = _T1>
|
||||
struct __less
|
||||
{
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
|
||||
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;}
|
||||
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;}
|
||||
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;}
|
||||
};
|
||||
|
||||
template <class _T1>
|
||||
struct __less<_T1, _T1>
|
||||
{
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
|
||||
};
|
||||
|
||||
template <class _T1>
|
||||
struct __less<const _T1, _T1>
|
||||
{
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
|
||||
};
|
||||
|
||||
template <class _T1>
|
||||
struct __less<_T1, const _T1>
|
||||
{
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
|
||||
};
|
||||
|
||||
// These are added to wistd to enable use of min/max without having to use the windows.h min/max
|
||||
// macros that some clients might not have access to. Note: the STL versions of these have debug
|
||||
// checking for the less than operator and support for iterators that these implementations lack.
|
||||
// Use the STL versions when you require use of those features.
|
||||
|
||||
// min
|
||||
|
||||
template <class _Tp, class _Compare>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const _Tp&
|
||||
(min)(const _Tp& __a, const _Tp& __b, _Compare __comp)
|
||||
{
|
||||
return __comp(__b, __a) ? __b : __a;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const _Tp&
|
||||
(min)(const _Tp& __a, const _Tp& __b)
|
||||
{
|
||||
return (min)(__a, __b, __less<_Tp>());
|
||||
}
|
||||
|
||||
// max
|
||||
|
||||
template <class _Tp, class _Compare>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const _Tp&
|
||||
(max)(const _Tp& __a, const _Tp& __b, _Compare __comp)
|
||||
{
|
||||
return __comp(__a, __b) ? __b : __a;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const _Tp&
|
||||
(max)(const _Tp& __a, const _Tp& __b)
|
||||
{
|
||||
return (max)(__a, __b, __less<_Tp>());
|
||||
}
|
||||
|
||||
template <class _Arg, class _Result>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS unary_function
|
||||
{
|
||||
typedef _Arg argument_type;
|
||||
typedef _Result result_type;
|
||||
};
|
||||
|
||||
template <class _Arg1, class _Arg2, class _Result>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS binary_function
|
||||
{
|
||||
typedef _Arg1 first_argument_type;
|
||||
typedef _Arg2 second_argument_type;
|
||||
typedef _Result result_type;
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
#endif _WISTD_CONFIG_H_
|
||||
544
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_functional.h
vendored
Normal file
544
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_functional.h
vendored
Normal file
@ -0,0 +1,544 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------ functional ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// STL common functionality
|
||||
//
|
||||
// Some aspects of STL are core language concepts that should be used from all C++ code, regardless
|
||||
// of whether exceptions are enabled in the component. Common library code that expects to be used
|
||||
// from exception-free components want these concepts, but including STL headers directly introduces
|
||||
// friction as it requires components not using STL to declare their STL version. Doing so creates
|
||||
// ambiguity around whether STL use is safe in a particular component and implicitly brings in
|
||||
// a long list of headers (including <new>) which can create further ambiguity around throwing new
|
||||
// support (some routines pulled in may expect it). Secondarily, pulling in these headers also has
|
||||
// the potential to create naming conflicts or other implied dependencies.
|
||||
//
|
||||
// To promote the use of these core language concepts outside of STL-based binaries, this file is
|
||||
// selectively pulling those concepts *directly* from corresponding STL headers. The corresponding
|
||||
// "std::" namespace STL functions and types should be preferred over these in code that is bound to
|
||||
// STL. The implementation and naming of all functions are taken directly from STL, instead using
|
||||
// "wistd" (Windows Implementation std) as the namespace.
|
||||
//
|
||||
// Routines in this namespace should always be considered a reflection of the *current* STL implementation
|
||||
// of those routines. Updates from STL should be taken, but no "bugs" should be fixed here.
|
||||
//
|
||||
// New, exception-based code should not use this namespace, but instead should prefer the std:: implementation.
|
||||
// Only code that is not exception-based and libraries that expect to be utilized across both exception
|
||||
// and non-exception based code should utilize this functionality.
|
||||
|
||||
#ifndef _WISTD_FUNCTIONAL_H_
|
||||
#define _WISTD_FUNCTIONAL_H_
|
||||
|
||||
// DO NOT add *any* additional includes to this file -- there should be no dependencies from its usage
|
||||
#include "wistd_memory.h"
|
||||
#include <intrin.h> // For __fastfail
|
||||
#include <new.h> // For placement new
|
||||
|
||||
#if !defined(__WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4324)
|
||||
#pragma warning(disable: 4800)
|
||||
|
||||
/// @cond
|
||||
namespace wistd // ("Windows Implementation" std)
|
||||
{
|
||||
// wistd::function
|
||||
//
|
||||
// All of the code below is in direct support of wistd::function. This class is identical to std::function
|
||||
// with the following exceptions:
|
||||
//
|
||||
// 1) It never allocates and is safe to use from exception-free code (custom allocators are not supported)
|
||||
// 2) It's slightly bigger on the stack (64 bytes, rather than 24 for 32bit)
|
||||
// 3) There is an explicit static-assert if a lambda becomes too large to hold in the internal buffer (rather than an allocation)
|
||||
|
||||
template <class _Ret>
|
||||
struct __invoke_void_return_wrapper
|
||||
{
|
||||
#ifndef __WI_LIBCPP_CXX03_LANG
|
||||
template <class ..._Args>
|
||||
static _Ret __call(_Args&&... __args) {
|
||||
return __invoke(wistd::forward<_Args>(__args)...);
|
||||
}
|
||||
#else
|
||||
template <class _Fn>
|
||||
static _Ret __call(_Fn __f) {
|
||||
return __invoke(__f);
|
||||
}
|
||||
|
||||
template <class _Fn, class _A0>
|
||||
static _Ret __call(_Fn __f, _A0& __a0) {
|
||||
return __invoke(__f, __a0);
|
||||
}
|
||||
|
||||
template <class _Fn, class _A0, class _A1>
|
||||
static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) {
|
||||
return __invoke(__f, __a0, __a1);
|
||||
}
|
||||
|
||||
template <class _Fn, class _A0, class _A1, class _A2>
|
||||
static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){
|
||||
return __invoke(__f, __a0, __a1, __a2);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __invoke_void_return_wrapper<void>
|
||||
{
|
||||
#ifndef __WI_LIBCPP_CXX03_LANG
|
||||
template <class ..._Args>
|
||||
static void __call(_Args&&... __args) {
|
||||
(void)__invoke(wistd::forward<_Args>(__args)...);
|
||||
}
|
||||
#else
|
||||
template <class _Fn>
|
||||
static void __call(_Fn __f) {
|
||||
__invoke(__f);
|
||||
}
|
||||
|
||||
template <class _Fn, class _A0>
|
||||
static void __call(_Fn __f, _A0& __a0) {
|
||||
__invoke(__f, __a0);
|
||||
}
|
||||
|
||||
template <class _Fn, class _A0, class _A1>
|
||||
static void __call(_Fn __f, _A0& __a0, _A1& __a1) {
|
||||
__invoke(__f, __a0, __a1);
|
||||
}
|
||||
|
||||
template <class _Fn, class _A0, class _A1, class _A2>
|
||||
static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) {
|
||||
__invoke(__f, __a0, __a1, __a2);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FUNCTION
|
||||
//==============================================================================
|
||||
|
||||
// bad_function_call
|
||||
|
||||
__WI_LIBCPP_NORETURN inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
void __throw_bad_function_call()
|
||||
{
|
||||
__fastfail(7); // FAST_FAIL_FATAL_APP_EXIT
|
||||
}
|
||||
|
||||
template<class _Fp> class __WI_LIBCPP_TEMPLATE_VIS function; // undefined
|
||||
|
||||
namespace __function
|
||||
{
|
||||
|
||||
template<class _Rp>
|
||||
struct __maybe_derive_from_unary_function
|
||||
{
|
||||
};
|
||||
|
||||
template<class _Rp, class _A1>
|
||||
struct __maybe_derive_from_unary_function<_Rp(_A1)>
|
||||
: public unary_function<_A1, _Rp>
|
||||
{
|
||||
};
|
||||
|
||||
template<class _Rp>
|
||||
struct __maybe_derive_from_binary_function
|
||||
{
|
||||
};
|
||||
|
||||
template<class _Rp, class _A1, class _A2>
|
||||
struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)>
|
||||
: public binary_function<_A1, _A2, _Rp>
|
||||
{
|
||||
};
|
||||
|
||||
template <class _Fp>
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool __not_null(_Fp const&) { return true; }
|
||||
|
||||
template <class _Fp>
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool __not_null(_Fp* __ptr) { return __ptr; }
|
||||
|
||||
template <class _Ret, class _Class>
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool __not_null(_Ret _Class::*__ptr) { return __ptr; }
|
||||
|
||||
template <class _Fp>
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool __not_null(function<_Fp> const& __f) { return !!__f; }
|
||||
|
||||
} // namespace __function
|
||||
|
||||
#ifndef __WI_LIBCPP_CXX03_LANG
|
||||
|
||||
namespace __function {
|
||||
|
||||
template<class _Fp> class __base;
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class __base<_Rp(_ArgTypes...)>
|
||||
{
|
||||
__base(const __base&);
|
||||
__base& operator=(const __base&);
|
||||
public:
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __base() {}
|
||||
__WI_LIBCPP_INLINE_VISIBILITY virtual ~__base() {}
|
||||
virtual void __clone(__base*) const = 0;
|
||||
virtual void __move(__base*) = 0;
|
||||
virtual void destroy() WI_NOEXCEPT = 0;
|
||||
virtual _Rp operator()(_ArgTypes&& ...) = 0;
|
||||
};
|
||||
|
||||
template<class _FD, class _FB> class __func;
|
||||
|
||||
template<class _Fp, class _Rp, class ..._ArgTypes>
|
||||
class __func<_Fp, _Rp(_ArgTypes...)>
|
||||
: public __base<_Rp(_ArgTypes...)>
|
||||
{
|
||||
_Fp __f_;
|
||||
public:
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
explicit __func(_Fp&& __f)
|
||||
: __f_(wistd::move(__f)) {}
|
||||
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
explicit __func(const _Fp& __f)
|
||||
: __f_(__f) {}
|
||||
|
||||
virtual void __clone(__base<_Rp(_ArgTypes...)>*) const;
|
||||
virtual void __move(__base<_Rp(_ArgTypes...)>*);
|
||||
virtual void destroy() WI_NOEXCEPT;
|
||||
virtual _Rp operator()(_ArgTypes&& ... __arg);
|
||||
};
|
||||
|
||||
template<class _Fp, class _Rp, class ..._ArgTypes>
|
||||
void
|
||||
__func<_Fp, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const
|
||||
{
|
||||
::new (__p) __func(__f_);
|
||||
}
|
||||
|
||||
template<class _Fp, class _Rp, class ..._ArgTypes>
|
||||
void
|
||||
__func<_Fp, _Rp(_ArgTypes...)>::__move(__base<_Rp(_ArgTypes...)>* __p)
|
||||
{
|
||||
::new (__p) __func(wistd::move(__f_));
|
||||
}
|
||||
|
||||
template<class _Fp, class _Rp, class ..._ArgTypes>
|
||||
void
|
||||
__func<_Fp, _Rp(_ArgTypes...)>::destroy() WI_NOEXCEPT
|
||||
{
|
||||
__f_.~_Fp();
|
||||
}
|
||||
|
||||
template<class _Fp, class _Rp, class ..._ArgTypes>
|
||||
_Rp
|
||||
__func<_Fp, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg)
|
||||
{
|
||||
typedef __invoke_void_return_wrapper<_Rp> _Invoker;
|
||||
return _Invoker::__call(__f_, wistd::forward<_ArgTypes>(__arg)...);
|
||||
}
|
||||
|
||||
} // __function
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class __WI_LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
|
||||
: public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
|
||||
public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
|
||||
{
|
||||
// 'wistd::function' is most similar to 'inplace_function' in that it _only_ permits holding function objects
|
||||
// that can fit within its internal buffer. Therefore, we expand this size to accommodate space for at least 12
|
||||
// pointers (__base vtable takes an additional one).
|
||||
static constexpr size_t __buffer_size = 13 * sizeof(void*);
|
||||
|
||||
typedef __function::__base<_Rp(_ArgTypes...)> __base;
|
||||
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
|
||||
typename aligned_storage<__buffer_size>::type __buf_;
|
||||
__base* __f_;
|
||||
|
||||
__WI_LIBCPP_NO_CFI static __base *__as_base(void *p) {
|
||||
return reinterpret_cast<__base*>(p);
|
||||
}
|
||||
|
||||
template <class _Fp, bool>
|
||||
struct __callable_imp
|
||||
{
|
||||
static const bool value = is_same<void, _Rp>::value ||
|
||||
is_convertible<typename __invoke_of<_Fp&, _ArgTypes...>::type,
|
||||
_Rp>::value;
|
||||
};
|
||||
|
||||
template <class _Fp>
|
||||
struct __callable_imp<_Fp, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class _Fp>
|
||||
struct __callable
|
||||
{
|
||||
static const bool value = __callable_imp<_Fp, __lazy_and<
|
||||
integral_constant<bool, !is_same<__uncvref_t<_Fp>, function>::value>,
|
||||
__invokable<_Fp&, _ArgTypes...>
|
||||
>::value>::value;
|
||||
};
|
||||
|
||||
template <class _Fp>
|
||||
using _EnableIfCallable = typename enable_if<__callable<_Fp>::value>::type;
|
||||
public:
|
||||
typedef _Rp result_type;
|
||||
|
||||
// construct/copy/destroy:
|
||||
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
|
||||
function() WI_NOEXCEPT : __f_(0) {}
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
function(nullptr_t) WI_NOEXCEPT : __f_(0) {}
|
||||
function(const function&);
|
||||
function(function&&);
|
||||
template<class _Fp, class = _EnableIfCallable<_Fp>>
|
||||
function(_Fp);
|
||||
|
||||
function& operator=(const function&);
|
||||
function& operator=(function&&);
|
||||
function& operator=(nullptr_t) WI_NOEXCEPT;
|
||||
template<class _Fp, class = _EnableIfCallable<_Fp>>
|
||||
function& operator=(_Fp&&);
|
||||
|
||||
~function();
|
||||
|
||||
// function modifiers:
|
||||
void swap(function&);
|
||||
|
||||
// function capacity:
|
||||
__WI_LIBCPP_INLINE_VISIBILITY
|
||||
__WI_LIBCPP_EXPLICIT operator bool() const WI_NOEXCEPT {return __f_;}
|
||||
|
||||
// deleted overloads close possible hole in the type system
|
||||
template<class _R2, class... _ArgTypes2>
|
||||
bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete;
|
||||
template<class _R2, class... _ArgTypes2>
|
||||
bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete;
|
||||
public:
|
||||
// function invocation:
|
||||
_Rp operator()(_ArgTypes...) const;
|
||||
|
||||
// NOTE: type_info is very compiler specific, and on top of that, we're operating in a namespace other than
|
||||
// 'std' so all functions requiring RTTI have been removed
|
||||
};
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
|
||||
function<_Rp(_ArgTypes...)>::function(const function& __f)
|
||||
{
|
||||
if (__f.__f_ == 0)
|
||||
__f_ = 0;
|
||||
else
|
||||
{
|
||||
__f_ = __as_base(&__buf_);
|
||||
__f.__f_->__clone(__f_);
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS
|
||||
function<_Rp(_ArgTypes...)>::function(function&& __f)
|
||||
{
|
||||
if (__f.__f_ == 0)
|
||||
__f_ = 0;
|
||||
else
|
||||
{
|
||||
__f_ = __as_base(&__buf_);
|
||||
__f.__f_->__move(__f_);
|
||||
__f.__f_->destroy();
|
||||
__f.__f_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
template <class _Fp, class>
|
||||
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
|
||||
function<_Rp(_ArgTypes...)>::function(_Fp __f)
|
||||
: __f_(0)
|
||||
{
|
||||
if (__function::__not_null(__f))
|
||||
{
|
||||
typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _FF;
|
||||
static_assert(sizeof(_FF) <= sizeof(__buf_),
|
||||
"The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture.");
|
||||
__f_ = ::new((void*)&__buf_) _FF(wistd::move(__f));
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
function<_Rp(_ArgTypes...)>&
|
||||
function<_Rp(_ArgTypes...)>::operator=(const function& __f)
|
||||
{
|
||||
*this = nullptr;
|
||||
if (__f.__f_)
|
||||
{
|
||||
__f_ = __as_base(&__buf_);
|
||||
__f.__f_->__clone(__f_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
function<_Rp(_ArgTypes...)>&
|
||||
function<_Rp(_ArgTypes...)>::operator=(function&& __f)
|
||||
{
|
||||
*this = nullptr;
|
||||
if (__f.__f_)
|
||||
{
|
||||
__f_ = __as_base(&__buf_);
|
||||
__f.__f_->__move(__f_);
|
||||
__f.__f_->destroy();
|
||||
__f.__f_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
function<_Rp(_ArgTypes...)>&
|
||||
function<_Rp(_ArgTypes...)>::operator=(nullptr_t) WI_NOEXCEPT
|
||||
{
|
||||
__base* __t = __f_;
|
||||
__f_ = 0;
|
||||
if (__t)
|
||||
__t->destroy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
template <class _Fp, class>
|
||||
function<_Rp(_ArgTypes...)>&
|
||||
function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
|
||||
{
|
||||
*this = nullptr;
|
||||
if (__function::__not_null(__f))
|
||||
{
|
||||
typedef __function::__func<typename decay<_Fp>::type, _Rp(_ArgTypes...)> _FF;
|
||||
static_assert(sizeof(_FF) <= sizeof(__buf_),
|
||||
"The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture.");
|
||||
__f_ = ::new((void*)&__buf_) _FF(wistd::move(__f));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
function<_Rp(_ArgTypes...)>::~function()
|
||||
{
|
||||
if (__f_)
|
||||
__f_->destroy();
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
void
|
||||
function<_Rp(_ArgTypes...)>::swap(function& __f)
|
||||
{
|
||||
if (wistd::addressof(__f) == this)
|
||||
return;
|
||||
if (__f_ && __f.__f_)
|
||||
{
|
||||
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
|
||||
__base* __t = __as_base(&__tempbuf);
|
||||
__f_->__move(__t);
|
||||
__f_->destroy();
|
||||
__f_ = 0;
|
||||
__f.__f_->__move(__as_base(&__buf_));
|
||||
__f.__f_->destroy();
|
||||
__f.__f_ = 0;
|
||||
__f_ = __as_base(&__buf_);
|
||||
__t->__move(__as_base(&__f.__buf_));
|
||||
__t->destroy();
|
||||
__f.__f_ = __as_base(&__f.__buf_);
|
||||
}
|
||||
else if (__f_)
|
||||
{
|
||||
__f_->__move(__as_base(&__f.__buf_));
|
||||
__f_->destroy();
|
||||
__f_ = 0;
|
||||
__f.__f_ = __as_base(&__f.__buf_);
|
||||
}
|
||||
else if (__f.__f_)
|
||||
{
|
||||
__f.__f_->__move(__as_base(&__buf_));
|
||||
__f.__f_->destroy();
|
||||
__f.__f_ = 0;
|
||||
__f_ = __as_base(&__buf_);
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
_Rp
|
||||
function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const
|
||||
{
|
||||
if (__f_ == 0)
|
||||
__throw_bad_function_call();
|
||||
return (*__f_)(wistd::forward<_ArgTypes>(__arg)...);
|
||||
}
|
||||
|
||||
template <class _Rp, class... _ArgTypes>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return !__f;}
|
||||
|
||||
template <class _Rp, class... _ArgTypes>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return !__f;}
|
||||
|
||||
template <class _Rp, class... _ArgTypes>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return (bool)__f;}
|
||||
|
||||
template <class _Rp, class... _ArgTypes>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return (bool)__f;}
|
||||
|
||||
// Provide both 'swap_wil' and 'swap' since we now have two ADL scenarios that we need to work
|
||||
template <class _Rp, class... _ArgTypes>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y)
|
||||
{return __x.swap(__y);}
|
||||
|
||||
template <class _Rp, class... _ArgTypes>
|
||||
inline __WI_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
swap_wil(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y)
|
||||
{return __x.swap(__y);}
|
||||
|
||||
// std::invoke
|
||||
template <class _Fn, class ..._Args>
|
||||
typename __invoke_of<_Fn, _Args...>::type
|
||||
invoke(_Fn&& __f, _Args&&... __args)
|
||||
__WI_NOEXCEPT_((__nothrow_invokable<_Fn, _Args...>::value))
|
||||
{
|
||||
return wistd::__invoke(wistd::forward<_Fn>(__f), wistd::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
#else // __WI_LIBCPP_CXX03_LANG
|
||||
|
||||
#error wistd::function and wistd::invoke not implemented for pre-C++11
|
||||
|
||||
#endif
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // _WISTD_FUNCTIONAL_H_
|
||||
1038
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_memory.h
vendored
Normal file
1038
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_memory.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4504
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_type_traits.h
vendored
Normal file
4504
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wistd_type_traits.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
84
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wrl.h
vendored
Normal file
84
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/wrl.h
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_WRL_INCLUDED
|
||||
#define __WIL_WRL_INCLUDED
|
||||
|
||||
#include <wrl.h>
|
||||
#include "result.h"
|
||||
#include "common.h" // wistd type_traits helpers
|
||||
|
||||
namespace wil
|
||||
{
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
#pragma region Object construction helpers that throw exceptions
|
||||
|
||||
/** Used to construct a RuntimeClass based object that uses 2 phase construction.
|
||||
Construct a RuntimeClass based object that uses 2 phase construction (by implementing
|
||||
RuntimeClassInitialize() and returning error codes for failures.
|
||||
~~~~
|
||||
// SomeClass uses 2 phase initialization by implementing RuntimeClassInitialize()
|
||||
auto someClass = MakeAndInitializeOrThrow<SomeClass>(L"input", true);
|
||||
~~~~ */
|
||||
|
||||
template <typename T, typename... TArgs>
|
||||
Microsoft::WRL::ComPtr<T> MakeAndInitializeOrThrow(TArgs&&... args)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<T> obj;
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<T>(&obj, Microsoft::WRL::Details::Forward<TArgs>(args)...));
|
||||
return obj;
|
||||
}
|
||||
|
||||
/** Used to construct an RuntimeClass based object that uses exceptions in its constructor (and does
|
||||
not require 2 phase construction).
|
||||
~~~~
|
||||
// SomeClass uses exceptions for error handling in its constructor.
|
||||
auto someClass = MakeOrThrow<SomeClass>(L"input", true);
|
||||
~~~~ */
|
||||
|
||||
template <typename T, typename... TArgs>
|
||||
Microsoft::WRL::ComPtr<T> MakeOrThrow(TArgs&&... args)
|
||||
{
|
||||
// This is how you can detect the presence of RuntimeClassInitialize() and find dangerous use.
|
||||
// Unfortunately this produces false positives as all RuntimeClass derived classes have
|
||||
// a RuntimeClassInitialize() method from their base class.
|
||||
// static_assert(!std::is_member_function_pointer<decltype(&T::RuntimeClassInitialize)>::value,
|
||||
// "class has a RuntimeClassInitialize member, use MakeAndInitializeOrThrow instead");
|
||||
auto obj = Microsoft::WRL::Make<T>(Microsoft::WRL::Details::Forward<TArgs>(args)...);
|
||||
THROW_IF_NULL_ALLOC(obj.Get());
|
||||
return obj;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
/** By default WRL Callback objects are not agile, use this to make an agile one. Replace use of Callback<> with MakeAgileCallback<>.
|
||||
Will return null on failure, translate that into E_OUTOFMEMORY using XXX_IF_NULL_ALLOC()
|
||||
from wil\result.h to test the result. */
|
||||
template<typename TDelegateInterface, typename ...Args>
|
||||
::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallbackNoThrow(Args&&... args) WI_NOEXCEPT
|
||||
{
|
||||
using namespace Microsoft::WRL;
|
||||
return Callback<Implements<RuntimeClassFlags<ClassicCom>, TDelegateInterface, FtmBase>>(wistd::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
template<typename TDelegateInterface, typename ...Args>
|
||||
::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallback(Args&&... args)
|
||||
{
|
||||
auto result = MakeAgileCallbackNoThrow<TDelegateInterface, Args...>(wistd::forward<Args>(args)...);
|
||||
THROW_IF_NULL_ALLOC(result);
|
||||
return result;
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
} // namespace wil
|
||||
|
||||
#endif // __WIL_WRL_INCLUDED
|
||||
BIN
packages/cpprestsdk.v141.2.10.12.1/.signature.p7s
vendored
Normal file
BIN
packages/cpprestsdk.v141.2.10.12.1/.signature.p7s
vendored
Normal file
Binary file not shown.
47
packages/cpprestsdk.v141.2.10.12.1/build/native/cpprestsdk.v141.targets
vendored
Normal file
47
packages/cpprestsdk.v141.2.10.12.1/build/native/cpprestsdk.v141.targets
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<PropertyGroup Condition="'$(Force-Enable-cpprestsdk)' == '' And ('$(PlatformToolset)' != 'v141' And '$(PlatformToolset)' != 'v142')">
|
||||
<Disable-cpprestsdk>true</Disable-cpprestsdk>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Force-Disable-cpprestsdk)' != ''">
|
||||
<Disable-cpprestsdk>true</Disable-cpprestsdk>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Disable-cpprestsdk)' == ''">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<!--
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
-->
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Disable-cpprestsdk)' == ''">
|
||||
<Link>
|
||||
<AdditionalDependencies Condition="'$(Configuration)' == 'Debug' And ('$(Platform)' == 'Win32' Or '$(Platform)' == 'x86')">$(MSBuildThisFileDirectory)x86\lib\cpprest141_2_10d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)' == 'Release' And ('$(Platform)' == 'Win32' Or '$(Platform)' == 'x86')">$(MSBuildThisFileDirectory)x86\lib\cpprest141_2_10.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
||||
<AdditionalDependencies Condition="'$(Configuration)' == 'Debug' And '$(Platform)' == 'x64'">$(MSBuildThisFileDirectory)x64\lib\cpprest141_2_10d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)' == 'Release' And '$(Platform)' == 'x64'">$(MSBuildThisFileDirectory)x64\lib\cpprest141_2_10.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Debug' And ('$(Platform)' == 'Win32' Or '$(Platform)' == 'x86') And '$(Disable-cpprestsdk)' == '' ">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)x86\bin\cpprest141_2_10d.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release' And ('$(Platform)' == 'Win32' Or '$(Platform)' == 'x86') And '$(Disable-cpprestsdk)' == '' ">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)x86\bin\cpprest141_2_10.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Debug' And '$(Platform)' == 'x64' And '$(Disable-cpprestsdk)' == '' ">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)x64\bin\cpprest141_2_10d.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release' And '$(Platform)' == 'x64' And '$(Disable-cpprestsdk)' == '' ">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)x64\bin\cpprest141_2_10.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
1180
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/astreambuf.h
vendored
Normal file
1180
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/astreambuf.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
697
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/asyncrt_utils.h
vendored
Normal file
697
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/asyncrt_utils.h
vendored
Normal file
@ -0,0 +1,697 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Various common utilities.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269
|
||||
/* Systems using glibc: xlocale.h has been removed from glibc 2.26
|
||||
The above include of locale.h is sufficient
|
||||
Further details: https://sourceware.org/git/?p=glibc.git;a=commit;h=f0be25b6336db7492e47d2e8e72eb8af53b5506d */
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Various utilities for string conversions and date and time manipulation.
|
||||
namespace utility
|
||||
{
|
||||
// Left over from VS2010 support, remains to avoid breaking.
|
||||
typedef std::chrono::seconds seconds;
|
||||
|
||||
/// Functions for converting to/from std::chrono::seconds to xml string.
|
||||
namespace timespan
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a timespan/interval in seconds to xml duration string as specified by
|
||||
/// http://www.w3.org/TR/xmlschema-2/#duration
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl seconds_to_xml_duration(utility::seconds numSecs);
|
||||
|
||||
/// <summary>
|
||||
/// Converts an xml duration to timespan/interval in seconds
|
||||
/// http://www.w3.org/TR/xmlschema-2/#duration
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::seconds __cdecl xml_duration_to_seconds(const utility::string_t& timespanString);
|
||||
} // namespace timespan
|
||||
|
||||
/// Functions for Unicode string conversions.
|
||||
namespace conversions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a UTF-16 string to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="w">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl utf16_to_utf8(const utf16string& w);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a UTF-8 string to a UTF-16
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl utf8_to_utf16(const std::string& s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a ASCII (us-ascii) string to a UTF-16 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character us-ascii string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl usascii_to_utf16(const std::string& s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Latin1 (iso-8859-1) string to a UTF-16 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl latin1_to_utf16(const std::string& s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Latin1 (iso-8859-1) string to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP utf8string __cdecl latin1_to_utf8(const std::string& s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
#ifdef _UTF16_STRINGS
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string&& s);
|
||||
#else
|
||||
inline utility::string_t&& to_string_t(std::string&& s) { return std::move(s); }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
#ifdef _UTF16_STRINGS
|
||||
inline utility::string_t&& to_string_t(utf16string&& s) { return std::move(s); }
|
||||
#else
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(utf16string&& s);
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
#ifdef _UTF16_STRINGS
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const std::string& s);
|
||||
#else
|
||||
inline const utility::string_t& to_string_t(const std::string& s) { return s; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
#ifdef _UTF16_STRINGS
|
||||
inline const utility::string_t& to_string_t(const utf16string& s) { return s; }
|
||||
#else
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const utf16string& s);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string& value);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
inline const utf16string& to_utf16string(const utf16string& value) { return value; }
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
inline utf16string&& to_utf16string(utf16string&& value) { return std::move(value); }
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
inline std::string&& to_utf8string(std::string&& value) { return std::move(value); }
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
inline const std::string& to_utf8string(const std::string& value) { return value; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl to_utf8string(const utf16string& value);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the given byte array into a base64 string
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_base64(const std::vector<unsigned char>& data);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the given 8-byte integer into a base64 string
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_base64(uint64_t data);
|
||||
|
||||
/// <summary>
|
||||
/// Decode the given base64 string to a byte array
|
||||
/// </summary>
|
||||
_ASYNCRTIMP std::vector<unsigned char> __cdecl from_base64(const utility::string_t& str);
|
||||
|
||||
template<typename Source>
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
utility::string_t print_string(const Source& val, const std::locale& loc = std::locale())
|
||||
{
|
||||
utility::ostringstream_t oss;
|
||||
oss.imbue(loc);
|
||||
oss << val;
|
||||
if (oss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
inline utility::string_t print_string(const utility::string_t& val) { return val; }
|
||||
|
||||
namespace details
|
||||
{
|
||||
#if defined(__ANDROID__)
|
||||
template<class T>
|
||||
inline std::string to_string(const T t)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os.imbue(std::locale::classic());
|
||||
os << t;
|
||||
return os.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline utility::string_t to_string_t(const T t)
|
||||
{
|
||||
#ifdef _UTF16_STRINGS
|
||||
using std::to_wstring;
|
||||
return to_wstring(t);
|
||||
#else
|
||||
#if !defined(__ANDROID__)
|
||||
using std::to_string;
|
||||
#endif
|
||||
return to_string(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
utility::string_t print_string(const Source& val)
|
||||
{
|
||||
utility::ostringstream_t oss;
|
||||
oss.imbue(std::locale::classic());
|
||||
oss << val;
|
||||
if (oss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
inline const utility::string_t& print_string(const utility::string_t& val) { return val; }
|
||||
|
||||
template<typename Source>
|
||||
utf8string print_utf8string(const Source& val)
|
||||
{
|
||||
return conversions::to_utf8string(print_string(val));
|
||||
}
|
||||
inline const utf8string& print_utf8string(const utf8string& val) { return val; }
|
||||
|
||||
template<typename Target>
|
||||
Target scan_string(const utility::string_t& str)
|
||||
{
|
||||
Target t;
|
||||
utility::istringstream_t iss(str);
|
||||
iss.imbue(std::locale::classic());
|
||||
iss >> t;
|
||||
if (iss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
inline const utility::string_t& scan_string(const utility::string_t& str) { return str; }
|
||||
} // namespace details
|
||||
|
||||
template<typename Target>
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
Target scan_string(const utility::string_t& str, const std::locale& loc = std::locale())
|
||||
{
|
||||
Target t;
|
||||
utility::istringstream_t iss(str);
|
||||
iss.imbue(loc);
|
||||
iss >> t;
|
||||
if (iss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
inline utility::string_t scan_string(const utility::string_t& str) { return str; }
|
||||
} // namespace conversions
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Cross platform RAII container for setting thread local locale.
|
||||
/// </summary>
|
||||
class scoped_c_thread_locale
|
||||
{
|
||||
public:
|
||||
_ASYNCRTIMP scoped_c_thread_locale();
|
||||
_ASYNCRTIMP ~scoped_c_thread_locale();
|
||||
|
||||
#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
|
||||
#ifdef _WIN32
|
||||
typedef _locale_t xplat_locale;
|
||||
#else
|
||||
typedef locale_t xplat_locale;
|
||||
#endif
|
||||
|
||||
static _ASYNCRTIMP xplat_locale __cdecl c_locale();
|
||||
#endif
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
std::string m_prevLocale;
|
||||
int m_prevThreadSetting;
|
||||
#elif !(defined(ANDROID) || defined(__ANDROID__))
|
||||
locale_t m_prevLocale;
|
||||
#endif
|
||||
scoped_c_thread_locale(const scoped_c_thread_locale&);
|
||||
scoped_c_thread_locale& operator=(const scoped_c_thread_locale&);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// </summary>
|
||||
inline bool __cdecl is_alnum(const unsigned char uch) CPPREST_NOEXCEPT
|
||||
{ // test if uch is an alnum character
|
||||
// special casing char to avoid branches
|
||||
// clang-format off
|
||||
static CPPREST_CONSTEXPR bool is_alnum_table[UCHAR_MAX + 1] = {
|
||||
/* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */
|
||||
/* 0X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 1X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 2X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0-9 */
|
||||
/* 4X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A-Z */
|
||||
/* 5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
/* 6X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a-z */
|
||||
/* 7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
|
||||
/* non-ASCII values initialized to 0 */
|
||||
};
|
||||
// clang-format on
|
||||
return (is_alnum_table[uch]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// </summary>
|
||||
inline bool __cdecl is_alnum(const char ch) CPPREST_NOEXCEPT { return (is_alnum(static_cast<unsigned char>(ch))); }
|
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// </summary>
|
||||
template<class Elem>
|
||||
inline bool __cdecl is_alnum(Elem ch) CPPREST_NOEXCEPT
|
||||
{
|
||||
// assumes 'x' == L'x' for the ASCII range
|
||||
typedef typename std::make_unsigned<Elem>::type UElem;
|
||||
const auto uch = static_cast<UElem>(ch);
|
||||
return (uch <= static_cast<UElem>('z') && is_alnum(static_cast<unsigned char>(uch)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simplistic implementation of make_unique. A better implementation would be based on variadic templates
|
||||
/// and therefore not be compatible with Dev10.
|
||||
/// </summary>
|
||||
template<typename _Type>
|
||||
std::unique_ptr<_Type> make_unique()
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type());
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3)
|
||||
{
|
||||
return std::unique_ptr<_Type>(
|
||||
new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(
|
||||
std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3), std::forward<_Arg4>(arg4)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4, typename _Arg5>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4, _Arg5&& arg5)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1),
|
||||
std::forward<_Arg2>(arg2),
|
||||
std::forward<_Arg3>(arg3),
|
||||
std::forward<_Arg4>(arg4),
|
||||
std::forward<_Arg5>(arg5)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4, typename _Arg5, typename _Arg6>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4, _Arg5&& arg5, _Arg6&& arg6)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1),
|
||||
std::forward<_Arg2>(arg2),
|
||||
std::forward<_Arg3>(arg3),
|
||||
std::forward<_Arg4>(arg4),
|
||||
std::forward<_Arg5>(arg5),
|
||||
std::forward<_Arg6>(arg6)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string equality comparison.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if the strings are equivalent, false otherwise</returns>
|
||||
_ASYNCRTIMP bool __cdecl str_iequal(const std::string& left, const std::string& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string equality comparison.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if the strings are equivalent, false otherwise</returns>
|
||||
_ASYNCRTIMP bool __cdecl str_iequal(const std::wstring& left, const std::wstring& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string less-than comparison.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise,
|
||||
/// false.</returns>
|
||||
_ASYNCRTIMP bool __cdecl str_iless(const std::string& left, const std::string& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string less-than comparison.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise,
|
||||
/// false.</returns>
|
||||
_ASYNCRTIMP bool __cdecl str_iless(const std::wstring& left, const std::wstring& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Convert a string to lowercase in place.
|
||||
/// </summary>
|
||||
/// <param name="target">The string to convert to lowercase.</param>
|
||||
_ASYNCRTIMP void __cdecl inplace_tolower(std::string& target) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Convert a string to lowercase in place.
|
||||
/// </summary>
|
||||
/// <param name="target">The string to convert to lowercase.</param>
|
||||
_ASYNCRTIMP void __cdecl inplace_tolower(std::wstring& target) CPPREST_NOEXCEPT;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/// <summary>
|
||||
/// Category error type for Windows OS errors.
|
||||
/// </summary>
|
||||
class windows_category_impl : public std::error_category
|
||||
{
|
||||
public:
|
||||
virtual const char* name() const CPPREST_NOEXCEPT { return "windows"; }
|
||||
|
||||
virtual std::string message(int errorCode) const CPPREST_NOEXCEPT;
|
||||
|
||||
virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the windows error category.
|
||||
/// </summary>
|
||||
/// </returns>An error category instance.</returns>
|
||||
_ASYNCRTIMP const std::error_category& __cdecl windows_category();
|
||||
|
||||
#else
|
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the linux error category.
|
||||
/// </summary>
|
||||
/// </returns>An error category instance.</returns>
|
||||
_ASYNCRTIMP const std::error_category& __cdecl linux_category();
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the current platform's error category.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP const std::error_category& __cdecl platform_category();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of std::system_error from a OS error code.
|
||||
/// </summary>
|
||||
inline std::system_error __cdecl create_system_error(unsigned long errorCode)
|
||||
{
|
||||
std::error_code code((int)errorCode, platform_category());
|
||||
return std::system_error(code, code.message());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a std::error_code from a OS error code.
|
||||
/// </summary>
|
||||
inline std::error_code __cdecl create_error_code(unsigned long errorCode)
|
||||
{
|
||||
return std::error_code((int)errorCode, platform_category());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the corresponding error message from a OS error code.
|
||||
/// </summary>
|
||||
inline utility::string_t __cdecl create_error_message(unsigned long errorCode)
|
||||
{
|
||||
return utility::conversions::to_string_t(create_error_code(errorCode).message());
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
class datetime
|
||||
{
|
||||
public:
|
||||
typedef uint64_t interval_type;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the supported date and time string formats.
|
||||
/// </summary>
|
||||
enum date_format
|
||||
{
|
||||
RFC_1123,
|
||||
ISO_8601
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current UTC time.
|
||||
/// </summary>
|
||||
static _ASYNCRTIMP datetime __cdecl utc_now();
|
||||
|
||||
/// <summary>
|
||||
/// An invalid UTC timestamp value.
|
||||
/// </summary>
|
||||
enum : interval_type
|
||||
{
|
||||
utc_timestamp_invalid = static_cast<interval_type>(-1)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns seconds since Unix/POSIX time epoch at 01-01-1970 00:00:00.
|
||||
/// If time is before epoch, utc_timestamp_invalid is returned.
|
||||
/// </summary>
|
||||
static interval_type utc_timestamp()
|
||||
{
|
||||
const auto seconds = utc_now().to_interval() / _secondTicks;
|
||||
if (seconds >= 11644473600LL)
|
||||
{
|
||||
return seconds - 11644473600LL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return utc_timestamp_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
datetime() : m_interval(0) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 format.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <c>datetime</c> of zero if not successful.</returns>
|
||||
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of the <c>datetime</c>.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t to_string(date_format format = RFC_1123) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integral time value.
|
||||
/// </summary>
|
||||
interval_type to_interval() const { return m_interval; }
|
||||
|
||||
datetime operator-(interval_type value) const { return datetime(m_interval - value); }
|
||||
|
||||
datetime operator+(interval_type value) const { return datetime(m_interval + value); }
|
||||
|
||||
bool operator==(datetime dt) const { return m_interval == dt.m_interval; }
|
||||
|
||||
bool operator!=(const datetime& dt) const { return !(*this == dt); }
|
||||
|
||||
static interval_type from_milliseconds(unsigned int milliseconds) { return milliseconds * _msTicks; }
|
||||
|
||||
static interval_type from_seconds(unsigned int seconds) { return seconds * _secondTicks; }
|
||||
|
||||
static interval_type from_minutes(unsigned int minutes) { return minutes * _minuteTicks; }
|
||||
|
||||
static interval_type from_hours(unsigned int hours) { return hours * _hourTicks; }
|
||||
|
||||
static interval_type from_days(unsigned int days) { return days * _dayTicks; }
|
||||
|
||||
bool is_initialized() const { return m_interval != 0; }
|
||||
|
||||
private:
|
||||
friend int operator-(datetime t1, datetime t2);
|
||||
|
||||
static const interval_type _msTicks = static_cast<interval_type>(10000);
|
||||
static const interval_type _secondTicks = 1000 * _msTicks;
|
||||
static const interval_type _minuteTicks = 60 * _secondTicks;
|
||||
static const interval_type _hourTicks = 60 * 60 * _secondTicks;
|
||||
static const interval_type _dayTicks = 24 * 60 * 60 * _secondTicks;
|
||||
|
||||
// Private constructor. Use static methods to create an instance.
|
||||
datetime(interval_type interval) : m_interval(interval) {}
|
||||
|
||||
// Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
|
||||
interval_type m_interval;
|
||||
};
|
||||
|
||||
inline int operator-(datetime t1, datetime t2)
|
||||
{
|
||||
auto diff = (t1.m_interval - t2.m_interval);
|
||||
|
||||
// Round it down to seconds
|
||||
diff /= 10 * 1000 * 1000;
|
||||
|
||||
return static_cast<int>(diff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nonce string generator class.
|
||||
/// </summary>
|
||||
class nonce_generator
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Define default nonce length.
|
||||
/// </summary>
|
||||
enum
|
||||
{
|
||||
default_length = 32
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Nonce generator constructor.
|
||||
/// </summary>
|
||||
/// <param name="length">Length of the generated nonce string.</param>
|
||||
nonce_generator(int length = default_length)
|
||||
: m_random(static_cast<unsigned int>(utility::datetime::utc_timestamp())), m_length(length)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a nonce string containing random alphanumeric characters (A-Za-z0-9).
|
||||
/// Length of the generated string is set by length().
|
||||
/// </summary>
|
||||
/// <returns>The generated nonce string.</returns>
|
||||
_ASYNCRTIMP utility::string_t generate();
|
||||
|
||||
/// <summary>
|
||||
/// Get length of generated nonce string.
|
||||
/// </summary>
|
||||
/// <returns>Nonce string length.</returns>
|
||||
int length() const { return m_length; }
|
||||
|
||||
/// <summary>
|
||||
/// Set length of the generated nonce string.
|
||||
/// </summary>
|
||||
/// <param name="length">Lenght of nonce string.</param>
|
||||
void set_length(int length) { m_length = length; }
|
||||
|
||||
private:
|
||||
std::mt19937 m_random;
|
||||
int m_length;
|
||||
};
|
||||
|
||||
} // namespace utility
|
||||
391
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/base_uri.h
vendored
Normal file
391
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/base_uri.h
vendored
Normal file
@ -0,0 +1,391 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Protocol independent support for URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
struct uri_components
|
||||
{
|
||||
uri_components() : m_path(_XPLATSTR("/")), m_port(-1) {}
|
||||
|
||||
uri_components(const uri_components&) = default;
|
||||
uri_components& operator=(const uri_components&) = default;
|
||||
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
uri_components(uri_components&& other) CPPREST_NOEXCEPT : m_scheme(std::move(other.m_scheme)),
|
||||
m_host(std::move(other.m_host)),
|
||||
m_user_info(std::move(other.m_user_info)),
|
||||
m_path(std::move(other.m_path)),
|
||||
m_query(std::move(other.m_query)),
|
||||
m_fragment(std::move(other.m_fragment)),
|
||||
m_port(other.m_port)
|
||||
{
|
||||
}
|
||||
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
uri_components& operator=(uri_components&& other) CPPREST_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_scheme = std::move(other.m_scheme);
|
||||
m_host = std::move(other.m_host);
|
||||
m_user_info = std::move(other.m_user_info);
|
||||
m_path = std::move(other.m_path);
|
||||
m_query = std::move(other.m_query);
|
||||
m_fragment = std::move(other.m_fragment);
|
||||
m_port = other.m_port;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
_ASYNCRTIMP utility::string_t join();
|
||||
|
||||
utility::string_t m_scheme;
|
||||
utility::string_t m_host;
|
||||
utility::string_t m_user_info;
|
||||
utility::string_t m_path;
|
||||
utility::string_t m_query;
|
||||
utility::string_t m_fragment;
|
||||
int m_port;
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A single exception type to represent errors in parsing, encoding, and decoding URIs.
|
||||
/// </summary>
|
||||
class uri_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
uri_exception(std::string msg) : m_msg(std::move(msg)) {}
|
||||
|
||||
~uri_exception() CPPREST_NOEXCEPT {}
|
||||
|
||||
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A flexible, protocol independent URI implementation.
|
||||
///
|
||||
/// URI instances are immutable. Querying the various fields on an empty URI will return empty strings. Querying
|
||||
/// various diagnostic members on an empty URI will return false.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation accepts both URIs ('http://msn.com/path') and URI relative-references
|
||||
/// ('/path?query#frag').
|
||||
///
|
||||
/// This implementation does not provide any scheme-specific handling -- an example of this
|
||||
/// would be the following: 'http://path1/path'. This is a valid URI, but it's not a valid
|
||||
/// http-uri -- that is, it's syntactically correct but does not conform to the requirements
|
||||
/// of the http scheme (http requires a host).
|
||||
/// We could provide this by allowing a pluggable 'scheme' policy-class, which would provide
|
||||
/// extra capability for validating and canonicalizing a URI according to scheme, and would
|
||||
/// introduce a layer of type-safety for URIs of differing schemes, and thus differing semantics.
|
||||
///
|
||||
/// One issue with implementing a scheme-independent URI facility is that of comparing for equality.
|
||||
/// For instance, these URIs are considered equal 'http://msn.com', 'http://msn.com:80'. That is --
|
||||
/// the 'default' port can be either omitted or explicit. Since we don't have a way to map a scheme
|
||||
/// to it's default port, we don't have a way to know these are equal. This is just one of a class of
|
||||
/// issues with regard to scheme-specific behavior.
|
||||
/// </remarks>
|
||||
class uri
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// The various components of a URI. This enum is used to indicate which
|
||||
/// URI component is being encoded to the encode_uri_component. This allows
|
||||
/// specific encoding to be performed.
|
||||
///
|
||||
/// Scheme and port don't allow '%' so they don't need to be encoded.
|
||||
/// </summary>
|
||||
class components
|
||||
{
|
||||
public:
|
||||
enum component
|
||||
{
|
||||
user_info,
|
||||
host,
|
||||
path,
|
||||
query,
|
||||
fragment,
|
||||
full_uri
|
||||
};
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a URI component according to RFC 3986.
|
||||
/// Note if a full URI is specified instead of an individual URI component all
|
||||
/// characters not in the unreserved set are escaped.
|
||||
/// </summary>
|
||||
/// <param name="raw">The URI as a string.</param>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_uri(const utility::string_t& raw,
|
||||
uri::components::component = components::full_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a string by converting all characters except for RFC 3986 unreserved characters to their
|
||||
/// hexadecimal representation.
|
||||
/// </summary>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t& data);
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an encoded string.
|
||||
/// </summary>
|
||||
/// <param name="encoded">The URI as a string.</param>
|
||||
/// <returns>The decoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl decode(const utility::string_t& encoded);
|
||||
|
||||
/// <summary>
|
||||
/// Splits a path into its hierarchical components.
|
||||
/// </summary>
|
||||
/// <param name="path">The path as a string</param>
|
||||
/// <returns>A <c>std::vector<utility::string_t></c> containing the segments in the path.</returns>
|
||||
_ASYNCRTIMP static std::vector<utility::string_t> __cdecl split_path(const utility::string_t& path);
|
||||
|
||||
/// <summary>
|
||||
/// Splits a query into its key-value components.
|
||||
/// </summary>
|
||||
/// <param name="query">The query string</param>
|
||||
/// <returns>A <c>std::map<utility::string_t, utility::string_t></c> containing the key-value components of
|
||||
/// the query.</returns>
|
||||
_ASYNCRTIMP static std::map<utility::string_t, utility::string_t> __cdecl split_query(
|
||||
const utility::string_t& query);
|
||||
|
||||
/// <summary>
|
||||
/// Validates a string as a URI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query').
|
||||
/// </remarks>
|
||||
/// <param name="uri_string">The URI string to be validated.</param>
|
||||
/// <returns><c>true</c> if the given string represents a valid URI, <c>false</c> otherwise.</returns>
|
||||
_ASYNCRTIMP static bool __cdecl validate(const utility::string_t& uri_string);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty uri
|
||||
/// </summary>
|
||||
uri() : m_uri(_XPLATSTR("/")) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given encoded string. This will throw an exception if the string
|
||||
/// does not contain a valid URI. Use uri::validate if processing user-input.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">A pointer to an encoded string to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const utility::char_t* uri_string);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given encoded string. This will throw an exception if the string
|
||||
/// does not contain a valid URI. Use uri::validate if processing user-input.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">An encoded URI string to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const utility::string_t& uri_string);
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
uri(const uri&) = default;
|
||||
|
||||
/// <summary>
|
||||
/// Copy assignment operator.
|
||||
/// </summary>
|
||||
uri& operator=(const uri&) = default;
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
uri(uri&& other) CPPREST_NOEXCEPT : m_uri(std::move(other.m_uri)), m_components(std::move(other.m_components)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator
|
||||
/// </summary>
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
uri& operator=(uri&& other) CPPREST_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_uri = std::move(other.m_uri);
|
||||
m_components = std::move(other.m_components);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the scheme component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI scheme as a string.</returns>
|
||||
const utility::string_t& scheme() const { return m_components.m_scheme; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the user information component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI user information as a string.</returns>
|
||||
const utility::string_t& user_info() const { return m_components.m_user_info; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the host component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI host as a string.</returns>
|
||||
const utility::string_t& host() const { return m_components.m_host; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the port component of the URI. Returns -1 if no port is specified.
|
||||
/// </summary>
|
||||
/// <returns>The URI port as an integer.</returns>
|
||||
int port() const { return m_components.m_port; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the path component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI path as a string.</returns>
|
||||
const utility::string_t& path() const { return m_components.m_path; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the query component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI query as a string.</returns>
|
||||
const utility::string_t& query() const { return m_components.m_query; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the fragment component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI fragment as a string.</returns>
|
||||
const utility::string_t& fragment() const { return m_components.m_fragment; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new uri object with the same authority portion as this one, omitting the resource and query portions.
|
||||
/// </summary>
|
||||
/// <returns>The new uri object with the same authority.</returns>
|
||||
_ASYNCRTIMP uri authority() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path, query, and fragment portion of this uri, which may be empty.
|
||||
/// </summary>
|
||||
/// <returns>The new URI object with the path, query and fragment portion of this URI.</returns>
|
||||
_ASYNCRTIMP uri resource() const;
|
||||
|
||||
/// <summary>
|
||||
/// An empty URI specifies no components, and serves as a default value
|
||||
/// </summary>
|
||||
bool is_empty() const { return this->m_uri.empty() || this->m_uri == _XPLATSTR("/"); }
|
||||
|
||||
/// <summary>
|
||||
/// A loopback URI is one which refers to a hostname or ip address with meaning only on the local machine.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Examples include "localhost", or ip addresses in the loopback range (127.0.0.0/24).
|
||||
/// </remarks>
|
||||
/// <returns><c>true</c> if this URI references the local host, <c>false</c> otherwise.</returns>
|
||||
bool is_host_loopback() const
|
||||
{
|
||||
return !is_empty() &&
|
||||
((host() == _XPLATSTR("localhost")) || (host().size() > 4 && host().substr(0, 4) == _XPLATSTR("127.")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wildcard URI is one which refers to all hostnames that resolve to the local machine (using the * or +)
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// http://*:80
|
||||
/// </example>
|
||||
bool is_host_wildcard() const
|
||||
{
|
||||
return !is_empty() && (this->host() == _XPLATSTR("*") || this->host() == _XPLATSTR("+"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A portable URI is one with a hostname that can be resolved globally (used from another machine).
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this URI can be resolved globally (used from another machine), <c>false</c>
|
||||
/// otherwise.</returns> <remarks> The hostname "localhost" is a reserved name that is guaranteed to resolve to the
|
||||
/// local machine, and cannot be used for inter-machine communication. Likewise the hostnames "*" and "+" on Windows
|
||||
/// represent wildcards, and do not map to a resolvable address.
|
||||
/// </remarks>
|
||||
bool is_host_portable() const { return !(is_empty() || is_host_loopback() || is_host_wildcard()); }
|
||||
|
||||
/// <summary>
|
||||
/// A default port is one where the port is unspecified, and will be determined by the operating system.
|
||||
/// The choice of default port may be dictated by the scheme (http -> 80) or not.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this URI instance has a default port, <c>false</c> otherwise.</returns>
|
||||
bool is_port_default() const { return !is_empty() && this->port() == 0; }
|
||||
|
||||
/// <summary>
|
||||
/// An "authority" URI is one with only a scheme, optional userinfo, hostname, and (optional) port.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this is an "authority" URI, <c>false</c> otherwise.</returns>
|
||||
bool is_authority() const { return !is_empty() && is_path_empty() && query().empty() && fragment().empty(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the other URI has the same authority as this one
|
||||
/// </summary>
|
||||
/// <param name="other">The URI to compare the authority with.</param>
|
||||
/// <returns><c>true</c> if both the URI's have the same authority, <c>false</c> otherwise.</returns>
|
||||
bool has_same_authority(const uri& other) const { return !is_empty() && this->authority() == other.authority(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the path portion of this URI is empty
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the path portion of this URI is empty, <c>false</c> otherwise.</returns>
|
||||
bool is_path_empty() const { return path().empty() || path() == _XPLATSTR("/"); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full (encoded) URI as a string.
|
||||
/// </summary>
|
||||
/// <returns>The full encoded URI string.</returns>
|
||||
utility::string_t to_string() const { return m_uri; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an URI resolved against <c>this</c> as the base URI
|
||||
/// according to RFC3986, Section 5 (https://tools.ietf.org/html/rfc3986#section-5).
|
||||
/// </summary>
|
||||
/// <param name="relativeUri">The relative URI to be resolved against <c>this</c> as base.</param>
|
||||
/// <returns>The new resolved URI string.</returns>
|
||||
_ASYNCRTIMP utility::string_t resolve_uri(const utility::string_t& relativeUri) const;
|
||||
|
||||
_ASYNCRTIMP bool operator==(const uri& other) const;
|
||||
|
||||
bool operator<(const uri& other) const { return m_uri < other.m_uri; }
|
||||
|
||||
bool operator!=(const uri& other) const { return !(this->operator==(other)); }
|
||||
|
||||
private:
|
||||
friend class uri_builder;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given URI components.
|
||||
/// </summary>
|
||||
/// <param name="components">A URI components object to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const details::uri_components& components);
|
||||
|
||||
// Used by uri_builder
|
||||
static utility::string_t __cdecl encode_query_impl(const utf8string& raw);
|
||||
|
||||
utility::string_t m_uri;
|
||||
details::uri_components m_components;
|
||||
};
|
||||
|
||||
} // namespace web
|
||||
590
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/containerstream.h
vendored
Normal file
590
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/containerstream.h
vendored
Normal file
@ -0,0 +1,590 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* This file defines a basic STL-container-based stream buffer. Reading from the buffer will not remove any data
|
||||
* from it and seeking is thus supported.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace Concurrency
|
||||
{
|
||||
namespace streams
|
||||
{
|
||||
// Forward declarations
|
||||
|
||||
template<typename _CollectionType>
|
||||
class container_buffer;
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// The basic_container_buffer class serves as a memory-based steam buffer that supports writing or reading
|
||||
/// sequences of characters.
|
||||
/// The class itself should not be used in application code, it is used by the stream definitions farther down in the
|
||||
/// header file.
|
||||
/// </summary>
|
||||
/// <remarks> When closed, neither writing nor reading is supported any longer. <c>basic_container_buffer</c> does not
|
||||
/// support simultaneous use of the buffer for reading and writing.</remarks>
|
||||
template<typename _CollectionType>
|
||||
class basic_container_buffer : public streams::details::streambuf_state_manager<typename _CollectionType::value_type>
|
||||
{
|
||||
public:
|
||||
typedef typename _CollectionType::value_type _CharType;
|
||||
typedef typename basic_streambuf<_CharType>::traits traits;
|
||||
typedef typename basic_streambuf<_CharType>::int_type int_type;
|
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type;
|
||||
typedef typename basic_streambuf<_CharType>::off_type off_type;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the underlying data container
|
||||
/// </summary>
|
||||
_CollectionType& collection() { return m_data; }
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_container_buffer()
|
||||
{
|
||||
// Invoke the synchronous versions since we need to
|
||||
// purge the request queue before deleting the buffer
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// <summary>
|
||||
/// can_seek is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the stream, if known. Calls to <c>has_size</c> will determine whether
|
||||
/// the result of <c>size</c> can be relied on.
|
||||
/// </summary>
|
||||
virtual utility::size64_t size() const { return utility::size64_t(m_data.size()); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const { return 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the stream buffer implementation to buffer or not buffer.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to use for internal buffering, 0 if no buffering should be done.</param>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will silently ignore calls to this function and it
|
||||
/// will not have any effect on what is returned by subsequent calls to <see cref="::buffer_size method"
|
||||
/// />.</remarks>
|
||||
virtual void set_buffer_size(size_t, std::ios_base::openmode = std::ios_base::in) { return; }
|
||||
|
||||
/// <summary>
|
||||
/// For any input stream, <c>in_avail</c> returns the number of characters that are immediately available
|
||||
/// to be consumed without blocking. May be used in conjunction with <cref="::sbumpc method"/> to read data without
|
||||
/// incurring the overhead of using tasks.
|
||||
/// </summary>
|
||||
virtual size_t in_avail() const
|
||||
{
|
||||
// See the comment in seek around the restriction that we do not allow read head to
|
||||
// seek beyond the current write_end.
|
||||
_ASSERTE(m_current_position <= m_data.size());
|
||||
|
||||
msl::safeint3::SafeInt<size_t> readhead(m_current_position);
|
||||
msl::safeint3::SafeInt<size_t> writeend(m_data.size());
|
||||
return (size_t)(writeend - readhead);
|
||||
}
|
||||
|
||||
virtual pplx::task<bool> _sync() { return pplx::task_from_result(true); }
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch)
|
||||
{
|
||||
int_type retVal = (this->write(&ch, 1) == 1) ? static_cast<int_type>(ch) : traits::eof();
|
||||
return pplx::task_from_result<int_type>(retVal);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _putn(const _CharType* ptr, size_t count)
|
||||
{
|
||||
return pplx::task_from_result<size_t>(this->write(ptr, count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a contiguous memory block and returns it.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to allocate.</param>
|
||||
/// <returns>A pointer to a block to write to, null if the stream buffer implementation does not support
|
||||
/// alloc/commit.</returns>
|
||||
_CharType* _alloc(size_t count)
|
||||
{
|
||||
if (!this->can_write()) return nullptr;
|
||||
|
||||
// Allocate space
|
||||
resize_for_write(m_current_position + count);
|
||||
|
||||
// Let the caller copy the data
|
||||
return (_CharType*)&m_data[m_current_position];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits a block already allocated by the stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to be committed.</param>
|
||||
void _commit(size_t actual)
|
||||
{
|
||||
// Update the write position and satisfy any pending reads
|
||||
update_current_position(m_current_position + actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the next already allocated contiguous block of data.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A reference to a pointer variable that will hold the address of the block on success.</param>
|
||||
/// <param name="count">The number of contiguous characters available at the address in 'ptr'.</param>
|
||||
/// <returns><c>true</c> if the operation succeeded, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// A return of false does not necessarily indicate that a subsequent read operation would fail, only that
|
||||
/// there is no block to return immediately or that the stream buffer does not support the operation.
|
||||
/// The stream buffer may not de-allocate the block until <see cref="::release method" /> is called.
|
||||
/// If the end of the stream is reached, the function will return <c>true</c>, a null pointer, and a count of zero;
|
||||
/// a subsequent read will not succeed.
|
||||
/// </remarks>
|
||||
virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count)
|
||||
{
|
||||
ptr = nullptr;
|
||||
count = 0;
|
||||
|
||||
if (!this->can_read()) return false;
|
||||
|
||||
count = in_avail();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
ptr = (_CharType*)&m_data[m_current_position];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can only be open for read OR write, not both. If there is no data then
|
||||
// we have reached the end of the stream so indicate such with true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a block of data acquired using <see cref="::acquire method"/>. This frees the stream buffer to
|
||||
/// de-allocate the memory, if it so desires. Move the read position ahead by the count.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A pointer to the block of data to be released.</param>
|
||||
/// <param name="count">The number of characters that were read.</param>
|
||||
virtual void release(_Out_writes_opt_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
if (ptr != nullptr) update_current_position(m_current_position + count);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
return pplx::task_from_result(this->read(ptr, count));
|
||||
}
|
||||
|
||||
size_t _sgetn(_Out_writes_(count) _CharType* ptr, _In_ size_t count) { return this->read(ptr, count); }
|
||||
|
||||
virtual size_t _scopy(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
return this->read(ptr, count, false);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _bumpc() { return pplx::task_from_result(this->read_byte(true)); }
|
||||
|
||||
virtual int_type _sbumpc() { return this->read_byte(true); }
|
||||
|
||||
virtual pplx::task<int_type> _getc() { return pplx::task_from_result(this->read_byte(false)); }
|
||||
|
||||
int_type _sgetc() { return this->read_byte(false); }
|
||||
|
||||
virtual pplx::task<int_type> _nextc()
|
||||
{
|
||||
this->read_byte(true);
|
||||
return pplx::task_from_result(this->read_byte(false));
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _ungetc()
|
||||
{
|
||||
auto pos = seekoff(-1, std::ios_base::cur, std::ios_base::in);
|
||||
if (pos == (pos_type)traits::eof()) return pplx::task_from_result(traits::eof());
|
||||
return this->getc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current read or write position in the stream.
|
||||
/// </summary>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The current position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the direction parameter defines whether to move the read or the write
|
||||
/// cursor.</remarks>
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
if (((mode & std::ios_base::in) && !this->can_read()) || ((mode & std::ios_base::out) && !this->can_write()))
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given position.
|
||||
/// </summary>
|
||||
/// <param name="pos">The offset from the beginning of the stream.</param>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks).</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors. For such streams, the direction parameter
|
||||
/// defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekpos(pos_type position, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg(0);
|
||||
|
||||
// In order to support relative seeking from the end position we need to fix an end position.
|
||||
// Technically, there is no end for the stream buffer as new writes would just expand the buffer.
|
||||
// For now, we assume that the current write_end is the end of the buffer. We use this artificial
|
||||
// end to restrict the read head from seeking beyond what is available.
|
||||
|
||||
pos_type end(m_data.size());
|
||||
|
||||
if (position >= beg)
|
||||
{
|
||||
auto pos = static_cast<size_t>(position);
|
||||
|
||||
// Read head
|
||||
if ((mode & std::ios_base::in) && this->can_read())
|
||||
{
|
||||
if (position <= end)
|
||||
{
|
||||
// We do not allow reads to seek beyond the end or before the start position.
|
||||
update_current_position(pos);
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
// Write head
|
||||
if ((mode & std::ios_base::out) && this->can_write())
|
||||
{
|
||||
// Allocate space
|
||||
resize_for_write(pos);
|
||||
|
||||
// Nothing to really copy
|
||||
|
||||
// Update write head and satisfy read requests if any
|
||||
update_current_position(pos);
|
||||
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to a position given by a relative offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The relative position to seek to</param>
|
||||
/// <param name="way">The starting point (beginning, end, current) for the seek.</param>
|
||||
/// <param name="mode">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the mode parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekoff(off_type offset, std::ios_base::seekdir way, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg = 0;
|
||||
pos_type cur = static_cast<pos_type>(m_current_position);
|
||||
pos_type end = static_cast<pos_type>(m_data.size());
|
||||
|
||||
switch (way)
|
||||
{
|
||||
case std::ios_base::beg: return seekpos(beg + offset, mode);
|
||||
|
||||
case std::ios_base::cur: return seekpos(cur + offset, mode);
|
||||
|
||||
case std::ios_base::end: return seekpos(end + offset, mode);
|
||||
|
||||
default: return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename _CollectionType1>
|
||||
friend class streams::container_buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_container_buffer(std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<typename _CollectionType::value_type>(mode), m_current_position(0)
|
||||
{
|
||||
validate_mode(mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_container_buffer(_CollectionType data, std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<typename _CollectionType::value_type>(mode)
|
||||
, m_data(std::move(data))
|
||||
, m_current_position((mode & std::ios_base::in) ? 0 : m_data.size())
|
||||
{
|
||||
validate_mode(mode);
|
||||
}
|
||||
|
||||
static void validate_mode(std::ios_base::openmode mode)
|
||||
{
|
||||
// Disallow simultaneous use of the stream buffer for writing and reading.
|
||||
if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
|
||||
throw std::invalid_argument("this combination of modes on container stream not supported");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the request can be satisfied.
|
||||
/// </summary>
|
||||
bool can_satisfy(size_t)
|
||||
{
|
||||
// We can always satisfy a read, at least partially, unless the
|
||||
// read position is at the very end of the buffer.
|
||||
return (in_avail() > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and returns it as int_type.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
int_type read_byte(bool advance = true)
|
||||
{
|
||||
_CharType value;
|
||||
auto read_size = this->read(&value, 1, advance);
|
||||
return read_size == 1 ? static_cast<int_type>(value) : traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to count characters into ptr and returns the count of characters copied.
|
||||
/// The return value (actual characters copied) could be <= count.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
size_t read(_Out_writes_(count) _CharType* ptr, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
if (!can_satisfy(count)) return 0;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> request_size(count);
|
||||
msl::safeint3::SafeInt<size_t> read_size = request_size.Min(in_avail());
|
||||
|
||||
size_t newPos = m_current_position + read_size;
|
||||
|
||||
auto readBegin = std::begin(m_data) + m_current_position;
|
||||
auto readEnd = std::begin(m_data) + newPos;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(readBegin, readEnd, stdext::checked_array_iterator<_CharType*>(ptr, count));
|
||||
#else
|
||||
std::copy(readBegin, readEnd, ptr);
|
||||
#endif // _WIN32
|
||||
|
||||
if (advance)
|
||||
{
|
||||
update_current_position(newPos);
|
||||
}
|
||||
|
||||
return (size_t)read_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write count characters from the ptr into the stream buffer
|
||||
/// </summary>
|
||||
size_t write(const _CharType* ptr, size_t count)
|
||||
{
|
||||
if (!this->can_write() || (count == 0)) return 0;
|
||||
|
||||
auto newSize = m_current_position + count;
|
||||
|
||||
// Allocate space
|
||||
resize_for_write(newSize);
|
||||
|
||||
// Copy the data
|
||||
std::copy(ptr, ptr + count, std::begin(m_data) + m_current_position);
|
||||
|
||||
// Update write head and satisfy pending reads if any
|
||||
update_current_position(newSize);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resize the underlying container to match the new write head
|
||||
/// </summary>
|
||||
void resize_for_write(size_t newPos)
|
||||
{
|
||||
// Resize the container if required
|
||||
if (newPos > m_data.size())
|
||||
{
|
||||
m_data.resize(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the write head to the new position
|
||||
/// </summary>
|
||||
void update_current_position(size_t newPos)
|
||||
{
|
||||
// The new write head
|
||||
m_current_position = newPos;
|
||||
_ASSERTE(m_current_position <= m_data.size());
|
||||
}
|
||||
|
||||
// The actual data store
|
||||
_CollectionType m_data;
|
||||
|
||||
// Read/write head
|
||||
size_t m_current_position;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The basic_container_buffer class serves as a memory-based steam buffer that supports writing or reading
|
||||
/// sequences of characters. Note that it cannot be used as a consumer producer buffer.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">
|
||||
/// The type of the container.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// This is a reference-counted version of <c>basic_container_buffer</c>.
|
||||
/// </remarks>
|
||||
template<typename _CollectionType>
|
||||
class container_buffer : public streambuf<typename _CollectionType::value_type>
|
||||
{
|
||||
public:
|
||||
typedef typename _CollectionType::value_type char_type;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a container_buffer given a collection, copying its data into the buffer.
|
||||
/// </summary>
|
||||
/// <param name="data">The collection that is the starting point for the buffer</param>
|
||||
/// <param name="mode">The I/O mode that the buffer should use (in / out)</param>
|
||||
container_buffer(_CollectionType data, std::ios_base::openmode mode = std::ios_base::in)
|
||||
: streambuf<typename _CollectionType::value_type>(
|
||||
std::shared_ptr<details::basic_container_buffer<_CollectionType>>(
|
||||
new streams::details::basic_container_buffer<_CollectionType>(std::move(data), mode)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a container_buffer starting from an empty collection.
|
||||
/// </summary>
|
||||
/// <param name="mode">The I/O mode that the buffer should use (in / out)</param>
|
||||
container_buffer(std::ios_base::openmode mode = std::ios_base::out)
|
||||
: streambuf<typename _CollectionType::value_type>(
|
||||
std::shared_ptr<details::basic_container_buffer<_CollectionType>>(
|
||||
new details::basic_container_buffer<_CollectionType>(mode)))
|
||||
{
|
||||
}
|
||||
|
||||
_CollectionType& collection() const
|
||||
{
|
||||
auto listBuf = static_cast<details::basic_container_buffer<_CollectionType>*>(this->get_base().get());
|
||||
return listBuf->collection();
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A static class to allow users to create input and out streams based off STL
|
||||
/// collections. The sole purpose of this class to avoid users from having to know
|
||||
/// anything about stream buffers.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">The type of the STL collection.</typeparam>
|
||||
template<typename _CollectionType>
|
||||
class container_stream
|
||||
{
|
||||
public:
|
||||
typedef typename _CollectionType::value_type char_type;
|
||||
typedef container_buffer<_CollectionType> buffer_type;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an input stream given an STL container.
|
||||
/// </summary>
|
||||
/// </param name="data">STL container to back the input stream.</param>
|
||||
/// <returns>An input stream.</returns>
|
||||
static concurrency::streams::basic_istream<char_type> open_istream(_CollectionType data)
|
||||
{
|
||||
return concurrency::streams::basic_istream<char_type>(buffer_type(std::move(data), std::ios_base::in));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an output stream using an STL container as the storage.
|
||||
/// </summary>
|
||||
/// <returns>An output stream.</returns>
|
||||
static concurrency::streams::basic_ostream<char_type> open_ostream()
|
||||
{
|
||||
return concurrency::streams::basic_ostream<char_type>(buffer_type(std::ios_base::out));
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The stringstream allows an input stream to be constructed from std::string or std::wstring
|
||||
/// For output streams the underlying string container could be retrieved using <c>buf->collection().</c>
|
||||
/// </summary>
|
||||
typedef container_stream<std::basic_string<char>> stringstream;
|
||||
typedef stringstream::buffer_type stringstreambuf;
|
||||
|
||||
typedef container_stream<utility::string_t> wstringstream;
|
||||
typedef wstringstream::buffer_type wstringstreambuf;
|
||||
|
||||
/// <summary>
|
||||
/// The <c>bytestream</c> is a static class that allows an input stream to be constructed from any STL container.
|
||||
/// </summary>
|
||||
class bytestream
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a single byte character input stream given an STL container.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">The type of the STL collection.</typeparam>
|
||||
/// <param name="data">STL container to back the input stream.</param>
|
||||
/// <returns>An single byte character input stream.</returns>
|
||||
template<typename _CollectionType>
|
||||
static concurrency::streams::istream open_istream(_CollectionType data)
|
||||
{
|
||||
return concurrency::streams::istream(
|
||||
streams::container_buffer<_CollectionType>(std::move(data), std::ios_base::in));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a single byte character output stream using an STL container as storage.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">The type of the STL collection.</typeparam>
|
||||
/// <returns>A single byte character output stream.</returns>
|
||||
template<typename _CollectionType>
|
||||
static concurrency::streams::ostream open_ostream()
|
||||
{
|
||||
return concurrency::streams::ostream(streams::container_buffer<_CollectionType>());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
7482
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/SafeInt3.hpp
vendored
Normal file
7482
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/SafeInt3.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
131
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/basic_types.h
vendored
Normal file
131
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/basic_types.h
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Platform-dependent type definitions
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include "cpprest/details/SafeInt3.hpp"
|
||||
|
||||
namespace utility
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#define _UTF16_STRINGS
|
||||
#endif
|
||||
|
||||
// We should be using a 64-bit size type for most situations that do
|
||||
// not involve specifying the size of a memory allocation or buffer.
|
||||
typedef uint64_t size64_t;
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef uint32_t HRESULT; // Needed for PPLX
|
||||
#endif
|
||||
|
||||
#ifdef _UTF16_STRINGS
|
||||
//
|
||||
// On Windows, all strings are wide
|
||||
//
|
||||
typedef wchar_t char_t;
|
||||
typedef std::wstring string_t;
|
||||
#define _XPLATSTR(x) L##x
|
||||
typedef std::wostringstream ostringstream_t;
|
||||
typedef std::wofstream ofstream_t;
|
||||
typedef std::wostream ostream_t;
|
||||
typedef std::wistream istream_t;
|
||||
typedef std::wifstream ifstream_t;
|
||||
typedef std::wistringstream istringstream_t;
|
||||
typedef std::wstringstream stringstream_t;
|
||||
#define ucout std::wcout
|
||||
#define ucin std::wcin
|
||||
#define ucerr std::wcerr
|
||||
#else
|
||||
//
|
||||
// On POSIX platforms, all strings are narrow
|
||||
//
|
||||
typedef char char_t;
|
||||
typedef std::string string_t;
|
||||
#define _XPLATSTR(x) x
|
||||
typedef std::ostringstream ostringstream_t;
|
||||
typedef std::ofstream ofstream_t;
|
||||
typedef std::ostream ostream_t;
|
||||
typedef std::istream istream_t;
|
||||
typedef std::ifstream ifstream_t;
|
||||
typedef std::istringstream istringstream_t;
|
||||
typedef std::stringstream stringstream_t;
|
||||
#define ucout std::cout
|
||||
#define ucin std::cin
|
||||
#define ucerr std::cerr
|
||||
#endif // endif _UTF16_STRINGS
|
||||
|
||||
#ifndef _TURN_OFF_PLATFORM_STRING
|
||||
// The 'U' macro can be used to create a string or character literal of the platform type, i.e. utility::char_t.
|
||||
// If you are using a library causing conflicts with 'U' macro, it can be turned off by defining the macro
|
||||
// '_TURN_OFF_PLATFORM_STRING' before including the C++ REST SDK header files, and e.g. use '_XPLATSTR' instead.
|
||||
#define U(x) _XPLATSTR(x)
|
||||
#endif // !_TURN_OFF_PLATFORM_STRING
|
||||
|
||||
} // namespace utility
|
||||
|
||||
typedef char utf8char;
|
||||
typedef std::string utf8string;
|
||||
typedef std::stringstream utf8stringstream;
|
||||
typedef std::ostringstream utf8ostringstream;
|
||||
typedef std::ostream utf8ostream;
|
||||
typedef std::istream utf8istream;
|
||||
typedef std::istringstream utf8istringstream;
|
||||
|
||||
#ifdef _UTF16_STRINGS
|
||||
typedef wchar_t utf16char;
|
||||
typedef std::wstring utf16string;
|
||||
typedef std::wstringstream utf16stringstream;
|
||||
typedef std::wostringstream utf16ostringstream;
|
||||
typedef std::wostream utf16ostream;
|
||||
typedef std::wistream utf16istream;
|
||||
typedef std::wistringstream utf16istringstream;
|
||||
#else
|
||||
typedef char16_t utf16char;
|
||||
typedef std::u16string utf16string;
|
||||
typedef std::basic_stringstream<utf16char> utf16stringstream;
|
||||
typedef std::basic_ostringstream<utf16char> utf16ostringstream;
|
||||
typedef std::basic_ostream<utf16char> utf16ostream;
|
||||
typedef std::basic_istream<utf16char> utf16istream;
|
||||
typedef std::basic_istringstream<utf16char> utf16istringstream;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Include on everything except Windows Desktop ARM, unless explicitly excluded.
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
#if defined(WINAPI_FAMILY)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && defined(_M_ARM)
|
||||
#define CPPREST_EXCLUDE_WEBSOCKETS
|
||||
#endif
|
||||
#else
|
||||
#if defined(_M_ARM)
|
||||
#define CPPREST_EXCLUDE_WEBSOCKETS
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
89
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/cpprest_compat.h
vendored
Normal file
89
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/cpprest_compat.h
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Standard macros and definitions.
|
||||
* This header has minimal dependency on windows headers and is safe for use in the public API
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#define CPPREST_NOEXCEPT noexcept
|
||||
#define CPPREST_CONSTEXPR constexpr
|
||||
#else
|
||||
#define CPPREST_NOEXCEPT
|
||||
#define CPPREST_CONSTEXPR const
|
||||
#endif // _MSC_VER >= 1900
|
||||
|
||||
#define CASABLANCA_UNREFERENCED_PARAMETER(x) (x)
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv
|
||||
|
||||
#define __declspec(x) __attribute__((x))
|
||||
#define dllimport
|
||||
#define novtable /* no novtable equivalent */
|
||||
#define __assume(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) __builtin_unreachable(); \
|
||||
} while (false)
|
||||
#define CASABLANCA_UNREFERENCED_PARAMETER(x) (void)x
|
||||
#define CPPREST_NOEXCEPT noexcept
|
||||
#define CPPREST_CONSTEXPR constexpr
|
||||
|
||||
#include <assert.h>
|
||||
#define _ASSERTE(x) assert(x)
|
||||
|
||||
// No SAL on non Windows platforms
|
||||
#include "cpprest/details/nosal.h"
|
||||
|
||||
#if !defined(__cdecl)
|
||||
#if defined(cdecl)
|
||||
#define __cdecl __attribute__((cdecl))
|
||||
#else // ^^^ defined cdecl ^^^ // vvv !defined cdecl vvv
|
||||
#define __cdecl
|
||||
#endif // defined cdecl
|
||||
#endif // not defined __cdecl
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// This is needed to disable the use of __thread inside the boost library.
|
||||
// Android does not support thread local storage -- if boost is included
|
||||
// without this macro defined, it will create references to __tls_get_addr
|
||||
// which (while able to link) will not be available at runtime and prevent
|
||||
// the .so from loading.
|
||||
#if not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#endif // not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#endif // defined(__ANDROID__)
|
||||
|
||||
#ifdef __clang__
|
||||
#include <cstdio>
|
||||
#endif // __clang__
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef _NO_ASYNCRTIMP
|
||||
#define _ASYNCRTIMP
|
||||
#else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv
|
||||
#ifdef _ASYNCRT_EXPORT
|
||||
#define _ASYNCRTIMP __declspec(dllexport)
|
||||
#else // ^^^ _ASYNCRT_EXPORT ^^^ // vvv !_ASYNCRT_EXPORT vvv
|
||||
#define _ASYNCRTIMP __declspec(dllimport)
|
||||
#endif // _ASYNCRT_EXPORT
|
||||
#endif // _NO_ASYNCRTIMP
|
||||
|
||||
#ifdef CASABLANCA_DEPRECATION_NO_WARNINGS
|
||||
#define CASABLANCA_DEPRECATED(x)
|
||||
#else
|
||||
#define CASABLANCA_DEPRECATED(x) __declspec(deprecated(x))
|
||||
#endif // CASABLANCA_DEPRECATION_NO_WARNINGS
|
||||
220
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/fileio.h
vendored
Normal file
220
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/fileio.h
vendored
Normal file
@ -0,0 +1,220 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* fileio.h
|
||||
*
|
||||
* Asynchronous I/O: stream buffer implementation details
|
||||
*
|
||||
* We're going to some lengths to avoid exporting C++ class member functions and implementation details across
|
||||
* module boundaries, and the factoring requires that we keep the implementation details away from the main header
|
||||
* files. The supporting functions, which are in this file, use C-like signatures to avoid as many issues as
|
||||
* possible.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
|
||||
namespace Concurrency
|
||||
{
|
||||
namespace streams
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// A record containing the essential private data members of a file stream,
|
||||
/// in particular the parts that need to be shared between the public header
|
||||
/// file and the implementation in the implementation file.
|
||||
/// </summary>
|
||||
struct _file_info
|
||||
{
|
||||
_ASYNCRTIMP _file_info(std::ios_base::openmode mode, size_t buffer_size)
|
||||
: m_rdpos(0)
|
||||
, m_wrpos(0)
|
||||
, m_atend(false)
|
||||
, m_buffer_size(buffer_size)
|
||||
, m_buffer(nullptr)
|
||||
, m_bufoff(0)
|
||||
, m_bufsize(0)
|
||||
, m_buffill(0)
|
||||
, m_mode(mode)
|
||||
{
|
||||
}
|
||||
|
||||
// Positional data
|
||||
|
||||
size_t m_rdpos;
|
||||
size_t m_wrpos;
|
||||
bool m_atend;
|
||||
|
||||
// Input buffer
|
||||
|
||||
size_t m_buffer_size; // The intended size of the buffer to read into.
|
||||
char* m_buffer;
|
||||
|
||||
size_t m_bufoff; // File position that the start of the buffer represents.
|
||||
msl::safeint3::SafeInt<size_t> m_bufsize; // Buffer allocated size, as actually allocated.
|
||||
size_t m_buffill; // Amount of file data actually in the buffer
|
||||
|
||||
std::ios_base::openmode m_mode;
|
||||
|
||||
pplx::extensibility::recursive_lock_t m_lock;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// This interface provides the necessary callbacks for completion events.
|
||||
/// </summary>
|
||||
class _filestream_callback
|
||||
{
|
||||
public:
|
||||
virtual void on_opened(_In_ details::_file_info*) {}
|
||||
virtual void on_closed() {}
|
||||
virtual void on_error(const std::exception_ptr&) {}
|
||||
virtual void on_completed(size_t) {}
|
||||
|
||||
protected:
|
||||
virtual ~_filestream_callback() {}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
extern "C"
|
||||
{
|
||||
/// <summary>
|
||||
/// Open a file and create a streambuf instance to represent it.
|
||||
/// </summary>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the file has been opened.</param>
|
||||
/// <param name="filename">The name of the file to open</param>
|
||||
/// <param name="mode">A creation mode for the stream buffer</param>
|
||||
/// <param name="prot">A file protection mode to use for the file stream (not supported on Linux)</param>
|
||||
/// <returns><c>true</c> if the opening operation could be initiated, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// True does not signal that the file will eventually be successfully opened, just that the process was started.
|
||||
/// </remarks>
|
||||
#if !defined(__cplusplus_winrt)
|
||||
_ASYNCRTIMP bool __cdecl _open_fsb_str(_In_ concurrency::streams::details::_filestream_callback* callback,
|
||||
const utility::char_t* filename,
|
||||
std::ios_base::openmode mode,
|
||||
int prot);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Create a streambuf instance to represent a WinRT file.
|
||||
/// </summary>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the file has been opened.</param>
|
||||
/// <param name="file">The file object</param>
|
||||
/// <param name="mode">A creation mode for the stream buffer</param>
|
||||
/// <returns><c>true</c> if the opening operation could be initiated, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// True does not signal that the file will eventually be successfully opened, just that the process was started.
|
||||
/// This is only available for WinRT.
|
||||
/// </remarks>
|
||||
#if defined(__cplusplus_winrt)
|
||||
_ASYNCRTIMP bool __cdecl _open_fsb_stf_str(_In_ concurrency::streams::details::_filestream_callback* callback,
|
||||
::Windows::Storage::StorageFile ^ file,
|
||||
std::ios_base::openmode mode,
|
||||
int prot);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Close a file stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the file has been opened.</param>
|
||||
/// <returns><c>true</c> if the closing operation could be initiated, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// True does not signal that the file will eventually be successfully closed, just that the process was started.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP bool __cdecl _close_fsb_nolock(_In_ concurrency::streams::details::_file_info** info,
|
||||
_In_ concurrency::streams::details::_filestream_callback* callback);
|
||||
_ASYNCRTIMP bool __cdecl _close_fsb(_In_ concurrency::streams::details::_file_info** info,
|
||||
_In_ concurrency::streams::details::_filestream_callback* callback);
|
||||
|
||||
/// <summary>
|
||||
/// Write data from a buffer into the file stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the write request is
|
||||
/// completed.</param> <param name="ptr">A pointer to a buffer where the data should be placed</param> <param
|
||||
/// name="count">The size (in characters) of the buffer</param> <returns>0 if the read request is still outstanding,
|
||||
/// -1 if the request failed, otherwise the size of the data read into the buffer</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _putn_fsb(_In_ concurrency::streams::details::_file_info* info,
|
||||
_In_ concurrency::streams::details::_filestream_callback* callback,
|
||||
const void* ptr,
|
||||
size_t count,
|
||||
size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Read data from a file stream into a buffer
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the write request is
|
||||
/// completed.</param> <param name="ptr">A pointer to a buffer where the data should be placed</param> <param
|
||||
/// name="count">The size (in characters) of the buffer</param> <returns>0 if the read request is still outstanding,
|
||||
/// -1 if the request failed, otherwise the size of the data read into the buffer</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _getn_fsb(_In_ concurrency::streams::details::_file_info* info,
|
||||
_In_ concurrency::streams::details::_filestream_callback* callback,
|
||||
_Out_writes_(count) void* ptr,
|
||||
_In_ size_t count,
|
||||
size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Flush all buffered data to the underlying file.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the write request is
|
||||
/// completed.</param> <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP bool __cdecl _sync_fsb(_In_ concurrency::streams::details::_file_info* info,
|
||||
_In_ concurrency::streams::details::_filestream_callback* callback);
|
||||
|
||||
/// <summary>
|
||||
/// Get the size of the underlying file.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <returns>The file size</returns>
|
||||
_ASYNCRTIMP utility::size64_t __cdecl _get_size(_In_ concurrency::streams::details::_file_info* info,
|
||||
size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the internal buffers and pointers when the application seeks to a new read location in the stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="pos">The new position (offset from the start) in the file stream</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _seekrdpos_fsb(_In_ concurrency::streams::details::_file_info* info,
|
||||
size_t pos,
|
||||
size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the internal buffers and pointers when the application seeks to a new read location in the stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="pos">The new position (offset from the start) in the file stream</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _seekrdtoend_fsb(_In_ concurrency::streams::details::_file_info* info,
|
||||
int64_t offset,
|
||||
size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the internal buffers and pointers when the application seeks to a new write location in the stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="pos">The new position (offset from the start) in the file stream</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _seekwrpos_fsb(_In_ concurrency::streams::details::_file_info* info,
|
||||
size_t pos,
|
||||
size_t char_size);
|
||||
}
|
||||
198
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_constants.dat
vendored
Normal file
198
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_constants.dat
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
#ifdef _METHODS
|
||||
DAT(GET, _XPLATSTR("GET"))
|
||||
DAT(POST, _XPLATSTR("POST"))
|
||||
DAT(PUT, _XPLATSTR("PUT"))
|
||||
DAT(DEL, _XPLATSTR("DELETE"))
|
||||
DAT(HEAD, _XPLATSTR("HEAD"))
|
||||
DAT(OPTIONS, _XPLATSTR("OPTIONS"))
|
||||
DAT(TRCE, _XPLATSTR("TRACE"))
|
||||
DAT(CONNECT, _XPLATSTR("CONNECT"))
|
||||
DAT(MERGE, _XPLATSTR("MERGE"))
|
||||
DAT(PATCH, _XPLATSTR("PATCH"))
|
||||
#endif
|
||||
|
||||
#ifdef _PHRASES
|
||||
DAT(Continue, 100, _XPLATSTR("Continue"))
|
||||
DAT(SwitchingProtocols, 101, _XPLATSTR("Switching Protocols"))
|
||||
DAT(OK, 200, _XPLATSTR("OK"))
|
||||
DAT(Created, 201, _XPLATSTR("Created"))
|
||||
DAT(Accepted, 202, _XPLATSTR("Accepted"))
|
||||
DAT(NonAuthInfo, 203, _XPLATSTR("Non-Authoritative Information"))
|
||||
DAT(NoContent, 204, _XPLATSTR("No Content"))
|
||||
DAT(ResetContent, 205, _XPLATSTR("Reset Content"))
|
||||
DAT(PartialContent, 206, _XPLATSTR("Partial Content"))
|
||||
DAT(MultiStatus, 207, _XPLATSTR("Multi-Status"))
|
||||
DAT(AlreadyReported, 208, _XPLATSTR("Already Reported"))
|
||||
DAT(IMUsed, 226, _XPLATSTR("IM Used"))
|
||||
DAT(MultipleChoices, 300, _XPLATSTR("Multiple Choices"))
|
||||
DAT(MovedPermanently, 301, _XPLATSTR("Moved Permanently"))
|
||||
DAT(Found, 302, _XPLATSTR("Found"))
|
||||
DAT(SeeOther, 303, _XPLATSTR("See Other"))
|
||||
DAT(NotModified, 304, _XPLATSTR("Not Modified"))
|
||||
DAT(UseProxy, 305, _XPLATSTR("Use Proxy"))
|
||||
DAT(TemporaryRedirect, 307, _XPLATSTR("Temporary Redirect"))
|
||||
DAT(PermanentRedirect, 308, _XPLATSTR("Permanent Redirect"))
|
||||
DAT(BadRequest, 400, _XPLATSTR("Bad Request"))
|
||||
DAT(Unauthorized, 401, _XPLATSTR("Unauthorized"))
|
||||
DAT(PaymentRequired, 402, _XPLATSTR("Payment Required"))
|
||||
DAT(Forbidden, 403, _XPLATSTR("Forbidden"))
|
||||
DAT(NotFound, 404, _XPLATSTR("Not Found"))
|
||||
DAT(MethodNotAllowed, 405, _XPLATSTR("Method Not Allowed"))
|
||||
DAT(NotAcceptable, 406, _XPLATSTR("Not Acceptable"))
|
||||
DAT(ProxyAuthRequired, 407, _XPLATSTR("Proxy Authentication Required"))
|
||||
DAT(RequestTimeout, 408, _XPLATSTR("Request Time-out"))
|
||||
DAT(Conflict, 409, _XPLATSTR("Conflict"))
|
||||
DAT(Gone, 410, _XPLATSTR("Gone"))
|
||||
DAT(LengthRequired, 411, _XPLATSTR("Length Required"))
|
||||
DAT(PreconditionFailed, 412, _XPLATSTR("Precondition Failed"))
|
||||
DAT(RequestEntityTooLarge, 413, _XPLATSTR("Request Entity Too Large"))
|
||||
DAT(RequestUriTooLarge, 414, _XPLATSTR("Request Uri Too Large"))
|
||||
DAT(UnsupportedMediaType, 415, _XPLATSTR("Unsupported Media Type"))
|
||||
DAT(RangeNotSatisfiable, 416, _XPLATSTR("Requested range not satisfiable"))
|
||||
DAT(ExpectationFailed, 417, _XPLATSTR("Expectation Failed"))
|
||||
DAT(MisdirectedRequest, 421, _XPLATSTR("Misdirected Request"))
|
||||
DAT(UnprocessableEntity, 422, _XPLATSTR("Unprocessable Entity"))
|
||||
DAT(Locked, 423, _XPLATSTR("Locked"))
|
||||
DAT(FailedDependency, 424, _XPLATSTR("Failed Dependency"))
|
||||
DAT(UpgradeRequired, 426, _XPLATSTR("Upgrade Required"))
|
||||
DAT(PreconditionRequired, 428, _XPLATSTR("Precondition Required"))
|
||||
DAT(TooManyRequests, 429, _XPLATSTR("Too Many Requests"))
|
||||
DAT(RequestHeaderFieldsTooLarge, 431, _XPLATSTR("Request Header Fields Too Large"))
|
||||
DAT(UnavailableForLegalReasons, 451, _XPLATSTR("Unavailable For Legal Reasons"))
|
||||
DAT(InternalError, 500, _XPLATSTR("Internal Error"))
|
||||
DAT(NotImplemented, 501, _XPLATSTR("Not Implemented"))
|
||||
DAT(BadGateway, 502, _XPLATSTR("Bad Gateway"))
|
||||
DAT(ServiceUnavailable, 503, _XPLATSTR("Service Unavailable"))
|
||||
DAT(GatewayTimeout, 504, _XPLATSTR("Gateway Time-out"))
|
||||
DAT(HttpVersionNotSupported, 505, _XPLATSTR("HTTP Version not supported"))
|
||||
DAT(VariantAlsoNegotiates, 506, _XPLATSTR("Variant Also Negotiates"))
|
||||
DAT(InsufficientStorage, 507, _XPLATSTR("Insufficient Storage"))
|
||||
DAT(LoopDetected, 508, _XPLATSTR("Loop Detected"))
|
||||
DAT(NotExtended, 510, _XPLATSTR("Not Extended"))
|
||||
DAT(NetworkAuthenticationRequired, 511, _XPLATSTR("Network Authentication Required"))
|
||||
#endif // _PHRASES
|
||||
|
||||
#ifdef _HEADER_NAMES
|
||||
DAT(accept, "Accept")
|
||||
DAT(accept_charset, "Accept-Charset")
|
||||
DAT(accept_encoding, "Accept-Encoding")
|
||||
DAT(accept_language, "Accept-Language")
|
||||
DAT(accept_ranges, "Accept-Ranges")
|
||||
DAT(access_control_allow_origin, "Access-Control-Allow-Origin")
|
||||
DAT(age, "Age")
|
||||
DAT(allow, "Allow")
|
||||
DAT(authorization, "Authorization")
|
||||
DAT(cache_control, "Cache-Control")
|
||||
DAT(connection, "Connection")
|
||||
DAT(content_encoding, "Content-Encoding")
|
||||
DAT(content_language, "Content-Language")
|
||||
DAT(content_length, "Content-Length")
|
||||
DAT(content_location, "Content-Location")
|
||||
DAT(content_md5, "Content-MD5")
|
||||
DAT(content_range, "Content-Range")
|
||||
DAT(content_type, "Content-Type")
|
||||
DAT(content_disposition, "Content-Disposition")
|
||||
DAT(date, "Date")
|
||||
DAT(etag, "ETag")
|
||||
DAT(expect, "Expect")
|
||||
DAT(expires, "Expires")
|
||||
DAT(from, "From")
|
||||
DAT(host, "Host")
|
||||
DAT(if_match, "If-Match")
|
||||
DAT(if_modified_since, "If-Modified-Since")
|
||||
DAT(if_none_match, "If-None-Match")
|
||||
DAT(if_range, "If-Range")
|
||||
DAT(if_unmodified_since, "If-Unmodified-Since")
|
||||
DAT(last_modified, "Last-Modified")
|
||||
DAT(location, "Location")
|
||||
DAT(max_forwards, "Max-Forwards")
|
||||
DAT(pragma, "Pragma")
|
||||
DAT(proxy_authenticate, "Proxy-Authenticate")
|
||||
DAT(proxy_authorization, "Proxy-Authorization")
|
||||
DAT(range, "Range")
|
||||
DAT(referer, "Referer")
|
||||
DAT(retry_after, "Retry-After")
|
||||
DAT(server, "Server")
|
||||
DAT(te, "TE")
|
||||
DAT(trailer, "Trailer")
|
||||
DAT(transfer_encoding, "Transfer-Encoding")
|
||||
DAT(upgrade, "Upgrade")
|
||||
DAT(user_agent, "User-Agent")
|
||||
DAT(vary, "Vary")
|
||||
DAT(via, "Via")
|
||||
DAT(warning, "Warning")
|
||||
DAT(www_authenticate, "WWW-Authenticate")
|
||||
#endif // _HEADER_NAMES
|
||||
|
||||
#ifdef _MIME_TYPES
|
||||
DAT(application_atom_xml, "application/atom+xml")
|
||||
DAT(application_http, "application/http")
|
||||
DAT(application_javascript, "application/javascript")
|
||||
DAT(application_json, "application/json")
|
||||
DAT(application_xjson, "application/x-json")
|
||||
DAT(application_octetstream, "application/octet-stream")
|
||||
DAT(application_x_www_form_urlencoded, "application/x-www-form-urlencoded")
|
||||
DAT(multipart_form_data, "multipart/form-data")
|
||||
DAT(boundary, "boundary")
|
||||
DAT(form_data, "form-data")
|
||||
DAT(application_xjavascript, "application/x-javascript")
|
||||
DAT(application_xml, "application/xml")
|
||||
DAT(message_http, "message/http")
|
||||
DAT(text, "text")
|
||||
DAT(text_javascript, "text/javascript")
|
||||
DAT(text_json, "text/json")
|
||||
DAT(text_plain, "text/plain")
|
||||
DAT(text_plain_utf16, "text/plain; charset=utf-16")
|
||||
DAT(text_plain_utf16le, "text/plain; charset=utf-16le")
|
||||
DAT(text_plain_utf8, "text/plain; charset=utf-8")
|
||||
DAT(text_xjavascript, "text/x-javascript")
|
||||
DAT(text_xjson, "text/x-json")
|
||||
#endif // _MIME_TYPES
|
||||
|
||||
#ifdef _CHARSET_TYPES
|
||||
DAT(ascii, "ascii")
|
||||
DAT(usascii, "us-ascii")
|
||||
DAT(latin1, "iso-8859-1")
|
||||
DAT(utf8, "utf-8")
|
||||
DAT(utf16, "utf-16")
|
||||
DAT(utf16le, "utf-16le")
|
||||
DAT(utf16be, "utf-16be")
|
||||
#endif // _CHARSET_TYPES
|
||||
|
||||
#ifdef _OAUTH1_METHODS
|
||||
DAT(hmac_sha1, _XPLATSTR("HMAC-SHA1"))
|
||||
DAT(plaintext, _XPLATSTR("PLAINTEXT"))
|
||||
#endif // _OAUTH1_METHODS
|
||||
|
||||
#ifdef _OAUTH1_STRINGS
|
||||
DAT(callback, "oauth_callback")
|
||||
DAT(callback_confirmed, "oauth_callback_confirmed")
|
||||
DAT(consumer_key, "oauth_consumer_key")
|
||||
DAT(nonce, "oauth_nonce")
|
||||
DAT(realm, "realm") // NOTE: No "oauth_" prefix.
|
||||
DAT(signature, "oauth_signature")
|
||||
DAT(signature_method, "oauth_signature_method")
|
||||
DAT(timestamp, "oauth_timestamp")
|
||||
DAT(token, "oauth_token")
|
||||
DAT(token_secret, "oauth_token_secret")
|
||||
DAT(verifier, "oauth_verifier")
|
||||
DAT(version, "oauth_version")
|
||||
#endif // _OAUTH1_STRINGS
|
||||
|
||||
#ifdef _OAUTH2_STRINGS
|
||||
DAT(access_token, "access_token")
|
||||
DAT(authorization_code, "authorization_code")
|
||||
DAT(bearer, "bearer")
|
||||
DAT(client_id, "client_id")
|
||||
DAT(client_secret, "client_secret")
|
||||
DAT(code, "code")
|
||||
DAT(expires_in, "expires_in")
|
||||
DAT(grant_type, "grant_type")
|
||||
DAT(redirect_uri, "redirect_uri")
|
||||
DAT(refresh_token, "refresh_token")
|
||||
DAT(response_type, "response_type")
|
||||
DAT(scope, "scope")
|
||||
DAT(state, "state")
|
||||
DAT(token, "token")
|
||||
DAT(token_type, "token_type")
|
||||
#endif // _OAUTH2_STRINGS
|
||||
48
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_helpers.h
vendored
Normal file
48
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_helpers.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Implementation Details of the http.h layer of messaging
|
||||
*
|
||||
* Functions and types for interoperating with http.h from modern C++
|
||||
* This file includes windows definitions and should not be included in a public header
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
namespace chunked_encoding
|
||||
{
|
||||
// Transfer-Encoding: chunked support
|
||||
static const size_t additional_encoding_space = 12;
|
||||
static const size_t data_offset = additional_encoding_space - 2;
|
||||
|
||||
// Add the data necessary for properly sending data with transfer-encoding: chunked.
|
||||
//
|
||||
// There are up to 12 additional bytes needed for each chunk:
|
||||
//
|
||||
// The last chunk requires 5 bytes, and is fixed.
|
||||
// All other chunks require up to 8 bytes for the length, and four for the two CRLF
|
||||
// delimiters.
|
||||
//
|
||||
_ASYNCRTIMP size_t __cdecl add_chunked_delimiters(_Out_writes_(buffer_size) uint8_t* data,
|
||||
_In_ size_t buffer_size,
|
||||
size_t bytes_read);
|
||||
} // namespace chunked_encoding
|
||||
|
||||
} // namespace details
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
72
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_server.h
vendored
Normal file
72
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_server.h
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: interface to implement HTTP server to service http_listeners.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
#error "Error: http server APIs are not supported in XP"
|
||||
#endif //_WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
|
||||
#include "cpprest/http_listener.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface http listeners interact with for receiving and responding to http requests.
|
||||
/// </summary>
|
||||
class http_server
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Release any held resources.
|
||||
/// </summary>
|
||||
virtual ~http_server() {};
|
||||
|
||||
/// <summary>
|
||||
/// Start listening for incoming requests.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> start() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Registers an http listener.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> register_listener(
|
||||
_In_ web::http::experimental::listener::details::http_listener_impl* pListener) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters an http listener.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> unregister_listener(
|
||||
_In_ web::http::experimental::listener::details::http_listener_impl* pListener) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Stop processing and listening for incoming requests.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> stop() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends the specified http response.
|
||||
/// </summary>
|
||||
/// <param name="response">The http_response to send.</param>
|
||||
/// <returns>A operation which is completed once the response has been sent.</returns>
|
||||
virtual pplx::task<void> respond(http::http_response response) = 0;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace experimental
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
93
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_server_api.h
vendored
Normal file
93
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/http_server_api.h
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: exposes the entry points to the http server transport apis.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
#error "Error: http server APIs are not supported in XP"
|
||||
#endif //_WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
|
||||
#include "cpprest/http_listener.h"
|
||||
#include <memory>
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class http_server;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton class used to register for http requests and send responses.
|
||||
///
|
||||
/// The lifetime is tied to http listener registration. When the first listener registers an instance is created
|
||||
/// and when the last one unregisters the receiver stops and is destroyed. It can be started back up again if
|
||||
/// listeners are again registered.
|
||||
/// </summary>
|
||||
class http_server_api
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Returns whether or not any listeners are registered.
|
||||
/// </summary>
|
||||
static bool __cdecl has_listener();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a HTTP server API.
|
||||
/// </summary>
|
||||
static void __cdecl register_server_api(std::unique_ptr<http_server> server_api);
|
||||
|
||||
/// <summary>
|
||||
/// Clears the http server API.
|
||||
/// </summary>
|
||||
static void __cdecl unregister_server_api();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a listener for HTTP requests and starts receiving.
|
||||
/// </summary>
|
||||
static pplx::task<void> __cdecl register_listener(
|
||||
_In_ web::http::experimental::listener::details::http_listener_impl* pListener);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the given listener and stops listening for HTTP requests.
|
||||
/// </summary>
|
||||
static pplx::task<void> __cdecl unregister_listener(
|
||||
_In_ web::http::experimental::listener::details::http_listener_impl* pListener);
|
||||
|
||||
/// <summary>
|
||||
/// Gets static HTTP server API. Could be null if no registered listeners.
|
||||
/// </summary>
|
||||
static http_server* __cdecl server_api();
|
||||
|
||||
private:
|
||||
/// Used to lock access to the server api registration
|
||||
static pplx::extensibility::critical_section_t s_lock;
|
||||
|
||||
/// Registers a server API set -- this assumes the lock has already been taken
|
||||
static void unsafe_register_server_api(std::unique_ptr<http_server> server_api);
|
||||
|
||||
// Static instance of the HTTP server API.
|
||||
static std::unique_ptr<http_server> s_server_api;
|
||||
|
||||
/// Number of registered listeners;
|
||||
static pplx::details::atomic_long s_registrations;
|
||||
|
||||
// Static only class. No creation.
|
||||
http_server_api();
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace experimental
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
77
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/nosal.h
vendored
Normal file
77
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/nosal.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
***/
|
||||
|
||||
#pragma once
|
||||
// selected MS SAL annotations
|
||||
|
||||
#ifdef _In_
|
||||
#undef _In_
|
||||
#endif
|
||||
#define _In_
|
||||
|
||||
#ifdef _Inout_
|
||||
#undef _Inout_
|
||||
#endif
|
||||
#define _Inout_
|
||||
|
||||
#ifdef _Out_
|
||||
#undef _Out_
|
||||
#endif
|
||||
#define _Out_
|
||||
|
||||
#ifdef _In_z_
|
||||
#undef _In_z_
|
||||
#endif
|
||||
#define _In_z_
|
||||
|
||||
#ifdef _Out_z_
|
||||
#undef _Out_z_
|
||||
#endif
|
||||
#define _Out_z_
|
||||
|
||||
#ifdef _Inout_z_
|
||||
#undef _Inout_z_
|
||||
#endif
|
||||
#define _Inout_z_
|
||||
|
||||
#ifdef _In_opt_
|
||||
#undef _In_opt_
|
||||
#endif
|
||||
#define _In_opt_
|
||||
|
||||
#ifdef _Out_opt_
|
||||
#undef _Out_opt_
|
||||
#endif
|
||||
#define _Out_opt_
|
||||
|
||||
#ifdef _Inout_opt_
|
||||
#undef _Inout_opt_
|
||||
#endif
|
||||
#define _Inout_opt_
|
||||
|
||||
#ifdef _Out_writes_
|
||||
#undef _Out_writes_
|
||||
#endif
|
||||
#define _Out_writes_(x)
|
||||
|
||||
#ifdef _Out_writes_opt_
|
||||
#undef _Out_writes_opt_
|
||||
#endif
|
||||
#define _Out_writes_opt_(x)
|
||||
|
||||
#ifdef _In_reads_
|
||||
#undef _In_reads_
|
||||
#endif
|
||||
#define _In_reads_(x)
|
||||
|
||||
#ifdef _Inout_updates_bytes_
|
||||
#undef _Inout_updates_bytes_
|
||||
#endif
|
||||
#define _Inout_updates_bytes_(x)
|
||||
14
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/resource.h
vendored
Normal file
14
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/resource.h
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Resource.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
223
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/web_utilities.h
vendored
Normal file
223
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/details/web_utilities.h
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* utility classes used by the different web:: clients
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/uri.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class zero_memory_deleter
|
||||
{
|
||||
public:
|
||||
_ASYNCRTIMP void operator()(::utility::string_t* data) const;
|
||||
};
|
||||
typedef std::unique_ptr<::utility::string_t, zero_memory_deleter> plaintext_string;
|
||||
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
#if defined(__cplusplus_winrt)
|
||||
class winrt_encryption
|
||||
{
|
||||
public:
|
||||
winrt_encryption() {}
|
||||
_ASYNCRTIMP winrt_encryption(const std::wstring& data);
|
||||
_ASYNCRTIMP plaintext_string decrypt() const;
|
||||
|
||||
private:
|
||||
::pplx::task<Windows::Storage::Streams::IBuffer ^> m_buffer;
|
||||
};
|
||||
#else
|
||||
class win32_encryption
|
||||
{
|
||||
public:
|
||||
win32_encryption() {}
|
||||
_ASYNCRTIMP win32_encryption(const std::wstring& data);
|
||||
_ASYNCRTIMP ~win32_encryption();
|
||||
_ASYNCRTIMP plaintext_string decrypt() const;
|
||||
|
||||
private:
|
||||
std::vector<char> m_buffer;
|
||||
size_t m_numCharacters;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// Represents a set of user credentials (user name and password) to be used
|
||||
/// for authentication.
|
||||
/// </summary>
|
||||
class credentials
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructs an empty set of credentials without a user name or password.
|
||||
/// </summary>
|
||||
credentials() {}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs credentials from given user name and password.
|
||||
/// </summary>
|
||||
/// <param name="username">User name as a string.</param>
|
||||
/// <param name="password">Password as a string.</param>
|
||||
credentials(utility::string_t username, const utility::string_t& password)
|
||||
: m_username(std::move(username)), m_password(password)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user name associated with the credentials.
|
||||
/// </summary>
|
||||
/// <returns>A string containing the user name.</returns>
|
||||
const utility::string_t& username() const { return m_username; }
|
||||
|
||||
/// <summary>
|
||||
/// The password for the user name associated with the credentials.
|
||||
/// </summary>
|
||||
/// <returns>A string containing the password.</returns>
|
||||
CASABLANCA_DEPRECATED(
|
||||
"This API is deprecated for security reasons to avoid unnecessary password copies stored in plaintext.")
|
||||
utility::string_t password() const
|
||||
{
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
return utility::string_t(*m_password.decrypt());
|
||||
#else
|
||||
return m_password;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if credentials have been set
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if user name and password is set, <c>false</c> otherwise.</returns>
|
||||
bool is_set() const { return !m_username.empty(); }
|
||||
|
||||
details::plaintext_string _internal_decrypt() const
|
||||
{
|
||||
// Encryption APIs not supported on XP
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
return m_password.decrypt();
|
||||
#else
|
||||
return details::plaintext_string(new ::utility::string_t(m_password));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
::utility::string_t m_username;
|
||||
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
#if defined(__cplusplus_winrt)
|
||||
details::winrt_encryption m_password;
|
||||
#else
|
||||
details::win32_encryption m_password;
|
||||
#endif
|
||||
#else
|
||||
::utility::string_t m_password;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// web_proxy represents the concept of the web proxy, which can be auto-discovered,
|
||||
/// disabled, or specified explicitly by the user.
|
||||
/// </summary>
|
||||
class web_proxy
|
||||
{
|
||||
enum web_proxy_mode_internal
|
||||
{
|
||||
use_default_,
|
||||
use_auto_discovery_,
|
||||
disabled_,
|
||||
user_provided_
|
||||
};
|
||||
|
||||
public:
|
||||
enum web_proxy_mode
|
||||
{
|
||||
use_default = use_default_,
|
||||
use_auto_discovery = use_auto_discovery_,
|
||||
disabled = disabled_
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a proxy with the default settings.
|
||||
/// </summary>
|
||||
web_proxy() : m_address(_XPLATSTR("")), m_mode(use_default_) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a proxy with specified mode.
|
||||
/// </summary>
|
||||
/// <param name="mode">Mode to use.</param>
|
||||
web_proxy(web_proxy_mode mode) : m_address(_XPLATSTR("")), m_mode(static_cast<web_proxy_mode_internal>(mode)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a proxy explicitly with provided address.
|
||||
/// </summary>
|
||||
/// <param name="address">Proxy URI to use.</param>
|
||||
web_proxy(uri address) : m_address(address), m_mode(user_provided_) {}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this proxy's URI address. Returns an empty URI if not explicitly set by user.
|
||||
/// </summary>
|
||||
/// <returns>A reference to this proxy's URI.</returns>
|
||||
const uri& address() const { return m_address; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the credentials used for authentication with this proxy.
|
||||
/// </summary>
|
||||
/// <returns>Credentials to for this proxy.</returns>
|
||||
const web::credentials& credentials() const { return m_credentials; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the credentials to use for authentication with this proxy.
|
||||
/// </summary>
|
||||
/// <param name="cred">Credentials to use for this proxy.</param>
|
||||
void set_credentials(web::credentials cred)
|
||||
{
|
||||
if (m_mode == disabled_)
|
||||
{
|
||||
throw std::invalid_argument("Cannot attach credentials to a disabled proxy");
|
||||
}
|
||||
m_credentials = std::move(cred);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this proxy was constructed with default settings.
|
||||
/// </summary>
|
||||
/// <returns>True if default, false otherwise.</param>
|
||||
bool is_default() const { return m_mode == use_default_; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if using a proxy is disabled.
|
||||
/// </summary>
|
||||
/// <returns>True if disabled, false otherwise.</returns>
|
||||
bool is_disabled() const { return m_mode == disabled_; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the auto discovery protocol, WPAD, is to be used.
|
||||
/// </summary>
|
||||
/// <returns>True if auto discovery enabled, false otherwise.</returns>
|
||||
bool is_auto_discovery() const { return m_mode == use_auto_discovery_; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a proxy address is explicitly specified by the user.
|
||||
/// </summary>
|
||||
/// <returns>True if a proxy address was explicitly specified, false otherwise.</returns>
|
||||
bool is_specified() const { return m_mode == user_provided_; }
|
||||
|
||||
private:
|
||||
web::uri m_address;
|
||||
web_proxy_mode_internal m_mode;
|
||||
web::credentials m_credentials;
|
||||
};
|
||||
|
||||
} // namespace web
|
||||
1094
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/filestream.h
vendored
Normal file
1094
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/filestream.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
729
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_client.h
vendored
Normal file
729
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_client.h
vendored
Normal file
@ -0,0 +1,729 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Client-side APIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_HTTP_CLIENT_H
|
||||
#define CASA_HTTP_CLIENT_H
|
||||
|
||||
#if defined(__cplusplus_winrt)
|
||||
#if !defined(__WRL_NO_DEFAULT_LIB__)
|
||||
#define __WRL_NO_DEFAULT_LIB__
|
||||
#endif
|
||||
#include <msxml6.h>
|
||||
#include <wrl.h>
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
typedef IXMLHTTPRequest2* native_handle;
|
||||
}
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
#else
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
typedef void* native_handle;
|
||||
}
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#if !defined(CPPREST_TARGET_XP)
|
||||
#include "cpprest/oauth1.h"
|
||||
#endif
|
||||
|
||||
#include "cpprest/oauth2.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#include "boost/asio/ssl.hpp"
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// The web namespace contains functionality common to multiple protocols like HTTP and WebSockets.
|
||||
namespace web
|
||||
{
|
||||
/// Declarations and functionality for the HTTP protocol.
|
||||
namespace http
|
||||
{
|
||||
/// HTTP client side library.
|
||||
namespace client
|
||||
{
|
||||
// credentials and web_proxy class has been moved from web::http::client namespace to web namespace.
|
||||
// The below using declarations ensure we don't break existing code.
|
||||
// Please use the web::credentials and web::web_proxy class going forward.
|
||||
using web::credentials;
|
||||
using web::web_proxy;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP client configuration class, used to set the possible configuration options
|
||||
/// used to create an http_client instance.
|
||||
/// </summary>
|
||||
class http_client_config
|
||||
{
|
||||
public:
|
||||
http_client_config()
|
||||
: m_guarantee_order(false)
|
||||
, m_timeout(std::chrono::seconds(30))
|
||||
, m_chunksize(0)
|
||||
, m_request_compressed(false)
|
||||
#if !defined(__cplusplus_winrt)
|
||||
, m_validate_certificates(true)
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
, m_tlsext_sni_enabled(true)
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__cplusplus_winrt)
|
||||
, m_buffer_request(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(CPPREST_TARGET_XP)
|
||||
/// <summary>
|
||||
/// Get OAuth 1.0 configuration.
|
||||
/// </summary>
|
||||
/// <returns>Shared pointer to OAuth 1.0 configuration.</returns>
|
||||
const std::shared_ptr<oauth1::experimental::oauth1_config> oauth1() const { return m_oauth1; }
|
||||
|
||||
/// <summary>
|
||||
/// Set OAuth 1.0 configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">OAuth 1.0 configuration to set.</param>
|
||||
void set_oauth1(oauth1::experimental::oauth1_config config)
|
||||
{
|
||||
m_oauth1 = std::make_shared<oauth1::experimental::oauth1_config>(std::move(config));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get OAuth 2.0 configuration.
|
||||
/// </summary>
|
||||
/// <returns>Shared pointer to OAuth 2.0 configuration.</returns>
|
||||
const std::shared_ptr<oauth2::experimental::oauth2_config> oauth2() const { return m_oauth2; }
|
||||
|
||||
/// <summary>
|
||||
/// Set OAuth 2.0 configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">OAuth 2.0 configuration to set.</param>
|
||||
void set_oauth2(oauth2::experimental::oauth2_config config)
|
||||
{
|
||||
m_oauth2 = std::make_shared<oauth2::experimental::oauth2_config>(std::move(config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the web proxy object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the web proxy object.</returns>
|
||||
const web_proxy& proxy() const { return m_proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the web proxy object
|
||||
/// </summary>
|
||||
/// <param name="proxy">A reference to the web proxy object.</param>
|
||||
void set_proxy(web_proxy proxy) { m_proxy = std::move(proxy); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the client credentials
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client credentials.</returns>
|
||||
const http::client::credentials& credentials() const { return m_credentials; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the client credentials
|
||||
/// </summary>
|
||||
/// <param name="cred">A reference to the client credentials.</param>
|
||||
void set_credentials(const http::client::credentials& cred) { m_credentials = cred; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the 'guarantee order' property
|
||||
/// </summary>
|
||||
/// <returns>The value of the property.</returns>
|
||||
bool guarantee_order() const { return m_guarantee_order; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the 'guarantee order' property
|
||||
/// </summary>
|
||||
/// <param name="guarantee_order">The value of the property.</param>
|
||||
CASABLANCA_DEPRECATED(
|
||||
"Confusing API will be removed in future releases. If you need to order HTTP requests use task continuations.")
|
||||
void set_guarantee_order(bool guarantee_order) { m_guarantee_order = guarantee_order; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the timeout
|
||||
/// </summary>
|
||||
/// <returns>The timeout (in seconds) used for each send and receive operation on the client.</returns>
|
||||
utility::seconds timeout() const { return std::chrono::duration_cast<utility::seconds>(m_timeout); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the timeout
|
||||
/// </summary>
|
||||
/// <returns>The timeout (in whatever duration) used for each send and receive operation on the client.</returns>
|
||||
template<class T>
|
||||
T timeout() const
|
||||
{
|
||||
return std::chrono::duration_cast<T>(m_timeout);
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout">The timeout (duration from microseconds range and up) used for each send and receive
|
||||
/// operation on the client.</param>
|
||||
template<class T>
|
||||
void set_timeout(const T& timeout)
|
||||
{
|
||||
m_timeout = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the client chunk size.
|
||||
/// </summary>
|
||||
/// <returns>The internal buffer size used by the http client when sending and receiving data from the
|
||||
/// network.</returns>
|
||||
size_t chunksize() const { return m_chunksize == 0 ? 64 * 1024 : m_chunksize; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the client chunk size.
|
||||
/// </summary>
|
||||
/// <param name="size">The internal buffer size used by the http client when sending and receiving data from the
|
||||
/// network.</param> <remarks>This is a hint -- an implementation may disregard the setting and use some other chunk
|
||||
/// size.</remarks>
|
||||
void set_chunksize(size_t size) { m_chunksize = size; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the default chunk size is in use.
|
||||
/// <remarks>If true, implementations are allowed to choose whatever size is best.</remarks>
|
||||
/// </summary>
|
||||
/// <returns>True if default, false if set by user.</returns>
|
||||
bool is_default_chunksize() const { return m_chunksize == 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if requesting a compressed response using Content-Encoding is turned on, the default is off.
|
||||
/// </summary>
|
||||
/// <returns>True if a content-encoded compressed response is allowed, false otherwise</returns>
|
||||
bool request_compressed_response() const { return m_request_compressed; }
|
||||
|
||||
/// <summary>
|
||||
/// Request that the server respond with a compressed body using Content-Encoding; to use Transfer-Encoding, do not
|
||||
/// set this, and specify a vector of <see cref="web::http::details::compression::decompress_factory" /> pointers
|
||||
/// to the set_decompress_factories method of the <see cref="web::http::http_request" /> object for the request.
|
||||
/// If true and the server does not support compression, this will have no effect.
|
||||
/// The response body is internally decompressed before the consumer receives the data.
|
||||
/// </summary>
|
||||
/// <param name="request_compressed">True to turn on content-encoded response body compression, false
|
||||
/// otherwise.</param> <remarks>Please note there is a performance cost due to copying the request data. Currently
|
||||
/// only supported on Windows and OSX.</remarks>
|
||||
void set_request_compressed_response(bool request_compressed) { m_request_compressed = request_compressed; }
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Gets the server certificate validation property.
|
||||
/// </summary>
|
||||
/// <returns>True if certificates are to be verified, false otherwise.</returns>
|
||||
bool validate_certificates() const { return m_validate_certificates; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the server certificate validation property.
|
||||
/// </summary>
|
||||
/// <param name="validate_certs">False to turn ignore all server certificate validation errors, true
|
||||
/// otherwise.</param> <remarks>Note ignoring certificate errors can be dangerous and should be done with
|
||||
/// caution.</remarks>
|
||||
void set_validate_certificates(bool validate_certs) { m_validate_certificates = validate_certs; }
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Checks if request data buffering is turned on, the default is off.
|
||||
/// </summary>
|
||||
/// <returns>True if buffering is enabled, false otherwise</returns>
|
||||
bool buffer_request() const { return m_buffer_request; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the request buffering property.
|
||||
/// If true, in cases where the request body/stream doesn't support seeking the request data will be buffered.
|
||||
/// This can help in situations where an authentication challenge might be expected.
|
||||
/// </summary>
|
||||
/// <param name="buffer_request">True to turn on buffer, false otherwise.</param>
|
||||
/// <remarks>Please note there is a performance cost due to copying the request data.</remarks>
|
||||
void set_buffer_request(bool buffer_request) { m_buffer_request = buffer_request; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of platform specific options.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The native_handle is the following type depending on the underlying platform:
|
||||
/// Windows Desktop, WinHTTP - HINTERNET (session)
|
||||
/// </remarks>
|
||||
/// <param name="callback">A user callback allowing for customization of the session</param>
|
||||
void set_nativesessionhandle_options(const std::function<void(native_handle)>& callback)
|
||||
{
|
||||
m_set_user_nativesessionhandle_options = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a user's callback to allow for customization of the session.
|
||||
/// </summary>
|
||||
/// <remarks>Internal Use Only</remarks>
|
||||
/// <param name="handle">A internal implementation handle.</param>
|
||||
void _invoke_nativesessionhandle_options(native_handle handle) const
|
||||
{
|
||||
if (m_set_user_nativesessionhandle_options) m_set_user_nativesessionhandle_options(handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of platform specific options.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The native_handle is the following type depending on the underlying platform:
|
||||
/// Windows Desktop, WinHTTP - HINTERNET
|
||||
/// Windows Runtime, WinRT - IXMLHTTPRequest2 *
|
||||
/// All other platforms, Boost.Asio:
|
||||
/// https - boost::asio::ssl::stream<boost::asio::ip::tcp::socket &> *
|
||||
/// http - boost::asio::ip::tcp::socket *
|
||||
/// </remarks>
|
||||
/// <param name="callback">A user callback allowing for customization of the request</param>
|
||||
void set_nativehandle_options(const std::function<void(native_handle)>& callback)
|
||||
{
|
||||
m_set_user_nativehandle_options = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a user's callback to allow for customization of the request.
|
||||
/// </summary>
|
||||
/// <param name="handle">A internal implementation handle.</param>
|
||||
void invoke_nativehandle_options(native_handle handle) const
|
||||
{
|
||||
if (m_set_user_nativehandle_options) m_set_user_nativehandle_options(handle);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of the ssl context, at construction time.
|
||||
/// </summary>
|
||||
/// <param name="callback">A user callback allowing for customization of the ssl context at construction
|
||||
/// time.</param>
|
||||
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& callback)
|
||||
{
|
||||
m_ssl_context_callback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user's callback to allow for customization of the ssl context.
|
||||
/// </summary>
|
||||
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
|
||||
{
|
||||
return m_ssl_context_callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TLS extension server name indication (SNI) status.
|
||||
/// </summary>
|
||||
/// <returns>True if TLS server name indication is enabled, false otherwise.</returns>
|
||||
bool is_tlsext_sni_enabled() const { return m_tlsext_sni_enabled; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the TLS extension server name indication (SNI) status.
|
||||
/// </summary>
|
||||
/// <param name="tlsext_sni_enabled">False to disable the TLS (ClientHello) extension for server name indication,
|
||||
/// true otherwise.</param> <remarks>Note: This setting is enabled by default as it is required in most virtual
|
||||
/// hosting scenarios.</remarks>
|
||||
void set_tlsext_sni_enabled(bool tlsext_sni_enabled) { m_tlsext_sni_enabled = tlsext_sni_enabled; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if !defined(CPPREST_TARGET_XP)
|
||||
std::shared_ptr<oauth1::experimental::oauth1_config> m_oauth1;
|
||||
#endif
|
||||
|
||||
std::shared_ptr<oauth2::experimental::oauth2_config> m_oauth2;
|
||||
web_proxy m_proxy;
|
||||
http::client::credentials m_credentials;
|
||||
// Whether or not to guarantee ordering, i.e. only using one underlying TCP connection.
|
||||
bool m_guarantee_order;
|
||||
|
||||
std::chrono::microseconds m_timeout;
|
||||
size_t m_chunksize;
|
||||
bool m_request_compressed;
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
// IXmlHttpRequest2 doesn't allow configuration of certificate verification.
|
||||
bool m_validate_certificates;
|
||||
#endif
|
||||
|
||||
std::function<void(native_handle)> m_set_user_nativehandle_options;
|
||||
std::function<void(native_handle)> m_set_user_nativesessionhandle_options;
|
||||
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
|
||||
bool m_tlsext_sni_enabled;
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__cplusplus_winrt)
|
||||
bool m_buffer_request;
|
||||
#endif
|
||||
};
|
||||
|
||||
class http_pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP client class, used to maintain a connection to an HTTP service for an extended session.
|
||||
/// </summary>
|
||||
class http_client
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a new http_client connected to specified uri.
|
||||
/// </summary>
|
||||
/// <param name="base_uri">A string representation of the base uri to be used for all requests. Must start with
|
||||
/// either "http://" or "https://"</param>
|
||||
_ASYNCRTIMP http_client(const uri& base_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new http_client connected to specified uri.
|
||||
/// </summary>
|
||||
/// <param name="base_uri">A string representation of the base uri to be used for all requests. Must start with
|
||||
/// either "http://" or "https://"</param> <param name="client_config">The http client configuration object
|
||||
/// containing the possible configuration options to initialize the <c>http_client</c>. </param>
|
||||
_ASYNCRTIMP http_client(const uri& base_uri, const http_client_config& client_config);
|
||||
|
||||
/// <summary>
|
||||
/// Note the destructor doesn't necessarily close the connection and release resources.
|
||||
/// The connection is reference counted with the http_responses.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP ~http_client() CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base URI.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A base URI initialized in constructor
|
||||
/// </returns>
|
||||
_ASYNCRTIMP const uri& base_uri() const;
|
||||
|
||||
/// <summary>
|
||||
/// Get client configuration object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client configuration object.</returns>
|
||||
_ASYNCRTIMP const http_client_config& client_config() const;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an HTTP pipeline stage to the client.
|
||||
/// </summary>
|
||||
/// <param name="handler">A function object representing the pipeline stage.</param>
|
||||
_ASYNCRTIMP void add_handler(const std::function<pplx::task<http_response> __cdecl(
|
||||
http_request, std::shared_ptr<http::http_pipeline_stage>)>& handler);
|
||||
|
||||
/// <summary>
|
||||
/// Adds an HTTP pipeline stage to the client.
|
||||
/// </summary>
|
||||
/// <param name="stage">A shared pointer to a pipeline stage.</param>
|
||||
_ASYNCRTIMP void add_handler(const std::shared_ptr<http::http_pipeline_stage>& stage);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="request">Request to send.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
_ASYNCRTIMP pplx::task<http_response> request(
|
||||
http_request request, const pplx::cancellation_token& token = pplx::cancellation_token::none());
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utility::string_t& path_query_fragment,
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body_data">The data to be used as the message body, represented using the json
|
||||
/// object library.</param> <param name="token">Cancellation token for cancellation of this request
|
||||
/// operation.</param> <returns>An asynchronous operation that is completed once a response from the request is
|
||||
/// received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utility::string_t& path_query_fragment,
|
||||
const json::value& body_data,
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
msg.set_body(body_data);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="content_type">A string holding the MIME type of the message body.</param> <param
|
||||
/// name="body_data">String containing the text to use in the message body.</param> <param name="token">Cancellation
|
||||
/// token for cancellation of this request operation.</param> <returns>An asynchronous operation that is completed
|
||||
/// once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utf8string& path_query_fragment,
|
||||
const utf8string& body_data,
|
||||
const utf8string& content_type = "text/plain; charset=utf-8",
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(body_data, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="content_type">A string holding the MIME type of the message body.</param> <param
|
||||
/// name="body_data">String containing the text to use in the message body.</param> <param name="token">Cancellation
|
||||
/// token for cancellation of this request operation.</param> <returns>An asynchronous operation that is completed
|
||||
/// once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utf8string& path_query_fragment,
|
||||
utf8string&& body_data,
|
||||
const utf8string& content_type = "text/plain; charset=utf-8",
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(std::move(body_data), content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-16 will perform conversion to UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="content_type">A string holding the MIME type of the message body.</param> <param
|
||||
/// name="body_data">String containing the text to use in the message body.</param> <param name="token">Cancellation
|
||||
/// token for cancellation of this request operation.</param> <returns>An asynchronous operation that is completed
|
||||
/// once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method& mtd,
|
||||
const utf16string& path_query_fragment,
|
||||
const utf16string& body_data,
|
||||
const utf16string& content_type = utility::conversions::to_utf16string("text/plain"),
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(body_data, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body_data">String containing the text to use in the message body.</param> <param
|
||||
/// name="token">Cancellation token for cancellation of this request operation.</param> <returns>An asynchronous
|
||||
/// operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utf8string& path_query_fragment,
|
||||
const utf8string& body_data,
|
||||
const pplx::cancellation_token& token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body_data, "text/plain; charset=utf-8", token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body_data">String containing the text to use in the message body.</param> <param
|
||||
/// name="token">Cancellation token for cancellation of this request operation.</param> <returns>An asynchronous
|
||||
/// operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utf8string& path_query_fragment,
|
||||
utf8string&& body_data,
|
||||
const pplx::cancellation_token& token)
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(std::move(body_data), "text/plain; charset=utf-8");
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes
|
||||
/// the character encoding of the string is UTF-16 will perform conversion to UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body_data">String containing the text to use in the message body.</param> <param
|
||||
/// name="token">Cancellation token for cancellation of this request operation.</param> <returns>An asynchronous
|
||||
/// operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utf16string& path_query_fragment,
|
||||
const utf16string& body_data,
|
||||
const pplx::cancellation_token& token)
|
||||
{
|
||||
return request(
|
||||
mtd, path_query_fragment, body_data, ::utility::conversions::to_utf16string("text/plain"), token);
|
||||
}
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body">An asynchronous stream representing the body data.</param> <param
|
||||
/// name="content_type">A string holding the MIME type of the message body.</param> <param name="token">Cancellation
|
||||
/// token for cancellation of this request operation.</param> <returns>A task that is completed once a response from
|
||||
/// the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utility::string_t& path_query_fragment,
|
||||
const concurrency::streams::istream& body,
|
||||
const utility::string_t& content_type = _XPLATSTR("application/octet-stream"),
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
msg.set_body(body, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body">An asynchronous stream representing the body data.</param> <param
|
||||
/// name="token">Cancellation token for cancellation of this request operation.</param> <returns>A task that is
|
||||
/// completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utility::string_t& path_query_fragment,
|
||||
const concurrency::streams::istream& body,
|
||||
const pplx::cancellation_token& token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body, _XPLATSTR("application/octet-stream"), token);
|
||||
}
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body">An asynchronous stream representing the body data.</param> <param
|
||||
/// name="content_length">Size of the message body.</param> <param name="content_type">A string holding the MIME
|
||||
/// type of the message body.</param> <param name="token">Cancellation token for cancellation of this request
|
||||
/// operation.</param> <returns>A task that is completed once a response from the request is received.</returns>
|
||||
/// <remarks>Winrt requires to provide content_length.</remarks>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utility::string_t& path_query_fragment,
|
||||
const concurrency::streams::istream& body,
|
||||
size_t content_length,
|
||||
const utility::string_t& content_type = _XPLATSTR("application/octet-stream"),
|
||||
const pplx::cancellation_token& token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
msg.set_body(body, content_length, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's
|
||||
/// base URI.</param> <param name="body">An asynchronous stream representing the body data.</param> <param
|
||||
/// name="content_length">Size of the message body.</param> <param name="token">Cancellation token for cancellation
|
||||
/// of this request operation.</param> <returns>A task that is completed once a response from the request is
|
||||
/// received.</returns> <remarks>Winrt requires to provide content_length.</remarks>
|
||||
pplx::task<http_response> request(const method& mtd,
|
||||
const utility::string_t& path_query_fragment,
|
||||
const concurrency::streams::istream& body,
|
||||
size_t content_length,
|
||||
const pplx::cancellation_token& token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body, content_length, _XPLATSTR("application/octet-stream"), token);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<::web::http::client::http_pipeline> m_pipeline;
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
extern const utility::char_t* get_with_body_err_msg;
|
||||
#endif
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace client
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
326
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_compression.h
vendored
Normal file
326
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_compression.h
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Compression and decompression interfaces
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace compression
|
||||
{
|
||||
/// <summary>
|
||||
/// Hint as to whether a compress or decompress call is meant to be the last for a particular HTTP request or reply
|
||||
/// </summary>
|
||||
enum operation_hint
|
||||
{
|
||||
is_last, // Used for the expected last compress() call, or for an expected single decompress() call
|
||||
has_more // Used when further compress() calls will be made, or when multiple decompress() calls may be required
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Result structure for asynchronous compression and decompression operations
|
||||
/// </summary>
|
||||
struct operation_result
|
||||
{
|
||||
size_t input_bytes_processed; // From the input buffer
|
||||
size_t output_bytes_produced; // To the output buffer
|
||||
bool done; // For compress, set when 'last' is true and there was enough space to complete compression;
|
||||
// for decompress, set if the end of the decompression stream has been reached
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Compression interface for use with HTTP requests
|
||||
/// </summary>
|
||||
class compress_provider
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual size_t compress(const uint8_t* input,
|
||||
size_t input_size,
|
||||
uint8_t* output,
|
||||
size_t output_size,
|
||||
operation_hint hint,
|
||||
size_t& input_bytes_processed,
|
||||
bool& done) = 0;
|
||||
virtual pplx::task<operation_result> compress(
|
||||
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual ~compress_provider() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Decompression interface for use with HTTP requests
|
||||
/// </summary>
|
||||
class decompress_provider
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual size_t decompress(const uint8_t* input,
|
||||
size_t input_size,
|
||||
uint8_t* output,
|
||||
size_t output_size,
|
||||
operation_hint hint,
|
||||
size_t& input_bytes_processed,
|
||||
bool& done) = 0;
|
||||
virtual pplx::task<operation_result> decompress(
|
||||
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual ~decompress_provider() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Factory interface for compressors for use with received HTTP requests
|
||||
/// </summary>
|
||||
class compress_factory
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual std::unique_ptr<compress_provider> make_compressor() const = 0;
|
||||
virtual ~compress_factory() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Factory interface for decompressors for use with HTTP requests
|
||||
/// </summary>
|
||||
class decompress_factory
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual uint16_t weight() const = 0;
|
||||
virtual std::unique_ptr<decompress_provider> make_decompressor() const = 0;
|
||||
virtual ~decompress_factory() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Built-in compression support
|
||||
/// </summary>
|
||||
namespace builtin
|
||||
{
|
||||
/// <summary>
|
||||
/// Test whether cpprestsdk was built with built-in compression support
|
||||
/// <returns>True if cpprestsdk was built with built-in compression support, and false if not.</returns>
|
||||
/// </summary>
|
||||
_ASYNCRTIMP bool supported();
|
||||
|
||||
/// <summary>
|
||||
// String constants for each built-in compression algorithm, for convenient use with the factory functions
|
||||
/// </summary>
|
||||
namespace algorithm
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
const utility::char_t* const GZIP = _XPLATSTR("gzip");
|
||||
const utility::char_t* const DEFLATE = _XPLATSTR("deflate");
|
||||
const utility::char_t* const BROTLI = _XPLATSTR("br");
|
||||
#else // ^^^ VS2013 and before ^^^ // vvv VS2015+, and everything else vvv
|
||||
constexpr const utility::char_t* const GZIP = _XPLATSTR("gzip");
|
||||
constexpr const utility::char_t* const DEFLATE = _XPLATSTR("deflate");
|
||||
constexpr const utility::char_t* const BROTLI = _XPLATSTR("br");
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Test whether cpprestsdk was built with built-in compression support and
|
||||
/// the supplied string matches a supported built-in algorithm
|
||||
/// <param name="algorithm">The name of the algorithm to test for built-in support.</param>
|
||||
/// <returns>True if cpprestsdk was built with built-in compression support and
|
||||
/// the supplied string matches a supported built-in algorithm, and false if not.</returns>
|
||||
/// <summary>
|
||||
_ASYNCRTIMP bool supported(const utility::string_t& algorithm);
|
||||
} // namespace algorithm
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a built-in compression provider with default parameters by compression algorithm
|
||||
/// name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to instantiate a provider.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_compressor(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a built-in decompression provider with default parameters by compression algorithm
|
||||
/// name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to instantiate a provider.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<decompress_provider> make_decompressor(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to obtain a pointer to a built-in compression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to find a factory.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::shared_ptr<compress_factory> get_compress_factory(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to obtain a pointer to a built-in decompression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to find a factory.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::shared_ptr<decompress_factory> get_decompress_factory(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
// Factory function to instantiate a built-in gzip compression provider with caller-selected parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a gzip compression provider, or to nullptr if the library was built without built-in
|
||||
/// compression support.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_gzip_compressor(int compressionLevel,
|
||||
int method,
|
||||
int strategy,
|
||||
int memLevel);
|
||||
|
||||
/// <summary>
|
||||
// Factory function to instantiate a built-in deflate compression provider with caller-selected parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a deflate compression provider, or to nullptr if the library was built without built-in
|
||||
/// compression support..
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_deflate_compressor(int compressionLevel,
|
||||
int method,
|
||||
int strategy,
|
||||
int memLevel);
|
||||
|
||||
/// <summary>
|
||||
// Factory function to instantiate a built-in Brotli compression provider with caller-selected parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a Brotli compression provider, or to nullptr if the library was built without built-in
|
||||
/// compression support.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_brotli_compressor(
|
||||
uint32_t window, uint32_t quality, uint32_t mode, uint32_t block, uint32_t nomodel, uint32_t hint);
|
||||
} // namespace builtin
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a compression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm supported by the factory. Must match that returned by the
|
||||
/// <c>web::http::compression::compress_provider</c> type instantiated by the factory's make_compressor function.
|
||||
/// The supplied string is copied, and thus need not remain valid once the call returns.</param>
|
||||
/// <param name="make_compressor">A factory function to be used to instantiate a compressor matching the factory's
|
||||
/// reported algorithm.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a generic provider factory implementation configured with the supplied parameters.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method may be used to conveniently instantiate a factory object for a caller-selected <c>compress_provider</c>.
|
||||
/// That provider may be of the caller's own design, or it may be one of the built-in types. As such, this method may
|
||||
/// be helpful when a caller wishes to build vectors containing a mix of custom and built-in providers.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP std::shared_ptr<compress_factory> make_compress_factory(
|
||||
const utility::string_t& algorithm, std::function<std::unique_ptr<compress_provider>()> make_compressor);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a decompression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm supported by the factory. Must match that returned by the
|
||||
/// <c>web::http::compression::decompress_provider</c> type instantiated by the factory's make_decompressor function.
|
||||
/// The supplied string is copied, and thus need not remain valid once the call returns.</param>
|
||||
/// <param name="weight">A numeric weight for the compression algorithm, times 1000, for use as a "quality value" when
|
||||
/// requesting that the server send a compressed response. Valid values are between 0 and 1000, inclusive, where higher
|
||||
/// values indicate more preferred algorithms, and 0 indicates that the algorithm is not allowed; values greater than
|
||||
/// 1000 are treated as 1000.</param>
|
||||
/// <param name="make_decompressor">A factory function to be used to instantiate a decompressor matching the factory's
|
||||
/// reported algorithm.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a generic provider factory implementation configured with the supplied parameters.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method may be used to conveniently instantiate a factory object for a caller-selected
|
||||
/// <c>decompress_provider</c>. That provider may be of the caller's own design, or it may be one of the built-in
|
||||
/// types. As such, this method may be helpful when a caller wishes to change the weights of built-in provider types,
|
||||
/// to use custom providers without explicitly implementing a <c>decompress_factory</c>, or to build vectors containing
|
||||
/// a mix of custom and built-in providers.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP std::shared_ptr<decompress_factory> make_decompress_factory(
|
||||
const utility::string_t& algorithm,
|
||||
uint16_t weight,
|
||||
std::function<std::unique_ptr<decompress_provider>()> make_decompressor);
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Header type enum for use with compressor and decompressor header parsing and building functions
|
||||
/// </summary>
|
||||
enum header_types
|
||||
{
|
||||
transfer_encoding,
|
||||
content_encoding,
|
||||
te,
|
||||
accept_encoding
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate an appropriate compression provider, if any.
|
||||
/// </summary>
|
||||
/// <param name="encoding">A TE or Accept-Encoding header to interpret.</param>
|
||||
/// <param name="type">Specifies the type of header whose contents are in the encoding parameter; valid values are
|
||||
/// <c>header_type::te</c> and <c>header_type::accept_encoding</c>.</param>
|
||||
/// <param name="preferred">A compressor object of the caller's preferred (possibly custom) type, which is used if
|
||||
/// possible.</param>
|
||||
/// <param name="factories">A collection of factory objects for use in construction of an appropriate compressor, if
|
||||
/// any. If empty or not supplied, the set of supported built-in compressors is used.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a compressor object that is acceptable per the supplied header, or to nullptr if no matching
|
||||
/// algorithm is found.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> get_compressor_from_header(
|
||||
const utility::string_t& encoding,
|
||||
header_types type,
|
||||
const std::vector<std::shared_ptr<compress_factory>>& factories = std::vector<std::shared_ptr<compress_factory>>());
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate an appropriate decompression provider, if any.
|
||||
/// </summary>
|
||||
/// <param name="encoding">A Transfer-Encoding or Content-Encoding header to interpret.</param>
|
||||
/// <param name="type">Specifies the type of header whose contents are in the encoding parameter; valid values are
|
||||
/// <c>header_type::transfer_encoding</c> and <c>header_type::content_encoding</c>.</param>
|
||||
/// <param name="factories">A collection of factory objects for use in construction of an appropriate decompressor,
|
||||
/// if any. If empty or not supplied, the set of supported built-in compressors is used.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a decompressor object that is acceptable per the supplied header, or to nullptr if no matching
|
||||
/// algorithm is found.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<decompress_provider> get_decompressor_from_header(
|
||||
const utility::string_t& encoding,
|
||||
header_types type,
|
||||
const std::vector<std::shared_ptr<decompress_factory>>& factories =
|
||||
std::vector<std::shared_ptr<decompress_factory>>());
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to compose a TE or Accept-Encoding header with supported, and possibly ranked, compression
|
||||
/// algorithms.
|
||||
/// </summary>
|
||||
/// <param name="type">Specifies the type of header to be built; valid values are <c>header_type::te</c> and
|
||||
/// <c>header_type::accept_encoding</c>.</param>
|
||||
/// <param name="factories">A collection of factory objects for use in header construction. If empty or not
|
||||
/// supplied, the set of supported built-in compressors is used.</param>
|
||||
/// <returns>
|
||||
/// A well-formed header, without the header name, specifying the acceptable ranked compression types.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP utility::string_t build_supported_header(header_types type,
|
||||
const std::vector<std::shared_ptr<decompress_factory>>& factories =
|
||||
std::vector<std::shared_ptr<decompress_factory>>());
|
||||
} // namespace details
|
||||
} // namespace compression
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
322
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_headers.h
vendored
Normal file
322
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_headers.h
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
/// <summary>
|
||||
/// Binds an individual reference to a string value.
|
||||
/// </summary>
|
||||
/// <typeparam name="key_type">The type of string value.</typeparam>
|
||||
/// <typeparam name="_t">The type of the value to bind to.</typeparam>
|
||||
/// <param name="text">The string value.</param>
|
||||
/// <param name="ref">The value to bind to.</param>
|
||||
/// <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
|
||||
template<typename key_type, typename _t>
|
||||
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release, std::istringstream instead.")
|
||||
bool bind(const key_type& text, _t& ref) // const
|
||||
{
|
||||
utility::istringstream_t iss(text);
|
||||
iss >> ref;
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds an individual reference to a string value.
|
||||
/// This specialization is need because <c>istringstream::>></c> delimits on whitespace.
|
||||
/// </summary>
|
||||
/// <typeparam name="key_type">The type of the string value.</typeparam>
|
||||
/// <param name="text">The string value.</param>
|
||||
/// <param name="ref">The value to bind to.</param>
|
||||
/// <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
|
||||
template<typename key_type>
|
||||
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release.")
|
||||
bool bind(const key_type& text, utility::string_t& ref) // const
|
||||
{
|
||||
ref = text;
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<typename key_type, typename _t>
|
||||
bool bind_impl(const key_type& text, _t& ref)
|
||||
{
|
||||
utility::istringstream_t iss(text);
|
||||
iss.imbue(std::locale::classic());
|
||||
iss >> ref;
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename key_type>
|
||||
bool bind_impl(const key_type& text, utf16string& ref)
|
||||
{
|
||||
ref = utility::conversions::to_utf16string(text);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename key_type>
|
||||
bool bind_impl(const key_type& text, std::string& ref)
|
||||
{
|
||||
ref = utility::conversions::to_utf8string(text);
|
||||
return true;
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// Represents HTTP headers, acts like a map.
|
||||
/// </summary>
|
||||
class http_headers
|
||||
{
|
||||
public:
|
||||
/// Function object to perform case insensitive comparison of wstrings.
|
||||
struct _case_insensitive_cmp
|
||||
{
|
||||
bool operator()(const utility::string_t& str1, const utility::string_t& str2) const
|
||||
{
|
||||
return utility::details::str_iless(str1, str2);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp> inner_container;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// STL-style typedefs
|
||||
/// </summary>
|
||||
typedef inner_container::key_type key_type;
|
||||
typedef inner_container::key_compare key_compare;
|
||||
typedef inner_container::allocator_type allocator_type;
|
||||
typedef inner_container::size_type size_type;
|
||||
typedef inner_container::difference_type difference_type;
|
||||
typedef inner_container::pointer pointer;
|
||||
typedef inner_container::const_pointer const_pointer;
|
||||
typedef inner_container::reference reference;
|
||||
typedef inner_container::const_reference const_reference;
|
||||
typedef inner_container::iterator iterator;
|
||||
typedef inner_container::const_iterator const_iterator;
|
||||
typedef inner_container::reverse_iterator reverse_iterator;
|
||||
typedef inner_container::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an empty set of HTTP headers.
|
||||
/// </summary>
|
||||
http_headers() {}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to copy from.</param>
|
||||
http_headers(const http_headers& other) : m_headers(other.m_headers) {}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to copy from.</param>
|
||||
http_headers& operator=(const http_headers& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_headers = other.m_headers;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to move.</param>
|
||||
http_headers(http_headers&& other) : m_headers(std::move(other.m_headers)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to move.</param>
|
||||
http_headers& operator=(http_headers&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_headers = std::move(other.m_headers);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a header field using the '<<' operator.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <param name="value">The value of the header field.</param>
|
||||
/// <remarks>If the header field exists, the value will be combined as comma separated string.</remarks>
|
||||
template<typename _t1>
|
||||
void add(const key_type& name, const _t1& value)
|
||||
{
|
||||
auto printedValue = utility::conversions::details::print_string(value);
|
||||
auto& mapVal = m_headers[name];
|
||||
if (mapVal.empty())
|
||||
{
|
||||
mapVal = std::move(printedValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapVal.append(_XPLATSTR(", ")).append(std::move(printedValue));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a header field.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
void remove(const key_type& name) { m_headers.erase(name); }
|
||||
|
||||
/// <summary>
|
||||
/// Removes all elements from the headers.
|
||||
/// </summary>
|
||||
void clear() { m_headers.clear(); }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there is a header with the given key.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <returns><c>true</c> if there is a header with the given name, <c>false</c> otherwise.</returns>
|
||||
bool has(const key_type& name) const { return m_headers.find(name) != m_headers.end(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of header fields.
|
||||
/// </summary>
|
||||
/// <returns>Number of header fields.</returns>
|
||||
size_type size() const { return m_headers.size(); }
|
||||
|
||||
/// <summary>
|
||||
/// Tests to see if there are any header fields.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if there are no headers, <c>false</c> otherwise.</returns>
|
||||
bool empty() const { return m_headers.empty(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to header field with given name, if there is no header field one is inserted.
|
||||
/// </summary>
|
||||
utility::string_t& operator[](const key_type& name) { return m_headers[name]; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a header field exists with given name and returns an iterator if found. Otherwise
|
||||
/// and iterator to end is returned.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <returns>An iterator to where the HTTP header is found.</returns>
|
||||
iterator find(const key_type& name) { return m_headers.find(name); }
|
||||
const_iterator find(const key_type& name) const { return m_headers.find(name); }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to match a header field with the given name using the '>>' operator.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <param name="value">The value of the header field.</param>
|
||||
/// <returns><c>true</c> if header field was found and successfully stored in value parameter.</returns>
|
||||
template<typename _t1>
|
||||
bool match(const key_type& name, _t1& value) const
|
||||
{
|
||||
auto iter = m_headers.find(name);
|
||||
if (iter == m_headers.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return web::http::details::bind_impl(iter->second, value) || iter->second.empty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an iterator referring to the first header field.
|
||||
/// </summary>
|
||||
/// <returns>An iterator to the beginning of the HTTP headers</returns>
|
||||
iterator begin() { return m_headers.begin(); }
|
||||
const_iterator begin() const { return m_headers.begin(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an iterator referring to the past-the-end header field.
|
||||
/// </summary>
|
||||
/// <returns>An iterator to the element past the end of the HTTP headers.</returns>
|
||||
iterator end() { return m_headers.end(); }
|
||||
const_iterator end() const { return m_headers.end(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content length of the message.
|
||||
/// </summary>
|
||||
/// <returns>The length of the content.</returns>
|
||||
_ASYNCRTIMP utility::size64_t content_length() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content length of the message.
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the content.</param>
|
||||
_ASYNCRTIMP void set_content_length(utility::size64_t length);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type of the message.
|
||||
/// </summary>
|
||||
/// <returns>The content type of the body.</returns>
|
||||
_ASYNCRTIMP utility::string_t content_type() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content type of the message.
|
||||
/// </summary>
|
||||
/// <param name="type">The content type of the body.</param>
|
||||
_ASYNCRTIMP void set_content_type(utility::string_t type);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cache control header of the message.
|
||||
/// </summary>
|
||||
/// <returns>The cache control header value.</returns>
|
||||
_ASYNCRTIMP utility::string_t cache_control() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the cache control header of the message.
|
||||
/// </summary>
|
||||
/// <param name="control">The cache control header value.</param>
|
||||
_ASYNCRTIMP void set_cache_control(utility::string_t control);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date header of the message.
|
||||
/// </summary>
|
||||
/// <returns>The date header value.</returns>
|
||||
_ASYNCRTIMP utility::string_t date() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the date header of the message.
|
||||
/// </summary>
|
||||
/// <param name="date">The date header value.</param>
|
||||
_ASYNCRTIMP void set_date(const utility::datetime& date);
|
||||
|
||||
private:
|
||||
// Headers are stored in a map with case insensitive key.
|
||||
inner_container m_headers;
|
||||
};
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
342
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_listener.h
vendored
Normal file
342
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_listener.h
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: HTTP listener (server-side) APIs
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_HTTP_LISTENER_H
|
||||
#define CASA_HTTP_LISTENER_H
|
||||
|
||||
#include "cpprest/http_msg.h"
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) || \
|
||||
defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
/// HTTP listener is currently in beta.
|
||||
namespace experimental
|
||||
{
|
||||
/// HTTP server side library.
|
||||
namespace listener
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration class used to set various options when constructing and http_listener instance.
|
||||
/// </summary>
|
||||
class http_listener_config
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Create an http_listener configuration with default options.
|
||||
/// </summary>
|
||||
http_listener_config() : m_timeout(utility::seconds(120)), m_backlog(0) {}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">http_listener_config to copy.</param>
|
||||
http_listener_config(const http_listener_config& other)
|
||||
: m_timeout(other.m_timeout)
|
||||
, m_backlog(other.m_backlog)
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
, m_ssl_context_callback(other.m_ssl_context_callback)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// <summary>
|
||||
/// <param name="other">http_listener_config to move from.</param>
|
||||
http_listener_config(http_listener_config&& other)
|
||||
: m_timeout(std::move(other.m_timeout))
|
||||
, m_backlog(std::move(other.m_backlog))
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
, m_ssl_context_callback(std::move(other.m_ssl_context_callback))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator.
|
||||
/// </summary>
|
||||
/// <returns>http_listener_config instance.</returns>
|
||||
http_listener_config& operator=(const http_listener_config& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
m_timeout = rhs.m_timeout;
|
||||
m_backlog = rhs.m_backlog;
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
m_ssl_context_callback = rhs.m_ssl_context_callback;
|
||||
#endif
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator.
|
||||
/// </summary>
|
||||
/// <returns>http_listener_config instance.</returns>
|
||||
http_listener_config& operator=(http_listener_config&& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
m_timeout = std::move(rhs.m_timeout);
|
||||
m_backlog = std::move(rhs.m_backlog);
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
m_ssl_context_callback = std::move(rhs.m_ssl_context_callback);
|
||||
#endif
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the timeout
|
||||
/// </summary>
|
||||
/// <returns>The timeout (in seconds).</returns>
|
||||
utility::seconds timeout() const { return m_timeout; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout">The timeout (in seconds) used for each send and receive operation on the client.</param>
|
||||
void set_timeout(utility::seconds timeout) { m_timeout = std::move(timeout); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the listen backlog
|
||||
/// </summary>
|
||||
/// <returns>The maximum length of the queue of pending connections, or zero for the implementation
|
||||
/// default.</returns> <remarks>The implementation may not honour this value.</remarks>
|
||||
int backlog() const { return m_backlog; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the listen backlog
|
||||
/// </summary>
|
||||
/// <param name="backlog">The maximum length of the queue of pending connections, or zero for the implementation
|
||||
/// default.</param> <remarks>The implementation may not honour this value.</remarks>
|
||||
void set_backlog(int backlog) { m_backlog = backlog; }
|
||||
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
/// <summary>
|
||||
/// Get the callback of ssl context
|
||||
/// </summary>
|
||||
/// <returns>The function defined by the user of http_listener_config to configure a ssl context.</returns>
|
||||
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
|
||||
{
|
||||
return m_ssl_context_callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the callback of ssl context
|
||||
/// </summary>
|
||||
/// <param name="ssl_context_callback">The function to configure a ssl context which will setup https
|
||||
/// connections.</param>
|
||||
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& ssl_context_callback)
|
||||
{
|
||||
m_ssl_context_callback = ssl_context_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
utility::seconds m_timeout;
|
||||
int m_backlog;
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal class for pointer to implementation design pattern.
|
||||
/// </summary>
|
||||
class http_listener_impl
|
||||
{
|
||||
public:
|
||||
http_listener_impl() : m_closed(true), m_close_task(pplx::task_from_result()) {}
|
||||
|
||||
_ASYNCRTIMP http_listener_impl(http::uri address);
|
||||
_ASYNCRTIMP http_listener_impl(http::uri address, http_listener_config config);
|
||||
|
||||
_ASYNCRTIMP pplx::task<void> open();
|
||||
_ASYNCRTIMP pplx::task<void> close();
|
||||
|
||||
/// <summary>
|
||||
/// Handler for all requests. The HTTP host uses this to dispatch a message to the pipeline.
|
||||
/// </summary>
|
||||
/// <remarks>Only HTTP server implementations should call this API.</remarks>
|
||||
_ASYNCRTIMP void handle_request(http::http_request msg);
|
||||
|
||||
const http::uri& uri() const { return m_uri; }
|
||||
|
||||
const http_listener_config& configuration() const { return m_config; }
|
||||
|
||||
// Handlers
|
||||
std::function<void(http::http_request)> m_all_requests;
|
||||
std::map<http::method, std::function<void(http::http_request)>> m_supported_methods;
|
||||
|
||||
private:
|
||||
// Default implementation for TRACE and OPTIONS.
|
||||
void handle_trace(http::http_request message);
|
||||
void handle_options(http::http_request message);
|
||||
|
||||
// Gets a comma separated string containing the methods supported by this listener.
|
||||
utility::string_t get_supported_methods() const;
|
||||
|
||||
http::uri m_uri;
|
||||
http_listener_config m_config;
|
||||
|
||||
// Used to record that the listener is closed.
|
||||
bool m_closed;
|
||||
pplx::task<void> m_close_task;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A class for listening and processing HTTP requests at a specific URI.
|
||||
/// </summary>
|
||||
class http_listener
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Create a listener from a URI.
|
||||
/// </summary>
|
||||
/// <remarks>The listener will not have been opened when returned.</remarks>
|
||||
/// <param name="address">URI at which the listener should accept requests.</param>
|
||||
http_listener(http::uri address)
|
||||
: m_impl(utility::details::make_unique<details::http_listener_impl>(std::move(address)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a listener with specified URI and configuration.
|
||||
/// </summary>
|
||||
/// <param name="address">URI at which the listener should accept requests.</param>
|
||||
/// <param name="config">Configuration to create listener with.</param>
|
||||
http_listener(http::uri address, http_listener_config config)
|
||||
: m_impl(utility::details::make_unique<details::http_listener_impl>(std::move(address), std::move(config)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
/// <remarks>The resulting listener cannot be used for anything, but is useful to initialize a variable
|
||||
/// that will later be overwritten with a real listener instance.</remarks>
|
||||
http_listener() : m_impl(utility::details::make_unique<details::http_listener_impl>()) {}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor frees any held resources.
|
||||
/// </summary>
|
||||
/// <remarks>Call close() before allowing a listener to be destroyed.</remarks>
|
||||
~http_listener()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
// As a safe guard close the listener if not already done.
|
||||
// Users are required to call close, but this is just a safeguard.
|
||||
try
|
||||
{
|
||||
m_impl->close().wait();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously open the listener, i.e. start accepting requests.
|
||||
/// </summary>
|
||||
/// <returns>A task that will be completed once this listener is actually opened, accepting requests.</returns>
|
||||
pplx::task<void> open() { return m_impl->open(); }
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously stop accepting requests and close all connections.
|
||||
/// </summary>
|
||||
/// <returns>A task that will be completed once this listener is actually closed, no longer accepting
|
||||
/// requests.</returns> <remarks> This function will stop accepting requests and wait for all outstanding handler
|
||||
/// calls to finish before completing the task. Waiting on the task returned from close() within a handler and
|
||||
/// blocking waiting for its result will result in a deadlock.
|
||||
///
|
||||
/// Call close() before allowing a listener to be destroyed.
|
||||
/// </remarks>
|
||||
pplx::task<void> close() { return m_impl->close(); }
|
||||
|
||||
/// <summary>
|
||||
/// Add a general handler to support all requests.
|
||||
/// </summary>
|
||||
/// <param name="handler">Function object to be called for all requests.</param>
|
||||
void support(const std::function<void(http_request)>& handler) { m_impl->m_all_requests = handler; }
|
||||
|
||||
/// <summary>
|
||||
/// Add support for a specific HTTP method.
|
||||
/// </summary>
|
||||
/// <param name="method">An HTTP method.</param>
|
||||
/// <param name="handler">Function object to be called for all requests for the given HTTP method.</param>
|
||||
void support(const http::method& method, const std::function<void(http_request)>& handler)
|
||||
{
|
||||
m_impl->m_supported_methods[method] = handler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the URI of the listener.
|
||||
/// </summary>
|
||||
/// <returns>The URI this listener is for.</returns>
|
||||
const http::uri& uri() const { return m_impl->uri(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the configuration of this listener.
|
||||
/// </summary>
|
||||
/// <returns>Configuration this listener was constructed with.</returns>
|
||||
const http_listener_config& configuration() const { return m_impl->configuration(); }
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">http_listener instance to construct this one from.</param>
|
||||
http_listener(http_listener&& other) : m_impl(std::move(other.m_impl)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator.
|
||||
/// </summary>
|
||||
/// <param name="other">http_listener to replace this one with.</param>
|
||||
http_listener& operator=(http_listener&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_impl = std::move(other.m_impl);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// No copying of listeners.
|
||||
http_listener(const http_listener& other);
|
||||
http_listener& operator=(const http_listener& other);
|
||||
|
||||
std::unique_ptr<details::http_listener_impl> m_impl;
|
||||
};
|
||||
|
||||
} // namespace listener
|
||||
} // namespace experimental
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
#endif
|
||||
1632
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_msg.h
vendored
Normal file
1632
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/http_msg.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
554
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/interopstream.h
vendored
Normal file
554
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/interopstream.h
vendored
Normal file
@ -0,0 +1,554 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Adapter classes for async and STD stream buffers, used to connect std-based and async-based APIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4250)
|
||||
#endif
|
||||
|
||||
namespace Concurrency
|
||||
{
|
||||
namespace streams
|
||||
{
|
||||
template<typename CharType>
|
||||
class stdio_ostream;
|
||||
template<typename CharType>
|
||||
class stdio_istream;
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// The basic_stdio_buffer class serves to support interoperability with STL stream buffers.
|
||||
/// Sitting atop a std::streambuf, which does all the I/O, instances of this class may read
|
||||
/// and write data to standard iostreams. The class itself should not be used in application
|
||||
/// code, it is used by the stream definitions farther down in the header file.
|
||||
/// </summary>
|
||||
template<typename _CharType>
|
||||
class basic_stdio_buffer : public streambuf_state_manager<_CharType>
|
||||
{
|
||||
typedef concurrency::streams::char_traits<_CharType> traits;
|
||||
typedef typename traits::int_type int_type;
|
||||
typedef typename traits::pos_type pos_type;
|
||||
typedef typename traits::off_type off_type;
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
basic_stdio_buffer(_In_ std::basic_streambuf<_CharType>* streambuf, std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<_CharType>(mode), m_buffer(streambuf)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_stdio_buffer()
|
||||
{
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
}
|
||||
|
||||
private:
|
||||
//
|
||||
// The functions overridden below here are documented elsewhere.
|
||||
// See astreambuf.h for further information.
|
||||
//
|
||||
virtual bool can_seek() const { return this->is_open(); }
|
||||
virtual bool has_size() const { return false; }
|
||||
|
||||
virtual size_t in_avail() const { return (size_t)m_buffer->in_avail(); }
|
||||
|
||||
virtual size_t buffer_size(std::ios_base::openmode) const { return 0; }
|
||||
virtual void set_buffer_size(size_t, std::ios_base::openmode) { return; }
|
||||
|
||||
virtual pplx::task<bool> _sync() { return pplx::task_from_result(m_buffer->pubsync() == 0); }
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch) { return pplx::task_from_result(m_buffer->sputc(ch)); }
|
||||
virtual pplx::task<size_t> _putn(const _CharType* ptr, size_t size)
|
||||
{
|
||||
return pplx::task_from_result((size_t)m_buffer->sputn(ptr, size));
|
||||
}
|
||||
|
||||
size_t _sgetn(_Out_writes_(size) _CharType* ptr, _In_ size_t size) const { return m_buffer->sgetn(ptr, size); }
|
||||
virtual size_t _scopy(_Out_writes_(size) _CharType*, _In_ size_t size)
|
||||
{
|
||||
(void)(size);
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_(size) _CharType* ptr, _In_ size_t size)
|
||||
{
|
||||
return pplx::task_from_result((size_t)m_buffer->sgetn(ptr, size));
|
||||
}
|
||||
|
||||
virtual int_type _sbumpc() { return m_buffer->sbumpc(); }
|
||||
virtual int_type _sgetc() { return m_buffer->sgetc(); }
|
||||
|
||||
virtual pplx::task<int_type> _bumpc() { return pplx::task_from_result<int_type>(m_buffer->sbumpc()); }
|
||||
virtual pplx::task<int_type> _getc() { return pplx::task_from_result<int_type>(m_buffer->sgetc()); }
|
||||
virtual pplx::task<int_type> _nextc() { return pplx::task_from_result<int_type>(m_buffer->snextc()); }
|
||||
virtual pplx::task<int_type> _ungetc() { return pplx::task_from_result<int_type>(m_buffer->sungetc()); }
|
||||
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
return m_buffer->pubseekoff(0, std::ios_base::cur, mode);
|
||||
}
|
||||
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode) { return m_buffer->pubseekpos(pos, mode); }
|
||||
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode)
|
||||
{
|
||||
return m_buffer->pubseekoff(off, dir, mode);
|
||||
}
|
||||
|
||||
virtual _CharType* _alloc(size_t) { return nullptr; }
|
||||
virtual void _commit(size_t) {}
|
||||
|
||||
virtual bool acquire(_CharType*&, size_t&) { return false; }
|
||||
virtual void release(_CharType*, size_t) {}
|
||||
|
||||
template<typename CharType>
|
||||
friend class concurrency::streams::stdio_ostream;
|
||||
template<typename CharType>
|
||||
friend class concurrency::streams::stdio_istream;
|
||||
|
||||
std::basic_streambuf<_CharType>* m_buffer;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// stdio_ostream represents an async ostream derived from a standard synchronous stream, as
|
||||
/// defined by the "std" namespace. It is constructed from a reference to a standard stream, which
|
||||
/// must be valid for the lifetime of the asynchronous stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the <c>stdio_ostream</c>.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// Since std streams are not reference-counted, great care must be taken by an application to make
|
||||
/// sure that the std stream does not get destroyed until all uses of the asynchronous stream are
|
||||
/// done and have been serviced.
|
||||
/// </remarks>
|
||||
template<typename CharType>
|
||||
class stdio_ostream : public basic_ostream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source output stream.
|
||||
/// </typeparam>
|
||||
/// <param name="stream">The synchronous stream that this is using for its I/O</param>
|
||||
template<typename AlterCharType>
|
||||
stdio_ostream(std::basic_ostream<AlterCharType>& stream)
|
||||
: basic_ostream<CharType>(
|
||||
streams::streambuf<AlterCharType>(std::shared_ptr<details::basic_stdio_buffer<AlterCharType>>(
|
||||
new details::basic_stdio_buffer<AlterCharType>(stream.rdbuf(), std::ios_base::out))))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
stdio_ostream(const stdio_ostream& other) : basic_ostream<CharType>(other) {}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
/// <returns>A reference to the output stream object that contains the result of the assignment.</returns>
|
||||
stdio_ostream& operator=(const stdio_ostream& other)
|
||||
{
|
||||
basic_ostream<CharType>::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// stdio_istream represents an async istream derived from a standard synchronous stream, as
|
||||
/// defined by the "std" namespace. It is constructed from a reference to a standard stream, which
|
||||
/// must be valid for the lifetime of the asynchronous stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the <c>stdio_istream</c>.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// Since std streams are not reference-counted, great care must be taken by an application to make
|
||||
/// sure that the std stream does not get destroyed until all uses of the asynchronous stream are
|
||||
/// done and have been serviced.
|
||||
/// </remarks>
|
||||
template<typename CharType>
|
||||
class stdio_istream : public basic_istream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source <c>istream</c>
|
||||
/// </typeparam>
|
||||
/// <param name="stream">The synchronous stream that this is using for its I/O</param>
|
||||
template<typename AlterCharType>
|
||||
stdio_istream(std::basic_istream<AlterCharType>& stream)
|
||||
: basic_istream<CharType>(
|
||||
streams::streambuf<AlterCharType>(std::shared_ptr<details::basic_stdio_buffer<AlterCharType>>(
|
||||
new details::basic_stdio_buffer<AlterCharType>(stream.rdbuf(), std::ios_base::in))))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
stdio_istream(const stdio_istream& other) : basic_istream<CharType>(other) {}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
/// <returns>A reference to the input stream object that contains the result of the assignment.</returns>
|
||||
stdio_istream& operator=(const stdio_istream& other)
|
||||
{
|
||||
basic_istream<CharType>::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// IO streams stream buffer implementation used to interface with an async streambuffer underneath.
|
||||
/// Used for implementing the standard synchronous streams that provide interop between std:: and concurrency::streams::
|
||||
/// </summary>
|
||||
template<typename CharType>
|
||||
class basic_async_streambuf : public std::basic_streambuf<CharType>
|
||||
{
|
||||
public:
|
||||
typedef concurrency::streams::char_traits<CharType> traits;
|
||||
typedef typename traits::int_type int_type;
|
||||
typedef typename traits::pos_type pos_type;
|
||||
typedef typename traits::off_type off_type;
|
||||
|
||||
basic_async_streambuf(const streams::streambuf<CharType>& async_buf) : m_buffer(async_buf) {}
|
||||
|
||||
protected:
|
||||
//
|
||||
// The following are the functions in std::basic_streambuf that we need to override.
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Writes one byte to the stream buffer.
|
||||
/// </summary>
|
||||
int_type overflow(int_type ch)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.putc(CharType(ch)).get();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return traits::eof();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one byte from the stream buffer without moving the read position.
|
||||
/// </summary>
|
||||
int_type underflow()
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.getc().get();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return traits::eof();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one byte from the stream buffer and move the read position one character.
|
||||
/// </summary>
|
||||
int_type uflow()
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.bumpc().get();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return traits::eof();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a number of characters from the buffer and place it into the provided memory block.
|
||||
/// </summary>
|
||||
std::streamsize xsgetn(_Out_writes_(count) CharType* ptr, _In_ std::streamsize count)
|
||||
{
|
||||
size_t cnt = size_t(count);
|
||||
size_t read_so_far = 0;
|
||||
|
||||
try
|
||||
{
|
||||
while (read_so_far < cnt)
|
||||
{
|
||||
size_t rd = m_buffer.getn(ptr + read_so_far, cnt - read_so_far).get();
|
||||
read_so_far += rd;
|
||||
if (rd == 0) break;
|
||||
}
|
||||
return read_so_far;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a given number of characters from the provided block into the stream buffer.
|
||||
/// </summary>
|
||||
std::streamsize xsputn(const CharType* ptr, std::streamsize count)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.putn_nocopy(ptr, static_cast<size_t>(count)).get();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronizes with the underlying medium.
|
||||
/// </summary>
|
||||
int sync() // must be int as per std::basic_streambuf
|
||||
{
|
||||
try
|
||||
{
|
||||
m_buffer.sync().wait();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given offset relative to the beginning, end, or current position.
|
||||
/// </summary>
|
||||
pos_type seekoff(off_type offset,
|
||||
std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dir == std::ios_base::cur && offset == 0) // Special case for getting the current position.
|
||||
return m_buffer.getpos(mode);
|
||||
return m_buffer.seekoff(offset, dir, mode);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return (pos_type(-1));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given offset relative to the beginning of the stream.
|
||||
/// </summary>
|
||||
pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.seekpos(pos, mode);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return (pos_type(-1));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
concurrency::streams::streambuf<CharType> m_buffer;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A concrete STL ostream which relies on an asynchronous stream for its I/O.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the stream.
|
||||
/// </typeparam>
|
||||
template<typename CharType>
|
||||
class async_ostream : public std::basic_ostream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source ostream.
|
||||
/// </typeparam>
|
||||
/// <param name="astream">The asynchronous stream whose stream buffer should be used for I/O</param>
|
||||
template<typename AlterCharType>
|
||||
async_ostream(const streams::basic_ostream<AlterCharType>& astream)
|
||||
: std::basic_ostream<CharType>(&m_strbuf), m_strbuf(astream.streambuf())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source <c>streambuf</c>.
|
||||
/// </typeparam>
|
||||
/// <param name="strbuf">The asynchronous stream buffer to use for I/O</param>
|
||||
template<typename AlterCharType>
|
||||
async_ostream(const streams::streambuf<AlterCharType>& strbuf)
|
||||
: std::basic_ostream<CharType>(&m_strbuf), m_strbuf(strbuf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
details::basic_async_streambuf<CharType> m_strbuf;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A concrete STL istream which relies on an asynchronous stream for its I/O.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the stream.
|
||||
/// </typeparam>
|
||||
template<typename CharType>
|
||||
class async_istream : public std::basic_istream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source istream.
|
||||
/// </typeparam>
|
||||
/// <param name="astream">The asynchronous stream whose stream buffer should be used for I/O</param>
|
||||
template<typename AlterCharType>
|
||||
async_istream(const streams::basic_istream<AlterCharType>& astream)
|
||||
: std::basic_istream<CharType>(&m_strbuf), m_strbuf(astream.streambuf())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source <c>streambuf</c>.
|
||||
/// </typeparam>
|
||||
/// <param name="strbuf">The asynchronous stream buffer to use for I/O</param>
|
||||
template<typename AlterCharType>
|
||||
async_istream(const streams::streambuf<AlterCharType>& strbuf)
|
||||
: std::basic_istream<CharType>(&m_strbuf), m_strbuf(strbuf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
details::basic_async_streambuf<CharType> m_strbuf;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A concrete STL istream which relies on an asynchronous stream buffer for its I/O.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the stream.
|
||||
/// </typeparam>
|
||||
template<typename CharType>
|
||||
class async_iostream : public std::basic_iostream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="strbuf">The asynchronous stream buffer to use for I/O</param>
|
||||
async_iostream(const streams::streambuf<CharType>& strbuf)
|
||||
: std::basic_iostream<CharType>(&m_strbuf), m_strbuf(strbuf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
details::basic_async_streambuf<CharType> m_strbuf;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus_winrt)
|
||||
|
||||
/// <summary>
|
||||
/// Static class containing factory functions for WinRT streams implemented on top of Casablanca async streams.
|
||||
/// </summary>
|
||||
/// <remarks>WinRT streams are defined in terms of single-byte characters only.</remarks>
|
||||
class winrt_stream
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a WinRT <c>IInputStream</c> reference from an asynchronous stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A stream buffer based on a single-byte character.</param>
|
||||
/// <returns>A reference to a WinRT <c>IInputStream</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The stream buffer passed in must allow reading.
|
||||
/// The stream buffer is shared with the caller, allowing data to be passed between the two contexts. For
|
||||
/// example, using a <c>producer_consumer_buffer</c>, a Casablanca-based caller can pass data to a WinRT component.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP static Windows::Storage::Streams::IInputStream ^
|
||||
__cdecl create_input_stream(const concurrency::streams::streambuf<uint8_t>& buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a WinRT <c>IOutputStream</c> reference from an asynchronous stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A stream buffer based on a single-byte character.</param>
|
||||
/// <returns>A reference to a WinRT <c>IOutputStream</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The stream buffer passed in must allow writing.
|
||||
/// The stream buffer is shared with the caller, allowing data to be passed between the two contexts. For
|
||||
/// example, using a <c>producer_consumer_buffer</c>, a Casablanca-based caller can retrieve data from a WinRT
|
||||
/// component.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP static Windows::Storage::Streams::IOutputStream ^
|
||||
__cdecl create_output_stream(const concurrency::streams::streambuf<uint8_t>& buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a WinRT <c>IRandomAccessStream reference from an asynchronous input stream.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A stream based on a single-byte character.</param>
|
||||
/// <returns>A reference to a WinRT <c>IRandomAccessStream</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The stream buffer is shared with the caller, allowing data to be passed between the two contexts. For
|
||||
/// example, using a <c>producer_consumer_buffer</c>, a Casablanca-based caller can pass data to and retrieve data
|
||||
/// from a WinRT component.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP static Windows::Storage::Streams::IRandomAccessStream ^
|
||||
__cdecl create_random_access_stream(const concurrency::streams::streambuf<uint8_t>& buffer);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
1786
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/json.h
vendored
Normal file
1786
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/json.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
576
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/oauth1.h
vendored
Normal file
576
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/oauth1.h
vendored
Normal file
@ -0,0 +1,576 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Oauth 1.0
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_OAUTH1_H
|
||||
#define CASA_OAUTH1_H
|
||||
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
// Forward declaration to avoid circular include dependency.
|
||||
class http_client_config;
|
||||
} // namespace client
|
||||
|
||||
/// oAuth 1.0 library.
|
||||
namespace oauth1
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class oauth1_handler;
|
||||
|
||||
// State currently used by oauth1_config to authenticate request.
|
||||
// The state varies for every request (due to timestamp and nonce).
|
||||
// The state also contains extra transmitted protocol parameters during
|
||||
// authorization flow (i.e. 'oauth_callback' or 'oauth_verifier').
|
||||
class oauth1_state
|
||||
{
|
||||
public:
|
||||
oauth1_state(utility::string_t timestamp,
|
||||
utility::string_t nonce,
|
||||
utility::string_t extra_key = utility::string_t(),
|
||||
utility::string_t extra_value = utility::string_t())
|
||||
: m_timestamp(std::move(timestamp))
|
||||
, m_nonce(std::move(nonce))
|
||||
, m_extra_key(std::move(extra_key))
|
||||
, m_extra_value(std::move(extra_value))
|
||||
{
|
||||
}
|
||||
|
||||
const utility::string_t& timestamp() const { return m_timestamp; }
|
||||
void set_timestamp(utility::string_t timestamp) { m_timestamp = std::move(timestamp); }
|
||||
|
||||
const utility::string_t& nonce() const { return m_nonce; }
|
||||
void set_nonce(utility::string_t nonce) { m_nonce = std::move(nonce); }
|
||||
|
||||
const utility::string_t& extra_key() const { return m_extra_key; }
|
||||
void set_extra_key(utility::string_t key) { m_extra_key = std::move(key); }
|
||||
|
||||
const utility::string_t& extra_value() const { return m_extra_value; }
|
||||
void set_extra_value(utility::string_t value) { m_extra_value = std::move(value); }
|
||||
|
||||
private:
|
||||
utility::string_t m_timestamp;
|
||||
utility::string_t m_nonce;
|
||||
utility::string_t m_extra_key;
|
||||
utility::string_t m_extra_value;
|
||||
};
|
||||
|
||||
// Constant strings for OAuth 1.0.
|
||||
typedef utility::string_t oauth1_string;
|
||||
class oauth1_strings
|
||||
{
|
||||
public:
|
||||
#define _OAUTH1_STRINGS
|
||||
#define DAT(a_, b_) _ASYNCRTIMP static const oauth1_string a_;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _OAUTH1_STRINGS
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// oAuth functionality is currently in beta.
|
||||
namespace experimental
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant strings for OAuth 1.0 signature methods.
|
||||
/// </summary>
|
||||
typedef utility::string_t oauth1_method;
|
||||
class oauth1_methods
|
||||
{
|
||||
public:
|
||||
#define _OAUTH1_METHODS
|
||||
#define DAT(a, b) _ASYNCRTIMP static const oauth1_method a;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _OAUTH1_METHODS
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Exception type for OAuth 1.0 errors.
|
||||
/// </summary>
|
||||
class oauth1_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
oauth1_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {}
|
||||
~oauth1_exception() CPPREST_NOEXCEPT {}
|
||||
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 1.0 token and associated information.
|
||||
/// </summary>
|
||||
class oauth1_token
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructs an initially empty invalid access token.
|
||||
/// </summary>
|
||||
oauth1_token() {}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a OAuth1 token from a given access token and secret.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string.</param>
|
||||
/// <param name="secret">Token secret string.</param>
|
||||
oauth1_token(utility::string_t access_token, utility::string_t secret)
|
||||
: m_token(std::move(access_token)), m_secret(std::move(secret))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get access token validity state.
|
||||
/// If true, token is a valid access token.
|
||||
/// </summary>
|
||||
/// <returns>Access token validity state of the token.</returns>
|
||||
bool is_valid_access_token() const { return !(access_token().empty() || secret().empty()); }
|
||||
|
||||
/// <summary>
|
||||
/// Get access token.
|
||||
/// </summary>
|
||||
/// <returns>The access token string.</returns>
|
||||
const utility::string_t& access_token() const { return m_token; }
|
||||
|
||||
/// <summary>
|
||||
/// Set access token.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string to set.</param>
|
||||
void set_access_token(utility::string_t&& access_token) { m_token = std::move(access_token); }
|
||||
|
||||
/// <summary>
|
||||
/// Set access token.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string to set.</param>
|
||||
void set_access_token(const utility::string_t& access_token) { m_token = access_token; }
|
||||
|
||||
/// <summary>
|
||||
/// Get token secret.
|
||||
/// </summary>
|
||||
/// <returns>Token secret string.</returns>
|
||||
const utility::string_t& secret() const { return m_secret; }
|
||||
|
||||
/// <summary>
|
||||
/// Set token secret.
|
||||
/// </summary>
|
||||
/// <param name="secret">Token secret string to set.</param>
|
||||
void set_secret(utility::string_t&& secret) { m_secret = std::move(secret); }
|
||||
|
||||
/// <summary>
|
||||
/// Set token secret.
|
||||
/// </summary>
|
||||
/// <param name="secret">Token secret string to set.</param>
|
||||
void set_secret(const utility::string_t& secret) { m_secret = secret; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves any additional parameters.
|
||||
/// </summary>
|
||||
/// <returns>A map containing the additional parameters.</returns>
|
||||
const std::map<utility::string_t, utility::string_t>& additional_parameters() const
|
||||
{
|
||||
return m_additional_parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a specific parameter additional parameter.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Parameter name.</param>
|
||||
/// <param name="paramValue">Parameter value.</param>
|
||||
void set_additional_parameter(utility::string_t&& paramName, utility::string_t&& paramValue)
|
||||
{
|
||||
m_additional_parameters[std::move(paramName)] = std::move(paramValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a specific parameter additional parameter.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Parameter name.</param>
|
||||
/// <param name="paramValue">Parameter value.</param>
|
||||
void set_additional_parameter(const utility::string_t& paramName, const utility::string_t& paramValue)
|
||||
{
|
||||
m_additional_parameters[paramName] = paramValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all additional parameters.
|
||||
/// </summary>
|
||||
void clear_additional_parameters() { m_additional_parameters.clear(); }
|
||||
|
||||
private:
|
||||
friend class oauth1_config;
|
||||
|
||||
utility::string_t m_token;
|
||||
utility::string_t m_secret;
|
||||
std::map<utility::string_t, utility::string_t> m_additional_parameters;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 1.0 configuration class.
|
||||
/// </summary>
|
||||
class oauth1_config
|
||||
{
|
||||
public:
|
||||
oauth1_config(utility::string_t consumer_key,
|
||||
utility::string_t consumer_secret,
|
||||
utility::string_t temp_endpoint,
|
||||
utility::string_t auth_endpoint,
|
||||
utility::string_t token_endpoint,
|
||||
utility::string_t callback_uri,
|
||||
oauth1_method method,
|
||||
utility::string_t realm = utility::string_t())
|
||||
: m_consumer_key(std::move(consumer_key))
|
||||
, m_consumer_secret(std::move(consumer_secret))
|
||||
, m_temp_endpoint(std::move(temp_endpoint))
|
||||
, m_auth_endpoint(std::move(auth_endpoint))
|
||||
, m_token_endpoint(std::move(token_endpoint))
|
||||
, m_callback_uri(std::move(callback_uri))
|
||||
, m_realm(std::move(realm))
|
||||
, m_method(std::move(method))
|
||||
, m_is_authorization_completed(false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds an authorization URI to be loaded in a web browser/view.
|
||||
/// The URI is built with auth_endpoint() as basis.
|
||||
/// The method creates a task for HTTP request to first obtain a
|
||||
/// temporary token. The authorization URI build based on this token.
|
||||
/// </summary>
|
||||
/// <returns>Authorization URI to be loaded in a web browser/view.</returns>
|
||||
_ASYNCRTIMP pplx::task<utility::string_t> build_authorization_uri();
|
||||
|
||||
/// <summary>
|
||||
/// Fetch an access token based on redirected URI.
|
||||
/// The URI is expected to contain 'oauth_verifier'
|
||||
/// parameter, which is then used to fetch an access token using the
|
||||
/// token_from_verifier() method.
|
||||
/// See: http://tools.ietf.org/html/rfc5849#section-2.2
|
||||
/// The received 'oauth_token' is parsed and verified to match the current token().
|
||||
/// When access token is successfully obtained, set_token() is called, and config is
|
||||
/// ready for use by oauth1_handler.
|
||||
/// </summary>
|
||||
/// <param name="redirected_uri">The URI where web browser/view was redirected after resource owner's
|
||||
/// authorization.</param> <returns>Task that fetches the access token based on redirected URI.</returns>
|
||||
_ASYNCRTIMP pplx::task<void> token_from_redirected_uri(const web::http::uri& redirected_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a task with HTTP request to fetch an access token from the token endpoint.
|
||||
/// The request exchanges a verifier code to an access token.
|
||||
/// If successful, the resulting token is set as active via set_token().
|
||||
/// See: http://tools.ietf.org/html/rfc5849#section-2.3
|
||||
/// </summary>
|
||||
/// <param name="verifier">Verifier received via redirect upon successful authorization.</param>
|
||||
/// <returns>Task that fetches the access token based on the verifier.</returns>
|
||||
pplx::task<void> token_from_verifier(utility::string_t verifier)
|
||||
{
|
||||
return _request_token(_generate_auth_state(details::oauth1_strings::verifier, std::move(verifier)), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a task with HTTP request to fetch an access token from the token endpoint.
|
||||
/// If successful, the resulting token is set as active via set_token().
|
||||
/// </summary>
|
||||
/// <returns>Task that fetches the access token based on the verifier.</returns>
|
||||
pplx::task<void> refresh_token(const utility::string_t& key)
|
||||
{
|
||||
return _request_token(_generate_auth_state(key, m_token.additional_parameters().at(key)), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get consumer key used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <returns>Consumer key string.</returns>
|
||||
const utility::string_t& consumer_key() const { return m_consumer_key; }
|
||||
/// <summary>
|
||||
/// Set consumer key used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <param name="key">Consumer key string to set.</param>
|
||||
void set_consumer_key(utility::string_t key) { m_consumer_key = std::move(key); }
|
||||
|
||||
/// <summary>
|
||||
/// Get consumer secret used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <returns>Consumer secret string.</returns>
|
||||
const utility::string_t& consumer_secret() const { return m_consumer_secret; }
|
||||
/// <summary>
|
||||
/// Set consumer secret used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <param name="secret">Consumer secret string to set.</param>
|
||||
void set_consumer_secret(utility::string_t secret) { m_consumer_secret = std::move(secret); }
|
||||
|
||||
/// <summary>
|
||||
/// Get temporary token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Temporary token endpoint URI string.</returns>
|
||||
const utility::string_t& temp_endpoint() const { return m_temp_endpoint; }
|
||||
/// <summary>
|
||||
/// Set temporary token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="temp_endpoint">Temporary token endpoint URI string to set.</param>
|
||||
void set_temp_endpoint(utility::string_t temp_endpoint) { m_temp_endpoint = std::move(temp_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Authorization endpoint URI string.</returns>
|
||||
const utility::string_t& auth_endpoint() const { return m_auth_endpoint; }
|
||||
/// <summary>
|
||||
/// Set authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="auth_endpoint">Authorization endpoint URI string to set.</param>
|
||||
void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Token endpoint URI string.</returns>
|
||||
const utility::string_t& token_endpoint() const { return m_token_endpoint; }
|
||||
/// <summary>
|
||||
/// Set token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="token_endpoint">Token endpoint URI string to set.</param>
|
||||
void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get callback URI string.
|
||||
/// </summary>
|
||||
/// <returns>Callback URI string.</returns>
|
||||
const utility::string_t& callback_uri() const { return m_callback_uri; }
|
||||
/// <summary>
|
||||
/// Set callback URI string.
|
||||
/// </summary>
|
||||
/// <param name="callback_uri">Callback URI string to set.</param>
|
||||
void set_callback_uri(utility::string_t callback_uri) { m_callback_uri = std::move(callback_uri); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token.
|
||||
/// </summary>
|
||||
/// <returns>Token.</returns>
|
||||
_ASYNCRTIMP const oauth1_token& token() const;
|
||||
|
||||
/// <summary>
|
||||
/// Set token.
|
||||
/// </summary>
|
||||
/// <param name="token">Token to set.</param>
|
||||
void set_token(oauth1_token token)
|
||||
{
|
||||
m_token = std::move(token);
|
||||
m_is_authorization_completed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get signature method.
|
||||
/// </summary>
|
||||
/// <returns>Signature method.</returns>
|
||||
const oauth1_method& method() const { return m_method; }
|
||||
/// <summary>
|
||||
/// Set signature method.
|
||||
/// </summary>
|
||||
/// <param name="method">Signature method.</param>
|
||||
void set_method(oauth1_method method) { m_method = std::move(method); }
|
||||
|
||||
/// <summary>
|
||||
/// Get authentication realm.
|
||||
/// </summary>
|
||||
/// <returns>Authentication realm string.</returns>
|
||||
const utility::string_t& realm() const { return m_realm; }
|
||||
/// <summary>
|
||||
/// Set authentication realm.
|
||||
/// </summary>
|
||||
/// <param name="realm">Authentication realm string to set.</param>
|
||||
void set_realm(utility::string_t realm) { m_realm = std::move(realm); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns enabled state of the configuration.
|
||||
/// The oauth1_handler will perform OAuth 1.0 authentication only if
|
||||
/// this method returns true.
|
||||
/// Return value is true if access token is valid (=fetched or manually set)
|
||||
/// and both consumer_key() and consumer_secret() are set (=non-empty).
|
||||
/// </summary>
|
||||
/// <returns>The configuration enabled state.</returns>
|
||||
bool is_enabled() const
|
||||
{
|
||||
return token().is_valid_access_token() && !(consumer_key().empty() || consumer_secret().empty());
|
||||
}
|
||||
|
||||
// Builds signature base string according to:
|
||||
// http://tools.ietf.org/html/rfc5849#section-3.4.1.1
|
||||
_ASYNCRTIMP utility::string_t _build_signature_base_string(http_request request, details::oauth1_state state) const;
|
||||
|
||||
// Builds HMAC-SHA1 signature according to:
|
||||
// http://tools.ietf.org/html/rfc5849#section-3.4.2
|
||||
utility::string_t _build_hmac_sha1_signature(http_request request, details::oauth1_state state) const
|
||||
{
|
||||
auto text(_build_signature_base_string(std::move(request), std::move(state)));
|
||||
auto digest(_hmac_sha1(_build_key(), std::move(text)));
|
||||
auto signature(utility::conversions::to_base64(std::move(digest)));
|
||||
return signature;
|
||||
}
|
||||
|
||||
// Builds PLAINTEXT signature according to:
|
||||
// http://tools.ietf.org/html/rfc5849#section-3.4.4
|
||||
utility::string_t _build_plaintext_signature() const { return _build_key(); }
|
||||
|
||||
details::oauth1_state _generate_auth_state(utility::string_t extra_key, utility::string_t extra_value)
|
||||
{
|
||||
return details::oauth1_state(
|
||||
_generate_timestamp(), _generate_nonce(), std::move(extra_key), std::move(extra_value));
|
||||
}
|
||||
|
||||
details::oauth1_state _generate_auth_state()
|
||||
{
|
||||
return details::oauth1_state(_generate_timestamp(), _generate_nonce());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets map of parameters to sign.
|
||||
/// </summary>
|
||||
/// <returns>Map of parameters.</returns>
|
||||
const std::map<utility::string_t, utility::string_t>& parameters() const { return m_parameters_to_sign; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a key value parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">Key as a string value.</param>
|
||||
/// <param name="value">Value as a string value.</param>
|
||||
void add_parameter(const utility::string_t& key, const utility::string_t& value)
|
||||
{
|
||||
m_parameters_to_sign[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a key value parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">Key as a string value.</param>
|
||||
/// <param name="value">Value as a string value.</param>
|
||||
void add_parameter(utility::string_t&& key, utility::string_t&& value)
|
||||
{
|
||||
m_parameters_to_sign[std::move(key)] = std::move(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets entire map or parameters replacing all previously values.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Map of values.</param>
|
||||
void set_parameters(const std::map<utility::string_t, utility::string_t>& parameters)
|
||||
{
|
||||
m_parameters_to_sign.clear();
|
||||
m_parameters_to_sign = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all parameters.
|
||||
/// </summary>
|
||||
void clear_parameters() { m_parameters_to_sign.clear(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the web proxy object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the web proxy object.</returns>
|
||||
const web_proxy& proxy() const { return m_proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the web proxy object that will be used by token_from_code and token_from_refresh
|
||||
/// </summary>
|
||||
/// <param name="proxy">A reference to the web proxy object.</param>
|
||||
void set_proxy(const web_proxy& proxy) { m_proxy = proxy; }
|
||||
|
||||
private:
|
||||
friend class web::http::client::http_client_config;
|
||||
friend class web::http::oauth1::details::oauth1_handler;
|
||||
|
||||
oauth1_config() : m_is_authorization_completed(false) {}
|
||||
|
||||
utility::string_t _generate_nonce() { return m_nonce_generator.generate(); }
|
||||
|
||||
static utility::string_t _generate_timestamp()
|
||||
{
|
||||
return utility::conversions::details::to_string_t(utility::datetime::utc_timestamp());
|
||||
}
|
||||
|
||||
_ASYNCRTIMP static std::vector<unsigned char> __cdecl _hmac_sha1(const utility::string_t& key,
|
||||
const utility::string_t& data);
|
||||
|
||||
static utility::string_t _build_base_string_uri(const uri& u);
|
||||
|
||||
utility::string_t _build_normalized_parameters(web::http::uri u, const details::oauth1_state& state) const;
|
||||
|
||||
utility::string_t _build_signature(http_request request, details::oauth1_state state) const;
|
||||
|
||||
utility::string_t _build_key() const
|
||||
{
|
||||
return uri::encode_data_string(consumer_secret()) + _XPLATSTR("&") + uri::encode_data_string(m_token.secret());
|
||||
}
|
||||
|
||||
void _authenticate_request(http_request& req) { _authenticate_request(req, _generate_auth_state()); }
|
||||
|
||||
_ASYNCRTIMP void _authenticate_request(http_request& req, details::oauth1_state state);
|
||||
|
||||
_ASYNCRTIMP pplx::task<void> _request_token(details::oauth1_state state, bool is_temp_token_request);
|
||||
|
||||
utility::string_t m_consumer_key;
|
||||
utility::string_t m_consumer_secret;
|
||||
oauth1_token m_token;
|
||||
|
||||
utility::string_t m_temp_endpoint;
|
||||
utility::string_t m_auth_endpoint;
|
||||
utility::string_t m_token_endpoint;
|
||||
utility::string_t m_callback_uri;
|
||||
utility::string_t m_realm;
|
||||
oauth1_method m_method;
|
||||
|
||||
std::map<utility::string_t, utility::string_t> m_parameters_to_sign;
|
||||
|
||||
web::web_proxy m_proxy;
|
||||
|
||||
utility::nonce_generator m_nonce_generator;
|
||||
bool m_is_authorization_completed;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
|
||||
namespace details
|
||||
{
|
||||
class oauth1_handler : public http_pipeline_stage
|
||||
{
|
||||
public:
|
||||
oauth1_handler(std::shared_ptr<experimental::oauth1_config> cfg) : m_config(std::move(cfg)) {}
|
||||
|
||||
virtual pplx::task<http_response> propagate(http_request request) override
|
||||
{
|
||||
if (m_config)
|
||||
{
|
||||
m_config->_authenticate_request(request);
|
||||
}
|
||||
return next_stage()->propagate(request);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<experimental::oauth1_config> m_config;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace oauth1
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
540
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/oauth2.h
vendored
Normal file
540
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/oauth2.h
vendored
Normal file
@ -0,0 +1,540 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Oauth 2.0
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_OAUTH2_H
|
||||
#define CASA_OAUTH2_H
|
||||
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
// Forward declaration to avoid circular include dependency.
|
||||
class http_client_config;
|
||||
} // namespace client
|
||||
|
||||
/// oAuth 2.0 library.
|
||||
namespace oauth2
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class oauth2_handler;
|
||||
|
||||
// Constant strings for OAuth 2.0.
|
||||
typedef utility::string_t oauth2_string;
|
||||
class oauth2_strings
|
||||
{
|
||||
public:
|
||||
#define _OAUTH2_STRINGS
|
||||
#define DAT(a_, b_) _ASYNCRTIMP static const oauth2_string a_;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _OAUTH2_STRINGS
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// oAuth functionality is currently in beta.
|
||||
namespace experimental
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception type for OAuth 2.0 errors.
|
||||
/// </summary>
|
||||
class oauth2_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
oauth2_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {}
|
||||
~oauth2_exception() CPPREST_NOEXCEPT {}
|
||||
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 2.0 token and associated information.
|
||||
/// </summary>
|
||||
class oauth2_token
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Value for undefined expiration time in expires_in().
|
||||
/// </summary>
|
||||
enum
|
||||
{
|
||||
undefined_expiration = -1
|
||||
};
|
||||
|
||||
oauth2_token(utility::string_t access_token = utility::string_t())
|
||||
: m_access_token(std::move(access_token)), m_expires_in(undefined_expiration)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get access token validity state.
|
||||
/// If true, access token is a valid.
|
||||
/// </summary>
|
||||
/// <returns>Access token validity state.</returns>
|
||||
bool is_valid_access_token() const { return !access_token().empty(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get access token.
|
||||
/// </summary>
|
||||
/// <returns>Access token string.</returns>
|
||||
const utility::string_t& access_token() const { return m_access_token; }
|
||||
/// <summary>
|
||||
/// Set access token.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string to set.</param>
|
||||
void set_access_token(utility::string_t access_token) { m_access_token = std::move(access_token); }
|
||||
|
||||
/// <summary>
|
||||
/// Get refresh token.
|
||||
/// </summary>
|
||||
/// <returns>Refresh token string.</returns>
|
||||
const utility::string_t& refresh_token() const { return m_refresh_token; }
|
||||
/// <summary>
|
||||
/// Set refresh token.
|
||||
/// </summary>
|
||||
/// <param name="refresh_token">Refresh token string to set.</param>
|
||||
void set_refresh_token(utility::string_t refresh_token) { m_refresh_token = std::move(refresh_token); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token type.
|
||||
/// </summary>
|
||||
/// <returns>Token type string.</returns>
|
||||
const utility::string_t& token_type() const { return m_token_type; }
|
||||
/// <summary>
|
||||
/// Set token type.
|
||||
/// </summary>
|
||||
/// <param name="token_type">Token type string to set.</param>
|
||||
void set_token_type(utility::string_t token_type) { m_token_type = std::move(token_type); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token scope.
|
||||
/// </summary>
|
||||
/// <returns>Token scope string.</returns>
|
||||
const utility::string_t& scope() const { return m_scope; }
|
||||
/// <summary>
|
||||
/// Set token scope.
|
||||
/// </summary>
|
||||
/// <param name="scope">Token scope string to set.</param>
|
||||
void set_scope(utility::string_t scope) { m_scope = std::move(scope); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the lifetime of the access token in seconds.
|
||||
/// For example, 3600 means the access token will expire in one hour from
|
||||
/// the time when access token response was generated by the authorization server.
|
||||
/// Value of undefined_expiration means expiration time is either
|
||||
/// unset or that it was not returned by the server with the access token.
|
||||
/// </summary>
|
||||
/// <returns>Lifetime of the access token in seconds or undefined_expiration if not set.</returns>
|
||||
int64_t expires_in() const { return m_expires_in; }
|
||||
/// <summary>
|
||||
/// Set lifetime of access token (in seconds).
|
||||
/// </summary>
|
||||
/// <param name="expires_in">Lifetime of access token in seconds.</param>
|
||||
void set_expires_in(int64_t expires_in) { m_expires_in = expires_in; }
|
||||
|
||||
private:
|
||||
utility::string_t m_access_token;
|
||||
utility::string_t m_refresh_token;
|
||||
utility::string_t m_token_type;
|
||||
utility::string_t m_scope;
|
||||
int64_t m_expires_in;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 2.0 configuration.
|
||||
///
|
||||
/// Encapsulates functionality for:
|
||||
/// - Authenticating requests with an access token.
|
||||
/// - Performing the OAuth 2.0 authorization code grant authorization flow.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.1
|
||||
/// - Performing the OAuth 2.0 implicit grant authorization flow.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.2
|
||||
///
|
||||
/// Performing OAuth 2.0 authorization:
|
||||
/// 1. Set service and client/app parameters:
|
||||
/// - Client/app key & secret (as provided by the service).
|
||||
/// - The service authorization endpoint and token endpoint.
|
||||
/// - Your client/app redirect URI.
|
||||
/// - Use set_state() to assign a unique state string for the authorization
|
||||
/// session (default: "").
|
||||
/// - If needed, use set_bearer_auth() to control bearer token passing in either
|
||||
/// query or header (default: header). See: http://tools.ietf.org/html/rfc6750#section-2
|
||||
/// - If needed, use set_access_token_key() to set "non-standard" access token
|
||||
/// key (default: "access_token").
|
||||
/// - If needed, use set_implicit_grant() to enable implicit grant flow.
|
||||
/// 2. Build authorization URI with build_authorization_uri() and open this in web browser/control.
|
||||
/// 3. The resource owner should then clicks "Yes" to authorize your client/app, and
|
||||
/// as a result the web browser/control is redirected to redirect_uri().
|
||||
/// 5. Capture the redirected URI either in web control or by HTTP listener.
|
||||
/// 6. Pass the redirected URI to token_from_redirected_uri() to obtain access token.
|
||||
/// - The method ensures redirected URI contains same state() as set in step 1.
|
||||
/// - In implicit_grant() is false, this will create HTTP request to fetch access token
|
||||
/// from the service. Otherwise access token is already included in the redirected URI.
|
||||
///
|
||||
/// Usage for issuing authenticated requests:
|
||||
/// 1. Perform authorization as above to obtain the access token or use an existing token.
|
||||
/// - Some services provide option to generate access tokens for testing purposes.
|
||||
/// 2. Pass the resulting oauth2_config with the access token to http_client_config::set_oauth2().
|
||||
/// 3. Construct http_client with this http_client_config. As a result, all HTTP requests
|
||||
/// by that client will be OAuth 2.0 authenticated.
|
||||
///
|
||||
/// </summary>
|
||||
class oauth2_config
|
||||
{
|
||||
public:
|
||||
oauth2_config(utility::string_t client_key,
|
||||
utility::string_t client_secret,
|
||||
utility::string_t auth_endpoint,
|
||||
utility::string_t token_endpoint,
|
||||
utility::string_t redirect_uri,
|
||||
utility::string_t scope = utility::string_t(),
|
||||
utility::string_t user_agent = utility::string_t())
|
||||
: m_client_key(std::move(client_key))
|
||||
, m_client_secret(std::move(client_secret))
|
||||
, m_auth_endpoint(std::move(auth_endpoint))
|
||||
, m_token_endpoint(std::move(token_endpoint))
|
||||
, m_redirect_uri(std::move(redirect_uri))
|
||||
, m_scope(std::move(scope))
|
||||
, m_user_agent(std::move(user_agent))
|
||||
, m_implicit_grant(false)
|
||||
, m_bearer_auth(true)
|
||||
, m_http_basic_auth(true)
|
||||
, m_access_token_key(details::oauth2_strings::access_token)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds an authorization URI to be loaded in the web browser/view.
|
||||
/// The URI is built with auth_endpoint() as basis.
|
||||
/// The implicit_grant() affects the built URI by selecting
|
||||
/// either authorization code or implicit grant flow.
|
||||
/// You can set generate_state to generate a new random state string.
|
||||
/// </summary>
|
||||
/// <param name="generate_state">If true, a new random state() string is generated
|
||||
/// which replaces the current state(). If false, state() is unchanged and used as-is.</param>
|
||||
/// <returns>Authorization URI string.</returns>
|
||||
_ASYNCRTIMP utility::string_t build_authorization_uri(bool generate_state);
|
||||
|
||||
/// <summary>
|
||||
/// Fetch an access token (and possibly a refresh token) based on redirected URI.
|
||||
/// Behavior depends on the implicit_grant() setting.
|
||||
/// If implicit_grant() is false, the URI is parsed for 'code'
|
||||
/// parameter, and then token_from_code() is called with this code.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.1
|
||||
/// Otherwise, redirect URI fragment part is parsed for 'access_token'
|
||||
/// parameter, which directly contains the token(s).
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.2
|
||||
/// In both cases, the 'state' parameter is parsed and is verified to match state().
|
||||
/// </summary>
|
||||
/// <param name="redirected_uri">The URI where web browser/view was redirected after resource owner's
|
||||
/// authorization.</param> <returns>Task that fetches the token(s) based on redirected URI.</returns>
|
||||
_ASYNCRTIMP pplx::task<void> token_from_redirected_uri(const web::http::uri& redirected_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an access token (and possibly a refresh token) from the token endpoint.
|
||||
/// The task creates an HTTP request to the token_endpoint() which exchanges
|
||||
/// the authorization code for the token(s).
|
||||
/// This also sets the refresh token if one was returned.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.1.3
|
||||
/// </summary>
|
||||
/// <param name="authorization_code">Code received via redirect upon successful authorization.</param>
|
||||
/// <returns>Task that fetches token(s) based on the authorization code.</returns>
|
||||
pplx::task<void> token_from_code(utility::string_t authorization_code)
|
||||
{
|
||||
uri_builder ub;
|
||||
ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::authorization_code, false);
|
||||
ub.append_query(details::oauth2_strings::code, uri::encode_data_string(std::move(authorization_code)), false);
|
||||
ub.append_query(details::oauth2_strings::redirect_uri, uri::encode_data_string(redirect_uri()), false);
|
||||
return _request_token(ub);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches a new access token (and possibly a new refresh token) using the refresh token.
|
||||
/// The task creates a HTTP request to the token_endpoint().
|
||||
/// If successful, resulting access token is set as active via set_token().
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-6
|
||||
/// This also sets a new refresh token if one was returned.
|
||||
/// </summary>
|
||||
/// <returns>Task that fetches the token(s) using the refresh token.</returns>
|
||||
pplx::task<void> token_from_refresh()
|
||||
{
|
||||
uri_builder ub;
|
||||
ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::refresh_token, false);
|
||||
ub.append_query(
|
||||
details::oauth2_strings::refresh_token, uri::encode_data_string(token().refresh_token()), false);
|
||||
return _request_token(ub);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns enabled state of the configuration.
|
||||
/// The oauth2_handler will perform OAuth 2.0 authentication only if
|
||||
/// this method returns true.
|
||||
/// Return value is true if access token is valid (=fetched or manually set).
|
||||
/// </summary>
|
||||
/// <returns>The configuration enabled state.</returns>
|
||||
bool is_enabled() const { return token().is_valid_access_token(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get client key.
|
||||
/// </summary>
|
||||
/// <returns>Client key string.</returns>
|
||||
const utility::string_t& client_key() const { return m_client_key; }
|
||||
/// <summary>
|
||||
/// Set client key.
|
||||
/// </summary>
|
||||
/// <param name="client_key">Client key string to set.</param>
|
||||
void set_client_key(utility::string_t client_key) { m_client_key = std::move(client_key); }
|
||||
|
||||
/// <summary>
|
||||
/// Get client secret.
|
||||
/// </summary>
|
||||
/// <returns>Client secret string.</returns>
|
||||
const utility::string_t& client_secret() const { return m_client_secret; }
|
||||
/// <summary>
|
||||
/// Set client secret.
|
||||
/// </summary>
|
||||
/// <param name="client_secret">Client secret string to set.</param>
|
||||
void set_client_secret(utility::string_t client_secret) { m_client_secret = std::move(client_secret); }
|
||||
|
||||
/// <summary>
|
||||
/// Get authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Authorization endpoint URI string.</returns>
|
||||
const utility::string_t& auth_endpoint() const { return m_auth_endpoint; }
|
||||
/// <summary>
|
||||
/// Set authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="auth_endpoint">Authorization endpoint URI string to set.</param>
|
||||
void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Token endpoint URI string.</returns>
|
||||
const utility::string_t& token_endpoint() const { return m_token_endpoint; }
|
||||
/// <summary>
|
||||
/// Set token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="token_endpoint">Token endpoint URI string to set.</param>
|
||||
void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get redirect URI string.
|
||||
/// </summary>
|
||||
/// <returns>Redirect URI string.</returns>
|
||||
const utility::string_t& redirect_uri() const { return m_redirect_uri; }
|
||||
/// <summary>
|
||||
/// Set redirect URI string.
|
||||
/// </summary>
|
||||
/// <param name="redirect_uri">Redirect URI string to set.</param>
|
||||
void set_redirect_uri(utility::string_t redirect_uri) { m_redirect_uri = std::move(redirect_uri); }
|
||||
|
||||
/// <summary>
|
||||
/// Get scope used in authorization for token.
|
||||
/// </summary>
|
||||
/// <returns>Scope string used in authorization.</returns>
|
||||
const utility::string_t& scope() const { return m_scope; }
|
||||
/// <summary>
|
||||
/// Set scope for authorization for token.
|
||||
/// </summary>
|
||||
/// <param name="scope">Scope string for authorization for token.</param>
|
||||
void set_scope(utility::string_t scope) { m_scope = std::move(scope); }
|
||||
|
||||
/// <summary>
|
||||
/// Get client state string used in authorization.
|
||||
/// </summary>
|
||||
/// <returns>Client state string used in authorization.</returns>
|
||||
const utility::string_t& state() { return m_state; }
|
||||
/// <summary>
|
||||
/// Set client state string for authorization for token.
|
||||
/// The state string is used in authorization for security reasons
|
||||
/// (to uniquely identify authorization sessions).
|
||||
/// If desired, suitably secure state string can be automatically generated
|
||||
/// by build_authorization_uri().
|
||||
/// A good state string consist of 30 or more random alphanumeric characters.
|
||||
/// </summary>
|
||||
/// <param name="state">Client authorization state string to set.</param>
|
||||
void set_state(utility::string_t state) { m_state = std::move(state); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token.
|
||||
/// </summary>
|
||||
/// <returns>Token.</returns>
|
||||
const oauth2_token& token() const { return m_token; }
|
||||
/// <summary>
|
||||
/// Set token.
|
||||
/// </summary>
|
||||
/// <param name="token">Token to set.</param>
|
||||
void set_token(oauth2_token token) { m_token = std::move(token); }
|
||||
|
||||
/// <summary>
|
||||
/// Get implicit grant setting for authorization.
|
||||
/// </summary>
|
||||
/// <returns>Implicit grant setting for authorization.</returns>
|
||||
bool implicit_grant() const { return m_implicit_grant; }
|
||||
/// <summary>
|
||||
/// Set implicit grant setting for authorization.
|
||||
/// False means authorization code grant is used for authorization.
|
||||
/// True means implicit grant is used.
|
||||
/// Default: False.
|
||||
/// </summary>
|
||||
/// <param name="implicit_grant">The implicit grant setting to set.</param>
|
||||
void set_implicit_grant(bool implicit_grant) { m_implicit_grant = implicit_grant; }
|
||||
|
||||
/// <summary>
|
||||
/// Get bearer token authentication setting.
|
||||
/// </summary>
|
||||
/// <returns>Bearer token authentication setting.</returns>
|
||||
bool bearer_auth() const { return m_bearer_auth; }
|
||||
/// <summary>
|
||||
/// Set bearer token authentication setting.
|
||||
/// This must be selected based on what the service accepts.
|
||||
/// True means access token is passed in the request header. (http://tools.ietf.org/html/rfc6750#section-2.1)
|
||||
/// False means access token in passed in the query parameters. (http://tools.ietf.org/html/rfc6750#section-2.3)
|
||||
/// Default: True.
|
||||
/// </summary>
|
||||
/// <param name="bearer_auth">The bearer token authentication setting to set.</param>
|
||||
void set_bearer_auth(bool bearer_auth) { m_bearer_auth = bearer_auth; }
|
||||
|
||||
/// <summary>
|
||||
/// Get HTTP Basic authentication setting for token endpoint.
|
||||
/// </summary>
|
||||
/// <returns>HTTP Basic authentication setting for token endpoint.</returns>
|
||||
bool http_basic_auth() const { return m_http_basic_auth; }
|
||||
/// <summary>
|
||||
/// Set HTTP Basic authentication setting for token endpoint.
|
||||
/// This setting must be selected based on what the service accepts.
|
||||
/// True means HTTP Basic authentication is used for the token endpoint.
|
||||
/// False means client key & secret are passed in the HTTP request body.
|
||||
/// Default: True.
|
||||
/// </summary>
|
||||
/// <param name="http_basic_auth">The HTTP Basic authentication setting to set.</param>
|
||||
void set_http_basic_auth(bool http_basic_auth) { m_http_basic_auth = http_basic_auth; }
|
||||
|
||||
/// <summary>
|
||||
/// Get access token key.
|
||||
/// </summary>
|
||||
/// <returns>Access token key string.</returns>
|
||||
const utility::string_t& access_token_key() const { return m_access_token_key; }
|
||||
/// <summary>
|
||||
/// Set access token key.
|
||||
/// If the service requires a "non-standard" key you must set it here.
|
||||
/// Default: "access_token".
|
||||
/// </summary>
|
||||
void set_access_token_key(utility::string_t access_token_key) { m_access_token_key = std::move(access_token_key); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the web proxy object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the web proxy object.</returns>
|
||||
const web_proxy& proxy() const { return m_proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the web proxy object that will be used by token_from_code and token_from_refresh
|
||||
/// </summary>
|
||||
/// <param name="proxy">A reference to the web proxy object.</param>
|
||||
void set_proxy(const web_proxy& proxy) { m_proxy = proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Get user agent to be used in oauth2 flows.
|
||||
/// </summary>
|
||||
/// <returns>User agent string.</returns>
|
||||
const utility::string_t& user_agent() const { return m_user_agent; }
|
||||
/// <summary>
|
||||
/// Set user agent to be used in oauth2 flows.
|
||||
/// If none is provided a default user agent is provided.
|
||||
/// </summary>
|
||||
void set_user_agent(utility::string_t user_agent) { m_user_agent = std::move(user_agent); }
|
||||
|
||||
private:
|
||||
friend class web::http::client::http_client_config;
|
||||
friend class web::http::oauth2::details::oauth2_handler;
|
||||
|
||||
oauth2_config() : m_implicit_grant(false), m_bearer_auth(true), m_http_basic_auth(true) {}
|
||||
|
||||
_ASYNCRTIMP pplx::task<void> _request_token(uri_builder& request_body);
|
||||
|
||||
oauth2_token _parse_token_from_json(const json::value& token_json);
|
||||
|
||||
void _authenticate_request(http_request& req) const
|
||||
{
|
||||
if (bearer_auth())
|
||||
{
|
||||
req.headers().add(header_names::authorization, _XPLATSTR("Bearer ") + token().access_token());
|
||||
}
|
||||
else
|
||||
{
|
||||
uri_builder ub(req.request_uri());
|
||||
ub.append_query(access_token_key(), token().access_token());
|
||||
req.set_request_uri(ub.to_uri());
|
||||
}
|
||||
}
|
||||
|
||||
utility::string_t m_client_key;
|
||||
utility::string_t m_client_secret;
|
||||
utility::string_t m_auth_endpoint;
|
||||
utility::string_t m_token_endpoint;
|
||||
utility::string_t m_redirect_uri;
|
||||
utility::string_t m_scope;
|
||||
utility::string_t m_state;
|
||||
utility::string_t m_user_agent;
|
||||
|
||||
web::web_proxy m_proxy;
|
||||
|
||||
bool m_implicit_grant;
|
||||
bool m_bearer_auth;
|
||||
bool m_http_basic_auth;
|
||||
utility::string_t m_access_token_key;
|
||||
|
||||
oauth2_token m_token;
|
||||
|
||||
utility::nonce_generator m_state_generator;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
|
||||
namespace details
|
||||
{
|
||||
class oauth2_handler : public http_pipeline_stage
|
||||
{
|
||||
public:
|
||||
oauth2_handler(std::shared_ptr<experimental::oauth2_config> cfg) : m_config(std::move(cfg)) {}
|
||||
|
||||
virtual pplx::task<http_response> propagate(http_request request) override
|
||||
{
|
||||
if (m_config)
|
||||
{
|
||||
m_config->_authenticate_request(request);
|
||||
}
|
||||
return next_stage()->propagate(request);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<experimental::oauth2_config> m_config;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace oauth2
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
655
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/producerconsumerstream.h
vendored
Normal file
655
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/producerconsumerstream.h
vendored
Normal file
@ -0,0 +1,655 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* This file defines a basic memory-based stream buffer, which allows consumer / producer pairs to communicate
|
||||
* data via a buffer.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_PRODUCER_CONSUMER_STREAMS_H
|
||||
#define CASA_PRODUCER_CONSUMER_STREAMS_H
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace Concurrency
|
||||
{
|
||||
namespace streams
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// The basic_producer_consumer_buffer class serves as a memory-based steam buffer that supports both writing and
|
||||
/// reading sequences of characters. It can be used as a consumer/producer buffer.
|
||||
/// </summary>
|
||||
template<typename _CharType>
|
||||
class basic_producer_consumer_buffer : public streams::details::streambuf_state_manager<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef typename ::concurrency::streams::char_traits<_CharType> traits;
|
||||
typedef typename basic_streambuf<_CharType>::int_type int_type;
|
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type;
|
||||
typedef typename basic_streambuf<_CharType>::off_type off_type;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_producer_consumer_buffer(size_t alloc_size)
|
||||
: streambuf_state_manager<_CharType>(std::ios_base::out | std::ios_base::in)
|
||||
, m_alloc_size(alloc_size)
|
||||
, m_allocBlock(nullptr)
|
||||
, m_total(0)
|
||||
, m_total_read(0)
|
||||
, m_total_written(0)
|
||||
, m_synced(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_producer_consumer_buffer()
|
||||
{
|
||||
// Note: there is no need to call 'wait()' on the result of close(),
|
||||
// since we happen to know that close() will return without actually
|
||||
// doing anything asynchronously. Should the implementation of _close_write()
|
||||
// change in that regard, this logic may also have to change.
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
|
||||
_ASSERTE(m_requests.empty());
|
||||
m_blocks.clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <c>can_seek<c/> is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const { return 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the stream buffer implementation to buffer or not buffer.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to use for internal buffering, 0 if no buffering should be done.</param>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will silently ignore calls to this function and it
|
||||
/// will not have any effect on what is returned by subsequent calls to <see cref="::buffer_size method"
|
||||
/// />.</remarks>
|
||||
virtual void set_buffer_size(size_t, std::ios_base::openmode = std::ios_base::in) { return; }
|
||||
|
||||
/// <summary>
|
||||
/// For any input stream, <c>in_avail</c> returns the number of characters that are immediately available
|
||||
/// to be consumed without blocking. May be used in conjunction with <cref="::sbumpc method"/> to read data without
|
||||
/// incurring the overhead of using tasks.
|
||||
/// </summary>
|
||||
virtual size_t in_avail() const { return m_total; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current read or write position in the stream.
|
||||
/// </summary>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The current position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the direction parameter defines whether to move the read or the write
|
||||
/// cursor.</remarks>
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
if (((mode & std::ios_base::in) && !this->can_read()) || ((mode & std::ios_base::out) && !this->can_write()))
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
|
||||
if (mode == std::ios_base::in)
|
||||
return (pos_type)m_total_read;
|
||||
else if (mode == std::ios_base::out)
|
||||
return (pos_type)m_total_written;
|
||||
else
|
||||
return (pos_type)traits::eof();
|
||||
}
|
||||
|
||||
// Seeking is not supported
|
||||
virtual pos_type seekpos(pos_type, std::ios_base::openmode) { return (pos_type)traits::eof(); }
|
||||
virtual pos_type seekoff(off_type, std::ios_base::seekdir, std::ios_base::openmode)
|
||||
{
|
||||
return (pos_type)traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a contiguous memory block and returns it.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to allocate.</param>
|
||||
/// <returns>A pointer to a block to write to, null if the stream buffer implementation does not support
|
||||
/// alloc/commit.</returns>
|
||||
virtual _CharType* _alloc(size_t count)
|
||||
{
|
||||
if (!this->can_write())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We always allocate a new block even if the count could be satisfied by
|
||||
// the current write block. While this does lead to wasted space it allows for
|
||||
// easier book keeping
|
||||
|
||||
_ASSERTE(!m_allocBlock);
|
||||
m_allocBlock = std::make_shared<_block>(count);
|
||||
return m_allocBlock->wbegin();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits a block already allocated by the stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to be committed.</param>
|
||||
virtual void _commit(size_t count)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
// The count does not reflect the actual size of the block.
|
||||
// Since we do not allow any more writes to this block it would suffice.
|
||||
// If we ever change the algorithm to reuse blocks then this needs to be revisited.
|
||||
|
||||
_ASSERTE((bool)m_allocBlock);
|
||||
m_allocBlock->update_write_head(count);
|
||||
m_blocks.push_back(m_allocBlock);
|
||||
m_allocBlock = nullptr;
|
||||
|
||||
update_write_head(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the next already allocated contiguous block of data.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A reference to a pointer variable that will hold the address of the block on success.</param>
|
||||
/// <param name="count">The number of contiguous characters available at the address in 'ptr'.</param>
|
||||
/// <returns><c>true</c> if the operation succeeded, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// A return of false does not necessarily indicate that a subsequent read operation would fail, only that
|
||||
/// there is no block to return immediately or that the stream buffer does not support the operation.
|
||||
/// The stream buffer may not de-allocate the block until <see cref="::release method" /> is called.
|
||||
/// If the end of the stream is reached, the function will return <c>true</c>, a null pointer, and a count of zero;
|
||||
/// a subsequent read will not succeed.
|
||||
/// </remarks>
|
||||
virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count)
|
||||
{
|
||||
count = 0;
|
||||
ptr = nullptr;
|
||||
|
||||
if (!this->can_read()) return false;
|
||||
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
if (m_blocks.empty())
|
||||
{
|
||||
// If the write head has been closed then have reached the end of the
|
||||
// stream (return true), otherwise more data could be written later (return false).
|
||||
return !this->can_write();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto block = m_blocks.front();
|
||||
|
||||
count = block->rd_chars_left();
|
||||
ptr = block->rbegin();
|
||||
|
||||
_ASSERTE(ptr != nullptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a block of data acquired using <see cref="::acquire method"/>. This frees the stream buffer to
|
||||
/// de-allocate the memory, if it so desires. Move the read position ahead by the count.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A pointer to the block of data to be released.</param>
|
||||
/// <param name="count">The number of characters that were read.</param>
|
||||
virtual void release(_Out_writes_opt_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
if (ptr == nullptr) return;
|
||||
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
auto block = m_blocks.front();
|
||||
|
||||
_ASSERTE(block->rd_chars_left() >= count);
|
||||
block->m_read += count;
|
||||
|
||||
update_read_head(count);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual pplx::task<bool> _sync()
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
m_synced = in_avail();
|
||||
|
||||
fulfill_outstanding();
|
||||
|
||||
return pplx::task_from_result(true);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch)
|
||||
{
|
||||
return pplx::task_from_result((this->write(&ch, 1) == 1) ? static_cast<int_type>(ch) : traits::eof());
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _putn(const _CharType* ptr, size_t count)
|
||||
{
|
||||
return pplx::task_from_result<size_t>(this->write(ptr, count));
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
pplx::task_completion_event<size_t> tce;
|
||||
enqueue_request(_request(count, [this, ptr, count, tce]() {
|
||||
// VS 2010 resolves read to a global function. Explicit
|
||||
// invocation through the "this" pointer fixes the issue.
|
||||
tce.set(this->read(ptr, count));
|
||||
}));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
virtual size_t _sgetn(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(count) ? this->read(ptr, count) : (size_t)traits::requires_async();
|
||||
}
|
||||
|
||||
virtual size_t _scopy(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(count) ? this->read(ptr, count, false) : (size_t)traits::requires_async();
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _bumpc()
|
||||
{
|
||||
pplx::task_completion_event<int_type> tce;
|
||||
enqueue_request(_request(1, [this, tce]() { tce.set(this->read_byte(true)); }));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
virtual int_type _sbumpc()
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(1) ? this->read_byte(true) : traits::requires_async();
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _getc()
|
||||
{
|
||||
pplx::task_completion_event<int_type> tce;
|
||||
enqueue_request(_request(1, [this, tce]() { tce.set(this->read_byte(false)); }));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
int_type _sgetc()
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(1) ? this->read_byte(false) : traits::requires_async();
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _nextc()
|
||||
{
|
||||
pplx::task_completion_event<int_type> tce;
|
||||
enqueue_request(_request(1, [this, tce]() {
|
||||
this->read_byte(true);
|
||||
tce.set(this->read_byte(false));
|
||||
}));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _ungetc() { return pplx::task_from_result<int_type>(traits::eof()); }
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Close the stream buffer for writing
|
||||
/// </summary>
|
||||
pplx::task<void> _close_write()
|
||||
{
|
||||
// First indicate that there could be no more writes.
|
||||
// Fulfill outstanding relies on that to flush all the
|
||||
// read requests.
|
||||
this->m_stream_can_write = false;
|
||||
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(this->m_lock);
|
||||
|
||||
// This runs on the thread that called close.
|
||||
this->fulfill_outstanding();
|
||||
}
|
||||
|
||||
return pplx::task_from_result();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the write head by an offset specified by count
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
void update_write_head(size_t count)
|
||||
{
|
||||
m_total += count;
|
||||
m_total_written += count;
|
||||
fulfill_outstanding();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes count characters from ptr into the stream buffer
|
||||
/// </summary>
|
||||
size_t write(const _CharType* ptr, size_t count)
|
||||
{
|
||||
if (!this->can_write() || (count == 0)) return 0;
|
||||
|
||||
// If no one is going to read, why bother?
|
||||
// Just pretend to be writing!
|
||||
if (!this->can_read()) return count;
|
||||
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
// Allocate a new block if necessary
|
||||
if (m_blocks.empty() || m_blocks.back()->wr_chars_left() < count)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> alloc = m_alloc_size.Max(count);
|
||||
m_blocks.push_back(std::make_shared<_block>(alloc));
|
||||
}
|
||||
|
||||
// The block at the back is always the write head
|
||||
auto last = m_blocks.back();
|
||||
auto countWritten = last->write(ptr, count);
|
||||
_ASSERTE(countWritten == count);
|
||||
|
||||
update_write_head(countWritten);
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fulfill pending requests
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
void fulfill_outstanding()
|
||||
{
|
||||
while (!m_requests.empty())
|
||||
{
|
||||
auto req = m_requests.front();
|
||||
|
||||
// If we cannot satisfy the request then we need
|
||||
// to wait for the producer to write data
|
||||
if (!can_satisfy(req.size())) return;
|
||||
|
||||
// We have enough data to satisfy this request
|
||||
req.complete();
|
||||
|
||||
// Remove it from the request queue
|
||||
m_requests.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a memory block
|
||||
/// </summary>
|
||||
class _block
|
||||
{
|
||||
public:
|
||||
_block(size_t size) : m_read(0), m_pos(0), m_size(size), m_data(new _CharType[size]) {}
|
||||
|
||||
~_block() { delete[] m_data; }
|
||||
|
||||
// Read head
|
||||
size_t m_read;
|
||||
|
||||
// Write head
|
||||
size_t m_pos;
|
||||
|
||||
// Allocation size (of m_data)
|
||||
size_t m_size;
|
||||
|
||||
// The data store
|
||||
_CharType* m_data;
|
||||
|
||||
// Pointer to the read head
|
||||
_CharType* rbegin() { return m_data + m_read; }
|
||||
|
||||
// Pointer to the write head
|
||||
_CharType* wbegin() { return m_data + m_pos; }
|
||||
|
||||
// Read up to count characters from the block
|
||||
size_t read(_Out_writes_(count) _CharType* dest, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> avail(rd_chars_left());
|
||||
auto countRead = static_cast<size_t>(avail.Min(count));
|
||||
|
||||
_CharType* beg = rbegin();
|
||||
_CharType* end = rbegin() + countRead;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(beg, end, stdext::checked_array_iterator<_CharType*>(dest, count));
|
||||
#else
|
||||
std::copy(beg, end, dest);
|
||||
#endif // _WIN32
|
||||
|
||||
if (advance)
|
||||
{
|
||||
m_read += countRead;
|
||||
}
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
// Write count characters into the block
|
||||
size_t write(const _CharType* src, size_t count)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> avail(wr_chars_left());
|
||||
auto countWritten = static_cast<size_t>(avail.Min(count));
|
||||
|
||||
const _CharType* srcEnd = src + countWritten;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(src, srcEnd, stdext::checked_array_iterator<_CharType*>(wbegin(), static_cast<size_t>(avail)));
|
||||
#else
|
||||
std::copy(src, srcEnd, wbegin());
|
||||
#endif // _WIN32
|
||||
|
||||
update_write_head(countWritten);
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
void update_write_head(size_t count) { m_pos += count; }
|
||||
|
||||
size_t rd_chars_left() const { return m_pos - m_read; }
|
||||
size_t wr_chars_left() const { return m_size - m_pos; }
|
||||
|
||||
private:
|
||||
// Copy is not supported
|
||||
_block(const _block&);
|
||||
_block& operator=(const _block&);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a request on the stream buffer - typically reads
|
||||
/// </summary>
|
||||
class _request
|
||||
{
|
||||
public:
|
||||
typedef std::function<void()> func_type;
|
||||
_request(size_t count, const func_type& func) : m_func(func), m_count(count) {}
|
||||
|
||||
void complete() { m_func(); }
|
||||
|
||||
size_t size() const { return m_count; }
|
||||
|
||||
private:
|
||||
func_type m_func;
|
||||
size_t m_count;
|
||||
};
|
||||
|
||||
void enqueue_request(_request req)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
if (can_satisfy(req.size()))
|
||||
{
|
||||
// We can immediately fulfill the request.
|
||||
req.complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We must wait for data to arrive.
|
||||
m_requests.push(req);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the request can be satisfied.
|
||||
/// </summary>
|
||||
bool can_satisfy(size_t count) { return (m_synced > 0) || (this->in_avail() >= count) || !this->can_write(); }
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and returns it as int_type.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
int_type read_byte(bool advance = true)
|
||||
{
|
||||
_CharType value;
|
||||
auto read_size = this->read(&value, 1, advance);
|
||||
return read_size == 1 ? static_cast<int_type>(value) : traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to count characters into ptr and returns the count of characters copied.
|
||||
/// The return value (actual characters copied) could be <= count.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
size_t read(_Out_writes_(count) _CharType* ptr, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
_ASSERTE(can_satisfy(count));
|
||||
|
||||
size_t read = 0;
|
||||
|
||||
for (auto iter = begin(m_blocks); iter != std::end(m_blocks); ++iter)
|
||||
{
|
||||
auto block = *iter;
|
||||
auto read_from_block = block->read(ptr + read, count - read, advance);
|
||||
|
||||
read += read_from_block;
|
||||
|
||||
_ASSERTE(count >= read);
|
||||
if (read == count) break;
|
||||
}
|
||||
|
||||
if (advance)
|
||||
{
|
||||
update_read_head(read);
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the read head by the specified offset
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
void update_read_head(size_t count)
|
||||
{
|
||||
m_total -= count;
|
||||
m_total_read += count;
|
||||
|
||||
if (m_synced > 0) m_synced = (m_synced > count) ? (m_synced - count) : 0;
|
||||
|
||||
// The block at the front is always the read head.
|
||||
// Purge empty blocks so that the block at the front reflects the read head
|
||||
while (!m_blocks.empty())
|
||||
{
|
||||
// If front block is not empty - we are done
|
||||
if (m_blocks.front()->rd_chars_left() > 0) break;
|
||||
|
||||
// The block has no more data to be read. Relase the block
|
||||
m_blocks.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// The in/out mode for the buffer
|
||||
std::ios_base::openmode m_mode;
|
||||
|
||||
// Default block size
|
||||
msl::safeint3::SafeInt<size_t> m_alloc_size;
|
||||
|
||||
// Block used for alloc/commit
|
||||
std::shared_ptr<_block> m_allocBlock;
|
||||
|
||||
// Total available data
|
||||
size_t m_total;
|
||||
|
||||
size_t m_total_read;
|
||||
size_t m_total_written;
|
||||
|
||||
// Keeps track of the number of chars that have been flushed but still
|
||||
// remain to be consumed by a read operation.
|
||||
size_t m_synced;
|
||||
|
||||
// The producer-consumer buffer is intended to be used concurrently by a reader
|
||||
// and a writer, who are not coordinating their accesses to the buffer (coordination
|
||||
// being what the buffer is for in the first place). Thus, we have to protect
|
||||
// against some of the internal data elements against concurrent accesses
|
||||
// and the possibility of inconsistent states. A simple non-recursive lock
|
||||
// should be sufficient for those purposes.
|
||||
pplx::extensibility::critical_section_t m_lock;
|
||||
|
||||
// Memory blocks
|
||||
std::deque<std::shared_ptr<_block>> m_blocks;
|
||||
|
||||
// Queue of requests
|
||||
std::queue<_request> m_requests;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The producer_consumer_buffer class serves as a memory-based steam buffer that supports both writing and reading
|
||||
/// sequences of bytes. It can be used as a consumer/producer buffer.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CharType">
|
||||
/// The data type of the basic element of the <c>producer_consumer_buffer</c>.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// This is a reference-counted version of basic_producer_consumer_buffer.</remarks>
|
||||
template<typename _CharType>
|
||||
class producer_consumer_buffer : public streambuf<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a producer_consumer_buffer.
|
||||
/// </summary>
|
||||
/// <param name="alloc_size">The internal default block size.</param>
|
||||
producer_consumer_buffer(size_t alloc_size = 512)
|
||||
: streambuf<_CharType>(std::make_shared<details::basic_producer_consumer_buffer<_CharType>>(alloc_size))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
#endif
|
||||
598
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/rawptrstream.h
vendored
Normal file
598
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/rawptrstream.h
vendored
Normal file
@ -0,0 +1,598 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* This file defines a stream buffer that is based on a raw pointer and block size. Unlike a vector-based
|
||||
* stream buffer, the buffer cannot be expanded or contracted, it has a fixed capacity.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_RAWPTR_STREAMS_H
|
||||
#define CASA_RAWPTR_STREAMS_H
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace Concurrency
|
||||
{
|
||||
namespace streams
|
||||
{
|
||||
// Forward declarations
|
||||
template<typename _CharType>
|
||||
class rawptr_buffer;
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// The basic_rawptr_buffer class serves as a memory-based steam buffer that supports both writing and reading
|
||||
/// sequences of characters to and from a fixed-size block.
|
||||
/// </summary>
|
||||
template<typename _CharType>
|
||||
class basic_rawptr_buffer : public streams::details::streambuf_state_manager<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
|
||||
typedef typename basic_streambuf<_CharType>::traits traits;
|
||||
typedef typename basic_streambuf<_CharType>::int_type int_type;
|
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type;
|
||||
typedef typename basic_streambuf<_CharType>::off_type off_type;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_rawptr_buffer()
|
||||
: streambuf_state_manager<_CharType>(std::ios_base::in | std::ios_base::out)
|
||||
, m_data(nullptr)
|
||||
, m_current_position(0)
|
||||
, m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_rawptr_buffer()
|
||||
{
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// <summary>
|
||||
/// can_seek is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the stream, if known. Calls to <c>has_size</c> will determine whether
|
||||
/// the result of <c>size</c> can be relied on.
|
||||
/// </summary>
|
||||
virtual utility::size64_t size() const { return utility::size64_t(m_size); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const { return 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the stream buffer implementation to buffer or not buffer.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to use for internal buffering, 0 if no buffering should be done.</param>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will silently ignore calls to this function and it
|
||||
/// will not have
|
||||
/// any effect on what is returned by subsequent calls to buffer_size().</remarks>
|
||||
virtual void set_buffer_size(size_t, std::ios_base::openmode = std::ios_base::in) { return; }
|
||||
|
||||
/// <summary>
|
||||
/// For any input stream, in_avail returns the number of characters that are immediately available
|
||||
/// to be consumed without blocking. May be used in conjunction with <cref="::sbumpc method"/> and sgetn() to
|
||||
/// read data without incurring the overhead of using tasks.
|
||||
/// </summary>
|
||||
virtual size_t in_avail() const
|
||||
{
|
||||
// See the comment in seek around the restiction that we do not allow read head to
|
||||
// seek beyond the current size.
|
||||
_ASSERTE(m_current_position <= m_size);
|
||||
|
||||
msl::safeint3::SafeInt<size_t> readhead(m_current_position);
|
||||
msl::safeint3::SafeInt<size_t> writeend(m_size);
|
||||
return (size_t)(writeend - readhead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the stream buffer, preventing further read or write operations.
|
||||
/// </summary>
|
||||
/// <param name="mode">The I/O mode (in or out) to close for.</param>
|
||||
virtual pplx::task<void> close(std::ios_base::openmode mode)
|
||||
{
|
||||
if (mode & std::ios_base::in)
|
||||
{
|
||||
this->_close_read().get(); // Safe to call get() here.
|
||||
}
|
||||
|
||||
if (mode & std::ios_base::out)
|
||||
{
|
||||
this->_close_write().get(); // Safe to call get() here.
|
||||
}
|
||||
|
||||
if (!this->can_read() && !this->can_write())
|
||||
{
|
||||
m_data = nullptr;
|
||||
}
|
||||
|
||||
// Exceptions will be propagated out of _close_read or _close_write
|
||||
return pplx::task_from_result();
|
||||
}
|
||||
|
||||
virtual pplx::task<bool> _sync() { return pplx::task_from_result(true); }
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch)
|
||||
{
|
||||
if (m_current_position >= m_size) return pplx::task_from_result<int_type>(traits::eof());
|
||||
int_type retVal = (this->write(&ch, 1) == 1) ? static_cast<int_type>(ch) : traits::eof();
|
||||
return pplx::task_from_result<int_type>(retVal);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _putn(const _CharType* ptr, size_t count)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> newSize = msl::safeint3::SafeInt<size_t>(count) + m_current_position;
|
||||
if (newSize > m_size)
|
||||
return pplx::task_from_exception<size_t>(
|
||||
std::make_exception_ptr(std::runtime_error("Writing past the end of the buffer")));
|
||||
return pplx::task_from_result<size_t>(this->write(ptr, count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a contiguous memory block and returns it.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to allocate.</param>
|
||||
/// <returns>A pointer to a block to write to, null if the stream buffer implementation does not support
|
||||
/// alloc/commit.</returns>
|
||||
_CharType* _alloc(size_t count)
|
||||
{
|
||||
if (!this->can_write()) return nullptr;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> readhead(m_current_position);
|
||||
msl::safeint3::SafeInt<size_t> writeend(m_size);
|
||||
size_t space_left = (size_t)(writeend - readhead);
|
||||
|
||||
if (space_left < count) return nullptr;
|
||||
|
||||
// Let the caller copy the data
|
||||
return (_CharType*)(m_data + m_current_position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits a block already allocated by the stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to be committed.</param>
|
||||
void _commit(size_t actual)
|
||||
{
|
||||
// Update the write position and satisfy any pending reads
|
||||
update_current_position(m_current_position + actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the next already allocated contiguous block of data.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A reference to a pointer variable that will hold the address of the block on success.</param>
|
||||
/// <param name="count">The number of contiguous characters available at the address in 'ptr'.</param>
|
||||
/// <returns><c>true</c> if the operation succeeded, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// A return of false does not necessarily indicate that a subsequent read operation would fail, only that
|
||||
/// there is no block to return immediately or that the stream buffer does not support the operation.
|
||||
/// The stream buffer may not de-allocate the block until <see cref="::release method" /> is called.
|
||||
/// If the end of the stream is reached, the function will return <c>true</c>, a null pointer, and a count of zero;
|
||||
/// a subsequent read will not succeed.
|
||||
/// </remarks>
|
||||
virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count)
|
||||
{
|
||||
count = 0;
|
||||
ptr = nullptr;
|
||||
|
||||
if (!this->can_read()) return false;
|
||||
|
||||
count = in_avail();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
ptr = (_CharType*)(m_data + m_current_position);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = nullptr;
|
||||
|
||||
// Can only be open for read OR write, not both. If there is no data then
|
||||
// we have reached the end of the stream so indicate such with true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a block of data acquired using <see cref="::acquire method"/>. This frees the stream buffer to
|
||||
/// de-allocate the memory, if it so desires. Move the read position ahead by the count.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A pointer to the block of data to be released.</param>
|
||||
/// <param name="count">The number of characters that were read.</param>
|
||||
virtual void release(_Out_writes_opt_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
if (ptr != nullptr) update_current_position(m_current_position + count);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
return pplx::task_from_result(this->read(ptr, count));
|
||||
}
|
||||
|
||||
size_t _sgetn(_Out_writes_(count) _CharType* ptr, _In_ size_t count) { return this->read(ptr, count); }
|
||||
|
||||
virtual size_t _scopy(_Out_writes_(count) _CharType* ptr, _In_ size_t count)
|
||||
{
|
||||
return this->read(ptr, count, false);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _bumpc() { return pplx::task_from_result(this->read_byte(true)); }
|
||||
|
||||
virtual int_type _sbumpc() { return this->read_byte(true); }
|
||||
|
||||
virtual pplx::task<int_type> _getc() { return pplx::task_from_result(this->read_byte(false)); }
|
||||
|
||||
int_type _sgetc() { return this->read_byte(false); }
|
||||
|
||||
virtual pplx::task<int_type> _nextc()
|
||||
{
|
||||
if (m_current_position >= m_size - 1) return pplx::task_from_result(basic_streambuf<_CharType>::traits::eof());
|
||||
|
||||
this->read_byte(true);
|
||||
return pplx::task_from_result(this->read_byte(false));
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _ungetc()
|
||||
{
|
||||
auto pos = seekoff(-1, std::ios_base::cur, std::ios_base::in);
|
||||
if (pos == (pos_type)traits::eof()) return pplx::task_from_result(traits::eof());
|
||||
return this->getc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current read or write position in the stream.
|
||||
/// </summary>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The current position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the direction parameter defines whether to move the read or the write
|
||||
/// cursor.</remarks>
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
if (((mode & std::ios_base::in) && !this->can_read()) || ((mode & std::ios_base::out) && !this->can_write()))
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
|
||||
if (mode == std::ios_base::in)
|
||||
return (pos_type)m_current_position;
|
||||
else if (mode == std::ios_base::out)
|
||||
return (pos_type)m_current_position;
|
||||
else
|
||||
return (pos_type)traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given position.
|
||||
/// </summary>
|
||||
/// <param name="pos">The offset from the beginning of the stream.</param>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks).</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors. For such streams, the direction parameter
|
||||
/// defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekpos(pos_type position, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg(0);
|
||||
pos_type end(m_size);
|
||||
|
||||
if (position >= beg)
|
||||
{
|
||||
auto pos = static_cast<size_t>(position);
|
||||
|
||||
// Read head
|
||||
if ((mode & std::ios_base::in) && this->can_read())
|
||||
{
|
||||
if (position <= end)
|
||||
{
|
||||
// We do not allow reads to seek beyond the end or before the start position.
|
||||
update_current_position(pos);
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
// Write head
|
||||
if ((mode & std::ios_base::out) && this->can_write())
|
||||
{
|
||||
// Update write head and satisfy read requests if any
|
||||
update_current_position(pos);
|
||||
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to a position given by a relative offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The relative position to seek to</param>
|
||||
/// <param name="way">The starting point (beginning, end, current) for the seek.</param>
|
||||
/// <param name="mode">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the mode parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekoff(off_type offset, std::ios_base::seekdir way, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg = 0;
|
||||
pos_type cur = static_cast<pos_type>(m_current_position);
|
||||
pos_type end = static_cast<pos_type>(m_size);
|
||||
|
||||
switch (way)
|
||||
{
|
||||
case std::ios_base::beg: return seekpos(beg + offset, mode);
|
||||
|
||||
case std::ios_base::cur: return seekpos(cur + offset, mode);
|
||||
|
||||
case std::ios_base::end: return seekpos(end + offset, mode);
|
||||
|
||||
default: return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename _CharType1>
|
||||
friend class ::concurrency::streams::rawptr_buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
basic_rawptr_buffer(const _CharType* data, size_t size)
|
||||
: streambuf_state_manager<_CharType>(std::ios_base::in)
|
||||
, m_data(const_cast<_CharType*>(data))
|
||||
, m_size(size)
|
||||
, m_current_position(0)
|
||||
{
|
||||
validate_mode(std::ios_base::in);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <param name="mode">The stream mode (in, out, etc.).</param>
|
||||
basic_rawptr_buffer(_CharType* data, size_t size, std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<_CharType>(mode), m_data(data), m_size(size), m_current_position(0)
|
||||
{
|
||||
validate_mode(mode);
|
||||
}
|
||||
|
||||
static void validate_mode(std::ios_base::openmode mode)
|
||||
{
|
||||
// Disallow simultaneous use of the stream buffer for writing and reading.
|
||||
if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
|
||||
throw std::invalid_argument("this combination of modes on raw pointer stream not supported");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the request can be satisfied.
|
||||
/// </summary>
|
||||
bool can_satisfy(size_t) const
|
||||
{
|
||||
// We can always satisfy a read, at least partially, unless the
|
||||
// read position is at the very end of the buffer.
|
||||
return (in_avail() > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and returns it as int_type.
|
||||
/// Note: This routine must only be called if can_satisfy() returns true.
|
||||
/// </summary>
|
||||
int_type read_byte(bool advance = true)
|
||||
{
|
||||
_CharType value;
|
||||
auto read_size = this->read(&value, 1, advance);
|
||||
return read_size == 1 ? static_cast<int_type>(value) : traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to count characters into ptr and returns the count of characters copied.
|
||||
/// The return value (actual characters copied) could be <= count.
|
||||
/// Note: This routine must only be called if can_satisfy() returns true.
|
||||
/// </summary>
|
||||
size_t read(_Out_writes_(count) _CharType* ptr, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
if (!can_satisfy(count)) return 0;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> request_size(count);
|
||||
msl::safeint3::SafeInt<size_t> read_size = request_size.Min(in_avail());
|
||||
|
||||
size_t newPos = m_current_position + read_size;
|
||||
|
||||
auto readBegin = m_data + m_current_position;
|
||||
auto readEnd = m_data + newPos;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(readBegin, readEnd, stdext::checked_array_iterator<_CharType*>(ptr, count));
|
||||
#else
|
||||
std::copy(readBegin, readEnd, ptr);
|
||||
#endif // _WIN32
|
||||
|
||||
if (advance)
|
||||
{
|
||||
update_current_position(newPos);
|
||||
}
|
||||
|
||||
return (size_t)read_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write count characters from the ptr into the stream buffer
|
||||
/// </summary>
|
||||
size_t write(const _CharType* ptr, size_t count)
|
||||
{
|
||||
if (!this->can_write() || (count == 0)) return 0;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> newSize = msl::safeint3::SafeInt<size_t>(count) + m_current_position;
|
||||
|
||||
if (newSize > m_size) throw std::runtime_error("Writing past the end of the buffer");
|
||||
|
||||
// Copy the data
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(ptr, ptr + count, stdext::checked_array_iterator<_CharType*>(m_data, m_size, m_current_position));
|
||||
#else
|
||||
std::copy(ptr, ptr + count, m_data + m_current_position);
|
||||
#endif // _WIN32
|
||||
|
||||
// Update write head and satisfy pending reads if any
|
||||
update_current_position(newSize);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current read or write position
|
||||
/// </summary>
|
||||
void update_current_position(size_t newPos)
|
||||
{
|
||||
// The new write head
|
||||
m_current_position = newPos;
|
||||
|
||||
_ASSERTE(m_current_position <= m_size);
|
||||
}
|
||||
|
||||
// The actual memory block
|
||||
_CharType* m_data;
|
||||
|
||||
// The size of the memory block
|
||||
size_t m_size;
|
||||
|
||||
// Read/write head
|
||||
size_t m_current_position;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The <c>rawptr_buffer</c> class serves as a memory-based stream buffer that supports reading
|
||||
/// sequences of characters to or from a fixed-size block. Note that it cannot be used simultaneously for reading as
|
||||
/// well as writing.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CharType">
|
||||
/// The data type of the basic element of the <c>rawptr_buffer</c>.
|
||||
/// </typeparam>
|
||||
template<typename _CharType>
|
||||
class rawptr_buffer : public streambuf<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr_buffer given a pointer to a memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
rawptr_buffer(const char_type* data, size_t size)
|
||||
: streambuf<char_type>(std::shared_ptr<details::basic_rawptr_buffer<char_type>>(
|
||||
new details::basic_rawptr_buffer<char_type>(data, size)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr_buffer given a pointer to a memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
rawptr_buffer(char_type* data, size_t size, std::ios_base::openmode mode = std::ios::out)
|
||||
: streambuf<char_type>(std::shared_ptr<details::basic_rawptr_buffer<char_type>>(
|
||||
new details::basic_rawptr_buffer<char_type>(data, size, mode)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
rawptr_buffer() {}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The rawptr_stream class is used to create memory-backed streams that support writing or reading
|
||||
/// sequences of characters to / from a fixed-size block.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CharType">
|
||||
/// The data type of the basic element of the <c>rawptr_stream</c>.
|
||||
/// </typeparam>
|
||||
template<typename _CharType>
|
||||
class rawptr_stream
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
typedef rawptr_buffer<_CharType> buffer_type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr-stream given a pointer to a read-only memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <returns>An opened input stream.</returns>
|
||||
static concurrency::streams::basic_istream<char_type> open_istream(const char_type* data, size_t size)
|
||||
{
|
||||
return concurrency::streams::basic_istream<char_type>(buffer_type(data, size));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr-stream given a pointer to a writable memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <returns>An opened input stream.</returns>
|
||||
static concurrency::streams::basic_istream<char_type> open_istream(char_type* data, size_t size)
|
||||
{
|
||||
return concurrency::streams::basic_istream<char_type>(buffer_type(data, size, std::ios::in));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr-stream given a pointer to a writable memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <returns>An opened output stream.</returns>
|
||||
static concurrency::streams::basic_ostream<char_type> open_ostream(char_type* data, size_t size)
|
||||
{
|
||||
return concurrency::streams::basic_ostream<char_type>(buffer_type(data, size, std::ios::out));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
#endif
|
||||
1755
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/streams.h
vendored
Normal file
1755
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/streams.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/uri.h
vendored
Normal file
21
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/uri.h
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Protocol independent support for URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_URI_H
|
||||
#define CASA_URI_H
|
||||
|
||||
#include "cpprest/base_uri.h"
|
||||
#include "cpprest/uri_builder.h"
|
||||
|
||||
#endif
|
||||
295
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/uri_builder.h
vendored
Normal file
295
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/uri_builder.h
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Builder style class for creating URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/base_uri.h"
|
||||
#include <string>
|
||||
|
||||
namespace web
|
||||
{
|
||||
/// <summary>
|
||||
/// Builder for constructing URIs incrementally.
|
||||
/// </summary>
|
||||
class uri_builder
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a builder with an initially empty URI.
|
||||
/// </summary>
|
||||
uri_builder() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a builder with a existing URI object.
|
||||
/// </summary>
|
||||
/// <param name="uri_str">Encoded string containing the URI.</param>
|
||||
uri_builder(const uri& uri_str) : m_uri(uri_str.m_components) {}
|
||||
|
||||
/// <summary>
|
||||
/// Get the scheme component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI scheme as a string.</returns>
|
||||
const utility::string_t& scheme() const { return m_uri.m_scheme; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the user information component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI user information as a string.</returns>
|
||||
const utility::string_t& user_info() const { return m_uri.m_user_info; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the host component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI host as a string.</returns>
|
||||
const utility::string_t& host() const { return m_uri.m_host; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the port component of the URI. Returns -1 if no port is specified.
|
||||
/// </summary>
|
||||
/// <returns>The URI port as an integer.</returns>
|
||||
int port() const { return m_uri.m_port; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the path component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI path as a string.</returns>
|
||||
const utility::string_t& path() const { return m_uri.m_path; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the query component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI query as a string.</returns>
|
||||
const utility::string_t& query() const { return m_uri.m_query; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the fragment component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI fragment as a string.</returns>
|
||||
const utility::string_t& fragment() const { return m_uri.m_fragment; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the scheme of the URI.
|
||||
/// </summary>
|
||||
/// <param name="scheme">Uri scheme.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_scheme(const utility::string_t& scheme)
|
||||
{
|
||||
m_uri.m_scheme = scheme;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the user info component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="user_info">User info as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_user_info(const utility::string_t& user_info, bool do_encoding = false)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_user_info = uri::encode_uri(user_info, uri::components::user_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_user_info = user_info;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the host component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="host">Host as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_host(const utility::string_t& host, bool do_encoding = false)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_host = uri::encode_uri(host, uri::components::host);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_host = host;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the port component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="port">Port as an integer.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_port(int port)
|
||||
{
|
||||
m_uri.m_port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the port component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="port">Port as a string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
/// <remarks>When string can't be converted to an integer the port is left unchanged.</remarks>
|
||||
_ASYNCRTIMP uri_builder& set_port(const utility::string_t& port);
|
||||
|
||||
/// <summary>
|
||||
/// Set the path component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="path">Path as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_path(const utility::string_t& path, bool do_encoding = false)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_path = uri::encode_uri(path, uri::components::path);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_path = path;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the query component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="query">Query as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_query(const utility::string_t& query, bool do_encoding = false)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_query = uri::encode_uri(query, uri::components::query);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_query = query;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the fragment component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="fragment">Fragment as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder& set_fragment(const utility::string_t& fragment, bool do_encoding = false)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_fragment = uri::encode_uri(fragment, uri::components::fragment);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_fragment = fragment;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all components of the underlying URI in this uri_builder.
|
||||
/// </summary>
|
||||
void clear() { m_uri = details::uri_components(); }
|
||||
|
||||
/// <summary>
|
||||
/// Appends another path to the path of this uri_builder.
|
||||
/// </summary>
|
||||
/// <param name="path">Path to append as a already encoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder& append_path(const utility::string_t& path, bool do_encoding = false);
|
||||
|
||||
/// <summary>
|
||||
/// Appends the raw contents of the path argument to the path of this uri_builder with no separator de-duplication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The path argument is appended after adding a '/' separator without regards to the contents of path. If an empty
|
||||
/// string is provided, this function will immediately return without changes to the stored path value. For example:
|
||||
/// if the current contents are "/abc" and path="/xyz", the result will be "/abc//xyz".
|
||||
/// </remarks>
|
||||
/// <param name="path">Path to append as a already encoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder& append_path_raw(const utility::string_t& path, bool do_encoding = false);
|
||||
|
||||
/// <summary>
|
||||
/// Appends another query to the query of this uri_builder.
|
||||
/// </summary>
|
||||
/// <param name="query">Query to append as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder& append_query(const utility::string_t& query, bool do_encoding = false);
|
||||
|
||||
/// <summary>
|
||||
/// Appends an relative uri (Path, Query and fragment) at the end of the current uri.
|
||||
/// </summary>
|
||||
/// <param name="relative_uri">The relative uri to append.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder& append(const uri& relative_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Appends another query to the query of this uri_builder, encoding it first. This overload is useful when building
|
||||
/// a query segment of the form "element=10", where the right hand side of the query is stored as a type other than
|
||||
/// a string, for instance, an integral type.
|
||||
/// </summary>
|
||||
/// <param name="name">The name portion of the query string</param>
|
||||
/// <param name="value">The value portion of the query string</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
template<typename T>
|
||||
uri_builder& append_query(const utility::string_t& name, const T& value, bool do_encoding = true)
|
||||
{
|
||||
if (do_encoding)
|
||||
append_query_encode_impl(name, utility::conversions::details::print_utf8string(value));
|
||||
else
|
||||
append_query_no_encode_impl(name, utility::conversions::details::print_string(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combine and validate the URI components into a encoded string. An exception will be thrown if the URI is
|
||||
/// invalid.
|
||||
/// </summary>
|
||||
/// <returns>The created URI as a string.</returns>
|
||||
_ASYNCRTIMP utility::string_t to_string() const;
|
||||
|
||||
/// <summary>
|
||||
/// Combine and validate the URI components into a URI class instance. An exception will be thrown if the URI is
|
||||
/// invalid.
|
||||
/// </summary>
|
||||
/// <returns>The create URI as a URI class instance.</returns>
|
||||
_ASYNCRTIMP uri to_uri() const;
|
||||
|
||||
/// <summary>
|
||||
/// Validate the generated URI from all existing components of this uri_builder.
|
||||
/// </summary>
|
||||
/// <returns>Whether the URI is valid.</returns>
|
||||
_ASYNCRTIMP bool is_valid();
|
||||
|
||||
private:
|
||||
_ASYNCRTIMP void append_query_encode_impl(const utility::string_t& name, const utf8string& value);
|
||||
_ASYNCRTIMP void append_query_no_encode_impl(const utility::string_t& name, const utility::string_t& value);
|
||||
|
||||
details::uri_components m_uri;
|
||||
};
|
||||
} // namespace web
|
||||
10
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/version.h
vendored
Normal file
10
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/version.h
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
*/
|
||||
#define CPPREST_VERSION_MINOR 10
|
||||
#define CPPREST_VERSION_MAJOR 2
|
||||
#define CPPREST_VERSION_REVISION 12
|
||||
|
||||
#define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION)
|
||||
611
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/ws_client.h
vendored
Normal file
611
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/ws_client.h
vendored
Normal file
@ -0,0 +1,611 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Websocket client side implementation
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_WS_CLIENT_H
|
||||
#define CASA_WS_CLIENT_H
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_headers.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "cpprest/ws_msg.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <condition_variable>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#if !defined(_WIN32) || !defined(__cplusplus_winrt)
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#include "boost/asio/ssl.hpp"
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace web
|
||||
{
|
||||
// For backwards compatibility for when in the experimental namespace.
|
||||
// At next major release this should be deleted.
|
||||
namespace experimental = web;
|
||||
|
||||
// In the past namespace was accidentally called 'web_sockets'. To avoid breaking code
|
||||
// alias it. At our next major release this should be deleted.
|
||||
namespace web_sockets = websockets;
|
||||
|
||||
namespace websockets
|
||||
{
|
||||
/// WebSocket client side library.
|
||||
namespace client
|
||||
{
|
||||
/// Websocket close status values.
|
||||
enum class websocket_close_status
|
||||
{
|
||||
normal = 1000,
|
||||
going_away = 1001,
|
||||
protocol_error = 1002,
|
||||
unsupported = 1003, // or data_mismatch
|
||||
abnormal_close = 1006,
|
||||
inconsistent_datatype = 1007,
|
||||
policy_violation = 1008,
|
||||
too_large = 1009,
|
||||
negotiate_error = 1010,
|
||||
server_terminate = 1011,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Websocket client configuration class, used to set the possible configuration options
|
||||
/// used to create an websocket_client instance.
|
||||
/// </summary>
|
||||
class websocket_client_config
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a websocket client configuration with default settings.
|
||||
/// </summary>
|
||||
websocket_client_config() : m_sni_enabled(true), m_validate_certificates(true) {}
|
||||
|
||||
/// <summary>
|
||||
/// Get the web proxy object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the web proxy object.</returns>
|
||||
const web_proxy& proxy() const { return m_proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the web proxy object
|
||||
/// </summary>
|
||||
/// <param name="proxy">The web proxy object.</param>
|
||||
void set_proxy(const web_proxy& proxy) { m_proxy = proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the client credentials
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client credentials.</returns>
|
||||
const web::credentials& credentials() const { return m_credentials; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the client credentials
|
||||
/// </summary>
|
||||
/// <param name="cred">The client credentials.</param>
|
||||
void set_credentials(const web::credentials& cred) { m_credentials = cred; }
|
||||
|
||||
/// <summary>
|
||||
/// Disables Server Name Indication (SNI). Default is on.
|
||||
/// </summary>
|
||||
void disable_sni() { m_sni_enabled = false; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if Server Name Indication (SNI) is enabled.
|
||||
/// </summary>
|
||||
/// <returns>True if enabled, false otherwise.</returns>
|
||||
bool is_sni_enabled() const { return m_sni_enabled; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the server host name to use for TLS Server Name Indication (SNI).
|
||||
/// </summary>
|
||||
/// <remarks>By default the host name is set to the websocket URI host.</remarks>
|
||||
/// <param name="name">The host name to use, as a string.</param>
|
||||
void set_server_name(const utf8string& name) { m_sni_hostname = name; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server host name to use for TLS Server Name Indication (SNI).
|
||||
/// </summary>
|
||||
/// <returns>Host name as a string.</returns>
|
||||
const utf8string& server_name() const { return m_sni_hostname; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the User Agent to be used for the connection
|
||||
/// </summary>
|
||||
/// <param name="name">The User Agent to use, as a string.</param>
|
||||
_ASYNCRTIMP void set_user_agent(const utf8string& user_agent);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers of the HTTP request message used in the WebSocket protocol handshake.
|
||||
/// </summary>
|
||||
/// <returns>HTTP headers for the WebSocket protocol handshake.</returns>
|
||||
/// <remarks>
|
||||
/// Use the <seealso cref="http_headers::add Method"/> to fill in desired headers.
|
||||
/// </remarks>
|
||||
web::http::http_headers& headers() { return m_headers; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a const reference to the headers of the WebSocket protocol handshake HTTP message.
|
||||
/// </summary>
|
||||
/// <returns>HTTP headers.</returns>
|
||||
const web::http::http_headers& headers() const { return m_headers; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a subprotocol to the request headers.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the subprotocol.</param>
|
||||
/// <remarks>If additional subprotocols have already been specified, the new one will just be added.</remarks>
|
||||
_ASYNCRTIMP void add_subprotocol(const ::utility::string_t& name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets list of the specified subprotocols.
|
||||
/// </summary>
|
||||
/// <returns>Vector of all the subprotocols </returns>
|
||||
/// <remarks>If you want all the subprotocols in a comma separated string
|
||||
/// they can be directly looked up in the headers using 'Sec-WebSocket-Protocol'.</remarks>
|
||||
_ASYNCRTIMP std::vector<::utility::string_t> subprotocols() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server certificate validation property.
|
||||
/// </summary>
|
||||
/// <returns>True if certificates are to be verified, false otherwise.</returns>
|
||||
bool validate_certificates() const { return m_validate_certificates; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the server certificate validation property.
|
||||
/// </summary>
|
||||
/// <param name="validate_certs">False to turn ignore all server certificate validation errors, true
|
||||
/// otherwise.</param> <remarks>Note ignoring certificate errors can be dangerous and should be done with
|
||||
/// caution.</remarks>
|
||||
void set_validate_certificates(bool validate_certs) { m_validate_certificates = validate_certs; }
|
||||
|
||||
#if !defined(_WIN32) || !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of the ssl context, at construction time.
|
||||
/// </summary>
|
||||
/// <param name="callback">A user callback allowing for customization of the ssl context at construction
|
||||
/// time.</param>
|
||||
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& callback)
|
||||
{
|
||||
m_ssl_context_callback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user's callback to allow for customization of the ssl context.
|
||||
/// </summary>
|
||||
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
|
||||
{
|
||||
return m_ssl_context_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
web::web_proxy m_proxy;
|
||||
web::credentials m_credentials;
|
||||
web::http::http_headers m_headers;
|
||||
bool m_sni_enabled;
|
||||
utf8string m_sni_hostname;
|
||||
bool m_validate_certificates;
|
||||
#if !defined(_WIN32) || !defined(__cplusplus_winrt)
|
||||
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a websocket error. This class holds an error message and an optional error code.
|
||||
/// </summary>
|
||||
class websocket_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates an <c>websocket_exception</c> with just a string message and no error code.
|
||||
/// </summary>
|
||||
/// <param name="whatArg">Error message string.</param>
|
||||
websocket_exception(const utility::string_t& whatArg) : m_msg(utility::conversions::to_utf8string(whatArg)) {}
|
||||
|
||||
#ifdef _WIN32
|
||||
/// <summary>
|
||||
/// Creates an <c>websocket_exception</c> with just a string message and no error code.
|
||||
/// </summary>
|
||||
/// <param name="whatArg">Error message string.</param>
|
||||
websocket_exception(std::string whatArg) : m_msg(std::move(whatArg)) {}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code using the current platform error category.
|
||||
/// The message of the error code will be used as the what() string message.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
websocket_exception(int errorCode) : m_errorCode(utility::details::create_error_code(errorCode))
|
||||
{
|
||||
m_msg = m_errorCode.message();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code using the current platform error category.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
websocket_exception(int errorCode, const utility::string_t& whatArg)
|
||||
: m_errorCode(utility::details::create_error_code(errorCode))
|
||||
, m_msg(utility::conversions::to_utf8string(whatArg))
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and string message.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
websocket_exception(int errorCode, std::string whatArg)
|
||||
: m_errorCode(utility::details::create_error_code(errorCode)), m_msg(std::move(whatArg))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and string message to use as the what() argument.
|
||||
/// <param name="code">Error code.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
/// </summary>
|
||||
websocket_exception(std::error_code code, std::string whatArg)
|
||||
: m_errorCode(std::move(code)), m_msg(std::move(whatArg))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and category. The message of the error code will be used
|
||||
/// as the <c>what</c> string message.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
/// <param name="cat">Error category for the code.</param>
|
||||
websocket_exception(int errorCode, const std::error_category& cat) : m_errorCode(std::error_code(errorCode, cat))
|
||||
{
|
||||
m_msg = m_errorCode.message();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and string message to use as the what() argument.
|
||||
/// <param name="code">Error code.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
/// </summary>
|
||||
websocket_exception(std::error_code code, const utility::string_t& whatArg)
|
||||
: m_errorCode(std::move(code)), m_msg(utility::conversions::to_utf8string(whatArg))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string identifying the cause of the exception.
|
||||
/// </summary>
|
||||
/// <returns>A null terminated character string.</returns>
|
||||
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying error code for the cause of the exception.
|
||||
/// </summary>
|
||||
/// <returns>The <c>error_code</c> object associated with the exception.</returns>
|
||||
const std::error_code& error_code() const CPPREST_NOEXCEPT { return m_errorCode; }
|
||||
|
||||
private:
|
||||
std::error_code m_errorCode;
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
// Interface to be implemented by the websocket client callback implementations.
|
||||
class websocket_client_callback_impl
|
||||
{
|
||||
public:
|
||||
websocket_client_callback_impl(websocket_client_config config) : m_config(std::move(config)) {}
|
||||
|
||||
virtual ~websocket_client_callback_impl() CPPREST_NOEXCEPT {}
|
||||
|
||||
virtual pplx::task<void> connect() = 0;
|
||||
|
||||
virtual pplx::task<void> send(websocket_outgoing_message& msg) = 0;
|
||||
|
||||
virtual void set_message_handler(const std::function<void(const websocket_incoming_message&)>& handler) = 0;
|
||||
|
||||
virtual pplx::task<void> close() = 0;
|
||||
|
||||
virtual pplx::task<void> close(websocket_close_status close_status,
|
||||
const utility::string_t& close_reason = _XPLATSTR("")) = 0;
|
||||
|
||||
virtual void set_close_handler(
|
||||
const std::function<void(websocket_close_status, const utility::string_t&, const std::error_code&)>&
|
||||
handler) = 0;
|
||||
|
||||
const web::uri& uri() const { return m_uri; }
|
||||
|
||||
void set_uri(const web::uri& uri) { m_uri = uri; }
|
||||
|
||||
const websocket_client_config& config() const { return m_config; }
|
||||
|
||||
static void verify_uri(const web::uri& uri)
|
||||
{
|
||||
// Most of the URI schema validation is taken care by URI class.
|
||||
// We only need to check certain things specific to websockets.
|
||||
if (uri.scheme() != _XPLATSTR("ws") && uri.scheme() != _XPLATSTR("wss"))
|
||||
{
|
||||
throw std::invalid_argument("URI scheme must be 'ws' or 'wss'");
|
||||
}
|
||||
|
||||
if (uri.host().empty())
|
||||
{
|
||||
throw std::invalid_argument("URI must contain a hostname.");
|
||||
}
|
||||
|
||||
// Fragment identifiers are meaningless in the context of WebSocket URIs
|
||||
// and MUST NOT be used on these URIs.
|
||||
if (!uri.fragment().empty())
|
||||
{
|
||||
throw std::invalid_argument("WebSocket URI must not contain fragment identifiers");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
web::uri m_uri;
|
||||
websocket_client_config m_config;
|
||||
};
|
||||
|
||||
// Interface to be implemented by the websocket client task implementations.
|
||||
class websocket_client_task_impl
|
||||
{
|
||||
public:
|
||||
_ASYNCRTIMP websocket_client_task_impl(websocket_client_config config);
|
||||
|
||||
_ASYNCRTIMP virtual ~websocket_client_task_impl() CPPREST_NOEXCEPT;
|
||||
|
||||
_ASYNCRTIMP pplx::task<websocket_incoming_message> receive();
|
||||
|
||||
_ASYNCRTIMP void close_pending_tasks_with_error(const websocket_exception& exc);
|
||||
|
||||
const std::shared_ptr<websocket_client_callback_impl>& callback_client() const { return m_callback_client; };
|
||||
|
||||
private:
|
||||
void set_handler();
|
||||
|
||||
// When a message arrives, if there are tasks waiting for a message, signal the topmost one.
|
||||
// Else enqueue the message in a queue.
|
||||
// m_receive_queue_lock : to guard access to the queue & m_client_closed
|
||||
std::mutex m_receive_queue_lock;
|
||||
// Queue to store incoming messages when there are no tasks waiting for a message
|
||||
std::queue<websocket_incoming_message> m_receive_msg_queue;
|
||||
// Queue to maintain the receive tasks when there are no messages(yet).
|
||||
std::queue<pplx::task_completion_event<websocket_incoming_message>> m_receive_task_queue;
|
||||
|
||||
// Initially set to false, becomes true if a close frame is received from the server or
|
||||
// if the underlying connection is aborted or terminated.
|
||||
bool m_client_closed;
|
||||
|
||||
std::shared_ptr<websocket_client_callback_impl> m_callback_client;
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// Websocket client class, used to maintain a connection to a remote host for an extended session.
|
||||
/// </summary>
|
||||
class websocket_client
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a new websocket_client.
|
||||
/// </summary>
|
||||
websocket_client() : m_client(std::make_shared<details::websocket_client_task_impl>(websocket_client_config())) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new websocket_client.
|
||||
/// </summary>
|
||||
/// <param name="config">The client configuration object containing the possible configuration options to initialize
|
||||
/// the <c>websocket_client</c>. </param>
|
||||
websocket_client(websocket_client_config config)
|
||||
: m_client(std::make_shared<details::websocket_client_task_impl>(std::move(config)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the remote network destination. The connect method initiates the websocket handshake with the
|
||||
/// remote network destination, takes care of the protocol upgrade request.
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri address to connect. </param>
|
||||
/// <returns>An asynchronous operation that is completed once the client has successfully connected to the websocket
|
||||
/// server.</returns>
|
||||
pplx::task<void> connect(const web::uri& uri)
|
||||
{
|
||||
m_client->callback_client()->verify_uri(uri);
|
||||
m_client->callback_client()->set_uri(uri);
|
||||
auto client = m_client;
|
||||
return m_client->callback_client()->connect().then([client](pplx::task<void> result) {
|
||||
try
|
||||
{
|
||||
result.get();
|
||||
}
|
||||
catch (const websocket_exception& ex)
|
||||
{
|
||||
client->close_pending_tasks_with_error(ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a websocket message to the server .
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed once the message is sent.</returns>
|
||||
pplx::task<void> send(websocket_outgoing_message msg) { return m_client->callback_client()->send(msg); }
|
||||
|
||||
/// <summary>
|
||||
/// Receive a websocket message.
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed when a message has been received by the client
|
||||
/// endpoint.</returns>
|
||||
pplx::task<websocket_incoming_message> receive() { return m_client->receive(); }
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the
|
||||
/// server.
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed the connection has been successfully closed.</returns>
|
||||
pplx::task<void> close() { return m_client->callback_client()->close(); }
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the
|
||||
/// server.
|
||||
/// </summary>
|
||||
/// <param name="close_status">Endpoint MAY use the following pre-defined status codes when sending a Close
|
||||
/// frame.</param> <param name="close_reason">While closing an established connection, an endpoint may indicate the
|
||||
/// reason for closure.</param> <returns>An asynchronous operation that is completed the connection has been
|
||||
/// successfully closed.</returns>
|
||||
pplx::task<void> close(websocket_close_status close_status, const utility::string_t& close_reason = _XPLATSTR(""))
|
||||
{
|
||||
return m_client->callback_client()->close(close_status, close_reason);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client URI.
|
||||
/// </summary>
|
||||
/// <returns>URI connected to.</returns>
|
||||
const web::uri& uri() const { return m_client->callback_client()->uri(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client config object.
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client configuration object.</returns>
|
||||
const websocket_client_config& config() const { return m_client->callback_client()->config(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<details::websocket_client_task_impl> m_client;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Websocket client class, used to maintain a connection to a remote host for an extended session, uses callback APIs
|
||||
/// for handling receive and close event instead of async task. For some scenarios would be a alternative for the
|
||||
/// websocket_client like if you want to special handling on close event.
|
||||
/// </summary>
|
||||
class websocket_callback_client
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a new websocket_callback_client.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP websocket_callback_client();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new websocket_callback_client.
|
||||
/// </summary>
|
||||
/// <param name="client_config">The client configuration object containing the possible configuration options to
|
||||
/// initialize the <c>websocket_client</c>. </param>
|
||||
_ASYNCRTIMP websocket_callback_client(websocket_client_config client_config);
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the remote network destination. The connect method initiates the websocket handshake with the
|
||||
/// remote network destination, takes care of the protocol upgrade request.
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri address to connect. </param>
|
||||
/// <returns>An asynchronous operation that is completed once the client has successfully connected to the websocket
|
||||
/// server.</returns>
|
||||
pplx::task<void> connect(const web::uri& uri)
|
||||
{
|
||||
m_client->verify_uri(uri);
|
||||
m_client->set_uri(uri);
|
||||
return m_client->connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a websocket message to the server .
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed once the message is sent.</returns>
|
||||
pplx::task<void> send(websocket_outgoing_message msg) { return m_client->send(msg); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the received handler for notification of client websocket messages.
|
||||
/// </summary>
|
||||
/// <param name="handler">A function representing the incoming websocket messages handler. It's parameters are:
|
||||
/// msg: a <c>websocket_incoming_message</c> value indicating the message received
|
||||
/// </param>
|
||||
/// <remarks>If this handler is not set before connecting incoming messages will be missed.</remarks>
|
||||
void set_message_handler(const std::function<void(const websocket_incoming_message& msg)>& handler)
|
||||
{
|
||||
m_client->set_message_handler(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the
|
||||
/// server.
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed the connection has been successfully closed.</returns>
|
||||
pplx::task<void> close() { return m_client->close(); }
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the
|
||||
/// server.
|
||||
/// </summary>
|
||||
/// <param name="close_status">Endpoint MAY use the following pre-defined status codes when sending a Close
|
||||
/// frame.</param> <param name="close_reason">While closing an established connection, an endpoint may indicate the
|
||||
/// reason for closure.</param> <returns>An asynchronous operation that is completed the connection has been
|
||||
/// successfully closed.</returns>
|
||||
pplx::task<void> close(websocket_close_status close_status, const utility::string_t& close_reason = _XPLATSTR(""))
|
||||
{
|
||||
return m_client->close(close_status, close_reason);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the closed handler for notification of client websocket closing event.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler for websocket closing event, It's parameters are:
|
||||
/// close_status: The pre-defined status codes used by the endpoint when sending a Close frame.
|
||||
/// reason: The reason string used by the endpoint when sending a Close frame.
|
||||
/// error: The error code if the websocket is closed with abnormal error.
|
||||
/// </param>
|
||||
void set_close_handler(const std::function<void(websocket_close_status close_status,
|
||||
const utility::string_t& reason,
|
||||
const std::error_code& error)>& handler)
|
||||
{
|
||||
m_client->set_close_handler(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client URI.
|
||||
/// </summary>
|
||||
/// <returns>URI connected to.</returns>
|
||||
const web::uri& uri() const { return m_client->uri(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client config object.
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client configuration object.</returns>
|
||||
const websocket_client_config& config() const { return m_client->config(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<details::websocket_client_callback_impl> m_client;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace websockets
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
231
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/ws_msg.h
vendored
Normal file
231
packages/cpprestsdk.v141.2.10.12.1/build/native/include/cpprest/ws_msg.h
vendored
Normal file
@ -0,0 +1,231 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Websocket incoming and outgoing message definitions.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/containerstream.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace websockets
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class winrt_callback_client;
|
||||
class wspp_callback_client;
|
||||
#if defined(__cplusplus_winrt)
|
||||
ref class ReceiveContext;
|
||||
#endif
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The different types of websocket message.
|
||||
/// Text type contains UTF-8 encoded data.
|
||||
/// Interpretation of Binary type is left to the application.
|
||||
/// Note: The fragment types and control frames like close, ping, pong are not supported on WinRT.
|
||||
/// </summary>
|
||||
enum class websocket_message_type
|
||||
{
|
||||
text_message,
|
||||
binary_message,
|
||||
close,
|
||||
ping,
|
||||
pong
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents an outgoing websocket message
|
||||
/// </summary>
|
||||
class websocket_outgoing_message
|
||||
{
|
||||
public:
|
||||
#if !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Sets a the outgoing message to be an unsolicited pong message.
|
||||
/// This is useful when the client side wants to check whether the server is alive.
|
||||
/// </summary>
|
||||
void set_pong_message() { this->set_message_pong(); }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="data">UTF-8 String containing body of the message.</param>
|
||||
void set_utf8_message(std::string&& data)
|
||||
{
|
||||
this->set_message(concurrency::streams::container_buffer<std::string>(std::move(data)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="data">UTF-8 String containing body of the message.</param>
|
||||
void set_utf8_message(const std::string& data)
|
||||
{
|
||||
this->set_message(concurrency::streams::container_buffer<std::string>(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">casablanca input stream representing the body of the message.</param>
|
||||
/// <remarks>Upon sending, the entire stream may be buffered to determine the length.</remarks>
|
||||
void set_utf8_message(const concurrency::streams::istream& istream)
|
||||
{
|
||||
this->set_message(istream, SIZE_MAX, websocket_message_type::text_message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">casablanca input stream representing the body of the message.</param>
|
||||
/// <param name="len">number of bytes to send.</param>
|
||||
void set_utf8_message(const concurrency::streams::istream& istream, size_t len)
|
||||
{
|
||||
this->set_message(istream, len, websocket_message_type::text_message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets binary data as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">casablanca input stream representing the body of the message.</param>
|
||||
/// <param name="len">number of bytes to send.</param>
|
||||
void set_binary_message(const concurrency::streams::istream& istream, size_t len)
|
||||
{
|
||||
this->set_message(istream, len, websocket_message_type::binary_message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets binary data as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">Input stream representing the body of the message.</param>
|
||||
/// <remarks>Upon sending, the entire stream may be buffered to determine the length.</remarks>
|
||||
void set_binary_message(const concurrency::streams::istream& istream)
|
||||
{
|
||||
this->set_message(istream, SIZE_MAX, websocket_message_type::binary_message);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class details::winrt_callback_client;
|
||||
friend class details::wspp_callback_client;
|
||||
|
||||
pplx::task_completion_event<void> m_body_sent;
|
||||
concurrency::streams::streambuf<uint8_t> m_body;
|
||||
websocket_message_type m_msg_type;
|
||||
size_t m_length;
|
||||
|
||||
void signal_body_sent() const { m_body_sent.set(); }
|
||||
|
||||
void signal_body_sent(const std::exception_ptr& e) const { m_body_sent.set_exception(e); }
|
||||
|
||||
const pplx::task_completion_event<void>& body_sent() const { return m_body_sent; }
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
void set_message_pong()
|
||||
{
|
||||
concurrency::streams::container_buffer<std::string> buffer("");
|
||||
m_msg_type = websocket_message_type::pong;
|
||||
m_length = static_cast<size_t>(buffer.size());
|
||||
m_body = buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_message(const concurrency::streams::container_buffer<std::string>& buffer)
|
||||
{
|
||||
m_msg_type = websocket_message_type::text_message;
|
||||
m_length = static_cast<size_t>(buffer.size());
|
||||
m_body = buffer;
|
||||
}
|
||||
|
||||
void set_message(const concurrency::streams::istream& istream, size_t len, websocket_message_type msg_type)
|
||||
{
|
||||
m_msg_type = msg_type;
|
||||
m_length = len;
|
||||
m_body = istream.streambuf();
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents an incoming websocket message
|
||||
/// </summary>
|
||||
class websocket_incoming_message
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Extracts the body of the incoming message as a string value, only if the message type is UTF-8.
|
||||
/// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out.
|
||||
/// </summary>
|
||||
/// <returns>String containing body of the message.</returns>
|
||||
_ASYNCRTIMP pplx::task<std::string> extract_string() const;
|
||||
|
||||
/// <summary>
|
||||
/// Produces a stream which the caller may use to retrieve body from an incoming message.
|
||||
/// Can be used for both UTF-8 (text) and binary message types.
|
||||
/// </summary>
|
||||
/// <returns>A readable, open asynchronous stream.</returns>
|
||||
/// <remarks>
|
||||
/// This cannot be used in conjunction with any other means of getting the body of the message.
|
||||
/// </remarks>
|
||||
concurrency::streams::istream body() const
|
||||
{
|
||||
auto to_uint8_t_stream =
|
||||
[](const concurrency::streams::streambuf<uint8_t>& buf) -> concurrency::streams::istream {
|
||||
return buf.create_istream();
|
||||
};
|
||||
return to_uint8_t_stream(m_body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of the received message.
|
||||
/// </summary>
|
||||
size_t length() const { return static_cast<size_t>(m_body.size()); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the type of the received message.
|
||||
/// </summary>
|
||||
CASABLANCA_DEPRECATED("Incorrectly spelled API, use message_type() instead.")
|
||||
websocket_message_type messge_type() const { return m_msg_type; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the type of the received message, either string or binary.
|
||||
/// </summary>
|
||||
/// <returns>websocket_message_type</returns>
|
||||
websocket_message_type message_type() const { return m_msg_type; }
|
||||
|
||||
private:
|
||||
friend class details::winrt_callback_client;
|
||||
friend class details::wspp_callback_client;
|
||||
#if defined(__cplusplus_winrt)
|
||||
friend ref class details::ReceiveContext;
|
||||
#endif
|
||||
|
||||
// Store message body in a container buffer backed by a string.
|
||||
// Allows for optimization in the string message cases.
|
||||
concurrency::streams::container_buffer<std::string> m_body;
|
||||
websocket_message_type m_msg_type;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace websockets
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
211
packages/cpprestsdk.v141.2.10.12.1/build/native/include/pplx/pplx.h
vendored
Normal file
211
packages/cpprestsdk.v141.2.10.12.1/build/native/include/pplx/pplx.h
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Parallel Patterns Library
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PPLX_H
|
||||
#define _PPLX_H
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX
|
||||
#error This file must not be included for Visual Studio 12 or later
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#if defined(_WIN32) || defined(__cplusplus_winrt)
|
||||
#define _WIN32
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef _NO_PPLXIMP
|
||||
#define _PPLXIMP
|
||||
#else
|
||||
#ifdef _PPLX_EXPORT
|
||||
#define _PPLXIMP __declspec(dllexport)
|
||||
#else
|
||||
#define _PPLXIMP __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
|
||||
// Use PPLx
|
||||
#ifdef _WIN32
|
||||
#include "pplx/pplxwin.h"
|
||||
#elif defined(__APPLE__)
|
||||
#undef _PPLXIMP
|
||||
#define _PPLXIMP
|
||||
#include "pplx/pplxlinux.h"
|
||||
#else
|
||||
#include "pplx/pplxlinux.h"
|
||||
#endif // _WIN32
|
||||
|
||||
// Common implementation across all the non-concrt versions
|
||||
#include "pplx/pplxcancellation_token.h"
|
||||
#include <functional>
|
||||
|
||||
// conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
|
||||
/// <summary>
|
||||
/// The <c>pplx</c> namespace provides classes and functions that give you access to the Concurrency Runtime,
|
||||
/// a concurrent programming framework for C++. For more information, see <see cref="Concurrency Runtime"/>.
|
||||
/// </summary>
|
||||
/**/
|
||||
namespace pplx
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the ambient scheduler to be used by the PPL constructs.
|
||||
/// </summary>
|
||||
_PPLXIMP void _pplx_cdecl set_ambient_scheduler(std::shared_ptr<pplx::scheduler_interface> _Scheduler);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ambient scheduler to be used by the PPL constructs
|
||||
/// </summary>
|
||||
_PPLXIMP std::shared_ptr<pplx::scheduler_interface> _pplx_cdecl get_ambient_scheduler();
|
||||
|
||||
namespace details
|
||||
{
|
||||
//
|
||||
// An internal exception that is used for cancellation. Users do not "see" this exception except through the
|
||||
// resulting stack unwind. This exception should never be intercepted by user code. It is intended
|
||||
// for use by the runtime only.
|
||||
//
|
||||
class _Interruption_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
_Interruption_exception() {}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
struct _AutoDeleter
|
||||
{
|
||||
_AutoDeleter(_T* _PPtr) : _Ptr(_PPtr) {}
|
||||
~_AutoDeleter() { delete _Ptr; }
|
||||
_T* _Ptr;
|
||||
};
|
||||
|
||||
struct _TaskProcHandle
|
||||
{
|
||||
_TaskProcHandle() {}
|
||||
|
||||
virtual ~_TaskProcHandle() {}
|
||||
virtual void invoke() const = 0;
|
||||
|
||||
static void _pplx_cdecl _RunChoreBridge(void* _Parameter)
|
||||
{
|
||||
auto _PTaskHandle = static_cast<_TaskProcHandle*>(_Parameter);
|
||||
_AutoDeleter<_TaskProcHandle> _AutoDeleter(_PTaskHandle);
|
||||
_PTaskHandle->invoke();
|
||||
}
|
||||
};
|
||||
|
||||
enum _TaskInliningMode
|
||||
{
|
||||
// Disable inline scheduling
|
||||
_NoInline = 0,
|
||||
// Let runtime decide whether to do inline scheduling or not
|
||||
_DefaultAutoInline = 16,
|
||||
// Always do inline scheduling
|
||||
_ForceInline = -1,
|
||||
};
|
||||
|
||||
// This is an abstraction that is built on top of the scheduler to provide these additional functionalities
|
||||
// - Ability to wait on a work item
|
||||
// - Ability to cancel a work item
|
||||
// - Ability to inline work on invocation of RunAndWait
|
||||
class _TaskCollectionImpl
|
||||
{
|
||||
public:
|
||||
typedef _TaskProcHandle _TaskProcHandle_t;
|
||||
|
||||
_TaskCollectionImpl(scheduler_ptr _PScheduler) : _M_pScheduler(_PScheduler) {}
|
||||
|
||||
void _ScheduleTask(_TaskProcHandle_t* _PTaskHandle, _TaskInliningMode _InliningMode)
|
||||
{
|
||||
if (_InliningMode == _ForceInline)
|
||||
{
|
||||
_TaskProcHandle_t::_RunChoreBridge(_PTaskHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
_M_pScheduler->schedule(_TaskProcHandle_t::_RunChoreBridge, _PTaskHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void _Cancel()
|
||||
{
|
||||
// No cancellation support
|
||||
}
|
||||
|
||||
void _RunAndWait()
|
||||
{
|
||||
// No inlining support yet
|
||||
_Wait();
|
||||
}
|
||||
|
||||
void _Wait() { _M_Completed.wait(); }
|
||||
|
||||
void _Complete() { _M_Completed.set(); }
|
||||
|
||||
scheduler_ptr _GetScheduler() const { return _M_pScheduler; }
|
||||
|
||||
// Fire and forget
|
||||
static void _RunTask(TaskProc_t _Proc, void* _Parameter, _TaskInliningMode _InliningMode)
|
||||
{
|
||||
if (_InliningMode == _ForceInline)
|
||||
{
|
||||
_Proc(_Parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Schedule the work on the ambient scheduler
|
||||
get_ambient_scheduler()->schedule(_Proc, _Parameter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool _pplx_cdecl _Is_cancellation_requested()
|
||||
{
|
||||
// We do not yet have the ability to determine the current task. So return false always
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
extensibility::event_t _M_Completed;
|
||||
scheduler_ptr _M_pScheduler;
|
||||
};
|
||||
|
||||
// For create_async lambdas that return a (non-task) result, we oversubscriber the current task for the duration of the
|
||||
// lambda.
|
||||
struct _Task_generator_oversubscriber
|
||||
{
|
||||
};
|
||||
|
||||
typedef _TaskCollectionImpl _TaskCollection_t;
|
||||
typedef _TaskInliningMode _TaskInliningMode_t;
|
||||
typedef _Task_generator_oversubscriber _Task_generator_oversubscriber_t;
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace pplx
|
||||
|
||||
#pragma pack(pop)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // _PPLX_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user