new
128
.editorconfig
Normal file
@ -0,0 +1,128 @@
|
||||
# editorconfig: http://editorconfig.org/
|
||||
# Help developers standardize spaces, tabs, encoding, end-line characters across editors
|
||||
|
||||
# top-most .editorconfig file
|
||||
root = true
|
||||
|
||||
# defaults for all files
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = crlf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# markdown, diff overrides
|
||||
# two trailing spaces are required for <br/> and hard line-breaks in markdown files
|
||||
# see: (https://daringfireball.net/projects/markdown/syntax#p) and (http://spec.commonmark.org/0.27/#hard-line-break)
|
||||
[*.{md,diff}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{md,xml,vcxproj,gprops,man,natvis}]
|
||||
indent_size = 2
|
||||
|
||||
# manifest validation tool requires BOM
|
||||
[*.man]
|
||||
charset = utf-8-bom
|
||||
|
||||
# csproj overrides
|
||||
[*.csproj]
|
||||
indent_size = 2
|
||||
|
||||
# YAML overrides
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
# package.json overrides
|
||||
# Updating package.json with NPM will revert indentation to 2 spaces so to
|
||||
# reduce churn, let's align to NPM and specify indent size 2
|
||||
[package.json]
|
||||
indent_size = 2
|
||||
|
||||
[*.{c,cpp,cxx,h,hpp,hxx,w,idl,rc}]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# C# overrides
|
||||
# Rules explanation: https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
|
||||
[*.cs]
|
||||
# Indent settings
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
# Newline settings
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Braces settings
|
||||
csharp_prefer_braces = true:error
|
||||
csharp_prefer_simple_default_expression = false:error
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = false
|
||||
|
||||
# Space settings
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = do_not_ignore
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# Suggest more modern language features when available
|
||||
csharp_style_conditional_delegate_call = false:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = false:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
|
||||
# Prefer property-like constructs to have an expression-body
|
||||
csharp_style_expression_bodied_accessors = true:suggestion
|
||||
csharp_style_expression_bodied_indexers = true:suggestion
|
||||
csharp_style_expression_bodied_properties = true:suggestion
|
||||
|
||||
# Suggest "var" when type is apparent
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
|
||||
# Sort using directives with System.* appearing first
|
||||
dotnet_sort_system_directives_first = true
|
||||
|
||||
# Suggest more modern language features when available
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
|
||||
# Use language keywords instead of framework type names for type references
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
# Avoid "this."
|
||||
dotnet_style_qualification_for_event = false:error
|
||||
dotnet_style_qualification_for_field = false:error
|
||||
dotnet_style_qualification_for_method = false:error
|
||||
dotnet_style_qualification_for_property = false:error
|
||||
37
.gitattributes
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.appxmanifest text eol=crlf
|
||||
*.c text eol=crlf
|
||||
*.cpp text eol=crlf
|
||||
*.cs text eol=crlf
|
||||
*.csproj text eol=crlf
|
||||
*.css text eol=crlf
|
||||
*.def text eol=crlf
|
||||
*.filters text eol=crlf
|
||||
*.h text eol=crlf
|
||||
*.htm text eol=crlf
|
||||
*.html text eol=crlf
|
||||
*.idl text eol=crlf
|
||||
*.inf text eol=crlf
|
||||
*.inx text eol=crlf
|
||||
*.js text eol=crlf
|
||||
*.jsproj text eol=crlf
|
||||
*.rc text eol=crlf
|
||||
*.rgs text eol=crlf
|
||||
*.sln text eol=crlf
|
||||
*.vcxproj text eol=crlf
|
||||
*.xaml text eol=crlf
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
*.cs diff=csharp
|
||||
|
||||
203
.gitignore
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
[Gg]enerated Files/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studo 2015 cache/options directory
|
||||
.vs/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
*.[Cc]ache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Custom ignores
|
||||
gallery.xml
|
||||
project.lock.json
|
||||
24
LICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
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.
|
||||
|
||||
Portions of this repo are provided under the SIL Open Font License.
|
||||
See the LICENSE file in individual samples for additional details.
|
||||
39
README.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Windows classic samples
|
||||
|
||||
This repo contains samples that demonstrate
|
||||
the API used in Windows classic desktop applications.
|
||||
|
||||
**Note**. You can use Microsoft Visual Studio to search the entire set of source code here to see whether the usage of a particular Windows API is being demonstrated. Clone this repo (or download the ZIP) to your local file system. Then **Find in Files** in Visual Studio, set **Look in** to the folder you cloned or downloaded into, and search for an API name. You can install [Visual Studio](https://visualstudio.microsoft.com/downloads/) without expense. A Community edition is available—it's free for students, open-source contributors, and individuals.
|
||||
|
||||
These samples demonstrate the functionality and programming model
|
||||
for Windows and Windows Server.
|
||||
This repo contains Visual Studio solution (SLN) files for each sample,
|
||||
along with the source files, assets, resources, and metadata
|
||||
needed to compile and run the sample.
|
||||
For more info about the programming models, platforms, languages,
|
||||
and APIs demonstrated in these samples,
|
||||
check out the documentation on the
|
||||
[Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421).
|
||||
|
||||
Most of these samples were created
|
||||
for Windows 7, Windows 8.1 and/or Windows Server 2012 R2
|
||||
using Visual Studio 2013,
|
||||
but some were created with earlier versions,
|
||||
or with specific SKU and other requirements.
|
||||
In many cases, the samples will also work on later versions than the ones indicated.
|
||||
If you cannot get a sample to work as expected,
|
||||
it might have platform, version, or SKU-specific requirements.
|
||||
If you have any issues with the samples, please provide feedback using the Issues list.
|
||||
|
||||
To get a copy of Visual Studio, go to
|
||||
[Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697).
|
||||
|
||||
Other samples:
|
||||
|
||||
- [Windows Universal Samples (UWP)](https://github.com/Microsoft/Windows-universal-samples)
|
||||
- [Desktop Bridge to Universal Windows Platform (UWP)](https://github.com/Microsoft/DesktopBridgeToUWP-Samples)
|
||||
- [Code samples browser](https://docs.microsoft.com/samples/)
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
41
SECURITY.md
Normal file
@ -0,0 +1,41 @@
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
||||
52
Samples/AcousticEchoCancellation/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: Acoustic echo cancellation
|
||||
urlFragment: AcousticEchoCancellation
|
||||
description: Set the reference endpoint id for acoustic echo cancellation.
|
||||
extendedZipContent:
|
||||
- path: LICENSE
|
||||
target: LICENSE
|
||||
---
|
||||
|
||||
# Acoustic Echo Cancellation Sample
|
||||
|
||||
This sample demonstrates the use of the IAcousticEchoCancellationControl::SetEchoCancellationRenderEndpoint method.
|
||||
|
||||
The Acoustic Echo Cancellation APIs provide applications using communications streams the ability to customize
|
||||
the reference stream of choice to use for echo cancellation. By default, the system uses the default render
|
||||
device as the reference stream.
|
||||
|
||||
The sample demonstrates how an application can check to see if the audio stream provides a way to configure
|
||||
echo cancellation. If it does, the interface is used to configure the reference endpoint to be used for echo
|
||||
cancellation on a communication stream by using the reference stream from a specific render endpoint.
|
||||
|
||||
To use this sample, select a render endpoint from the list (by number),
|
||||
and the sample use that render endpoint as the reference stream for echo cancellation.
|
||||
|
||||
This sample requires Windows 11 build 22540 or later.
|
||||
|
||||
Sample Language Implementations
|
||||
===============================
|
||||
C++
|
||||
|
||||
To build the sample using the command prompt:
|
||||
=============================================
|
||||
|
||||
1. Open the Command Prompt window and navigate to the directory.
|
||||
2. Type msbuild [Solution Filename]
|
||||
|
||||
To build the sample using Visual Studio (preferred method):
|
||||
================================================================
|
||||
|
||||
1. Open Windows Explorer and navigate to the directory.
|
||||
2. Double-click the icon for the .sln (solution) file to open the file in Visual Studio.
|
||||
3. In the Build menu, select Build Solution. The application will be built in the default
|
||||
\Debug or \Release directory
|
||||
|
||||
To run the sample:
|
||||
=================
|
||||
Type AcousticEchoCancellation.exe at the command line.
|
||||
173
Samples/AcousticEchoCancellation/cpp/AECCapture.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include <windows.h>
|
||||
#include <wchar.h>
|
||||
#include <AudioSessionTypes.h>
|
||||
|
||||
#include "AECCapture.h"
|
||||
|
||||
#if !defined(NTDDI_WIN10_NI) || (NTDDI_VERSION < NTDDI_WIN10_NI)
|
||||
#error This sample requires SDK version 22540 or higher.
|
||||
#endif
|
||||
|
||||
#define REFTIMES_PER_SEC 10000000
|
||||
|
||||
HRESULT CAECCapture::IsAcousticEchoCancellationEffectPresent(bool* result)
|
||||
{
|
||||
*result = false;
|
||||
|
||||
// IAudioEffectsManager requires build 22000 or higher.
|
||||
wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
|
||||
HRESULT hr = _audioClient->GetService(IID_PPV_ARGS(&audioEffectsManager));
|
||||
if (hr == E_NOINTERFACE)
|
||||
{
|
||||
// Audio effects manager is not supported, so clearly not present.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
|
||||
UINT32 numEffects;
|
||||
RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));
|
||||
|
||||
for (UINT32 i = 0; i < numEffects; i++)
|
||||
{
|
||||
// Check for acoustic echo cancellation Audio Processing Object (APO)
|
||||
if (effects[i].id == AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION)
|
||||
{
|
||||
*result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CAECCapture::InitializeCaptureClient()
|
||||
{
|
||||
wil::com_ptr_nothrow<IMMDeviceEnumerator> enumerator;
|
||||
RETURN_IF_FAILED(::CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&enumerator)));
|
||||
|
||||
wil::com_ptr_nothrow<IMMDevice> device;
|
||||
RETURN_IF_FAILED(enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, &device));
|
||||
|
||||
RETURN_IF_FAILED(device->Activate(__uuidof(IAudioClient2), CLSCTX_INPROC_SERVER, NULL, (void**)&_audioClient));
|
||||
|
||||
// Set the category as communications.
|
||||
AudioClientProperties clientProperties = {};
|
||||
clientProperties.cbSize = sizeof(AudioClientProperties);
|
||||
clientProperties.eCategory = AudioCategory_Communications;
|
||||
RETURN_IF_FAILED(_audioClient->SetClientProperties(&clientProperties));
|
||||
|
||||
wil::unique_cotaskmem_ptr<WAVEFORMATEX> wfxCapture;
|
||||
RETURN_IF_FAILED(_audioClient->GetMixFormat(wil::out_param(wfxCapture)));
|
||||
|
||||
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
|
||||
RETURN_IF_FAILED(_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||
hnsRequestedDuration,
|
||||
0,
|
||||
wfxCapture.get(),
|
||||
NULL));
|
||||
|
||||
bool aecEffectPresent;
|
||||
RETURN_IF_FAILED(IsAcousticEchoCancellationEffectPresent(&aecEffectPresent));
|
||||
|
||||
if (!aecEffectPresent)
|
||||
{
|
||||
wprintf(L"Warning: Capture stream is not echo cancelled.\n");
|
||||
|
||||
// An APO vendor can add code here to insert an in-app
|
||||
// acoustic echo cancellation APO before starting the capture stream.
|
||||
}
|
||||
|
||||
wil::unique_cotaskmem_string deviceId;
|
||||
RETURN_IF_FAILED(device->GetId(&deviceId));
|
||||
wprintf(L"Created communications stream on capture endpoint %ls\n", deviceId.get());
|
||||
|
||||
RETURN_IF_FAILED(_audioClient->GetService(IID_PPV_ARGS(&_captureClient)));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CAECCapture::RecordCommunicationsStream()
|
||||
{
|
||||
DWORD mmcssTaskIndex = 0;
|
||||
HANDLE mmcssTaskHandle = AvSetMmThreadCharacteristics(L"Audio", &mmcssTaskIndex);
|
||||
RETURN_HR_IF(HRESULT_FROM_WIN32(GetLastError()), mmcssTaskHandle == 0);
|
||||
|
||||
auto avRevertMmThreadCharacteristicsOnExit = wil::scope_exit([&]()
|
||||
{
|
||||
AvRevertMmThreadCharacteristics(mmcssTaskHandle);
|
||||
});
|
||||
|
||||
wil::unique_event_nothrow bufferComplete;
|
||||
RETURN_IF_FAILED(bufferComplete.create());
|
||||
RETURN_IF_FAILED(_audioClient->SetEventHandle(bufferComplete.get()));
|
||||
|
||||
RETURN_IF_FAILED(_audioClient->Start());
|
||||
|
||||
wprintf(L"Started communications capture stream.\n");
|
||||
|
||||
HANDLE events[] = { _terminationEvent.get(), bufferComplete.get() };
|
||||
|
||||
while (WAIT_OBJECT_0 != WaitForMultipleObjects(ARRAYSIZE(events), events, FALSE, INFINITE))
|
||||
{
|
||||
UINT32 packetLength = 0;
|
||||
while (SUCCEEDED(_captureClient->GetNextPacketSize(&packetLength)) && packetLength > 0)
|
||||
{
|
||||
PBYTE buffer;
|
||||
UINT32 numFramesRead;
|
||||
DWORD flags = 0;
|
||||
RETURN_IF_FAILED(_captureClient->GetBuffer(&buffer, &numFramesRead, &flags, nullptr, nullptr));
|
||||
|
||||
// At this point, the app can send the buffer to the capture pipeline.
|
||||
// This program just discards the buffer without processing it.
|
||||
|
||||
RETURN_IF_FAILED(_captureClient->ReleaseBuffer(numFramesRead));
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_FAILED(_audioClient->Stop());
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CAECCapture::StartCapture() try
|
||||
{
|
||||
RETURN_IF_FAILED(_terminationEvent.create());
|
||||
|
||||
RETURN_IF_FAILED(InitializeCaptureClient());
|
||||
|
||||
_captureThread = std::thread(
|
||||
[this]()
|
||||
{
|
||||
RecordCommunicationsStream();
|
||||
});
|
||||
|
||||
return S_OK;
|
||||
} CATCH_RETURN()
|
||||
|
||||
HRESULT CAECCapture::StopCapture()
|
||||
{
|
||||
_terminationEvent.SetEvent();
|
||||
_captureThread.join();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CAECCapture::SetEchoCancellationRenderEndpoint(PCWSTR aecReferenceEndpointId)
|
||||
{
|
||||
wil::com_ptr_nothrow<IAcousticEchoCancellationControl> aecControl;
|
||||
HRESULT hr = _audioClient->GetService(IID_PPV_ARGS(&aecControl));
|
||||
|
||||
if (hr == E_NOINTERFACE)
|
||||
{
|
||||
// For this app, we ignore any failure to to control acoustic echo cancellation.
|
||||
// (Treat as best effort.)
|
||||
wprintf(L"Warning: Acoustic echo cancellation control is not available.\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RETURN_IF_FAILED_MSG(hr, "_audioClient->GetService(IID_PPV_ARGS(&aecControl))");
|
||||
|
||||
// Call SetEchoCancellationRenderEndpoint to change the endpoint of the auxiliary input stream.
|
||||
RETURN_IF_FAILED(aecControl->SetEchoCancellationRenderEndpoint(aecReferenceEndpointId));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
34
Samples/AcousticEchoCancellation/cpp/AECCapture.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <AudioClient.h>
|
||||
#include <mmdeviceapi.h>
|
||||
#include <initguid.h>
|
||||
#include <guiddef.h>
|
||||
#include <mfapi.h>
|
||||
|
||||
#include <wrl\implements.h>
|
||||
#include <wil\com.h>
|
||||
#include <wil\result.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
class CAECCapture :
|
||||
public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::ClassicCom >, Microsoft::WRL::FtmBase >
|
||||
{
|
||||
public:
|
||||
HRESULT StartCapture();
|
||||
HRESULT StopCapture();
|
||||
|
||||
HRESULT SetEchoCancellationRenderEndpoint(PCWSTR aecReferenceEndpointId);
|
||||
|
||||
private:
|
||||
HRESULT InitializeCaptureClient();
|
||||
HRESULT IsAcousticEchoCancellationEffectPresent(bool* result);
|
||||
HRESULT RecordCommunicationsStream();
|
||||
|
||||
std::thread _captureThread;
|
||||
wil::com_ptr_nothrow<IAudioCaptureClient> _captureClient;
|
||||
wil::com_ptr_nothrow<IAudioClient2> _audioClient;
|
||||
|
||||
wil::unique_event_nothrow _terminationEvent;
|
||||
};
|
||||
@ -0,0 +1,104 @@
|
||||
#include <Windows.h>
|
||||
#include <propkeydef.h>
|
||||
#include <Functiondiscoverykeys_devpkey.h>
|
||||
#include "AECCapture.h"
|
||||
|
||||
HRESULT GetRenderEndpointId(PWSTR* endpointId)
|
||||
{
|
||||
*endpointId = nullptr;
|
||||
|
||||
wil::com_ptr_nothrow<IMMDeviceEnumerator> deviceEnumerator;
|
||||
RETURN_IF_FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC, __uuidof(IMMDeviceEnumerator), (void**)&deviceEnumerator));
|
||||
|
||||
wil::com_ptr_nothrow<IMMDeviceCollection> spDeviceCollection;
|
||||
RETURN_IF_FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &spDeviceCollection));
|
||||
|
||||
UINT deviceCount;
|
||||
RETURN_IF_FAILED(spDeviceCollection->GetCount(&deviceCount));
|
||||
|
||||
wprintf(L"0: system default\n");
|
||||
|
||||
for (UINT i = 0; i < deviceCount; i++)
|
||||
{
|
||||
// Get the device from the collection.
|
||||
wil::com_ptr_nothrow<IMMDevice> device;
|
||||
RETURN_IF_FAILED(spDeviceCollection->Item(i, &device));
|
||||
|
||||
// Get the device friendly name.
|
||||
wil::com_ptr_nothrow<IPropertyStore> properties;
|
||||
RETURN_IF_FAILED(device->OpenPropertyStore(STGM_READ, &properties));
|
||||
wil::unique_prop_variant variant;
|
||||
RETURN_IF_FAILED(properties->GetValue(PKEY_Device_FriendlyName, &variant));
|
||||
|
||||
wprintf(L"%d: %ls\n", i + 1, variant.pwszVal);
|
||||
}
|
||||
|
||||
wprintf(L"Choose a device to use as the acoustic echo cancellation render endpoint: ");
|
||||
fflush(stdout);
|
||||
|
||||
UINT index;
|
||||
if (wscanf_s(L"%u", &index) != 1)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_CANCELLED);
|
||||
}
|
||||
if (index == 0)
|
||||
{
|
||||
// nullptr means "use the system default"
|
||||
*endpointId = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Convert from 1-based index to 0-based index.
|
||||
index = index - 1;
|
||||
|
||||
if (index > deviceCount)
|
||||
{
|
||||
wprintf(L"Invalid choice.\n");
|
||||
return HRESULT_FROM_WIN32(ERROR_CANCELLED);
|
||||
}
|
||||
|
||||
// Get the chosen device from the collection.
|
||||
wil::com_ptr_nothrow<IMMDevice> device;
|
||||
RETURN_IF_FAILED(spDeviceCollection->Item(index, &device));
|
||||
|
||||
// Get and return the endpoint ID for that device.
|
||||
RETURN_IF_FAILED(device->GetId(endpointId));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
// Print diagnostic messages to the console for developer convenience.
|
||||
wil::SetResultLoggingCallback([](wil::FailureInfo const& failure) noexcept
|
||||
{
|
||||
wchar_t message[1024];
|
||||
wil::GetFailureLogString(message, ARRAYSIZE(message), failure);
|
||||
wprintf(L"Diagnostic message: %ls\n", message);
|
||||
});
|
||||
|
||||
|
||||
RETURN_IF_FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
|
||||
wil::unique_couninitialize_call uninitialize;
|
||||
|
||||
wil::unique_cotaskmem_string endpointId;
|
||||
RETURN_IF_FAILED(GetRenderEndpointId(&endpointId));
|
||||
|
||||
CAECCapture aecCapture;
|
||||
RETURN_IF_FAILED(aecCapture.StartCapture());
|
||||
|
||||
// Make sure we Stop capture even if an error occurs.
|
||||
auto stop = wil::scope_exit([&]
|
||||
{
|
||||
aecCapture.StopCapture();
|
||||
});
|
||||
|
||||
RETURN_IF_FAILED(aecCapture.SetEchoCancellationRenderEndpoint(endpointId.get()));
|
||||
|
||||
// Capture for 10 seconds.
|
||||
wprintf(L"Capturing for 10 seconds...\n");
|
||||
Sleep(10000);
|
||||
wprintf(L"Finished.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30204.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AcousticEchoCancellation", "AcousticEchoCancellation.vcxproj", "{6E745655-513E-4713-B3AB-D6D3F62D7734}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x64.Build.0 = Debug|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x64.ActiveCfg = Release|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x64.Build.0 = Release|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {64406148-8C03-42D2-8A2A-C14A03CFF8E3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -0,0 +1,169 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{6e745655-513e-4713-b3ab-d6d3f62d7734}</ProjectGuid>
|
||||
<RootNamespace>AcousticEchoCancellation</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>false</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<EnableManagedIncrementalBuild>false</EnableManagedIncrementalBuild>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>F:\os2\os2\public\amd64fre</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AcousticEchoCancellation.cpp" />
|
||||
<ClCompile Include="AECCapture.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AECCapture.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AcousticEchoCancellation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AECCapture.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AECCapture.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
4
Samples/AcousticEchoCancellation/cpp/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
49
Samples/AmbientLightAware/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
Ambient light sensor sample
|
||||
===========================
|
||||
|
||||
This sample demonstrates how to optimize a label's font size, based on light conditions reported by an Ambient Light sensor.
|
||||
|
||||
The sample creates a smaller font when it detects indoor lighting conditions. It creates a larger font when it detects outdoor lighting conditions.
|
||||
|
||||
**Note**
|
||||
|
||||
This sample is not optimized for light conditions. It is intended to demonstrate one use of the sensor platform.
|
||||
|
||||
Related topics
|
||||
--------------
|
||||
|
||||
[Sensor API](http://msdn.microsoft.com/en-us/library/windows/desktop/dd318953)
|
||||
|
||||
Operating system requirements
|
||||
-----------------------------
|
||||
|
||||
Client
|
||||
|
||||
Windows 7
|
||||
|
||||
Server
|
||||
|
||||
None supported
|
||||
|
||||
Build the sample
|
||||
----------------
|
||||
|
||||
To build the sample by using Visual Studio 2013 or later (preferred method):
|
||||
|
||||
1. Open Windows Explorer and navigate to the directory.
|
||||
2. Double-click the icon for the **.sln** (solution) file to open the file in Visual Studio.
|
||||
3. In the **Build** menu, select **Build Solution**. The application is built in the default \\Debug or \\Release directory.
|
||||
|
||||
To build the sample by using the command line:
|
||||
|
||||
1. Open the **Command Prompt** window and navigate to the directory.
|
||||
2. Type **msbuild ambientlightaware.sln**.
|
||||
|
||||
Run the sample
|
||||
--------------
|
||||
|
||||
To run the sample:
|
||||
|
||||
1. Navigate to the directory that contains the new executable, by using the command prompt.
|
||||
2. Type **ambientlightaware.exe** at the command line.
|
||||
|
||||
82
Samples/AmbientLightAware/cpp/AmbientLightAware.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAware.cpp
|
||||
//
|
||||
// Description:
|
||||
// Dialog for Ambient Light Aware SDK Sample
|
||||
//
|
||||
// Comments:
|
||||
// Standard vc++ dialog created by VS 2005 wizard.
|
||||
// This code just creates a dialog and cleans it up when finished.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "AmbientLightAware.h"
|
||||
#include "AmbientLightAwareSensorEvents.h"
|
||||
#include "AmbientLightAwareSensorManagerEvents.h"
|
||||
#include "AmbientLightAwareDlg.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
|
||||
// CAmbientLightAwareApp
|
||||
|
||||
BEGIN_MESSAGE_MAP(CAmbientLightAwareApp, CWinApp)
|
||||
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CAmbientLightAwareApp construction
|
||||
// Wizard generated constructor
|
||||
CAmbientLightAwareApp::CAmbientLightAwareApp()
|
||||
{
|
||||
// Place all significant initialization in InitInstance
|
||||
|
||||
// Protect against heap corruption
|
||||
(void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
// The one and only CAmbientLightAwareApp object
|
||||
CAmbientLightAwareApp theApp;
|
||||
|
||||
|
||||
// CAmbientLightAwareApp initialization
|
||||
BOOL CAmbientLightAwareApp::InitInstance()
|
||||
{
|
||||
// InitCommonControlsEx() is required on Windows XP if an application
|
||||
// manifest specifies use of ComCtl32.dll version 6 or later to enable
|
||||
// visual styles. Otherwise, any window creation will fail.
|
||||
INITCOMMONCONTROLSEX InitCtrls;
|
||||
InitCtrls.dwSize = sizeof(InitCtrls);
|
||||
// Set this to include all the common control classes you want to use
|
||||
// in your application.
|
||||
InitCtrls.dwICC = ICC_WIN95_CLASSES;
|
||||
InitCommonControlsEx(&InitCtrls);
|
||||
|
||||
CWinApp::InitInstance();
|
||||
|
||||
// ************************************************************************
|
||||
// Added COM initialization, dialog cleanup, and COM uninitialization.
|
||||
// ************************************************************************
|
||||
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // Initializes COM
|
||||
CAmbientLightAwareDlg dlg;
|
||||
m_pMainWnd = &dlg;
|
||||
dlg.DoModal();
|
||||
dlg.CleanUp(); // Once the dialog has returned, clean up its private members
|
||||
::CoUninitialize(); // Uninitializes COM
|
||||
|
||||
// Since the dialog has been closed, return FALSE so that we exit the
|
||||
// application, rather than start the application's message pump.
|
||||
return FALSE;
|
||||
}
|
||||
47
Samples/AmbientLightAware/cpp/AmbientLightAware.h
Normal file
@ -0,0 +1,47 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAware.h
|
||||
//
|
||||
// Description:
|
||||
// Dialog for Ambient Light Aware SDK Sample
|
||||
//
|
||||
// Comments:
|
||||
// Standard vc++ dialog created by VS 2005 wizard.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __AFXWIN_H__
|
||||
#error "include 'stdafx.h' before including this file for PCH"
|
||||
#endif
|
||||
|
||||
#include "resource.h" // main symbols
|
||||
|
||||
|
||||
// CAmbientLightAwareApp:
|
||||
// See AmbientLightAware.cpp for the implementation of this class
|
||||
//
|
||||
|
||||
class CAmbientLightAwareApp : public CWinApp
|
||||
{
|
||||
public:
|
||||
CAmbientLightAwareApp();
|
||||
|
||||
// Overrides
|
||||
public:
|
||||
virtual BOOL InitInstance();
|
||||
|
||||
// Implementation
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
extern CAmbientLightAwareApp theApp;
|
||||
BIN
Samples/AmbientLightAware/cpp/AmbientLightAware.ico
Normal file
|
After Width: | Height: | Size: 21 KiB |
168
Samples/AmbientLightAware/cpp/AmbientLightAware.rc
Normal file
@ -0,0 +1,168 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
|
||||
"#define _AFX_NO_OLE_RESOURCES\r\n"
|
||||
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
|
||||
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
|
||||
"\r\n"
|
||||
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
|
||||
"LANGUAGE 9, 1\r\n"
|
||||
"#pragma code_page(1252)\r\n"
|
||||
"#include ""res\\AmbientLightAware.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
|
||||
"#include ""afxres.rc"" // Standard components\r\n"
|
||||
"#endif\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDR_MAINFRAME ICON "AmbientLightAware.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_AMBIENTLIGHTAWARE_DIALOG DIALOGEX 0, 0, 207, 88
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "Ambient Light Aware SDK Sample"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Done",IDOK,7,65,50,16
|
||||
LTEXT "Ambient light level: lux",IDC_STATIC_LUX,7,7,193,12
|
||||
LTEXT "Sample Optimized Text",IDC_STATIC_SAMPLE,7,33,193,32
|
||||
LTEXT "Sensors: 0",IDC_STATIC_SENSORS,7,18,193,9
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Microsoft"
|
||||
VALUE "FileDescription", "AmbientLightAware"
|
||||
VALUE "FileVersion", "1.0.0.1"
|
||||
VALUE "InternalName", "AmbientLightAware.exe"
|
||||
VALUE "LegalCopyright", "(c) Microsoft. All rights reserved."
|
||||
VALUE "OriginalFilename", "AmbientLightAware.exe"
|
||||
VALUE "ProductName", "AmbientLightAware"
|
||||
VALUE "ProductVersion", "1.0.0.1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_AMBIENTLIGHTAWARE_DIALOG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 200
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 81
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
#define _AFX_NO_SPLITTER_RESOURCES
|
||||
#define _AFX_NO_OLE_RESOURCES
|
||||
#define _AFX_NO_TRACKER_RESOURCES
|
||||
#define _AFX_NO_PROPERTY_RESOURCES
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE 9, 1
|
||||
#pragma code_page(1252)
|
||||
#include "AmbientLightAware.rc2" // non-Microsoft Visual C++ edited resources
|
||||
#include "afxres.rc" // Standard components
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
13
Samples/AmbientLightAware/cpp/AmbientLightAware.rc2
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// AmbientLightAware.RC2 - resources Microsoft Visual C++ does not edit directly
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#error this file is not editable by Microsoft Visual C++
|
||||
#endif //APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Add manually edited resources here...
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
26
Samples/AmbientLightAware/cpp/AmbientLightAware.sln
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 11
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmbientLightAware", "AmbientLightAware.vcxproj", "{D3528BE0-D48A-4240-95FD-7724D6BAA755}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|x64.Build.0 = Debug|x64
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|Win32.Build.0 = Release|Win32
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|x64.ActiveCfg = Release|x64
|
||||
{D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
256
Samples/AmbientLightAware/cpp/AmbientLightAware.vcxproj
Normal file
@ -0,0 +1,256 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and '$(VisualStudioVersion)' == ''">$(VCTargetsPath11)</VCTargetsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D3528BE0-D48A-4240-95FD-7724D6BAA755}</ProjectGuid>
|
||||
<RootNamespace>AmbientLightAware</RootNamespace>
|
||||
<Keyword>MFCProj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<UseOfMfc>Dynamic</UseOfMfc>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<UseOfMfc>Dynamic</UseOfMfc>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<UseOfMfc>Dynamic</UseOfMfc>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<UseOfMfc>Dynamic</UseOfMfc>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.50214.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
<ValidateAllParameters>false</ValidateAllParameters>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>sensorsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
<ValidateAllParameters>false</ValidateAllParameters>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>sensorsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>sensorsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>sensorsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AmbientLightAware.cpp" />
|
||||
<ClCompile Include="AmbientLightAwareDlg.cpp" />
|
||||
<ClCompile Include="AmbientLightAwareSensorEvents.cpp" />
|
||||
<ClCompile Include="AmbientLightAwareSensorManagerEvents.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AmbientLightAware.h" />
|
||||
<ClInclude Include="AmbientLightAwareDlg.h" />
|
||||
<ClInclude Include="AmbientLightAwareSensorEvents.h" />
|
||||
<ClInclude Include="AmbientLightAwareSensorManagerEvents.h" />
|
||||
<ClInclude Include="Resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="AmbientLightAware.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="AmbientLightAware.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="AmbientLightAware.rc2" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties RESOURCE_FILE="AmbientLightAware.rc" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
277
Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAwareDlg.cpp
|
||||
//
|
||||
// Description:
|
||||
// Dialog for Ambient Light Aware SDK Sample
|
||||
//
|
||||
// Comments:
|
||||
// Standard vc++ dialog created by VS 2005 wizard.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "AmbientLightAware.h"
|
||||
#include "AmbientLightAwareSensorEvents.h"
|
||||
#include "AmbientLightAwareSensorManagerEvents.h"
|
||||
#include "AmbientLightAwareDlg.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
// Wizard generated constructor
|
||||
CAmbientLightAwareDlg::CAmbientLightAwareDlg(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(CAmbientLightAwareDlg::IDD, pParent)
|
||||
{
|
||||
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
||||
m_pSensorManagerEvents = NULL;
|
||||
ZeroMemory(&m_lfLogFont, sizeof(LOGFONT));
|
||||
}
|
||||
|
||||
// Wizard generated destructor
|
||||
CAmbientLightAwareDlg::~CAmbientLightAwareDlg()
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareDlg::CleanUp
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, called by main winapp to do clean up of private
|
||||
// members
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareDlg::CleanUp()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = m_pSensorManagerEvents->Uninitialize();
|
||||
|
||||
if (NULL != m_pSensorManagerEvents)
|
||||
{
|
||||
delete m_pSensorManagerEvents;
|
||||
m_pSensorManagerEvents = NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Wizard generated function
|
||||
void CAmbientLightAwareDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CAmbientLightAwareDlg, CDialog)
|
||||
ON_WM_PAINT()
|
||||
ON_WM_QUERYDRAGICON()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CAmbientLightAwareDlg message handlers
|
||||
// Wizard generated function. Added helper function call inside.
|
||||
BOOL CAmbientLightAwareDlg::OnInitDialog()
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// Set the icon for this dialog. The framework does this automatically
|
||||
// when the application's main window is not a dialog
|
||||
SetIcon(m_hIcon, TRUE); // Set big icon
|
||||
SetIcon(m_hIcon, FALSE); // Set small icon
|
||||
|
||||
// ************************************************************************
|
||||
// Added this helper function call to initialize sensor events
|
||||
// ************************************************************************
|
||||
InitAmbientLightAware();
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
}
|
||||
|
||||
// If you add a minimize button to your dialog, you will need the code below
|
||||
// to draw the icon. For MFC applications using the document/view model,
|
||||
// this is automatically done for you by the framework.
|
||||
// Wizard generated function. Added font size change for optimized text.
|
||||
void CAmbientLightAwareDlg::OnPaint()
|
||||
{
|
||||
if (IsIconic())
|
||||
{
|
||||
CPaintDC dc(this); // device context for painting
|
||||
|
||||
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
|
||||
|
||||
// Center icon in client rectangle
|
||||
int cxIcon = GetSystemMetrics(SM_CXICON);
|
||||
int cyIcon = GetSystemMetrics(SM_CYICON);
|
||||
CRect rect;
|
||||
GetClientRect(&rect);
|
||||
int x = (rect.Width() - cxIcon + 1) / 2;
|
||||
int y = (rect.Height() - cyIcon + 1) / 2;
|
||||
|
||||
// Draw the icon
|
||||
dc.DrawIcon(x, y, m_hIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDialog::OnPaint();
|
||||
|
||||
// ********************************************************************
|
||||
// Change the font size for the optimzed text.
|
||||
// ********************************************************************
|
||||
CFont fontOptimzed;
|
||||
BOOL fRet = fontOptimzed.CreateFontIndirect(&m_lfLogFont);
|
||||
if (fRet)
|
||||
{
|
||||
CWnd* pStaticTextSample = GetDlgItem(IDC_STATIC_SAMPLE);
|
||||
if (NULL != pStaticTextSample)
|
||||
{
|
||||
pStaticTextSample->SetFont(&fontOptimzed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The system calls this function to obtain the cursor to display while the user drags
|
||||
// the minimized window.
|
||||
// Wizard generated function
|
||||
HCURSOR CAmbientLightAwareDlg::OnQueryDragIcon()
|
||||
{
|
||||
return static_cast<HCURSOR>(m_hIcon);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareDlg::InitAmbientLightAware
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, initializes sensor events class
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareDlg::InitAmbientLightAware()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// save the font so we can easily change the text size in UpdateLux
|
||||
CFont* pFont;
|
||||
CWnd* pWnd = GetDlgItem(IDC_STATIC_SAMPLE);
|
||||
if (NULL != pWnd)
|
||||
{
|
||||
pFont = pWnd->GetFont();
|
||||
if (NULL != pFont)
|
||||
{
|
||||
LONG lRet = pFont->GetLogFont(&m_lfLogFont);
|
||||
if (0 != lRet)
|
||||
{
|
||||
m_pSensorManagerEvents = new CAmbientLightAwareSensorManagerEvents(this);
|
||||
hr = m_pSensorManagerEvents->Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareDlg::UpdateLux
|
||||
//
|
||||
// Description of function/method:
|
||||
// Callback function. This function is called by the events class when
|
||||
// new data has been received. This function then uses this information
|
||||
// to change the font size to be optimized for the current brightness
|
||||
// (lux).
|
||||
//
|
||||
// This sample is not meant to be an ideal implementation, but just
|
||||
// showing how sensor data can be collected and processed.
|
||||
//
|
||||
// Parameters:
|
||||
// lux: The average lux value for all sensors
|
||||
// numSensors: The number of sensors reporting data
|
||||
//
|
||||
// Return Values:
|
||||
// TRUE on success, FALSE on failure
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareDlg::UpdateLux(float lux, int numSensors)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
CString strLux, strSensors;
|
||||
CFont fontSample;
|
||||
|
||||
if(lux < 10.0)
|
||||
{
|
||||
// Darkness
|
||||
m_lfLogFont.lfHeight = 12; // A sample font size for dark environments
|
||||
}
|
||||
else if(lux < 300)
|
||||
{
|
||||
// Dim Indoors
|
||||
m_lfLogFont.lfHeight = 12; // A sample font size for dim indoor environments
|
||||
}
|
||||
else if(lux < 800)
|
||||
{
|
||||
// Normal Indoors
|
||||
m_lfLogFont.lfHeight = 12; // A sample font size for indoor environments
|
||||
}
|
||||
else if(lux < 10000)
|
||||
{
|
||||
// Bright Indoors
|
||||
m_lfLogFont.lfHeight = 16; // A sample font size for bright indoor environments
|
||||
}
|
||||
else if(lux < 30000)
|
||||
{
|
||||
// Overcast Outdoors
|
||||
m_lfLogFont.lfHeight = 20; // A sample font size for overcast environments
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct Sunlight
|
||||
m_lfLogFont.lfHeight = 30; // A sample font size for sunny environments
|
||||
}
|
||||
|
||||
strLux.Format(_T("Ambient light level: %.2f lux"), lux);
|
||||
SetDlgItemText(IDC_STATIC_LUX, strLux);
|
||||
|
||||
strSensors.Format(_T("Sensors: %i"), numSensors);
|
||||
SetDlgItemText(IDC_STATIC_SENSORS, strSensors);
|
||||
|
||||
// Force OnPaint which changes the text font to be optimized for this lux
|
||||
Invalidate();
|
||||
UpdateWindow();
|
||||
|
||||
return hr;
|
||||
}
|
||||
58
Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.h
Normal file
@ -0,0 +1,58 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAwareDlg.h
|
||||
//
|
||||
// Description:
|
||||
// Dialog for Ambient Light Aware SDK Sample
|
||||
//
|
||||
// Comments:
|
||||
// Standard vc++ dialog created by VS 2005 wizard.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
// CAmbientLightAwareDlg dialog
|
||||
class CAmbientLightAwareDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
// standard constructor
|
||||
CAmbientLightAwareDlg(CWnd* pParent = NULL);
|
||||
virtual ~CAmbientLightAwareDlg();
|
||||
|
||||
// Dialog Data
|
||||
enum { IDD = IDD_AMBIENTLIGHTAWARE_DIALOG };
|
||||
|
||||
// Our callback function from CAmbientLightAwareEvents
|
||||
HRESULT UpdateLux(float lux, int numSensors);
|
||||
// Clean up function called by parent winapp
|
||||
HRESULT CleanUp();
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
HICON m_hIcon;
|
||||
|
||||
// Generated message map functions
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnPaint();
|
||||
afx_msg HCURSOR OnQueryDragIcon();
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
private:
|
||||
// helper function
|
||||
HRESULT InitAmbientLightAware();
|
||||
|
||||
CAmbientLightAwareSensorManagerEvents* m_pSensorManagerEvents; // events class
|
||||
LOGFONT m_lfLogFont; // font to be adjusted for current brightness
|
||||
};
|
||||
436
Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.cpp
Normal file
@ -0,0 +1,436 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAwareSensorEvents.cpp
|
||||
//
|
||||
// Description:
|
||||
// Implementation of ISensorManagerEvents
|
||||
//
|
||||
// Comments:
|
||||
// This is a standard c++ class, but needs to support IUnknown methods
|
||||
// to be properly implemented. This class overrides ISensorEvents
|
||||
// functions to receive updated information from the Sensors API when it
|
||||
// is published.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Resource.h"
|
||||
#include "AmbientLightAwareSensorEvents.h"
|
||||
#include "AmbientLightAwareDlg.h"
|
||||
#include "AmbientLightAwareSensorManagerEvents.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::CAmbientLightAwareSensorEvents
|
||||
//
|
||||
// Description of function/method:
|
||||
// Constructor.
|
||||
//
|
||||
// Parameters:
|
||||
// CAmbientLightAwareDlg* dlg: Parent dialog for callbacks
|
||||
// CAmbientLightAwareSensorManagerEvents* sensorManagerEvents:
|
||||
// Parent class for callbacks
|
||||
//
|
||||
// Return Values:
|
||||
// None
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
CAmbientLightAwareSensorEvents::CAmbientLightAwareSensorEvents(CAmbientLightAwareDlg* dlg, CAmbientLightAwareSensorManagerEvents* sensorManagerEvents)
|
||||
{
|
||||
m_lRefCount = 1; //ref count initialized to 1
|
||||
m_pParentDlg = dlg;
|
||||
m_pSensorManagerEvents = sensorManagerEvents;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::~CAmbientLightAwareSensorEvents
|
||||
//
|
||||
// Description of function/method:
|
||||
// Destructor. Clean up stored data.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// None
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
CAmbientLightAwareSensorEvents::~CAmbientLightAwareSensorEvents()
|
||||
{
|
||||
m_mapLux.RemoveAll();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::QueryInterface
|
||||
//
|
||||
// Description of function/method:
|
||||
// IUnknown method, need to implement to support COM classes that
|
||||
// are inherited.
|
||||
//
|
||||
// Parameters:
|
||||
// REFIID riid: Input. ID of the interface being requested. Either
|
||||
// IUnknown or one of the two classes we inherit.
|
||||
// void** ppObject: Output. Address of pointer variable that receives
|
||||
// the interface pointer requested in riid. Upon
|
||||
// successful return, *ppvObject contains the requested
|
||||
// interface pointer to the object. If the object does
|
||||
// not support the interface specified in iid,
|
||||
// *ppvObject is set to NULL.
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else E_NOINTERFACE
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
STDMETHODIMP CAmbientLightAwareSensorEvents::QueryInterface(REFIID riid, void** ppObject)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
*ppObject = NULL;
|
||||
if (riid == __uuidof(ISensorEvents))
|
||||
{
|
||||
*ppObject = reinterpret_cast<ISensorEvents*>(this);
|
||||
}
|
||||
else if (riid == IID_IUnknown)
|
||||
{
|
||||
*ppObject = reinterpret_cast<IUnknown*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(reinterpret_cast<IUnknown*>(*ppObject))->AddRef();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::AddRef
|
||||
//
|
||||
// Description of function/method:
|
||||
// Increments the reference count for an interface on an object.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// Returns an integer from 1 to n, the value of the new reference count.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ULONG _stdcall CAmbientLightAwareSensorEvents::AddRef()
|
||||
{
|
||||
m_lRefCount++;
|
||||
return m_lRefCount;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::Release
|
||||
//
|
||||
// Description of function/method:
|
||||
// Decrements the reference count for the calling interface on a object.
|
||||
// If the reference count on the object falls to 0, the object is freed
|
||||
// from memory.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// Returns an integer from 1 to n, the value of the new reference count.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ULONG _stdcall CAmbientLightAwareSensorEvents::Release()
|
||||
{
|
||||
ULONG lRet = --m_lRefCount;
|
||||
|
||||
if (m_lRefCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return lRet;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::OnStateChanged
|
||||
//
|
||||
// Description of function/method:
|
||||
// Implementation of ISensor.OnStateChanged. Called when permissions of
|
||||
// the sensor have changed, such as the sensor being disabled in control
|
||||
// panel. If the sensor is not SENSOR_STATE_READY then its lux value
|
||||
// should be ignored.
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor* pSensor: Sensor that has changed
|
||||
// SensorState state: State of the sensor
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::OnStateChanged(__RPC__in_opt ISensor *pSensor, SensorState state)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (NULL != pSensor)
|
||||
{
|
||||
SENSOR_ID idSensor = GUID_NULL;
|
||||
hr = pSensor->GetID(&idSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (SENSOR_STATE_READY == state)
|
||||
{
|
||||
hr = GetSensorData(pSensor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the sensor is not ready, its lux value is ignored
|
||||
m_mapLux[idSensor] = -1.0;
|
||||
hr = UpdateLux();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::OnDataUpdated
|
||||
//
|
||||
// Description of function/method:
|
||||
// Implementation of ISensor.OnDataUpdated. Called when the sensor has
|
||||
// published new data. This reads in the lux value from the report.
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor* pSensor: Sensor that has updated data.
|
||||
// ISensorDataReport *pNewData: New data to be read
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::OnDataUpdated(__RPC__in_opt ISensor *pSensor, __RPC__in_opt ISensorDataReport *pNewData)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if ((NULL != pSensor) && (NULL != pNewData))
|
||||
{
|
||||
hr = GetSensorData(pSensor, pNewData);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::OnEvent
|
||||
//
|
||||
// Description of function/method:
|
||||
// Implementation of ISensor.OnEevent, a generic or custom sensor event.
|
||||
// OnDataUpdated is the event this sample uses to get sensor
|
||||
// information.
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor* pSensor: Sensor that has the event.
|
||||
// GUID& eventID: Type of event.
|
||||
// IPortableDeviceValues *pEventData: Data to be read.
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::OnEvent(__RPC__in_opt ISensor* /*pSensor*/, __RPC__in REFGUID /*eventID*/, __RPC__in_opt IPortableDeviceValues* /*pEventData*/)
|
||||
{
|
||||
// Not implemented
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::OnLeave
|
||||
//
|
||||
// Description of function/method:
|
||||
// Implementation of ISensor.OnLeave. This sensor is being removed, so
|
||||
// it needs to be deleted and freed.
|
||||
//
|
||||
// Parameters:
|
||||
// REFSENSOR_ID sensorID:
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::OnLeave(__RPC__in REFSENSOR_ID sensorID)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = m_pSensorManagerEvents->RemoveSensor(sensorID); // Callback into parent
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Remove the data for this device
|
||||
if (m_mapLux.RemoveKey(sensorID))
|
||||
{
|
||||
hr = UpdateLux();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::UpdateLux
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, calculates average lux and does a callback to the
|
||||
// parent dialog.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// none
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::UpdateLux()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
float fpLux = 0.0;
|
||||
float fpLuxTemp = 0.0;
|
||||
float count = 0;
|
||||
|
||||
POSITION pos = m_mapLux.GetStartPosition();
|
||||
while (NULL != pos)
|
||||
{
|
||||
fpLuxTemp = m_mapLux.GetNextValue(pos);
|
||||
if (fpLuxTemp >= 0)
|
||||
{
|
||||
count++;
|
||||
fpLux += fpLuxTemp;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
fpLux = fpLux / count;
|
||||
}
|
||||
|
||||
hr = m_pParentDlg->UpdateLux(fpLux, (int) count);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::GetSensorData
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, get data from a sensor and updates the lux
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor* pSensor: Input sensor
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::GetSensorData(ISensor* pSensor)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (NULL != pSensor)
|
||||
{
|
||||
CComPtr<ISensorDataReport> spDataReport;
|
||||
hr = pSensor->GetData(&spDataReport);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = GetSensorData(pSensor, spDataReport);
|
||||
}
|
||||
else
|
||||
{
|
||||
SENSOR_ID idSensor = GUID_NULL;
|
||||
hr = pSensor->GetID(&idSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
m_mapLux[idSensor] = -1.0;
|
||||
hr = UpdateLux();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorEvents::GetSensorData
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, get data from a sensor and updates the lux
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor *pSensor: Input sensor
|
||||
// ISensorDataReport* pDataReport: The data to be read
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorEvents::GetSensorData(ISensor *pSensor, ISensorDataReport *pDataReport)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (NULL != pSensor && NULL != pDataReport)
|
||||
{
|
||||
SENSOR_ID idSensor = GUID_NULL;
|
||||
hr = pSensor->GetID(&idSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PROPVARIANT pvLux;
|
||||
PropVariantInit(&pvLux);
|
||||
hr = pDataReport->GetSensorValue(SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, &pvLux);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Save the lux value into our member variable
|
||||
m_mapLux[idSensor] = V_R4(&pvLux);
|
||||
|
||||
hr = UpdateLux();
|
||||
}
|
||||
PropVariantClear(&pvLux);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAwareSensorEvents.h
|
||||
//
|
||||
// Description:
|
||||
// Implementation of ISensorEvents
|
||||
//
|
||||
// Comments:
|
||||
// This is a standard c++ class, but needs to support IUnknown methods
|
||||
// to be properly implemented. This class overrides ISensorEvents and
|
||||
// functions to receive updated information from Sensors API when it
|
||||
// is published.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
// Forward declarations.
|
||||
class CAmbientLightAwareDlg;
|
||||
class CAmbientLightAwareSensorManagerEvents;
|
||||
|
||||
class CAmbientLightAwareSensorEvents :
|
||||
public ISensorEvents
|
||||
{
|
||||
public:
|
||||
// These three methods are for IUnknown
|
||||
STDMETHOD(QueryInterface)(REFIID riid, void** ppObject );
|
||||
ULONG _stdcall AddRef();
|
||||
ULONG _stdcall Release();
|
||||
|
||||
// Constructor and destructor
|
||||
CAmbientLightAwareSensorEvents(CAmbientLightAwareDlg* dlg, CAmbientLightAwareSensorManagerEvents* sensorManagerEvents);
|
||||
virtual ~CAmbientLightAwareSensorEvents();
|
||||
|
||||
// ISensorEvents method overrides
|
||||
STDMETHOD(OnStateChanged)(__RPC__in_opt ISensor* pSensor, SensorState state);
|
||||
STDMETHOD(OnDataUpdated)(__RPC__in_opt ISensor* pSensor, __RPC__in_opt ISensorDataReport* pNewData);
|
||||
STDMETHOD(OnEvent)(__RPC__in_opt ISensor* pSensor, __RPC__in REFGUID eventID, __RPC__in_opt IPortableDeviceValues* pEventData);
|
||||
STDMETHOD(OnLeave)(__RPC__in REFSENSOR_ID sensorID);
|
||||
|
||||
// Helper functions, also called by parent SensorManagerEvents class
|
||||
HRESULT GetSensorData(ISensor* pSensor);
|
||||
|
||||
private:
|
||||
// Member variable to implement IUnknown reference count
|
||||
LONG m_lRefCount;
|
||||
|
||||
// Helper functions
|
||||
HRESULT UpdateLux();
|
||||
HRESULT GetSensorData(ISensor* pSensor, ISensorDataReport* pDataReport);
|
||||
|
||||
CAmbientLightAwareDlg* m_pParentDlg; // Parent dialog used for callbacks
|
||||
CAmbientLightAwareSensorManagerEvents* m_pSensorManagerEvents; // Parent class for callbacks
|
||||
CAtlMap<SENSOR_ID, float> m_mapLux; // Map to store lux values for each sensor
|
||||
};
|
||||
@ -0,0 +1,417 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAwareSensorManagerEvents.cpp
|
||||
//
|
||||
// Description:
|
||||
// Implementation of ISensorManagerEvents
|
||||
//
|
||||
// Comments:
|
||||
// This is a standard c++ class, but needs to support IUnknown methods
|
||||
// to be properly implemented. This class overrides
|
||||
// ISensorManagerEvents functions to receive updated information from
|
||||
// the Sensors API when it is published.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Resource.h"
|
||||
#include "AmbientLightAwareSensorEvents.h"
|
||||
#include "AmbientLightAwareSensorManagerEvents.h"
|
||||
#include "AmbientLightAwareDlg.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::CAmbientLightAwareSensorManagerEvents
|
||||
//
|
||||
// Description of function/method:
|
||||
// Constructor.
|
||||
//
|
||||
// Parameters:
|
||||
// CAmbientLightAwareDlg* dlg: pointer to parent dialog for callbacks
|
||||
//
|
||||
// Return Values:
|
||||
// None
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
CAmbientLightAwareSensorManagerEvents::CAmbientLightAwareSensorManagerEvents(CAmbientLightAwareDlg* dlg)
|
||||
{
|
||||
m_lRefCount = 1; //ref count initialized to 1
|
||||
m_pSensorEvents = new CAmbientLightAwareSensorEvents(dlg, this);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::~CAmbientLightAwareSensorManagerEvents
|
||||
//
|
||||
// Description of function/method:
|
||||
// Destructor. Clean up stored data.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// None
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
CAmbientLightAwareSensorManagerEvents::~CAmbientLightAwareSensorManagerEvents()
|
||||
{
|
||||
if (NULL != m_pSensorEvents)
|
||||
{
|
||||
delete m_pSensorEvents;
|
||||
m_pSensorEvents = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::QueryInterface
|
||||
//
|
||||
// Description of function/method:
|
||||
// IUnknown method, need to implement to support COM classes that
|
||||
// are inherited.
|
||||
//
|
||||
// Parameters:
|
||||
// REFIID riid: Input. ID of the interface being requested. Either
|
||||
// IUnknown or one of the two classes we inherit.
|
||||
// void** ppObject: Output. Address of pointer variable that receives
|
||||
// the interface pointer requested in riid. Upon
|
||||
// successful return, *ppvObject contains the requested
|
||||
// interface pointer to the object. If the object does
|
||||
// not support the interface specified in iid,
|
||||
// *ppvObject is set to NULL.
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else E_NOINTERFACE
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
STDMETHODIMP CAmbientLightAwareSensorManagerEvents::QueryInterface(REFIID riid, void** ppObject)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
*ppObject = NULL;
|
||||
if (riid == __uuidof(ISensorManagerEvents))
|
||||
{
|
||||
*ppObject = reinterpret_cast<ISensorManagerEvents*>(this);
|
||||
}
|
||||
else if (riid == IID_IUnknown)
|
||||
{
|
||||
*ppObject = reinterpret_cast<IUnknown*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(reinterpret_cast<IUnknown*>(*ppObject))->AddRef();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::AddRef
|
||||
//
|
||||
// Description of function/method:
|
||||
// Increments the reference count for an interface on an object.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// Returns an integer from 1 to n, the value of the new reference count.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ULONG _stdcall CAmbientLightAwareSensorManagerEvents::AddRef()
|
||||
{
|
||||
m_lRefCount++;
|
||||
return m_lRefCount;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::Release
|
||||
//
|
||||
// Description of function/method:
|
||||
// Decrements the reference count for the calling interface on a object.
|
||||
// If the reference count on the object falls to 0, the object is freed
|
||||
// from memory.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// Returns an integer from 1 to n, the value of the new reference count.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ULONG _stdcall CAmbientLightAwareSensorManagerEvents::Release()
|
||||
{
|
||||
ULONG lRet = --m_lRefCount;
|
||||
|
||||
if (m_lRefCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return lRet;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::Initialize
|
||||
//
|
||||
// Description of function/method:
|
||||
// Initialize the sensor data.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// HRESULT S_OK on success
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorManagerEvents::Initialize()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_spISensorManager->SetEventSink(this);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Find all Ambient Light Sensors
|
||||
CComPtr<ISensorCollection> spSensors;
|
||||
hr = m_spISensorManager->GetSensorsByType(SENSOR_TYPE_AMBIENT_LIGHT, &spSensors);
|
||||
if (SUCCEEDED(hr) && NULL != spSensors)
|
||||
{
|
||||
ULONG ulCount = 0;
|
||||
hr = spSensors->GetCount(&ulCount);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for(ULONG i=0; i < ulCount; i++)
|
||||
{
|
||||
CComPtr<ISensor> spSensor;
|
||||
hr = spSensors->GetAt(i, &spSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = AddSensor(spSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_pSensorEvents->GetSensorData(spSensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::Uninitialize
|
||||
//
|
||||
// Description of function/method:
|
||||
// Uninitialize the sensor data.
|
||||
//
|
||||
// Parameters:
|
||||
// none
|
||||
//
|
||||
// Return Values:
|
||||
// HRESULT S_OK on success
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorManagerEvents::Uninitialize()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
POSITION pos = m_Sensors.GetStartPosition();
|
||||
while (NULL != pos)
|
||||
{
|
||||
ISensor* pSensor = m_Sensors.GetNextValue(pos);
|
||||
RemoveSensor(pSensor);
|
||||
}
|
||||
|
||||
if (NULL != m_spISensorManager)
|
||||
{
|
||||
hr = m_spISensorManager->SetEventSink(NULL);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::OnSensorEnter
|
||||
//
|
||||
// Description of function/method:
|
||||
// Implementation of ISensorManager.OnSensorEnter. Check if the sensor
|
||||
// is an Ambient Light Sensor and if so then add the sensor.
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor* pSensor: Sensor that has been installed
|
||||
// SensorState state: State of the sensor
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorManagerEvents::OnSensorEnter(__RPC__in_opt ISensor* pSensor, SensorState state)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (NULL != pSensor)
|
||||
{
|
||||
SENSOR_TYPE_ID idType = GUID_NULL;
|
||||
hr = pSensor->GetType(&idType);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (IsEqualIID(idType, SENSOR_TYPE_AMBIENT_LIGHT))
|
||||
{
|
||||
hr = AddSensor(pSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (SENSOR_STATE_READY == state)
|
||||
{
|
||||
hr = m_pSensorEvents->GetSensorData(pSensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::AddSensor
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, sets up event sinking for a sensor and saves the
|
||||
// sensor.
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor *pSensor: Input sensor
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorManagerEvents::AddSensor(ISensor *pSensor)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (NULL != pSensor)
|
||||
{
|
||||
hr = pSensor->SetEventSink(m_pSensorEvents);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Get the sensor's ID to be used as a key to store the sensor
|
||||
SENSOR_ID idSensor = GUID_NULL;
|
||||
hr = pSensor->GetID(&idSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Enter the sensor into the map and take the ownership of its lifetime
|
||||
pSensor->AddRef(); // the sensor is released in the destructor
|
||||
m_Sensors[idSensor] = pSensor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::RemoveSensor
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, clears the event sink for the sensor and then
|
||||
// releases the sensor.
|
||||
//
|
||||
// Parameters:
|
||||
// ISensor *pSensor: Input sensor
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorManagerEvents::RemoveSensor(ISensor* pSensor)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// Release the event and ISensor objecets
|
||||
if (NULL != pSensor)
|
||||
{
|
||||
hr = pSensor->SetEventSink(NULL); // This also decreases the ref count of the sink object.
|
||||
|
||||
SENSOR_ID idSensor = GUID_NULL;
|
||||
hr = pSensor->GetID(&idSensor);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
m_Sensors.RemoveKey(idSensor);
|
||||
}
|
||||
|
||||
pSensor->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAmbientLightAwareSensorManagerEvents::RemoveSensor
|
||||
//
|
||||
// Description of function/method:
|
||||
// Helper function, clears the event sink for the sensor and then
|
||||
// releases the sensor.
|
||||
//
|
||||
// Parameters:
|
||||
// REFSENSOR_ID sensorID: Input sensor
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK on success, else an error
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HRESULT CAmbientLightAwareSensorManagerEvents::RemoveSensor(REFSENSOR_ID sensorID)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (m_Sensors.Lookup(sensorID))
|
||||
{
|
||||
ISensor* pSensor = m_Sensors[sensorID];
|
||||
m_Sensors.RemoveKey(sensorID);
|
||||
pSensor->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module:
|
||||
// AmbientLightAwareSensorManagerEvents.h
|
||||
//
|
||||
// Description:
|
||||
// Implementation of ISensorManagerEvents
|
||||
//
|
||||
// Comments:
|
||||
// This is a standard c++ class, but needs to support IUnknown methods
|
||||
// to be properly implemented. This class overrides
|
||||
// ISensorManagerEvents functions to receive updated information from
|
||||
// the Sensors API when it is published.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
// Forward declaration.
|
||||
class CAmbientLightAwareDlg;
|
||||
|
||||
class CAmbientLightAwareSensorManagerEvents :
|
||||
public ISensorManagerEvents
|
||||
{
|
||||
public:
|
||||
// These three methods are for IUnknown
|
||||
STDMETHOD(QueryInterface)(REFIID riid, void** ppObject );
|
||||
ULONG _stdcall AddRef();
|
||||
ULONG _stdcall Release();
|
||||
|
||||
// Constructor and destructor
|
||||
CAmbientLightAwareSensorManagerEvents(CAmbientLightAwareDlg* dlg);
|
||||
virtual ~CAmbientLightAwareSensorManagerEvents();
|
||||
|
||||
// Initialize and Uninitialize called by parent dialog
|
||||
HRESULT Initialize();
|
||||
HRESULT Uninitialize();
|
||||
|
||||
// ISensorManagerEvents method override
|
||||
STDMETHOD(OnSensorEnter)(__RPC__in_opt ISensor* pSensor, SensorState state);
|
||||
|
||||
// Is a callback from child SensorEvents
|
||||
HRESULT RemoveSensor(REFSENSOR_ID sensorID);
|
||||
|
||||
private:
|
||||
// Member variable to implement IUnknown reference count
|
||||
LONG m_lRefCount;
|
||||
|
||||
// Helper functions
|
||||
HRESULT AddSensor(ISensor* pSensor);
|
||||
HRESULT RemoveSensor(ISensor* pSensor);
|
||||
|
||||
CAmbientLightAwareSensorEvents* m_pSensorEvents; // Sensor Events class used for event sinking
|
||||
CComPtr<ISensorManager> m_spISensorManager; // Global to keep reference for life of class
|
||||
CAtlMap<SENSOR_ID, ISensor*> m_Sensors; // Map to store sensors for life of class
|
||||
};
|
||||
57
Samples/AmbientLightAware/cpp/ReadMe.txt
Normal file
@ -0,0 +1,57 @@
|
||||
=========================
|
||||
Ambient Light Aware
|
||||
Windows 7 Sensor Platform
|
||||
=========================
|
||||
This MFC sample shows how to use the Sensor Platform by reading data from Ambient Light Sensors on the computer and changing a label's font size to be optimized for the reported light conditions. Such as smaller font while inside and larger font while outside in a sunny environment. The sample is not meant to be perfect in optimizing for light conditions, but done to show the usage of the Sensor Platform. This sample requires Visual Studio to be built.
|
||||
|
||||
===============================
|
||||
Sample Language Implementations
|
||||
===============================
|
||||
This sample is available in the following language implementations:
|
||||
C++
|
||||
|
||||
=====
|
||||
Files
|
||||
=====
|
||||
AmbientLightAware.cpp The main CWinApp file
|
||||
AmbientLightAware.h Header file
|
||||
AmbientLightAware.rc Resource file for MFC
|
||||
AmbientLightAware.sln Solution for the project
|
||||
AmbientLightAware.vcproj VS Project file
|
||||
AmbientLightAwareDlg.cpp Dialog class
|
||||
AmbientLightAwareDlg.h Header file
|
||||
AmbientLightAwareSensorManagerEvents.cpp Custom class to handle ISensorManager events
|
||||
AmbientLightAwareSensorManagerEvents.h Header file
|
||||
AmbientLightAwareSensorEvents.cpp Custom class to handle ISensor events
|
||||
AmbientLightAwareSensorEvents.h Header file
|
||||
ReadMe.txt This ReadMe
|
||||
resource.h Resource file
|
||||
stdafx.cpp Precompiled file
|
||||
stdafx.h Precompiled header
|
||||
|
||||
=============
|
||||
Prerequisites
|
||||
=============
|
||||
Windows 7
|
||||
Visual Studio 2008
|
||||
|
||||
========
|
||||
Building
|
||||
========
|
||||
This sample cannot be built in the SDK environment. Visual Studio must be used.
|
||||
To build the sample using Visual Studio 2008:
|
||||
1. Run the Windows SDK Configuration Tool provided with the SDK to add SDK include directories to Visual Studio
|
||||
2. Open File Explorer and navigate to the directory.
|
||||
3. Double-click the icon for the .sln (solution) file to open the file in Visual Studio.
|
||||
4. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory.
|
||||
|
||||
=======
|
||||
Running
|
||||
=======
|
||||
To run the sample:
|
||||
1. Navigate to the directory that contains the new executable, using the command prompt or File Explorer.
|
||||
2. Type AmbientLightAware.exe at the command line, or double-click the icon for AmbientLightAware.exe to launch it from File Explorer.
|
||||
|
||||
To run from Visual Studio:
|
||||
1. Press F5 or Click menu
|
||||
Debug->Start Debugging
|
||||
21
Samples/AmbientLightAware/cpp/resource.h
Normal file
@ -0,0 +1,21 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by AmbientLightAware.rc
|
||||
//
|
||||
#define IDD_AMBIENTLIGHTAWARE_DIALOG 102
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDC_STATIC_LUX 1001
|
||||
#define IDC_STATIC_SAMPLE 1002
|
||||
#define IDC_STATIC_LUX_SENSORS 1003
|
||||
#define IDC_STATIC_SENSORS 1003
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 129
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1003
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
14
Samples/AmbientLightAware/cpp/stdafx.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// AmbientLightAware.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
90
Samples/AmbientLightAware/cpp/stdafx.h
Normal file
@ -0,0 +1,90 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright © Microsoft Corporation. All rights reserved.
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently,
|
||||
// but are changed infrequently
|
||||
|
||||
#pragma once
|
||||
|
||||
// Suppress warning that CComCritSecLock::Lock "Possibly failing to release lock"
|
||||
#pragma warning(disable: 26165)
|
||||
|
||||
// Suppress warning that CComCritSecLock::Unlock "Possibly releasing unheld lock"
|
||||
#pragma warning(disable: 26167)
|
||||
|
||||
#ifndef _SECURE_ATL
|
||||
#define _SECURE_ATL 1
|
||||
#endif
|
||||
|
||||
#ifndef VC_EXTRALEAN
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
#endif
|
||||
|
||||
// Modify the following defines if you have to target a platform prior to the ones specified below.
|
||||
// Refer to MSDN for the latest info on corresponding values for different platforms.
|
||||
#ifndef WINVER // Allow use of features specific to Windows XP or later.
|
||||
#define WINVER 0x0601 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
|
||||
#define _WIN32_WINNT 0x0601 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
|
||||
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
|
||||
#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
|
||||
#endif
|
||||
|
||||
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||
|
||||
// turns off MFC's hiding of some common and often safely ignored warning messages
|
||||
#define _AFX_ALL_WARNINGS
|
||||
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
#include <afxext.h> // MFC extensions
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef _AFX_NO_OLE_SUPPORT
|
||||
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
|
||||
#endif
|
||||
#ifndef _AFX_NO_AFXCMN_SUPPORT
|
||||
#include <afxcmn.h> // MFC support for Windows Common Controls
|
||||
#endif // _AFX_NO_AFXCMN_SUPPORT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef _UNICODE
|
||||
#if defined _M_IX86
|
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#elif defined _M_IA64
|
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#elif defined _M_X64
|
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#else
|
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ****************************************************************************
|
||||
// Sensors related includes
|
||||
// ****************************************************************************
|
||||
#include <sensors.h>
|
||||
#include <sensorsapi.h>
|
||||
#include <atlcoll.h>
|
||||
280
Samples/AmsiProvider/AmsiProvider.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
// Define a trace logging provider: 00604c86-2d25-46d6-b814-cd149bfdf0b3
|
||||
TRACELOGGING_DEFINE_PROVIDER(g_traceLoggingProvider, "SampleAmsiProvider",
|
||||
(0x00604c86, 0x2d25, 0x46d6, 0xb8, 0x14, 0xcd, 0x14, 0x9b, 0xfd, 0xf0, 0xb3));
|
||||
|
||||
HMODULE g_currentModule;
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
g_currentModule = module;
|
||||
DisableThreadLibraryCalls(module);
|
||||
TraceLoggingRegister(g_traceLoggingProvider);
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Loaded");
|
||||
Module<InProc>::GetModule().Create();
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
Module<InProc>::GetModule().Terminate();
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Unloaded");
|
||||
TraceLoggingUnregister(g_traceLoggingProvider);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#pragma region COM server boilerplate
|
||||
HRESULT WINAPI DllCanUnloadNow()
|
||||
{
|
||||
return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv)
|
||||
{
|
||||
return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
// Simple RAII class to ensure memory is freed.
|
||||
template<typename T>
|
||||
class HeapMemPtr
|
||||
{
|
||||
public:
|
||||
HeapMemPtr() { }
|
||||
HeapMemPtr(const HeapMemPtr& other) = delete;
|
||||
HeapMemPtr(HeapMemPtr&& other) : p(other.p) { other.p = nullptr; }
|
||||
HeapMemPtr& operator=(const HeapMemPtr& other) = delete;
|
||||
HeapMemPtr& operator=(HeapMemPtr&& other) {
|
||||
auto t = p; p = other.p; other.p = t;
|
||||
}
|
||||
|
||||
~HeapMemPtr()
|
||||
{
|
||||
if (p) HeapFree(GetProcessHeap(), 0, p);
|
||||
}
|
||||
|
||||
HRESULT Alloc(size_t size)
|
||||
{
|
||||
p = reinterpret_cast<T*>(HeapAlloc(GetProcessHeap(), 0, size));
|
||||
return p ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
T* Get() { return p; }
|
||||
operator bool() { return p != nullptr; }
|
||||
|
||||
private:
|
||||
T* p = nullptr;
|
||||
};
|
||||
|
||||
class
|
||||
DECLSPEC_UUID("2E5D8A62-77F9-4F7B-A90C-2744820139B2")
|
||||
SampleAmsiProvider : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IAntimalwareProvider, FtmBase>
|
||||
{
|
||||
public:
|
||||
IFACEMETHOD(Scan)(_In_ IAmsiStream* stream, _Out_ AMSI_RESULT* result) override;
|
||||
IFACEMETHOD_(void, CloseSession)(_In_ ULONGLONG session) override;
|
||||
IFACEMETHOD(DisplayName)(_Outptr_ LPWSTR* displayName) override;
|
||||
|
||||
private:
|
||||
// We assign each Scan request a unique number for logging purposes.
|
||||
LONG m_requestNumber = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T GetFixedSizeAttribute(_In_ IAmsiStream* stream, _In_ AMSI_ATTRIBUTE attribute)
|
||||
{
|
||||
T result;
|
||||
|
||||
ULONG actualSize;
|
||||
if (SUCCEEDED(stream->GetAttribute(attribute, sizeof(T), reinterpret_cast<PBYTE>(&result), &actualSize)) &&
|
||||
actualSize == sizeof(T))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
HeapMemPtr<wchar_t> GetStringAttribute(_In_ IAmsiStream* stream, _In_ AMSI_ATTRIBUTE attribute)
|
||||
{
|
||||
HeapMemPtr<wchar_t> result;
|
||||
|
||||
ULONG allocSize;
|
||||
ULONG actualSize;
|
||||
if (stream->GetAttribute(attribute, 0, nullptr, &allocSize) == E_NOT_SUFFICIENT_BUFFER &&
|
||||
SUCCEEDED(result.Alloc(allocSize)) &&
|
||||
SUCCEEDED(stream->GetAttribute(attribute, allocSize, reinterpret_cast<PBYTE>(result.Get()), &actualSize)) &&
|
||||
actualSize <= allocSize)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return HeapMemPtr<wchar_t>();
|
||||
}
|
||||
|
||||
BYTE CalculateBufferXor(_In_ LPCBYTE buffer, _In_ ULONGLONG size)
|
||||
{
|
||||
BYTE value = 0;
|
||||
for (ULONGLONG i = 0; i < size; i++)
|
||||
{
|
||||
value ^= buffer[i];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
HRESULT SampleAmsiProvider::Scan(_In_ IAmsiStream* stream, _Out_ AMSI_RESULT* result)
|
||||
{
|
||||
LONG requestNumber = InterlockedIncrement(&m_requestNumber);
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Scan Start", TraceLoggingValue(requestNumber));
|
||||
|
||||
auto appName = GetStringAttribute(stream, AMSI_ATTRIBUTE_APP_NAME);
|
||||
auto contentName = GetStringAttribute(stream, AMSI_ATTRIBUTE_CONTENT_NAME);
|
||||
auto contentSize = GetFixedSizeAttribute<ULONGLONG>(stream, AMSI_ATTRIBUTE_CONTENT_SIZE);
|
||||
auto session = GetFixedSizeAttribute<ULONGLONG>(stream, AMSI_ATTRIBUTE_SESSION);
|
||||
auto contentAddress = GetFixedSizeAttribute<PBYTE>(stream, AMSI_ATTRIBUTE_CONTENT_ADDRESS);
|
||||
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Attributes",
|
||||
TraceLoggingValue(requestNumber),
|
||||
TraceLoggingWideString(appName.Get(), "App Name"),
|
||||
TraceLoggingWideString(contentName.Get(), "Content Name"),
|
||||
TraceLoggingUInt64(contentSize, "Content Size"),
|
||||
TraceLoggingUInt64(session, "Session"),
|
||||
TraceLoggingPointer(contentAddress, "Content Address"));
|
||||
|
||||
if (contentAddress)
|
||||
{
|
||||
// The data to scan is provided in the form of a memory buffer.
|
||||
auto result = CalculateBufferXor(contentAddress, contentSize);
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Memory xor",
|
||||
TraceLoggingValue(requestNumber),
|
||||
TraceLoggingValue(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Provided as a stream. Read it stream a chunk at a time.
|
||||
BYTE cumulativeXor = 0;
|
||||
BYTE chunk[1024];
|
||||
ULONG readSize;
|
||||
for (ULONGLONG position = 0; position < contentSize; position += readSize)
|
||||
{
|
||||
HRESULT hr = stream->Read(position, sizeof(chunk), chunk, &readSize);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
cumulativeXor ^= CalculateBufferXor(chunk, readSize);
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Read chunk",
|
||||
TraceLoggingValue(requestNumber),
|
||||
TraceLoggingValue(position),
|
||||
TraceLoggingValue(readSize),
|
||||
TraceLoggingValue(cumulativeXor));
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Read failed",
|
||||
TraceLoggingValue(requestNumber),
|
||||
TraceLoggingValue(position),
|
||||
TraceLoggingValue(hr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Scan End", TraceLoggingValue(requestNumber));
|
||||
|
||||
// AMSI_RESULT_NOT_DETECTED means "We did not detect a problem but let other providers scan it, too."
|
||||
*result = AMSI_RESULT_NOT_DETECTED;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void SampleAmsiProvider::CloseSession(_In_ ULONGLONG session)
|
||||
{
|
||||
TraceLoggingWrite(g_traceLoggingProvider, "Close session",
|
||||
TraceLoggingValue(session));
|
||||
}
|
||||
|
||||
HRESULT SampleAmsiProvider::DisplayName(_Outptr_ LPWSTR *displayName)
|
||||
{
|
||||
*displayName = const_cast<LPWSTR>(L"Sample AMSI Provider");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CoCreatableClass(SampleAmsiProvider);
|
||||
|
||||
#pragma region Install / uninstall
|
||||
|
||||
HRESULT SetKeyStringValue(_In_ HKEY key, _In_opt_ PCWSTR subkey, _In_opt_ PCWSTR valueName, _In_ PCWSTR stringValue)
|
||||
{
|
||||
LONG status = RegSetKeyValue(key, subkey, valueName, REG_SZ, stringValue, (wcslen(stringValue) + 1) * sizeof(wchar_t));
|
||||
return HRESULT_FROM_WIN32(status);
|
||||
}
|
||||
|
||||
STDAPI DllRegisterServer()
|
||||
{
|
||||
wchar_t modulePath[MAX_PATH];
|
||||
if (GetModuleFileName(g_currentModule, modulePath, ARRAYSIZE(modulePath)) >= ARRAYSIZE(modulePath))
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Create a standard COM registration for our CLSID.
|
||||
// The class must be registered as "Both" threading model
|
||||
// and support multithreaded access.
|
||||
wchar_t clsidString[40];
|
||||
if (StringFromGUID2(__uuidof(SampleAmsiProvider), clsidString, ARRAYSIZE(clsidString)) == 0)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
wchar_t keyPath[200];
|
||||
HRESULT hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Classes\\CLSID\\%ls", clsidString);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, nullptr, L"SampleAmsiProvider");
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Classes\\CLSID\\%ls\\InProcServer32", clsidString);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, nullptr, modulePath);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, L"ThreadingModel", L"Both");
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
// Register this CLSID as an anti-malware provider.
|
||||
hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Microsoft\\AMSI\\Providers\\%ls", clsidString);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = SetKeyStringValue(HKEY_LOCAL_MACHINE, keyPath, nullptr, L"SampleAmsiProvider");
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI DllUnregisterServer()
|
||||
{
|
||||
wchar_t clsidString[40];
|
||||
if (StringFromGUID2(__uuidof(SampleAmsiProvider), clsidString, ARRAYSIZE(clsidString)) == 0)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Unregister this CLSID as an anti-malware provider.
|
||||
wchar_t keyPath[200];
|
||||
HRESULT hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Microsoft\\AMSI\\Providers\\%ls", clsidString);
|
||||
if (FAILED(hr)) return hr;
|
||||
LONG status = RegDeleteTree(HKEY_LOCAL_MACHINE, keyPath);
|
||||
if (status != NO_ERROR && status != ERROR_PATH_NOT_FOUND) return HRESULT_FROM_WIN32(status);
|
||||
|
||||
// Unregister this CLSID as a COM server.
|
||||
hr = StringCchPrintf(keyPath, ARRAYSIZE(keyPath), L"Software\\Classes\\CLSID\\%ls", clsidString);
|
||||
if (FAILED(hr)) return hr;
|
||||
status = RegDeleteTree(HKEY_LOCAL_MACHINE, keyPath);
|
||||
if (status != NO_ERROR && status != ERROR_PATH_NOT_FOUND) return HRESULT_FROM_WIN32(status);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#pragma endregion
|
||||
7
Samples/AmsiProvider/AmsiProvider.def
Normal file
@ -0,0 +1,7 @@
|
||||
LIBRARY
|
||||
|
||||
EXPORTS
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllGetClassObject PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
31
Samples/AmsiProvider/AmsiProvider.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27428.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmsiProvider", "AmsiProvider.vcxproj", "{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Debug|x64.Build.0 = Debug|x64
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Debug|x86.Build.0 = Debug|Win32
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Release|x64.ActiveCfg = Release|x64
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Release|x64.Build.0 = Release|x64
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Release|x86.ActiveCfg = Release|Win32
|
||||
{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5C5A6A8C-50D7-4CDD-AD3E-AC2F73128E3C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
175
Samples/AmsiProvider/AmsiProvider.vcxproj
Normal file
@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{58B32FCA-F385-4500-9A8E-7CBA1FC9BA13}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>AmsiProvider</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;AMSIPROVIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;windowsapp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>AmsiProvider.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;AMSIPROVIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>AmsiProvider.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>kernel32.lib;windowsapp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;AMSIPROVIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>AmsiProvider.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>kernel32.lib;windowsapp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;AMSIPROVIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>AmsiProvider.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>kernel32.lib;windowsapp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AmsiProvider.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="AmsiProvider.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
35
Samples/AmsiProvider/AmsiProvider.vcxproj.filters
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AmsiProvider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="AmsiProvider.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
54
Samples/AmsiProvider/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: IAntimalwareProvider interface sample
|
||||
urlFragment: iantimalwareprovider-sample
|
||||
description: Demonstrates how to use the Antimalware Provider Interface to register as a provider and scan an incoming stream.
|
||||
extendedZipContent:
|
||||
- path: LICENSE
|
||||
target: LICENSE
|
||||
---
|
||||
|
||||
# IAntimalwareProvider interface sample
|
||||
|
||||
Demonstrates how to use the Antimalware Provider Interface to register as a provider and scan an incoming stream.
|
||||
|
||||
The sample implements the
|
||||
[IAntimalwareProvider](https://msdn.microsoft.com/en-us/library/windows/desktop/dn889593(v=vs.85).aspx) interface
|
||||
which receives a stream to be scanned in the form of an IAmsiStream interface.
|
||||
|
||||
The sample demonstrates a simple provider which computes the XOR of all the bytes in the file and logs the results. It reports all streams as safe.
|
||||
|
||||
Note that the provider is loaded as an in-process server, which means that you need to install both 32-bit and 64-bit versions in order to support both 32-bit and 64-bit applications.
|
||||
|
||||
## Instructions
|
||||
|
||||
### Building and installing the sample provider
|
||||
|
||||
1. Load the Project solution.
|
||||
2. Build the Project.
|
||||
3. From an elevated command prompt, go to the output directory and type `regsvr32 AmsiProvider.dll`.
|
||||
|
||||
If your system has other providers installed, they may take priority over the sample provider. To prevent this from happening (for testing purposes), go to the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AMSI\Providers` and `HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AMSI\Providers` registry keys and temporarily rename the other providers so that the system will use the sample provider.
|
||||
|
||||
### Exercising the sample provider
|
||||
|
||||
Events logged by the sample provider can be captured using ETW tools such as xperf. The log files are generated in ETL format so they can be viewed and processed by the Windows Performance Toolkit (WPT), as well as utilities such as *tracerpt.exe* or *xperf.exe*.
|
||||
|
||||
1. From an elevated command prompt, type `xperf.exe -start mySession -f myFile.etl -on 00604c86-2d25-46d6-b814-cd149bfdf0b3` to begin capturing events from the provider used by the sample.
|
||||
2. From an unelevated command prompt, launch PowerShell with the Bypass execution policy.
|
||||
The PowerShell program should be the same bitness as the project you built and installed.
|
||||
* To run 32-bit PowerShell on a 32-bit system, or 64-bit PowerShell on a 64-bit system: `powershell -ep bypass`
|
||||
* To run 32-bit PowerShell on a 64-bit system: `C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell -ep bypass`
|
||||
3. Run some PowerShell commands. For example, type `calc` to launch calc.
|
||||
4. Exit PowerShell.
|
||||
5. From an elevated command prompt, type `xperf.exe -stop mySession` to stop capturing events.
|
||||
6. View the `myFile.etl` trace graphically in WPA, or generate a text version by typing `tracerpt myFile.etl`.
|
||||
|
||||
### Uninstalling the sample provider
|
||||
|
||||
1. From an elevated command prompt, go to the output directory and type `regsvr32 /u AmsiProvider.dll`.
|
||||
2. If you temporarily renamed conflicting providers when you installed the sample provider, rename the keys back.
|
||||
1
Samples/AmsiProvider/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
||||
14
Samples/AmsiProvider/stdafx.h
Normal file
@ -0,0 +1,14 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <TraceLoggingProvider.h>
|
||||
#include <amsi.h>
|
||||
#include <wrl/module.h>
|
||||
|
||||
TRACELOGGING_DECLARE_PROVIDER(g_traceLoggingProvider);
|
||||
325
Samples/AmsiStream/AmsiStream.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
|
||||
constexpr wchar_t AppName[] = L"Contoso Script Engine v3.4.9999.0";
|
||||
|
||||
class CAmsiStreamBase
|
||||
{
|
||||
protected:
|
||||
~CAmsiStreamBase()
|
||||
{
|
||||
free(m_contentName);
|
||||
}
|
||||
|
||||
HRESULT SetContentName(_In_ PCWSTR name)
|
||||
{
|
||||
m_contentName = _wcsdup(name);
|
||||
return m_contentName ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
HRESULT BaseGetAttribute(
|
||||
_In_ AMSI_ATTRIBUTE attribute,
|
||||
_In_ ULONG bufferSize,
|
||||
_Out_writes_bytes_to_(bufferSize, *actualSize) PBYTE buffer,
|
||||
_Out_ ULONG* actualSize)
|
||||
//
|
||||
// Return Values:
|
||||
// S_OK: SUCCESS
|
||||
// E_NOTIMPL: attribute not supported
|
||||
// E_NOT_SUFFICIENT_BUFFER: need a larger buffer, required size in *retSize
|
||||
// E_INVALIDARG: bad arguments
|
||||
// E_NOT_VALID_STATE: object not initialized
|
||||
//
|
||||
{
|
||||
wprintf(L"GetAttribute() called with: attribute = %u, bufferSize = %u\n", attribute, bufferSize);
|
||||
|
||||
if (actualSize == nullptr || (buffer == nullptr && bufferSize > 0)) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*actualSize = 0;
|
||||
|
||||
switch (attribute)
|
||||
{
|
||||
case AMSI_ATTRIBUTE_CONTENT_SIZE:
|
||||
return CopyAttribute(&m_contentSize, sizeof(m_contentSize), bufferSize, buffer, actualSize);
|
||||
|
||||
case AMSI_ATTRIBUTE_CONTENT_NAME:
|
||||
return CopyAttribute(m_contentName, (wcslen(m_contentName) + 1) * sizeof(WCHAR), bufferSize, buffer, actualSize);
|
||||
|
||||
case AMSI_ATTRIBUTE_APP_NAME:
|
||||
return CopyAttribute(AppName, sizeof(AppName), bufferSize, buffer, actualSize);
|
||||
|
||||
case AMSI_ATTRIBUTE_SESSION:
|
||||
constexpr HAMSISESSION session = nullptr; // no session for file stream
|
||||
return CopyAttribute(&session, sizeof(session), bufferSize, buffer, actualSize);
|
||||
}
|
||||
|
||||
return E_NOTIMPL; // unsupport attribute
|
||||
}
|
||||
|
||||
HRESULT CopyAttribute(
|
||||
_In_ const void* resultData,
|
||||
_In_ size_t resultSize,
|
||||
_In_ ULONG bufferSize,
|
||||
_Out_writes_bytes_to_(bufferSize, *actualSize) PBYTE buffer,
|
||||
_Out_ ULONG* actualSize)
|
||||
{
|
||||
*actualSize = (ULONG)resultSize;
|
||||
if (bufferSize < resultSize)
|
||||
{
|
||||
return E_NOT_SUFFICIENT_BUFFER;
|
||||
}
|
||||
memcpy_s(buffer, bufferSize, resultData, resultSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ULONGLONG m_contentSize = 0;
|
||||
PWSTR m_contentName = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class CAmsiFileStream : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IAmsiStream>, CAmsiStreamBase
|
||||
{
|
||||
public:
|
||||
HRESULT RuntimeClassInitialize(_In_ LPCWSTR fileName)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = SetContentName(fileName);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
m_fileHandle.Attach(CreateFileW(fileName,
|
||||
GENERIC_READ, // dwDesiredAccess
|
||||
0, // dwShareMode
|
||||
nullptr, // lpSecurityAttributes
|
||||
OPEN_EXISTING, // dwCreationDisposition
|
||||
FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
|
||||
nullptr)); // hTemplateFile
|
||||
|
||||
if (!m_fileHandle.IsValid())
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
wprintf(L"Unable to open file %s, hr = 0x%x\n", fileName, hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(m_fileHandle.Get(), &fileSize))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
wprintf(L"GetFileSizeEx failed with 0x%x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
m_contentSize = (ULONGLONG)fileSize.QuadPart;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IAmsiStream
|
||||
|
||||
STDMETHOD(GetAttribute)(
|
||||
_In_ AMSI_ATTRIBUTE attribute,
|
||||
_In_ ULONG bufferSize,
|
||||
_Out_writes_bytes_to_(bufferSize, *actualSize) PBYTE buffer,
|
||||
_Out_ ULONG* actualSize)
|
||||
{
|
||||
return BaseGetAttribute(attribute, bufferSize, buffer, actualSize);
|
||||
}
|
||||
|
||||
STDMETHOD(Read)(
|
||||
_In_ ULONGLONG position,
|
||||
_In_ ULONG size,
|
||||
_Out_writes_bytes_to_(size, *readSize) PBYTE buffer,
|
||||
_Out_ ULONG* readSize)
|
||||
{
|
||||
wprintf(L"Read() called with: position = %I64u, size = %u\n", position, size);
|
||||
|
||||
OVERLAPPED o = {};
|
||||
o.Offset = LODWORD(position);
|
||||
o.OffsetHigh = HIDWORD(position);
|
||||
|
||||
if (!ReadFile(m_fileHandle.Get(), buffer, size, readSize, &o))
|
||||
{
|
||||
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
wprintf(L"ReadFile failed with 0x%x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
FileHandle m_fileHandle;
|
||||
};
|
||||
|
||||
const char SampleStream[] = "Hello, world";
|
||||
|
||||
class CAmsiMemoryStream : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IAmsiStream>, CAmsiStreamBase
|
||||
{
|
||||
public:
|
||||
HRESULT RuntimeClassInitialize()
|
||||
{
|
||||
m_contentSize = sizeof(SampleStream);
|
||||
return SetContentName(L"Sample content.txt");
|
||||
}
|
||||
|
||||
// IAmsiStream
|
||||
|
||||
STDMETHOD(GetAttribute)(
|
||||
_In_ AMSI_ATTRIBUTE attribute,
|
||||
_In_ ULONG bufferSize,
|
||||
_Out_writes_bytes_to_(bufferSize, *actualSize) PBYTE buffer,
|
||||
_Out_ ULONG* actualSize)
|
||||
{
|
||||
HRESULT hr = BaseGetAttribute(attribute, bufferSize, buffer, actualSize);
|
||||
if (hr == E_NOTIMPL)
|
||||
{
|
||||
switch (attribute)
|
||||
{
|
||||
case AMSI_ATTRIBUTE_CONTENT_ADDRESS:
|
||||
const void* contentAddress = SampleStream;
|
||||
hr = CopyAttribute(&contentAddress, sizeof(contentAddress), bufferSize, buffer, actualSize);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHOD(Read)(
|
||||
_In_ ULONGLONG position,
|
||||
_In_ ULONG size,
|
||||
_Out_writes_bytes_to_(size, *readSize) PBYTE buffer,
|
||||
_Out_ ULONG* readSize)
|
||||
{
|
||||
wprintf(L"Read() called with: position = %I64u, size = %u\n", position, size);
|
||||
|
||||
*readSize = 0;
|
||||
if (position >= m_contentSize)
|
||||
{
|
||||
wprintf(L"Reading beyond end of stream\n");
|
||||
return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
|
||||
}
|
||||
|
||||
if (size > m_contentSize - position) {
|
||||
size = static_cast<ULONG>(m_contentSize - position);
|
||||
}
|
||||
|
||||
*readSize = size;
|
||||
memcpy_s(buffer, size, SampleStream + position, size);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class CStreamScanner
|
||||
{
|
||||
public:
|
||||
HRESULT Initialize()
|
||||
{
|
||||
return CoCreateInstance(
|
||||
__uuidof(CAntimalware),
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&m_antimalware));
|
||||
}
|
||||
|
||||
HRESULT ScanStream(_In_ IAmsiStream* stream)
|
||||
{
|
||||
wprintf(L"Calling antimalware->Scan() ...\n");
|
||||
ComPtr<IAntimalwareProvider> provider;
|
||||
AMSI_RESULT r;
|
||||
HRESULT hr = m_antimalware->Scan(stream, &r, &provider);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
wprintf(L"Scan result is %u. IsMalware: %d\n", r, AmsiResultIsMalware(r));
|
||||
|
||||
if (provider) {
|
||||
PWSTR name;
|
||||
hr = provider->DisplayName(&name);
|
||||
if (SUCCEEDED(hr)) {
|
||||
wprintf(L"Provider display name: %s\n", name);
|
||||
CoTaskMemFree(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf(L"DisplayName failed with 0x%x", hr);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
ComPtr<IAntimalware> m_antimalware;
|
||||
};
|
||||
|
||||
HRESULT ScanArguments(_In_ int argc, _In_reads_(argc) wchar_t** argv)
|
||||
{
|
||||
CStreamScanner scanner;
|
||||
HRESULT hr = scanner.Initialize();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
// Scan a single memory stream.
|
||||
wprintf(L"Creating memory stream object\n");
|
||||
|
||||
ComPtr<IAmsiStream> stream;
|
||||
hr = MakeAndInitialize<CAmsiMemoryStream>(&stream);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = scanner.ScanStream(stream.Get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scan the files passed on the command line.
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
LPWSTR fileName = argv[i];
|
||||
|
||||
wprintf(L"Creating stream object with file name: %s\n", fileName);
|
||||
ComPtr<IAmsiStream> stream;
|
||||
hr = MakeAndInitialize<CAmsiFileStream>(&stream, fileName);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = scanner.ScanStream(stream.Get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int __cdecl wmain(_In_ int argc, _In_reads_(argc) WCHAR **argv)
|
||||
{
|
||||
|
||||
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = ScanArguments(argc, argv);
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
wprintf(L"Leaving with hr = 0x%x\n", hr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
36
Samples/AmsiStream/AmsiStream.filters
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ConsoleApplication4.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
31
Samples/AmsiStream/AmsiStream.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2020
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmsiStream", "AmsiStream.vcxproj", "{6CC971B8-BFDA-441E-876E-140451F5B309}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Debug|x64.Build.0 = Debug|x64
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Release|x64.ActiveCfg = Release|x64
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Release|x64.Build.0 = Release|x64
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6CC971B8-BFDA-441E-876E-140451F5B309}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5039118B-DA9C-4510-9788-50BFA6B2FCF5}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
161
Samples/AmsiStream/AmsiStream.vcxproj
Normal file
@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{6CC971B8-BFDA-441E-876E-140451F5B309}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ConsoleApplication4</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>amsi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AmsiStream.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
47
Samples/AmsiStream/README.md
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: IAmsiStream interface sample
|
||||
urlFragment: iamsistream-sample
|
||||
description: Demonstrates how to use the Antimalware Scan Interface to scan a stream.
|
||||
extendedZipContent:
|
||||
- path: LICENSE
|
||||
target: LICENSE
|
||||
---
|
||||
|
||||
# IAmsiStream interface sample
|
||||
|
||||
Demonstrates how to use the Antimalware Scan Interface to scan a stream.
|
||||
|
||||
The sample implements the [IAmsiStream](https://msdn.microsoft.com/en-us/library/windows/desktop/dn889589(v=vs.85).aspx) interface so that an antimalware provider can use it to scan the contents of a stream.
|
||||
|
||||
The sample demonstrates a stream where the data comes from a file and a stream where the data comes from an in-memory buffer.
|
||||
|
||||
## Instructions
|
||||
1. Load the Project solution.
|
||||
2. Go to **Project Properties, Debugging**.
|
||||
3. To scan an in-memory buffer, leave the *Command Arguments* blank. To scan a file, enter the file's complete path in the *Command Arguments*.
|
||||
4. Press **F5** to build and run.
|
||||
|
||||
## Sample output
|
||||
|
||||
Creating stream object with file name: C:\sample.txt
|
||||
Calling antimalware->Scan() ...
|
||||
GetAttribute() called with: attribute = 0, bufferSize = 1
|
||||
GetAttribute() called with: attribute = 0, bufferSize = 68
|
||||
GetAttribute() called with: attribute = 1, bufferSize = 1
|
||||
GetAttribute() called with: attribute = 1, bufferSize = 28
|
||||
GetAttribute() called with: attribute = 2, bufferSize = 8
|
||||
GetAttribute() called with: attribute = 3, bufferSize = 8
|
||||
Read() called with: position = 0, size = 507
|
||||
GetAttribute() called with: attribute = 4, bufferSize = 8
|
||||
GetAttribute() called with: attribute = 6, bufferSize = 8
|
||||
GetAttribute() called with: attribute = 8, bufferSize = 8
|
||||
GetAttribute() called with: attribute = 2, bufferSize = 8
|
||||
GetAttribute() called with: attribute = 3, bufferSize = 8
|
||||
Scan result is 1. IsMalware: 0
|
||||
Provider display name: Windows Defender Antivirus
|
||||
Leaving with hr = 0x0
|
||||
8
Samples/AmsiStream/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// $safeprojectname$.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
14
Samples/AmsiStream/stdafx.h
Normal file
@ -0,0 +1,14 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <amsi.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <wrl\implements.h>
|
||||
#include <wrl\wrappers\corewrappers.h>
|
||||
#include <memory>
|
||||
65
Samples/AppTabsIntegration/README.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: Tab Integration sample
|
||||
urlFragment: apptabsintegration-sample
|
||||
description: Demonstrates how tabbed apps can expose their tabs to the system.
|
||||
extendedZipContent:
|
||||
- path: LICENSE
|
||||
target: LICENSE
|
||||
---
|
||||
|
||||
# Tab Integration sample
|
||||
|
||||
This sample shows how a tabbed app can expose its tabs to the system.
|
||||
|
||||
* Detecting whether WindowTab support exists on the system.
|
||||
* Obtaining the WindowTabManager for a window.
|
||||
* Associating each app tab with a WindowTab object.
|
||||
* Updating the list of WindowTabs when the app tabs change.
|
||||
* Updating the the WindowTab as the app tab's state changes.
|
||||
* Setting the WindowTab as active when the user changes tabs.
|
||||
* Providing thumbnails for tabs.
|
||||
* Responding to system-initiated tab switches.
|
||||
* Responding to system-initiated tab tear-out.
|
||||
|
||||
**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server.
|
||||
|
||||
This sample was created for Windows 11 using features added in the May 2023 release, using Visual Studio and the Windows SDK 10.0.22621.1778, but it should also work with later versions of Windows and the Windows SDK.
|
||||
|
||||
To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696).
|
||||
|
||||
To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697).
|
||||
|
||||
## Related topics
|
||||
|
||||
[**WindowTabManager**](https://learn.microsoft.com/en-us/uwp/api/windows.ui.shell.windowtabmanager)
|
||||
|
||||
## Operating system requirements
|
||||
|
||||
Windows 11 May 2023 release
|
||||
|
||||
## Build the sample
|
||||
|
||||
* Install the Windows SDK version 10.0.22621.1778 or higher.
|
||||
* Open the solution (*.sln*) file titled *AppTabsIntegration.sln* from Visual Studio.
|
||||
* **Important**: Add a reference to the Desktop Extension SDK version 10.0.22621.1778 or higher. (If you forget, the build will remind you.)
|
||||
* Press Ctrl+Shift+B or select **Build** \> **Build Solution**.
|
||||
|
||||
## Run the sample
|
||||
|
||||
Press F5 or select Debug \> Start Debugging. To run the sample without debugging, press Ctrl+F5 or select Debug \> Start Without Debugging.
|
||||
|
||||
Things to try with the sample:
|
||||
|
||||
* Use the + button to create multiple tabs.
|
||||
* Alt+Tab integration: Requires "Show tabs from apps when snapping or pressing Alt+Tab" in Settings to show recent tabs.
|
||||
* Press Alt+Tab and observe that additional tabs show up in the Alt+Tab list in addition to the active tab. The app itself is represented by the active tab. The most recently used non-active tabs show up as separate windows in the Alt+Tab UI.
|
||||
* Select one of the non-active tabs. Observe that the app switches tabs to the tab you selected.
|
||||
* Snap Assist integration: Requires Alt+Tab integration, as well as "Snap windows" and "When I snap a window, suggest what I can snap next to it" to be enabled.
|
||||
* Snap the app window to trigger Snap Assist. Observe that the most recently used non-active tabs show up as snap options.
|
||||
* Select one of the non-active tabs of the window that you snapped. Observe that the tab is "torn out" and placed next to the snapped window.
|
||||
* Select a tab, change its title, and change its color. Repeat the above steps to observe that the changes are reflected in the Alt+Tab and Snap Assist UI.
|
||||
6
Samples/AppTabsIntegration/cpp/App.idl
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace AppTabsIntegration
|
||||
{
|
||||
}
|
||||
18
Samples/AppTabsIntegration/cpp/App.xaml
Normal file
@ -0,0 +1,18 @@
|
||||
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
|
||||
<!-- Licensed under the MIT License. -->
|
||||
|
||||
<Application
|
||||
x:Class="AppTabsIntegration.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:AppTabsIntegration">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
48
Samples/AppTabsIntegration/cpp/App.xaml.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "App.xaml.h"
|
||||
#include "MainWindow.xaml.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Microsoft::UI::Xaml;
|
||||
using namespace Microsoft::UI::Xaml::Controls;
|
||||
using namespace Microsoft::UI::Xaml::Navigation;
|
||||
using namespace AppTabsIntegration;
|
||||
using namespace AppTabsIntegration::implementation;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
App::App()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
|
||||
UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e)
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
auto errorMessage = e.Message();
|
||||
__debugbreak();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched.
|
||||
/// </summary>
|
||||
/// <param name="e">Details about the launch request and process.</param>
|
||||
void App::OnLaunched(LaunchActivatedEventArgs const&)
|
||||
{
|
||||
window = make<MainWindow>();
|
||||
window.Activate();
|
||||
}
|
||||
19
Samples/AppTabsIntegration/cpp/App.xaml.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "App.xaml.g.h"
|
||||
|
||||
namespace winrt::AppTabsIntegration::implementation
|
||||
{
|
||||
struct App : AppT<App>
|
||||
{
|
||||
App();
|
||||
|
||||
void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&);
|
||||
|
||||
private:
|
||||
winrt::Microsoft::UI::Xaml::Window window{ nullptr };
|
||||
};
|
||||
}
|
||||
43
Samples/AppTabsIntegration/cpp/AppTabsIntegration.sln
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.33502.453
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppTabsIntegration", "AppTabsIntegration.vcxproj", "{4FCF5980-C8B1-4E00-93D9-F79C7B718387}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|x64.Build.0 = Debug|x64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|x64.ActiveCfg = Release|x64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|x64.Build.0 = Release|x64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|x64.Deploy.0 = Release|x64
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|x86.Build.0 = Release|Win32
|
||||
{4FCF5980-C8B1-4E00-93D9-F79C7B718387}.Release|x86.Deploy.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {21BA6E0B-FCDD-4DA9-AFDC-AD787992E696}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
208
Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj
Normal file
@ -0,0 +1,208 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||
<MinimalCoreWin>true</MinimalCoreWin>
|
||||
<ProjectGuid>{4fcf5980-c8b1-4e00-93d9-f79c7b718387}</ProjectGuid>
|
||||
<ProjectName>AppTabsIntegration</ProjectName>
|
||||
<RootNamespace>AppTabsIntegration</RootNamespace>
|
||||
<!--
|
||||
$(TargetName) should be same as $(RootNamespace) so that the produced binaries (.exe/.pri/etc.)
|
||||
have a name that matches the .winmd
|
||||
-->
|
||||
<TargetName>$(RootNamespace)</TargetName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>16.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>false</AppContainerApplication>
|
||||
<AppxPackage>true</AppxPackage>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<EnableMsixTooling>true</EnableMsixTooling>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<DesktopCompatible>true</DesktopCompatible>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup Condition="'$(WindowsPackageType)'!='None' and Exists('Package.appxmanifest')">
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="App.xaml.h">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MainWindow.xaml.h">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TabViewModel.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml" />
|
||||
<Page Include="MainWindow.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="App.xaml.cpp">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MainWindow.xaml.cpp">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="TabViewModel.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="App.idl">
|
||||
<SubType>Code</SubType>
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Midl>
|
||||
<Midl Include="MainWindow.idl">
|
||||
<SubType>Code</SubType>
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
</Midl>
|
||||
<Midl Include="TabViewModel.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="readme.txt">
|
||||
<DeploymentContent>false</DeploymentContent>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\icon.ico" />
|
||||
<Image Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Image Include="Assets\SplashScreen.scale-200.png" />
|
||||
<Image Include="Assets\Square150x150Logo.scale-200.png" />
|
||||
<Image Include="Assets\Square44x44Logo.scale-200.png" />
|
||||
<Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Image Include="Assets\StoreLogo.png" />
|
||||
<Image Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||
</ItemGroup>
|
||||
<!--
|
||||
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
|
||||
Tools extension to be activated for this project even if the Windows App SDK Nuget
|
||||
package has not yet been restored.
|
||||
-->
|
||||
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<ProjectCapability Include="Msix" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<!--
|
||||
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
|
||||
Explorer "Package and Publish" context menu entry to be enabled for this project even if
|
||||
the Windows App SDK Nuget package has not yet been restored.
|
||||
-->
|
||||
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
<Import Project="packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
<Error Condition="!Exists('packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.WindowsAppSDK.1.2.221109.1\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MainWindow.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="App.idl" />
|
||||
<Midl Include="MainWindow.idl" />
|
||||
<Midl Include="TabViewModel.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="TabViewModel.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="TabViewModel.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\Wide310x150Logo.scale-200.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\StoreLogo.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\Square150x150Logo.scale-200.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\Square44x44Logo.scale-200.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\SplashScreen.scale-200.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\LockScreenLogo.scale-200.png">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\icon.ico">
|
||||
<Filter>Assets</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Assets">
|
||||
<UniqueIdentifier>{4fcf5980-c8b1-4e00-93d9-f79c7b718387}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="readme.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
After Width: | Height: | Size: 432 B |
BIN
Samples/AppTabsIntegration/cpp/Assets/SplashScreen.scale-200.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 283 B |
BIN
Samples/AppTabsIntegration/cpp/Assets/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 456 B |
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Samples/AppTabsIntegration/cpp/Assets/icon.ico
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
13
Samples/AppTabsIntegration/cpp/MainWindow.idl
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import "TabViewModel.idl";
|
||||
|
||||
namespace AppTabsIntegration
|
||||
{
|
||||
[default_interface]
|
||||
runtimeclass MainWindow : Microsoft.UI.Xaml.Window
|
||||
{
|
||||
MainWindow();
|
||||
}
|
||||
}
|
||||
38
Samples/AppTabsIntegration/cpp/MainWindow.xaml
Normal file
@ -0,0 +1,38 @@
|
||||
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
|
||||
<!-- Licensed under the MIT License. -->
|
||||
|
||||
<Window
|
||||
x:Class="AppTabsIntegration.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:AppTabsIntegration"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<TabView x:Name="MainWindowTabView"
|
||||
CanDragTabs="True"
|
||||
CanReorderTabs="True"
|
||||
SelectionChanged="TabView_SelectionChanged"
|
||||
AddTabButtonClick="TabView_AddTabClicked"
|
||||
TabCloseRequested="TabView_CloseRequested"
|
||||
TabDroppedOutside="TabView_TabDroppedOutside"
|
||||
VerticalAlignment="Stretch">
|
||||
<TabView.TabItemTemplate>
|
||||
<DataTemplate x:DataType="local:TabViewModel">
|
||||
<TabViewItem Header="{x:Bind Name, Mode=OneWay}">
|
||||
<TabViewItem.Content>
|
||||
<StackPanel Orientation="Vertical" Padding="10">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Text="Tab title:" Margin="0,0,10,0" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{x:Bind Name, Mode=TwoWay}" VerticalAlignment="Center" Margin="0,0,10,0"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="Tab thumbnail color:" Margin="0,10,00,0" HorizontalAlignment="Left"/>
|
||||
<ColorPicker Color="{x:Bind Color, Mode=TwoWay}" HorizontalAlignment="Left"/>
|
||||
</StackPanel>
|
||||
</TabViewItem.Content>
|
||||
</TabViewItem>
|
||||
</DataTemplate>
|
||||
</TabView.TabItemTemplate>
|
||||
</TabView>
|
||||
</Window>
|
||||
327
Samples/AppTabsIntegration/cpp/MainWindow.xaml.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "MainWindow.xaml.h"
|
||||
#if __has_include("MainWindow.g.cpp")
|
||||
#include "MainWindow.g.cpp"
|
||||
#endif
|
||||
#include "TabViewModel.h"
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
using namespace winrt::AppTabsIntegration;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::Foundation::Metadata;
|
||||
using namespace winrt::Windows::Graphics::Imaging;
|
||||
using namespace winrt::Windows::Storage::Streams;
|
||||
using namespace winrt::Windows::UI::Shell;
|
||||
using namespace winrt::Microsoft::UI::Xaml;
|
||||
using namespace winrt::Microsoft::UI::Xaml::Controls;
|
||||
using namespace winrt::Microsoft::UI::Xaml::Media::Imaging;
|
||||
}
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace
|
||||
{
|
||||
// Helper for making Windows.UI.WindowId objects from HWNDs.
|
||||
winrt::Windows::UI::WindowId WindowsWindowIdFromHwnd(HWND hwnd)
|
||||
{
|
||||
static_assert(sizeof(winrt::Windows::UI::WindowId) == sizeof(winrt::Microsoft::UI::WindowId));
|
||||
auto id = winrt::Microsoft::UI::GetWindowIdFromWindow(hwnd);
|
||||
return reinterpret_cast<winrt::Windows::UI::WindowId&>(id);
|
||||
}
|
||||
}
|
||||
|
||||
namespace winrt::AppTabsIntegration::implementation
|
||||
{
|
||||
MainWindow::MainWindow(winrt::TabViewModel const& initialTab)
|
||||
{
|
||||
InitializeComponent();
|
||||
m_dispatcherQueue = this->DispatcherQueue();
|
||||
MainWindowTabView().TabItemsSource(m_tabs);
|
||||
|
||||
// Retrieve the window handle (HWND) of this WinUI 3 window.
|
||||
HWND hwnd;
|
||||
winrt::check_hresult(this->try_as<::IWindowNative>()->get_WindowHandle(&hwnd));
|
||||
|
||||
// Apply right-to-left flow direction if this window has right-to-left layout.
|
||||
if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
|
||||
{
|
||||
this->Content().as<winrt::FrameworkElement>().FlowDirection(FlowDirection::RightToLeft);
|
||||
}
|
||||
|
||||
// Add WindowTabManager support if it is available.
|
||||
if (ApiInformation::IsApiContractPresent(winrt::name_of<WindowTabManagerContract>(), 1) && WindowTabManager::IsSupported())
|
||||
{
|
||||
// Get the WindowTabManager for this window.
|
||||
m_tabManager = WindowTabManager::GetForWindow(WindowsWindowIdFromHwnd(hwnd));
|
||||
|
||||
// Register WindowTabManager events so we can respond to requests from the system.
|
||||
m_tabSwitchRevoker = m_tabManager.TabSwitchRequested(winrt::auto_revoke, { get_weak(), &MainWindow::TabSwitchRequested});
|
||||
m_tabCloseRevoker = m_tabManager.TabCloseRequested(winrt::auto_revoke, { get_weak(), &MainWindow::TabCloseRequested });
|
||||
m_tabThumbnailRequestedRevoker = m_tabManager.TabThumbnailRequested(winrt::auto_revoke, { get_weak(), &MainWindow::TabThumbnailRequested });
|
||||
|
||||
// You can use WindowTabManager::IsTabTearOutSupported() to detect whether the system supports tab tear-out.
|
||||
// If the feature is not supported, then the TabTearOutRequested event is never raised, but it's still okay
|
||||
// to register a handler for it.
|
||||
m_tabTearOutRequestedRevoker = m_tabManager.TabTearOutRequested(winrt::auto_revoke, { get_weak(), &MainWindow::TabTearOutRequested });
|
||||
}
|
||||
|
||||
// Subscribe to vector changes so we can keep the WindowTabManager in sync.
|
||||
// This is also how we learn about XAML tab rearrangement.
|
||||
m_tabs.VectorChanged({ get_weak(), &MainWindow::TabCollection_VectorChanged });
|
||||
|
||||
// Insert the initial app tab.
|
||||
// The VectorChanged event handler will update the WindowTabManager.
|
||||
if (initialTab)
|
||||
{
|
||||
// Caller provided an initial tab.
|
||||
m_tabs.Append(initialTab);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a default initial tab.
|
||||
m_tabs.Append(CreateTabViewModel());
|
||||
}
|
||||
}
|
||||
|
||||
winrt::TabViewModel MainWindow::CreateTabViewModel()
|
||||
{
|
||||
static int s_counter = 0;
|
||||
|
||||
winrt::hstring tabName = L"Tab #" + winrt::to_hstring(++s_counter);
|
||||
WindowTab windowTab{ nullptr };
|
||||
|
||||
if (m_tabManager)
|
||||
{
|
||||
// Make a WindowTab that is the counterpart to our app tab.
|
||||
windowTab = WindowTab();
|
||||
|
||||
// The Icon of the WindowTab should match the icon of the tab in the app (if any).
|
||||
RandomAccessStreamReference icoStream = RandomAccessStreamReference::CreateFromUri(Uri(L"ms-appx:///Assets/icon.ico"));
|
||||
windowTab.Icon(WindowTabIcon::CreateFromImage(icoStream));
|
||||
}
|
||||
|
||||
// Create a tab to add to our TabView.
|
||||
auto const tabViewModel = winrt::make<TabViewModel>(tabName, windowTab);
|
||||
|
||||
return tabViewModel;
|
||||
}
|
||||
|
||||
// Handle the XAML event that tells us that the user wants to close a tab.
|
||||
// This event is raised on the UI thread.
|
||||
void MainWindow::TabView_CloseRequested(TabView const&, TabViewTabCloseRequestedEventArgs const& args)
|
||||
{
|
||||
auto const tabViewModel = args.Item().as<winrt::TabViewModel>();
|
||||
RemoveTabByItem(tabViewModel);
|
||||
}
|
||||
|
||||
// Handle the XAML event that tells us that the user wants to create a new tab.
|
||||
// This event is raised on the UI thread.
|
||||
void MainWindow::TabView_AddTabClicked(TabView const&, IInspectable const&)
|
||||
{
|
||||
// Add a new TabViewModel to our app's TabView.
|
||||
winrt::TabViewModel tabViewModel = CreateTabViewModel();
|
||||
|
||||
// The VectorChanged event handler will update the WindowTabManager.
|
||||
m_tabs.Append(tabViewModel);
|
||||
|
||||
// Auto-select the newly-added tab.
|
||||
MainWindowTabView().SelectedItem(tabViewModel);
|
||||
}
|
||||
|
||||
// Handle the XAML event that tells us that the user switched tabs.
|
||||
// This event is raised on the UI thread.
|
||||
void MainWindow::TabView_SelectionChanged(IInspectable const&, SelectionChangedEventArgs const&)
|
||||
{
|
||||
auto const tabModel = MainWindowTabView().SelectedItem().as<winrt::TabViewModel>();
|
||||
if (m_tabManager && tabModel)
|
||||
{
|
||||
// Tell the WindowTabManager that we have changed active tabs.
|
||||
m_tabManager.SetActiveTab(TabViewModel::GetWindowTab(tabModel));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the XAML event that tells us that the user tore out a tab.
|
||||
// This event is raised on the UI thread.
|
||||
void MainWindow::TabView_TabDroppedOutside(TabView const&, TabViewTabDroppedOutsideEventArgs const& args)
|
||||
{
|
||||
// Don't let the user tear out the last tab.
|
||||
if (m_tabs.Size() < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the tab from this window
|
||||
winrt::TabViewModel tabViewModel = args.Item().as<winrt::TabViewModel>();
|
||||
RemoveTabByItem(tabViewModel);
|
||||
|
||||
// Create another MainWindow with that tab as its only tab.
|
||||
auto tornOut = winrt::make<MainWindow>(tabViewModel);
|
||||
|
||||
// Position the window under the cursor.
|
||||
POINT pos;
|
||||
if (GetCursorPos(&pos))
|
||||
{
|
||||
HWND hwnd;
|
||||
winrt::check_hresult(tornOut.try_as<::IWindowNative>()->get_WindowHandle(&hwnd));
|
||||
RECT rect;
|
||||
GetWindowRect(hwnd, &rect);
|
||||
MapWindowPoints(HWND_DESKTOP, hwnd, reinterpret_cast<LPPOINT>(&rect), 2);
|
||||
if (this->Content().as<winrt::FrameworkElement>().FlowDirection() == FlowDirection::RightToLeft)
|
||||
{
|
||||
RECT clientRect;
|
||||
GetClientRect(hwnd, &clientRect);
|
||||
pos.x -= clientRect.right;
|
||||
}
|
||||
SetWindowPos(hwnd, nullptr, pos.x + rect.left, pos.y + rect.top,
|
||||
0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
// Show the new window.
|
||||
tornOut.Activate();
|
||||
}
|
||||
|
||||
// Handle the IObservableVector event that tells us that the list of TabDataModel objects changed.
|
||||
// This event is raised on the UI thread.
|
||||
void MainWindow::TabCollection_VectorChanged(IObservableVector<winrt::TabViewModel> const&, IVectorChangedEventArgs const& args)
|
||||
{
|
||||
// Keep the WindowTabManager's tab list in sync with our app's TabView tab list.
|
||||
if (m_tabManager)
|
||||
{
|
||||
auto index = args.Index();
|
||||
switch (args.CollectionChange())
|
||||
{
|
||||
case CollectionChange::ItemInserted:
|
||||
m_tabManager.Tabs().InsertAt(index, TabViewModel::GetWindowTab(m_tabs.GetAt(index)));
|
||||
break;
|
||||
case CollectionChange::ItemRemoved:
|
||||
m_tabManager.Tabs().RemoveAt(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the window title to reflect the number of tabs.
|
||||
auto const tabCount = m_tabs.Size();
|
||||
if (tabCount == 1)
|
||||
{
|
||||
this->Title(L"AppTabsIntegration Sample (1 tab)");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Title(L"AppTabsIntegration Sample (" + winrt::to_hstring(tabCount) + L" tabs)");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the system event that tells us that the user used the system to select a tab in our app.
|
||||
// This event can be raised on any thread, so we explicitly switch to the UI thread before doing work.
|
||||
fire_and_forget MainWindow::TabSwitchRequested(WindowTabManager const&, WindowTabSwitchRequestedEventArgs args)
|
||||
{
|
||||
// Take a strong reference to the MainWindow so it doesn't get destructed while we co_await.
|
||||
auto strongThis = get_strong();
|
||||
co_await wil::resume_foreground(m_dispatcherQueue);
|
||||
|
||||
// Switch to that tab in our UI. When we get the TabView.SelectionChanged event,
|
||||
// we will update the WindowTabManager to let it know that the switch has occurred.
|
||||
winrt::TabViewModel tabViewModel = TabViewModel::GetFromWindowTab(args.Tab());
|
||||
MainWindowTabView().SelectedItem(tabViewModel);
|
||||
}
|
||||
|
||||
// Handle the system event that tells us that the user used the system to close a tab in our app.
|
||||
// This event can be raised on any thread, so we explicitly switch to the UI thread before doing work.
|
||||
fire_and_forget MainWindow::TabCloseRequested(WindowTabManager const&, WindowTabCloseRequestedEventArgs args)
|
||||
{
|
||||
// Take a strong reference to the MainWindow so it doesn't get destructed while we co_await.
|
||||
auto strongThis = get_strong();
|
||||
co_await wil::resume_foreground(m_dispatcherQueue);
|
||||
|
||||
winrt::TabViewModel tabViewModel = TabViewModel::GetFromWindowTab(args.Tab());
|
||||
RemoveTabByItem(tabViewModel);
|
||||
}
|
||||
|
||||
// Handle the system event that tells us that the system wants us to produce a thumbnail of a tab.
|
||||
// This event can be raised on any thread, so we explicitly switch to the UI thread before doing work.
|
||||
fire_and_forget MainWindow::TabThumbnailRequested(WindowTabManager const&, WindowTabThumbnailRequestedEventArgs args)
|
||||
{
|
||||
// Take a strong reference to the MainWindow so it doesn't get destructed while we co_await.
|
||||
auto strongThis = get_strong();
|
||||
|
||||
// Take a deferral before we co_await so the system knows that we are still working on the thumbnail.
|
||||
auto deferral = args.GetDeferral();
|
||||
co_await wil::resume_foreground(m_dispatcherQueue);
|
||||
|
||||
// For demonstration purposes, the thumbnail for a tab is the tab's solid color.
|
||||
// A real program would probably generate a thumbnail image of the tab contents.
|
||||
winrt::TabViewModel tabViewModel = TabViewModel::GetFromWindowTab(args.Tab());
|
||||
auto color = tabViewModel.Color();
|
||||
uint8_t pixel[4] = { color.B, color.G, color.R, 0xFF };
|
||||
auto inMemoryStream = InMemoryRandomAccessStream();
|
||||
auto encoder = co_await BitmapEncoder::CreateAsync(BitmapEncoder::PngEncoderId(), inMemoryStream);
|
||||
encoder.SetPixelData(
|
||||
BitmapPixelFormat::Bgra8, BitmapAlphaMode::Ignore,
|
||||
1, 1, 96, 96, pixel);
|
||||
|
||||
auto size = args.RequestedSize();
|
||||
encoder.BitmapTransform().ScaledWidth(size.Width);
|
||||
encoder.BitmapTransform().ScaledHeight(size.Height);
|
||||
|
||||
co_await encoder.FlushAsync();
|
||||
inMemoryStream.Seek(0);
|
||||
|
||||
auto streamRef = RandomAccessStreamReference::CreateFromStream(inMemoryStream);
|
||||
args.Image(streamRef);
|
||||
|
||||
// Complete the deferral to tell the system that the Image is ready.
|
||||
deferral.Complete();
|
||||
}
|
||||
|
||||
// Handle the system event that tells us that the user has asked for a tab to be torn out.
|
||||
// This event can be raised on any thread, so we explicitly switch to the UI thread before doing work.
|
||||
winrt::fire_and_forget MainWindow::TabTearOutRequested(WindowTabManager const&, const WindowTabTearOutRequestedEventArgs args)
|
||||
{
|
||||
// Take a strong reference to the MainWindow so it doesn't get destructed while we co_await.
|
||||
auto strongThis = get_strong();
|
||||
|
||||
// Take a deferral before we co_await so the system knows that we are still working on the tear-out.
|
||||
auto deferral = args.GetDeferral();
|
||||
co_await wil::resume_foreground(m_dispatcherQueue);
|
||||
|
||||
// Remove the tab from this window
|
||||
winrt::TabViewModel tabViewModel = TabViewModel::GetFromWindowTab(args.Tab());
|
||||
RemoveTabByItem(tabViewModel);
|
||||
|
||||
// Create another MainWindow with that tab as its only tab.
|
||||
auto tornOut = winrt::make<MainWindow>(tabViewModel);
|
||||
|
||||
HWND hwnd;
|
||||
winrt::check_hresult(tornOut.try_as<::IWindowNative>()->get_WindowHandle(&hwnd));
|
||||
args.WindowId(reinterpret_cast<uint64_t>(hwnd));
|
||||
|
||||
// Complete the deferral to tell the system the WindowId is ready.
|
||||
deferral.Complete();
|
||||
|
||||
// Show the window after completing the deferral.
|
||||
tornOut.Activate();
|
||||
}
|
||||
|
||||
void MainWindow::RemoveTabByItem(winrt::TabViewModel const& model)
|
||||
{
|
||||
uint32_t index;
|
||||
if (m_tabs.IndexOf(model, index))
|
||||
{
|
||||
// Note that this RemoveAt may trigger a SelectionChanged if the current selection is being removed.
|
||||
// Our VectorChanged event handler will update the WindowTabManager.
|
||||
m_tabs.RemoveAt(index);
|
||||
}
|
||||
|
||||
// If that was the last tab, then exit this window.
|
||||
if (m_tabs.Size() == 0)
|
||||
{
|
||||
this->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Samples/AppTabsIntegration/cpp/MainWindow.xaml.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MainWindow.g.h"
|
||||
|
||||
namespace winrt::AppTabsIntegration::implementation
|
||||
{
|
||||
struct MainWindow : MainWindowT<MainWindow>
|
||||
{
|
||||
MainWindow(AppTabsIntegration::TabViewModel const& initialTab = nullptr);
|
||||
|
||||
void TabView_AddTabClicked(Microsoft::UI::Xaml::Controls::TabView const& sender, Windows::Foundation::IInspectable const& args);
|
||||
void TabView_CloseRequested(Microsoft::UI::Xaml::Controls::TabView const& sender, Microsoft::UI::Xaml::Controls::TabViewTabCloseRequestedEventArgs const& args);
|
||||
void TabView_SelectionChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& args);
|
||||
void TabView_TabDroppedOutside(Microsoft::UI::Xaml::Controls::TabView const& sender, Microsoft::UI::Xaml::Controls::TabViewTabDroppedOutsideEventArgs const& args);
|
||||
private:
|
||||
winrt::fire_and_forget TabSwitchRequested(winrt::Windows::UI::Shell::WindowTabManager const&, winrt::Windows::UI::Shell::WindowTabSwitchRequestedEventArgs args);
|
||||
winrt::fire_and_forget TabCloseRequested(winrt::Windows::UI::Shell::WindowTabManager const&, winrt::Windows::UI::Shell::WindowTabCloseRequestedEventArgs args);
|
||||
winrt::fire_and_forget TabThumbnailRequested(winrt::Windows::UI::Shell::WindowTabManager const&, winrt::Windows::UI::Shell::WindowTabThumbnailRequestedEventArgs args);
|
||||
winrt::fire_and_forget TabTearOutRequested(winrt::Windows::UI::Shell::WindowTabManager const&, winrt::Windows::UI::Shell::WindowTabTearOutRequestedEventArgs args);
|
||||
|
||||
void TabCollection_VectorChanged(winrt::Windows::Foundation::Collections::IObservableVector<AppTabsIntegration::TabViewModel> const& sender, Windows::Foundation::Collections::IVectorChangedEventArgs const& args);
|
||||
|
||||
void RemoveTabByItem(AppTabsIntegration::TabViewModel const& tabViewModel);
|
||||
AppTabsIntegration::TabViewModel CreateTabViewModel();
|
||||
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<AppTabsIntegration::TabViewModel> m_tabs = winrt::single_threaded_observable_vector<winrt::AppTabsIntegration::TabViewModel>();
|
||||
winrt::Microsoft::UI::Dispatching::DispatcherQueue m_dispatcherQueue = this->DispatcherQueue();
|
||||
|
||||
winrt::Windows::UI::Shell::WindowTabManager m_tabManager{ nullptr };
|
||||
winrt::Windows::UI::Shell::WindowTabManager::TabSwitchRequested_revoker m_tabSwitchRevoker{};
|
||||
winrt::Windows::UI::Shell::WindowTabManager::TabCloseRequested_revoker m_tabCloseRevoker{};
|
||||
winrt::Windows::UI::Shell::WindowTabManager::TabThumbnailRequested_revoker m_tabThumbnailRequestedRevoker{};
|
||||
winrt::Windows::UI::Shell::WindowTabManager::TabTearOutRequested_revoker m_tabTearOutRequestedRevoker{};
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::AppTabsIntegration::factory_implementation
|
||||
{
|
||||
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
|
||||
{
|
||||
};
|
||||
}
|
||||
48
Samples/AppTabsIntegration/cpp/Package.appxmanifest
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity
|
||||
Name="d21e8a52-ae32-4eff-b5f4-a2b4aafe77b8"
|
||||
Publisher="CN=sankalpg"
|
||||
Version="1.0.0.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>AppTabsIntegration</DisplayName>
|
||||
<PublisherDisplayName>sankalpg</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="AppTabsIntegration"
|
||||
Description="AppTabsIntegration"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
110
Samples/AppTabsIntegration/cpp/TabViewModel.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "pch.h"
|
||||
#include "TabViewModel.h"
|
||||
#include "TabViewModel.g.cpp"
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
using namespace winrt::AppTabsIntegration;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::UI::Shell;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
winrt::Windows::UI::Color RandomColor()
|
||||
{
|
||||
static constexpr winrt::Windows::UI::Color colors[] = {
|
||||
{ 0x00, 0x00, 0x00, 0xFF },
|
||||
{ 0xFF, 0x00, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0x00, 0xFF },
|
||||
{ 0xFF, 0xFF, 0x00, 0xFF },
|
||||
{ 0x00, 0x00, 0xFF, 0xFF },
|
||||
{ 0xFF, 0x00, 0xFF, 0xFF },
|
||||
{ 0x00, 0xFF, 0xFF, 0xFF },
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF },
|
||||
};
|
||||
return colors[static_cast<uint32_t>(GetTickCount64() / 16) % ARRAYSIZE(colors)];
|
||||
}
|
||||
|
||||
// A TabDataModel object holds a strong reference to its paired WindowTab object as a member.
|
||||
// A WindowTab objects holds a weak reference to the paired TabDataModel object in its Tag.
|
||||
// The weak reference avoids a reference cycle.
|
||||
|
||||
// Weak references are not IInspectable, so we wrap one inside an object that *is* IInspectable
|
||||
// so we can use it as a Tag.
|
||||
template<typename T>
|
||||
struct InspectableWeakReference : winrt::implements<InspectableWeakReference<T>, winrt::IInspectable>
|
||||
{
|
||||
InspectableWeakReference(winrt::weak_ref<T> const& weak) : m_weak(weak) {}
|
||||
T get() const { return m_weak.get(); }
|
||||
|
||||
winrt::weak_ref<T> m_weak;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::AppTabsIntegration::implementation
|
||||
{
|
||||
TabViewModel::TabViewModel(const winrt::hstring& name, winrt::Windows::UI::Shell::WindowTab const& windowTab)
|
||||
: m_windowTab(windowTab), m_color(RandomColor())
|
||||
{
|
||||
Name(name);
|
||||
|
||||
// A few lines above, we initialized m_windowTab to hold a reference to the windowTab.
|
||||
// Here, we create the weak reference from the windowTab back to the TabViewModel.
|
||||
if (m_windowTab)
|
||||
{
|
||||
windowTab.Tag(winrt::make<InspectableWeakReference<winrt::TabViewModel>>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ winrt::TabViewModel TabViewModel::GetFromWindowTab(winrt::Windows::UI::Shell::WindowTab const& windowTab)
|
||||
{
|
||||
// From the WindowTab, get the Tag, then resolve it from a weak reference back to a strong reference.
|
||||
return winrt::get_self<InspectableWeakReference<winrt::TabViewModel>>(windowTab.Tag())->get();
|
||||
}
|
||||
|
||||
/* static */ winrt::WindowTab TabViewModel::GetWindowTab(winrt::TabViewModel const& tabViewModel)
|
||||
{
|
||||
// From the TabViewModel, get the WindowTab.
|
||||
return winrt::get_self<TabViewModel>(tabViewModel)->m_windowTab;
|
||||
}
|
||||
|
||||
winrt::hstring TabViewModel::Name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void TabViewModel::Name(const winrt::hstring& value)
|
||||
{
|
||||
m_name = value;
|
||||
|
||||
if (m_windowTab)
|
||||
{
|
||||
// Propagate the app's tab title into the WindowTab title.
|
||||
m_windowTab.Title(value);
|
||||
}
|
||||
|
||||
NotifyChange(L"Name");
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Color TabViewModel::Color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void TabViewModel::Color(winrt::Windows::UI::Color const& value)
|
||||
{
|
||||
if (value != m_color)
|
||||
{
|
||||
m_color = value;
|
||||
|
||||
if (m_windowTab)
|
||||
{
|
||||
// Inform the Window Tab Manager that the thumbnail has changed.
|
||||
m_windowTab.ReportThumbnailAvailable();
|
||||
}
|
||||
|
||||
NotifyChange(L"Color");
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Samples/AppTabsIntegration/cpp/TabViewModel.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "TabViewModel.g.h"
|
||||
|
||||
namespace winrt::AppTabsIntegration::implementation
|
||||
{
|
||||
struct TabViewModel : TabViewModelT<TabViewModel>
|
||||
{
|
||||
TabViewModel(winrt::hstring const& name, winrt::Windows::UI::Shell::WindowTab const& windowTab);
|
||||
|
||||
winrt::hstring Name() const;
|
||||
void Name(winrt::hstring const& value);
|
||||
|
||||
winrt::Windows::UI::Color Color() const;
|
||||
void Color(winrt::Windows::UI::Color const& value);
|
||||
|
||||
winrt::event_token PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
|
||||
{
|
||||
return m_propertyChanged.add(handler);
|
||||
}
|
||||
|
||||
void PropertyChanged(winrt::event_token token)
|
||||
{
|
||||
return m_propertyChanged.remove(token);
|
||||
}
|
||||
|
||||
// Methods for converting between TabViewModel and WindowTab.
|
||||
static AppTabsIntegration::TabViewModel GetFromWindowTab(winrt::Windows::UI::Shell::WindowTab const& windowTab);
|
||||
static winrt::Windows::UI::Shell::WindowTab GetWindowTab(AppTabsIntegration::TabViewModel const& tabViewModel);
|
||||
|
||||
private:
|
||||
winrt::event<winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
|
||||
winrt::Windows::UI::Shell::WindowTab const m_windowTab;
|
||||
winrt::hstring m_name{};
|
||||
winrt::Windows::UI::Color m_color;
|
||||
|
||||
template<typename T>
|
||||
void NotifyChange(T&& name)
|
||||
{
|
||||
m_propertyChanged(*this, winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventArgs(std::forward<T>(name)));
|
||||
}
|
||||
};
|
||||
}
|
||||
8
Samples/AppTabsIntegration/cpp/TabViewModel.idl
Normal file
@ -0,0 +1,8 @@
|
||||
namespace AppTabsIntegration
|
||||
{
|
||||
runtimeclass TabViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
String Name;
|
||||
Windows.UI.Color Color;
|
||||
}
|
||||
}
|
||||
25
Samples/AppTabsIntegration/cpp/app.manifest
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="AppTabsIntegration.app"/>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!--The ID below informs the system that this application is compatible with OS features first introduced in Windows 8.
|
||||
For more info see https://docs.microsoft.com/windows/win32/sysinfo/targeting-your-application-at-windows-8-1
|
||||
|
||||
It is also necessary to support features in unpackaged applications, for example the custom titlebar implementation.-->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
7
Samples/AppTabsIntegration/cpp/packages.config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.220929.3" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220914.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.755" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.2.221109.1" targetFramework="native" />
|
||||
</packages>
|
||||
4
Samples/AppTabsIntegration/cpp/pch.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
50
Samples/AppTabsIntegration/cpp/pch.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) Microsoft Corporation and Contributors.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <unknwn.h>
|
||||
#include <restrictederrorinfo.h>
|
||||
#include <hstring.h>
|
||||
#include <objbase.h>
|
||||
#include <sstream>
|
||||
|
||||
// Undefine GetCurrentTime macro to prevent
|
||||
// conflict with Storyboard::GetCurrentTime
|
||||
#undef GetCurrentTime
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.Activation.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
#include <winrt/Windows.Graphics.Imaging.h>
|
||||
#include <winrt/Windows.Storage.Streams.h>
|
||||
#include <winrt/Windows.UI.h>
|
||||
#include <winrt/Windows.UI.Core.h>
|
||||
#include <winrt/Windows.UI.Shell.h>
|
||||
#include <winrt/Microsoft.UI.h>
|
||||
#include <winrt/Microsoft.UI.Composition.h>
|
||||
#include <winrt/Microsoft.UI.Dispatching.h>
|
||||
#include <winrt/Microsoft.UI.Interop.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Data.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Interop.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Markup.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Media.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Shapes.h>
|
||||
#include <winrt/AppTabsIntegration.h>
|
||||
#include <wil/cppwinrt_helpers.h>
|
||||
#include <Microsoft.UI.Xaml.Window.h>
|
||||
|
||||
// Verify that the correct WindowsDesktop reference has been added.
|
||||
namespace winrt::Windows::UI::Shell
|
||||
{
|
||||
struct WindowTabManager;
|
||||
struct IWindowTabManager;
|
||||
static_assert(std::is_same_v<winrt::default_interface<WindowTabManager>, IWindowTabManager>,
|
||||
"Please add a reference to the Windows Desktop Extension SDK, version 10.0.22621.1778 or higher.");
|
||||
}
|
||||
50
Samples/AppVisibility/README.md
Normal file
@ -0,0 +1,50 @@
|
||||
Start screen visibility sample
|
||||
==============================
|
||||
|
||||
This sample shows how to get information about monitors that are displaying Windows Store apps or the Start screen. It also demonstrates how to receive notifications when the state of a monitor changes or when the visibility of the Start screen changes.
|
||||
|
||||
**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server.
|
||||
|
||||
This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample!
|
||||
|
||||
To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696).
|
||||
|
||||
To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697).
|
||||
|
||||
Related topics
|
||||
--------------
|
||||
|
||||
[**IAppVisibility**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119)
|
||||
|
||||
[**IAppVisibilityEvents**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj554120)
|
||||
|
||||
[**MONITOR\_APP\_VISIBILITY**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj152046)
|
||||
|
||||
Related technologies
|
||||
--------------------
|
||||
|
||||
[**IAppVisibility**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119)
|
||||
|
||||
Operating system requirements
|
||||
-----------------------------
|
||||
|
||||
Client
|
||||
|
||||
Windows 8.1
|
||||
|
||||
Server
|
||||
|
||||
Windows Server 2012 R2
|
||||
|
||||
Build the sample
|
||||
----------------
|
||||
|
||||
To build this sample, open the solution (.sln) file titled AppVisibilitySample.sln from Visual Studio Professional 2012, Visual Studio 2013, or a later version (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded.
|
||||
|
||||
**Warning** This sample requires Visual Studio Professional 2012, Visual Studio 2013, or later versions of Visual Studio (any SKU) and doesn't compile in Microsoft Visual Studio Express 2013 for Windows
|
||||
|
||||
Run the sample
|
||||
--------------
|
||||
|
||||
To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio. (Or select the corresponding options from the **Debug** menu.) When the app is running, switch to the Start screen and back to the desktop.
|
||||
|
||||
167
Samples/AppVisibility/cpp/AppVisibilitySample.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
#include <shobjidl.h>
|
||||
#include <stdio.h>
|
||||
#include <wrl\client.h>
|
||||
#include <wrl\implements.h>
|
||||
|
||||
// Simple helper function to turn a MONITOR_APP_VISIBILITY enumeration into a string
|
||||
PCWSTR const _GetMonitorAppVisibilityString(MONITOR_APP_VISIBILITY monitorAppVisibility)
|
||||
{
|
||||
PCWSTR pszAppVisibilityString = nullptr;
|
||||
switch (monitorAppVisibility)
|
||||
{
|
||||
case MAV_NO_APP_VISIBLE:
|
||||
pszAppVisibilityString = L"no apps visible";
|
||||
break;
|
||||
|
||||
case MAV_APP_VISIBLE:
|
||||
pszAppVisibilityString = L"a visible app";
|
||||
break;
|
||||
|
||||
case MAV_UNKNOWN:
|
||||
__fallthrough;
|
||||
default:
|
||||
pszAppVisibilityString = L"unknown";
|
||||
break;
|
||||
}
|
||||
return pszAppVisibilityString;
|
||||
}
|
||||
|
||||
// This class will implement the IAppVisibilityEvents interface and will receive notifications
|
||||
// from the AppVisibility COM object.
|
||||
class CAppVisibilityNotificationSubscriber :
|
||||
public Microsoft::WRL::RuntimeClass<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>,
|
||||
IAppVisibilityEvents>
|
||||
{
|
||||
public:
|
||||
CAppVisibilityNotificationSubscriber();
|
||||
|
||||
// AppVisibilityOnMonitorChanged will be called when applications appear or disappear on a monitor
|
||||
IFACEMETHODIMP AppVisibilityOnMonitorChanged(_In_ HMONITOR hMonitor,
|
||||
MONITOR_APP_VISIBILITY previousAppVisibility,
|
||||
MONITOR_APP_VISIBILITY currentAppVisibility);
|
||||
|
||||
// LauncherVisibilityChange will be called whenever the Start menu becomes visible or hidden
|
||||
IFACEMETHODIMP LauncherVisibilityChange(BOOL currentVisibleState);
|
||||
|
||||
private:
|
||||
~CAppVisibilityNotificationSubscriber();
|
||||
|
||||
// This variable will be used to trigger this program's message loop
|
||||
// to exit. The variable will be incremented when the launcher becomes visible.
|
||||
// When the launcher becomes visible five times, the program will exit.
|
||||
unsigned int _cLauncherChanges;
|
||||
|
||||
};
|
||||
|
||||
CAppVisibilityNotificationSubscriber::CAppVisibilityNotificationSubscriber() : _cLauncherChanges(0)
|
||||
{
|
||||
}
|
||||
|
||||
CAppVisibilityNotificationSubscriber::~CAppVisibilityNotificationSubscriber()
|
||||
{
|
||||
}
|
||||
|
||||
// Implementation of IAppVisibilityEvents
|
||||
IFACEMETHODIMP CAppVisibilityNotificationSubscriber::AppVisibilityOnMonitorChanged(_In_ HMONITOR hMonitor,
|
||||
MONITOR_APP_VISIBILITY previousAppVisibility,
|
||||
MONITOR_APP_VISIBILITY currentAppVisibility)
|
||||
{
|
||||
wprintf_s(L"Monitor %p previously had %s and now has %s\r\n",
|
||||
hMonitor,
|
||||
_GetMonitorAppVisibilityString(previousAppVisibility),
|
||||
_GetMonitorAppVisibilityString(currentAppVisibility));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CAppVisibilityNotificationSubscriber::LauncherVisibilityChange(BOOL currentVisibleState)
|
||||
{
|
||||
wprintf_s(L"The Start menu is now %s\r\n", currentVisibleState ? L"visible" : L"not visible");
|
||||
if (currentVisibleState)
|
||||
{
|
||||
_cLauncherChanges++;
|
||||
if (_cLauncherChanges == 5)
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL CALLBACK DisplayMonitorEnumProc(_In_ HMONITOR hMonitor,
|
||||
_In_ HDC /*hdcMonitor*/,
|
||||
_In_ LPRECT /*lprcMonitor*/,
|
||||
_In_ LPARAM dwData)
|
||||
{
|
||||
IAppVisibility *pAppVisibility = reinterpret_cast<IAppVisibility *>(dwData);
|
||||
|
||||
MONITOR_APP_VISIBILITY monitorAppVisibility;
|
||||
HRESULT hr = pAppVisibility->GetAppVisibilityOnMonitor(hMonitor, &monitorAppVisibility);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
wprintf_s(L"\tMonitor %p has %s\r\n", hMonitor, _GetMonitorAppVisibilityString(monitorAppVisibility));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int __cdecl wmain()
|
||||
{
|
||||
wprintf_s(L"Toggle Start menu visibility 5 times to exit\r\n");
|
||||
|
||||
// Initialization of COM is required to use the AppVisibility (CLSID_AppVisibility) object
|
||||
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Create the App Visibility component
|
||||
Microsoft::WRL::ComPtr<IAppVisibility> spAppVisibility;
|
||||
hr = CoCreateInstance(CLSID_AppVisibility, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spAppVisibility));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Enumerate the current display devices and display app visibility status
|
||||
wprintf_s(L"Current app visibility status is:\r\n");
|
||||
EnumDisplayMonitors(nullptr, nullptr, DisplayMonitorEnumProc, reinterpret_cast<LPARAM>(spAppVisibility.Get()));
|
||||
wprintf_s(L"\r\n\r\n");
|
||||
|
||||
// Display the current launcher visibility
|
||||
BOOL launcherVisibility;
|
||||
if (SUCCEEDED(spAppVisibility->IsLauncherVisible(&launcherVisibility)))
|
||||
{
|
||||
wprintf_s(L"The Start menu is currently %s\r\n", launcherVisibility ? L"visible" : L"not visible");
|
||||
}
|
||||
|
||||
// Create an object that implements IAppVisibilityEvents that will receive
|
||||
// callbacks when either app visibility or Start menu visibility changes.
|
||||
Microsoft::WRL::ComPtr<IAppVisibilityEvents> spSubscriber = Microsoft::WRL::Details::Make<CAppVisibilityNotificationSubscriber>();
|
||||
|
||||
// Advise to receive change notifications from the AppVisibility object
|
||||
// NOTE: There must be a reference held on the AppVisibility object in order to continue
|
||||
// NOTE: receiving notifications on the implementation of the IAppVisibilityEvents object
|
||||
DWORD dwCookie;
|
||||
hr = spAppVisibility->Advise(spSubscriber.Get(), &dwCookie);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Since the visibility notifications are delivered via COM, a message loop must
|
||||
// be employed in order to receive notifications
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
// Unadvise from the AppVisibility component to stop receiving notifications
|
||||
spAppVisibility->Unadvise(dwCookie);
|
||||
}
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
20
Samples/AppVisibility/cpp/AppVisibilitySample.sln
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 11
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppVisibilitySample", "AppVisibilitySample.vcxproj", "{99AAE228-9918-411F-8509-D60947940800}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{99AAE228-9918-411F-8509-D60947940800}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{99AAE228-9918-411F-8509-D60947940800}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{99AAE228-9918-411F-8509-D60947940800}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{99AAE228-9918-411F-8509-D60947940800}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
75
Samples/AppVisibility/cpp/AppVisibilitySample.vcxproj
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and '$(VisualStudioVersion)' == ''">$(VCTargetsPath11)</VCTargetsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{99AAE228-9918-411F-8509-D60947940800}</ProjectGuid>
|
||||
<RootNamespace>AppVisibilitySample</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AppVisibilitySample.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
83
Samples/ApplicationLoopback/README.md
Normal file
@ -0,0 +1,83 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: Application loopback audio capture
|
||||
urlFragment: applicationloopbackaudio-sample
|
||||
description: Demonstrates how to capture system audio either from a specific process tree or for all process except a process tree.
|
||||
extendedZipContent:
|
||||
- path: LICENSE
|
||||
target: LICENSE
|
||||
---
|
||||
|
||||
# Application loopback API Capture Sample
|
||||
|
||||
This sample demonstrates the use of ActivateAudioInterfaceAsync Win32 API with a new initialization structure.
|
||||
The new data structure makes it possible to restrict captured audio data to that rendered by a specific
|
||||
process and any of its child processes. Windows 10 has always supported capturing all audio that is played on
|
||||
an audio endpoint (referred to as "system" loopback capture), which captures all audio from all apps that
|
||||
are playing sounds on the chosen audio endpoint.
|
||||
|
||||
With the new structure, only audio from the specified process, and its children, will be captured. Audio rendered by
|
||||
other processes will not be captured. A flag is also provided to reverse the behavior, capturing all system
|
||||
audio *except* those from the the specified process (and its children). Furthermore, the capture is not tied to a
|
||||
specific audio endpoint, eliminating the need to create a separate IAudioClient to capture from each physical
|
||||
audio endpoint.
|
||||
|
||||
If the processes whose audio will be captured does not have any audio rendering streams, then the capturing
|
||||
process receives silence.
|
||||
|
||||
To use this sample, obtain the process ID for the process tree you wish to capture or exclude from capture.
|
||||
You can use Task Manager or the tlist program to get this ID. Run the sample with the process ID, the
|
||||
desired capture mode (including the process tree or excluding it), and the output WAV file.
|
||||
|
||||
Examples:
|
||||
|
||||
* Capture audio from process 1234 and its children: `ApplicationLoopback 1234 includetree Captured.wav`
|
||||
* Capture audio from all process except process 1234 and its children: `ApplicationLoopback 1234 excludetree Captured.wav`
|
||||
|
||||
Note that this sample requires Windows 10 build 20348 or later.
|
||||
|
||||
Sample Language Implementations
|
||||
===============================
|
||||
C++
|
||||
|
||||
Files
|
||||
===============================
|
||||
|
||||
ApplicationLoopback.vcproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
ApplicationLoopback.cpp
|
||||
This is the main application source file. It parses the command line and instantiates a
|
||||
CLoopbackCapture object which actually performs the capturing.
|
||||
|
||||
LoopbackCapture.cpp/LoopbackCapture.h
|
||||
Implementation of a class which uses the WASAPI APIs to capture audio from a process using ActivateAudioInterfaceAsync.
|
||||
|
||||
Common.h
|
||||
Helper for implementing IMFAsyncCallback.
|
||||
|
||||
|
||||
To build the sample using the command prompt:
|
||||
=============================================
|
||||
|
||||
1. Open the Command Prompt window and navigate to the directory.
|
||||
2. Type msbuild [Solution Filename]
|
||||
|
||||
To build the sample using Visual Studio 2019 (preferred method):
|
||||
================================================================
|
||||
|
||||
1. Open Windows Explorer and navigate to the directory.
|
||||
2. Double-click the icon for the .sln (solution) file to open the file in Visual Studio.
|
||||
3. In the Build menu, select Build Solution. The application will be built in the default
|
||||
\Debug or \Release directory
|
||||
|
||||
To run the sample:
|
||||
=================
|
||||
Type ApplicationLoopback.exe at the command line with appropriate command line options described above.
|
||||
81
Samples/ApplicationLoopback/cpp/ApplicationLoopback.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// ApplicationLoopback.cpp : This file contains the 'main' function. Program execution begins and ends there.
|
||||
//
|
||||
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include "LoopbackCapture.h"
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::wcout <<
|
||||
L"Usage: ApplicationLoopback <pid> <includetree|excludetree> <outputfilename>\n"
|
||||
L"\n"
|
||||
L"<pid> is the process ID to capture or exclude from capture\n"
|
||||
L"includetree includes audio from that process and its child processes\n"
|
||||
L"excludetree includes audio from all processes except that process and its child processes\n"
|
||||
L"<outputfilename> is the WAV file to receive the captured audio (10 seconds)\n"
|
||||
L"\n"
|
||||
L"Examples:\n"
|
||||
L"\n"
|
||||
L"ApplicationLoopback 1234 includetree CapturedAudio.wav\n"
|
||||
L"\n"
|
||||
L" Captures audio from process 1234 and its children.\n"
|
||||
L"\n"
|
||||
L"ApplicationLoopback 1234 excludetree CapturedAudio.wav\n"
|
||||
L"\n"
|
||||
L" Captures audio from all processes except process 1234 and its children.\n";
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD processId = wcstoul(argv[1], nullptr, 0);
|
||||
if (processId == 0)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool includeProcessTree;
|
||||
if (wcscmp(argv[2], L"includetree") == 0)
|
||||
{
|
||||
includeProcessTree = true;
|
||||
}
|
||||
else if (wcscmp(argv[2], L"excludetree") == 0)
|
||||
{
|
||||
includeProcessTree = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PCWSTR outputFile = argv[3];
|
||||
|
||||
CLoopbackCapture loopbackCapture;
|
||||
HRESULT hr = loopbackCapture.StartCaptureAsync(processId, includeProcessTree, outputFile);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wil::unique_hlocal_string message;
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, hr,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (PWSTR)&message, 0, nullptr);
|
||||
std::wcout << L"Failed to start capture\n0x" << std::hex << hr << L": " << message.get() << L"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"Capturing 10 seconds of audio." << std::endl;
|
||||
Sleep(10000);
|
||||
|
||||
loopbackCapture.StopCaptureAsync();
|
||||
|
||||
std::wcout << L"Finished.\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
31
Samples/ApplicationLoopback/cpp/ApplicationLoopback.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30204.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ApplicationLoopback", "ApplicationLoopback.vcxproj", "{6E745655-513E-4713-B3AB-D6D3F62D7734}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x64.Build.0 = Debug|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x64.ActiveCfg = Release|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x64.Build.0 = Release|x64
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6E745655-513E-4713-B3AB-D6D3F62D7734}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {64406148-8C03-42D2-8A2A-C14A03CFF8E3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
169
Samples/ApplicationLoopback/cpp/ApplicationLoopback.vcxproj
Normal file
@ -0,0 +1,169 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{6e745655-513e-4713-b3ab-d6d3f62d7734}</ProjectGuid>
|
||||
<RootNamespace>ApplicationLoopback</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>false</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<EnableManagedIncrementalBuild>false</EnableManagedIncrementalBuild>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;mfplat.lib;mmdevapi.lib;mfuuid.lib;mfreadwrite.lib;windowsapp.lib;userenv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ApplicationLoopback.cpp" />
|
||||
<ClCompile Include="LoopbackCapture.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Common.h" />
|
||||
<ClInclude Include="LoopbackCapture.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ApplicationLoopback.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LoopbackCapture.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="LoopbackCapture.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
58
Samples/ApplicationLoopback/cpp/Common.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <mfidl.h>
|
||||
#include <mfapi.h>
|
||||
#include <mfobjects.h>
|
||||
|
||||
#ifndef METHODASYNCCALLBACK
|
||||
#define METHODASYNCCALLBACK(Parent, AsyncCallback, pfnCallback) \
|
||||
class Callback##AsyncCallback :\
|
||||
public IMFAsyncCallback \
|
||||
{ \
|
||||
public: \
|
||||
Callback##AsyncCallback() : \
|
||||
_parent(((Parent*)((BYTE*)this - offsetof(Parent, m_x##AsyncCallback)))), \
|
||||
_dwQueueID( MFASYNC_CALLBACK_QUEUE_MULTITHREADED ) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
STDMETHOD_( ULONG, AddRef )() \
|
||||
{ \
|
||||
return _parent->AddRef(); \
|
||||
} \
|
||||
STDMETHOD_( ULONG, Release )() \
|
||||
{ \
|
||||
return _parent->Release(); \
|
||||
} \
|
||||
STDMETHOD( QueryInterface )( REFIID riid, void **ppvObject ) \
|
||||
{ \
|
||||
if (riid == IID_IMFAsyncCallback || riid == IID_IUnknown) \
|
||||
{ \
|
||||
(*ppvObject) = this; \
|
||||
AddRef(); \
|
||||
return S_OK; \
|
||||
} \
|
||||
*ppvObject = NULL; \
|
||||
return E_NOINTERFACE; \
|
||||
} \
|
||||
STDMETHOD( GetParameters )( \
|
||||
/* [out] */ __RPC__out DWORD *pdwFlags, \
|
||||
/* [out] */ __RPC__out DWORD *pdwQueue) \
|
||||
{ \
|
||||
*pdwFlags = 0; \
|
||||
*pdwQueue = _dwQueueID; \
|
||||
return S_OK; \
|
||||
} \
|
||||
STDMETHOD( Invoke )( /* [out] */ __RPC__out IMFAsyncResult * pResult ) \
|
||||
{ \
|
||||
_parent->pfnCallback( pResult ); \
|
||||
return S_OK; \
|
||||
} \
|
||||
void SetQueueID( DWORD dwQueueID ) { _dwQueueID = dwQueueID; } \
|
||||
\
|
||||
protected: \
|
||||
Parent* _parent; \
|
||||
DWORD _dwQueueID; \
|
||||
\
|
||||
} m_x##AsyncCallback;
|
||||
#endif
|
||||
417
Samples/ApplicationLoopback/cpp/LoopbackCapture.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
#include <shlobj.h>
|
||||
#include <wchar.h>
|
||||
#include <iostream>
|
||||
#include <audioclientactivationparams.h>
|
||||
|
||||
#include "LoopbackCapture.h"
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
|
||||
HRESULT CLoopbackCapture::SetDeviceStateErrorIfFailed(HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
m_DeviceState = DeviceState::Error;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CLoopbackCapture::InitializeLoopbackCapture()
|
||||
{
|
||||
// Create events for sample ready or user stop
|
||||
RETURN_IF_FAILED(m_SampleReadyEvent.create(wil::EventOptions::None));
|
||||
|
||||
// Initialize MF
|
||||
RETURN_IF_FAILED(MFStartup(MF_VERSION, MFSTARTUP_LITE));
|
||||
|
||||
// Register MMCSS work queue
|
||||
DWORD dwTaskID = 0;
|
||||
RETURN_IF_FAILED(MFLockSharedWorkQueue(L"Capture", 0, &dwTaskID, &m_dwQueueID));
|
||||
|
||||
// Set the capture event work queue to use the MMCSS queue
|
||||
m_xSampleReady.SetQueueID(m_dwQueueID);
|
||||
|
||||
// Create the completion event as auto-reset
|
||||
RETURN_IF_FAILED(m_hActivateCompleted.create(wil::EventOptions::None));
|
||||
|
||||
// Create the capture-stopped event as auto-reset
|
||||
RETURN_IF_FAILED(m_hCaptureStopped.create(wil::EventOptions::None));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CLoopbackCapture::~CLoopbackCapture()
|
||||
{
|
||||
if (m_dwQueueID != 0)
|
||||
{
|
||||
MFUnlockWorkQueue(m_dwQueueID);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CLoopbackCapture::ActivateAudioInterface(DWORD processId, bool includeProcessTree)
|
||||
{
|
||||
return SetDeviceStateErrorIfFailed([&]() -> HRESULT
|
||||
{
|
||||
AUDIOCLIENT_ACTIVATION_PARAMS audioclientActivationParams = {};
|
||||
audioclientActivationParams.ActivationType = AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK;
|
||||
audioclientActivationParams.ProcessLoopbackParams.ProcessLoopbackMode = includeProcessTree ?
|
||||
PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE : PROCESS_LOOPBACK_MODE_EXCLUDE_TARGET_PROCESS_TREE;
|
||||
audioclientActivationParams.ProcessLoopbackParams.TargetProcessId = processId;
|
||||
|
||||
PROPVARIANT activateParams = {};
|
||||
activateParams.vt = VT_BLOB;
|
||||
activateParams.blob.cbSize = sizeof(audioclientActivationParams);
|
||||
activateParams.blob.pBlobData = (BYTE*)&audioclientActivationParams;
|
||||
|
||||
wil::com_ptr_nothrow<IActivateAudioInterfaceAsyncOperation> asyncOp;
|
||||
RETURN_IF_FAILED(ActivateAudioInterfaceAsync(VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, __uuidof(IAudioClient), &activateParams, this, &asyncOp));
|
||||
|
||||
// Wait for activation completion
|
||||
m_hActivateCompleted.wait();
|
||||
|
||||
return m_activateResult;
|
||||
}());
|
||||
}
|
||||
|
||||
//
|
||||
// ActivateCompleted()
|
||||
//
|
||||
// Callback implementation of ActivateAudioInterfaceAsync function. This will be called on MTA thread
|
||||
// when results of the activation are available.
|
||||
//
|
||||
HRESULT CLoopbackCapture::ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation)
|
||||
{
|
||||
m_activateResult = SetDeviceStateErrorIfFailed([&]()->HRESULT
|
||||
{
|
||||
// Check for a successful activation result
|
||||
HRESULT hrActivateResult = E_UNEXPECTED;
|
||||
wil::com_ptr_nothrow<IUnknown> punkAudioInterface;
|
||||
RETURN_IF_FAILED(operation->GetActivateResult(&hrActivateResult, &punkAudioInterface));
|
||||
RETURN_IF_FAILED(hrActivateResult);
|
||||
|
||||
// Get the pointer for the Audio Client
|
||||
RETURN_IF_FAILED(punkAudioInterface.copy_to(&m_AudioClient));
|
||||
|
||||
// The app can also call m_AudioClient->GetMixFormat instead to get the capture format.
|
||||
// 16 - bit PCM format.
|
||||
m_CaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
m_CaptureFormat.nChannels = 2;
|
||||
m_CaptureFormat.nSamplesPerSec = 44100;
|
||||
m_CaptureFormat.wBitsPerSample = 16;
|
||||
m_CaptureFormat.nBlockAlign = m_CaptureFormat.nChannels * m_CaptureFormat.wBitsPerSample / BITS_PER_BYTE;
|
||||
m_CaptureFormat.nAvgBytesPerSec = m_CaptureFormat.nSamplesPerSec * m_CaptureFormat.nBlockAlign;
|
||||
|
||||
// Initialize the AudioClient in Shared Mode with the user specified buffer
|
||||
RETURN_IF_FAILED(m_AudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,
|
||||
AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||
200000,
|
||||
AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM,
|
||||
&m_CaptureFormat,
|
||||
nullptr));
|
||||
|
||||
// Get the maximum size of the AudioClient Buffer
|
||||
RETURN_IF_FAILED(m_AudioClient->GetBufferSize(&m_BufferFrames));
|
||||
|
||||
// Get the capture client
|
||||
RETURN_IF_FAILED(m_AudioClient->GetService(IID_PPV_ARGS(&m_AudioCaptureClient)));
|
||||
|
||||
// Create Async callback for sample events
|
||||
RETURN_IF_FAILED(MFCreateAsyncResult(nullptr, &m_xSampleReady, nullptr, &m_SampleReadyAsyncResult));
|
||||
|
||||
// Tell the system which event handle it should signal when an audio buffer is ready to be processed by the client
|
||||
RETURN_IF_FAILED(m_AudioClient->SetEventHandle(m_SampleReadyEvent.get()));
|
||||
|
||||
// Creates the WAV file.
|
||||
RETURN_IF_FAILED(CreateWAVFile());
|
||||
|
||||
// Everything is ready.
|
||||
m_DeviceState = DeviceState::Initialized;
|
||||
|
||||
return S_OK;
|
||||
}());
|
||||
|
||||
// Let ActivateAudioInterface know that m_activateResult has the result of the activation attempt.
|
||||
m_hActivateCompleted.SetEvent();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// CreateWAVFile()
|
||||
//
|
||||
// Creates a WAV file in music folder
|
||||
//
|
||||
HRESULT CLoopbackCapture::CreateWAVFile()
|
||||
{
|
||||
return SetDeviceStateErrorIfFailed([&]()->HRESULT
|
||||
{
|
||||
m_hFile.reset(CreateFile(m_outputFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
|
||||
RETURN_LAST_ERROR_IF(!m_hFile);
|
||||
|
||||
// Create and write the WAV header
|
||||
|
||||
// 1. RIFF chunk descriptor
|
||||
DWORD header[] = {
|
||||
FCC('RIFF'), // RIFF header
|
||||
0, // Total size of WAV (will be filled in later)
|
||||
FCC('WAVE'), // WAVE FourCC
|
||||
FCC('fmt '), // Start of 'fmt ' chunk
|
||||
sizeof(m_CaptureFormat) // Size of fmt chunk
|
||||
};
|
||||
DWORD dwBytesWritten = 0;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(WriteFile(m_hFile.get(), header, sizeof(header), &dwBytesWritten, NULL));
|
||||
|
||||
m_cbHeaderSize += dwBytesWritten;
|
||||
|
||||
// 2. The fmt sub-chunk
|
||||
WI_ASSERT(m_CaptureFormat.cbSize == 0);
|
||||
RETURN_IF_WIN32_BOOL_FALSE(WriteFile(m_hFile.get(), &m_CaptureFormat, sizeof(m_CaptureFormat), &dwBytesWritten, NULL));
|
||||
m_cbHeaderSize += dwBytesWritten;
|
||||
|
||||
// 3. The data sub-chunk
|
||||
DWORD data[] = { FCC('data'), 0 }; // Start of 'data' chunk
|
||||
RETURN_IF_WIN32_BOOL_FALSE(WriteFile(m_hFile.get(), data, sizeof(data), &dwBytesWritten, NULL));
|
||||
m_cbHeaderSize += dwBytesWritten;
|
||||
|
||||
return S_OK;
|
||||
}());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// FixWAVHeader()
|
||||
//
|
||||
// The size values were not known when we originally wrote the header, so now go through and fix the values
|
||||
//
|
||||
HRESULT CLoopbackCapture::FixWAVHeader()
|
||||
{
|
||||
// Write the size of the 'data' chunk first
|
||||
DWORD dwPtr = SetFilePointer(m_hFile.get(), m_cbHeaderSize - sizeof(DWORD), NULL, FILE_BEGIN);
|
||||
RETURN_LAST_ERROR_IF(INVALID_SET_FILE_POINTER == dwPtr);
|
||||
|
||||
DWORD dwBytesWritten = 0;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(WriteFile(m_hFile.get(), &m_cbDataSize, sizeof(DWORD), &dwBytesWritten, NULL));
|
||||
|
||||
// Write the total file size, minus RIFF chunk and size
|
||||
// sizeof(DWORD) == sizeof(FOURCC)
|
||||
RETURN_LAST_ERROR_IF(INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile.get(), sizeof(DWORD), NULL, FILE_BEGIN));
|
||||
|
||||
DWORD cbTotalSize = m_cbDataSize + m_cbHeaderSize - 8;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(WriteFile(m_hFile.get(), &cbTotalSize, sizeof(DWORD), &dwBytesWritten, NULL));
|
||||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(FlushFileBuffers(m_hFile.get()));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CLoopbackCapture::StartCaptureAsync(DWORD processId, bool includeProcessTree, PCWSTR outputFileName)
|
||||
{
|
||||
m_outputFileName = outputFileName;
|
||||
auto resetOutputFileName = wil::scope_exit([&] { m_outputFileName = nullptr; });
|
||||
|
||||
RETURN_IF_FAILED(InitializeLoopbackCapture());
|
||||
RETURN_IF_FAILED(ActivateAudioInterface(processId, includeProcessTree));
|
||||
|
||||
// We should be in the initialzied state if this is the first time through getting ready to capture.
|
||||
if (m_DeviceState == DeviceState::Initialized)
|
||||
{
|
||||
m_DeviceState = DeviceState::Starting;
|
||||
return MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_xStartCapture, nullptr);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnStartCapture()
|
||||
//
|
||||
// Callback method to start capture
|
||||
//
|
||||
HRESULT CLoopbackCapture::OnStartCapture(IMFAsyncResult* pResult)
|
||||
{
|
||||
return SetDeviceStateErrorIfFailed([&]()->HRESULT
|
||||
{
|
||||
// Start the capture
|
||||
RETURN_IF_FAILED(m_AudioClient->Start());
|
||||
|
||||
m_DeviceState = DeviceState::Capturing;
|
||||
MFPutWaitingWorkItem(m_SampleReadyEvent.get(), 0, m_SampleReadyAsyncResult.get(), &m_SampleReadyKey);
|
||||
|
||||
return S_OK;
|
||||
}());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// StopCaptureAsync()
|
||||
//
|
||||
// Stop capture asynchronously via MF Work Item
|
||||
//
|
||||
HRESULT CLoopbackCapture::StopCaptureAsync()
|
||||
{
|
||||
RETURN_HR_IF(E_NOT_VALID_STATE, (m_DeviceState != DeviceState::Capturing) &&
|
||||
(m_DeviceState != DeviceState::Error));
|
||||
|
||||
m_DeviceState = DeviceState::Stopping;
|
||||
|
||||
RETURN_IF_FAILED(MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_xStopCapture, nullptr));
|
||||
|
||||
// Wait for capture to stop
|
||||
m_hCaptureStopped.wait();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnStopCapture()
|
||||
//
|
||||
// Callback method to stop capture
|
||||
//
|
||||
HRESULT CLoopbackCapture::OnStopCapture(IMFAsyncResult* pResult)
|
||||
{
|
||||
// Stop capture by cancelling Work Item
|
||||
// Cancel the queued work item (if any)
|
||||
if (0 != m_SampleReadyKey)
|
||||
{
|
||||
MFCancelWorkItem(m_SampleReadyKey);
|
||||
m_SampleReadyKey = 0;
|
||||
}
|
||||
|
||||
m_AudioClient->Stop();
|
||||
m_SampleReadyAsyncResult.reset();
|
||||
|
||||
return FinishCaptureAsync();
|
||||
}
|
||||
|
||||
//
|
||||
// FinishCaptureAsync()
|
||||
//
|
||||
// Finalizes WAV file on a separate thread via MF Work Item
|
||||
//
|
||||
HRESULT CLoopbackCapture::FinishCaptureAsync()
|
||||
{
|
||||
// We should be flushing when this is called
|
||||
return MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_xFinishCapture, nullptr);
|
||||
}
|
||||
|
||||
//
|
||||
// OnFinishCapture()
|
||||
//
|
||||
// Because of the asynchronous nature of the MF Work Queues and the DataWriter, there could still be
|
||||
// a sample processing. So this will get called to finalize the WAV header.
|
||||
//
|
||||
HRESULT CLoopbackCapture::OnFinishCapture(IMFAsyncResult* pResult)
|
||||
{
|
||||
// FixWAVHeader will set the DeviceStateStopped when all async tasks are complete
|
||||
HRESULT hr = FixWAVHeader();
|
||||
|
||||
m_DeviceState = DeviceState::Stopped;
|
||||
|
||||
m_hCaptureStopped.SetEvent();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// OnSampleReady()
|
||||
//
|
||||
// Callback method when ready to fill sample buffer
|
||||
//
|
||||
HRESULT CLoopbackCapture::OnSampleReady(IMFAsyncResult* pResult)
|
||||
{
|
||||
if (SUCCEEDED(OnAudioSampleRequested()))
|
||||
{
|
||||
// Re-queue work item for next sample
|
||||
if (m_DeviceState == DeviceState::Capturing)
|
||||
{
|
||||
// Re-queue work item for next sample
|
||||
return MFPutWaitingWorkItem(m_SampleReadyEvent.get(), 0, m_SampleReadyAsyncResult.get(), &m_SampleReadyKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DeviceState = DeviceState::Error;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnAudioSampleRequested()
|
||||
//
|
||||
// Called when audio device fires m_SampleReadyEvent
|
||||
//
|
||||
HRESULT CLoopbackCapture::OnAudioSampleRequested()
|
||||
{
|
||||
UINT32 FramesAvailable = 0;
|
||||
BYTE* Data = nullptr;
|
||||
DWORD dwCaptureFlags;
|
||||
UINT64 u64DevicePosition = 0;
|
||||
UINT64 u64QPCPosition = 0;
|
||||
DWORD cbBytesToCapture = 0;
|
||||
|
||||
auto lock = m_CritSec.lock();
|
||||
|
||||
// If this flag is set, we have already queued up the async call to finialize the WAV header
|
||||
// So we don't want to grab or write any more data that would possibly give us an invalid size
|
||||
if (m_DeviceState == DeviceState::Stopping)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// A word on why we have a loop here;
|
||||
// Suppose it has been 10 milliseconds or so since the last time
|
||||
// this routine was invoked, and that we're capturing 48000 samples per second.
|
||||
//
|
||||
// The audio engine can be reasonably expected to have accumulated about that much
|
||||
// audio data - that is, about 480 samples.
|
||||
//
|
||||
// However, the audio engine is free to accumulate this in various ways:
|
||||
// a. as a single packet of 480 samples, OR
|
||||
// b. as a packet of 80 samples plus a packet of 400 samples, OR
|
||||
// c. as 48 packets of 10 samples each.
|
||||
//
|
||||
// In particular, there is no guarantee that this routine will be
|
||||
// run once for each packet.
|
||||
//
|
||||
// So every time this routine runs, we need to read ALL the packets
|
||||
// that are now available;
|
||||
//
|
||||
// We do this by calling IAudioCaptureClient::GetNextPacketSize
|
||||
// over and over again until it indicates there are no more packets remaining.
|
||||
while (SUCCEEDED(m_AudioCaptureClient->GetNextPacketSize(&FramesAvailable)) && FramesAvailable > 0)
|
||||
{
|
||||
cbBytesToCapture = FramesAvailable * m_CaptureFormat.nBlockAlign;
|
||||
|
||||
// WAV files have a 4GB (0xFFFFFFFF) size limit, so likely we have hit that limit when we
|
||||
// overflow here. Time to stop the capture
|
||||
if ((m_cbDataSize + cbBytesToCapture) < m_cbDataSize)
|
||||
{
|
||||
StopCaptureAsync();
|
||||
break;
|
||||
}
|
||||
|
||||
// Get sample buffer
|
||||
RETURN_IF_FAILED(m_AudioCaptureClient->GetBuffer(&Data, &FramesAvailable, &dwCaptureFlags, &u64DevicePosition, &u64QPCPosition));
|
||||
|
||||
|
||||
// Write File
|
||||
if (m_DeviceState != DeviceState::Stopping)
|
||||
{
|
||||
DWORD dwBytesWritten = 0;
|
||||
RETURN_IF_WIN32_BOOL_FALSE(WriteFile(
|
||||
m_hFile.get(),
|
||||
Data,
|
||||
cbBytesToCapture,
|
||||
&dwBytesWritten,
|
||||
NULL));
|
||||
}
|
||||
|
||||
// Release buffer back
|
||||
m_AudioCaptureClient->ReleaseBuffer(FramesAvailable);
|
||||
|
||||
// Increase the size of our 'data' chunk. m_cbDataSize needs to be accurate
|
||||
m_cbDataSize += cbBytesToCapture;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
86
Samples/ApplicationLoopback/cpp/LoopbackCapture.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <AudioClient.h>
|
||||
#include <mmdeviceapi.h>
|
||||
#include <initguid.h>
|
||||
#include <guiddef.h>
|
||||
#include <mfapi.h>
|
||||
|
||||
#include <wrl\implements.h>
|
||||
#include <wil\com.h>
|
||||
#include <wil\result.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
class CLoopbackCapture :
|
||||
public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
|
||||
{
|
||||
public:
|
||||
CLoopbackCapture() = default;
|
||||
~CLoopbackCapture();
|
||||
|
||||
HRESULT StartCaptureAsync(DWORD processId, bool includeProcessTree, PCWSTR outputFileName);
|
||||
HRESULT StopCaptureAsync();
|
||||
|
||||
METHODASYNCCALLBACK(CLoopbackCapture, StartCapture, OnStartCapture);
|
||||
METHODASYNCCALLBACK(CLoopbackCapture, StopCapture, OnStopCapture);
|
||||
METHODASYNCCALLBACK(CLoopbackCapture, SampleReady, OnSampleReady);
|
||||
METHODASYNCCALLBACK(CLoopbackCapture, FinishCapture, OnFinishCapture);
|
||||
|
||||
// IActivateAudioInterfaceCompletionHandler
|
||||
STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation* operation);
|
||||
|
||||
private:
|
||||
// NB: All states >= Initialized will allow some methods
|
||||
// to be called successfully on the Audio Client
|
||||
enum class DeviceState
|
||||
{
|
||||
Uninitialized,
|
||||
Error,
|
||||
Initialized,
|
||||
Starting,
|
||||
Capturing,
|
||||
Stopping,
|
||||
Stopped,
|
||||
};
|
||||
|
||||
HRESULT OnStartCapture(IMFAsyncResult* pResult);
|
||||
HRESULT OnStopCapture(IMFAsyncResult* pResult);
|
||||
HRESULT OnFinishCapture(IMFAsyncResult* pResult);
|
||||
HRESULT OnSampleReady(IMFAsyncResult* pResult);
|
||||
|
||||
HRESULT InitializeLoopbackCapture();
|
||||
HRESULT CreateWAVFile();
|
||||
HRESULT FixWAVHeader();
|
||||
HRESULT OnAudioSampleRequested();
|
||||
|
||||
HRESULT ActivateAudioInterface(DWORD processId, bool includeProcessTree);
|
||||
HRESULT FinishCaptureAsync();
|
||||
|
||||
HRESULT SetDeviceStateErrorIfFailed(HRESULT hr);
|
||||
|
||||
wil::com_ptr_nothrow<IAudioClient> m_AudioClient;
|
||||
WAVEFORMATEX m_CaptureFormat{};
|
||||
UINT32 m_BufferFrames = 0;
|
||||
wil::com_ptr_nothrow<IAudioCaptureClient> m_AudioCaptureClient;
|
||||
wil::com_ptr_nothrow<IMFAsyncResult> m_SampleReadyAsyncResult;
|
||||
|
||||
wil::unique_event_nothrow m_SampleReadyEvent;
|
||||
MFWORKITEM_KEY m_SampleReadyKey = 0;
|
||||
wil::unique_hfile m_hFile;
|
||||
wil::critical_section m_CritSec;
|
||||
DWORD m_dwQueueID = 0;
|
||||
DWORD m_cbHeaderSize = 0;
|
||||
DWORD m_cbDataSize = 0;
|
||||
|
||||
// These two members are used to communicate between the main thread
|
||||
// and the ActivateCompleted callback.
|
||||
PCWSTR m_outputFileName = nullptr;
|
||||
HRESULT m_activateResult = E_UNEXPECTED;
|
||||
|
||||
DeviceState m_DeviceState{ DeviceState::Uninitialized };
|
||||
wil::unique_event_nothrow m_hActivateCompleted;
|
||||
wil::unique_event_nothrow m_hCaptureStopped;
|
||||
};
|
||||
4
Samples/ApplicationLoopback/cpp/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
97
Samples/AppxPackingCreateAppx/README.md
Normal file
@ -0,0 +1,97 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: Create app package sample
|
||||
urlFragment: create-app-package
|
||||
description: Demonstrates how to create an app package by using the app Packaging API.
|
||||
---
|
||||
|
||||
# Create app package sample
|
||||
|
||||
This sample shows you how to create an app package by using the app [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766).
|
||||
|
||||
Users acquire your app as an app package. Windows uses the information in an app package to install the app on a per-user basis, and ensure that all traces of the app are gone from the device after all users who installed the app uninstall it. Each package consists of the files that constitute the app, along with a package manifest file that describes the app to Windows.
|
||||
|
||||
The sample covers the following tasks:
|
||||
|
||||
- Use [IAppxFactory::CreatePackageWriter](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446679) to create a package writer.
|
||||
- Use [IAppxPackageWriter::AddPayloadFile](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446763) to add the payload files to the package.
|
||||
- Create an input stream and use [IAppxPackageWriter::Close](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446764) to write the manifest at the end of the package.
|
||||
|
||||
**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU); it doesn't compile with Microsoft Visual Studio Express 2013 for Windows.
|
||||
|
||||
**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample!
|
||||
|
||||
To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696).
|
||||
|
||||
To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697).
|
||||
|
||||
## Operating system requirements
|
||||
|
||||
### Client
|
||||
|
||||
Windows 8.1
|
||||
|
||||
### Server
|
||||
|
||||
Windows Server 2012 R2
|
||||
|
||||
## Build the sample
|
||||
|
||||
### From the Command window
|
||||
|
||||
1. Open a Command window.
|
||||
|
||||
2. Go to the directory where you downloaded the CreateAppx sample.
|
||||
|
||||
3. Run the following command:
|
||||
|
||||
```msbuild CreateAppx.sln```
|
||||
|
||||
### From Visual Studio
|
||||
|
||||
1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**.
|
||||
|
||||
2. Go to the directory where you downloaded the CreateAppx sample and select its Microsoft Visual Studio Solution (*.sln*) file.
|
||||
|
||||
3. Press **F7** (or **F6** for Visual Studio 2013) or use **Build** \> **Build Solution**.
|
||||
|
||||
Run the sample
|
||||
--------------
|
||||
|
||||
1. Open a Command window.
|
||||
|
||||
2. Go to the *CreateAppx\\Data* directory.
|
||||
|
||||
3. Run the following command (where \<path\> is "..\\debug\\CreateAppx" or "..\\release\\CreateAppx"):
|
||||
|
||||
```\<path\>\\CreateAppx```
|
||||
|
||||
This command creates an app package named *HelloWorld.appx* from the contents of the *CreateAppx\\Data* directory.
|
||||
|
||||
## Related topics
|
||||
|
||||
### Sample
|
||||
|
||||
[Extract app package contents sample](http://go.microsoft.com/fwlink/p/?linkid=106455)
|
||||
|
||||
### Tasks
|
||||
|
||||
[How to create a package](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446616)
|
||||
|
||||
### Concepts
|
||||
|
||||
[App packages and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh464929)
|
||||
|
||||
### Reference
|
||||
|
||||
[IAppxFactory::CreatePackageWriter](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446679)
|
||||
|
||||
[IAppxPackageWriter](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446762)
|
||||
|
||||
## Related technologies
|
||||
|
||||
[App packaging and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446593)
|
||||
266
Samples/AppxPackingCreateAppx/cpp/CreateAppx.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
// This is a simple application which uses the Appx packaging APIs to produce
|
||||
// an Appx package from a list of files on disk.
|
||||
//
|
||||
// For the sake of simplicity, the list of files to be packaged is hard coded
|
||||
// in this sample. A fully functional application might read its list of
|
||||
// files from user input, or even generate content dynamically.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#include <AppxPackaging.h> // For Appx Packaging APIs
|
||||
|
||||
#include "CreateAppx.h"
|
||||
|
||||
// Path where all input files are stored
|
||||
const LPCWSTR DataPath = L"Data\\";
|
||||
|
||||
// The produced Appx package's content consists of these files, with
|
||||
// corresponding content types and compression options.
|
||||
const int PayloadFilesCount = 4;
|
||||
const LPCWSTR PayloadFilesName[PayloadFilesCount] = {
|
||||
L"AppTile.png",
|
||||
L"Default.html",
|
||||
L"images\\smiley.jpg",
|
||||
L"Error.html",
|
||||
};
|
||||
const LPCWSTR PayloadFilesContentType[PayloadFilesCount] = {
|
||||
L"image/png",
|
||||
L"text/html",
|
||||
L"image/jpeg",
|
||||
L"text/html",
|
||||
};
|
||||
const APPX_COMPRESSION_OPTION PayloadFilesCompression[PayloadFilesCount] = {
|
||||
APPX_COMPRESSION_OPTION_NONE,
|
||||
APPX_COMPRESSION_OPTION_NORMAL,
|
||||
APPX_COMPRESSION_OPTION_NONE,
|
||||
APPX_COMPRESSION_OPTION_NORMAL,
|
||||
};
|
||||
|
||||
// The Appx package's manifest is read from this file
|
||||
const LPCWSTR ManifestFileName = L"AppxManifest.xml";
|
||||
|
||||
// The hash algorithm to be used for the package's block map is SHA2-256
|
||||
const LPCWSTR Sha256AlgorithmUri = L"http://www.w3.org/2001/04/xmlenc#sha256";
|
||||
|
||||
// The produced package will be stored under this file name
|
||||
const LPCWSTR OutputPackagePath = L"HelloWorld.appx";
|
||||
|
||||
//
|
||||
// Function to create a readable IStream over the file whose name is the
|
||||
// concatenation of the path and fileName parameters. For simplicity, file
|
||||
// names including path are assumed to be 100 characters or less. A real
|
||||
// application should be able to handle longer names and allocate the
|
||||
// necessary buffer dynamically.
|
||||
//
|
||||
// Parameters:
|
||||
// path - Path of the folder containing the file to be opened, ending with a
|
||||
// slash ('\') character
|
||||
// fileName - Name, not including path, of the file to be opened
|
||||
// stream - Output parameter pointing to the created instance of IStream over
|
||||
// the specified file when this function succeeds.
|
||||
//
|
||||
HRESULT GetFileStream(
|
||||
_In_ LPCWSTR path,
|
||||
_In_ LPCWSTR fileName,
|
||||
_Outptr_ IStream** stream)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
const int MaxFileNameLength = 100;
|
||||
WCHAR fullFileName[MaxFileNameLength + 1];
|
||||
|
||||
// Create full file name by concatenating path and fileName
|
||||
hr = StringCchCopyW(fullFileName, MaxFileNameLength, path);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = StringCchCat(fullFileName, MaxFileNameLength, fileName);
|
||||
}
|
||||
|
||||
// Create stream for reading the file
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = SHCreateStreamOnFileEx(
|
||||
fullFileName,
|
||||
STGM_READ | STGM_SHARE_EXCLUSIVE,
|
||||
0, // default file attributes
|
||||
FALSE, // do not create new file
|
||||
NULL, // no template
|
||||
stream);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// Function to create an Appx package writer with default settings, given the
|
||||
// output file name.
|
||||
//
|
||||
// Parameters:
|
||||
// outputFileName - Name including path to the Appx package (.appx file) to be
|
||||
// created.
|
||||
// writer - Output parameter pointing to the created instance of
|
||||
// IAppxPackageWriter when this function succeeds.
|
||||
//
|
||||
HRESULT GetPackageWriter(
|
||||
_In_ LPCWSTR outputFileName,
|
||||
_Outptr_ IAppxPackageWriter** writer)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
IStream* outputStream = NULL;
|
||||
IUri* hashMethod = NULL;
|
||||
APPX_PACKAGE_SETTINGS packageSettings = {0};
|
||||
IAppxFactory* appxFactory = NULL;
|
||||
|
||||
// Create a stream over the output file where the package will be written
|
||||
hr = SHCreateStreamOnFileEx(
|
||||
outputFileName,
|
||||
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
|
||||
0, // default file attributes
|
||||
TRUE, // create file if it does not exist
|
||||
NULL, // no template
|
||||
&outputStream);
|
||||
|
||||
// Create default package writer settings, including hash algorithm URI
|
||||
// and Zip format.
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = CreateUri(
|
||||
Sha256AlgorithmUri,
|
||||
Uri_CREATE_CANONICALIZE,
|
||||
0, // reserved parameter
|
||||
&hashMethod);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
packageSettings.forceZip32 = TRUE;
|
||||
packageSettings.hashMethod = hashMethod;
|
||||
}
|
||||
|
||||
// Create a new Appx factory
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = CoCreateInstance(
|
||||
__uuidof(AppxFactory),
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IAppxFactory),
|
||||
(LPVOID*)(&appxFactory));
|
||||
}
|
||||
|
||||
// Create a new package writer using the factory
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = appxFactory->CreatePackageWriter(
|
||||
outputStream,
|
||||
&packageSettings,
|
||||
writer);
|
||||
}
|
||||
|
||||
// Clean up allocated resources
|
||||
if (appxFactory != NULL)
|
||||
{
|
||||
appxFactory->Release();
|
||||
appxFactory = NULL;
|
||||
}
|
||||
if (hashMethod != NULL)
|
||||
{
|
||||
hashMethod->Release();
|
||||
hashMethod = NULL;
|
||||
}
|
||||
if (outputStream != NULL)
|
||||
{
|
||||
outputStream->Release();
|
||||
outputStream = NULL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// Main entry point of the sample
|
||||
//
|
||||
int wmain()
|
||||
{
|
||||
wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n");
|
||||
wprintf(L"CreateAppx sample\n\n");
|
||||
|
||||
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Create a package writer
|
||||
IAppxPackageWriter* packageWriter = NULL;
|
||||
IStream* manifestStream = NULL;
|
||||
|
||||
wprintf(L"\nCreating package writer\n\n");
|
||||
|
||||
hr = GetPackageWriter(OutputPackagePath, &packageWriter);
|
||||
|
||||
// Add all payload files to the package writer
|
||||
for (int i = 0; SUCCEEDED(hr) && (i < PayloadFilesCount); i++)
|
||||
{
|
||||
IStream* fileStream = NULL;
|
||||
|
||||
wprintf(L"Adding file: %s\n", PayloadFilesName[i]);
|
||||
|
||||
hr = GetFileStream(DataPath, PayloadFilesName[i], &fileStream);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
packageWriter->AddPayloadFile(
|
||||
PayloadFilesName[i],
|
||||
PayloadFilesContentType[i],
|
||||
PayloadFilesCompression[i],
|
||||
fileStream);
|
||||
}
|
||||
|
||||
if (fileStream != NULL)
|
||||
{
|
||||
fileStream->Release();
|
||||
fileStream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Add manifest to package and close package writer
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
wprintf(L"\nClosing package writer and adding AppxManifest.xml as the package manifest\n");
|
||||
hr = GetFileStream(DataPath, ManifestFileName, &manifestStream);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = packageWriter->Close(manifestStream);
|
||||
}
|
||||
|
||||
// Clean up allocated resources
|
||||
if (manifestStream != NULL)
|
||||
{
|
||||
manifestStream->Release();
|
||||
manifestStream = NULL;
|
||||
}
|
||||
if (packageWriter != NULL)
|
||||
{
|
||||
packageWriter->Release();
|
||||
packageWriter = NULL;
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
wprintf(L"\nPackage successfully saved to %s.\n", OutputPackagePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf(L"\nPackage creation failed with HRESULT 0x%08X.\n", hr);
|
||||
}
|
||||
return SUCCEEDED(hr) ? 0 : 1;
|
||||
}
|
||||
31
Samples/AppxPackingCreateAppx/cpp/CreateAppx.h
Normal file
@ -0,0 +1,31 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
// This is a simple application which uses the Appx packaging APIs to produce
|
||||
// an Appx package from a list of files on disk.
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Function to create a readable IStream over the file whose name is the
|
||||
// concatenation of the path and fileName parameters. For simplicity, file
|
||||
// names including path are assumed to be 100 characters or less. A real
|
||||
// application should be able to handle longer names and allocate the
|
||||
// necessary buffer dynamically.
|
||||
//
|
||||
HRESULT GetFileStream(
|
||||
_In_ LPCWSTR path,
|
||||
_In_ LPCWSTR fileName,
|
||||
_Outptr_ IStream** stream);
|
||||
|
||||
//
|
||||
// Function to create an Appx package writer with default settings, given the
|
||||
// output file name.
|
||||
//
|
||||
HRESULT GetPackageWriter(
|
||||
_In_ LPCWSTR outputFileName,
|
||||
_Outptr_ IAppxPackageWriter** writer);
|
||||
20
Samples/AppxPackingCreateAppx/cpp/CreateAppx.sln
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 11
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CreateAppx", "CreateAppx.vcxproj", "{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
110
Samples/AppxPackingCreateAppx/cpp/CreateAppx.vcxproj
Normal file
@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and '$(VisualStudioVersion)' == ''">$(VCTargetsPath11)</VCTargetsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}</ProjectGuid>
|
||||
<RootNamespace>CreateAppx</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<UseOfAtl>false</UseOfAtl>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<UseOfAtl>false</UseOfAtl>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.40602.0</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>urlmon.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>urlmon.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CreateAppx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CreateAppx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="readme.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
BIN
Samples/AppxPackingCreateAppx/cpp/Data/AppTile.png
Normal file
|
After Width: | Height: | Size: 1023 B |
42
Samples/AppxPackingCreateAppx/cpp/Data/AppxManifest.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
|
||||
<Identity Name="Microsoft.SDKSamples.HelloWorldPackage"
|
||||
ProcessorArchitecture="neutral"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="1.0.0.0"
|
||||
ResourceId="en-us"
|
||||
/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>HelloWorld</DisplayName>
|
||||
<Description>Sample package containing a "Hello World!" application</Description>
|
||||
<Logo>AppTile.png</Logo>
|
||||
<PublisherDisplayName>Microsoft</PublisherDisplayName>
|
||||
</Properties>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="en-us"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="HelloWorld" StartPage="Default.html">
|
||||
<VisualElements DisplayName="Hello World Sample App"
|
||||
Logo="AppTile.png"
|
||||
SmallLogo="AppTile.png"
|
||||
Description="Hello world package!"
|
||||
BackgroundColor="#AA00AA"
|
||||
ForegroundText="light"
|
||||
>
|
||||
<DefaultTile WideLogo="AppTile.png" />
|
||||
<SplashScreen Image="AppTile.png" />
|
||||
</VisualElements>
|
||||
</Application>
|
||||
|
||||
</Applications>
|
||||
|
||||
<Prerequisites>
|
||||
<OSMinVersion>6.2.1</OSMinVersion>
|
||||
<OSMaxVersionTested>6.2.1</OSMaxVersionTested>
|
||||
</Prerequisites>
|
||||
</Package>
|
||||
8
Samples/AppxPackingCreateAppx/cpp/Data/Default.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>Hello World</title>
|
||||
</head><body>
|
||||
<h2>Hello world!</h2>
|
||||
<img src="images\smiley.jpg">
|
||||
</body></html>
|
||||
1
Samples/AppxPackingCreateAppx/cpp/Data/Error.html
Normal file
@ -0,0 +1 @@
|
||||
<html><body>Error!</body></html>
|
||||
BIN
Samples/AppxPackingCreateAppx/cpp/Data/images/smiley.jpg
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
72
Samples/AppxPackingCreateAppx/cpp/readme.txt
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
Appx Package Creation Sample
|
||||
============================
|
||||
|
||||
This sample demonstrates how to use Appx packaging APIs to produce an Appx package from a collection of files on disk.
|
||||
|
||||
The package created using data files supplied with this sample is a valid Windows Modern Application. It can be installed in Windows 8 or above if it is signed with a valid developer test certificate.
|
||||
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
This sample requires Windows 8 or higher, and an installation of Visual Studio 2012 Ultimate.
|
||||
|
||||
|
||||
Sample Language Implementations
|
||||
===============================
|
||||
|
||||
This sample is available in the following language implementations:
|
||||
|
||||
C++
|
||||
|
||||
|
||||
Files
|
||||
=====
|
||||
|
||||
CreateAppx.cpp - main entry point for the sample application
|
||||
|
||||
CreateAppx.h - main header file
|
||||
|
||||
CreateAppx.vcxproj - build configuration for this sample
|
||||
|
||||
CreateAppx.sln - Visual Studio 2012 Solution file for this sample
|
||||
|
||||
Data\AppxManifest.xml - A sample Appx package manifest for the package to be produced
|
||||
|
||||
Data\AppTile.png
|
||||
Data\Default.html
|
||||
Data\Error.html
|
||||
Data\images\smiley.jpg - Sample data (payload) files for the package to be produced
|
||||
|
||||
|
||||
To build the sample using the command prompt:
|
||||
=============================================
|
||||
|
||||
1. Open the Command Prompt window and navigate to the directory containing CreateAppx.vcxproj
|
||||
|
||||
2. Type: msbuild CreateAppx.vcxproj
|
||||
|
||||
|
||||
To build the sample using Visual Studio 2012 Ultimate (preferred method):
|
||||
=========================================================================
|
||||
|
||||
1. Open File Explorer and navigate to the directory containing CreateAppx.vcxproj.
|
||||
|
||||
2. Double-click the icon for the CreateAppx.vcxproj file to open the file in Visual Studio.
|
||||
|
||||
3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory.
|
||||
|
||||
|
||||
To run the sample:
|
||||
==================
|
||||
|
||||
1. Open a command prompt window and navigate to the directory containing the Data folder for this sample.
|
||||
|
||||
2. Type the command:
|
||||
|
||||
<path>\CreateAppx.exe
|
||||
|
||||
where <path> is the full or relative path to where CreateAppx.exe is built. If CreateAppx.exe is built using Visual Studio, then <path> is usually "Debug" or "Release" depending on the configuration used.
|
||||
|
||||
3. When the application exits successfully, an Appx package named "HelloWorld.appx" should be created.
|
||||
48
Samples/AppxPackingCreateBundle/README.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows-api-win32
|
||||
name: Create app bundle sample
|
||||
urlFragment: create-app-bundle
|
||||
description: Demonstrates how to create an app bundle using the Packaging API.
|
||||
---
|
||||
|
||||
# Create app bundle sample
|
||||
|
||||
This sample shows you how to create an app bundle using the [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766).
|
||||
|
||||
The sample covers these tasks:
|
||||
|
||||
- Use [IAppxBundleFactory::CreateBundleWriter](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280280) to create a bundle writer.
|
||||
- Use [IAppxBundleWriter::AddPayloadPackage](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280303) to add the payload packages to the bundle.
|
||||
- Create an input stream and use [IAppxBundleWriter::Close](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280304) to flush the stream.
|
||||
|
||||
## Operating system requirements
|
||||
|
||||
### Client
|
||||
|
||||
Windows 8.1
|
||||
|
||||
### Server
|
||||
|
||||
Windows Server 2012 R2
|
||||
|
||||
## Build the sample
|
||||
|
||||
1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**.
|
||||
2. Go to the directory named for the sample, and double-click the Visual Studio Solution (*.sln*) file.
|
||||
3. Press **F7** or use **Build** \> **Build Solution** to build the sample.
|
||||
|
||||
## Run the sample
|
||||
|
||||
To debug the app and then run it, press **F5** or use **Debug** \> **Start Debugging**. To run the app without debugging, press **Ctrl**+**F5** or use **Debug** \> **Start Without Debugging**.
|
||||
|
||||
## Related topics
|
||||
|
||||
### Reference
|
||||
|
||||
[IAppxBundleFactory::CreateBundleWriter](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280280)
|
||||
|
||||
[IAppxBundleWriter](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280302)
|
||||