Skip to content

Commit 534d40a

Browse files
committed
Windows 11 Version 23H2 - September 2024 Samples Update
* WebSocket: Use a script to generate the certificates and private keys * LampArray: New LampArray.IsAvailable property
1 parent 0db108e commit 534d40a

18 files changed

+164
-14
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,6 @@ FakesAssemblies/
203203

204204
# Custom ignores
205205
gallery.xml
206-
project.lock.json
206+
project.lock.json
207+
Samples/WebSocket/server/WebSocketSampleScriptSettings
208+
Samples/StreamSocket/**/StreamSocketSampleScriptSettings.xml

Samples/LampArray/cppwinrt/SampleConfiguration.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ using namespace winrt::SDKTemplate;
1818
using namespace winrt::Windows::Devices::Lights;
1919
using namespace winrt::Windows::Foundation::Collections;
2020

21-
hstring winrt::to_hstring(LampArrayKind lampArrayKind)
21+
std::wstring std::to_wstring(LampArrayKind lampArrayKind)
2222
{
2323
switch (lampArrayKind)
2424
{
@@ -44,7 +44,8 @@ hstring winrt::to_hstring(LampArrayKind lampArrayKind)
4444
return L"Art";
4545
case LampArrayKind::Undefined:
4646
default:
47-
return L"Unknown LampArrayKind";
47+
// Additional lamp array kinds can be looked up in the USB HID specification.
48+
return std::to_wstring(static_cast<uint32_t>(lampArrayKind));
4849
}
4950
}
5051

Samples/LampArray/cppwinrt/SampleConfiguration.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
#pragma once
1313
#include "pch.h"
1414

15-
namespace winrt
15+
namespace std
1616
{
17-
hstring to_hstring(winrt::Windows::Devices::Lights::LampArrayKind lampArrayKind);
17+
std::wstring to_wstring(winrt::Windows::Devices::Lights::LampArrayKind lampArrayKind);
1818
}
1919

2020
namespace winrt::SDKTemplate
@@ -29,5 +29,7 @@ namespace winrt::SDKTemplate
2929
winrt::hstring const id;
3030
winrt::hstring const displayName;
3131
winrt::Windows::Devices::Lights::LampArray const lampArray;
32+
33+
winrt::Windows::Devices::Lights::LampArray::AvailabilityChanged_revoker availabilityChangedRevoker;
3234
};
3335
}

Samples/LampArray/cppwinrt/Scenario1_Basics.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ namespace winrt::SDKTemplate::implementation
7070
co_return;
7171
}
7272

73+
// Set up the AvailabilityChanged event callback for being notified whether this process can control
74+
// RGB lighting for the newly attached LampArray.
75+
info->availabilityChangedRevoker = info->lampArray.AvailabilityChanged(winrt::auto_revoke, { this, &Scenario1_Basics::LampArray_AvailabilityChanged });
76+
7377
// Remember this new LampArray and add it to the list.
7478
m_attachedLampArrays.push_back(std::move(info));
7579
UpdateLampArrayList();
@@ -91,14 +95,24 @@ namespace winrt::SDKTemplate::implementation
9195
UpdateLampArrayList();
9296
}
9397

98+
// The AvailabilityChanged event will fire when this calling process gains or loses control of RGB lighting
99+
// for the specified LampArray.
100+
winrt::fire_and_forget Scenario1_Basics::LampArray_AvailabilityChanged(const LampArray& sender, const IInspectable&)
101+
{
102+
co_await winrt::resume_foreground(Dispatcher());
103+
104+
UpdateLampArrayList();
105+
}
106+
94107
void Scenario1_Basics::UpdateLampArrayList()
95108
{
96109
std::wstring message = std::wstring(L"Attached LampArrays: ") + std::to_wstring(m_attachedLampArrays.size()) + L"\n";
97110

98111
for (auto&& info : m_attachedLampArrays)
99112
{
100113
message += std::wstring(L"\t") + std::wstring(info->displayName) + L" ("
101-
+ winrt::to_hstring(info->lampArray.LampArrayKind()) + L", " + std::to_wstring(info->lampArray.LampCount()) + L" lamps)\n";
114+
+ std::to_wstring(info->lampArray.LampArrayKind()) + L", " + std::to_wstring(info->lampArray.LampCount()) + L" lamps, "
115+
+ std::wstring(info->lampArray.IsAvailable() ? L"Available" : L"Unavailable") + L")\n";
102116
}
103117

104118
LampArraysSummary().Text(message);

Samples/LampArray/cppwinrt/Scenario1_Basics.h

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ namespace winrt::SDKTemplate::implementation
4545
winrt::Windows::Devices::Enumeration::DeviceWatcher const&,
4646
winrt::Windows::Devices::Enumeration::DeviceInformationUpdate deviceInformationUpdate);
4747

48+
winrt::fire_and_forget LampArray_AvailabilityChanged(
49+
winrt::Windows::Devices::Lights::LampArray const& sender,
50+
winrt::Windows::Foundation::IInspectable const&);
51+
4852
void UpdateLampArrayList();
4953

5054
void ApplySettingsToLampArray(winrt::Windows::Devices::Lights::LampArray const& lampArray);

Samples/LampArray/cppwinrt/Scenario2_Effects.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ namespace winrt::SDKTemplate::implementation
9191
// Initial condition for the new LampArray is all lights off.
9292
info->lampArray.SetColor(Colors::Black());
9393

94+
// Set up the AvailabilityChanged event callback for being notified whether this process can control
95+
// RGB lighting for the newly attached LampArray.
96+
info->availabilityChangedRevoker = info->lampArray.AvailabilityChanged(winrt::auto_revoke, { this, &Scenario2_Effects::LampArray_AvailabilityChanged });
97+
9498
m_attachedLampArrays.push_back(std::move(info));
9599

96100
UpdateLampArrayList();
@@ -112,14 +116,24 @@ namespace winrt::SDKTemplate::implementation
112116
UpdateLampArrayList();
113117
}
114118

119+
// The AvailabilityChanged event will fire when this calling process gains or loses control of RGB lighting
120+
// for the specified LampArray.
121+
winrt::fire_and_forget Scenario2_Effects::LampArray_AvailabilityChanged(const LampArray& sender, const IInspectable&)
122+
{
123+
co_await winrt::resume_foreground(Dispatcher());
124+
125+
UpdateLampArrayList();
126+
}
127+
115128
void Scenario2_Effects::UpdateLampArrayList()
116129
{
117130
std::wstring message = std::wstring(L"Attached LampArrays: ") + std::to_wstring(m_attachedLampArrays.size()) + L"\n";
118131

119132
for (auto&& info : m_attachedLampArrays)
120133
{
121134
message += L"\t" + info->displayName + L" ("
122-
+ winrt::to_hstring(info->lampArray.LampArrayKind()) + L", " + std::to_wstring(info->lampArray.LampCount()) + L" lamps)\n";
135+
+ std::to_wstring(info->lampArray.LampArrayKind()) + L", " + std::to_wstring(info->lampArray.LampCount()) + L" lamps, "
136+
+ std::wstring(info->lampArray.IsAvailable() ? L"Available" : L"Unavailable") + L")\n";
123137
}
124138

125139
LampArraysSummary().Text(message);

Samples/LampArray/cppwinrt/Scenario2_Effects.h

+4
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ namespace winrt::SDKTemplate::implementation
125125
winrt::Windows::Devices::Enumeration::DeviceWatcher const&,
126126
winrt::Windows::Devices::Enumeration::DeviceInformationUpdate deviceInformationUpdate);
127127

128+
winrt::fire_and_forget LampArray_AvailabilityChanged(
129+
winrt::Windows::Devices::Lights::LampArray const& sender,
130+
winrt::Windows::Foundation::IInspectable const&);
131+
128132
void UpdateLampArrayList();
129133
void CleanupPreviousEffect();
130134

Samples/LampArray/cs/Scenario1_Basics.xaml.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
7272
return;
7373
}
7474

75+
// Set up the AvailabilityChanged event callback for being notified whether this process can control
76+
// RGB lighting for the newly attached LampArray.
77+
info.lampArray.AvailabilityChanged += LampArray_AvailabilityChanged;
78+
7579
// Remember this new LampArray and add it to the list.
7680
m_attachedLampArrays.Add(info);
7781
UpdateLampArrayList();
@@ -90,12 +94,23 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
9094
});
9195
}
9296

97+
// The AvailabilityChanged event will fire when this calling process gains or loses control of RGB lighting
98+
// for the specified LampArray.
99+
private async void LampArray_AvailabilityChanged(LampArray sender, object args)
100+
{
101+
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
102+
{
103+
UpdateLampArrayList();
104+
});
105+
}
106+
93107
private void UpdateLampArrayList()
94108
{
95109
string message = $"Attached LampArrays: {m_attachedLampArrays.Count}\n";
96110
foreach (LampArrayInfo info in m_attachedLampArrays)
97111
{
98-
message += $"\t{info.displayName} ({info.lampArray.LampArrayKind}, {info.lampArray.LampCount} lamps)\n";
112+
message += $"\t{info.displayName} ({info.lampArray.LampArrayKind.ToString()}, {info.lampArray.LampCount} lamps, " +
113+
$"{(info.lampArray.IsAvailable ? "Available" : "Unavailable")})\n";
99114
}
100115
LampArraysSummary.Text = message;
101116
}

Samples/LampArray/cs/Scenario2_Effects.xaml.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
125125
// Initial condition for the new LampArray is all lights off.
126126
info.lampArray.SetColor(Colors.Black);
127127

128+
// Set up the AvailabilityChanged event callback for being notified whether this process can control
129+
// RGB lighting for the newly attached LampArray.
130+
info.lampArray.AvailabilityChanged += LampArray_AvailabilityChanged;
131+
128132
m_attachedLampArrays.Add(info);
129133

130134
UpdateLampArrayList();
@@ -143,12 +147,23 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
143147
});
144148
}
145149

150+
// The AvailabilityChanged event will fire when this calling process gains or loses control of RGB lighting
151+
// for the specified LampArray.
152+
private async void LampArray_AvailabilityChanged(LampArray sender, object args)
153+
{
154+
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
155+
{
156+
UpdateLampArrayList();
157+
});
158+
}
159+
146160
private void UpdateLampArrayList()
147161
{
148162
string message = $"Attached LampArrays: {m_attachedLampArrays.Count}\n";
149163
foreach (LampArrayInfo info in m_attachedLampArrays)
150164
{
151-
message += $"\t{info.displayName} ({info.lampArray.LampArrayKind.ToString()}, {info.lampArray.LampCount} lamps)\n";
165+
message += $"\t{info.displayName} ({info.lampArray.LampArrayKind.ToString()}, {info.lampArray.LampCount} lamps, " +
166+
$"{(info.lampArray.IsAvailable ? "Available" : "Unavailable")})\n";
152167
}
153168
LampArraysSummary.Text = message;
154169
}

Samples/WebSocket/README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,10 @@ This sample requires that network capabilities be set in the *Package.appxmanife
9595
## Build the sample
9696

9797
1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build.
98-
2. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**.
99-
3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or JavaScript). Double-click the Visual Studio Solution (.sln) file.
100-
4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
98+
2. **Important**: From an elevated Powershell command prompt, navigate to the `WebSocket/shared` folder and execute the Powershell script `.\\clientCertGenerator.ps1`, This script will generate a custom RootCert.cer and clientCert.pfx, which are required for the application and server.
99+
3. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**.
100+
4. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for your preferred language (C++, C++/WinRT, C#). Double-click the Visual Studio Solution (.sln) file.
101+
5. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
101102

102103
## Run the sample
103104

Samples/WebSocket/cpp/WebSocket.vcxproj

+3
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,7 @@
236236
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
237237
<ImportGroup Label="ExtensionTargets">
238238
</ImportGroup>
239+
<Target Name="CheckCertificates" BeforeTargets="PrepareForBuild">
240+
<Error Condition="!Exists('$(MSBuildThisFileDirectory)\..\shared\clientCert.pfx')" Text="Before building this project, run the clientCertGenerator.ps1 script elevated as described in the README.md."/>
241+
</Target>
239242
</Project>

Samples/WebSocket/cppwinrt/WebSocket.vcxproj

+3
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@
196196
<ImportGroup Label="ExtensionTargets">
197197
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.200703.9\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.200703.9\build\native\Microsoft.Windows.CppWinRT.targets')" />
198198
</ImportGroup>
199+
<Target Name="CheckCertificates" BeforeTargets="PrepareForBuild">
200+
<Error Condition="!Exists('$(MSBuildThisFileDirectory)\..\shared\clientCert.pfx')" Text="Before building this project, run the clientCertGenerator.ps1 script elevated as described in the README.md."/>
201+
</Target>
199202
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
200203
<PropertyGroup>
201204
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>

Samples/WebSocket/cs/WebSocket.csproj

+3-2
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,11 @@
205205
<VisualStudioVersion>14.0</VisualStudioVersion>
206206
</PropertyGroup>
207207
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
208-
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
209-
Other similar extension points exist, see Microsoft.Common.targets.
210208
<Target Name="BeforeBuild">
209+
<Error Condition="!Exists('$(MSBuildThisFileDirectory)\..\shared\clientCert.pfx')" Text="Before building this project, run the clientCertGenerator.ps1 script as described in the README.md."/>
211210
</Target>
211+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
212+
Other similar extension points exist, see Microsoft.Common.targets.
212213
<Target Name="AfterBuild">
213214
</Target>
214215
-->

Samples/WebSocket/server/RootCert.cer

-824 Bytes
Binary file not shown.
Binary file not shown.

Samples/WebSocket/server/setupserver.ps1

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ $wssFirewallRuleName = "WebSocketSample - HTTPS 443"
1919
$requiredFeatures = "IIS-WebServer", "IIS-WebServerRole", "NetFx4Extended-ASPNET45", "IIS-ApplicationDevelopment", "IIS-ASPNET45", "IIS-ISAPIExtensions", "IIS-ISAPIFilter", "IIS-NetFxExtensibility45", "IIS-WebSockets"
2020
$settings = @{"featuresToEnable"=@(); "serverCertificateThumbprint"=""; "clientRootCertThumbprint" = ""; "webBindingAdded"=$false; "oldDefaultCert"=""}
2121
$settingsFile = "$scriptPath\WebSocketSampleScriptSettings"
22+
$rootCertFile = "$scriptPath\Rootcert.cer"
2223

2324
# Check if running as Administrator.
2425
$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
@@ -37,6 +38,13 @@ if (Test-Path $settingsFile)
3738
return;
3839
}
3940

41+
# Check if the necessary certificates have been created. If not, then user should run the certificate scripts first.
42+
if (Test-Path $rootCertFile)
43+
{
44+
"You need to run the ..\shared\clientCertGenerator.ps1 script to create the certificates before running this script."
45+
return;
46+
}
47+
4048
# Get features that should be enabled.
4149
$featuresToEnable = @()
4250
Get-WindowsOptionalFeature -Online | ?{ $_.State -eq [Microsoft.Dism.Commands.FeatureState]::Disabled -and $requiredFeatures -contains $_.FeatureName } | %{ $featuresToEnable += $_.FeatureName }
-3.54 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#*********************************************************
2+
#
3+
# Copyright (c) Microsoft. All rights reserved.
4+
# This code is licensed under the MIT License (MIT).
5+
# THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6+
# ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7+
# IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8+
# PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9+
#
10+
#*********************************************************
11+
12+
$sampleRootPath = Split-Path $(Split-Path -Resolve $MyInvocation.MyCommand.Path)
13+
$rootCertPath = "$sampleRootPath\server\RootCert.cer"
14+
$pfxFilePath = "$sampleRootPath\shared\clientCert.pfx"
15+
16+
if ((Test-Path $rootCertPath) -And (Test-Path $pfxFilePath)) {
17+
"The necessary certificates for this sample have already been created."
18+
"If you want to regenerate them, delete the files below and rerun this script."
19+
$rootCertPath
20+
$pfxFilePath
21+
return
22+
}
23+
24+
# Check if running as Administrator.
25+
$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
26+
$principal = New-Object System.Security.Principal.WindowsPrincipal($windowsIdentity)
27+
$administratorRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
28+
if ($principal.IsInRole($administratorRole) -eq $false)
29+
{
30+
"This script must be run from an elevated PowerShell."
31+
return
32+
}
33+
34+
# Create a Root Certificate with a Private Key
35+
$rootCert = New-SelfSignedCertificate -DnsName "www.contoso.com" -KeySpec Signature -Subject "CN=www.contoso.com" -KeyExportPolicy Exportable -KeyUsage CertSign,CRLSign,DigitalSignature -CertStoreLocation "cert:\LocalMachine\My" -TextExtension @("2.5.29.19={text}CA=true&pathlength=0")
36+
37+
# Export the root certificate to a file
38+
Export-Certificate -Cert $rootCert -FilePath $rootCertPath
39+
40+
# Verify if the root certificate was created successfully
41+
if ($rootCert -eq $null) {
42+
Write-Error "Failed to create the root certificate."
43+
return
44+
}
45+
46+
# Create the Client Certificate
47+
$clientCert = New-SelfSignedCertificate -KeySpec Signature -Subject "CN=WebSocketSample" -KeyExportPolicy Exportable -KeyUsage DigitalSignature,KeyEncipherment -CertStoreLocation "cert:\LocalMachine\My" -FriendlyName "WebSocketSampleClientCert" -Signer $rootCert -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2")
48+
49+
# Verify if the client certificate was created successfully
50+
if ($clientCert -eq $null) {
51+
Write-Error "Failed to create the client certificate."
52+
return
53+
}
54+
55+
# Export the Client Certificate to a PFX File
56+
$pfxPassword = ConvertTo-SecureString -String "1234" -Force -AsPlainText
57+
Export-PfxCertificate -Cert $clientCert -FilePath $pfxFilePath -Password $pfxPassword
58+
59+
# Verify if the client certificate was exported successfully
60+
if (-Not (Test-Path $pfxFilePath)) {
61+
Write-Error "Failed to export the client certificate to a PFX file."
62+
return
63+
}

0 commit comments

Comments
 (0)