diff --git a/Samples/AppTabsIntegration/README.md b/Samples/AppTabsIntegration/README.md new file mode 100644 index 00000000..508d9cdc --- /dev/null +++ b/Samples/AppTabsIntegration/README.md @@ -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. diff --git a/Samples/AppTabsIntegration/cpp/App.idl b/Samples/AppTabsIntegration/cpp/App.idl new file mode 100644 index 00000000..142d0dbf --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/App.idl @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +namespace AppTabsIntegration +{ +} diff --git a/Samples/AppTabsIntegration/cpp/App.xaml b/Samples/AppTabsIntegration/cpp/App.xaml new file mode 100644 index 00000000..8fdedc05 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/App.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/Samples/AppTabsIntegration/cpp/App.xaml.cpp b/Samples/AppTabsIntegration/cpp/App.xaml.cpp new file mode 100644 index 00000000..c82c3fbe --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/App.xaml.cpp @@ -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. + +/// +/// 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(). +/// +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 +} + +/// +/// Invoked when the application is launched. +/// +/// Details about the launch request and process. +void App::OnLaunched(LaunchActivatedEventArgs const&) +{ + window = make(); + window.Activate(); +} diff --git a/Samples/AppTabsIntegration/cpp/App.xaml.h b/Samples/AppTabsIntegration/cpp/App.xaml.h new file mode 100644 index 00000000..86d6da43 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/App.xaml.h @@ -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(); + + void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&); + + private: + winrt::Microsoft::UI::Xaml::Window window{ nullptr }; + }; +} diff --git a/Samples/AppTabsIntegration/cpp/AppTabsIntegration.sln b/Samples/AppTabsIntegration/cpp/AppTabsIntegration.sln new file mode 100644 index 00000000..0a40d47b --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/AppTabsIntegration.sln @@ -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 diff --git a/Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj b/Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj new file mode 100644 index 00000000..d920b480 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj @@ -0,0 +1,208 @@ + + + + + + + true + true + true + {4fcf5980-c8b1-4e00-93d9-f79c7b718387} + AppTabsIntegration + AppTabsIntegration + + $(RootNamespace) + en-US + 16.0 + false + true + Windows Store + 10.0 + 10.0 + 10.0.19041.0 + true + true + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + ARM64 + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v143 + Unicode + true + + + true + true + + + false + true + false + + + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + Designer + + + + + + + + + App.xaml + + + MainWindow.xaml + + + + + + + + + + Create + + + App.xaml + + + MainWindow.xaml + + + + + + + Code + App.xaml + + + Code + MainWindow.xaml + + + + + + false + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + 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}. + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj.filters b/Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj.filters new file mode 100644 index 00000000..af2d6e58 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/AppTabsIntegration.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + {4fcf5980-c8b1-4e00-93d9-f79c7b718387} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppTabsIntegration/cpp/Assets/LockScreenLogo.scale-200.png b/Samples/AppTabsIntegration/cpp/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 00000000..7440f0d4 Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/LockScreenLogo.scale-200.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/SplashScreen.scale-200.png b/Samples/AppTabsIntegration/cpp/Assets/SplashScreen.scale-200.png new file mode 100644 index 00000000..32f486a8 Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/SplashScreen.scale-200.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/Square150x150Logo.scale-200.png b/Samples/AppTabsIntegration/cpp/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 00000000..53ee3777 Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/Square150x150Logo.scale-200.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/Square44x44Logo.scale-200.png b/Samples/AppTabsIntegration/cpp/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 00000000..f713bba6 Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/Square44x44Logo.scale-200.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/AppTabsIntegration/cpp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 00000000..dc9f5bea Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/StoreLogo.png b/Samples/AppTabsIntegration/cpp/Assets/StoreLogo.png new file mode 100644 index 00000000..a4586f26 Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/StoreLogo.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/Wide310x150Logo.scale-200.png b/Samples/AppTabsIntegration/cpp/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 00000000..8b4a5d0d Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/Wide310x150Logo.scale-200.png differ diff --git a/Samples/AppTabsIntegration/cpp/Assets/icon.ico b/Samples/AppTabsIntegration/cpp/Assets/icon.ico new file mode 100644 index 00000000..a686070c Binary files /dev/null and b/Samples/AppTabsIntegration/cpp/Assets/icon.ico differ diff --git a/Samples/AppTabsIntegration/cpp/MainWindow.idl b/Samples/AppTabsIntegration/cpp/MainWindow.idl new file mode 100644 index 00000000..72e3eeab --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/MainWindow.idl @@ -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(); + } +} diff --git a/Samples/AppTabsIntegration/cpp/MainWindow.xaml b/Samples/AppTabsIntegration/cpp/MainWindow.xaml new file mode 100644 index 00000000..30011bb5 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/MainWindow.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/AppTabsIntegration/cpp/MainWindow.xaml.cpp b/Samples/AppTabsIntegration/cpp/MainWindow.xaml.cpp new file mode 100644 index 00000000..6ed3b578 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/MainWindow.xaml.cpp @@ -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(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().FlowDirection(FlowDirection::RightToLeft); + } + + // Add WindowTabManager support if it is available. + if (ApiInformation::IsApiContractPresent(winrt::name_of(), 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(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(); + 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(); + 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(); + RemoveTabByItem(tabViewModel); + + // Create another MainWindow with that tab as its only tab. + auto tornOut = winrt::make(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(&rect), 2); + if (this->Content().as().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 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(tabViewModel); + + HWND hwnd; + winrt::check_hresult(tornOut.try_as<::IWindowNative>()->get_WindowHandle(&hwnd)); + args.WindowId(reinterpret_cast(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(); + } + } +} diff --git a/Samples/AppTabsIntegration/cpp/MainWindow.xaml.h b/Samples/AppTabsIntegration/cpp/MainWindow.xaml.h new file mode 100644 index 00000000..02b0391f --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/MainWindow.xaml.h @@ -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(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 const& sender, Windows::Foundation::Collections::IVectorChangedEventArgs const& args); + + void RemoveTabByItem(AppTabsIntegration::TabViewModel const& tabViewModel); + AppTabsIntegration::TabViewModel CreateTabViewModel(); + + winrt::Windows::Foundation::Collections::IObservableVector m_tabs = winrt::single_threaded_observable_vector(); + 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 + { + }; +} diff --git a/Samples/AppTabsIntegration/cpp/Package.appxmanifest b/Samples/AppTabsIntegration/cpp/Package.appxmanifest new file mode 100644 index 00000000..4123b165 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/Package.appxmanifest @@ -0,0 +1,48 @@ + + + + + + + + AppTabsIntegration + sankalpg + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/AppTabsIntegration/cpp/TabViewModel.cpp b/Samples/AppTabsIntegration/cpp/TabViewModel.cpp new file mode 100644 index 00000000..17df25c2 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/TabViewModel.cpp @@ -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(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 + struct InspectableWeakReference : winrt::implements, winrt::IInspectable> + { + InspectableWeakReference(winrt::weak_ref const& weak) : m_weak(weak) {} + T get() const { return m_weak.get(); } + + winrt::weak_ref 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>(*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>(windowTab.Tag())->get(); + } + + /* static */ winrt::WindowTab TabViewModel::GetWindowTab(winrt::TabViewModel const& tabViewModel) + { + // From the TabViewModel, get the WindowTab. + return winrt::get_self(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"); + } + } +} diff --git a/Samples/AppTabsIntegration/cpp/TabViewModel.h b/Samples/AppTabsIntegration/cpp/TabViewModel.h new file mode 100644 index 00000000..2df0f7e2 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/TabViewModel.h @@ -0,0 +1,42 @@ +#pragma once +#include "TabViewModel.g.h" + +namespace winrt::AppTabsIntegration::implementation +{ + struct TabViewModel : TabViewModelT + { + 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 m_propertyChanged; + winrt::Windows::UI::Shell::WindowTab const m_windowTab; + winrt::hstring m_name{}; + winrt::Windows::UI::Color m_color; + + template + void NotifyChange(T&& name) + { + m_propertyChanged(*this, winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventArgs(std::forward(name))); + } + }; +} diff --git a/Samples/AppTabsIntegration/cpp/TabViewModel.idl b/Samples/AppTabsIntegration/cpp/TabViewModel.idl new file mode 100644 index 00000000..01fc6510 --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/TabViewModel.idl @@ -0,0 +1,8 @@ +namespace AppTabsIntegration +{ + runtimeclass TabViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged + { + String Name; + Windows.UI.Color Color; + } +} diff --git a/Samples/AppTabsIntegration/cpp/app.manifest b/Samples/AppTabsIntegration/cpp/app.manifest new file mode 100644 index 00000000..dd122c9f --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/app.manifest @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/Samples/AppTabsIntegration/cpp/packages.config b/Samples/AppTabsIntegration/cpp/packages.config new file mode 100644 index 00000000..18f5f2ba --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Samples/AppTabsIntegration/cpp/pch.cpp b/Samples/AppTabsIntegration/cpp/pch.cpp new file mode 100644 index 00000000..0850baca --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" diff --git a/Samples/AppTabsIntegration/cpp/pch.h b/Samples/AppTabsIntegration/cpp/pch.h new file mode 100644 index 00000000..1e2d48ea --- /dev/null +++ b/Samples/AppTabsIntegration/cpp/pch.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once +#include +#include +#include +#include +#include +#include + +// Undefine GetCurrentTime macro to prevent +// conflict with Storyboard::GetCurrentTime +#undef GetCurrentTime + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Verify that the correct WindowsDesktop reference has been added. +namespace winrt::Windows::UI::Shell +{ + struct WindowTabManager; + struct IWindowTabManager; + static_assert(std::is_same_v, IWindowTabManager>, + "Please add a reference to the Windows Desktop Extension SDK, version 10.0.22621.1778 or higher."); +} diff --git a/Samples/BindLink/BindLink.sln b/Samples/BindLink/BindLink.sln new file mode 100644 index 00000000..37741176 --- /dev/null +++ b/Samples/BindLink/BindLink.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33516.290 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BindLink", "BindLink.vcxproj", "{20FDBB33-84E9-458C-9817-3AA0083C82F0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F7D1BC06-707F-4CBB-9A53-AE51F73EC000}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +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 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Debug|x64.ActiveCfg = Debug|x64 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Debug|x64.Build.0 = Debug|x64 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Debug|x86.ActiveCfg = Debug|Win32 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Debug|x86.Build.0 = Debug|Win32 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Release|x64.ActiveCfg = Release|x64 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Release|x64.Build.0 = Release|x64 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Release|x86.ActiveCfg = Release|Win32 + {20FDBB33-84E9-458C-9817-3AA0083C82F0}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1D1DC3D1-61CB-4FEF-9AF9-5436040E1E3E} + EndGlobalSection +EndGlobal diff --git a/Samples/BindLink/BindLink.vcxproj b/Samples/BindLink/BindLink.vcxproj new file mode 100644 index 00000000..79fcc684 --- /dev/null +++ b/Samples/BindLink/BindLink.vcxproj @@ -0,0 +1,99 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {20fdbb33-84e9-458c-9817-3aa0083c82f0} + BindFltAPI + 10.0 + BindLink + + + + Application + v143 + Unicode + + + true + true + + + false + true + false + + + + + + + + + + + + + Level3 + true + WIN32;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + bindlink.lib;%(AdditionalDependencies) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + true + true + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + + + + + + + + + + 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}. + + + + \ No newline at end of file diff --git a/Samples/BindLink/BindLinkUtil.cpp b/Samples/BindLink/BindLinkUtil.cpp new file mode 100644 index 00000000..6fdf4950 --- /dev/null +++ b/Samples/BindLink/BindLinkUtil.cpp @@ -0,0 +1,140 @@ +/* +Copyright (c) Microsoft Corporation + +This file contains a sample app showing how to Create and Remove Bind Links. +The assocated README file shows how to use this app to demonstrate the +features of Bind Links. + +*/ + +#include +#include +#include +#include +#if !__has_include() +#error This sample requires the Windows SDK version 10.0.25314.0 or higher. +#endif +#include + +void usage(FILE* fp) +{ + fprintf(fp, "Usage: BindLink command command-parameters [command-options]\n"); + fprintf(fp, "Commands:\n"); + fprintf(fp, " CREATE virtPath targetPath\n"); + fprintf(fp, " REMOVE virtPath\n"); + fprintf(fp, "Command options for CREATE:\n"); + fprintf(fp, " /merge merge bind links\n"); + fprintf(fp, " /read-only read only bind links\n"); +} + +void printErrorDetails(PCWSTR command, HRESULT hr) +{ + std::wcout << command << " failed with HRESULT 0x" << std::hex << std::setw(8) << std::setfill(L'0') << hr << "\n"; + wchar_t buffer[32768]; + if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, + 0, buffer, ARRAYSIZE(buffer), nullptr)) + { + std::wcout << buffer << "\n"; + } +} + +int handleCreateCommand(int argc, wchar_t* argv[]) +{ + // argv[0] = program name + // argv[1] = "CREATE" + // argv[2] = virtPath + // argv[3] = backingPath + // argv[4...] = options + + if (argc < 4) + { + usage(stderr); + return 1; + } + + PCWSTR virtPath = argv[2]; + PCWSTR backingPath = argv[3]; + + auto bindLinkFlags = CREATE_BIND_LINK_FLAG_NONE; + + for (int index = 4; index < argc && argv[index][0] == L'/'; ++index) + { + if (!_wcsicmp(argv[index], L"/read-only")) + { + WI_SetFlag(bindLinkFlags, CREATE_BIND_LINK_FLAG_READ_ONLY); + } + else if (!_wcsicmp(argv[index], L"/merge")) + { + WI_SetFlag(bindLinkFlags, CREATE_BIND_LINK_FLAG_MERGED); + } + else + { + usage(stderr); + return 1; + } + } + + auto hr = CreateBindLink(virtPath, backingPath, bindLinkFlags, 0, nullptr); + + if (FAILED(hr)) + { + printErrorDetails(L"CreateBindLink", hr); + return hr; + } + + std::wcout << "Bind Link Created.\n"; + std::wcout << "\"" << virtPath << "\" draws content from \"" << backingPath << "\"\n"; + + return 0; +} + +int handleRemoveCommand(int argc, wchar_t* argv[]) +{ + // argv[0] = program name + // argv[1] = "REMOVE" + // argv[2] = virtPath + + if (argc != 3) + { + usage(stderr); + return 1; + } + + PCWSTR virtPath = argv[2]; + + auto hr = RemoveBindLink(virtPath); + + if (FAILED(hr)) + { + printErrorDetails(L"RemoveBindLink", hr); + return hr; + } + + std::wcout << "Bind Link for \"" << virtPath << "\" removed.\n"; + + return 0; +} + +int wmain(int argc, wchar_t* argv[]) +{ + if (argc < 2) { + usage(stderr); + return 1; + } + + if (!_wcsicmp(argv[1], L"CREATE")) + { + return handleCreateCommand(argc, argv); + } + else if (!_wcsicmp(argv[1], L"REMOVE")) + { + return handleRemoveCommand(argc, argv); + } + else + { + usage(stderr); + return 1; + } + + return 0; +} diff --git a/Samples/BindLink/README.md b/Samples/BindLink/README.md new file mode 100644 index 00000000..f6c482ca --- /dev/null +++ b/Samples/BindLink/README.md @@ -0,0 +1,121 @@ +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: BindLink sample +urlFragment: bindLink +description: Demonstrates how to get started with Bind Link APIs. +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# BindLink Sample + +This sample shows how to use the Bind Link APIs to link a local "virtualPath" to a local or remote "backingPath". +It also demonstrates how the created Bind Link can be deleted. Note that creating and removing Bind Links +requires administrator privilege. + +The BindLink sample supports the following operations: +* Creating a Bind Link between the "virtualPath" and the "backingPath", optionally in read-only and/or merge modes. +* Deleting the Bind Link. + +The following steps demonstrate how Bind Links work, with the help of the sample. +Follow them in order. + +### Preparation +* Create a directory called C:\backingPath and create files and directories in it. +* Make sure there is no directory C:\virtualPath by looking from Explorer or command prompt. +* Open an administrative command prompt. + +### Creating and removing an anchorless bind link + +An anchorless bind link is one that creates a virtual path where there was no directory before. + +* Continue from the "Preparation" steps above. +* Create a bind link with the command `BindLink.exe CREATE C:\virtualPath C:\backingPath` +* From Explorer or a command prompt, observe that C:\virtualPath contains the same content as C:\backingPath. +* Run the command `BindLink.exe CREATE C:\virtualPath c:\otherBackingPath` +* The command fails with a "file not found" error because c:\otherBackingPath doesn't exist. +* Create the directory c:\otherBackingPath and create files and directories in it. +* Run the command `BindLink.exe CREATE C:\virtualPath c:\otherBackingPath` +* The command fails with an "invalid argument" because there is an existing link from C:\virtualPath. +* Remove the existing bind link with the command `BindLink.exe REMOVE C:\virtualPath` +* Observe that c:\virtualPath doesn't exist anymore. + +### Creating and removing a shadow bind link + +A shadow bind link is one that creates a virtual path that hides (shadows) an existing directory. + +* Continue from the "Creating and removing an anchorless bind link" steps above. +* Create the directory c:\virtualPath and create files and directories in it. +* Run the command `BindLink.exe CREATE C:\virtualPath c:\otherBackingPath` - This will now succeed. +* From Explorer or a command prompt, observe that C:\virtualPath contains the same content as C:\otherBackingPath, + and the contents of C:\backingPath are not present in C:\virtualPath. Also, the contents of c:\virtualPath that were created before the CREATE command are not present. +* Remove the existing bind link with the command `BindLink.exe REMOVE C:\virtualPath` +* The original contents of the directory C:\virtualPath are now present. + +### Creating and removing a merged bind link + +A merged bind link creates a virtual path that matches an existing directory. +The contents of the existing directory are combined with the contents +of another directory. + +* Continue from the "Creating and removing a shadow bind link" steps above. +* Keep the directory C:\virtualPath and its contents on the disk. +* Create a Repeat the above exercise, but this time use the /merge option when creating the binding. + "BindLink.exe CREATE C:\virtualPath c:\otherBackingPath /merge" +* From Explorer or a command prompt or using BindLink.exe LIST, observe that C:\virtualPath contains contents from c:\otherBackingPath as well as + C:\virtualPath before the merged link was created. +* Remove all bindlinks by doing a "BindLink.exe REMOVE C:\virtualPath". Note now that the original contents of the directory C:\virtualPath can be seen. + +### Creating a read-only bind link + +A read-only bind link maps the files in the backing path as read-only. + +* Continue from the "Creating and removing a merged bind link" steps above. +* Keep the directory C:\virtualPath and its contents on the disk. +* Run the command `BindLink.exe CREATE C:\virtualPath c:\otherBackingPath /read-only` +* From Explorer or a command prompt, observe that C:\virtualPath contains contents only from c:\otherBackingPath. +* Try to modify the contents of one of the files from c:\otherBackingPath via the C:\virtualPath. For example, if you have a file C:\otherBackingPath\fileInOtherPath.txt, it will show in C:\virtualPath as C:\virtualPath\fileInOtherPath.txt. If you run the command `echo append to fileInOtherPath >> C:\virtualPath\fileInOtherPath.txt` the command will fail with an "access denied" error. +* The original file in C:\otherBackingPath\fileInOtherPath.txt retains its original security attributes. If you update the file via its path in otherBackingPath, the changes will be reflect in the path C:\virtualPath\fileInOtherPath.txt + +### Notes + +**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 Version 22H2 public preview 25330.1000 using Visual Studio 2022 and using the Preview Windows SDK 10.0.25330.0. +Please provide feedback on this sample! + +Build this sample to get the executable BindLink.exe. + +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 + +[**Bind Link API**]() + +## Operating system requirements + +Windows 11 Version 22H2 Build 25330 or higher + +## Build the sample + +Open the solution (*.sln*) file titled *BindLink.sln* from Visual Studio. + +Choose a configuration that matches your system. This will probably be x64. + +Go to **Build** \> **Build Solution** to build the sample. + +**Warning** This sample requires the Windows SDK 10.0.25314.0 or higher. + +## Run the sample +1. After building the sample, locate the path of the executable BindLink.exe from the Output. +2. Open an admin command prompt. +3. Either change your current directory to the directory that contains BindLink.exe or run the executable as "PathToBindLink\BindLink.exe ...", using the command line options suggested above. + +**NOTE**: When you are finished, don't forget to run BindLink.exe REMOVE to remove all bind links that you created. diff --git a/Samples/BindLink/packages.config b/Samples/BindLink/packages.config new file mode 100644 index 00000000..26065b14 --- /dev/null +++ b/Samples/BindLink/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Samples/CimFSAPI/app.cpp b/Samples/CimFSAPI/app.cpp index 858feca1..1abef6f9 100644 --- a/Samples/CimFSAPI/app.cpp +++ b/Samples/CimFSAPI/app.cpp @@ -22,10 +22,14 @@ Topics to cover: #include #include #include +#include #include #include +#include #include +#define BUFFERSIZE 65536 //64 KB + // Keep information of a file's alternate streams struct StreamData { @@ -808,6 +812,64 @@ TogglePrivilege(std::wstring_view privilegeName, bool enable) return previouslyEnabled; } +bool +ReadFileFromCim(_In_ const std::wstring& imagePath, + _In_ const std::wstring& filePath, + _In_ const int offset) +// Routine Description: +// Reads a file from the provided CIM image and writes it to STDOUT. +// +// Parameters: +// imagePath - Path to a CIM image. +// +// filePath - Relative path of the file from the root in the CIM Image. +// +// offset - offset at which to start reading the file +// +{ + // Get the file size + FILE_STAT_BASIC_INFORMATION statInfo{}; + THROW_IF_FAILED(CimGetFileStatBasicInformation(imagePath.c_str(), + filePath.c_str(), + &statInfo)); + uint64_t filesize = statInfo.EndOfFile.QuadPart; + uint64_t length = filesize - offset; + uint64_t readoffset = offset; + + std::wcout << "The content of the file in the CIM are as follows: " << std::endl; + + while (length > 0) + { + std::byte buffer[BUFFERSIZE]; + uint64_t readbytes = 0; + uint64_t remainingbytes = 0; + THROW_IF_FAILED(CimReadFile(imagePath.c_str(), + filePath.c_str(), + readoffset, + &buffer, + BUFFERSIZE, + &readbytes, + &remainingbytes)); + + if(readbytes == 0) + { + std::wcerr << "Unable to read file" << std::endl; + break; + } + + DWORD dummy; + THROW_IF_WIN32_BOOL_FALSE(WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), + buffer, + wil::safe_cast(readbytes), + &dummy, + nullptr)); + readoffset += readbytes; + length = remainingbytes; + } + + return true; +} + int __cdecl wmain(int argc, const wchar_t** argv) try { if (argc != 5) @@ -827,6 +889,9 @@ int __cdecl wmain(int argc, const wchar_t** argv) try CompareFileWithCimFile(cimPath, imageName, imageRelativePath, filePath); + std::wstring imagepath = cimPath + L"\\" + imageName; + ReadFileFromCim(imagepath, imageRelativePath, 0); + auto attributes = GetFileAttributes(filePath.c_str()); std::wstring imageHardLinkPath(L"link"); diff --git a/Samples/ConnectionManagerCost/README.md b/Samples/ConnectionManagerCost/README.md index 33f8ead5..d0a56b2d 100644 --- a/Samples/ConnectionManagerCost/README.md +++ b/Samples/ConnectionManagerCost/README.md @@ -4,18 +4,24 @@ languages: - cpp products: - windows-api-win32 -name: Windows Connection Manager WLAN cost sample +name: Windows Connection Manager cost sample urlFragment: connection-manager-wlan-cost -description: The sample demonstrates how to set and get cost for WLAN profiles using Windows Connection Manager (WCM) Cost APIs. +description: The sample demonstrates how to set and get cost for WLAN profiles using Windows Connection Manager (WCM) cost APIs. +extendedZipContent: +- path: LICENSE + target: LICENSE --- -# Windows Connection Manager WLAN cost sample +# Windows Connection Manager cost sample -The sample demonstrates how to set and get cost for WLAN profiles using Windows Connection Manager (WCM) Cost APIs. +The sample demonstrates how to set and get cost for WLAN profiles using Windows Connection Manager (WCM) cost APIs. -**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU) and doesn't compile in Microsoft Visual Studio Express 2013 for Windows. +The APIs demonstrated in this sample are: -**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! +1. WcmSetProperty - to set cost or data plan status for a profile. +2. WcmQueryProperty - to query cost or data plan status info for a profile. + +**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. To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). @@ -23,21 +29,11 @@ To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.micros ## Related topics -[Windows Connection Manager](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437650) - -## Related technologies - -[Windows Connection Manager](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437650) - -## Operating system requirements - -Client - -Windows 8.1 +[Windows Connection Manager](https://learn.microsoft.com/en-us/windows/win32/wcm/windows-connection-manager-portal) -Server +## System requirements -Windows Server 2012 R2 +- Requires Windows SDK 10.0.22621.0 to build and Windows 8 to run. ## Build the sample diff --git a/Samples/ConnectionManagerCost/Readme.txt b/Samples/ConnectionManagerCost/Readme.txt deleted file mode 100644 index c31b3af3..00000000 --- a/Samples/ConnectionManagerCost/Readme.txt +++ /dev/null @@ -1,39 +0,0 @@ -WCM Cost Sample -================================ -The sample demonstrates how to set and get cost for WLAN profiles using WCM -cost APIs. - -The APIs demonstrated in this sample are: -1.WcmSetProperty - to set cost or dataplan status for a profile. -2.WcmQueryProperty - to query cost or dataplan status info for a profile. - -Sample Language Implementations -=============================== - This sample is available in the following language implementations: -C++ - -Files: -============================================= -Wcmcostsample.cpp - This file includes the functions to demonstrate how to use Wcm Set/Query - APIs to get cost and dataplan status. - -Utils.cpp - This file contains the utility functions required for the WcmCostSample SDK. - -To build the sample using the command prompt: -============================================= - 1. Open the Command Prompt window and navigate to the directory containing the sample for a specific language. - 2. Type "msbuild wcmcostsample". - - -To build the sample using Visual Studio (preferred method): -=========================================================== - 1. Open File Explorer and navigate to the directory containing the sample for CPP language. - 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: -================= - 1. Navigate to the directory that contains the new executable, using the command prompt or File Explorer. - 2. Type wcmcostsample at the command line, or double-click the icon for wcmcostsample to launch it from File Explorer. diff --git a/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln b/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln index 52d3b9cf..2829f30b 100644 --- a/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln +++ b/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln @@ -1,18 +1,32 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 11 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34302.85 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WcmCostSample", "WcmCostSample.vcxproj", "{C11BA656-32FE-4BE3-A3D8-943E832FFDB3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + 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 - {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|Win32.ActiveCfg = Debug|Win32 - {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|Win32.Build.0 = Debug|Win32 - {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|Win32.ActiveCfg = Release|Win32 - {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|Win32.Build.0 = Release|Win32 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|ARM64.Build.0 = Debug|ARM64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|x64.ActiveCfg = Debug|x64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|x64.Build.0 = Debug|x64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|x86.ActiveCfg = Debug|Win32 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Debug|x86.Build.0 = Debug|Win32 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|ARM64.ActiveCfg = Release|ARM64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|ARM64.Build.0 = Release|ARM64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|x64.ActiveCfg = Release|x64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|x64.Build.0 = Release|x64 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|x86.ActiveCfg = Release|Win32 + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj b/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj index 13ab969b..5cbdf094 100644 --- a/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj +++ b/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj @@ -1,14 +1,30 @@ + + Debug + ARM64 + Debug Win32 + + Debug + x64 + + + Release + ARM64 + Release Win32 + + Release + x64 + $(VCTargetsPath11) @@ -17,18 +33,45 @@ {C11BA656-32FE-4BE3-A3D8-943E832FFDB3} Win32Proj WcmCostSample + 10.0.22621.0 Application true - v110 + v143 + Unicode + + + Application + true + v143 + Unicode + + + Application + true + v143 Unicode Application false - v110 + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + Application + false + v143 true Unicode @@ -38,16 +81,40 @@ + + + + + + + + + + + + true + + true + + + true + false + + false + + + false + NotUsing @@ -63,6 +130,40 @@ wcmapi.lib;rpcrt4.lib;wlanapi.lib;%(AdditionalDependencies) + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + wcmapi.lib;rpcrt4.lib;wlanapi.lib;%(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + wcmapi.lib;rpcrt4.lib;wlanapi.lib;%(AdditionalDependencies) + + Level3 @@ -82,6 +183,48 @@ wcmapi.lib;rpcrt4.lib;wlanapi.lib;%(AdditionalDependencies) + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + true + true + wcmapi.lib;rpcrt4.lib;wlanapi.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + true + true + wcmapi.lib;rpcrt4.lib;wlanapi.lib;%(AdditionalDependencies) + + diff --git a/Samples/CredentialProvider/README.md b/Samples/CredentialProvider/README.md index 8aeabdb2..7fa6bdd6 100644 --- a/Samples/CredentialProvider/README.md +++ b/Samples/CredentialProvider/README.md @@ -11,11 +11,25 @@ description: Demonstrates how to build a v2 credential provider that makes use o # V2 Credential Provider Sample -Demonstrates how to build a v2 credential provider that makes use of the new capabilities introduced to credential provider framework in Windows 8 and Windows 8.1. - -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). +This sample implements a simple v2 credential provider. A credential provider allows a 3rd +party to provide an alternate way of logging on. For example, a fingerprint solution vendor +would write a credential provider to interact with the user and send the appropriate +credentials to the system for authentication. + +This sample implements a simplified credential provider that is based on the password +credential provider that ships with Windows. When run, the credential provider +should enumerate two tiles, one for the administrator and one for the guest account. Note +that the guest account must be enabled for that tile to log on successfully. (The guest account +is disabled by default.) + +This sample demonstrates simple password based log on and unlock behavior. It also shows how to construct +a simple user tile and handle the user interaction with that tile. + +Note that this sample does not demonstrate the following: +- other credential provider scenarios, like participating in credui or handling change password. +- every possible field that you can put in your user tile +- any network access prior to local authentication (the Pre-Logon Access Provider (PLAP) behavior) +- an event based credential provider (like a smartcard or fingerprint based system) ## Operating system requirements @@ -35,4 +49,7 @@ Windows Server 2012 R2 ## 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**. +Copy SampleV2CredentialProvider.dll to the System32 directory +and run Register.reg from an elevated command prompt. The credential should appear the next +time a logon is invoked (such as when logging off or rebooting the machine). + diff --git a/Samples/LocationAwarenessEvents/README.md b/Samples/LocationAwarenessEvents/README.md index 26855923..1e6414b2 100644 --- a/Samples/LocationAwarenessEvents/README.md +++ b/Samples/LocationAwarenessEvents/README.md @@ -1,38 +1,39 @@ -Handling Location API events sample -=================================== +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: Handling Location API events sample +urlFragment: location-api-events +description: The sample demonstrates the use of the Location API to handle location awareness events. +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# Handling Location API events sample The sample demonstrates the use of the Location API to handle location awareness events. -**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! +**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. 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 +## System requirements -Server +- Requires Windows SDK 10.0.22621.0 to build and Windows 8.1 to run. -Windows Server 2012 R2 +## Build the sample -Build the sample ----------------- +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. -1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file titled LocationEvents.sln. -2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file titled LocationEvents.sln. +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. -3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. - -Run 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**. - diff --git a/Samples/LocationAwarenessEvents/cpp/LocationEvents.sln b/Samples/LocationAwarenessEvents/cpp/LocationEvents.sln index 600baa01..4fddb68f 100644 --- a/Samples/LocationAwarenessEvents/cpp/LocationEvents.sln +++ b/Samples/LocationAwarenessEvents/cpp/LocationEvents.sln @@ -1,22 +1,33 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 11 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34302.85 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocationEvents", "LocationEvents.vcxproj", "{7935C037-49C8-54F3-58A3-8C30E15B8D2F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|Win32.ActiveCfg = Debug|Win32 - {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|Win32.Build.0 = Debug|Win32 - {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|Win32.Deploy.0 = Debug|Win32 - {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|Win32.ActiveCfg = Release|Win32 - {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|Win32.Build.0 = Release|Win32 - {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|Win32.Deploy.0 = Release|Win32 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|x64.ActiveCfg = Debug|x64 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|x64.Build.0 = Debug|x64 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|x86.ActiveCfg = Debug|Win32 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|x86.Build.0 = Debug|Win32 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Debug|x86.Deploy.0 = Debug|Win32 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|x64.ActiveCfg = Release|x64 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|x64.Build.0 = Release|x64 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|x86.ActiveCfg = Release|Win32 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|x86.Build.0 = Release|Win32 + {7935C037-49C8-54F3-58A3-8C30E15B8D2F}.Release|x86.Deploy.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E1F2040C-08A9-4110-9A47-539BD698A316} + EndGlobalSection EndGlobal diff --git a/Samples/LocationAwarenessEvents/cpp/LocationEvents.vcxproj b/Samples/LocationAwarenessEvents/cpp/LocationEvents.vcxproj index fabb1271..f7709f27 100644 --- a/Samples/LocationAwarenessEvents/cpp/LocationEvents.vcxproj +++ b/Samples/LocationAwarenessEvents/cpp/LocationEvents.vcxproj @@ -1,14 +1,30 @@  + + Debug + ARM64 + Debug Win32 + + Debug + x64 + + + Release + ARM64 + Release Win32 + + Release + x64 + $(VCTargetsPath11) @@ -16,18 +32,46 @@ Win32Proj LocationEvents + {7935C037-49C8-54F3-58A3-8C30E15B8D2F} + 10.0.22621.0 Application true - v110 + v143 + Unicode + + + Application + true + v143 + Unicode + + + Application + true + v143 Unicode Application false - v110 + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + Application + false + v143 true Unicode @@ -37,16 +81,40 @@ + + + + + + + + + + + + true + + true + + + true + false + + false + + + false + @@ -61,6 +129,34 @@ locationapi.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) + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + locationapi.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) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + locationapi.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) + + Level3 @@ -79,6 +175,42 @@ locationapi.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) + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + locationapi.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) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + locationapi.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) + + diff --git a/Samples/LocationSetDefault/README.md b/Samples/LocationSetDefault/README.md index 348e7b6e..76f351ef 100644 --- a/Samples/LocationSetDefault/README.md +++ b/Samples/LocationSetDefault/README.md @@ -1,38 +1,39 @@ -Setting the default location sample -=================================== +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: Setting the default location sample +urlFragment: location-set-default-location +description: Demonstrates how to set the default location using the Location API. +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# Setting the default location sample Demonstrates how to set the default location using the Location API. -**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! +**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. 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 +## System requirements -Server +- Requires Windows SDK 10.0.22621.0 to build and Windows 8.1 to run. -Windows Server 2012 R2 +## Build the sample -Build the sample ----------------- +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. -1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file titled SetLocation.sln. -2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file titled SetLocation.sln. +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. -3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. - -Run 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**. - diff --git a/Samples/LocationSetDefault/cpp/SetLocation.sln b/Samples/LocationSetDefault/cpp/SetLocation.sln index 3fa6981b..339b6ed7 100644 --- a/Samples/LocationSetDefault/cpp/SetLocation.sln +++ b/Samples/LocationSetDefault/cpp/SetLocation.sln @@ -1,22 +1,33 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 11 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34302.85 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetLocation", "SetLocation.vcxproj", "{BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|Win32.ActiveCfg = Debug|Win32 - {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|Win32.Build.0 = Debug|Win32 - {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|Win32.Deploy.0 = Debug|Win32 - {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|Win32.ActiveCfg = Release|Win32 - {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|Win32.Build.0 = Release|Win32 - {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|Win32.Deploy.0 = Release|Win32 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|x64.ActiveCfg = Debug|x64 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|x64.Build.0 = Debug|x64 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|x86.ActiveCfg = Debug|Win32 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|x86.Build.0 = Debug|Win32 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Debug|x86.Deploy.0 = Debug|Win32 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|x64.ActiveCfg = Release|x64 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|x64.Build.0 = Release|x64 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|x86.ActiveCfg = Release|Win32 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|x86.Build.0 = Release|Win32 + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E}.Release|x86.Deploy.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C02EEC87-CA49-4823-A697-88CB5692A5C2} + EndGlobalSection EndGlobal diff --git a/Samples/LocationSetDefault/cpp/SetLocation.vcxproj b/Samples/LocationSetDefault/cpp/SetLocation.vcxproj index 5935729a..a9b62be1 100644 --- a/Samples/LocationSetDefault/cpp/SetLocation.vcxproj +++ b/Samples/LocationSetDefault/cpp/SetLocation.vcxproj @@ -1,14 +1,30 @@  + + Debug + ARM64 + Debug Win32 + + Debug + x64 + + + Release + ARM64 + Release Win32 + + Release + x64 + $(VCTargetsPath11) @@ -16,18 +32,46 @@ Win32Proj SetLocation + {BB2FAA29-1F8F-1A31-E8F0-EF0D7A07762E} + 10.0.22621.0 Application true - v110 + v143 + Unicode + + + Application + true + v143 + Unicode + + + Application + true + v143 Unicode Application false - v110 + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + Application + false + v143 true Unicode @@ -37,16 +81,40 @@ + + + + + + + + + + + + true + + true + + + true + false + + false + + + false + @@ -61,6 +129,34 @@ locationapi.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) + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + locationapi.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) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + locationapi.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) + + Level3 @@ -79,6 +175,42 @@ locationapi.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) + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + locationapi.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) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + locationapi.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) + + diff --git a/Samples/LocationSynchronousAccess/README.md b/Samples/LocationSynchronousAccess/README.md index 6057a208..6bedad23 100644 --- a/Samples/LocationSynchronousAccess/README.md +++ b/Samples/LocationSynchronousAccess/README.md @@ -1,38 +1,39 @@ -Location platform synchronous access sample -=========================================== +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: Location platform synchronous access sample +urlFragment: location-synchronous-access +description: This sample demonstrates how to access the Location platform in a synchronous manner. +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# Location platform synchronous access sample This sample demonstrates how to access the Location platform in a synchronous manner. -**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! +**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. 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 +## System requirements -Server +- Requires Windows SDK 10.0.22621.0 to build and Windows 8.1 to run. -Windows Server 2012 R2 +## Build the sample -Build the sample ----------------- +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. -1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file titled SimpleLocation.sln. -2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file titled SimpleLocation.sln. +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. -3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. - -Run 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**. - diff --git a/Samples/LocationSynchronousAccess/cpp/SimpleLocation.sln b/Samples/LocationSynchronousAccess/cpp/SimpleLocation.sln index 54f82794..01ab0736 100644 --- a/Samples/LocationSynchronousAccess/cpp/SimpleLocation.sln +++ b/Samples/LocationSynchronousAccess/cpp/SimpleLocation.sln @@ -1,22 +1,33 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 11 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34302.85 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleLocation", "SimpleLocation.vcxproj", "{DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|Win32.ActiveCfg = Debug|Win32 - {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|Win32.Build.0 = Debug|Win32 - {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|Win32.Deploy.0 = Debug|Win32 - {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|Win32.ActiveCfg = Release|Win32 - {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|Win32.Build.0 = Release|Win32 - {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|Win32.Deploy.0 = Release|Win32 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|x64.ActiveCfg = Debug|x64 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|x64.Build.0 = Debug|x64 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|x86.ActiveCfg = Debug|Win32 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|x86.Build.0 = Debug|Win32 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Debug|x86.Deploy.0 = Debug|Win32 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|x64.ActiveCfg = Release|x64 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|x64.Build.0 = Release|x64 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|x86.ActiveCfg = Release|Win32 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|x86.Build.0 = Release|Win32 + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5}.Release|x86.Deploy.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {936EFB81-0471-4795-B625-092B2F169CA6} + EndGlobalSection EndGlobal diff --git a/Samples/LocationSynchronousAccess/cpp/SimpleLocation.vcxproj b/Samples/LocationSynchronousAccess/cpp/SimpleLocation.vcxproj index df71c83e..3de14731 100644 --- a/Samples/LocationSynchronousAccess/cpp/SimpleLocation.vcxproj +++ b/Samples/LocationSynchronousAccess/cpp/SimpleLocation.vcxproj @@ -1,14 +1,30 @@  + + Debug + ARM64 + Debug Win32 + + Debug + x64 + + + Release + ARM64 + Release Win32 + + Release + x64 + $(VCTargetsPath11) @@ -16,18 +32,46 @@ Win32Proj SimpleLocation + {DDDFF90D-E617-7FC0-C960-0DFBDD0AABE5} + 10.0.22621.0 Application true - v110 + v143 + Unicode + + + Application + true + v143 + Unicode + + + Application + true + v143 Unicode Application false - v110 + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + Application + false + v143 true Unicode @@ -37,16 +81,40 @@ + + + + + + + + + + + + true + + true + + + true + false + + false + + + false + @@ -61,6 +129,34 @@ locationapi.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) + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + locationapi.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) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + locationapi.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) + + Level3 @@ -79,6 +175,42 @@ locationapi.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) + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + locationapi.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) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + locationapi.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) + + diff --git a/Samples/NetworkCost/README.md b/Samples/NetworkCost/README.md index e6dd080f..9c2fcc1c 100644 --- a/Samples/NetworkCost/README.md +++ b/Samples/NetworkCost/README.md @@ -1,52 +1,65 @@ -DUSM network cost sample -======================== +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: DUSM network cost sample +description: The network cost sample demonstrates the features of Data Usage and Subscription Management (DUSM). +extendedZipContent: +- path: LICENSE + target: LICENSE +--- -The network cost sample allows the application developer to play with the features of the DUSM (Data Usage and Subscription Management).This sample allows the user to get local machine cost, destination cost and connection cost. The user can register for cost change notifications for machine cost, destination cost and connection cost and receive the new cost when there is a cost change event. +# DUSM network cost sample -**Note** While the DUSM feature allows the user to register for cost change notifications for multiple destination addresses, this sample restricts registration for cost change notifications to a single destination address at a time for the sake of simplicity. +The network cost sample demonstrates the features of Data Usage and Subscription Management (DUSM). +This sample allows the user to get local machine cost, destination cost and connection cost. The user can register for cost change +notifications for machine cost, destination cost and connection cost and receive the new cost when there is a cost change event. -**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU) and will not compile in Microsoft Visual Studio Express 2013 for Windows. +These are few points to note about this sample app: -**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! +1. The DUSM feature API allows the user to register for cost change notifications for multiple destination addresses, using +SetDestinationAddresses; although the NetCostSample SDK restricts the user to register for cost change notifications for single +destination address at a time. This is done to make the sample SDK simple. -To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). +2. When the user registers for cost change notifications, since the events are out-of-band this sample, the events have to be generated +by doing one of the following: -To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + - Connect or disconnect Ethernet + - Switch between mobile broadband and Wi-Fi + - Change cost for mobile broadband using WCM Sample SDK which defines the use of set cost feature for WCM API. + +3. While the DUSM feature allows the user to register for cost change notifications for multiple destination addresses, this sample restricts registration for cost change notifications to a single destination address at a time for the sake of simplicity. -Related topics --------------- +**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. -[**INetworkCostManager**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh448257) +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). -[**INetworkConnectionCostEvents**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh448252) +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). -Related technologies --------------------- +## Related topics -[Network List Manager](http://msdn.microsoft.com/en-us/library/windows/desktop/aa370803) +[**INetworkCostManager**](https://learn.microsoft.com/en-us/windows/win32/api/netlistmgr/nn-netlistmgr-inetworkcostmanager) -Operating system requirements ------------------------------ +[**INetworkConnectionCostEvents**](https://learn.microsoft.com/en-us/windows/win32/api/netlistmgr/nn-netlistmgr-inetworkconnectioncostevents) -Client +## Related technologies -Windows 8.1 +[Network List Manager](https://learn.microsoft.com/en-us/windows/win32/nla/portal) -Server +## System requirements -Windows Server 2012 R2 +- Requires Windows SDK 10.0.22621.0 to build and Windows 8.1 to run. -Build the sample ----------------- +## Build the sample -1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. -2. 2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file. +2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file. -3. Press F6 or use **Build** \> **Build Solution** to build the sample. +3. Press F6 or use **Build** \> **Build Solution** to build the sample. -Run 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**. - diff --git a/Samples/NetworkCost/Readme.txt b/Samples/NetworkCost/Readme.txt deleted file mode 100644 index fcf19f5b..00000000 --- a/Samples/NetworkCost/Readme.txt +++ /dev/null @@ -1,65 +0,0 @@ -Network Cost Sample -================================ -The SDK Sample NetCostSample, allows the application developer to play with -the features of the DUSM (Data Usage and Subscription Management). The sample -allows the user to get Machine cost, destination cost and connection cost. -Additionally, the user can register for cost change notifications for -machine cost, destination cost and connection cost and receive the new cost -when there is a cost change event. - -Sample Language Implementations -=============================== - This sample is available in the following language implementations: -C++ - -Files: -============================================= -NetCostEventSink.cpp - This file implements the cost event sink for cost change notifications, and -includes callback functions to display new cost and profile data values when -there is a cost change notification. - -NetCostSample.cpp - This file displays the user choice menu, to play with the Sample SDK. This -file contains the entry point for the sample SDK, and based on user choice, -the respective functions are executed. It also displays a list of suggested -actions for the application developer based on the cost value retrieved. - -Utils.cpp - This file contains the utility functions required for the NetCostSample SDK. - -To build the sample using the command prompt: -============================================= - 1. Open the Command Prompt window and navigate to the directory containing the sample for a specific language. - 2. Type "msbuild netcostsample". - - -To build the sample using Visual Studio (preferred method): -=========================================================== - 1. Open File Explorer and navigate to the directory containing the sample for CPP language. - 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: -================= - 1. Navigate to the directory that contains the new executable, using the command prompt or File Explorer. - 2. Type netcostsample at the command line, or double-click the icon for netcostsample to launch it from File Explorer. - -Comments -These are few points to be noted, about this sample SDK. -1. The DUSM feature API allows the user to register for cost change -notifications for multiple destination addresses, using -SetDestinationAddresses; although the NetCostSample SDK restricts the user to -register for cost change notifications for single destination address at a -time. This is done to make the sample SDK simple. - -2. When the user registers for cost change notifications, since the events -are out-of-band this sample, the events have to be generated by doing one of -the following: - - • Connect or disconnect Ethernet - • Switch between mobile broadband and wifi - • Change cost for mobile broadband using WCM Sample SDK which defines the use -of set cost feature for WCM API. - - diff --git a/Samples/NetworkCost/cpp/NetCostSample.sln b/Samples/NetworkCost/cpp/NetCostSample.sln index 6dcba0bc..bd54a040 100644 --- a/Samples/NetworkCost/cpp/NetCostSample.sln +++ b/Samples/NetworkCost/cpp/NetCostSample.sln @@ -1,18 +1,32 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 11 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34302.85 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetCostSample", "NetCostSample.vcxproj", "{C5BE0963-6F0E-4998-A726-D626509B7AA8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + 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 - {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|Win32.ActiveCfg = Debug|Win32 - {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|Win32.Build.0 = Debug|Win32 - {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|Win32.ActiveCfg = Release|Win32 - {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|Win32.Build.0 = Release|Win32 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|ARM64.Build.0 = Debug|ARM64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|x64.ActiveCfg = Debug|x64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|x64.Build.0 = Debug|x64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|x86.ActiveCfg = Debug|Win32 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Debug|x86.Build.0 = Debug|Win32 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|ARM64.ActiveCfg = Release|ARM64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|ARM64.Build.0 = Release|ARM64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|x64.ActiveCfg = Release|x64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|x64.Build.0 = Release|x64 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|x86.ActiveCfg = Release|Win32 + {C5BE0963-6F0E-4998-A726-D626509B7AA8}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/NetworkCost/cpp/NetCostSample.vcxproj b/Samples/NetworkCost/cpp/NetCostSample.vcxproj index 0fa84307..261390db 100644 --- a/Samples/NetworkCost/cpp/NetCostSample.vcxproj +++ b/Samples/NetworkCost/cpp/NetCostSample.vcxproj @@ -1,14 +1,30 @@ + + Debug + ARM64 + Debug Win32 + + Debug + x64 + + + Release + ARM64 + Release Win32 + + Release + x64 + $(VCTargetsPath11) @@ -17,18 +33,45 @@ {C5BE0963-6F0E-4998-A726-D626509B7AA8} Win32Proj NetCostSample + 10.0.22621.0 Application true - v110 + v143 + Unicode + + + Application + true + v143 + Unicode + + + Application + true + v143 Unicode Application false - v110 + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + Application + false + v143 true Unicode @@ -38,16 +81,40 @@ + + + + + + + + + + + + true + + true + + + true + false + + false + + + false + NotUsing @@ -63,6 +130,40 @@ Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies) + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies) + + Level3 @@ -82,6 +183,48 @@ Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies) + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + true + true + Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + + + Console + true + true + true + Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies) + + diff --git a/Samples/NetworkListManager/NetworkListManager.sln b/Samples/NetworkListManager/NetworkListManager.sln new file mode 100644 index 00000000..207fd61f --- /dev/null +++ b/Samples/NetworkListManager/NetworkListManager.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33516.290 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetworkListManager", "NetworkListManager.vcxproj", "{B6CEBFF2-9383-4657-8BB8-DB1944369B97}" +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 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Debug|ARM64.Build.0 = Debug|ARM64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Debug|x64.ActiveCfg = Debug|x64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Debug|x64.Build.0 = Debug|x64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Debug|x86.ActiveCfg = Debug|Win32 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Debug|x86.Build.0 = Debug|Win32 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Release|ARM64.ActiveCfg = Release|ARM64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Release|ARM64.Build.0 = Release|ARM64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Release|x64.ActiveCfg = Release|x64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Release|x64.Build.0 = Release|x64 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Release|x86.ActiveCfg = Release|Win32 + {B6CEBFF2-9383-4657-8BB8-DB1944369B97}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1C83441E-E596-4AD9-BD42-7EB7ACCE941F} + EndGlobalSection +EndGlobal diff --git a/Samples/NetworkListManager/NetworkListManager.vcxproj b/Samples/NetworkListManager/NetworkListManager.vcxproj new file mode 100644 index 00000000..19fcd791 --- /dev/null +++ b/Samples/NetworkListManager/NetworkListManager.vcxproj @@ -0,0 +1,122 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {b6cebff2-9383-4657-8bb8-db1944369b97} + NetworkListManager + + + + Application + v143 + Unicode + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level4 + true + _CONSOLE;%(PreprocessorDefinitions) + true + true + + + Console + true + $(CoreLibraryDependencies);%(AdditionalDependencies) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + true + true + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + + + + + + + + + + + + + + + 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}. + + + + \ No newline at end of file diff --git a/Samples/NetworkListManager/NetworkListManager.vcxproj.filters b/Samples/NetworkListManager/NetworkListManager.vcxproj.filters new file mode 100644 index 00000000..4d6c456e --- /dev/null +++ b/Samples/NetworkListManager/NetworkListManager.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + + \ No newline at end of file diff --git a/Samples/NetworkListManager/NetworkListManagerSample.cpp b/Samples/NetworkListManager/NetworkListManagerSample.cpp new file mode 100644 index 00000000..14f46f0e --- /dev/null +++ b/Samples/NetworkListManager/NetworkListManagerSample.cpp @@ -0,0 +1,208 @@ + // 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 "stdafx.h" + +#pragma region COM helpers +using unique_connectionpoint_token = wil::unique_com_token; + +unique_connectionpoint_token FindConnectionPointAndAdvise(REFIID itf, IUnknown* source, IUnknown* sink) +{ + wil::com_ptr container = wil::com_query(source); + wil::com_ptr connectionPoint; + THROW_IF_FAILED(container->FindConnectionPoint(itf, connectionPoint.put())); + + unique_connectionpoint_token token{ connectionPoint.get() }; + THROW_IF_FAILED(connectionPoint->Advise(sink, token.put())); + return token; +} + +// typename T is the connection point interface we are connecting to. +template +unique_connectionpoint_token FindConnectionPointAndAdvise(IUnknown* source, IUnknown* sink) +{ + return FindConnectionPointAndAdvise(__uuidof(T), source, sink); +} +#pragma endregion + +#pragma region QueryCurrentNetworkConnectivitySample + +void QueryCurrentNetworkConnectivitySample(bool optedIn) +{ + std::wcout << L"Querying current network connectivity." << std::endl; + if (optedIn) + { + std::wcout << L"User has opted into possible network usage charges." << std::endl; + } + else + { + std::wcout << L"User has not opted into possible network usage charges." << std::endl; + } + + const wil::com_ptr networkListManager = wil::CoCreateInstance(); + // Checks machine level connectivity via ipv4 or ipv6 or both. + NLM_CONNECTIVITY connectivity{ NLM_CONNECTIVITY_DISCONNECTED }; + THROW_IF_FAILED(networkListManager->GetConnectivity(&connectivity)); + + Utility::EvaluateAndReportConnectivity(optedIn, connectivity, networkListManager.get()); +} + +#pragma endregion + +#pragma region QueryCurrentNetworkCostSample + +void QueryCurrentNetworkCostSample() +{ + std::wcout << "Querying current network cost information." << std::endl; + + // Use INetworkCostManager to query machine-wide cost associated with + // a network connection used for machine-wide Internet connectivity. + const wil::com_ptr networkCostManager = wil::CoCreateInstance(); + + DWORD cost{ 0 }; + THROW_IF_FAILED(networkCostManager->GetCost(&cost, nullptr)); + const auto connectionCost = static_cast(cost); + + Utility::EvaluateAndReportConnectionCost(connectionCost); +} + +#pragma endregion + +#pragma region ListenToNetworkConnectivityChangesSample + +class NetworkConnectivityListener final + : public Microsoft::WRL::RuntimeClass, INetworkListManagerEvents> +{ +public: + NetworkConnectivityListener(bool optedIn, INetworkListManager* networkListManager) + : m_optedIn(optedIn), m_networkListManager(networkListManager) {} + + NetworkConnectivityListener(const NetworkConnectivityListener&) = delete; + NetworkConnectivityListener& operator=(const NetworkConnectivityListener&) = delete; + + IFACEMETHODIMP ConnectivityChanged(NLM_CONNECTIVITY connectivity) noexcept override try + { + std::wcout << L"INetworkListManagerEvents::ConnectivityChanged" << std::endl; + Utility::EvaluateAndReportConnectivity(m_optedIn, connectivity, m_networkListManager.get()); + return S_OK; + } + CATCH_RETURN(); + +private: + wil::com_ptr m_networkListManager; + bool m_optedIn; +}; + +void ListenToNetworkConnectivityChangesSample(bool optedIn) +{ + std::wcout << "Listening to network connectivity changes." << std::endl; + if (optedIn) + { + std::wcout << L"User has opted into possible network usage charges." << std::endl; + } + else + { + std::wcout << L"User has not opted into possible network usage charges." << std::endl; + } + + const wil::com_ptr networkListManager = wil::CoCreateInstance(); + + unique_connectionpoint_token token = FindConnectionPointAndAdvise( + networkListManager.get(), + Microsoft::WRL::Make(optedIn, networkListManager.get()).Get()); + + std::wcout << "Press Enter to stop." << std::endl; + static_cast(getchar()); +} + +#pragma endregion + +#pragma region ListenToNetworkCostChangesSample + +class NetworkCostListener final + : public Microsoft::WRL::RuntimeClass, INetworkCostManagerEvents> +{ +public: + NetworkCostListener(INetworkCostManager* networkCostManager) : m_networkCostManager(networkCostManager) {} + + NetworkCostListener(const NetworkCostListener&) = delete; + NetworkCostListener& operator=(const NetworkCostListener&) = delete; + + IFACEMETHODIMP CostChanged(DWORD cost, __RPC__in_opt NLM_SOCKADDR* /*pDestAddr*/) noexcept override try + { + const auto connectionCost = static_cast(cost); + std::wcout << L"INetworkCostManagerEvents::CostChanged" << std::endl; + + Utility::EvaluateAndReportConnectionCost(connectionCost); + + return S_OK; + } + CATCH_RETURN(); + + IFACEMETHODIMP DataPlanStatusChanged(__RPC__in_opt NLM_SOCKADDR* /*pDestAddr*/) noexcept override + { + // This event is not used by the sample. + return S_OK; + } + +private: + wil::com_ptr m_networkCostManager; +}; +void ListenToNetworkCostChangesSample() +{ + std::wcout << "Listening to network cost changes." << std::endl; + + const wil::com_ptr networkCostManager = wil::CoCreateInstance(); + + unique_connectionpoint_token token = FindConnectionPointAndAdvise( + networkCostManager.get(), + Microsoft::WRL::Make(networkCostManager.get()).Get()); + + std::wcout << "Press Enter to stop." << std::endl; + static_cast(getchar()); +} + +#pragma endregion + +int __cdecl wmain(int argc, wchar_t** argv) +try +{ + auto coinit = wil::CoInitializeEx_failfast(COINIT_MULTITHREADED); + int scenario = argc == 2 ? _wtoi(argv[1]) : 0; + switch (scenario) + { + case 1: + case 2: + QueryCurrentNetworkConnectivitySample(scenario == 2); + break; + + case 3: + QueryCurrentNetworkCostSample(); + break; + + case 4: + case 5: + ListenToNetworkConnectivityChangesSample(scenario == 5); + break; + + case 6: + ListenToNetworkCostChangesSample(); + break; + + default: + std::wcout << "NetworkListManager.exe sample demonstrates how to use network list manager APIs." << std::endl + << " [parameter]" << std::endl + << " 1: Query current network connectivity: User has not opted into possible network usage charges." << std::endl + << " 2: Query current network connectivity: User has opted into possible network usage charges." << std::endl + << " 3: Query current network cost information." << std::endl + << " 4: Listen to network connectivity changes: User has not opted into possible network usage charges." << std::endl + << " 5: Listen to network connectivity changes: User has opted into possible network usage charges." << std::endl + << " 6: Listen to network cost changes." << std::endl; + break; + } + return 0; +} +CATCH_RETURN(); diff --git a/Samples/NetworkListManager/README.md b/Samples/NetworkListManager/README.md new file mode 100644 index 00000000..2e250fa0 --- /dev/null +++ b/Samples/NetworkListManager/README.md @@ -0,0 +1,39 @@ +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: Network List Manager API sample +urlFragment: network-list-manager-api-sample +description: Demonstrates how to use Windows APIs to determine the network connectivity status, and shows how to use this information to determine when to attempt to connect to the Internet. +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# Network List Manager API sample + +Apps can use INetworkListManager APIs to check the network connectivity status before +attempting to connect to the Internet. This check is recommended as it saves apps the complex task +of determining connectivity for various network configurations on their own. However this check +is not required as higher-level APIs (HttpClient, etc.) provide network connectivity status +through failures/results at point of connection. + +This sample also demonstrates how to register for network connectivity change notifications. +Apps can listen to the notifications published by Windows instead of building their +own state machine to track network connectivity changes. + +## System requirements + +- Requires Windows SDK 10.0.22621.0 to build and Windows 8 to run. + +## Build the sample + +1. Open File 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. + +## Run the sample + +1. Press F5 in Visual Studio or later. diff --git a/Samples/NetworkListManager/Utility.cpp b/Samples/NetworkListManager/Utility.cpp new file mode 100644 index 00000000..836f42aa --- /dev/null +++ b/Samples/NetworkListManager/Utility.cpp @@ -0,0 +1,275 @@ +// 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 "stdafx.h" +#pragma comment(lib, "winhttp.lib") + +namespace Utility +{ + enum class CostGuidance + { + Normal, + OptIn, + Conservative + }; + + CostGuidance GetNetworkCostGuidance(NLM_CONNECTION_COST cost) + { + if (WI_IsAnyFlagSet(cost, NLM_CONNECTION_COST_ROAMING | NLM_CONNECTION_COST_OVERDATALIMIT)) + { + if (WI_IsFlagSet(cost, NLM_CONNECTION_COST_ROAMING)) + { + std::wcout << "Connection is roaming; using the connection may result in additional charge." << std::endl; + } + else + { + std::wcout << "Connection has exceeded the usage cap limit." << std::endl; + } + return CostGuidance::OptIn; + } + else if (WI_IsAnyFlagSet(cost, NLM_CONNECTION_COST_FIXED | NLM_CONNECTION_COST_VARIABLE)) + { + if (WI_IsFlagSet(cost, NLM_CONNECTION_COST_FIXED)) + { + std::wcout << "Connection has limited allowed usage." << std::endl; + } + else + { + std::wcout << "Connection is charged based on usage." << std::endl; + } + return CostGuidance::Conservative; + } + else + { + if (WI_IsFlagSet(cost, NLM_CONNECTION_COST_UNRESTRICTED)) + { + std::wcout << "Connection cost is unrestricted." << std::endl; + } + else + { + std::wcout << "Connection cost is unknown." << std::endl; + } + return CostGuidance::Normal; + } + } + + bool ShouldAttemptToConnectToInternet(NLM_CONNECTIVITY connectivity, INetworkListManager* networkListManager) + { + // check internet connectivity + if (WI_IsAnyFlagSet(connectivity, NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET)) + { + std::wcout << "Machine has internet connectivity." << std::endl; + return true; + } + else if (WI_IsAnyFlagSet(connectivity, NLM_CONNECTIVITY_IPV4_LOCALNETWORK | NLM_CONNECTIVITY_IPV6_LOCALNETWORK)) + { + // we are local connected, check if we're behind a captive portal before attempting to connect to the Internet. + // + // note: being behind a captive portal means connectivity is local and there is at least one interface(network) + // behind a captive portal. + + bool localConnectedBehindCaptivePortal = false; + wil::com_ptr enumConnectedNetworks; + THROW_IF_FAILED( + networkListManager->GetNetworks( + NLM_ENUM_NETWORK_CONNECTED, + enumConnectedNetworks.put())); + + // Enumeration returns S_FALSE when there are no more items. + wil::com_ptr networkConnection; + while (THROW_IF_FAILED(enumConnectedNetworks->Next(1, networkConnection.put(), nullptr)) == S_OK) + { + wil::com_ptr networkProperties = networkConnection.query(); + + // these might fail if there's no value + wil::unique_variant variantInternetConnectivityV4; + networkProperties->Read(NA_InternetConnectivityV4, variantInternetConnectivityV4.addressof(), nullptr); + wil::unique_variant variantInternetConnectivityV6; + networkProperties->Read(NA_InternetConnectivityV6, variantInternetConnectivityV6.addressof(), nullptr); + + // read the VT_UI4 from the VARIANT and cast it to a NLM_INTERNET_CONNECTIVITY + // If there is no value, then assume no special treatment. + NLM_INTERNET_CONNECTIVITY v4Connectivity = static_cast(variantInternetConnectivityV6.vt == VT_UI4 ? variantInternetConnectivityV4.ulVal : 0); + NLM_INTERNET_CONNECTIVITY v6Connectivity = static_cast(variantInternetConnectivityV6.vt == VT_UI4 ? variantInternetConnectivityV6.ulVal : 0); + + if (WI_IsFlagSet(v4Connectivity, NLM_INTERNET_CONNECTIVITY_WEBHIJACK) || WI_IsFlagSet(v6Connectivity, NLM_INTERNET_CONNECTIVITY_WEBHIJACK)) + { + // at least one connected interface is behind a captive portal + // we should assume that the device is behind it + localConnectedBehindCaptivePortal = true; + } + } + + if (!localConnectedBehindCaptivePortal) + { + std::wcout << "Machine has local connectivity and not behind a captive portal." << std::endl; + return true; + } + else + { + std::wcout << "Machine is behind a captive portal." << std::endl; + } + } + else + { + std::wcout << "Machine is not connected." << std::endl; + } + return false; + } + + void SendHttpGetRequest() + { + wil::unique_winhttp_hinternet session( + WinHttpOpen(L"NetworkListManagerSample.exe", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0)); + + if (!session) + { + std::wcout << "WinHttpOpen failed to get a session handle with error code " << GetLastError() << std::endl; + return; + } + + wil::unique_winhttp_hinternet connect(WinHttpConnect(session.get(), L"www.msftconnecttest.com", INTERNET_DEFAULT_HTTP_PORT, 0)); + if (!connect) + { + std::wcout << "WinHttpConnect failed to get a connect handle with error code " << GetLastError() << std::endl; + return; + } + + wil::unique_winhttp_hinternet request(WinHttpOpenRequest( + connect.get(), L"GET", L"/connecttest.txt", nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0)); + if (!request) + { + std::wcout << "WinHttpOpenRequest failed with error code " << GetLastError() << std::endl; + return; + } + + if (!WinHttpSendRequest(request.get(), WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) + { + std::wcout << "WinHttpSendRequest failed with error code " << GetLastError() << std::endl; + return; + } + + if (!WinHttpReceiveResponse(request.get(), nullptr)) + { + std::wcout << "WinHttpReceiveResponse failed with error code " << GetLastError() << std::endl; + return; + } + + DWORD statusCode{0}; + DWORD headerBytes = sizeof(statusCode); + if (WinHttpQueryHeaders(request.get(), WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &statusCode, &headerBytes, WINHTTP_NO_HEADER_INDEX)) + { + if (statusCode >= 200 && statusCode < 300) + { + std::wcout << "Http request succeeded with status code " << statusCode << std::endl; + + DWORD bytesRead{0}; + if (WinHttpQueryDataAvailable(request.get(), &bytesRead) && bytesRead > 0) + { + std::unique_ptr readBuffer = std::make_unique(bytesRead); + if (WinHttpReadData(request.get(), readBuffer.get(), bytesRead, &bytesRead)) + { + std::wcout << "Received " << bytesRead << " bytes in response." << std::endl; + return; + } + else + { + std::wcout << "WinHttpReadData failed with error code " << GetLastError() << std::endl; + return; + } + } + else + { + std::wcout << "WinHttpQueryDataAvailable failed with error code " << GetLastError() << std::endl; + return; + } + } + else + { + std::wcout << "Http request completed with status code " << statusCode << std::endl; + } + } + else + { + std::wcout << "WinHttpQueryHeaders failed with error code " << GetLastError() << std::endl; + } + } + + void EvaluateCostAndConnect(bool optedIn, INetworkListManager* networkListManager) + { + wil::com_ptr netCostManager = wil::com_query(networkListManager); + + DWORD cost{0}; + THROW_IF_FAILED(netCostManager->GetCost(&cost, nullptr)); + const auto nlmConnectionCost = static_cast(cost); + Utility::CostGuidance costGuidance = Utility::GetNetworkCostGuidance(nlmConnectionCost); + + switch (costGuidance) + { + case Utility::CostGuidance::OptIn: + { + std::cout << "Network access cost is significantly higher." << std::endl; + if (optedIn) + { + std::cout << "User has opted into network usage while roaming. Connecting." << std::endl; + SendHttpGetRequest(); + } + else + { + std::cout << "User has not opted into network usage while roaming. Not connecting." << std::endl; + } + break; + } + case Utility::CostGuidance::Conservative: + { + std::wcout << "Attempt connecting to the Internet for critical requests." << std::endl; + SendHttpGetRequest(); + break; + } + case Utility::CostGuidance::Normal: + default: + std::wcout << "Attempt connecting to the Internet." << std::endl; + SendHttpGetRequest(); + break; + } + } + + void EvaluateAndReportConnectivity(bool optedIn, NLM_CONNECTIVITY connectivity, INetworkListManager* networkListManager) + { + if (Utility::ShouldAttemptToConnectToInternet(connectivity, networkListManager)) + { + Utility::EvaluateCostAndConnect(optedIn, networkListManager); + } + else + { + std::wcout << "Not attempting to connect to the Internet." << std::endl; + } + } + + void EvaluateAndReportConnectionCost(NLM_CONNECTION_COST connectionCost) + { + const auto costGuidance = Utility::GetNetworkCostGuidance(connectionCost); + + switch (costGuidance) + { + case Utility::CostGuidance::OptIn: + // In opt-in scenarios, apps handle cases where the network access cost is significantly higher than the plan cost. + // For example, when a user is roaming, a mobile carrier may charge a higher rate data usage. + std::wcout << "Apps should implement opt-in behavior." << std::endl; + break; + case Utility::CostGuidance::Conservative: + // In conservative scenarios, apps implement restrictions for optimizing network usage to handle transfers over metered networks. + std::wcout << "Apps should implement conservative behavior." << std::endl; + break; + case Utility::CostGuidance::Normal: + default: + // In normal scenarios, apps do not implement restrictions. Apps treat the connection as unlimited in cost. + std::wcout << "Apps should implement normal behavior." << std::endl; + break; + } + } +} + diff --git a/Samples/NetworkListManager/Utility.h b/Samples/NetworkListManager/Utility.h new file mode 100644 index 00000000..02dcf583 --- /dev/null +++ b/Samples/NetworkListManager/Utility.h @@ -0,0 +1,12 @@ +// 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 +#pragma once +namespace Utility +{ + void EvaluateAndReportConnectivity(bool optedIn, NLM_CONNECTIVITY connectivity, INetworkListManager* networkListManager); + void EvaluateAndReportConnectionCost(NLM_CONNECTION_COST connectionCost); +} diff --git a/Samples/NetworkListManager/packages.config b/Samples/NetworkListManager/packages.config new file mode 100644 index 00000000..64523ba6 --- /dev/null +++ b/Samples/NetworkListManager/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Samples/NetworkListManager/stdafx.h b/Samples/NetworkListManager/stdafx.h new file mode 100644 index 00000000..dd46c06e --- /dev/null +++ b/Samples/NetworkListManager/stdafx.h @@ -0,0 +1,21 @@ +// 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 +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Utility.h" + diff --git a/Samples/PersonalDataEncryption/README.md b/Samples/PersonalDataEncryption/README.md new file mode 100644 index 00000000..0e648784 --- /dev/null +++ b/Samples/PersonalDataEncryption/README.md @@ -0,0 +1,68 @@ +--- +page_type: sample +languages: +- cpp +- cppwinrt +products: +- windows-api-win32 +name: Personal Data Encryption sample (Win32) +urlFragment: PersonalDataEncryption +description: "Demonstrates the usage of Personal Data Encryption (Windows Data Protection)." +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# Personal Data Encryption sample + +Shows how to use [Personal Data Encryption](https://learn.microsoft.com/windows/security/operating-system-security/data-protection/personal-data-encryption/) +for protecting user files and memory buffers. + +Personal Data Encryption can protect data either while a user is signed out ("Level 1" or "L1") or while a system is locked ("Level 2" or "L2"). + +The sample shows the following: + +- Marking a folder so that all new files are protected at a particular level, or removing protection. +- Protecting a file at a particular level, or removing protection. +- Protecting a memory buffer at a particular level, or removing protection. + +**Note** This sample requires Visual Studio to build and Windows 10 to execute. + +To obtain information about Windows development, go to the [Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421) + +To obtain information about Microsoft Visual Studio and the tools for developing Windows apps, go to [Visual Studio](http://go.microsoft.com/fwlink/?LinkID=532422) + +## Related topics + +### Reference + +[UserDataProtectionManager class](https://learn.microsoft.com/uwp/api/windows.security.dataprotection.userdataprotectionmanager) + +### Related samples + +* [Personal Data Encryption UWP sample](https://github.com/microsoft/Windows-universal-samples/tree/main/Samples/PersonalDataEncryption) + +## System requirements + +* Windows 10 Version 1903 (build 18362) or higher + +## Build the sample + +To build this sample: + +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it. + +### Deploying the sample + +- Select Build \> Deploy Solution. + +### Deploying and running the sample + +- Set the Debugging options to specify the desired command line options. +- To debug the sample and then run it, press F5 or select Debug \> Start Debugging. To run the sample without debugging, press Ctrl+F5 or select Debug \> Start Without Debugging. diff --git a/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.cpp b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.cpp new file mode 100644 index 00000000..ac8e9da7 --- /dev/null +++ b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include + +namespace winrt +{ + using namespace winrt::Windows::Foundation; + using namespace winrt::Windows::Security::DataProtection; + using namespace winrt::Windows::Storage; + using namespace winrt::Windows::Storage::Streams; +} + +void usage() +{ + std::wcout << LR"(PersonalDataEncryption sample usage. + +PersonalDataEncryption.exe file + + Protect a file to a protection level. + Path must be a fully-qualified path. + +PersonalDataEncryption.exe folder + + Protect a folder to a protection level. + Path must be a fully-qualified path. + +PersonalDataEncryption.exe memory + + Protect a memory buffer to a protection level. + +For both options, the following protection levels are supported: + + Level 0: No protection (always available). + Level 1: Available after first unlock. + Level 2: Avaialble when unlocked. + +Examples: + +Protect a file to level 1: + PersonalDataEncryption.exe file 1 C:\Users\Abby\Documents\file.txt + +Remove protection from a folder: + PersonalDataEncryption.exe folder 1 C:\Users\Abby\Documents\Party + +Protect a string to level 2: + PersonalDataEncryption.exe memory 2 "hello, world!" +)"; +} + +void ProtectItem(winrt::UserDataProtectionManager const& manager, winrt::UserDataAvailability availability, winrt::IStorageItem const& item) +{ + auto status = manager.ProtectStorageItemAsync(item, availability).get(); + wchar_t const* message; + switch (status) + { + case winrt::UserDataStorageItemProtectionStatus::Succeeded: + message = L"Succeeded"; + break; + + case winrt::UserDataStorageItemProtectionStatus::NotProtectable: + message = L"Not protectable"; + break; + + case winrt::UserDataStorageItemProtectionStatus::DataUnavailable: + message = L"Data unavailable"; + break; + + default: + message = L"Unknown failure"; + break; + } + + std::wcout << + L"Protecting " << std::wstring_view(item.Path()) << + L" to level " << static_cast(availability) << + L": " << message << L"\n"; +} + +void ProtectFile(winrt::UserDataProtectionManager const& manager, winrt::hstring const& path, winrt::UserDataAvailability availability) +{ + winrt::IStorageItem item; + try + { + item = winrt::StorageFile::GetFileFromPathAsync(path).get(); + } + catch (...) + { + std::wcout << L"Error getting StorageFile: " << std::wstring_view(winrt::to_message()) << L"\n"; + } + ProtectItem(manager, availability, item); +} + +// Note that setting the availability of a folder establishes the availability for any new items +// created in that folder, but it does not affect the availability of existing items in the folder. +// If you want to change the availability of an entire folder tree, you should first call +// ProtectStorageItemAsync to protect the folder (so that any new items are suitably protected), +// and then recursively protect all the files and subfolders inside that folder. +void ProtectFolder(winrt::UserDataProtectionManager const& manager, winrt::hstring const& path, winrt::UserDataAvailability availability) +{ + winrt::IStorageItem item; + try + { + item = winrt::StorageFolder::GetFolderFromPathAsync(path).get(); + } + catch (...) + { + std::wcout << L"Error getting StorageFile: " << std::wstring_view(winrt::to_message()) << L"\n"; + } + ProtectItem(manager, availability, item); +} + +void ProtectMemory(winrt::UserDataProtectionManager const& manager, winrt::hstring const& message, winrt::UserDataAvailability availability) +{ + // Convert the string to a Buffer. + auto bufferSize = message.size() * static_cast(sizeof(wchar_t)); + auto buffer = winrt::Buffer(bufferSize); + memcpy_s(buffer.data(), bufferSize, message.c_str(), bufferSize); + buffer.Length(bufferSize); + + // Protect the buffer. + auto protectedBuffer = manager.ProtectBufferAsync(buffer, availability).get(); + + // Zero out the original buffer to ensure it holds no data. + memset(buffer.data(), 0, bufferSize); + + // Free the original buffer and retain the protected buffer. + buffer = nullptr; + + std::wcout << L"Memory buffer has been protected.\n" + << L"Press Enter to unprotect it.\n"; + + std::cin.get(); + + // Now unprotect the buffer to recover the string. + auto result = manager.UnprotectBufferAsync(protectedBuffer).get(); + + winrt::UserDataBufferUnprotectStatus status = result.Status(); + winrt::IBuffer unprotectedBuffer = result.UnprotectedBuffer(); + + switch (status) + { + case winrt::UserDataBufferUnprotectStatus::Succeeded: + // Extract the string from the unprotected buffer. + std::wcout << L"Original message: " + << std::wstring_view(reinterpret_cast(unprotectedBuffer.data()), unprotectedBuffer.Length() / sizeof(wchar_t)) + << L"\n"; + break; + + case winrt::UserDataBufferUnprotectStatus::Unavailable: + std::wcout << L"Buffer cannot be unprotected at this time.\n"; + break; + + default: + std::wcout << L"Unexpected error when unprotecting buffer.\n"; + break; + } +} + +void Run(int argc, wchar_t** argv) +{ + if (argc != 4) + { + usage(); + return; + } + + wchar_t* end; + auto availability = static_cast(wcstoul(argv[2], &end, 10)); + if (*end != L'\0') + { + // Not an integer. + usage(); + return; + } + + if (availability != winrt::UserDataAvailability::Always && + availability != winrt::UserDataAvailability::AfterFirstUnlock && + availability != winrt::UserDataAvailability::WhileUnlocked) + { + // Not a valid integer. + usage(); + return; + } + + winrt::UserDataProtectionManager manager = winrt::UserDataProtectionManager::TryGetDefault(); + if (!manager) + { + std::wcout << L"Personal Data Encryption is not enabled.\n"; + return; + } + + if (wcscmp(argv[1], L"file") == 0) + { + ProtectFile(manager, argv[3], availability); + } + else if (wcscmp(argv[1], L"folder") == 0) + { + ProtectFolder(manager, argv[3], availability); + } + else if (wcscmp(argv[1], L"memory") == 0) + { + ProtectMemory(manager, argv[3], availability); + } + else + { + usage(); + } +} + +int wmain(int argc, wchar_t** argv) +{ + winrt::init_apartment(); + Run(argc, argv); + winrt::uninit_apartment(); + return 0; +} diff --git a/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.sln b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.sln new file mode 100644 index 00000000..7de500c2 --- /dev/null +++ b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PersonalDataEncryption", "PersonalDataEncryption.vcxproj", "{774485F3-27FC-4803-B090-70766D4837E1}" +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 + {774485F3-27FC-4803-B090-70766D4837E1}.Debug|x64.ActiveCfg = Debug|x64 + {774485F3-27FC-4803-B090-70766D4837E1}.Debug|x64.Build.0 = Debug|x64 + {774485F3-27FC-4803-B090-70766D4837E1}.Debug|x86.ActiveCfg = Debug|Win32 + {774485F3-27FC-4803-B090-70766D4837E1}.Debug|x86.Build.0 = Debug|Win32 + {774485F3-27FC-4803-B090-70766D4837E1}.Release|x64.ActiveCfg = Release|x64 + {774485F3-27FC-4803-B090-70766D4837E1}.Release|x64.Build.0 = Release|x64 + {774485F3-27FC-4803-B090-70766D4837E1}.Release|x86.ActiveCfg = Release|Win32 + {774485F3-27FC-4803-B090-70766D4837E1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AFB433FF-2A1F-4801-8D13-3CF71612ED30} + EndGlobalSection +EndGlobal diff --git a/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.vcxproj b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.vcxproj new file mode 100644 index 00000000..d9dd98f6 --- /dev/null +++ b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.vcxproj @@ -0,0 +1,137 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {774485f3-27fc-4803-b090-70766d4837e1} + PersonalDataEncryption + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.vcxproj.filters b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.vcxproj.filters new file mode 100644 index 00000000..7a2097c5 --- /dev/null +++ b/Samples/PersonalDataEncryption/cppwinrt/PersonalDataEncryption.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/Samples/PowerGrid/README.md b/Samples/PowerGrid/README.md new file mode 100644 index 00000000..05c57c4c --- /dev/null +++ b/Samples/PowerGrid/README.md @@ -0,0 +1,65 @@ +--- +page_type: sample +languages: +- cpp +- cppwinrt +products: +- windows-api-win32 +name: Power grid forecast sample +urlFragment: PowerGrid +description: "Shows how to use power grid forecasts (Win32)." +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +# Power grid forecast sample + +Shows how to use the PowerGrid Forecast API from Win32. + +This sample covers the following: +- Obtaining the power grid forecast +- Registering for ForecastUpdated notifications +- Looking for the lowest severity in a specified timeframe + +**Note** This sample requires Visual Studio to build and Windows 11 to execute. + +To obtain information about Windows development, go to the [Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421) + +To obtain information about Microsoft Visual Studio and the tools for developing Windows apps, go to [Visual Studio](http://go.microsoft.com/fwlink/?LinkID=532422) + +## Related topics + +### Reference + +[PowerGridForecast class](https://learn.microsoft.com/uwp/api/windows.devices.power.powergridforecast) + +### Related samples + +[Power grid forecast from a UWP app](https://github.com/microsoft/Windows-universal-samples/tree/main/Samples/PowerGrid) + +## System requirements + +- Windows 11 SDK (build 26100 or higher) +- Windows 11 (build 26100 or higher) + +## Build the sample + +To build this sample: + +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Microsoft Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it. + +### Deploying the sample + +- Select Build \> Deploy Solution. + +### Deploying and running the sample + +- To debug the sample and then run it, press F5 or select Debug \> Start Debugging. To run the sample without debugging, press Ctrl+F5 or select Debug \> Start Without Debugging. + diff --git a/Samples/PowerGrid/cppwinrt/PowerGrid.cpp b/Samples/PowerGrid/cppwinrt/PowerGrid.cpp new file mode 100644 index 00000000..f490ed6e --- /dev/null +++ b/Samples/PowerGrid/cppwinrt/PowerGrid.cpp @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace winrt +{ + using namespace winrt::Windows::Devices::Power; + using namespace winrt::Windows::Foundation; + using namespace winrt::Windows::Foundation::Collections; + using namespace winrt::Windows::Globalization::DateTimeFormatting; + using namespace winrt::Windows::Globalization::NumberFormatting; +} + +std::wstring FormatDateTime(winrt::DateTime dateTime) +{ + return std::wstring{ winrt::DateTimeFormatter(L"shortdate shorttime").Format(dateTime) }; +} + +std::wstring FormatSeverity(double severity) +{ + winrt::DecimalFormatter severityFormatter; + severityFormatter.FractionDigits(2); + severityFormatter.IntegerDigits(1); + severityFormatter.IsDecimalPointAlwaysDisplayed(true); + winrt::IncrementNumberRounder rounder; + rounder.Increment(0.01); + severityFormatter.NumberRounder(rounder); + return std::wstring{ severityFormatter.Format(severity) }; +} + +void ShowForecast() +{ + winrt::PowerGridForecast gridForecast = winrt::PowerGridForecast::GetForecast(); + + // If the API cannot obtain a forecast, the forecast is empty + winrt::IVectorView forecast = gridForecast.Forecast(); + if (forecast.Size() > 0) + { + // Print some forecast general information. + winrt::DateTime blockStartTime = gridForecast.StartTime(); + winrt::TimeSpan blockDuration = gridForecast.BlockDuration(); + + std::wcout << L"Forecast start time:" << FormatDateTime(blockStartTime) << L"\n"; + std::wcout << L"Forecast block duration (minutes):" << std::chrono::round(blockDuration).count() << L"\n"; + std::wcout << L"\n"; + + // Print each entry in the forecast. + for (winrt::PowerGridData const& data : forecast) + { + std::wcout << L"Date/Time: " << FormatDateTime(blockStartTime) << + L", Severity: " << FormatSeverity(data.Severity()) << + L", Is low user impact: " << (data.IsLowUserExperienceImpact() ? "Yes" : "No") << "\n"; + blockStartTime += blockDuration; + } + } + else + { + std::wcout << L"No forecast available. Try again later.\n"; + } + std::wcout << L"\n"; +} + + +// Calculate the index of the forecast entry that contains the requested time. +// If the time is before the start of the forecast, then returns 0. +// If the time is past the end of the forecast, then returns the number of forecasts. +int GetForecastIndexContainingTime(winrt::PowerGridForecast const& gridForecast, winrt::DateTime time) +{ + winrt::TimeSpan blockDuration = gridForecast.BlockDuration(); + + // Avoid division by zero. + if (blockDuration.count() == 0) + { + return 0; + } + + auto startBlock = static_cast((time - gridForecast.StartTime()) / blockDuration); + return std::clamp(startBlock, 0, static_cast(gridForecast.Forecast().Size())); +} + +void FindBest(winrt::TimeSpan lookAhead, bool restrictToLowUXImpact) +{ + winrt::PowerGridForecast gridForecast = winrt::PowerGridForecast::GetForecast(); + + // Find the first and last blocks that include the time range we are + // interested in. + winrt::DateTime startTime = winrt::clock::now(); + winrt::DateTime endTime = startTime + lookAhead; + + int startBlock = GetForecastIndexContainingTime(gridForecast, startTime); + int endBlock = GetForecastIndexContainingTime(gridForecast, endTime + gridForecast.BlockDuration()); + + double lowestSeverity = (std::numeric_limits::max)(); + winrt::DateTime timeWithLowestSeverity = (winrt::DateTime::max)(); + + for (int index = startBlock; index < endBlock; ++index) + { + winrt::PowerGridData data = gridForecast.Forecast().GetAt(index); + + // If we are restricting to low impact, then use only low impact time periods. + if (restrictToLowUXImpact && !data.IsLowUserExperienceImpact()) + { + continue; + } + + // If the severity is not an improvement, then don't use this one. + double severity = data.Severity(); + if (severity >= lowestSeverity) + { + continue; + } + + lowestSeverity = severity; + timeWithLowestSeverity = gridForecast.StartTime() + index * gridForecast.BlockDuration(); + } + + // Print the results. + if (lowestSeverity <= 1.0) + { + std::wcout << + FormatDateTime(timeWithLowestSeverity) << + L" to " << + FormatDateTime(timeWithLowestSeverity + gridForecast.BlockDuration()) << + L" (severity = " << + FormatSeverity(lowestSeverity) << + L")\n"; + } + else + { + std::wcout << L"Unable to find a good time to do work\n"; + } + std::wcout << L"\n"; +} + +void PerformForecastCalculations() +{ + // Show the entire forecast. + ShowForecast(); + + // Arbitrarily look ahead 10 hours with low user impact. + std::wcout << L"Best time to do work in the next 10 hours with low user experience impact:\n"; + FindBest(std::chrono::hours(10), true); + + // Arbitrarily look ahead 10 hours with no regard for low user impact. + std::wcout << L"Best time to do work in the next 10 hours without regard for user experience impact:\n"; + FindBest(std::chrono::hours(10), false); +} + +int wmain(int /* argc */, wchar_t** /* argv */) +{ + winrt::init_apartment(); + + // Do calculations immediately. + PerformForecastCalculations(); + + // If the forecast changes, then do the calculations again. + auto token = winrt::PowerGridForecast::ForecastUpdated([](auto&&, auto&&) + { + PerformForecastCalculations(); + }); + + + // Wait until the user presses a key to exit. + std::wcout << L"Waiting for the forecast to change...\n"; + std::wcout << L"Press Enter to exit the program.\n"; + std::cin.get(); + + // Clean up. + winrt::PowerGridForecast::ForecastUpdated(token); // unsubscribe from event + winrt::uninit_apartment(); + + + return 0; +} diff --git a/Samples/PowerGrid/cppwinrt/PowerGrid.sln b/Samples/PowerGrid/cppwinrt/PowerGrid.sln new file mode 100644 index 00000000..2e194368 --- /dev/null +++ b/Samples/PowerGrid/cppwinrt/PowerGrid.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerGrid", "PowerGrid.vcxproj", "{0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}" +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 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Debug|x64.ActiveCfg = Debug|x64 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Debug|x64.Build.0 = Debug|x64 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Debug|x86.ActiveCfg = Debug|Win32 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Debug|x86.Build.0 = Debug|Win32 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Release|x64.ActiveCfg = Release|x64 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Release|x64.Build.0 = Release|x64 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Release|x86.ActiveCfg = Release|Win32 + {0BF9B8CE-A5E3-4856-85AA-A43A0D86521D}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CEBD919A-BDE7-490D-9917-7BAC82C35BB5} + EndGlobalSection +EndGlobal diff --git a/Samples/PowerGrid/cppwinrt/PowerGrid.vcxproj b/Samples/PowerGrid/cppwinrt/PowerGrid.vcxproj new file mode 100644 index 00000000..8cd84ca8 --- /dev/null +++ b/Samples/PowerGrid/cppwinrt/PowerGrid.vcxproj @@ -0,0 +1,137 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {0bf9b8ce-a5e3-4856-85aa-a43a0d86521d} + PowerGrid + 10.0.26100.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Samples/PowerGrid/cppwinrt/PowerGrid.vcxproj.filters b/Samples/PowerGrid/cppwinrt/PowerGrid.vcxproj.filters new file mode 100644 index 00000000..b0f630aa --- /dev/null +++ b/Samples/PowerGrid/cppwinrt/PowerGrid.vcxproj.filters @@ -0,0 +1,18 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/Samples/PowerSettingRegisterNotification/README.md b/Samples/PowerSettingRegisterNotification/README.md new file mode 100644 index 00000000..a8539406 --- /dev/null +++ b/Samples/PowerSettingRegisterNotification/README.md @@ -0,0 +1,46 @@ +--- +page_type: sample +languages: +- cpp +products: +- windows-api-win32 +name: Power setting notification sample +urlFragment: PowerSettingRegisterNotification +description: "Shows how to register for changes in energy saver status." +extendedZipContent: +- path: LICENSE + target: LICENSE +--- + +Power Setting Register Notification (`GUID_ENERGY_SAVER_STATUS`) sample +======================================== + +This sample shows how to use the Power Setting Register Notification API (PowerSettingRegisterNotification) to listen to the `GUID_ENERGY_SAVER_STATUS` setting in particular. + +This app demonstrates the following +- Registering for the `GUID_ENERGY_SAVER_STATUS` power setting notification. + +**Note** This sample requires Microsoft Visual Studio to build and Windows 11 to execute. + +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 +----------------------------- + +- Windows 11 SDK (build 26100 or higher) +- Windows 11 (build 26100 or higher) + +Build the sample +---------------- + +Open Windows Explorer and navigate to the directory containing the sample. Double-click the icon for the .sln (solution) file to open the file in Visual Studio. In the Build menu, select Build Solution. The application will be built in the default \\Debug or \\Release directory. + +Run the sample +-------------- + +Navigate to the directory that contains the new executable, using the command prompt. Type "PowerSettingRegisterNotificationSample.exe" at the command line. +The program will register for the `GUID_ENERGY_SAVER_STATUS` notification listen for the notification to be triggered. To trigger an energy saver notification, +toggle energy saver either on the Quick Actions menu or opening Settings > Power & Battery and toggling the energy saver setting there. + diff --git a/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotification.vcxproj b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotification.vcxproj new file mode 100644 index 00000000..f171df48 --- /dev/null +++ b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotification.vcxproj @@ -0,0 +1,99 @@ + + + + true + true + true + true + 15.0 + {cfd0029e-5b15-4c2d-8cbb-34de5ec797a1} + Win32Proj + PowerSettingRegisterNotification + 10.0.26100.0 + 10.0.26027.0 + PowerSettingRegisterNotificationSample + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + Application + v143 + v142 + v141 + v140 + Unicode + + + true + true + + + false + true + false + + + + + + + + + + NotUsing + pch.h + $(IntDir)pch.pch + _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) + Level4 + %(AdditionalOptions) /permissive- /bigobj + + + Console + false + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + + + + + WIN32;%(PreprocessorDefinitions) + + + + + MaxSpeed + true + true + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + + \ No newline at end of file diff --git a/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotification.vcxproj.filters b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotification.vcxproj.filters new file mode 100644 index 00000000..d29806c3 --- /dev/null +++ b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotification.vcxproj.filters @@ -0,0 +1,12 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + \ No newline at end of file diff --git a/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotificationSample.cpp b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotificationSample.cpp new file mode 100644 index 00000000..4cf55e23 --- /dev/null +++ b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotificationSample.cpp @@ -0,0 +1,144 @@ +#include "initguid.h" +#include "Windows.h" +#include "winnt.h" +#include "powrprof.h" +#include "powersetting.h" +#include "stdio.h" +#include "iostream" + +#pragma comment(lib, "powrprof.lib") + +ULONG CALLBACK EnergySaverPowerSettingCallback( + _In_opt_ PVOID Context, + _In_ ULONG Type, + _In_ PVOID Setting +) + +/*++ + +Routine Description: + + This is the callback function for when GUID_ENERGY_SAVER_STATUS power setting + notification is triggered. It shows an example of how an App can + adjust behavior depending on the energy saver status. + +Arguments: + + Context - The context provided when registering for the power notification. + + Type - The type of power event that caused this notification (e.g. + GUID_ENERGY_SAVER_STATUS) + + Setting - The data associated with the power event. For + GUID_ENERGY_SAVER_STATUS, this is a value of type ENERGY_SAVER_STATUS. + +Return Value: + + Returns error status. + +--*/ + +{ + + UNREFERENCED_PARAMETER(Type); + UNREFERENCED_PARAMETER(Context); + + auto powerSetting = reinterpret_cast(Setting); + GUID const& settingId = powerSetting->PowerSetting; + + // + // Check the data size is expected + // + if (settingId != GUID_ENERGY_SAVER_STATUS || powerSetting->DataLength != sizeof(ENERGY_SAVER_STATUS)) + { + return ERROR_INVALID_PARAMETER; + } + + auto status = *reinterpret_cast(powerSetting->Data); + + // + // Change app behavior depending on energy saver status. + // For example, an app that does data synchronization might reduce its + // synchronization when under standard energy saver mode and pause it + // entirely when under extreme energy saver mode. + // + + switch (status) { + case ENERGY_SAVER_STANDARD: + printf("Standard energy saver mode: Reduce activities.\n"); + break; + + case ENERGY_SAVER_HIGH_SAVINGS: + printf("Extreme energy saver mode: Pause all non-essential activities.\n"); + break; + + default: + printf("Energy saver not active: Run normally.\n"); + break; + } + + return ERROR_SUCCESS; +} + + +int main() + +/*++ + +Routine Description: + + Main method which runs when exe is launched. It registers for the GUID_ENERGY_SAVER_STATUS notification + and waits for notifications until the user terminates the program by entering any input and hitting "enter". + While the program is running, the callback method will print out to the console the notification is triggered + (according to the callback method). + +Return Value: + + Returns error status. + +--*/ + +{ + + DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS params{}; + params.Callback = EnergySaverPowerSettingCallback; + + HPOWERNOTIFY registrationHandle{ nullptr }; + + // + // Register for GUID_ENERGY_SAVER_STATUS to receive notifications whenever setting updates + // + + DWORD error = PowerSettingRegisterNotification( + &GUID_ENERGY_SAVER_STATUS, + DEVICE_NOTIFY_CALLBACK, + ¶ms, + ®istrationHandle); + + if (error != ERROR_SUCCESS) { + printf("Error registering for GUID_ENERGY_SAVER_STATUS: %d. Terminating program...\n\n", error); + + return (int)error; + } + + printf("Registered for GUID_ENERGY_SAVER_STATUS notifications\n\n"); + + // + // Wait for user input before unregistering... + // + + printf("Waiting for GUID_ENERGY_SAVER_STATUS notifications... \n\n"); + printf("You can toggle Energy Saver in Quick Settings or Settings > Power & Battery to trigger the notification.\n\n"); + printf("Press any key to end the program...\n\n"); + std::cin.get(); + + // + // Unregister from GUID_ENERGY_SAVER_STATUS notifications for cleanup + // + + PowerSettingUnregisterNotification(registrationHandle); + printf("Unregistered for GUID_ENERGY_SAVER_STATUS notifications\n\n"); + + return ERROR_SUCCESS; +} + diff --git a/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotificationSample.sln b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotificationSample.sln new file mode 100644 index 00000000..c888ab40 --- /dev/null +++ b/Samples/PowerSettingRegisterNotification/cpp/PowerSettingRegisterNotificationSample.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34408.163 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerSettingRegisterNotification", "PowerSettingRegisterNotification.vcxproj", "{CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Debug|Win32.ActiveCfg = Debug|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Debug|Win32.Build.0 = Debug|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Debug|x64.ActiveCfg = Debug|x64 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Debug|x64.Build.0 = Debug|x64 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Debug|x86.ActiveCfg = Debug|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Debug|x86.Build.0 = Debug|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Release|Win32.ActiveCfg = Release|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Release|Win32.Build.0 = Release|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Release|x64.ActiveCfg = Release|x64 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Release|x64.Build.0 = Release|x64 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Release|x86.ActiveCfg = Release|Win32 + {CFD0029E-5B15-4C2D-8CBB-34DE5EC797A1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DE714B34-CD91-4465-8FAC-F6D456C66BCB} + EndGlobalSection +EndGlobal diff --git a/Samples/ProjectedFileSystem/stdafx.h b/Samples/ProjectedFileSystem/stdafx.h index 19d12565..5d5a771c 100644 --- a/Samples/ProjectedFileSystem/stdafx.h +++ b/Samples/ProjectedFileSystem/stdafx.h @@ -14,6 +14,7 @@ #include #include #include +#include // Windows SDK #include diff --git a/Samples/TaskbarManager/.gitattributes b/Samples/TaskbarManager/.gitattributes new file mode 100644 index 00000000..eba1110b --- /dev/null +++ b/Samples/TaskbarManager/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto \ No newline at end of file diff --git a/Samples/TaskbarManager/.gitignore b/Samples/TaskbarManager/.gitignore new file mode 100644 index 00000000..e3b706a7 --- /dev/null +++ b/Samples/TaskbarManager/.gitignore @@ -0,0 +1,276 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.vcxproj.filters + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +Generated Files/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# 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 + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +#**/Properties/launchSettings.json + +*_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 +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# 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 add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# 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 + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# 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 +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#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/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.idl b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.idl new file mode 100644 index 00000000..826a8e78 --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.idl @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +namespace CppPackagedDesktopTaskbarPin +{ +} diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml new file mode 100644 index 00000000..2c239f2f --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml.cpp b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml.cpp new file mode 100644 index 00000000..2cb3bc15 --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml.cpp @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" + +#include "App.xaml.h" +#include "MainWindow.xaml.h" + +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 winrt::CppPackagedDesktopTaskbarPin; +using namespace winrt::CppPackagedDesktopTaskbarPin::implementation; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +/// +/// 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(). +/// +App::App() +{ + InitializeComponent(); + +#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException([this](winrt::IInspectable const&, winrt::UnhandledExceptionEventArgs const& e) + { + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); +#endif +} + +/// +/// Invoked when the application is launched. +/// +/// Details about the launch request and process. +void App::OnLaunched(winrt::LaunchActivatedEventArgs const&) +{ + window = make(); + window.Activate(); +} diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml.h b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml.h new file mode 100644 index 00000000..5ae68d0a --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/App.xaml.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "App.xaml.g.h" + +namespace winrt::CppPackagedDesktopTaskbarPin::implementation +{ + struct App : AppT + { + App(); + + void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&); + + private: + winrt::Microsoft::UI::Xaml::Window window{ nullptr }; + }; +} diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/LockScreenLogo.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 00000000..e19810dc Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/LockScreenLogo.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/SplashScreen.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/SplashScreen.scale-200.png new file mode 100644 index 00000000..8a28b09f Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/SplashScreen.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square150x150Logo.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 00000000..28605231 Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square150x150Logo.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square150x150Secondary.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square150x150Secondary.scale-200.png new file mode 100644 index 00000000..87296542 Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square150x150Secondary.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Logo.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 00000000..429acdff Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Logo.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-48_altform-unplated.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-48_altform-unplated.png new file mode 100644 index 00000000..e19810dc Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-48_altform-unplated.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Secondary.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Secondary.scale-200.png new file mode 100644 index 00000000..cf30cb59 Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Square44x44Secondary.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/StoreLogo.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/StoreLogo.png new file mode 100644 index 00000000..5c397dea Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/StoreLogo.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Wide310x150Logo.scale-200.png b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 00000000..08b7c585 Binary files /dev/null and b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/Assets/Wide310x150Logo.scale-200.png differ diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/CppPackagedWin32TaskbarPin.vcxproj b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/CppPackagedWin32TaskbarPin.vcxproj new file mode 100644 index 00000000..120c0547 --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/CppPackagedWin32TaskbarPin.vcxproj @@ -0,0 +1,199 @@ + + + + + + + true + true + true + {91679704-ed4f-419b-a803-448a4ef98b09} + CppPackagedDesktopTaskbarPin + CppPackagedDesktopTaskbarPin + + $(RootNamespace) + en-US + 16.0 + false + true + Windows Store + 10.0 + 10.0 + 10.0.17763.0 + true + true + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + ARM64 + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v143 + Unicode + true + + + true + true + + + false + true + false + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + true + + + true + true + + + + + Designer + + + + + + + + + + App.xaml + + + MainWindow.xaml + + + + + + + + + Create + + + App.xaml + + + MainWindow.xaml + + + + + + Code + App.xaml + + + Code + MainWindow.xaml + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + 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}. + + + + + + + + + + \ No newline at end of file diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/LafData.h b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/LafData.h new file mode 100644 index 00000000..2800cf5a --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/LafData.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +constexpr std::wstring_view c_lafFeature = L""; +constexpr std::wstring_view c_lafToken = L""; +constexpr std::wstring_view c_lafAttestation = L""; diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/MainWindow.idl b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/MainWindow.idl new file mode 100644 index 00000000..afda24c1 --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/MainWindow.idl @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace CppPackagedDesktopTaskbarPin +{ + [default_interface] + runtimeclass MainWindow : Microsoft.UI.Xaml.Window + { + MainWindow(); + } +} diff --git a/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/MainWindow.xaml b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/MainWindow.xaml new file mode 100644 index 00000000..0ef4b907 --- /dev/null +++ b/Samples/TaskbarManager/CppPackagedDesktopTaskbarPin/MainWindow.xaml @@ -0,0 +1,71 @@ + + + + + + Usage of this sample requires that you have an assigned Limited Access Feature token for this functionality and have set it in LafData.h. See README.md for more information. + + + + + + You might want to encourage users to pin your app to taskbar so they can quickly re-engage with your app. + This app illustrates how you can check for the appropriate pinning support and use the functionality of the TaskbarManager API to perform taskbar pin operations. + + + + + + This section demonstrates how an app can use the TaskbarManager API to allow the user to trigger a taskbar pin request for the current app. + The "Update pin UI" button below will do a few things... + - Unlocks the desktop taskbar pinning LAF + - Checks whether the taskbar supports pinning and whether pinning from desktop apps is supported + - Checks whether the app is already pinned + - Shows/hides or enables/disables a pin button according to the results of the above checks; this pin button will make the actual pinning request when clicked + Generally, your app should automatically run the checks run by "Update pin UI" to determine whether pinning is possible and only provide the user with a pin action if pinning is supported and allowed. + + + + + + + + + + + + + + diff --git a/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/MainWindow.xaml.cpp b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/MainWindow.xaml.cpp new file mode 100644 index 00000000..cb9f951d --- /dev/null +++ b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/MainWindow.xaml.cpp @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "MainWindow.xaml.h" +#if __has_include("MainWindow.g.cpp") +#include "MainWindow.g.cpp" +#endif + +namespace winrt +{ + using namespace Windows::ApplicationModel; + using namespace Windows::Foundation; + using namespace Windows::UI::Shell; + using namespace Microsoft::UI::Xaml; +} + +namespace +{ + // Returns the explicitly set app user model ID for the current process. + wil::unique_cotaskmem_string GetCurrentProcessExplicitAumid() + { + wil::unique_cotaskmem_string aumid; + winrt::check_win32(GetCurrentProcessExplicitAppUserModelID(&aumid)); + return aumid; + } + + // Returns the path to the app list shortcut for this sample app. + std::wstring GetAppListShortcutPath() + { + wil::unique_cotaskmem_string appListPath; + winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_Programs, KF_FLAG_DEFAULT, nullptr, &appListPath)); + return (std::wstring(appListPath.get()) + L"\\CppUnpackagedDesktopTaskbarPin.lnk"); + } + + // Tries to unlock the necessary taskbar pinning LAF and returns true if successful. + bool TryUnlockPinningLaf() + { + // Ensure the appropriate LAF is unlocked. + // Appropriate LAF values must be specified in "LafData.h" based on your LAF token. + auto unlockStatus = winrt::LimitedAccessFeatures::TryUnlockFeature( + c_lafFeature.data(), c_lafToken.data(), c_lafAttestation.data()).Status(); + return ((unlockStatus == winrt::LimitedAccessFeatureStatus::Available) || (unlockStatus == winrt::LimitedAccessFeatureStatus::AvailableWithoutToken)); + } + + // Returns true if TaskbarManager supports desktop clients. + bool IsDesktopAppPinningSupported() + { + // Check whether the available TaskbarManager supports desktop app clients by checking for the associated marker interface. + return !!winrt::try_get_activation_factory(); + } +} + +namespace winrt::CppUnpackagedDesktopTaskbarPin::implementation +{ + MainWindow::MainWindow() + { + InitializeComponent(); + + // Usage of this sample requires that you have an assigned LAF token for this functionality and have + // updated both LafData.h and CppUnpackagedDesktopTaskbarPin.rc. See README.md for details. + if (!c_lafToken.empty() && ::FindResourceEx(nullptr, L"LimitedAccessFeature", L"Identity", 0)) + { + this->samplePanel().Visibility(Visibility::Visible); + this->lafErrorText().Visibility(Visibility::Collapsed); + } + } + + // Checks whether pinning the current app is possible and updates the pin button and status text accordingly. + // NOTE: Your app should not give the user an option to pin if requesting the pin won't do anything, so the ability to pin should be checked first. + // There is no guarantee that an app will be allowed to pin at any given time. + winrt::fire_and_forget MainWindow::PinCurrentScenarioButton_Click(winrt::IInspectable const&, winrt::RoutedEventArgs const&) + { + auto strongThis{ get_strong() }; + + // First, check whether pinning from desktop apps is supported at all. + if (TryUnlockPinningLaf() && IsDesktopAppPinningSupported()) + { + // Then, check whether the current app is already pinned and, if not, whether pinning is currently allowed from this app. + auto taskbarManager = winrt::TaskbarManager::GetDefault(); + if (!co_await taskbarManager.IsCurrentAppPinnedAsync()) + { + if (taskbarManager.IsPinningAllowed()) + { + // Pinning is supported and allowed, and the app is not already pinned. The app can offer the user the option to pin it. + this->pinCurrentScenarioPinButton().IsEnabled(true); + this->pinCurrentScenarioStatusText().Text({}); + } + else + { + // Pinning is supported, but pinning is not currently allowed (e.g., the system may not be able to show the prompt + // at this time). The app should not offer the usre an option to pin now, but it may check again at a later time + // (such as when showing the UI with the pin option on it again). + this->pinCurrentScenarioPinButton().IsEnabled(false); + this->pinCurrentScenarioStatusText().Text(L"Pinning is not allowed"); + } + } + else + { + // Pinning is supported, but the app is already pinned. The app should not offer ther user an option to pin again. + this->pinCurrentScenarioPinButton().IsEnabled(false); + this->pinCurrentScenarioStatusText().Text(L"App is already pinned"); + } + + this->pinCurrentScenarioPinButton().Visibility(Visibility::Visible); + } + else + { + // Pinning is not supported on this system, either because the limited access feature couldn't be unlocked + // or the API indicated desktop callers aren't supported. The app should not offer the user an option to pin. + this->pinCurrentScenarioStatusText().Text(L"Pinning is not supported"); + this->pinCurrentScenarioPinButton().Visibility(Visibility::Collapsed); + } + } + + // Attempts to pin the current app and update the status text with the result. + winrt::fire_and_forget MainWindow::PinCurrentScenarioPinButton_Click(winrt::IInspectable const&, winrt::RoutedEventArgs const&) + { + auto strongThis{ get_strong() }; + + // Make the pin request. Additional pin requests for the current app may not be made + // while one is still outstanding, so disable the pin request UI until the operation is complete. + this->pinCurrentScenarioButton().IsEnabled(false); + this->pinCurrentScenarioPinButton().IsEnabled(false); + auto isPinned = co_await winrt::TaskbarManager::GetDefault().RequestPinCurrentAppAsync(); + + // Update the UI to the appropriate state based on the results of the pin request. + this->pinCurrentScenarioStatusText().Text(isPinned ? L"Pinned" : L"Not pinned"); + this->pinCurrentScenarioPinButton().IsEnabled(!isPinned); + this->pinCurrentScenarioButton().IsEnabled(true); + } + + // Create a shortcut in the appropriate location to give this app an entry in the Start app list. This is + // required for the app to be allowed to request pinning of itself. Update the status text with the result. + // NOTE: Typically, this entry would be created by your apps installer. + void MainWindow::AddAppListEntryButton_Click(winrt::IInspectable const&, winrt::RoutedEventArgs const&) try + { + // https://learn.microsoft.com/en-us/windows/win32/shell/how-to-add-shortcuts-to-the-start-menu + // https://learn.microsoft.com/en-us/windows/win32/shell/appids + + auto link = wil::CoCreateInstance(); + winrt::check_hresult(link->SetPath(wil::QueryFullProcessImageNameW().get())); + winrt::check_hresult(link->SetDescription(L"C++ Unpackaged Desktop Taskbar Pinning App")); + + wil::unique_prop_variant appIdPropVar; + winrt::check_hresult(InitPropVariantFromString(GetCurrentProcessExplicitAumid().get(), &appIdPropVar)); + + auto propertyStore = link.query(); + winrt::check_hresult(propertyStore->SetValue(INIT_PKEY_AppUserModel_ID, appIdPropVar)); + winrt::check_hresult(propertyStore->Commit()); + + auto persistFile = link.query(); + winrt::check_hresult(persistFile->Save(GetAppListShortcutPath().c_str(), TRUE)); + + this->appListEntryStatusText().Text(L"Entry added"); + } + catch (const winrt::hresult_error& e) + { + this->appListEntryStatusText().Text(e.message()); + } + + // Removes the app list shortcut for this sample app. + void MainWindow::RemoveAppListEntryButton_Click(winrt::IInspectable const&, winrt::RoutedEventArgs const&) try + { + winrt::check_bool(DeleteFileW(GetAppListShortcutPath().c_str())); + this->appListEntryStatusText().Text(L"Entry removed"); + } + catch (const winrt::hresult_error& e) + { + this->appListEntryStatusText().Text(e.message()); + } +} diff --git a/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/MainWindow.xaml.h b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/MainWindow.xaml.h new file mode 100644 index 00000000..61d50e55 --- /dev/null +++ b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/MainWindow.xaml.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "MainWindow.g.h" + +namespace winrt::CppUnpackagedDesktopTaskbarPin::implementation +{ + struct MainWindow : MainWindowT + { + MainWindow(); + + winrt::fire_and_forget PinCurrentScenarioButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + winrt::fire_and_forget PinCurrentScenarioPinButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + + void UnlockLafButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void CheckPinningSupportedButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void CheckDesktopAppsSupportedButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void CheckAllowedButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + winrt::fire_and_forget CheckCurrentAppPinnedButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + winrt::fire_and_forget RequestPinCurrentAppButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void AddAppListEntryButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void RemoveAppListEntryButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + }; +} + +namespace winrt::CppUnpackagedDesktopTaskbarPin::factory_implementation +{ + struct MainWindow : MainWindowT + { + }; +} diff --git a/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/app.manifest b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/app.manifest new file mode 100644 index 00000000..a2d32d68 --- /dev/null +++ b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/app.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + PerMonitorV2 + + + \ No newline at end of file diff --git a/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/packages.config b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/packages.config new file mode 100644 index 00000000..254213b9 --- /dev/null +++ b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/pch.cpp b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/pch.cpp new file mode 100644 index 00000000..c084a84a --- /dev/null +++ b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" diff --git a/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/pch.h b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/pch.h new file mode 100644 index 00000000..be611818 --- /dev/null +++ b/Samples/TaskbarManager/CppUnpackagedDesktopTaskbarPin/pch.h @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Undefine GetCurrentTime macro to prevent +// conflict with Storyboard::GetCurrentTime +#undef GetCurrentTime + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LafData.h" diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/App.xaml b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/App.xaml new file mode 100644 index 00000000..dcecb5b0 --- /dev/null +++ b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/App.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/App.xaml.cs b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/App.xaml.cs new file mode 100644 index 00000000..903d8905 --- /dev/null +++ b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/App.xaml.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace CsPackagedDesktopTaskbarPin +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + public partial class App : Application + { + /// + /// 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(). + /// + public App() + { + InitializeComponent(); + } + + /// + /// Invoked when the application is launched. + /// + /// Details about the launch request and process. + protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) + { + m_window = new MainWindow(); + m_window.Activate(); + } + + private Window m_window; + } +} diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/LockScreenLogo.scale-200.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 00000000..e19810dc Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/LockScreenLogo.scale-200.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/SplashScreen.scale-200.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/SplashScreen.scale-200.png new file mode 100644 index 00000000..8a28b09f Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/SplashScreen.scale-200.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square150x150Logo.scale-200.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 00000000..28605231 Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square150x150Logo.scale-200.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square150x150Secondary.scale-200.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square150x150Secondary.scale-200.png new file mode 100644 index 00000000..53ee3777 Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square150x150Secondary.scale-200.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.scale-200.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 00000000..429acdff Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.scale-200.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 00000000..f6c02ce9 Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-48_altform-unplated.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-48_altform-unplated.png new file mode 100644 index 00000000..e19810dc Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Square44x44Logo.targetsize-48_altform-unplated.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/StoreLogo.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/StoreLogo.png new file mode 100644 index 00000000..5c397dea Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/StoreLogo.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Wide310x150Logo.scale-200.png b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 00000000..08b7c585 Binary files /dev/null and b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/Assets/Wide310x150Logo.scale-200.png differ diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/CsPackagedDesktopTaskbarPin.csproj b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/CsPackagedDesktopTaskbarPin.csproj new file mode 100644 index 00000000..a7059018 --- /dev/null +++ b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/CsPackagedDesktopTaskbarPin.csproj @@ -0,0 +1,66 @@ + + + WinExe + net6.0-windows10.0.22621.0 + 10.0.17763.0 + CsPackagedDesktopTaskbarPin + app.manifest + x86;x64;ARM64 + win10-x86;win10-x64;win10-arm64 + win10-$(Platform).pubxml + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + True + + + True + + + True + + + True + + + True + + + True + + diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/LafData.cs b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/LafData.cs new file mode 100644 index 00000000..47bbf214 --- /dev/null +++ b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/LafData.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace CsPackagedDesktopTaskbarPin +{ + internal static class LafData + { + public static readonly string Feature = ""; + public static readonly string Token = ""; + public static readonly string Attestation = ""; + } +} diff --git a/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/MainWindow.xaml b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/MainWindow.xaml new file mode 100644 index 00000000..b12d32b1 --- /dev/null +++ b/Samples/TaskbarManager/CsPackagedDesktopTaskbarPin/MainWindow.xaml @@ -0,0 +1,51 @@ + + + + + + Usage of this sample requires that you have an assigned Limited Access Feature token for this functionality and have set it in LafData.cs. See readme.md for more information. + + + + + + You might want to encourage users to pin your app to taskbar so they can quickly re-engage with your app. + This app illustrates how you can check for the appropriate pinning support and use the functionality of the TaskbarManager API to perform taskbar pin operations. + + + + + + This section demonstrates how an app can use the TaskbarManager API to allow the user to trigger a taskbar pin request for the current app. + The "Update pin UI" button below will do a few things... + - Unlocks the desktop taskbar pinning LAF + - Checks whether the taskbar supports pinning and whether pinning from desktop apps is supported + - Checks whether the app is already pinned + - Enables or disables a pin button according to the results of the above checks; this pin button will make the actual pinning request when clicked + Generally, your app would automatically run the checks to determine whether pinning is possible and only provide the user with a pin action if pinning is supported and allowed. + + + + +