From d57fb8ce9fff44fe409a8278c438f710625c3ac2 Mon Sep 17 00:00:00 2001 From: Dave Wilson Date: Thu, 10 Sep 2015 10:29:25 -0700 Subject: [PATCH] initial sample push --- .gitattributes | 37 + .gitignore | 200 + LICENSE | 21 + README.md | 12 +- Samples/AmbientLightAware/README.md | 49 + .../cpp/AmbientLightAware.cpp | 82 + .../AmbientLightAware/cpp/AmbientLightAware.h | 47 + .../cpp/AmbientLightAware.ico | Bin 0 -> 21630 bytes .../cpp/AmbientLightAware.rc | 168 + .../cpp/AmbientLightAware.rc2 | 13 + .../cpp/AmbientLightAware.sln | 26 + .../cpp/AmbientLightAware.vcxproj | 256 + .../cpp/AmbientLightAwareDlg.cpp | 277 + .../cpp/AmbientLightAwareDlg.h | 58 + .../cpp/AmbientLightAwareSensorEvents.cpp | 436 + .../cpp/AmbientLightAwareSensorEvents.h | 61 + .../AmbientLightAwareSensorManagerEvents.cpp | 417 + .../AmbientLightAwareSensorManagerEvents.h | 61 + Samples/AmbientLightAware/cpp/ReadMe.txt | 57 + Samples/AmbientLightAware/cpp/resource.h | 21 + Samples/AmbientLightAware/cpp/stdafx.cpp | 14 + Samples/AmbientLightAware/cpp/stdafx.h | 90 + Samples/AppVisibility/README.md | 50 + .../AppVisibility/cpp/AppVisibilitySample.cpp | 167 + .../AppVisibility/cpp/AppVisibilitySample.sln | 20 + .../cpp/AppVisibilitySample.vcxproj | 75 + Samples/AppxPackingCreateAppx/README.md | 93 + .../AppxPackingCreateAppx/cpp/CreateAppx.cpp | 266 + .../AppxPackingCreateAppx/cpp/CreateAppx.h | 31 + .../AppxPackingCreateAppx/cpp/CreateAppx.sln | 20 + .../cpp/CreateAppx.vcxproj | 110 + .../cpp/Data/AppTile.png | Bin 0 -> 1023 bytes .../cpp/Data/AppxManifest.xml | 42 + .../cpp/Data/Default.html | 8 + .../AppxPackingCreateAppx/cpp/Data/Error.html | 1 + .../cpp/Data/images/smiley.jpg | Bin 0 -> 8052 bytes Samples/AppxPackingCreateAppx/cpp/readme.txt | 72 + Samples/AppxPackingCreateBundle/README.md | 43 + .../cpp/CreateBundle.cpp | 209 + .../cpp/CreateBundle.h | 31 + .../cpp/CreateBundle.sln | 20 + .../cpp/CreateBundle.vcxproj | 110 + .../cpp/Data/MainAppPackage.appx | Bin 0 -> 11953 bytes .../cpp/Data/ResourcePackage.lang-de.appx | Bin 0 -> 5116 bytes .../AppxPackingCreateBundle/cpp/readme.txt | 68 + Samples/AppxPackingDescribeAppx/README.md | 95 + .../cpp/Data/SamplePackage.appx | Bin 0 -> 59971 bytes .../cpp/DescribeAppx.cpp | 620 + .../cpp/DescribeAppx.h | 56 + .../cpp/DescribeAppx.sln | 20 + .../cpp/DescribeAppx.vcxproj | 110 + .../AppxPackingDescribeAppx/cpp/readme.txt | 63 + Samples/AppxPackingDescribeBundle/README.md | 47 + .../cpp/Data/sample.appxbundle | Bin 0 -> 18898 bytes .../cpp/DescribeBundle.cpp | 321 + .../cpp/DescribeBundle.h | 40 + .../cpp/DescribeBundle.sln | 20 + .../cpp/DescribeBundle.vcxproj | 110 + .../AppxPackingDescribeBundle/cpp/readme.txt | 63 + Samples/AppxPackingExtractAppx/README.md | 93 + .../cpp/Data/HelloWorld.appx | Bin 0 -> 11463 bytes .../cpp/ExtractAppx.cpp | 403 + .../AppxPackingExtractAppx/cpp/ExtractAppx.h | 52 + .../cpp/ExtractAppx.sln | 20 + .../cpp/ExtractAppx.vcxproj | 110 + Samples/AppxPackingExtractAppx/cpp/readme.txt | 69 + Samples/AppxPackingExtractBundle/README.md | 41 + .../cpp/Data/sample.appxbundle | Bin 0 -> 18898 bytes .../cpp/ExtractBundle.cpp | 401 + .../cpp/ExtractBundle.h | 52 + .../cpp/ExtractBundle.sln | 20 + .../cpp/ExtractBundle.vcxproj | 110 + .../AppxPackingExtractBundle/cpp/readme.txt | 69 + .../README.md | 34 + .../cpp/TransferPolicy.cpp | 101 + .../cpp/TransferPolicy.sln | 22 + .../cpp/TransferPolicy.vcxproj | 96 + .../cpp/stdafx.cpp | 8 + .../cpp/stdafx.h | 17 + .../cpp/targetver.h | 8 + .../BackgroundCopyFileProperties/README.md | 36 + .../cpp/BACKGROUNDCOPYFILEPROPERTIES.cpp | 473 + .../cpp/BACKGROUNDCOPYFILEPROPERTIES.sln | 22 + .../cpp/BACKGROUNDCOPYFILEPROPERTIES.vcxproj | 96 + .../cpp/stdafx.cpp | 8 + .../BackgroundCopyFileProperties/cpp/stdafx.h | 15 + .../cpp/targetver.h | 8 + Samples/BasicPlugins/README.md | 53 + Samples/BasicPlugins/cs/AssemblyInfo.cs | 42 + Samples/BasicPlugins/cs/BasicPlugins.csproj | 66 + Samples/BasicPlugins/cs/BasicPlugins.sln | 20 + .../BasicPlugins/cs/CustomAuthorization.cs | 75 + .../BasicPlugins/cs/SessionConfiguration.cs | 57 + .../BasicPlugins/cs/setup/InstallModata.ps1 | 11 + .../cs/setup/Microsoft.Management.Odata.svc | 1 + Samples/BasicPlugins/cs/setup/Readme.txt | 6 + Samples/BasicPlugins/cs/setup/Schema.mof | 180 + Samples/BasicPlugins/cs/setup/Schema.xml | 163 + .../BasicPlugins/cs/setup/SetupEndpoint.ps1 | 33 + .../BasicPlugins/cs/setup/SetupIISConfig.ps1 | 332 + Samples/BasicPlugins/cs/setup/Web.config | 34 + Samples/CaptureEngineVideoCapture/README.md | 76 + .../CaptureEngineVideoCapture/cpp/Capture.cpp | 827 ++ .../CaptureEngineVideoCapture/cpp/Capture.h | 266 + .../CaptureEngineVideoCapture/cpp/Capture.rc | Bin 0 -> 6382 bytes .../cpp/CaptureEngine.sln | 20 + .../cpp/CaptureEngine.vcxproj | 106 + .../cpp/PreviewWnd.cpp | 91 + .../CaptureEngineVideoCapture/cpp/resource.h | Bin 0 -> 2198 bytes .../CaptureEngineVideoCapture/cpp/utils.cpp | 176 + .../CaptureEngineVideoCapture/cpp/winmain.cpp | 757 ++ Samples/CauSamplePlugin/README.md | 49 + Samples/CauSamplePlugin/cs/AssemblyInfo.cs | 16 + .../CauSamplePlugin/cs/CauSamplePlugin.csproj | 57 + Samples/CauSamplePlugin/cs/CauSamplePlugin.rc | 11 + .../CauSamplePlugin/cs/CauSamplePlugin.sln | 22 + .../CauSamplePlugin/cs/FabrikamCauPlugin.cs | 478 + Samples/ClsIDCallback/README.md | 34 + Samples/ClsIDCallback/cpp/ClsIDCallback.cpp | 188 + Samples/ClsIDCallback/cpp/ClsIDCallback.sln | 20 + .../ClsIDCallback/cpp/ClsIDCallback.vcxproj | 104 + .../ClsIDCallback/cpp/NotifyInterfaceImp.cpp | 291 + .../ClsIDCallback/cpp/NotifyInterfaceImp.h | 133 + Samples/ClsIDCallback/cpp/ReadMe.txt | 43 + Samples/ClsIDCallback/cpp/stdafx.cpp | 8 + Samples/ClsIDCallback/cpp/stdafx.h | 17 + Samples/ClsIDCallback/cpp/targetver.h | 8 + Samples/ClsIDCallback/cpp/utils.cpp | 167 + Samples/ClsIDCallback/cpp/utils.h | 61 + Samples/ConnectionManagerCost/README.md | 56 + Samples/ConnectionManagerCost/Readme.txt | 39 + Samples/ConnectionManagerCost/cpp/Utils.cpp | 472 + Samples/ConnectionManagerCost/cpp/Utils.h | 79 + .../cpp/WcmCostSample.sln | 20 + .../cpp/WcmCostSample.vcxproj | 96 + .../cpp/WcmCostSample.vcxproj.filters | 33 + .../cpp/Wcmcostsample.cpp | 343 + .../ConnectionManagerCost/cpp/Wcmcostsample.h | 37 + Samples/CredentialProvider/README.md | 32 + .../cpp/CSampleCredential.cpp | 700 + .../cpp/CSampleCredential.h | 120 + .../cpp/CSampleProvider.cpp | 279 + .../CredentialProvider/cpp/CSampleProvider.h | 85 + Samples/CredentialProvider/cpp/Dll.cpp | 151 + Samples/CredentialProvider/cpp/Dll.h | 18 + .../cpp/SampleV2CredentialProvider.sln | 26 + .../cpp/SampleV2CredentialProvider.vcxproj | 183 + ...SampleV2CredentialProvider.vcxproj.filters | 77 + Samples/CredentialProvider/cpp/Unregister.reg | Bin 0 -> 362 bytes Samples/CredentialProvider/cpp/common.h | 95 + Samples/CredentialProvider/cpp/guid.cpp | 11 + Samples/CredentialProvider/cpp/guid.h | 11 + Samples/CredentialProvider/cpp/helpers.cpp | 710 ++ Samples/CredentialProvider/cpp/helpers.h | 101 + Samples/CredentialProvider/cpp/register.reg | Bin 0 -> 926 bytes Samples/CredentialProvider/cpp/resource.h | 10 + Samples/CredentialProvider/cpp/resources.rc | 6 + .../cpp/samplev2credentialprovider.def | 5 + Samples/CredentialProvider/cpp/tileimage.bmp | Bin 0 -> 49206 bytes Samples/CustomResourceManager/README.md | 34 + .../CustomResourceManager/cpp/CSecInfo.cpp | 1089 ++ Samples/CustomResourceManager/cpp/CSecInfo.h | 231 + .../cpp/CustomResourceManager.sln | 20 + .../cpp/CustomResourceManager.vcxproj | 86 + .../cpp/CustomResourceManager.vcxproj.filters | 45 + .../cpp/SecurityInformation1.cpp | 450 + Samples/CustomResourceManager/cpp/main.cpp | 111 + .../CustomResourceManager/cpp/resource.cpp | 70 + Samples/CustomResourceManager/cpp/resource.h | 87 + Samples/CustomResourceManager/cpp/utility.cpp | 747 ++ Samples/CustomResourceManager/cpp/utility.h | 77 + Samples/D2DPrintingFromDesktopApps/README.md | 40 + .../cpp/D2DPrintJobChecker.cpp | 338 + .../cpp/D2DPrintJobChecker.h | 98 + .../cpp/D2DPrintingFromDesktopApps.cpp | 1746 +++ .../cpp/D2DPrintingFromDesktopApps.h | 195 + .../cpp/D2DPrintingFromDesktopApps.sln | 26 + .../cpp/D2DPrintingFromDesktopApps.vcxproj | 129 + .../cpp/sampleimage.jpg | Bin 0 -> 158728 bytes .../DCompV2BackfaceandD2DBatching/README.md | 32 + .../cpp/Application.cpp | 1227 ++ .../cpp/Application.h | 127 + .../cpp/DCompV2BackfaceandD2DBatching.sln | 22 + .../cpp/DCompV2BackfaceandD2DBatching.vcxproj | 92 + .../cpp/Main.cpp | 20 + Samples/DHCP/AddPolicyRange/README.md | 42 + .../AddPolicyRange/cpp/addpolicyrange.cpp | 48 + .../AddPolicyRange/cpp/addpolicyrange.sln | 20 + .../AddPolicyRange/cpp/addpolicyrange.vcxproj | 94 + Samples/DHCP/AddScopeToRelationship/README.md | 42 + .../cpp/AddScopeToRelationship.cpp | 206 + .../cpp/AddScopeToRelationship.sln | 20 + .../cpp/AddScopeToRelationship.vcxproj | 94 + Samples/DHCP/CreatePolicy/README.md | 42 + .../DHCP/CreatePolicy/cpp/createpolicy.cpp | 109 + .../DHCP/CreatePolicy/cpp/createpolicy.sln | 20 + .../CreatePolicy/cpp/createpolicy.vcxproj | 94 + Samples/DHCP/CreateRelationship/README.md | 42 + .../cpp/createrelationship.cpp | 228 + .../cpp/createrelationship.sln | 20 + .../cpp/createrelationship.vcxproj | 94 + Samples/DHCP/DeletePolicy/README.md | 42 + .../DHCP/DeletePolicy/cpp/deletepolicy.cpp | 37 + .../DHCP/DeletePolicy/cpp/deletepolicy.sln | 20 + .../DeletePolicy/cpp/deletepolicy.vcxproj | 94 + Samples/DHCP/DeleteRelationship/README.md | 42 + .../cpp/DeleteRelationship.cpp | 152 + .../cpp/DeleteRelationship.sln | 20 + .../cpp/DeleteRelationship.vcxproj | 94 + .../DeleteScopeFromRelationship/README.md | 42 + .../cpp/DeleteScopeFromRelationship.cpp | 168 + .../cpp/DeleteScopeFromRelationship.sln | 20 + .../cpp/DeleteScopeFromRelationship.vcxproj | 94 + Samples/DHCP/EnumPolicy/README.md | 42 + Samples/DHCP/EnumPolicy/cpp/enumpolicy.cpp | 125 + Samples/DHCP/EnumPolicy/cpp/enumpolicy.sln | 20 + .../DHCP/EnumPolicy/cpp/enumpolicy.vcxproj | 94 + Samples/DHCP/EnumRelationship/README.md | 42 + .../EnumRelationship/cpp/EnumRelationship.cpp | 116 + .../EnumRelationship/cpp/EnumRelationship.sln | 20 + .../cpp/EnumRelationship.vcxproj | 94 + Samples/DHCP/EnumSubnetClients/README.md | 42 + .../cpp/EnumSubnetClients.cpp | 120 + .../cpp/EnumSubnetClients.sln | 20 + .../cpp/EnumSubnetClients.vcxproj | 94 + Samples/DHCP/EnumSubnetReservations/README.md | 42 + .../cpp/EnumSubnetReservations.cpp | 105 + .../cpp/EnumSubnetReservations.sln | 20 + .../cpp/EnumSubnetReservations.vcxproj | 94 + Samples/DHCP/GetAddressStatus/README.md | 42 + .../GetAddressStatus/cpp/GetAddressStatus.cpp | 47 + .../GetAddressStatus/cpp/GetAddressStatus.sln | 20 + .../cpp/GetAddressStatus.vcxproj | 94 + Samples/DHCP/GetClientInfo/README.md | 42 + .../DHCP/GetClientInfo/cpp/GetClientInfo.cpp | 78 + .../DHCP/GetClientInfo/cpp/GetClientInfo.sln | 20 + .../GetClientInfo/cpp/GetClientInfo.vcxproj | 94 + Samples/DHCP/GetPolicy/README.md | 42 + Samples/DHCP/GetPolicy/cpp/getpolicy.cpp | 95 + Samples/DHCP/GetPolicy/cpp/getpolicy.sln | 20 + Samples/DHCP/GetPolicy/cpp/getpolicy.vcxproj | 94 + Samples/DHCP/GetRelationship/README.md | 42 + .../GetRelationship/cpp/GetRelationship.cpp | 72 + .../GetRelationship/cpp/GetRelationship.sln | 20 + .../cpp/GetRelationship.vcxproj | 94 + Samples/DHCP/GetScopeRelationship/README.md | 42 + .../cpp/GetScopeRelationship.cpp | 77 + .../cpp/GetScopeRelationship.sln | 20 + .../cpp/GetScopeRelationship.vcxproj | 94 + Samples/DHCP/GetScopeStatistics/README.md | 42 + .../cpp/GetScopeStatistics.cpp | 48 + .../cpp/GetScopeStatistics.sln | 20 + .../cpp/GetScopeStatistics.vcxproj | 94 + Samples/DHCP/GetStatelessStatistics/README.md | 42 + .../cpp/GetStatelessStatistics.cpp | 68 + .../cpp/GetStatelessStatistics.sln | 20 + .../cpp/GetStatelessStatistics.vcxproj | 94 + .../DHCP/GetStatelessStoreParams/README.md | 42 + .../cpp/GetStatelessStoreParams.cpp | 44 + .../cpp/GetStatelessStoreParams.sln | 20 + .../cpp/GetStatelessStoreParams.vcxproj | 94 + Samples/DHCP/GetSystemTime/README.md | 42 + .../DHCP/GetSystemTime/cpp/GetSystemTime.cpp | 29 + .../DHCP/GetSystemTime/cpp/GetSystemTime.sln | 20 + .../GetSystemTime/cpp/GetSystemTime.vcxproj | 94 + Samples/DHCP/HlprAddPolicyCondition/README.md | 42 + .../cpp/hlpraddpolicycond.cpp | 105 + .../cpp/hlpraddpolicycond.sln | 20 + .../cpp/hlpraddpolicycond.vcxproj | 94 + Samples/DHCP/HlprAddPolicyExpr/README.md | 42 + .../cpp/hlpraddpolicyexpr.cpp | 153 + .../cpp/hlpraddpolicyexpr.sln | 20 + .../cpp/hlpraddpolicyexpr.vcxproj | 94 + Samples/DHCP/HlprAddPolicyRange/README.md | 42 + .../cpp/hlpraddpolicyrange.cpp | 112 + .../cpp/hlpraddpolicyrange.sln | 20 + .../cpp/hlpraddpolicyrange.vcxproj | 94 + Samples/DHCP/HlprCreatePolicy/README.md | 42 + .../HlprCreatePolicy/cpp/hlprcreatepolicy.cpp | 45 + .../HlprCreatePolicy/cpp/hlprcreatepolicy.sln | 20 + .../cpp/hlprcreatepolicy.vcxproj | 94 + Samples/DHCP/HlprIsPolicySingleUC/README.md | 42 + .../cpp/hlprispolicysingleuc.cpp | 103 + .../cpp/hlprispolicysingleuc.sln | 20 + .../cpp/hlprispolicysingleuc.vcxproj | 94 + Samples/DHCP/HlprIsPolicyWellFormed/README.md | 42 + .../cpp/hlprispolicywellformed.cpp | 155 + .../cpp/hlprispolicywellformed.sln | 20 + .../cpp/hlprispolicywellformed.vcxproj | 94 + Samples/DHCP/HlprModifyPolicyExpr/README.md | 42 + .../cpp/hlprmodifypolicyexpr.cpp | 108 + .../cpp/hlprmodifypolicyexpr.sln | 20 + .../cpp/hlprmodifypolicyexpr.vcxproj | 94 + Samples/DHCP/HlprResetPolicyExpr/README.md | 42 + .../cpp/hlprresetpolicyexpr.cpp | 163 + .../cpp/hlprresetpolicyexpr.sln | 20 + .../cpp/hlprresetpolicyexpr.vcxproj | 94 + Samples/DHCP/HlprisPolicyValid/README.md | 42 + .../cpp/hlprispolicyvalid.cpp | 115 + .../cpp/hlprispolicyvalid.sln | 20 + .../cpp/hlprispolicyvalid.vcxproj | 94 + Samples/DHCP/QueryPolicyEnforcement/README.md | 42 + .../cpp/querypolicyenforcement.cpp | 41 + .../cpp/querypolicyenforcement.sln | 20 + .../cpp/querypolicyenforcement.vcxproj | 94 + Samples/DHCP/RemovePolicyRange/README.md | 42 + .../cpp/removepolicyrange.cpp | 44 + .../cpp/removepolicyrange.sln | 20 + .../cpp/removepolicyrange.vcxproj | 94 + Samples/DHCP/SetPolicy/README.md | 42 + Samples/DHCP/SetPolicy/cpp/setpolicy.cpp | 116 + Samples/DHCP/SetPolicy/cpp/setpolicy.sln | 20 + Samples/DHCP/SetPolicy/cpp/setpolicy.vcxproj | 94 + Samples/DHCP/SetPolicyEnforcement/README.md | 42 + .../cpp/setpolicyenforcement.cpp | 50 + .../cpp/setpolicyenforcement.sln | 20 + .../cpp/setpolicyenforcement.vcxproj | 94 + Samples/DHCP/SetRelationship/README.md | 42 + .../SetRelationship/cpp/setrelationship.cpp | 91 + .../SetRelationship/cpp/setrelationship.sln | 20 + .../cpp/setrelationship.vcxproj | 94 + .../DHCP/SetStatelessStoreParams/README.md | 42 + .../cpp/SetStatelessStoreParams.cpp | 39 + .../cpp/SetStatelessStoreParams.sln | 20 + .../cpp/SetStatelessStoreParams.vcxproj | 94 + Samples/DHCP/TriggerAddrAllocation/README.md | 42 + .../cpp/TriggerAddrAllocation.cpp | 33 + .../cpp/TriggerAddrAllocation.sln | 20 + .../cpp/TriggerAddrAllocation.vcxproj | 94 + Samples/DHCP/V4CreateClientInfo/README.md | 42 + .../cpp/V4CreateClientInfo.cpp | 80 + .../cpp/V4CreateClientInfo.sln | 20 + .../cpp/V4CreateClientInfo.vcxproj | 94 + Samples/DHCP/V4GetAllOptionValue/README.md | 42 + .../cpp/v4getalloptionvalue.cpp | 39 + .../cpp/v4getalloptionvalue.sln | 20 + .../cpp/v4getalloptionvalue.vcxproj | 94 + Samples/DHCP/V4GetClientInfo/README.md | 42 + .../V4GetClientInfo/cpp/V4GetClientInfo.cpp | 74 + .../V4GetClientInfo/cpp/V4GetClientInfo.sln | 20 + .../cpp/V4GetClientInfo.vcxproj | 94 + Samples/DHCP/V4GetFreeIPAddress/README.md | 42 + .../cpp/V4GetFreeIPAddress.cpp | 51 + .../cpp/V4GetFreeIPAddress.sln | 20 + .../cpp/V4GetFreeIPAddress.vcxproj | 94 + Samples/DHCP/V6CreateClientInfo/README.md | 42 + .../cpp/V6CreateClientInfo.cpp | 72 + .../cpp/V6CreateClientInfo.sln | 20 + .../cpp/V6CreateClientInfo.vcxproj | 94 + Samples/DHCP/V6GetFreeIPAddress/README.md | 42 + .../cpp/V6GetFreeIPAddress.cpp | 57 + .../cpp/V6GetFreeIPAddress.sln | 20 + .../cpp/V6GetFreeIPAddress.vcxproj | 94 + Samples/DHCP/v4GetOptionValue/README.md | 42 + .../v4GetOptionValue/cpp/v4getoptionvalue.cpp | 45 + .../v4GetOptionValue/cpp/v4getoptionvalue.sln | 20 + .../cpp/v4getoptionvalue.vcxproj | 94 + Samples/DHCP/v4RemoveOptionValue/README.md | 42 + .../cpp/v4removeoptionvalue.cpp | 39 + .../cpp/v4removeoptionvalue.sln | 20 + .../cpp/v4removeoptionvalue.vcxproj | 94 + Samples/DHCP/v4SetOptionValue/README.md | 42 + .../v4SetOptionValue/cpp/v4setoptionvalue.cpp | 55 + .../v4SetOptionValue/cpp/v4setoptionvalue.sln | 20 + .../cpp/v4setoptionvalue.vcxproj | 94 + Samples/DHCP/v4SetOptionValues/README.md | 42 + .../cpp/v4setoptionvalues.cpp | 82 + .../cpp/v4setoptionvalues.sln | 20 + .../cpp/v4setoptionvalues.vcxproj | 94 + .../DNSAsyncNetworkNameResolution/README.md | 37 + .../cpp/ResolveName.cpp | 236 + .../cpp/ResolveName.sln | 20 + .../cpp/ResolveName.vcxproj | 92 + Samples/DNSAsyncQuery/README.md | 45 + Samples/DNSAsyncQuery/cpp/DnsQueryEx.cpp | 364 + Samples/DNSAsyncQuery/cpp/DnsQueryEx.sln | 20 + Samples/DNSAsyncQuery/cpp/DnsQueryEx.vcxproj | 94 + Samples/DNSAsyncQuery/cpp/ParseArgs.cpp | 301 + Samples/DNSAsyncQuery/cpp/PrintDnsRecord.cpp | 327 + Samples/DPIAwarenessPerMonitor/README.md | 30 + .../cpp/DPITutorial.cpp | 471 + .../DPIAwarenessPerMonitor/cpp/DPITutorial.h | 145 + .../cpp/DPITutorial.ico | Bin 0 -> 2998 bytes .../DPIAwarenessPerMonitor/cpp/DPITutorial.rc | Bin 0 -> 6440 bytes .../cpp/DPITutorial.sln | 22 + .../cpp/DPITutorial.vcxproj | 106 + .../cpp/DPITutorial.vcxproj.filters | 55 + Samples/DPIAwarenessPerMonitor/cpp/Resource.h | 41 + .../DPIAwarenessPerMonitor/cpp/scaled100.bmp | Bin 0 -> 90054 bytes .../DPIAwarenessPerMonitor/cpp/scaled125.bmp | Bin 0 -> 141430 bytes .../DPIAwarenessPerMonitor/cpp/scaled150.bmp | Bin 0 -> 202554 bytes .../DPIAwarenessPerMonitor/cpp/scaled200.bmp | Bin 0 -> 360054 bytes Samples/DPIAwarenessPerMonitor/cpp/small.ico | Bin 0 -> 2998 bytes Samples/DPIAwarenessPerMonitor/cpp/stdafx.cpp | 5 + Samples/DPIAwarenessPerMonitor/cpp/stdafx.h | 21 + .../DPIAwarenessPerMonitor/cpp/targetver.h | 8 + Samples/DX11VideoRenderer/README.md | 56 + Samples/DX11VideoRenderer/cpp/Activate.cpp | 213 + Samples/DX11VideoRenderer/cpp/Activate.h | 43 + .../DX11VideoRenderer/cpp/ClassFactory.cpp | 88 + Samples/DX11VideoRenderer/cpp/ClassFactory.h | 32 + Samples/DX11VideoRenderer/cpp/Common.h | 384 + Samples/DX11VideoRenderer/cpp/DLLMain.cpp | 261 + .../cpp/DX11VideoRenderer.def | 9 + .../DX11VideoRenderer/cpp/DX11VideoRenderer.h | 11 + .../cpp/DX11VideoRenderer.sln | 20 + .../cpp/DX11VideoRenderer.vcxproj | 117 + .../DX11VideoRenderer/cpp/MFAttributesImpl.h | 352 + Samples/DX11VideoRenderer/cpp/Marker.cpp | 142 + Samples/DX11VideoRenderer/cpp/Marker.h | 62 + Samples/DX11VideoRenderer/cpp/MediaSink.cpp | 791 ++ Samples/DX11VideoRenderer/cpp/MediaSink.h | 76 + Samples/DX11VideoRenderer/cpp/Presenter.cpp | 2307 ++++ Samples/DX11VideoRenderer/cpp/Presenter.h | 704 ++ Samples/DX11VideoRenderer/cpp/Scheduler.cpp | 416 + Samples/DX11VideoRenderer/cpp/Scheduler.h | 89 + .../cpp/StaticAsyncCallback.h | 116 + Samples/DX11VideoRenderer/cpp/StreamSink.cpp | 1648 +++ Samples/DX11VideoRenderer/cpp/StreamSink.h | 186 + Samples/DX11VideoRenderer/cpp/display.cpp | 313 + Samples/DX11VideoRenderer/cpp/display.h | 73 + Samples/DX11VideoRenderer/cpp/linklist.h | 735 ++ Samples/DXGIDesktopDuplication/README.md | 44 + .../DXGIDesktopDuplication/cpp/CommonTypes.h | 115 + .../cpp/DesktopDuplication.cpp | 697 + .../cpp/DesktopDuplication.sln | 26 + .../cpp/DesktopDuplication.vcxproj | 229 + .../cpp/DisplayManager.cpp | 478 + .../cpp/DisplayManager.h | 46 + .../cpp/DuplicationManager.cpp | 319 + .../cpp/DuplicationManager.h | 39 + .../cpp/OutputManager.cpp | 1103 ++ .../cpp/OutputManager.h | 61 + .../cpp/PixelShader.hlsl | 24 + .../cpp/ThreadManager.cpp | 258 + .../cpp/ThreadManager.h | 33 + .../cpp/VertexShader.hlsl | 28 + Samples/DataDedupBackupRestore/README.md | 68 + .../cpp/DedupBackupRestore.cpp | 2690 ++++ .../cpp/DedupBackupRestore.sln | 20 + .../cpp/DedupBackupRestore.vcxproj | 92 + Samples/DesktopAutomationDismiss/README.md | 59 + .../cpp/DesktopAutomation.sln | 20 + .../cpp/DesktopAutomation.vcxproj | 91 + .../cpp/ShowDesktop.cpp | 373 + .../DesktopAutomationDismiss/cpp/readme.txt | 55 + Samples/DesktopToasts/README.md | 65 + .../DesktopToasts/cpp/DesktopToastsSample.cpp | 453 + .../DesktopToasts/cpp/DesktopToastsSample.h | 67 + .../DesktopToasts/cpp/DesktopToastsSample.sln | 26 + .../cpp/DesktopToastsSample.vcxproj | 169 + Samples/DesktopToasts/cpp/Product.wxs | 34 + .../cpp/StringReferenceWrapper.h | 60 + .../DesktopToasts/cpp/ToastEventHandler.cpp | 63 + Samples/DesktopToasts/cpp/ToastEventHandler.h | 55 + Samples/DesktopToasts/cpp/stdafx.cpp | 6 + Samples/DesktopToasts/cpp/stdafx.h | 30 + .../DesktopToasts/cpp/toastImageAndText.png | Bin 0 -> 468 bytes Samples/DesktopToasts/cs/App.config | 6 + Samples/DesktopToasts/cs/App.xaml | 8 + Samples/DesktopToasts/cs/App.xaml.cs | 19 + .../cs/DesktopToastsSample.csproj | 143 + .../DesktopToasts/cs/DesktopToastsSample.sln | 26 + Samples/DesktopToasts/cs/MainWindow.xaml | 9 + Samples/DesktopToasts/cs/MainWindow.xaml.cs | 138 + Samples/DesktopToasts/cs/Product.wxs | 34 + .../cs/Properties/AssemblyInfo.cs | 55 + .../cs/Properties/Resources.Designer.cs | 62 + .../cs/Properties/Resources.resx | 117 + .../cs/Properties/Settings.Designer.cs | 30 + .../cs/Properties/Settings.settings | 7 + Samples/DesktopToasts/cs/ShellHelpers.cs | 133 + .../DesktopToasts/cs/toastImageAndText.png | Bin 0 -> 468 bytes Samples/DetectBootSector/README.md | 65 + .../DetectBootSector/cpp/DetectBootSector.cpp | 132 + .../DetectBootSector/cpp/DetectBootSector.sln | 26 + .../cpp/DetectBootSector.vcxproj | 155 + Samples/DirectCompositionEffects/README.md | 56 + .../cpp/Application.cpp | 1534 +++ .../cpp/Application.h | 146 + .../cpp/Application.rc | Bin 0 -> 396 bytes .../cpp/DirectComposition_Effects.sln | 20 + .../cpp/DirectComposition_Effects.vcxproj | 91 + Samples/DirectCompositionEffects/cpp/Main.cpp | 15 + .../DirectCompositionEffects/cpp/resource.h | 26 + .../README.md | 60 + .../DirectComposition_LayeredChildWindow.cpp | 1537 +++ .../DirectComposition_LayeredChildWindow.h | 206 + ...ectComposition_LayeredChildWindow.manifest | 20 + .../DirectComposition_LayeredChildWindow.rc | Bin 0 -> 396 bytes .../DirectComposition_LayeredChildWindow.sln | 20 + ...rectComposition_LayeredChildWindow.vcxproj | 100 + .../cpp/media/TallShip-medium.wmv | Bin 0 -> 4141440 bytes .../cpp/resource.h | 27 + .../README.md | 45 + .../cpp/220Strawberry.png | Bin 0 -> 20834 bytes .../cpp/Application.rc | Bin 0 -> 396 bytes .../cpp/DirectComposition_WAM.cpp | 1133 ++ .../cpp/DirectComposition_WAM.h | 118 + .../cpp/DirectComposition_WAM.sln | 20 + .../cpp/DirectComposition_WAM.vcxproj | 100 + .../cpp/resource.h | 26 + Samples/DirectXTextureConverter/Cpp/BC.cpp | 1141 ++ Samples/DirectXTextureConverter/Cpp/BC.h | 891 ++ .../DirectXTextureConverter/Cpp/BC4BC5.cpp | 548 + .../DirectXTextureConverter/Cpp/BC6HBC7.cpp | 2871 +++++ Samples/DirectXTextureConverter/Cpp/DDS.h | 227 + .../DirectXTextureConverter/Cpp/DirectXTex.h | 550 + .../Cpp/DirectXTex.inl | 276 + .../Cpp/DirectXTexCompress.cpp | 773 ++ .../Cpp/DirectXTexConvert.cpp | 3485 +++++ .../Cpp/DirectXTexD3D11.cpp | 865 ++ .../Cpp/DirectXTexDDS.cpp | 1823 +++ .../Cpp/DirectXTexFlipRotate.cpp | 329 + .../Cpp/DirectXTexImage.cpp | 741 ++ .../Cpp/DirectXTexMipMaps.cpp | 3059 +++++ .../Cpp/DirectXTexMisc.cpp | 339 + .../Cpp/DirectXTexNormalMaps.cpp | 379 + .../Cpp/DirectXTexPMAlpha.cpp | 184 + .../Cpp/DirectXTexResize.cpp | 1032 ++ .../Cpp/DirectXTexTGA.cpp | 1393 ++ .../Cpp/DirectXTexUtil.cpp | 945 ++ .../Cpp/DirectXTexWIC.cpp | 1123 ++ .../DirectXTextureConverter/Cpp/DirectXTexp.h | 207 + .../DirectXTextureConverter/Cpp/Texconv.sln | 31 + .../Cpp/Texconv.vcxproj | 402 + .../Cpp/Texconv.vcxproj.filters | 102 + Samples/DirectXTextureConverter/Cpp/filters.h | 424 + Samples/DirectXTextureConverter/Cpp/scoped.h | 65 + .../DirectXTextureConverter/Cpp/texconv.cpp | 1244 ++ .../DirectXTextureConverter/Cpp/texconv.rc | 67 + Samples/DirectXTextureConverter/README.md | 38 + Samples/DynamicDPI/README.md | 36 + Samples/DynamicDPI/cpp/Application.cpp | 81 + Samples/DynamicDPI/cpp/Application.h | 11 + Samples/DynamicDPI/cpp/ColorToolbarIcons.ttf | Bin 0 -> 11532 bytes Samples/DynamicDPI/cpp/DeviceResources.cpp | 576 + Samples/DynamicDPI/cpp/DeviceResources.h | 129 + Samples/DynamicDPI/cpp/DirectXHelper.h | 59 + Samples/DynamicDPI/cpp/DynamicDPI.rc | Bin 0 -> 7238 bytes Samples/DynamicDPI/cpp/DynamicDPI.sln | 24 + Samples/DynamicDPI/cpp/DynamicDPI.vcxproj | 170 + .../DynamicDPI/cpp/DynamicDPI.vcxproj.filters | 143 + Samples/DynamicDPI/cpp/FontFileStream.cpp | 99 + Samples/DynamicDPI/cpp/FontFileStream.h | 50 + Samples/DynamicDPI/cpp/FontLoader.cpp | 214 + Samples/DynamicDPI/cpp/FontLoader.h | 79 + .../cpp/LinearEaseInOutAnimation.cpp | 91 + .../DynamicDPI/cpp/LinearEaseInOutAnimation.h | 34 + .../cpp/SampleCustomColorFontButton.cpp | 160 + .../cpp/SampleCustomColorFontButton.h | 56 + .../DynamicDPI/cpp/SampleDesktopWindow.cpp | 481 + Samples/DynamicDPI/cpp/SampleDesktopWindow.h | 123 + .../DynamicDPI/cpp/SampleDynamicDpiWindow.cpp | 412 + .../DynamicDPI/cpp/SampleDynamicDpiWindow.h | 63 + .../DynamicDPI/cpp/SampleElementAnimation.cpp | 60 + .../DynamicDPI/cpp/SampleElementAnimation.h | 29 + Samples/DynamicDPI/cpp/SampleElementBase.cpp | 72 + Samples/DynamicDPI/cpp/SampleElementBase.h | 60 + .../DynamicDPI/cpp/SampleElementTextBlock.cpp | 90 + .../DynamicDPI/cpp/SampleElementTextBlock.h | 32 + Samples/DynamicDPI/cpp/SampleEngine.cpp | 203 + Samples/DynamicDPI/cpp/SampleEngine.h | 54 + Samples/DynamicDPI/cpp/SampleHoverElement.cpp | 99 + Samples/DynamicDPI/cpp/SampleHoverElement.h | 32 + .../DynamicDPI/cpp/SampleMultiDpiImage.cpp | 205 + Samples/DynamicDPI/cpp/SampleMultiDpiImage.h | 39 + .../DynamicDPI/cpp/SampleRichEditControl.cpp | 716 ++ .../DynamicDPI/cpp/SampleRichEditControl.h | 90 + Samples/DynamicDPI/cpp/SlimRWLock.cpp | 37 + Samples/DynamicDPI/cpp/SlimRWLock.h | 23 + Samples/DynamicDPI/cpp/pch.cpp | 7 + Samples/DynamicDPI/cpp/pch.h | 44 + Samples/DynamicDPI/cpp/png100.png | Bin 0 -> 3721 bytes Samples/DynamicDPI/cpp/png125.png | Bin 0 -> 4664 bytes Samples/DynamicDPI/cpp/png150.png | Bin 0 -> 5917 bytes Samples/DynamicDPI/cpp/png200.png | Bin 0 -> 7014 bytes Samples/DynamicDPI/cpp/resource.h | Bin 0 -> 1524 bytes Samples/EapHostClientMethod/README.md | 62 + Samples/EapHostClientMethod/Readme.txt | 29 + Samples/EapHostClientMethod/cpp/DllMain.cpp | 242 + .../cpp/EapHostClientMethod.cpp | 3099 +++++ .../cpp/EapHostClientMethod.h | 578 + .../cpp/EapHostClientMethod.rc | 32 + .../cpp/EapHostClientMethodConfig.rc | 41 + .../cpp/EapHostClientMethodSample.def | 17 + .../cpp/EapHostClientMethodSample.sln | 26 + .../cpp/EapHostClientMethodSample.vcxproj | 101 + .../EapHostClientMethod/cpp/EapHostCommon.cpp | 658 + .../EapHostClientMethod/cpp/EapHostCommon.h | 260 + Samples/EapHostClientMethod/cpp/memory.cpp | 213 + Samples/EapHostClientMethod/cpp/memory.h | 54 + Samples/EapHostClientMethod/cpp/resource.h | 32 + Samples/EapHostServerMethod/README.md | 62 + Samples/EapHostServerMethod/Readme.txt | 29 + Samples/EapHostServerMethod/cpp/DllMain.cpp | 214 + .../EapHostServerMethod/cpp/EapHostCommon.cpp | 658 + .../EapHostServerMethod/cpp/EapHostCommon.h | 260 + .../cpp/EapHostServerMethod.cpp | 1803 +++ .../cpp/EapHostServerMethod.h | 527 + .../cpp/EapHostServerMethodConfig.rc | 45 + .../cpp/EapHostServerMethodSample.def | 9 + .../cpp/EapHostServerMethodSample.sln | 26 + .../cpp/EapHostServerMethodSample.vcxproj | 100 + Samples/EapHostServerMethod/cpp/memory.cpp | 213 + Samples/EapHostServerMethod/cpp/memory.h | 54 + Samples/EapHostServerMethod/cpp/resource.h | 25 + Samples/EapHostSupplicant/README.md | 57 + Samples/EapHostSupplicant/Readme.txt | 29 + .../EapHostSupplicant/cpp/EapHostCommon.cpp | 658 + Samples/EapHostSupplicant/cpp/EapHostCommon.h | 260 + Samples/EapHostSupplicant/cpp/EapHostConn.xml | 18 + .../cpp/EapHostSupplicant.cpp | 1880 +++ .../EapHostSupplicant/cpp/EapHostSupplicant.h | 284 + .../cpp/EapHostSupplicant.rc | 43 + .../cpp/EapHostSupplicantMain.cpp | 93 + .../cpp/EapHostSupplicantSample.sln | 26 + .../cpp/EapHostSupplicantSample.vcxproj | 99 + Samples/EapHostSupplicant/cpp/EapHostUser.xml | 19 + Samples/EapHostSupplicant/cpp/memory.cpp | 213 + Samples/EapHostSupplicant/cpp/memory.h | 54 + Samples/EapHostSupplicant/cpp/resource.h | 32 + Samples/FmapiVersionCheck/README.md | 65 + .../cpp/FmapiVersionCheck.cpp | 101 + .../cpp/FmapiVersionCheck.sln | 26 + .../cpp/FmapiVersionCheck.vcxproj | 155 + Samples/HangulDecomposition/README.md | 38 + .../cpp/HangulDecomposition.cpp | 86 + .../cpp/HangulDecomposition.sln | 26 + .../cpp/HangulDecomposition.vcxproj | 151 + .../cpp/HangulDecomposition.vcxproj.filters | 22 + Samples/HttpInternationalDomainName/README.md | 48 + .../cpp/IdnSample.cpp | 93 + .../cpp/IdnSample.sln | 20 + .../cpp/IdnSample.vcxproj | 92 + Samples/HttpSSLConfig/README.md | 54 + Samples/HttpSSLConfig/cpp/SslConfig.cpp | 833 ++ Samples/HttpSSLConfig/cpp/SslConfig.sln | 20 + Samples/HttpSSLConfig/cpp/SslConfig.vcxproj | 83 + Samples/Hyper-V/AppHealth/README.md | 53 + Samples/Hyper-V/AppHealth/cs/AppHealth.csproj | 57 + Samples/Hyper-V/AppHealth/cs/AppHealth.sln | 32 + .../Hyper-V/AppHealth/cs/AppHealthStatus.cs | 90 + Samples/Hyper-V/AppHealth/cs/Program.cs | 61 + Samples/Hyper-V/AppHealth/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/AppHealth/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/DynamicMemory/README.md | 89 + .../Hyper-V/DynamicMemory/cs/DynMem.csproj | 57 + Samples/Hyper-V/DynamicMemory/cs/DynMem.sln | 32 + Samples/Hyper-V/DynamicMemory/cs/Program.cs | 86 + Samples/Hyper-V/DynamicMemory/cs/Slp.cs | 155 + .../Hyper-V/DynamicMemory/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/DynamicMemory/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/EnhancedSession/README.md | 51 + .../Hyper-V/EnhancedSession/cs/Available.cs | 56 + Samples/Hyper-V/EnhancedSession/cs/Enable.cs | 67 + .../EnhancedSession/cs/EnhancedSession.csproj | 63 + .../EnhancedSession/cs/EnhancedSession.sln | 29 + Samples/Hyper-V/EnhancedSession/cs/Program.cs | 105 + .../EnhancedSession/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/EnhancedSession/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/FibreChannel/README.md | 195 + .../FibreChannel/cs/ConfigureWwnGenerator.cs | 109 + Samples/Hyper-V/FibreChannel/cs/CreateSan.cs | 114 + .../FibreChannel/cs/CreateVirtualFcPort.cs | 245 + Samples/Hyper-V/FibreChannel/cs/DeleteSan.cs | 73 + .../FibreChannel/cs/DeleteVirtualFcPort.cs | 148 + .../FibreChannel/cs/EnumerateFcPorts.cs | 231 + .../FibreChannel/cs/FibreChannel.csproj | 62 + .../Hyper-V/FibreChannel/cs/FibreChannel.sln | 32 + .../FibreChannel/cs/FibreChannelUtilities.cs | 350 + .../Hyper-V/FibreChannel/cs/ModifySanName.cs | 85 + .../Hyper-V/FibreChannel/cs/ModifySanPorts.cs | 126 + Samples/Hyper-V/FibreChannel/cs/Program.cs | 136 + .../Hyper-V/FibreChannel/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/FibreChannel/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Generation2VM/README.md | 51 + Samples/Hyper-V/Generation2VM/cs/CreateVM.cs | 63 + .../Generation2VM/cs/Generation2VM.csproj | 107 + .../Generation2VM/cs/Generation2VM.sln | 29 + .../Hyper-V/Generation2VM/cs/GetBootOrder.cs | 67 + .../cs/GetPauseAfterBootFailure.cs | 47 + .../Hyper-V/Generation2VM/cs/GetSecureBoot.cs | 48 + .../Generation2VM/cs/GetVMGeneration.cs | 49 + Samples/Hyper-V/Generation2VM/cs/Program.cs | 183 + .../Hyper-V/Generation2VM/cs/SetBootOrder.cs | 95 + .../Generation2VM/cs/SetBootProtocol.cs | 67 + .../cs/SetPauseAfterBootFailure.cs | 66 + .../Hyper-V/Generation2VM/cs/SetSecureBoot.cs | 65 + .../Hyper-V/Generation2VM/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Generation2VM/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/IntegrationServices/README.md | 61 + .../cs/GuestServiceInterface.cs | 226 + .../cs/IntegrationServices.csproj | 57 + .../cs/IntegrationServices.sln | 22 + .../Hyper-V/IntegrationServices/cs/Program.cs | 103 + .../IntegrationServices/cs/WmiUtilities.cs | 638 + .../Hyper-V/IntegrationServices/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Metrics/README.md | 137 + Samples/Hyper-V/Metrics/cs/ControlMetrics.cs | 143 + .../Hyper-V/Metrics/cs/EnumerateMetrics.cs | 180 + Samples/Hyper-V/Metrics/cs/MetricUtilities.cs | 221 + Samples/Hyper-V/Metrics/cs/Metrics.csproj | 65 + Samples/Hyper-V/Metrics/cs/Metrics.sln | 32 + .../Metrics/cs/ModifyServiceSettings.cs | 75 + Samples/Hyper-V/Metrics/cs/Program.cs | 98 + Samples/Hyper-V/Metrics/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Metrics/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Migration/README.md | 287 + Samples/Hyper-V/Migration/cs/Migration.csproj | 61 + Samples/Hyper-V/Migration/cs/Migration.sln | 32 + .../Hyper-V/Migration/cs/MigrationCommon.cs | 264 + .../Hyper-V/Migration/cs/MigrationSettings.cs | 296 + Samples/Hyper-V/Migration/cs/Program.cs | 280 + .../Hyper-V/Migration/cs/StorageMigration.cs | 165 + .../Migration/cs/VmAndStorageMigration.cs | 164 + Samples/Hyper-V/Migration/cs/VmMigration.cs | 594 + Samples/Hyper-V/Migration/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Migration/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Networking/README.md | 316 + .../Networking/cs/AddAndRemovePorts.cs | 260 + .../cs/AdvancedConnectionProperties.cs | 501 + .../Networking/cs/AdvancedSwitchProperties.cs | 232 + .../Networking/cs/ConnectVmToSwitch.cs | 329 + .../cs/ConnectVmUsingResourcePool.cs | 125 + Samples/Hyper-V/Networking/cs/CreateSwitch.cs | 341 + Samples/Hyper-V/Networking/cs/DeleteSwitch.cs | 77 + .../Hyper-V/Networking/cs/EnumerateSwitch.cs | 536 + .../Hyper-V/Networking/cs/ManageExtension.cs | 277 + Samples/Hyper-V/Networking/cs/ModifyPorts.cs | 164 + Samples/Hyper-V/Networking/cs/ModifySwitch.cs | 106 + .../Hyper-V/Networking/cs/Networking.csproj | 72 + Samples/Hyper-V/Networking/cs/Networking.sln | 32 + .../Networking/cs/NetworkingUtilities.cs | 550 + Samples/Hyper-V/Networking/cs/Program.cs | 139 + .../Networking/cs/SetRequiredFeature.cs | 186 + .../Networking/cs/SupportsTrunkMode.cs | 113 + .../cs/SyntheticEthernetPortProperties.cs | 151 + Samples/Hyper-V/Networking/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Networking/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Pvm/README.md | 144 + Samples/Hyper-V/Pvm/cs/FixUpUtilities.cs | 113 + Samples/Hyper-V/Pvm/cs/ImportUtilities.cs | 252 + Samples/Hyper-V/Pvm/cs/PVM.csproj | 100 + Samples/Hyper-V/Pvm/cs/PVM.sln | 32 + Samples/Hyper-V/Pvm/cs/Program.cs | 178 + Samples/Hyper-V/Pvm/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Pvm/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Replica/README.md | 239 + .../Hyper-V/Replica/cs/ManageReplication.cs | 461 + .../Replica/cs/ModifyServiceSettings.cs | 209 + Samples/Hyper-V/Replica/cs/Program.cs | 150 + Samples/Hyper-V/Replica/cs/Replica.csproj | 57 + Samples/Hyper-V/Replica/cs/Replica.sln | 32 + .../Hyper-V/Replica/cs/ReplicaUtilities.cs | 229 + Samples/Hyper-V/Replica/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Replica/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/ResourcePools/README.md | 245 + .../cs/MsvmResourceAllocationSettingData.cs | 402 + .../ResourcePools/cs/MsvmResourcePool.cs | 187 + .../MsvmResourcePoolConfigurationService.cs | 576 + .../cs/MsvmResourcePoolSettingData.cs | 189 + Samples/Hyper-V/ResourcePools/cs/Program.cs | 165 + .../ResourcePools/cs/ResourcePoolUtilities.cs | 208 + .../ResourcePools/cs/ResourcePools.csproj | 106 + .../ResourcePools/cs/ResourcePools.sln | 32 + .../ResourcePools/cs/ResourceUtilities.cs | 140 + .../Hyper-V/ResourcePools/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/ResourcePools/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/Storage/README.md | 585 + .../Storage/cpp/AddVirtualDiskParent.cpp | 91 + .../Hyper-V/Storage/cpp/AttachVirtualDisk.cpp | 166 + .../Hyper-V/Storage/cpp/CreateVirtualDisk.cpp | 116 + .../Storage/cpp/DeleteUserMetaData.cpp | 112 + .../Hyper-V/Storage/cpp/DetachVirtualDisk.cpp | 118 + .../Storage/cpp/EnumerateUserMetaData.cpp | 142 + ...GetAllAttachedVirtualDiskPhysicalPaths.cpp | 119 + .../cpp/GetStorageDependencyInformation.cpp | 185 + .../Hyper-V/Storage/cpp/GetUserMetaData.cpp | 147 + .../Storage/cpp/GetVirtualDiskInformation.cpp | 412 + .../Hyper-V/Storage/cpp/MergeVirtualDisk.cpp | 110 + .../Hyper-V/Storage/cpp/MirrorVirtualDisk.cpp | 198 + Samples/Hyper-V/Storage/cpp/Program.cpp | 294 + Samples/Hyper-V/Storage/cpp/RawIO.cpp | 274 + .../Hyper-V/Storage/cpp/ResizeVirtualDisk.cpp | 109 + .../Hyper-V/Storage/cpp/SetUserMetaData.cpp | 139 + .../Storage/cpp/SetVirtualDiskInformation.cpp | 229 + Samples/Hyper-V/Storage/cpp/Storage.h | 88 + Samples/Hyper-V/Storage/cpp/Storage.sln | 22 + Samples/Hyper-V/Storage/cpp/Storage.vcxproj | 108 + .../Storage/cpp/compactVirtualDisk.cpp | 110 + .../Storage/cs/AttachVirtualHardDisk.cs | 56 + .../Storage/cs/CompactVirtualHardDisk.cs | 59 + .../Storage/cs/ConvertVirtualHardDisk.cs | 67 + .../Storage/cs/CreateVirtualFloppyDisk.cs | 47 + .../Storage/cs/CreateVirtualHardDisk.cs | 75 + .../Storage/cs/DetachVirtualHardDisk.cs | 52 + .../Hyper-V/Storage/cs/GetVirtualHardDisk.cs | 124 + .../Storage/cs/MergeVirtualHardDisk.cs | 50 + Samples/Hyper-V/Storage/cs/Program.cs | 372 + .../Storage/cs/ResizeVirtualHardDisk.cs | 50 + .../Storage/cs/SetParentVirtualHardDisk.cs | 57 + .../Hyper-V/Storage/cs/SetVirtualHardDisk.cs | 67 + Samples/Hyper-V/Storage/cs/Storage.csproj | 76 + Samples/Hyper-V/Storage/cs/Storage.sln | 29 + .../Hyper-V/Storage/cs/StorageUtilities.cs | 37 + .../Storage/cs/ValidateVirtualHardDisk.cs | 48 + .../Storage/cs/VirtualHardDiskSettingData.cs | 367 + .../Storage/cs/VirtualHardDiskState.cs | 241 + Samples/Hyper-V/Storage/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/Storage/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/StorageQoS/README.md | 104 + Samples/Hyper-V/StorageQoS/cs/Program.cs | 97 + Samples/Hyper-V/StorageQoS/cs/StorageQoS.cs | 328 + .../Hyper-V/StorageQoS/cs/StorageQoS.csproj | 75 + Samples/Hyper-V/StorageQoS/cs/StorageQoS.sln | 38 + Samples/Hyper-V/StorageQoS/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/StorageQoS/desktop.ico | Bin 0 -> 1078 bytes Samples/Hyper-V/VmOperations/README.md | 81 + .../VmOperations/cs/LinuxAffinityUtilities.cs | 80 + Samples/Hyper-V/VmOperations/cs/Program.cs | 88 + .../VmOperations/cs/VmOperations.csproj | 100 + .../Hyper-V/VmOperations/cs/VmOperations.sln | 32 + .../Hyper-V/VmOperations/cs/WmiUtilities.cs | 638 + Samples/Hyper-V/VmOperations/desktop.ico | Bin 0 -> 1078 bytes Samples/IME/README.md | 85 + Samples/IME/cpp/SampleIME.sln | 26 + .../ActiveLanguageProfileNotifySink.cpp | 117 + .../cpp/SampleIME/BaseDictionaryEngine.cpp | 118 + .../IME/cpp/SampleIME/BaseDictionaryEngine.h | 41 + Samples/IME/cpp/SampleIME/BaseWindow.cpp | 662 + Samples/IME/cpp/SampleIME/BaseWindow.h | 160 + Samples/IME/cpp/SampleIME/ButtonWindow.cpp | 90 + Samples/IME/cpp/SampleIME/ButtonWindow.h | 27 + .../SampleIME/CandidateListUIPresenter.cpp | 1305 ++ .../cpp/SampleIME/CandidateListUIPresenter.h | 139 + Samples/IME/cpp/SampleIME/CandidateWindow.cpp | 1438 +++ Samples/IME/cpp/SampleIME/CandidateWindow.h | 118 + Samples/IME/cpp/SampleIME/Compartment.cpp | 343 + Samples/IME/cpp/SampleIME/Compartment.h | 61 + Samples/IME/cpp/SampleIME/Composition.cpp | 377 + .../SampleIME/CompositionProcessorEngine.cpp | 1940 +++ .../SampleIME/CompositionProcessorEngine.h | 195 + Samples/IME/cpp/SampleIME/Define.h | 48 + .../Dictionary/SampleIMESimplifiedQuanPin.txt | Bin 0 -> 1574528 bytes .../IME/cpp/SampleIME/DictionaryParser.cpp | 222 + Samples/IME/cpp/SampleIME/DictionaryParser.h | 50 + .../IME/cpp/SampleIME/DictionarySearch.cpp | 250 + Samples/IME/cpp/SampleIME/DictionarySearch.h | 76 + .../IME/cpp/SampleIME/DisplayAttribute.cpp | 115 + .../cpp/SampleIME/DisplayAttributeInfo.cpp | 227 + .../IME/cpp/SampleIME/DisplayAttributeInfo.h | 87 + .../SampleIME/DisplayAttributeProvider.cpp | 81 + Samples/IME/cpp/SampleIME/DisplayString.h | 43 + Samples/IME/cpp/SampleIME/DllMain.cpp | 54 + Samples/IME/cpp/SampleIME/EditSession.cpp | 99 + Samples/IME/cpp/SampleIME/EditSession.h | 33 + Samples/IME/cpp/SampleIME/EndComposition.cpp | 98 + .../SampleIME/EnumDisplayAttributeInfo.cpp | 226 + .../cpp/SampleIME/EnumDisplayAttributeInfo.h | 36 + .../IME/cpp/SampleIME/EnumTfCandidates.cpp | 146 + Samples/IME/cpp/SampleIME/EnumTfCandidates.h | 40 + Samples/IME/cpp/SampleIME/File.cpp | 245 + Samples/IME/cpp/SampleIME/File.h | 68 + Samples/IME/cpp/SampleIME/FileMapping.cpp | 87 + Samples/IME/cpp/SampleIME/FileMapping.h | 46 + .../cpp/SampleIME/FunctionProviderSink.cpp | 55 + .../SampleIME/GetTextExtentEditSession.cpp | 43 + .../cpp/SampleIME/GetTextExtentEditSession.h | 41 + Samples/IME/cpp/SampleIME/Globals.cpp | 460 + Samples/IME/cpp/SampleIME/Globals.h | 162 + Samples/IME/cpp/SampleIME/KeyEventSink.cpp | 457 + Samples/IME/cpp/SampleIME/KeyHandler.cpp | 635 + .../cpp/SampleIME/KeyHandlerEditSession.cpp | 46 + .../IME/cpp/SampleIME/KeyHandlerEditSession.h | 30 + .../IME/cpp/SampleIME/KeyStateCategory.cpp | 370 + Samples/IME/cpp/SampleIME/KeyStateCategory.h | 236 + Samples/IME/cpp/SampleIME/LanguageBar.cpp | 662 + Samples/IME/cpp/SampleIME/LanguageBar.h | 74 + Samples/IME/cpp/SampleIME/Private.h | 22 + Samples/IME/cpp/SampleIME/RegKey.cpp | 278 + Samples/IME/cpp/SampleIME/RegKey.h | 45 + Samples/IME/cpp/SampleIME/Register.cpp | 283 + Samples/IME/cpp/SampleIME/SampleIME.cpp | 432 + Samples/IME/cpp/SampleIME/SampleIME.def | 7 + Samples/IME/cpp/SampleIME/SampleIME.h | 248 + Samples/IME/cpp/SampleIME/SampleIME.rc | 122 + Samples/IME/cpp/SampleIME/SampleIME.vcxproj | 267 + .../cpp/SampleIME/SampleIME.vcxproj.filters | 301 + .../cpp/SampleIME/SampleIMEBaseStructure.cpp | 325 + .../cpp/SampleIME/SampleIMEBaseStructure.h | 271 + .../cpp/SampleIME/SampleIMEStructureArray.h | 80 + Samples/IME/cpp/SampleIME/ScrollBarWindow.cpp | 650 + Samples/IME/cpp/SampleIME/ScrollBarWindow.h | 220 + .../cpp/SampleIME/SearchCandidateProvider.cpp | 210 + .../cpp/SampleIME/SearchCandidateProvider.h | 50 + Samples/IME/cpp/SampleIME/Server.cpp | 285 + Samples/IME/cpp/SampleIME/ShadowWindow.cpp | 370 + Samples/IME/cpp/SampleIME/ShadowWindow.h | 47 + .../IME/cpp/SampleIME/StartComposition.cpp | 133 + .../cpp/SampleIME/TableDictionaryEngine.cpp | 120 + .../IME/cpp/SampleIME/TableDictionaryEngine.h | 30 + Samples/IME/cpp/SampleIME/TextEditSink.cpp | 134 + .../cpp/SampleIME/TfInputProcessorProfile.cpp | 54 + .../cpp/SampleIME/TfInputProcessorProfile.h | 22 + .../IME/cpp/SampleIME/TfTextLayoutSink.cpp | 220 + Samples/IME/cpp/SampleIME/TfTextLayoutSink.h | 46 + Samples/IME/cpp/SampleIME/ThreadFocusSink.cpp | 106 + .../IME/cpp/SampleIME/ThreadMgrEventSink.cpp | 178 + .../IME/cpp/SampleIME/TipCandidateList.cpp | 185 + Samples/IME/cpp/SampleIME/TipCandidateList.h | 43 + .../IME/cpp/SampleIME/TipCandidateString.cpp | 128 + .../IME/cpp/SampleIME/TipCandidateString.h | 39 + .../SampleIME/image/DoubleSingleByteOff.ico | Bin 0 -> 17542 bytes .../SampleIME/image/DoubleSingleByteOn.ico | Bin 0 -> 17542 bytes .../IME/cpp/SampleIME/image/ImeModeOff.ico | Bin 0 -> 39766 bytes Samples/IME/cpp/SampleIME/image/ImeModeOn.ico | Bin 0 -> 39766 bytes .../cpp/SampleIME/image/PunctuationOff.ico | Bin 0 -> 17542 bytes .../IME/cpp/SampleIME/image/PunctuationOn.ico | Bin 0 -> 17542 bytes Samples/IME/cpp/SampleIME/image/SampleIme.ico | Bin 0 -> 39766 bytes Samples/IME/cpp/SampleIME/resource.h | 29 + Samples/IME/cpp/SampleIME/stdafx.h | 9 + Samples/IdentifyInputSource/README.md | 43 + .../IdentifyInputSource/cpp/InputSource.cpp | 228 + .../IdentifyInputSource/cpp/InputSource.rc | 12 + .../IdentifyInputSource/cpp/InputSource.sln | 26 + .../cpp/InputSource.vcxproj | 142 + Samples/IdentifyInputSource/cpp/stdafx.cpp | 6 + Samples/IdentifyInputSource/cpp/stdafx.h | 40 + Samples/InjectTouchPointerInput/README.md | 43 + .../cpp/InjectTouch.cpp | 75 + .../cpp/InjectTouch.rc | 12 + .../cpp/InjectTouch.sln | 26 + .../cpp/InjectTouch.vcxproj | 142 + .../InjectTouchPointerInput/cpp/stdafx.cpp | 6 + Samples/InjectTouchPointerInput/cpp/stdafx.h | 32 + .../README.md | 36 + .../cpp/Application.cpp | 76 + .../cpp/Application.h | 11 + .../cpp/DeviceResources.cpp | 529 + .../cpp/DeviceResources.h | 122 + .../cpp/DirectXHelper.h | 59 + .../cpp/InteractionContextSample.cpp | 431 + .../cpp/InteractionContextSample.h | 78 + .../cpp/InteractionContextSample.sln | 24 + .../cpp/InteractionContextSample.vcxproj | 116 + .../cpp/SampleDesktopWindow.cpp | 528 + .../cpp/SampleDesktopWindow.h | 136 + .../cpp/pch.cpp | 8 + .../cpp/pch.h | 44 + Samples/LocationAwarenessEvents/README.md | 38 + .../cpp/LocationCallback.cpp | 143 + .../cpp/LocationCallback.h | 53 + .../cpp/LocationEvents.cpp | 85 + .../cpp/LocationEvents.sln | 22 + .../cpp/LocationEvents.vcxproj | 95 + .../LocationAwarenessEvents/cpp/Readme.txt | 48 + Samples/LocationSetDefault/README.md | 38 + .../cpp/LocationReportObject.cpp | 276 + .../cpp/LocationReportObject.h | 112 + Samples/LocationSetDefault/cpp/ReadMe.txt | 57 + .../LocationSetDefault/cpp/SetLocation.cpp | 452 + .../LocationSetDefault/cpp/SetLocation.sln | 22 + .../cpp/SetLocation.vcxproj | 95 + Samples/LocationSynchronousAccess/README.md | 38 + .../LocationSynchronousAccess/cpp/ReadMe.txt | 46 + .../cpp/SimpleLocation.cpp | 180 + .../cpp/SimpleLocation.sln | 22 + .../cpp/SimpleLocation.vcxproj | 91 + Samples/MSXML/DynamDom/README.md | 26 + Samples/MSXML/DynamDom/cpp/dynamDOM.cpp | 280 + Samples/MSXML/DynamDom/cpp/dynamdom.sln | 20 + Samples/MSXML/DynamDom/cpp/dynamdom.vcxproj | 74 + .../DynamDom/cpp/dynamdom.vcxproj.filters | 22 + Samples/MSXML/LoadDom/README.md | 26 + Samples/MSXML/LoadDom/cpp/loadDom.cpp | 94 + Samples/MSXML/LoadDom/cpp/loaddom.sln | 20 + Samples/MSXML/LoadDom/cpp/loaddom.vcxproj | 74 + .../MSXML/LoadDom/cpp/loaddom.vcxproj.filters | 22 + Samples/MSXML/LoadDom/cpp/stocks.xml | 24 + Samples/MSXML/QueryNodes/README.md | 26 + Samples/MSXML/QueryNodes/cpp/queryNodes.cpp | 166 + Samples/MSXML/QueryNodes/cpp/querynodes.sln | 20 + .../MSXML/QueryNodes/cpp/querynodes.vcxproj | 74 + .../QueryNodes/cpp/querynodes.vcxproj.filters | 22 + Samples/MSXML/QueryNodes/cpp/stocks.xml | 24 + Samples/MSXML/SaveDom/README.md | 26 + Samples/MSXML/SaveDom/cpp/saveDom.cpp | 105 + Samples/MSXML/SaveDom/cpp/savedom.sln | 20 + Samples/MSXML/SaveDom/cpp/savedom.vcxproj | 74 + .../MSXML/SaveDom/cpp/savedom.vcxproj.filters | 22 + Samples/MSXML/Xslt/README.md | 32 + Samples/MSXML/Xslt/cpp/XSLT.cpp | 155 + Samples/MSXML/Xslt/cpp/stocks.xml | 24 + Samples/MSXML/Xslt/cpp/stocks.xsl | 42 + Samples/MSXML/Xslt/cpp/xslt.sln | 20 + Samples/MSXML/Xslt/cpp/xslt.vcxproj | 74 + Samples/MSXML/Xslt/cpp/xslt.vcxproj.filters | 22 + Samples/Magnification/README.md | 91 + .../Fullscreen/FullscreenMagnifierSample.cpp | 412 + .../Fullscreen/FullscreenMagnifierSample.rc | Bin 0 -> 5788 bytes .../FullscreenMagnifierSample.vcxproj | 178 + .../Magnification/cpp/Fullscreen/resource.h | Bin 0 -> 1694 bytes Samples/Magnification/cpp/MagnifierSample.sln | 36 + .../cpp/Windowed/MagnifierSample.cpp | 343 + .../cpp/Windowed/MagnifierSample.vcxproj | 134 + Samples/ManagementInfrastructure/README.md | 32 + .../cpp/DecoupledHost/DecoupledHost.c | 288 + .../cpp/DecoupledHost/ReadMe.txt | 46 + .../cpp/DecoupledHost/dcuphost.vcxproj | 162 + .../cpp/Indication/CIMCmdlet/Indication.ps1 | 41 + .../cpp/Indication/ManagedClient/ReadMe.txt | 1 + .../cpp/Indication/NativeClient/ReadMe.txt | 1 + .../cpp/Indication/Provider/CIM_Indication.h | 357 + .../Indication/Provider/CIM_InstIndication.h | 458 + .../Provider/CIM_InstModification.h | 492 + .../Provider/MSFT_WindowsServiceStarted.c | 114 + .../Provider/MSFT_WindowsServiceStarted.h | 543 + .../Provider/MSFT_WindowsServiceStopped.c | 114 + .../Provider/MSFT_WindowsServiceStopped.h | 543 + .../cpp/Indication/Provider/Provider.DEF | 20 + .../cpp/Indication/Provider/WMIAdapter.c | 202 + .../cpp/Indication/Provider/WindowsService.c | 801 ++ .../cpp/Indication/Provider/WindowsService.h | 90 + .../cpp/Indication/Provider/module.c | 49 + .../cpp/Indication/Provider/schema.c | 2091 +++ .../cpp/Indication/Provider/svcind.vcxproj | 188 + .../cpp/Indication/ReadMe.txt | 151 + .../cpp/MSFT_Qualifiers.mof | 12 + .../WindowsProcess/WindowsProcess.cdxml | 212 + .../WindowsProcess.format.ps1xml | 90 + .../WindowsProcess/WindowsProcess.psd1 | 22 + .../WindowsProcess.types.ps1xml | 58 + .../cpp/Process/CIMCmdlet/Process.ps1 | 65 + .../cpp/Process/ManagedClient/Main.cs | 265 + .../ManagedClient/Properties/AssemblyInfo.cs | 27 + .../ManagedClient/SampleCimOperation.cs | 1064 ++ .../ManagedClient/SampleDotNetClient.csproj | 81 + .../cpp/Process/ManagedClient/TestObserver.cs | 154 + .../cpp/Process/NativeClient/CimClient.c | 116 + .../NativeClient/SampleNativeMiClient.vcxproj | 177 + .../SampleNativeMiClient.vcxproj.filters | 66 + .../cpp/Process/NativeClient/association.c | 265 + .../cpp/Process/NativeClient/create.c | 262 + .../cpp/Process/NativeClient/delete.c | 219 + .../cpp/Process/NativeClient/enumerate.c | 214 + .../cpp/Process/NativeClient/get.c | 220 + .../cpp/Process/NativeClient/invoke.c | 470 + .../cpp/Process/NativeClient/modify.c | 295 + .../cpp/Process/NativeClient/operations.c | 503 + .../cpp/Process/NativeClient/operations.h | 118 + .../cpp/Process/NativeClient/query.c | 208 + .../cpp/Process/NativeClient/reference.c | 250 + .../cpp/Process/NativeClient/subscribe.c | 272 + .../cpp/Process/NativeClient/utilities.c | 998 ++ .../cpp/Process/NativeClient/utilities.h | 38 + .../cpp/Process/Provider/CIM_ConcreteJob.h | 1293 ++ .../Provider/CIM_EnabledLogicalElement.h | 809 ++ .../cpp/Process/Provider/CIM_Error.h | 564 + .../cpp/Process/Provider/CIM_Job.h | 1036 ++ .../cpp/Process/Provider/CIM_LogicalElement.h | 513 + .../cpp/Process/Provider/CIM_ManagedElement.h | 260 + .../Provider/CIM_ManagedSystemElement.h | 512 + .../cpp/Process/Provider/CIM_Process.h | 1166 ++ .../cpp/Process/Provider/CIM_Service.h | 1165 ++ .../cpp/Process/Provider/CIM_ServiceProcess.h | 215 + .../cpp/Process/Provider/Helper.h | 20 + .../Process/Provider/MSFT_WindowsProcess.c | 209 + .../Process/Provider/MSFT_WindowsProcess.h | 1505 +++ .../Provider/MSFT_WindowsServiceProcess.c | 289 + .../Provider/MSFT_WindowsServiceProcess.h | 318 + .../cpp/Process/Provider/Provider.DEF | 19 + .../cpp/Process/Provider/WMIAdapter.c | 202 + .../cpp/Process/Provider/WindowsProcess.c | 855 ++ .../cpp/Process/Provider/WindowsProcess.h | 66 + .../Process/Provider/WindowsServiceProcess.c | 313 + .../Process/Provider/WindowsServiceProcess.h | 36 + .../cpp/Process/Provider/helper.c | 87 + .../cpp/Process/Provider/module.c | 44 + .../cpp/Process/Provider/process.vcxproj | 192 + .../cpp/Process/Provider/schema.c | 10513 ++++++++++++++++ .../cpp/Process/ReadMe.txt | 223 + .../ManagementInfrastructure/cpp/ReadMe.txt | 185 + .../ManagementInfrastructure/cpp/Sample.mof | 83 + .../WindowsService/WindowsService.cdxml | 129 + .../WindowsService.format.ps1xml | 47 + .../WindowsService/WindowsService.psd1 | 21 + .../cpp/Service/CIMCmdlet/Service.ps1 | 41 + .../cpp/Service/ManagedClient/ReadMe.txt | 1 + .../cpp/Service/NativeClient/ReadMe.txt | 1 + .../cpp/Service/Provider/CIM_ConcreteJob.h | 1293 ++ .../Provider/CIM_EnabledLogicalElement.h | 809 ++ .../cpp/Service/Provider/CIM_Error.h | 564 + .../cpp/Service/Provider/CIM_Job.h | 1036 ++ .../cpp/Service/Provider/CIM_LogicalElement.h | 513 + .../cpp/Service/Provider/CIM_ManagedElement.h | 260 + .../Provider/CIM_ManagedSystemElement.h | 512 + .../cpp/Service/Provider/CIM_Service.h | 1165 ++ .../Service/Provider/MSFT_WindowsService.c | 182 + .../Service/Provider/MSFT_WindowsService.h | 1252 ++ .../Provider/MSFT_WindowsServiceManager.c | 54 + .../Provider/MSFT_WindowsServiceManager.h | 243 + .../cpp/Service/Provider/Provider.DEF | 20 + .../cpp/Service/Provider/WMIAdapter.c | 202 + .../cpp/Service/Provider/WindowsService.c | 762 ++ .../cpp/Service/Provider/WindowsService.h | 48 + .../Service/Provider/WindowsServiceManager.c | 199 + .../Service/Provider/WindowsServiceManager.h | 14 + .../cpp/Service/Provider/module.c | 45 + .../cpp/Service/Provider/mui.rcconfig | 10 + .../cpp/Service/Provider/schema.c | 9282 ++++++++++++++ .../cpp/Service/Provider/service.vcxproj | 194 + .../cpp/Service/Provider/strings.rc | 413 + .../cpp/Service/Provider/util.c | 95 + .../cpp/Service/Provider/util.h | 55 + .../cpp/Service/ReadMe.txt | 183 + .../ManagementInfrastructure/cpp/misample.sln | 128 + .../MediaFoundationTransformDecoder/README.md | 50 + .../cpp/CAutoLock.cpp | 23 + .../cpp/CAutoLock.h | 15 + .../cpp/CHWMFT.cpp | 1087 ++ .../cpp/CHWMFT.h | 266 + .../cpp/CHWMFT_DebugLogger.cpp | 109 + .../cpp/CHWMFT_DebugLogger.h | 27 + .../cpp/CHWMFT_DecodeTask.cpp | 228 + .../cpp/CHWMFT_DecodeTask.h | 46 + .../cpp/CHWMFT_IMFAsyncCallback_Impl.cpp | 55 + .../CHWMFT_IMFMediaEventGenerator_Impl.cpp | 64 + .../cpp/CHWMFT_IMFShutdown_Impl.cpp | 59 + .../cpp/CHWMFT_IMFTransform_Impl.cpp | 1349 ++ .../cpp/CHWMFT_IUnknown_Impl.cpp | 82 + .../cpp/CSampleQueue.cpp | 307 + .../cpp/CSampleQueue.h | 60 + .../cpp/IMYMFT.h | 16 + .../cpp/MFHMFT.def | 7 + .../cpp/MFHMFT.sln | 20 + .../cpp/MFHMFT.vcxproj | 112 + .../cpp/dllmain.cpp | 579 + .../README.md | 75 + .../cpp/DebugHelper/DebugHelper.cpp | 250 + .../cpp/DebugHelper/DebugHelper.h | 86 + .../cpp/DebugHelper/DebugHelper.vcxproj | 140 + .../cpp/SHA/DLL/ComponentInfo.cpp | 281 + .../cpp/SHA/DLL/ComponentInfo.h | 76 + .../cpp/SHA/DLL/Messages.mc | 66 + .../cpp/SHA/DLL/SdkShaInfo.cpp | 108 + .../cpp/SHA/DLL/SdkShaInfo.def | 10 + .../cpp/SHA/DLL/SdkShaInfo.rc | 112 + .../cpp/SHA/DLL/SdkShaInfo.vcxproj | 312 + .../cpp/SHA/DLL/SdkShaInfoCF.H | 40 + .../cpp/SHA/DLL/SdkShaInfoCF.cpp | 101 + .../cpp/SHA/DLL/dllmain.cpp | 305 + .../cpp/SHA/DLL/dllmain.h | 27 + .../cpp/SHA/DLL/icon1.ico | Bin 0 -> 1078 bytes .../cpp/SHA/DLL/resource.h | 28 + .../cpp/SHA/EXE/Callback.cpp | 615 + .../cpp/SHA/EXE/Callback.h | 102 + .../cpp/SHA/EXE/Messages.mc | 64 + .../cpp/SHA/EXE/SdkSha.vcxproj | 217 + .../cpp/SHA/EXE/SdkShaModule.cpp | 150 + .../cpp/SHA/EXE/SdkShaModule.h | 61 + .../cpp/SHA/EXE/Sha.H | 30 + .../cpp/SHA/EXE/Sha.cpp | 285 + .../cpp/SHA/EXE/resource.h | 20 + .../cpp/SHV/SampleShv.cpp | 858 ++ .../cpp/SHV/SampleShv.h | 162 + .../cpp/SHV/SdkShv.cpp | 120 + .../cpp/SHV/SdkShv.def | 10 + .../cpp/SHV/SdkShv.rc | 100 + .../cpp/SHV/SdkShv.vcxproj | 272 + .../cpp/SHV/SdkShvCF.H | 40 + .../cpp/SHV/SdkShvCF.cpp | 101 + .../cpp/SHV/SdkShvModule.H | 67 + .../cpp/SHV/SdkShvModule.cpp | 463 + .../cpp/SHV/resource.h | 18 + .../cpp/SampleShvUi/Registration.cpp | 133 + .../cpp/SampleShvUi/Registration.h | 15 + .../cpp/SampleShvUi/Regutil.cpp | 399 + .../cpp/SampleShvUi/Regutil.h | 70 + .../cpp/SampleShvUi/resource.h | 36 + .../cpp/SampleShvUi/sampleshvui.vcxproj | 215 + .../cpp/SampleShvUi/sdkshv.ico | Bin 0 -> 1078 bytes .../cpp/SampleShvUi/shvui.cpp | 719 ++ .../cpp/SampleShvUi/shvui.h | 166 + .../cpp/SampleShvUi/shvui.rc | 94 + .../cpp/SampleShvUi/shvuicf.cpp | 173 + .../cpp/SampleShvUi/shvuicf.h | 91 + .../cpp/SdkCommon/SdkCommon.cpp | 654 + .../cpp/SdkCommon/SdkCommon.h | 169 + .../cpp/SdkCommon/SdkCommon.vcxproj | 144 + .../cpp/SdkSamples.sln | 85 + .../cpp/sdkqec/QEC.cpp | 248 + .../cpp/sdkqec/QEC.h | 31 + .../cpp/sdkqec/QecCallback.cpp | 309 + .../cpp/sdkqec/QecCallback.h | 91 + .../cpp/sdkqec/SdkQec.vcxproj | 210 + .../cpp/sdkqec/SdkQecModule.H | 60 + .../cpp/sdkqec/SdkQecModule.cpp | 156 + .../cpp/sdkqec/resource.h | 23 + Samples/NetworkCost/README.md | 52 + Samples/NetworkCost/Readme.txt | 65 + Samples/NetworkCost/cpp/NetCostEventSink.cpp | 372 + Samples/NetworkCost/cpp/NetCostEventSink.h | 70 + Samples/NetworkCost/cpp/NetCostSample.cpp | 604 + Samples/NetworkCost/cpp/NetCostSample.h | 78 + Samples/NetworkCost/cpp/NetCostSample.sln | 20 + Samples/NetworkCost/cpp/NetCostSample.vcxproj | 98 + .../cpp/NetCostSample.vcxproj.filters | 39 + Samples/NetworkCost/cpp/Utils.cpp | 578 + Samples/NetworkCost/cpp/Utils.h | 89 + Samples/ODataEntitiesAssociation/README.md | 34 + .../cs/AssemblyInfo.cs | 42 + .../cs/AssociationClient.csproj | 68 + .../cs/AssociationClient.sln | 20 + .../cs/OdataJsonRequest.cs | 235 + .../ODataEntitiesAssociation/cs/Program.cs | 577 + .../cs/setup/HostVMSystem.xml | 45 + .../cs/setup/ReadMe.txt | 7 + .../cs/setup/VMSystem.mof | 51 + .../cs/setup/VMSystem.psm1 | 482 + .../cs/setup/VMSystem.xml | 283 + .../cs/setup/Web.config | 24 + Samples/OpenDatabaseConnectivity/README.md | 27 + .../OpenDatabaseConnectivity/cpp/Readme.txt | 35 + .../OpenDatabaseConnectivity/cpp/odbcsql.cpp | 653 + .../OpenDatabaseConnectivity/cpp/odbcsql.sln | 26 + .../cpp/odbcsql.vcxproj | 173 + Samples/PackageManagerAddPackage/README.md | 81 + .../cpp/AddPackageSample.cpp | 90 + .../cpp/AddPackageSample.sln | 20 + .../cpp/AddPackageSample.vcxproj | 94 + .../PackageManagerAddPackage/cpp/README.txt | 39 + .../cs/AddPackageSample.cs | 80 + .../cs/AddPackageSample.csproj | 68 + .../cs/AddPackageSample.sln | 20 + .../PackageManagerAddPackage/cs/README.txt | 39 + .../PackageManagerAddPackage/cs/app.config | 3 + Samples/PackageManagerFindPackages/README.md | 83 + .../cpp/FindPackagesSample.cpp | 119 + .../cpp/FindPackagesSample.sln | 20 + .../cpp/FindPackagesSample.vcxproj | 94 + .../PackageManagerFindPackages/cpp/README.txt | 42 + .../cs/FindPackagesSample.cs | 108 + .../cs/FindPackagesSample.csproj | 68 + .../cs/FindPackagesSample.sln | 20 + .../PackageManagerFindPackages/cs/README.txt | 42 + .../PackageManagerFindPackages/cs/app.config | 3 + .../README.md | 85 + .../FindPackagesByNameAndPublisherSample.cpp | 133 + .../FindPackagesByNameAndPublisherSample.sln | 20 + ...ndPackagesByNameAndPublisherSample.vcxproj | 94 + .../cpp/README.txt | 47 + .../FindPackagesByNameAndPublisherSample.cs | 116 + ...indPackagesByNameAndPublisherSample.csproj | 72 + .../FindPackagesByNameAndPublisherSample.sln | 20 + .../cs/README.txt | 47 + .../cs/app.config | 3 + .../README.md | 85 + .../FindPackagesByUserSecurityIdSample.cpp | 81 + .../FindPackagesByUserSecurityIdSample.sln | 20 + ...FindPackagesByUserSecurityIdSample.vcxproj | 94 + .../cpp/README.txt | 44 + .../cs/FindPackagesByUserSecurityIdSample.cs | 84 + .../FindPackagesByUserSecurityIdSample.csproj | 68 + .../cs/FindPackagesByUserSecurityIdSample.sln | 20 + .../cs/README.txt | 44 + .../cs/app.config | 3 + .../README.md | 70 + .../FindPackagesWithPackageTypesSample.cpp | 72 + .../FindPackagesWithPackageTypesSample.sln | 20 + ...FindPackagesWithPackageTypesSample.vcxproj | 94 + .../cpp/README.txt | 43 + .../cs/FindPackagesWithPackageTypesSample.cs | 78 + .../FindPackagesWithPackageTypesSample.csproj | 68 + .../cs/FindPackagesWithPackageTypesSample.sln | 20 + .../cs/README.txt | 43 + .../cs/app.config | 3 + Samples/PackageManagerRemovePackage/README.md | 81 + .../cpp/README.txt | 39 + .../cpp/RemovePackageSample.cpp | 88 + .../cpp/RemovePackageSample.sln | 20 + .../cpp/RemovePackageSample.vcxproj | 95 + .../PackageManagerRemovePackage/cs/README.txt | 39 + .../cs/RemovePackageSample.cs | 78 + .../cs/RemovePackageSample.csproj | 68 + .../cs/RemovePackageSample.sln | 20 + .../PackageManagerRemovePackage/cs/app.config | 3 + Samples/PerMonitorDPIAware/README.md | 37 + .../cs/NativeHelpers/AssemblyInfo.cpp | 40 + .../cs/NativeHelpers/NativeHelpers.vcxproj | 107 + .../NativeHelpers.vcxproj.filters | 38 + .../cs/NativeHelpers/PerMonitorDPIHelpers.cpp | 75 + .../cs/NativeHelpers/PerMonitorDPIHelpers.h | 30 + .../cs/NativeHelpers/PerMonitorDPIWindow.cpp | 155 + .../cs/NativeHelpers/PerMonitorDPIWindow.h | 81 + .../cs/NativeHelpers/pch.cpp | 13 + .../PerMonitorDPIAware/cs/NativeHelpers/pch.h | 12 + .../cs/PerMonitorAwareWPFApplication.sln | 56 + .../cs/WpfApplication/App.config | 6 + .../cs/WpfApplication/App.xaml | 8 + .../cs/WpfApplication/App.xaml.cs | 17 + .../PerMonitorAwareWPFWindow.xaml | 49 + .../PerMonitorAwareWPFWindow.xaml.cs | 82 + .../WpfApplication/Properties/AssemblyInfo.cs | 58 + .../Properties/Resources.Designer.cs | 70 + .../WpfApplication/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 30 + .../Properties/Settings.settings | 7 + .../cs/WpfApplication/WpfApplication.csproj | 166 + Samples/PortableDeviceCOM/README.md | 45 + .../PortableDeviceCOM/cpp/CommonFunctions.h | 46 + .../cpp/ContentEnumeration.cpp | 311 + .../cpp/ContentProperties.cpp | 1215 ++ .../PortableDeviceCOM/cpp/ContentTransfer.cpp | 1644 +++ .../cpp/DeviceCapabilities.cpp | 1002 ++ .../cpp/DeviceEnumeration.cpp | 439 + .../PortableDeviceCOM/cpp/DeviceEvents.cpp | 142 + Samples/PortableDeviceCOM/cpp/ReadMe.txt | 53 + .../PortableDeviceCOM/cpp/WpdApiSample.cpp | 272 + .../PortableDeviceCOM/cpp/WpdApiSample.sln | 45 + .../cpp/WpdApiSample.vcxproj | 206 + Samples/PortableDeviceCOM/cpp/stdafx.h | 47 + Samples/PortableDeviceServices/README.md | 38 + .../cpp/CommonFunctions.h | 55 + .../cpp/ContentEnumeration.cpp | 83 + .../cpp/ContentProperties.cpp | 307 + Samples/PortableDeviceServices/cpp/ReadMe.txt | 50 + .../cpp/ServiceCapabilities.cpp | 455 + .../cpp/ServiceEnumeration.cpp | 464 + .../cpp/ServiceMethods.cpp | 499 + .../cpp/WpdServicesApiSample.cpp | 136 + .../cpp/WpdServicesApiSample.sln | 45 + .../cpp/WpdServicesApiSample.vcxproj | 210 + Samples/PortableDeviceServices/cpp/stdafx.h | 60 + .../AbstractSyntaxTreeProfiler/README.md | 47 + .../cs/AssemblyInfo.cs | Bin 0 -> 1870 bytes .../cs/PSProfiler.cs | 573 + .../cs/PSProfiler.csproj | 55 + .../cs/PSProfiler.sln | 20 + .../AbstractSyntaxTreeProfiler/cs/Readme.txt | 39 + .../PowerShell/ActivityGenerator/README.md | 63 + .../cs/ActivityGenerator.csproj | 64 + .../cs/ActivityGenerator.sln | 23 + .../ActivityGenerator/cs/AssemblyInfo.cs | 46 + .../ActivityGenerator/cs/Math.cdxml | 133 + .../ActivityGenerator/cs/New-PSActivity.ps1 | 89 + .../ActivityGenerator/cs/Program.cs | 68 + .../ActivityGenerator/cs/Readme.txt | 56 + .../PowerShell/ContainerActivity/README.md | 51 + .../ContainerActivity/cs/AssemblyInfo.cs | 46 + .../ContainerActivity/cs/ContainerActivity.cs | 99 + .../cs/ContainerActivity.csproj | 64 + .../cs/ContainerActivity.sln | 23 + .../cs/Invoke-ContainerActivity.ps1 | 63 + .../ContainerActivity/cs/Readme.txt | 52 + Samples/PowerShell/Debugger/README.md | 66 + Samples/PowerShell/Debugger/cs/App.config | 6 + .../PowerShell/Debugger/cs/AssemblyInfo.cs | 46 + .../PowerShell/Debugger/cs/DebuggerSample.cs | 315 + .../Debugger/cs/DebuggerSample.csproj | 63 + .../PowerShell/Debugger/cs/DebuggerSample.sln | 20 + Samples/PowerShell/Debugger/cs/Readme.txt | 55 + .../PowerShell/EventNotification/README.md | 51 + .../EventNotification/cs/AssemblyInfo.cs | Bin 0 -> 410 bytes .../EventNotification/cs/Events02.cs | 137 + .../EventNotification/cs/Events02.csproj | 60 + .../EventNotification/cs/Events02.sln | 20 + .../EventNotification/cs/Readme.txt | 40 + .../PowerShell/EventRegistration/README.md | 77 + .../EventRegistration/cs/AssemblyInfo.cs | Bin 0 -> 410 bytes .../EventRegistration/cs/Events01.cs | 116 + .../EventRegistration/cs/Events01.csproj | 62 + .../EventRegistration/cs/Events01.sln | 20 + .../EventRegistration/cs/Readme.txt | 56 + Samples/PowerShell/Host/Host01/README.md | 52 + .../PowerShell/Host/Host01/cs/AssemblyInfo.cs | Bin 0 -> 412 bytes Samples/PowerShell/Host/Host01/cs/Host01.cs | Bin 0 -> 7380 bytes .../PowerShell/Host/Host01/cs/Host01.csproj | 62 + Samples/PowerShell/Host/Host01/cs/Host01.sln | 20 + Samples/PowerShell/Host/Host01/cs/MyHost.cs | Bin 0 -> 12664 bytes Samples/PowerShell/Host/Host01/cs/Readme.txt | Bin 0 -> 3162 bytes Samples/PowerShell/Host/Host02/README.md | 49 + .../PowerShell/Host/Host02/cs/AssemblyInfo.cs | Bin 0 -> 412 bytes Samples/PowerShell/Host/Host02/cs/Host02.cs | Bin 0 -> 9104 bytes .../PowerShell/Host/Host02/cs/Host02.csproj | 51 + Samples/PowerShell/Host/Host02/cs/Host02.sln | 20 + Samples/PowerShell/Host/Host02/cs/MyHost.cs | Bin 0 -> 12830 bytes .../Host/Host02/cs/MyHostUserInterface.cs | Bin 0 -> 21308 bytes .../Host/Host02/cs/MyRawUserInterface.cs | Bin 0 -> 15972 bytes Samples/PowerShell/Host/Host02/cs/Readme.txt | Bin 0 -> 3402 bytes Samples/PowerShell/Host/Host03/README.md | 46 + .../PowerShell/Host/Host03/cs/AssemblyInfo.cs | Bin 0 -> 412 bytes Samples/PowerShell/Host/Host03/cs/Host03.cs | Bin 0 -> 25532 bytes .../PowerShell/Host/Host03/cs/Host03.csproj | 51 + Samples/PowerShell/Host/Host03/cs/Host03.sln | 20 + Samples/PowerShell/Host/Host03/cs/MyHost.cs | Bin 0 -> 13596 bytes .../Host/Host03/cs/MyHostUserInterface.cs | Bin 0 -> 35804 bytes .../Host/Host03/cs/MyRawUserInterface.cs | Bin 0 -> 17496 bytes Samples/PowerShell/Host/Host03/cs/Readme.txt | Bin 0 -> 3078 bytes Samples/PowerShell/Host/Host04/README.md | 53 + .../PowerShell/Host/Host04/cs/AssemblyInfo.cs | Bin 0 -> 412 bytes Samples/PowerShell/Host/Host04/cs/Host04.cs | Bin 0 -> 27922 bytes .../PowerShell/Host/Host04/cs/Host04.csproj | 52 + Samples/PowerShell/Host/Host04/cs/Host04.sln | 20 + .../Host/Host04/cs/HostUtilities.cs | 233 + Samples/PowerShell/Host/Host04/cs/MyHost.cs | Bin 0 -> 13990 bytes .../Host/Host04/cs/MyHostUserInterface.cs | Bin 0 -> 45112 bytes .../Host/Host04/cs/MyRawUserInterface.cs | Bin 0 -> 18796 bytes Samples/PowerShell/Host/Host04/cs/Readme.txt | Bin 0 -> 3740 bytes Samples/PowerShell/Host/Host05/README.md | 62 + .../PowerShell/Host/Host05/cs/AssemblyInfo.cs | Bin 0 -> 412 bytes Samples/PowerShell/Host/Host05/cs/Host05.cs | Bin 0 -> 29004 bytes .../PowerShell/Host/Host05/cs/Host05.csproj | 52 + Samples/PowerShell/Host/Host05/cs/Host05.sln | 20 + .../Host/Host05/cs/HostUtilities.cs | 224 + Samples/PowerShell/Host/Host05/cs/MyHost.cs | Bin 0 -> 17132 bytes .../Host/Host05/cs/MyHostUserInterface.cs | Bin 0 -> 46310 bytes .../Host/Host05/cs/MyRawUserInterface.cs | Bin 0 -> 18860 bytes Samples/PowerShell/Host/Host05/cs/Readme.txt | Bin 0 -> 4056 bytes Samples/PowerShell/Host/Host06/README.md | 55 + .../PowerShell/Host/Host06/cs/AssemblyInfo.cs | Bin 0 -> 412 bytes Samples/PowerShell/Host/Host06/cs/Host06.cs | Bin 0 -> 29544 bytes .../PowerShell/Host/Host06/cs/Host06.csproj | 53 + Samples/PowerShell/Host/Host06/cs/Host06.sln | 20 + .../Host/Host06/cs/HostUtilities.cs | 218 + Samples/PowerShell/Host/Host06/cs/MyHost.cs | Bin 0 -> 16506 bytes .../Host/Host06/cs/MyHostUserInterface.cs | Bin 0 -> 45976 bytes .../Host/Host06/cs/MyRawUserInterface.cs | Bin 0 -> 19118 bytes Samples/PowerShell/Host/Host06/cs/Readme.txt | Bin 0 -> 4272 bytes Samples/PowerShell/Host/Host06/cs/readline.cs | 484 + .../PowerShell/InitialSessionState/README.md | 53 + .../InitialSessionState/cs/AssemblyInfo.cs | Bin 0 -> 426 bytes .../InitialSessionState/cs/PowerShell01.cs | 219 + .../cs/PowerShell01.csproj | 64 + .../InitialSessionState/cs/PowerShell01.sln | 20 + .../InitialSessionState/cs/Readme.txt | 43 + Samples/PowerShell/JobSourceAdapter/README.md | 58 + .../JobSourceAdapter/cs/AssemblyInfo.cs | 46 + .../cs/JobSourceAdapter.csproj | 59 + .../JobSourceAdapter/cs/JobSourceAdapter.sln | 20 + .../cs/JobSourceAdapterSample.cs | 553 + .../PowerShell/JobSourceAdapter/cs/Readme.txt | 46 + .../PowerShell/Process/GetProcess01/README.md | 54 + .../Process/GetProcess01/cs/AssemblyInfo.cs | Bin 0 -> 422 bytes .../GetProcess01/cs/GetProcessSample01.cs | 126 + .../GetProcess01/cs/GetProcessSample01.csproj | 50 + .../GetProcess01/cs/GetProcessSample01.sln | 20 + .../Process/GetProcess01/cs/Readme.txt | Bin 0 -> 3084 bytes .../PowerShell/Process/GetProcess02/README.md | 47 + .../Process/GetProcess02/cs/AssemblyInfo.cs | Bin 0 -> 432 bytes .../GetProcess02/cs/GetProcessSample02.cs | 77 + .../GetProcess02/cs/GetProcessSample02.csproj | 50 + .../GetProcess02/cs/GetProcessSample02.sln | 20 + .../Process/GetProcess02/cs/Readme.txt | Bin 0 -> 3152 bytes .../PowerShell/Process/GetProcess03/README.md | 47 + .../Process/GetProcess03/cs/AssemblyInfo.cs | Bin 0 -> 436 bytes .../GetProcess03/cs/GetProcessSample03.cs | 79 + .../GetProcess03/cs/GetProcessSample03.csproj | 50 + .../GetProcess03/cs/GetProcessSample03.sln | 20 + .../Process/GetProcess03/cs/Readme.txt | Bin 0 -> 3242 bytes .../PowerShell/Process/GetProcess04/README.md | 48 + .../Process/GetProcess04/cs/AssemblyInfo.cs | Bin 0 -> 436 bytes .../GetProcess04/cs/GetProcessSample04.cs | 99 + .../GetProcess04/cs/GetProcessSample04.csproj | 50 + .../GetProcess04/cs/GetProcessSample04.sln | 20 + .../Process/GetProcess04/cs/Readme.txt | Bin 0 -> 3398 bytes .../PowerShell/Process/GetProcess05/README.md | 49 + .../Process/GetProcess05/cs/AssemblyInfo.cs | Bin 0 -> 422 bytes .../GetProcess05/cs/GetProcessSample05.cs | 412 + .../GetProcess05/cs/GetProcessSample05.csproj | 50 + .../GetProcess05/cs/GetProcessSample05.sln | 20 + .../Process/GetProcess05/cs/Readme.txt | Bin 0 -> 3544 bytes .../Process/StopProcessSample01/README.md | 54 + .../StopProcessSample01/cs/AssemblyInfo.cs | Bin 0 -> 440 bytes .../Process/StopProcessSample01/cs/Readme.txt | Bin 0 -> 4006 bytes .../cs/StopProcessSample01.cs | 213 + .../cs/StopProcessSample01.csproj | 50 + .../cs/StopProcessSample01.sln | 20 + .../Process/StopProcessSample02/README.md | 63 + .../StopProcessSample02/cs/AssemblyInfo.cs | Bin 0 -> 440 bytes .../Process/StopProcessSample02/cs/Readme.txt | Bin 0 -> 3922 bytes .../cs/StopProcessSample02.cs | 256 + .../cs/StopProcessSample02.csproj | 50 + .../cs/StopProcessSample02.sln | 20 + .../Process/StopProcessSample03/README.md | 57 + .../StopProcessSample03/cs/AssemblyInfo.cs | Bin 0 -> 440 bytes .../Process/StopProcessSample03/cs/Readme.txt | Bin 0 -> 3760 bytes .../cs/StopProcessSample03.cs | 299 + .../cs/StopProcessSample03.csproj | 50 + .../cs/StopProcessSample03.sln | 20 + .../Process/StopProcessSample04/README.md | 66 + .../StopProcessSample04/cs/AssemblyInfo.cs | Bin 0 -> 440 bytes .../Process/StopProcessSample04/cs/Readme.txt | Bin 0 -> 4298 bytes .../cs/StopProcessSample04.cs | 436 + .../cs/StopProcessSample04.csproj | 50 + .../cs/StopProcessSample04.sln | 20 + .../Provider/AccessDBProvider01/README.md | 48 + .../cs/AccessDBProviderSample01.cs | 31 + .../cs/AccessDBProviderSample01.csproj | 50 + .../cs/AccessDBProviderSample01.sln | 20 + .../AccessDBProvider01/cs/AssemblyInfo.cs | Bin 0 -> 466 bytes .../Provider/AccessDBProvider01/cs/Readme.txt | Bin 0 -> 3004 bytes .../Provider/AccessDBProvider02/README.md | 50 + .../cs/AccessDBProviderSample02.cs | 155 + .../cs/AccessDBProviderSample02.csproj | 50 + .../cs/AccessDBProviderSample02.sln | 20 + .../AccessDBProvider02/cs/AssemblyInfo.cs | Bin 0 -> 466 bytes .../Provider/AccessDBProvider02/cs/Readme.txt | Bin 0 -> 3272 bytes .../Provider/AccessDBProvider03/README.md | 54 + .../cs/AccessDBProviderSample03.cs | 977 ++ .../cs/AccessDBProviderSample03.csproj | 50 + .../cs/AccessDBProviderSample03.sln | 20 + .../AccessDBProvider03/cs/AssemblyInfo.cs | Bin 0 -> 466 bytes .../Provider/AccessDBProvider03/cs/Readme.txt | Bin 0 -> 3558 bytes .../Provider/AccessDBProvider04/README.md | 55 + .../cs/AccessDBProviderSample04.cs | 1636 +++ .../cs/AccessDBProviderSample04.csproj | 50 + .../cs/AccessDBProviderSample04.sln | 20 + .../AccessDBProvider04/cs/AssemblyInfo.cs | Bin 0 -> 466 bytes .../Provider/AccessDBProvider04/cs/Readme.txt | Bin 0 -> 3676 bytes .../Provider/AccessDBProvider05/README.md | 57 + .../cs/AccessDBProviderSample05.cs | 1961 +++ .../cs/AccessDBProviderSample05.csproj | 50 + .../cs/AccessDBProviderSample05.sln | 20 + .../AccessDBProvider05/cs/AssemblyInfo.cs | Bin 0 -> 466 bytes .../Provider/AccessDBProvider05/cs/Readme.txt | Bin 0 -> 3978 bytes .../Provider/AccessDBProvider06/README.md | 59 + .../cs/AccessDBProviderSample06.cs | 2400 ++++ .../cs/AccessDBProviderSample06.csproj | 50 + .../cs/AccessDBProviderSample06.sln | 20 + .../AccessDBProvider06/cs/AssemblyInfo.cs | Bin 0 -> 466 bytes .../Provider/AccessDBProvider06/cs/Readme.txt | Bin 0 -> 4018 bytes .../Remoting/RemoteRunspace01/README.md | 50 + .../RemoteRunspace01/cs/AssemblyInfo.cs | Bin 0 -> 424 bytes .../Remoting/RemoteRunspace01/cs/Readme.txt | 42 + .../RemoteRunspace01/cs/RemoteRunspace01.cs | 69 + .../cs/RemoteRunspace01.csproj | 56 + .../RemoteRunspace01/cs/RemoteRunspace01.sln | 20 + .../Remoting/RemoteRunspacePool01/README.md | 50 + .../RemoteRunspacePool01/cs/AssemblyInfo.cs | Bin 0 -> 440 bytes .../RemoteRunspacePool01/cs/Readme.txt | 42 + .../cs/RemoteRunspacePool01.cs | 98 + .../cs/RemoteRunspacePool01.csproj | 56 + .../cs/RemoteRunspacePool01.sln | 20 + .../RemotingDisconnectConnect01/README.md | 59 + .../cs/AssemblyInfo.cs | 46 + .../RemotingDisconnectConnect01/cs/Readme.txt | 62 + .../cs/RemotingDisconnectConnect01.cs | 221 + .../cs/RemotingDisconnectConnect01.csproj | 72 + .../cs/RemotingDisconnectConnect01.sln | 20 + .../PowerShell/Runspace/Runspace01/README.md | 48 + .../Runspace/Runspace01/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace01/cs/Readme.txt | 38 + .../Runspace/Runspace01/cs/Runspace01.cs | Bin 0 -> 5196 bytes .../Runspace/Runspace01/cs/Runspace01.csproj | 49 + .../Runspace/Runspace01/cs/Runspace01.sln | 20 + .../PowerShell/Runspace/Runspace02/README.md | 48 + .../Runspace/Runspace02/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace02/cs/Readme.txt | Bin 0 -> 2996 bytes .../Runspace/Runspace02/cs/Runspace02.cs | Bin 0 -> 6228 bytes .../Runspace/Runspace02/cs/Runspace02.csproj | 49 + .../Runspace/Runspace02/cs/Runspace02.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace03/README.md | 49 + .../Runspace/Runspace03/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace03/cs/Readme.txt | 39 + .../Runspace/Runspace03/cs/Runspace03.cs | Bin 0 -> 7932 bytes .../Runspace/Runspace03/cs/Runspace03.csproj | 49 + .../Runspace/Runspace03/cs/Runspace03.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace04/README.md | 50 + .../Runspace/Runspace04/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace04/cs/Readme.txt | 44 + .../Runspace/Runspace04/cs/Runspace04.cs | Bin 0 -> 7324 bytes .../Runspace/Runspace04/cs/Runspace04.csproj | 49 + .../Runspace/Runspace04/cs/Runspace04.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace05/README.md | 49 + .../Runspace/Runspace05/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace05/cs/Readme.txt | 42 + .../Runspace/Runspace05/cs/Runspace05.cs | 87 + .../Runspace/Runspace05/cs/Runspace05.csproj | 49 + .../Runspace/Runspace05/cs/Runspace05.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace06/README.md | 49 + .../Runspace/Runspace06/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace06/cs/Readme.txt | 44 + .../Runspace/Runspace06/cs/Runspace06.cs | 86 + .../Runspace/Runspace06/cs/Runspace06.csproj | 49 + .../Runspace/Runspace06/cs/Runspace06.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace07/README.md | 49 + .../Runspace/Runspace07/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace07/cs/Readme.txt | 42 + .../Runspace/Runspace07/cs/Runspace07.cs | Bin 0 -> 8920 bytes .../Runspace/Runspace07/cs/Runspace07.csproj | 49 + .../Runspace/Runspace07/cs/Runspace07.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace08/README.md | 49 + .../Runspace/Runspace08/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace08/cs/Readme.txt | 41 + .../Runspace/Runspace08/cs/Runspace08.cs | Bin 0 -> 7372 bytes .../Runspace/Runspace08/cs/Runspace08.csproj | 49 + .../Runspace/Runspace08/cs/Runspace08.sln | Bin 0 -> 1814 bytes .../PowerShell/Runspace/Runspace09/README.md | 49 + .../Runspace/Runspace09/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace09/cs/Readme.txt | 40 + .../Runspace/Runspace09/cs/Runspace09.cs | Bin 0 -> 10304 bytes .../Runspace/Runspace09/cs/Runspace09.csproj | 49 + .../Runspace/Runspace09/cs/Runspace09.sln | 20 + .../PowerShell/Runspace/Runspace10/README.md | 54 + .../Runspace/Runspace10/cs/AssemblyInfo.cs | Bin 0 -> 404 bytes .../Runspace/Runspace10/cs/Readme.txt | 40 + .../Runspace/Runspace10/cs/Runspace10.cs | 119 + .../Runspace/Runspace10/cs/Runspace10.csproj | 49 + .../Runspace/Runspace10/cs/Runspace10.sln | 20 + .../PowerShell/Runspace/Runspace11/README.md | 50 + .../Runspace/Runspace11/cs/AssemblyInfo.cs | Bin 0 -> 400 bytes .../Runspace/Runspace11/cs/Readme.txt | 43 + .../Runspace/Runspace11/cs/Runspace11.cs | 204 + .../Runspace/Runspace11/cs/Runspace11.csproj | 49 + .../Runspace/Runspace11/cs/Runspace11.sln | 20 + Samples/PowerShell/RunspacePool/README.md | 50 + .../RunspacePool/cs/AssemblyInfo.cs | Bin 0 -> 426 bytes .../RunspacePool/cs/PowerShell02.cs | 96 + .../RunspacePool/cs/PowerShell02.csproj | 64 + .../RunspacePool/cs/PowerShell02.sln | 20 + Samples/PowerShell/RunspacePool/cs/Readme.txt | 41 + .../SelectObject/SelectObject01/README.md | 44 + .../SelectObject01/cs/AssemblyInfo.cs | Bin 0 -> 624 bytes .../cs/ObjectCommandComparer.cs | Bin 0 -> 14148 bytes .../SelectObject/SelectObject01/cs/Readme.txt | 41 + .../SelectObject01/cs/SelectObject01.cs | Bin 0 -> 37926 bytes .../SelectObject01/cs/SelectObject01.csproj | 50 + .../SelectObject01/cs/SelectObject01.sln | 20 + .../SelectString/SelectStrCommand/README.md | 47 + .../SelectStrCommand/cs/AssemblyInfo.cs | Bin 0 -> 440 bytes .../SelectStrCommand/cs/Readme.txt | 43 + .../cs/SelectStrCommandSample.cs | 606 + .../cs/SelectStrCommandSample.csproj | 52 + .../cs/SelectStrCommandSample.sln | 20 + .../Serialization/Serialization01/README.md | 47 + .../Serialization01/cs/AssemblyInfo.cs | Bin 0 -> 420 bytes .../Serialization01/cs/Readme.txt | 40 + .../Serialization01/cs/Serialization01.cs | 93 + .../Serialization01/cs/Serialization01.csproj | 54 + .../Serialization01/cs/Serialization01.sln | 20 + .../cs/Serialization01.types.ps1xml | 33 + .../Serialization/Serialization02/README.md | 45 + .../Serialization02/cs/AssemblyInfo.cs | Bin 0 -> 420 bytes .../Serialization02/cs/Readme.txt | 41 + .../Serialization02/cs/Serialization02.cs | 97 + .../Serialization02/cs/Serialization02.csproj | 54 + .../Serialization02/cs/Serialization02.sln | 20 + .../cs/Serialization02.types.ps1xml | 33 + .../Serialization/Serialization03/README.md | 45 + .../Serialization03/cs/AssemblyInfo.cs | Bin 0 -> 420 bytes .../Serialization03/cs/Readme.txt | 40 + .../Serialization03/cs/Serialization03.cs | 215 + .../Serialization03/cs/Serialization03.csproj | 54 + .../Serialization03/cs/Serialization03.sln | 20 + .../cs/Serialization03.types.ps1xml | 50 + .../SupportsPaging/SupportsPaging01/README.md | 55 + .../SupportsPaging01/cs/AssemblyInfo.cs | 21 + .../SupportsPaging01/cs/GetNumbersCommand.cs | 90 + .../SupportsPaging01/cs/Readme.txt | 57 + .../SupportsPaging01/cs/Result.cs | 36 + .../cs/SupportsPaging01.csproj | 59 + .../SupportsPaging01/cs/SupportsPaging01.ps1 | Bin 0 -> 6064 bytes .../SupportsPaging01/cs/SupportsPaging01.sln | 20 + .../TemplateProvider01/README.md | 61 + .../TemplateProvider01/cs/AssemblyInfo.cs | Bin 0 -> 446 bytes .../TemplateProvider01/cs/Readme.txt | 44 + .../cs/TemplateProvider01.cs | 2594 ++++ .../cs/TemplateProvider01.csproj | 48 + .../cs/TemplateProvider01.sln | 20 + .../Transactions/Transactions01/README.md | 45 + .../cs/AddTransactedCommentCommand.cs | 101 + .../Transactions01/cs/AssemblyInfo.cs | 36 + .../cs/ClearTransactedCommentCommand.cs | 66 + .../cs/GetTransactedCommentCommand.cs | 66 + .../Transactions/Transactions01/cs/Readme.txt | 51 + .../Transactions01/cs/TransactedComment.cs | 251 + .../cs/TransactedComment.csproj | 70 + .../Transactions01/cs/TransactedComment.sln | 19 + .../ActivityControllerExtensibility/README.md | 48 + ...tivityControllerExtensibilitySample.csproj | 89 + .../ActivityControllerExtensibilitySample.sln | 20 + .../cs/AssemblyInfo.cs | 46 + .../cs/CustomWorkflowEndpointSetup.ps1 | 28 + .../cs/Program.cs | 77 + .../cs/Readme.txt | 40 + .../cs/SampleActivityController.cs | 185 + .../cs/SampleConfigurationProvider.cs | 40 + .../cs/SampleWorkflow.xaml | 39 + .../SimpleExtensibility/README.md | 45 + .../SimpleExtensibility/cs/AssemblyInfo.cs | 46 + .../SimpleExtensibility/cs/Program.cs | 79 + .../SimpleExtensibility/cs/Readme.txt | 39 + .../cs/SampleConfigurationProvider.cs | 54 + .../cs/SampleWorkflow.xaml | 37 + .../cs/SimpleExtensibilitySample.csproj | 85 + .../cs/SimpleExtensibilitySample.sln | 20 + Samples/RoleBasedPlugins/README.md | 53 + Samples/RoleBasedPlugins/cs/AssemblyInfo.cs | 42 + .../cs/CustomAuthorization.cs | 64 + Samples/RoleBasedPlugins/cs/NativeMethods.cs | 32 + Samples/RoleBasedPlugins/cs/Rbac.xsd | 68 + .../RoleBasedPlugins/cs/RbacConfiguration.cs | 180 + Samples/RoleBasedPlugins/cs/RbacGroup.cs | 173 + Samples/RoleBasedPlugins/cs/RbacQuota.cs | 49 + Samples/RoleBasedPlugins/cs/RbacSystem.cs | 253 + Samples/RoleBasedPlugins/cs/RbacUser.cs | 184 + .../RoleBasedPlugins/cs/Resources.Designer.cs | 83 + Samples/RoleBasedPlugins/cs/Resources.resx | 124 + .../cs/RoleBasedPlugins.csproj | 90 + .../RoleBasedPlugins/cs/RoleBasedPlugins.sln | 20 + .../cs/SessionConfiguration.cs | 88 + Samples/RoleBasedPlugins/cs/Utils.cs | 75 + .../cs/WindowsIdentityHelper.cs | 82 + .../cs/setup/InstallModata.ps1 | 11 + .../cs/setup/Microsoft.Management.Odata.svc | 1 + .../cs/setup/RbacConfiguration.xml | 51 + Samples/RoleBasedPlugins/cs/setup/Readme.txt | 9 + Samples/RoleBasedPlugins/cs/setup/Schema.mof | 180 + Samples/RoleBasedPlugins/cs/setup/Schema.xml | 163 + .../cs/setup/SetupEndpoint.ps1 | 39 + .../cs/setup/SetupIISConfig.ps1 | 348 + Samples/RoleBasedPlugins/cs/setup/Web.config | 34 + .../RoutingandRemoteAccessService/README.md | 70 + .../RoutingandRemoteAccessService/Readme.txt | 76 + .../cpp/InterfaceConfiguration.cpp | 853 ++ .../cpp/InterfaceConfiguration.h | 86 + .../cpp/MprApiSample.sln | 26 + .../cpp/MprApiSample.vcxproj | 98 + .../cpp/ServerConfiguration.cpp | 576 + .../cpp/ServerConfiguration.h | 52 + .../cpp/Utils.cpp | 1010 ++ .../RoutingandRemoteAccessService/cpp/Utils.h | 257 + .../cpp/VpnConnection.cpp | 254 + .../cpp/VpnConnection.h | 33 + .../cpp/main.cpp | 116 + Samples/ScanRestorableFiles/README.md | 59 + .../cpp/ScanRestorableFiles.cpp | 178 + .../cpp/ScanRestorableFiles.sln | 26 + .../cpp/ScanRestorableFiles.vcxproj | 155 + .../CipherEncryptionDecryption/README.md | 43 + .../cpp/CipherEncryptionDecryption.cpp | 714 ++ .../cpp/CipherEncryptionDecryption.sln | 20 + .../cpp/CipherEncryptionDecryption.vcxproj | 76 + Samples/Security/CodeSigning/README.md | 36 + .../Security/CodeSigning/cpp/codesigning.cpp | 349 + .../Security/CodeSigning/cpp/codesigning.sln | 20 + .../CodeSigning/cpp/codesigning.vcxproj | 85 + .../cpp/codesigning.vcxproj.filters | 22 + Samples/Security/DataProtection/README.md | 38 + .../DataProtection/cpp/DataProtection.cpp | 399 + .../DataProtection/cpp/DataProtection.sln | 20 + .../DataProtection/cpp/DataProtection.vcxproj | 76 + Samples/Security/DhOakleyGroup1/README.md | 38 + .../DhOakleyGroup1/cpp/DhOakleyGroup1.cpp | 651 + .../DhOakleyGroup1/cpp/DhOakleyGroup1.sln | 20 + .../DhOakleyGroup1/cpp/DhOakleyGroup1.vcxproj | 76 + .../Security/EffectiveAccessRights/README.md | 34 + .../EffectiveAccessRights/cs/App.config | 6 + .../cs/AvailableCentralPolicies.cs | 338 + .../cs/EffectiveAccess.cs | 959 ++ .../cs/EffectiveAccess.csproj | 75 + .../cs/EffectiveAccess.sln | 20 + .../cs/GlobalSuppressions.cs | Bin 0 -> 20300 bytes .../EffectiveAccessRights/cs/Groups.cs | 157 + .../EffectiveAccessRights/cs/Program.cs | 454 + .../cs/Properties/AssemblyInfo.cs | 36 + .../cs/SecurityAttribute.cs | 555 + .../cs/Utility/Helper.cs | 121 + .../cs/Utility/SafeHandleEx.cs | 334 + .../cs/Utility/TokenPrivilege.cs | 833 ++ .../EffectiveAccessRights/cs/Utility/Win32.cs | 138 + .../GetAppliedCentralPolicies/README.md | 38 + .../cpp/GetAppliedCentralPolicies.cpp | 606 + .../cpp/GetAppliedCentralPolicies.sln | 20 + .../cpp/GetAppliedCentralPolicies.vcxproj | 89 + .../GetAppliedCentralPolicies.vcxproj.filters | 22 + Samples/Security/HashComputation/README.md | 38 + .../HashComputation/cpp/HashComputation.cpp | 199 + .../HashComputation/cpp/HashComputation.sln | 20 + .../cpp/HashComputation.vcxproj | 76 + Samples/Security/KeyDerivation/README.md | 38 + .../KeyDerivation/cpp/KeyDerivation.cpp | 217 + .../KeyDerivation/cpp/KeyDerivation.h | 188 + .../KeyDerivation/cpp/KeyDerivation.sln | 20 + .../KeyDerivation/cpp/KeyDerivation.vcxproj | 79 + .../KeyDerivationWithPersistedKeys/README.md | 38 + .../cpp/KeyDerivationWithPersistedKeys.cpp | 832 ++ .../cpp/KeyDerivationWithPersistedKeys.sln | 20 + .../KeyDerivationWithPersistedKeys.vcxproj | 76 + .../Security/RSACapiAndCngInterop/README.md | 43 + .../cpp/RSACapiAndCngInterop.cpp | 1347 ++ .../cpp/RSACapiAndCngInterop.sln | 20 + .../cpp/RSACapiAndCngInterop.vcxproj | 76 + .../Security/RandomNumGeneration/README.md | 38 + .../cpp/RandomNumGeneration.cpp | 89 + .../cpp/RandomNumGeneration.sln | 20 + .../cpp/RandomNumGeneration.vcxproj | 76 + Samples/Security/ResourceAttributes/README.md | 41 + .../cpp/ResourceAttributesSample.cpp | 1460 +++ .../cpp/ResourceAttributesSample.h | 168 + .../cpp/ResourceAttributesSample.sln | 20 + .../cpp/ResourceAttributesSample.vcxproj | 93 + .../ResourceAttributesSample.vcxproj.filters | 27 + .../Security/SHA1-HMACComputation/README.md | 38 + .../cpp/HmacComputation.cpp | 260 + .../cpp/HmacComputation.sln | 20 + .../cpp/HmacComputation.vcxproj | 76 + .../README.md | 38 + .../cpp/SecretAgreementWithPersistedKeys.cpp | 576 + .../cpp/SecretAgreementWithPersistedKeys.sln | 20 + .../SecretAgreementWithPersistedKeys.vcxproj | 76 + .../SignHashAndVerifySignature/README.md | 38 + .../cpp/SignHashAndVerifySignature.cpp | 636 + .../cpp/SignHashAndVerifySignature.sln | 20 + .../cpp/SignHashAndVerifySignature.vcxproj | 76 + .../SignHashWithPersistedKeys/README.md | 38 + .../cpp/SignHashWithPersistedKeys.cpp | 653 + .../cpp/SignHashWithPersistedKeys.sln | 20 + .../cpp/SignHashWithPersistedKeys.vcxproj | 76 + .../Security/StrongKeyProtection/README.md | 38 + .../cpp/StrongKeyProtection.cpp | 323 + .../cpp/StrongKeyProtection.sln | 20 + .../cpp/StrongKeyProtection.vcxproj | 76 + Samples/ServerEssentialsDashboard/README.md | 62 + .../cs/WSSDashboard.sln | 192 + .../StandaloneXml/Image.png | Bin 0 -> 764 bytes .../WindowsUpdatesHomePageTask.home | 11 + .../StandaloneXml/readme.txt | 17 + .../XmlInDll/Properties/AssemblyInfo.cs | 42 + .../XmlInDll/WindowsUpdates.home | 17 + .../XmlInDll/WindowsUpdates.home.Designer.cs | 97 + .../XmlInDll/WindowsUpdates.home.resx | 135 + .../XmlInDll/WindowsUpdatesTask.csproj | 92 + .../XmlInDll/pics/Windows_update_icon.png | Bin 0 -> 727 bytes .../cs/WSSHomepageCommunity/Sample.home | 10 + .../cs/WSSHomepageCommunity/readme.txt | 17 + .../CancellableAsyncQuickStatus.cs | 62 + .../CancellableAsyncQuickStatus.csproj | 61 + .../Properties/AssemblyInfo.cs | 42 + .../CustomQuickStatus.home | 14 + .../Properties/AssemblyInfo.cs | 42 + .../SyncQuickStatus/Resources.Designer.cs | 90 + .../SyncQuickStatus/Resources.resx | 134 + .../SyncQuickStatus/SyncQuickStatus.cs | 43 + .../SyncQuickStatus/SyncQuickStatus.csproj | 73 + .../MyBusinessObject.cs | 37 + .../Properties/AssemblyInfo.cs | 41 + .../SubTabAddinConfig.addin | 51 + .../WSSSubTabListviewSample/SubTabDetails.cs | 29 + .../SubTabListColumns.cs | 30 + .../SubTabListGroupings.cs | 32 + .../SubTabListProvider.cs | 70 + .../cs/WSSSubTabListviewSample/SubTabPage.cs | 39 + .../cs/WSSSubTabListviewSample/SubTabTasks.cs | 37 + .../WSSSubTabListviewSample.csproj | 128 + .../MyControlHost.Designer.cs | 67 + .../MyCustomWPFControl/MyControlHost.cs | 25 + .../MyCustomWPFControl/MyControlHost.resx | 125 + .../MyCustomWPFControl.xaml | 157 + .../MyCustomWPFControl.xaml.cs | 48 + .../Properties/AssemblyInfo.cs | 41 + .../SubTabAddinConfig.addin | 51 + .../cs/WSSSubTabWPFSample/SubTabPage.cs | 33 + .../WSSSubTabWPFSample.csproj | 157 + .../MyCustomWinformControl.cs | 100 + .../MyCustomWinformControl.designer.cs | 192 + .../Properties/AssemblyInfo.cs | 41 + .../SubTabAddinConfig.addin | 50 + .../cs/WSSSubTabWinFormsSample/SubTabPage.cs | 33 + .../WSSSubTabWinFormsSample.csproj | 127 + .../cs/WSSTabExtenderSample/ListAdorner.cs | 30 + .../cs/WSSTabExtenderSample/PageAdorner.cs | 97 + .../Properties/AssemblyInfo.cs | 39 + .../TabExtensionAddinConfig.addin | 44 + .../WSSTabExtenderSample.csproj | 117 + .../ListViewSubTab/ListViewSubTab.csproj | 121 + .../ListViewSubTab/MyBusinessObject.cs | 37 + .../ListViewSubTab/Properties/AssemblyInfo.cs | 41 + .../ListViewSubTab/SubTabDetails.cs | 29 + .../ListViewSubTab/SubTabListColumns.cs | 30 + .../ListViewSubTab/SubTabListGroupings.cs | 32 + .../ListViewSubTab/SubTabListProvider.cs | 70 + .../ListViewSubTab/SubTabPage.cs | 39 + .../ListViewSubTab/SubTabTasks.cs | 37 + .../TopLevelTab/Properties/AssemblyInfo.cs | 39 + .../TopLevelTab/Resources/GenericIcon.ico | Bin 0 -> 4286 bytes .../TopLevelTab/TopLevelAddinConfig.addin | 41 + .../TopLevelTab/TopLevelTab.cs | 37 + .../TopLevelTab/TopLevelTab.csproj | 125 + .../WSSTopLevelTabListView.Designer.cs | 79 + .../TopLevelTab/WSSTopLevelTabListView.resx | 129 + .../ListViewSubTab/ListViewSubTab.csproj | 121 + .../ListViewSubTab/MyBusinessObject.cs | 37 + .../ListViewSubTab/Properties/AssemblyInfo.cs | 41 + .../ListViewSubTab/SubTabDetails.cs | 29 + .../ListViewSubTab/SubTabListColumns.cs | 30 + .../ListViewSubTab/SubTabListGroupings.cs | 32 + .../ListViewSubTab/SubTabListProvider.cs | 70 + .../ListViewSubTab/SubTabPage.cs | 39 + .../ListViewSubTab/SubTabTasks.cs | 37 + .../TopLevelTab/CustomSubTabPage.cs | 28 + .../MyCustomWinformControl.Designer.cs | 192 + .../MyCustomWinformControl.cs | 100 + .../TopLevelTab/Properties/AssemblyInfo.cs | 39 + .../TopLevelTab/Resources/GenericIcon.ico | Bin 0 -> 4286 bytes .../TopLevelTab/TopLevelAddinConfig.addin | 41 + .../TopLevelTab/TopLevelTab.cs | 35 + .../TopLevelTab/TopLevelTab.csproj | 133 + .../WSSTopLevelTwoSubTabsSample.Designer.cs | 79 + .../WSSTopLevelTwoSubTabsSample.resx | 129 + .../MyControlHost.Designer.cs | 67 + .../MyCustomWPFControl/MyControlHost.cs | 25 + .../MyCustomWPFControl/MyControlHost.resx | 125 + .../MyCustomWPFControl.xaml | 157 + .../MyCustomWPFControl.xaml.cs | 48 + .../Properties/AssemblyInfo.cs | 41 + .../Resources/GenericIcon.ico | Bin 0 -> 4286 bytes .../cs/WSSTopLevelTabWPFSample/SubTabPage.cs | 28 + .../cs/WSSTopLevelTabWPFSample/TopLevelTab.cs | 40 + .../TopLevelTabResources.Designer.cs | 79 + .../TopLevelTabResources.resx | 129 + .../WSSTopLevelTabWPFSample.addin | 42 + .../WSSTopLevelTabWPFSample.csproj | 202 + .../MyCustomWinformControl.Designer.cs | 192 + .../MyCustomWinformControl.cs | 100 + .../Properties/AssemblyInfo.cs | 41 + .../Resources/GenericIcon.ico | Bin 0 -> 4286 bytes .../SubTabPage.cs | 28 + .../TopLevelAddinConfig.addin | 43 + .../TopLevelTab.Designer.cs | 79 + .../TopLevelTab.cs | 36 + .../TopLevelTab.resx | 129 + .../WSSTopLevelTabWinformsSample.csproj | 139 + .../cs/WSSUserExtensions/Sample.proplink | 4 + .../cs/WSSUserExtensions/readme.txt | 19 + Samples/ServerEssentialsHostedEmail/README.md | 52 + .../ContosoCustomAction.csproj | 59 + .../ContosoCustomAction/CustomAction.config | 37 + .../cs/ContosoCustomAction/CustomAction.cs | 86 + .../Properties/AssemblyInfo.cs | 39 + .../cs/ContosoHostedEmail.sln | 122 + ...ContosoHostedEmailAdaptorLogMonitor.csproj | 62 + .../Program.cs | 53 + .../Properties/AssemblyInfo.cs | 39 + .../ContosoMockEmailService/AccountManager.cs | 297 + .../AccountManagerExceptions.cs | 43 + .../cs/ContosoMockEmailService/CSVUtil.cs | 80 + .../cs/ContosoMockEmailService/Constants.cs | 67 + .../ContosoMockEmailService.csproj | 103 + .../ContosoMockEmailService/DataConverter.cs | 40 + .../EmailServiceConfiguration.cs | 92 + .../cs/ContosoMockEmailService/LogManager.cs | 92 + .../MockEmailService.cs | 325 + .../MockEmailServiceConfiguration.cs | 323 + .../MockEmailServiceConfiguration.xml | 67 + .../MockEmailServiceConfiguration.xsd | 92 + .../Properties/AssemblyInfo.cs | 39 + .../Resources.Designer.cs | 120 + .../cs/ContosoMockEmailService/Resources.resx | 135 + .../cs/HomepageAddin/ContosoHostedEmail.home | 25 + .../ContosoHostedEmail.home.Designer.cs | 125 + .../ContosoHostedEmail.home.resx | 144 + .../ContosoHostedEmailHomepageAddin.csproj | 99 + .../cs/HomepageAddin/LearnMore.png | Bin 0 -> 851 bytes .../cs/HomepageAddin/Logo.png | Bin 0 -> 3410 bytes .../HomepageAddin/Properties/AssemblyInfo.cs | 39 + .../Wssg.HostedEmailConfigureWizard.vbs | 7 + .../Adaptor/ContosoHostedEmailAdaptor.cs | 239 + .../Adaptor/CredentialManager.cs | 54 + .../ContosoDistributionGroupAddin.addin | 8 + .../AddinFiles/ContosoHostedEmail.addin | 43 + .../AddinFiles/ContosoTopLevelDashboard.addin | 43 + .../ContosoUserPropertyAdvanced.addin | 43 + .../ContosoHostedEmailAddin.csproj | 177 + .../DGSelectCtrl.Designer.cs | 108 + .../DistributionGroup/DGSelectCtrl.cs | 100 + .../DistributionGroup/DGSelectCtrl.resx | 302 + .../DistributionGroupAdorner.cs | 107 + .../DistributionGroupControl.Designer.cs | 129 + .../DistributionGroupControl.cs | 193 + .../DistributionGroupControl.resx | 422 + .../Properties/AssemblyInfo.cs | 42 + .../cs/HostedEmailAddin/Resources.Designer.cs | 366 + .../cs/HostedEmailAddin/Resources.resx | 224 + .../Schema/HosteEmailAddinSchema.xsd | 108 + .../cs/HostedEmailAddin/UI/AdvancedPage.cs | 44 + .../cs/HostedEmailAddin/UI/GlobalTasks.cs | 113 + .../SampleAddinForm.Designer.cs | 342 + .../SampleAddinForm.cs | 316 + .../SampleAddinForm.resx | 1055 ++ .../UserPropertyAdvancedForm.Designer.cs | 150 + .../UserPropertyAdvancedForm.cs | 130 + .../UserPropertyAdvancedForm.resx | 431 + .../cs/HostedEmailAddin/UI/SubTabPage.cs | 26 + .../cs/HostedEmailAddin/UI/TopLevelTab.cs | 32 + .../cs/HostedEmailAddin/UI/UIConstants.cs | 23 + .../Wssg.HostedEmailConfigureWizard.Reset.vbs | 7 + Samples/ServerEssentialsLaunchpad/README.md | 39 + .../cs/Content.launchpad | 59 + .../cs/Launchpad.Designer.cs | 78 + .../cs/Launchpad.resx | 128 + .../cs/Properties/AssemblyInfo.cs | 43 + .../cs/WSSLaunchpadAddinWithResource.csproj | 76 + .../cs/WSSLaunchpadAddinWithResource.sln | 27 + Samples/ServerEssentialsProvider/README.md | 50 + .../cs/ChatProvider.sln | 62 + .../ChatProvider.ObjectModel.csproj | 117 + .../ChatReceivedEventArgs.cs | 24 + .../ChatProvider.ObjectModel/IProvider.cs | 22 + .../IProviderCallback.cs | 17 + .../ChatProvider.ObjectModel/ObjectModel.cs | 97 + .../ObjectModelImplementation.cs | 83 + .../Properties/AssemblyInfo.cs | 42 + .../ChatProvider/ChatProvider.csproj | 119 + .../cs/ChatProvider/ChatProvider/Program.cs | 29 + .../ChatProvider/Properties/AssemblyInfo.cs | 42 + .../ChatProvider/ChatProvider/ProviderCore.cs | 48 + .../ChatProvider/ProviderService.cs | 60 + .../cs/ChatProvider/ChatProvider/app.config | 8 + .../cs/ChatWindow/App.xaml | 13 + .../cs/ChatWindow/App.xaml.cs | 22 + .../cs/ChatWindow/ChatWindow.csproj | 116 + .../cs/ChatWindow/MainWindow.xaml | 32 + .../cs/ChatWindow/MainWindow.xaml.cs | 92 + .../cs/ChatWindow/Properties/AssemblyInfo.cs | 61 + .../Properties/Resources.Designer.cs | 69 + .../cs/ChatWindow/Properties/Resources.resx | 122 + .../Properties/Settings.Designer.cs | 32 + .../ChatWindow/Properties/Settings.settings | 12 + Samples/ServerManagerDeploymentCIM/README.md | 41 + .../cs/AddRoleSample.cs | 112 + .../cs/AssemblyInfo.cs | 36 + .../cs/GetRoleSample.cs | 306 + .../ServerManagerDeploymentCIM/cs/Program.cs | 59 + .../cs/RemoveRoleSample.cs | 113 + .../cs/SMDSampleApp.csproj | 87 + .../cs/SMDSampleApp.sln | 37 + Samples/SpellCheckerClient/README.md | 45 + Samples/SpellCheckerClient/cpp/Readme.txt | 119 + .../cpp/SampleSpellingClient.cpp | 211 + .../cpp/SampleSpellingClient.sln | 38 + .../cpp/SampleSpellingClient.vcxproj | 168 + .../cpp/SampleSpellingClient.vcxproj.filters | 15 + Samples/SpellCheckerClient/cpp/commands.h | 137 + .../cpp/onspellcheckerchanged.h | 103 + Samples/SpellCheckerClient/cpp/resources.rc | 10 + Samples/SpellCheckerClient/cpp/spellprint.h | 353 + Samples/SpellCheckerClient/cpp/util.h | 67 + Samples/SpellCheckerProvider/README.md | 58 + .../cpp/EnumSpellingError.cpp | 84 + .../cpp/EnumSpellingError.h | 50 + Samples/SpellCheckerProvider/cpp/EnumString.h | 42 + .../cpp/OptionDescription.cpp | 87 + .../cpp/OptionDescription.h | 46 + Samples/SpellCheckerProvider/cpp/Readme.txt | 63 + .../cpp/SampleSpellCheckProvider.cpp | 155 + .../cpp/SampleSpellCheckProvider.h | 57 + .../cpp/SampleSpellCheckProviderFactory.cpp | 54 + .../cpp/SampleSpellCheckProviderFactory.h | 38 + .../cpp/SampleSpellChecker.def | 7 + .../cpp/SampleSpellChecker.idl | 74 + .../cpp/SampleSpellChecker.rgs | 35 + .../cpp/SampleSpellCheckerModule.cpp | 49 + .../cpp/SampleSpellingProvider.sln | 38 + .../cpp/SampleSpellingProvider.vcxproj | 281 + .../SampleSpellingProvider.vcxproj.filters | 34 + .../cpp/SpellingError.cpp | 69 + .../SpellCheckerProvider/cpp/SpellingError.h | 52 + .../SpellCheckerProvider/cpp/currentuser.reg | 16 + .../SpellCheckerProvider/cpp/engineoptions.h | 222 + .../SpellCheckerProvider/cpp/localmachine.reg | 16 + Samples/SpellCheckerProvider/cpp/resource.h | 17 + Samples/SpellCheckerProvider/cpp/resources.rc | 26 + .../SpellCheckerProvider/cpp/sampleengine.h | 373 + Samples/SpellCheckerProvider/cpp/util.h | 60 + Samples/StorageManagement/README.md | 62 + .../cpp/StorageManagementApplication.cpp | 1775 +++ .../cpp/StorageManagementApplication.h | 183 + .../cpp/StorageManagementApplication.sln | 26 + .../cpp/StorageManagementApplication.vcxproj | 162 + ...orageManagementApplication.vcxproj.filters | 27 + Samples/TimerCoalescence/README.md | 50 + Samples/TimerCoalescence/cpp/timer.cpp | 351 + Samples/TimerCoalescence/cpp/timer.rc | 12 + Samples/TimerCoalescence/cpp/timer.sln | 26 + Samples/TimerCoalescence/cpp/timer.vcxproj | 136 + Samples/TouchHitTesting/README.md | 48 + Samples/TouchHitTesting/cpp/D2DDriver.cpp | 336 + Samples/TouchHitTesting/cpp/D2DDriver.h | 80 + Samples/TouchHitTesting/cpp/Program.cpp | 546 + Samples/TouchHitTesting/cpp/Program.h | 100 + Samples/TouchHitTesting/cpp/Shape.cpp | 316 + Samples/TouchHitTesting/cpp/Shape.h | 165 + .../cpp/ShapesPuzzleDesktop.cpp | 247 + .../cpp/ShapesPuzzleDesktop.rc | 67 + .../cpp/ShapesPuzzleDesktop.sln | 26 + .../cpp/ShapesPuzzleDesktop.vcxproj | 157 + Samples/TouchHitTesting/cpp/resource.h | 27 + .../TouchInputDirectManipulation/README.md | 52 + .../cpp/AppWindow.cpp | 1327 ++ .../cpp/AppWindow.h | 100 + .../cpp/Circles.png | Bin 0 -> 14122 bytes .../cpp/DirectManipulationSample.cpp | 22 + .../cpp/DirectManipulationSample.h | 5 + .../cpp/DirectManipulationSample.ico | Bin 0 -> 2998 bytes .../cpp/DirectManipulationSample.rc | Bin 0 -> 7270 bytes .../cpp/DirectManipulationSample.sln | 26 + .../cpp/DirectManipulationSample.vcxproj | 175 + .../DirectManipulationSample.vcxproj.filters | 70 + .../cpp/Resource.h | 33 + .../cpp/ViewportEventHandler.cpp | 83 + .../cpp/ViewportEventHandler.h | 35 + .../cpp/small.ico | Bin 0 -> 2998 bytes .../cpp/stdafx.cpp | 10 + .../TouchInputDirectManipulation/cpp/stdafx.h | 24 + .../cpp/targetver.h | 10 + Samples/UIAutomationCleanShutdown/README.md | 54 + Samples/UIAutomationCleanShutdown/ReadMe.txt | 70 + .../cpp/UiaCleanShutdown.sln | 39 + .../UiaCleanShutdownControl.cpp | 273 + .../UiaCleanShutdownControl.def | 4 + .../UiaCleanShutdownControl.h | 38 + .../UiaCleanShutdownControl.vcxproj | 167 + .../UiaCleanShutdownControl/UiaProvider.cpp | 189 + .../cpp/UiaCleanShutdownControl/UiaProvider.h | 42 + .../UiaCleanShutdownHost.cpp | 172 + .../UiaCleanShutdownHost.exe.manifest | 21 + .../UiaCleanShutdownHost.rc | 10 + .../UiaCleanShutdownHost.vcxproj | 166 + Samples/UIAutomationDocumentClient/README.md | 64 + Samples/UIAutomationDocumentClient/ReadMe.txt | 55 + .../cpp/UiaDocumentClient.cpp | 1240 ++ .../cpp/UiaDocumentClient.sln | 26 + .../cpp/UiaDocumentClient.vcxproj | 155 + .../UIAutomationDocumentProvider/README.md | 54 + .../UIAutomationDocumentProvider/ReadMe.txt | 62 + .../cpp/AnnotatedTextControl.cpp | 1252 ++ .../cpp/AnnotatedTextControl.h | 139 + .../cpp/AnnotationProvider.cpp | 420 + .../cpp/AnnotationProvider.h | 56 + .../cpp/FrameProvider.cpp | 310 + .../cpp/FrameProvider.h | 46 + .../cpp/TextAreaProvider.cpp | 1506 +++ .../cpp/TextAreaProvider.h | 103 + .../cpp/UiaDocumentProvider.cpp | 116 + .../cpp/UiaDocumentProvider.sln | 26 + .../cpp/UiaDocumentProvider.vcxproj | 165 + ...UiaDocumentProviderSample.partial.manifest | 15 + .../UIAutomationFragmentProvider/README.md | 58 + .../cpp/CustomControl.cpp | 571 + .../cpp/CustomControl.h | 119 + .../cpp/ListItemProvider.cpp | 391 + .../cpp/ListProvider.cpp | 345 + .../cpp/UIAFragmentProvider.cpp | 117 + .../cpp/UIAFragmentProvider.ico | Bin 0 -> 23558 bytes .../cpp/UIAFragmentProvider.rc | 22 + .../cpp/UIAFragmentProvider.sln | 26 + .../cpp/UIAFragmentProvider.vcxproj | 201 + .../cpp/UIAProviders.h | 131 + .../cpp/resource.h | 11 + .../UIAutomationFragmentProvider/cpp/stdafx.h | 38 + Samples/UIAutomationSimpleProvider/README.md | 54 + .../cpp/Control.cpp | 196 + .../UIAutomationSimpleProvider/cpp/Control.h | 40 + .../cpp/Provider.cpp | 146 + .../UIAutomationSimpleProvider/cpp/Provider.h | 45 + .../cpp/UiaSimpleProvider.cpp | 67 + .../cpp/UiaSimpleProvider.ico | Bin 0 -> 23558 bytes .../cpp/UiaSimpleProvider.rc | 14 + .../cpp/UiaSimpleProvider.sln | 26 + .../cpp/UiaSimpleProvider.vcxproj | 209 + .../UIAutomationSimpleProvider/cpp/resource.h | 8 + .../UIAutomationSimpleProvider/cpp/stdafx.h | 40 + Samples/UPnPDimmerService/README.md | 55 + Samples/UPnPDimmerService/Readme.txt | 49 + Samples/UPnPDimmerService/cpp/DeviceDll.cpp | 92 + Samples/UPnPDimmerService/cpp/DeviceDll.def | 7 + Samples/UPnPDimmerService/cpp/DeviceDll.h | 14 + .../UPnPDimmerService/cpp/DimmerDevice.idl | 84 + .../UPnPDimmerService/cpp/DimmerDeviceDCO.cpp | 213 + .../UPnPDimmerService/cpp/DimmerDeviceDCO.h | 67 + .../UPnPDimmerService/cpp/DimmerDeviceDCO.rgs | 25 + .../UPnPDimmerService/cpp/DimmerService.cpp | 281 + Samples/UPnPDimmerService/cpp/DimmerService.h | 66 + .../cpp/UPNPSampleDimmerDevice.rc | 42 + .../cpp/UPNPSampleDimmerDevice.sln | 26 + .../cpp/UPNPSampleDimmerDevice.vcxproj | 223 + Samples/UPnPDimmerService/cpp/resource.h | 15 + Samples/UPnPGenericUCP/README.md | 58 + Samples/UPnPGenericUCP/Readme.txt | 101 + Samples/UPnPGenericUCP/cpp/CAsyncResult.h | 128 + Samples/UPnPGenericUCP/cpp/GenericUCPDlg.cpp | 3059 +++++ Samples/UPnPGenericUCP/cpp/SCPDDisplay.cpp | 92 + Samples/UPnPGenericUCP/cpp/SCPDDisplay.h | 55 + Samples/UPnPGenericUCP/cpp/Util.cpp | 512 + Samples/UPnPGenericUCP/cpp/Util.h | 24 + Samples/UPnPGenericUCP/cpp/deviceprop.cpp | 222 + Samples/UPnPGenericUCP/cpp/deviceprop.h | 71 + Samples/UPnPGenericUCP/cpp/devtype.txt | 5 + Samples/UPnPGenericUCP/cpp/genericucp.cpp | 86 + Samples/UPnPGenericUCP/cpp/genericucp.h | 61 + Samples/UPnPGenericUCP/cpp/genericucp.ico | Bin 0 -> 766 bytes Samples/UPnPGenericUCP/cpp/genericucp.rc | 286 + Samples/UPnPGenericUCP/cpp/genericucp.sln | 26 + Samples/UPnPGenericUCP/cpp/genericucp.vcxproj | 200 + Samples/UPnPGenericUCP/cpp/genericucpdlg.h | 200 + Samples/UPnPGenericUCP/cpp/resource.h | 69 + Samples/UPnPGenericUCP/cpp/stdafx.cpp | 16 + Samples/UPnPGenericUCP/cpp/stdafx.h | 45 + Samples/UPnPGenericUCP/cpp/udn.txt | 4 + Samples/UPnPRegisterDevice/README.md | 70 + Samples/UPnPRegisterDevice/Readme.txt | 70 + .../cpp/DimmerDevice-Desc.xml | 36 + .../cpp/DimmerPresentation.htm | 204 + .../cpp/DimmingService_SCPD.xml | 77 + Samples/UPnPRegisterDevice/cpp/RegDevice.cpp | 359 + Samples/UPnPRegisterDevice/cpp/RegDevice.sln | 26 + .../UPnPRegisterDevice/cpp/RegDevice.vcxproj | 182 + Samples/VShadowVolumeShadowCopy/README.md | 91 + Samples/VShadowVolumeShadowCopy/cpp/break.cpp | 354 + .../VShadowVolumeShadowCopy/cpp/create.cpp | 283 + .../VShadowVolumeShadowCopy/cpp/delete.cpp | 221 + .../VShadowVolumeShadowCopy/cpp/expose.cpp | 187 + Samples/VShadowVolumeShadowCopy/cpp/macros.h | 169 + Samples/VShadowVolumeShadowCopy/cpp/query.cpp | 154 + .../VShadowVolumeShadowCopy/cpp/readme.html | 852 ++ .../VShadowVolumeShadowCopy/cpp/readme.txt | 28 + .../VShadowVolumeShadowCopy/cpp/revert.cpp | 97 + .../VShadowVolumeShadowCopy/cpp/select.cpp | 772 ++ .../VShadowVolumeShadowCopy/cpp/shadow.cpp | 1178 ++ Samples/VShadowVolumeShadowCopy/cpp/shadow.h | 103 + .../VShadowVolumeShadowCopy/cpp/stdafx.cpp | 17 + Samples/VShadowVolumeShadowCopy/cpp/stdafx.h | 38 + .../VShadowVolumeShadowCopy/cpp/tracing.cpp | 187 + Samples/VShadowVolumeShadowCopy/cpp/tracing.h | 54 + Samples/VShadowVolumeShadowCopy/cpp/util.h | 746 ++ .../VShadowVolumeShadowCopy/cpp/vshadow.rc | 15 + .../VShadowVolumeShadowCopy/cpp/vshadow.sln | 22 + .../cpp/vshadow.vcxproj | 115 + .../cpp/vshadow.vcxproj.filters | 83 + .../VShadowVolumeShadowCopy/cpp/vssclient.cpp | 134 + .../VShadowVolumeShadowCopy/cpp/vssclient.h | 291 + .../VShadowVolumeShadowCopy/cpp/writer.cpp | 897 ++ Samples/VShadowVolumeShadowCopy/cpp/writer.h | 200 + .../README.md | 92 + .../cpp/ExpressW.sln | 22 + .../cpp/ExpressW.vcxproj | 97 + .../cpp/ExpressW.vcxproj.filters | 33 + .../cpp/helpers.cpp | 323 + .../cpp/helpers.h | 33 + .../cpp/main.cpp | 360 + .../cpp/readme.txt | 54 + .../cpp/stdafx.h | 69 + .../VolumeShadowCopyServiceProvider/README.md | 138 + .../cpp/VssSampleProvider.vcxproj | 334 + .../cpp/VssSampleProvider.vcxproj.filters | 82 + .../cpp/async.h | 140 + .../cpp/eventlogmsgs.mc | 10 + .../cpp/install-sampleprovider.cmd | 75 + .../cpp/readme.txt | 62 + .../cpp/resource.h | 18 + .../cpp/sampleprovider.cpp | 1538 +++ .../cpp/sampleprovider.h | 254 + .../cpp/sampleprovider.rgs | 26 + .../cpp/setup.txt | 58 + .../cpp/stdafx.cpp | 21 + .../cpp/stdafx.h | 70 + .../cpp/uninstall-sampleprovider.cmd | 63 + .../cpp/utility.cpp | 331 + .../cpp/utility.h | 216 + .../cpp/vsssampleprovider.cpp | 127 + .../cpp/vsssampleprovider.def | 9 + .../cpp/vsssampleprovider.idl | 52 + .../cpp/vsssampleprovider.rc | 107 + .../cpp/vsssampleprovider.rgs | 11 + .../cpp/vsssampleprovider.sln | 25 + .../cpp/vstorinterface.h | 144 + .../VolumeShadowCopyServiceWriter/README.md | 84 + .../cpp/SampleWriter.sln | 25 + .../cpp/SampleWriter.vcxproj | 211 + .../cpp/SampleWriter.vcxproj.filters | 36 + .../cpp/main.cpp | 99 + .../VolumeShadowCopyServiceWriter/cpp/main.h | 26 + .../cpp/stdafx.h | 28 + .../cpp/swriter.cpp | 164 + .../cpp/swriter.h | 59 + Samples/WebSecurityCenter/README.md | 51 + .../WebSecurityCenter/cpp/WscApiSample.cpp | 291 + .../WebSecurityCenter/cpp/WscApiSample.sln | 20 + .../cpp/WscApiSample.vcxproj | 88 + .../cpp/WscApiSample.vcxproj.filters | 22 + .../README.md | 56 + .../cpp/AsmxCustomProxyClient.cpp | 290 + ...AsmxPublicServiceSampleWithCustomProxy.sln | 32 + ...PublicServiceSampleWithCustomProxy.vcxproj | 193 + ...rviceSampleWithCustomProxy.vcxproj.filters | 32 + .../cpp/terraservice-usa.com.wsdl | 754 ++ .../readme.txt | 58 + .../WebServices/AsyncAdd3Explicit/README.md | 52 + .../cpp/AsyncAdd3Explicit.cpp | 357 + .../cpp/AsyncAdd3Explicit.sln | 32 + .../cpp/AsyncAdd3Explicit.vcxproj | 255 + .../cpp/AsyncAdd3Explicit.vcxproj.filters | 21 + .../WebServices/AsyncAdd3Explicit/readme.txt | 60 + .../WebServices/AsyncAdd3Implicit/README.md | 54 + .../cpp/AsyncAdd3Implicit.cpp | 361 + .../cpp/AsyncAdd3Implicit.sln | 32 + .../cpp/AsyncAdd3Implicit.vcxproj | 255 + .../cpp/AsyncAdd3Implicit.vcxproj.filters | 21 + .../WebServices/AsyncAdd3Implicit/readme.txt | 60 + Samples/WebServices/AsyncModel/README.md | 41 + .../WebServices/AsyncModel/cpp/AsyncModel.cpp | 362 + .../WebServices/AsyncModel/cpp/AsyncModel.sln | 32 + .../AsyncModel/cpp/AsyncModel.vcxproj | 255 + .../AsyncModel/cpp/AsyncModel.vcxproj.filters | 21 + Samples/WebServices/AsyncModel/readme.txt | 66 + .../AsyncStreamingTcpClient/README.md | 66 + .../cpp/AsyncStreamingTcpClient.cpp | 512 + .../cpp/AsyncStreamingTcpClient.sln | 32 + .../cpp/AsyncStreamingTcpClient.vcxproj | 266 + .../AsyncStreamingTcpClient.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../AsyncStreamingTcpClient/readme.txt | 60 + .../AsyncStreamingTcpServer/README.md | 66 + .../cpp/AsyncStreamingTcpServer.cpp | 551 + .../cpp/AsyncStreamingTcpServer.sln | 32 + .../cpp/AsyncStreamingTcpServer.vcxproj | 266 + .../AsyncStreamingTcpServer.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../AsyncStreamingTcpServer/readme.txt | 60 + Samples/WebServices/CallAbandon/README.md | 56 + .../CallAbandon/cpp/AbandonCallClient.cpp | 170 + .../CallAbandon/cpp/BlockUnBlockService.wsdl | 76 + .../CallAbandon/cpp/CallAbandon.sln | 32 + .../CallAbandon/cpp/CallAbandon.vcxproj | 266 + .../cpp/CallAbandon.vcxproj.filters | 32 + Samples/WebServices/CallAbandon/readme.txt | 57 + .../WebServices/CancellingService/README.md | 56 + .../cpp/BlockUnBlockService.wsdl | 76 + .../cpp/CancellingService.cpp | 240 + .../cpp/CancellingService.sln | 32 + .../cpp/CancellingService.vcxproj | 266 + .../cpp/CancellingService.vcxproj.filters | 32 + .../WebServices/CancellingService/readme.txt | 57 + Samples/WebServices/CustomHeader/README.md | 52 + .../CustomHeader/cpp/CustomHeader.cpp | 156 + .../CustomHeader/cpp/CustomHeader.sln | 32 + .../CustomHeader/cpp/CustomHeader.vcxproj | 266 + .../cpp/CustomHeader.vcxproj.filters | 32 + .../CustomHeader/cpp/PurchaseOrder.wsdl | 106 + Samples/WebServices/CustomHeader/readme.txt | 57 + Samples/WebServices/DerivedType/README.md | 58 + .../DerivedType/cpp/DerivedType.cpp | 342 + .../DerivedType/cpp/DerivedType.sln | 32 + .../DerivedType/cpp/DerivedType.vcxproj | 271 + .../cpp/DerivedType.vcxproj.filters | 34 + .../DerivedType/cpp/DerivedType.xsd | 24 + Samples/WebServices/DerivedType/readme.txt | 58 + Samples/WebServices/FileRepService/README.md | 54 + .../FileRepService/cpp/CChannelManager.cpp | 309 + .../FileRepService/cpp/CFileRep.cpp | 389 + .../FileRepService/cpp/CFileRepClient.cpp | 688 + .../FileRepService/cpp/CFileRepServer.cpp | 412 + .../FileRepService/cpp/CRequest.cpp | 662 + .../WebServices/FileRepService/cpp/FileRep.mc | 42 + .../WebServices/FileRepService/cpp/FileRep.rc | 2 + .../FileRepService/cpp/FileRepService.sln | 32 + .../FileRepService/cpp/FileRepService.vcxproj | 210 + .../cpp/FileRepService.vcxproj.filters | 53 + .../FileRepService/cpp/Service.cpp | 241 + .../WebServices/FileRepService/cpp/Service.h | 519 + .../WebServices/FileRepService/cpp/common.h | 589 + Samples/WebServices/FileRepService/readme.txt | 96 + Samples/WebServices/FileRepTool/README.md | 54 + .../FileRepTool/cpp/FileRepTool.sln | 32 + .../FileRepTool/cpp/FileRepTool.vcxproj | 182 + .../cpp/FileRepTool.vcxproj.filters | 21 + Samples/WebServices/FileRepTool/cpp/Tool.cpp | 415 + Samples/WebServices/FileRepTool/cpp/common.h | 589 + Samples/WebServices/FileRepTool/readme.txt | 67 + Samples/WebServices/ForwardMessage/README.md | 62 + .../ForwardMessage/cpp/ForwardMessage.cpp | 779 ++ .../ForwardMessage/cpp/ForwardMessage.sln | 32 + .../ForwardMessage/cpp/ForwardMessage.vcxproj | 266 + .../cpp/ForwardMessage.vcxproj.filters | 32 + .../ForwardMessage/cpp/PurchaseOrder.wsdl | 106 + Samples/WebServices/ForwardMessage/readme.txt | 57 + .../HttpCalculatorClient/README.md | 46 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/HttpCalculatorClient.cpp | 167 + .../cpp/HttpCalculatorClient.sln | 32 + .../cpp/HttpCalculatorClient.vcxproj | 266 + .../cpp/HttpCalculatorClient.vcxproj.filters | 32 + .../HttpCalculatorClient/readme.txt | 57 + .../HttpCalculatorService/README.md | 46 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/HttpCalculatorService.cpp | 219 + .../cpp/HttpCalculatorService.sln | 32 + .../cpp/HttpCalculatorService.vcxproj | 266 + .../cpp/HttpCalculatorService.vcxproj.filters | 32 + .../HttpCalculatorService/readme.txt | 57 + .../README.md | 60 + .../cpp/CalculatorService.wsdl | 92 + .../HttpCalculatorWithBasicOverSslClient.cpp | 203 + .../HttpCalculatorWithBasicOverSslClient.sln | 32 + ...tpCalculatorWithBasicOverSslClient.vcxproj | 266 + ...atorWithBasicOverSslClient.vcxproj.filters | 32 + .../readme.txt | 62 + .../README.md | 56 + .../cpp/CalculatorService.wsdl | 92 + .../HttpCalculatorWithBasicOverSslService.cpp | 248 + .../HttpCalculatorWithBasicOverSslService.sln | 32 + ...pCalculatorWithBasicOverSslService.vcxproj | 266 + ...torWithBasicOverSslService.vcxproj.filters | 32 + .../readme.txt | 62 + .../README.md | 60 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/EncodedChannel.cpp | 366 + .../cpp/EncodedChannel.h | 9 + ...HttpCalculatorWithEncodedChannelClient.cpp | 173 + ...HttpCalculatorWithEncodedChannelClient.sln | 32 + ...CalculatorWithEncodedChannelClient.vcxproj | 268 + ...orWithEncodedChannelClient.vcxproj.filters | 35 + .../readme.txt | 58 + .../README.md | 56 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/EncodedChannel.cpp | 366 + .../cpp/EncodedChannel.h | 9 + ...ttpCalculatorWithEncodedChannelService.cpp | 241 + ...ttpCalculatorWithEncodedChannelService.sln | 32 + ...alculatorWithEncodedChannelService.vcxproj | 268 + ...rWithEncodedChannelService.vcxproj.filters | 35 + .../readme.txt | 58 + .../README.md | 60 + .../cpp/CalculatorClientKerberosOverSsl.cpp | 222 + .../cpp/CalculatorService.wsdl | 92 + ...ttpCalculatorWithKerberosOverSslClient.sln | 32 + ...alculatorWithKerberosOverSslClient.vcxproj | 266 + ...rWithKerberosOverSslClient.vcxproj.filters | 32 + .../readme.txt | 62 + .../README.md | 56 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/CalculatorServiceKerberosOverSsl.cpp | 240 + ...tpCalculatorWithKerberosOverSslService.sln | 32 + ...lculatorWithKerberosOverSslService.vcxproj | 266 + ...WithKerberosOverSslService.vcxproj.filters | 32 + .../readme.txt | 60 + .../README.md | 60 + .../cpp/CalculatorService.wsdl | 92 + ...HttpCalculatorWithLayeredChannelClient.cpp | 202 + ...HttpCalculatorWithLayeredChannelClient.sln | 32 + ...CalculatorWithLayeredChannelClient.vcxproj | 268 + ...orWithLayeredChannelClient.vcxproj.filters | 35 + .../cpp/LayeredChannel.cpp | 254 + .../cpp/LayeredChannel.h | 32 + .../readme.txt | 59 + .../README.md | 56 + .../cpp/CalculatorService.wsdl | 92 + ...ttpCalculatorWithLayeredChannelService.cpp | 358 + ...ttpCalculatorWithLayeredChannelService.sln | 32 + ...alculatorWithLayeredChannelService.vcxproj | 268 + ...rWithLayeredChannelService.vcxproj.filters | 38 + .../cpp/LayeredChannel.cpp | 254 + .../cpp/LayeredChannel.h | 32 + .../cpp/LayeredListener.cpp | 236 + .../cpp/LayeredListener.h | 32 + .../readme.txt | 58 + .../HttpCalculatorWithSslClient/README.md | 60 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/HttpCalculatorClientWithSsl.cpp | 180 + .../cpp/HttpCalculatorWithSslClient.sln | 32 + .../cpp/HttpCalculatorWithSslClient.vcxproj | 266 + ...ttpCalculatorWithSslClient.vcxproj.filters | 32 + .../HttpCalculatorWithSslClient/readme.txt | 57 + .../README.md | 58 + .../cpp/CalculatorServiceWithPolicy.wsdl | 120 + .../cpp/HttpCalculatorWithSslPolicyClient.cpp | 145 + .../cpp/HttpCalculatorWithSslPolicyClient.sln | 32 + .../HttpCalculatorWithSslPolicyClient.vcxproj | 266 + ...culatorWithSslPolicyClient.vcxproj.filters | 32 + .../readme.txt | 60 + .../README.md | 56 + .../cpp/CalculatorServiceWithPolicy.wsdl | 120 + .../HttpCalculatorWithSslPolicyService.cpp | 239 + .../HttpCalculatorWithSslPolicyService.sln | 32 + ...HttpCalculatorWithSslPolicyService.vcxproj | 266 + ...ulatorWithSslPolicyService.vcxproj.filters | 32 + .../readme.txt | 62 + .../HttpCalculatorWithSslService/README.md | 52 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/HttpCalculatorServiceWithSsl.cpp | 235 + .../cpp/HttpCalculatorWithSslService.sln | 32 + .../cpp/HttpCalculatorWithSslService.vcxproj | 266 + ...tpCalculatorWithSslService.vcxproj.filters | 32 + .../HttpCalculatorWithSslService/readme.txt | 57 + .../README.md | 56 + .../cpp/CalculatorService.wsdl | 92 + .../cpp/CalculatorServiceUserNameOverSsl.cpp | 321 + ...tpCalculatorWithUserNameOverSslService.sln | 32 + ...lculatorWithUserNameOverSslService.vcxproj | 266 + ...WithUserNameOverSslService.vcxproj.filters | 32 + .../readme.txt | 60 + .../README.md | 56 + .../cpp/CalculatorClientUserNameOverSsl.cpp | 194 + .../cpp/CalculatorService.wsdl | 92 + ...ttpCalculatorWithUsernameOverSslClient.sln | 32 + ...alculatorWithUsernameOverSslClient.vcxproj | 266 + ...rWithUsernameOverSslClient.vcxproj.filters | 32 + .../readme.txt | 62 + .../README.md | 70 + ...alculatorClientUserNameXmlTokenOverSsl.cpp | 312 + .../cpp/CalculatorService.wsdl | 92 + ...latorWithUsernameXmlTokenOverSslClient.sln | 32 + ...rWithUsernameXmlTokenOverSslClient.vcxproj | 266 + ...rnameXmlTokenOverSslClient.vcxproj.filters | 32 + .../readme.txt | 69 + Samples/WebServices/HttpClient/README.md | 50 + .../WebServices/HttpClient/cpp/HttpClient.cpp | 375 + .../WebServices/HttpClient/cpp/HttpClient.sln | 32 + .../HttpClient/cpp/HttpClient.vcxproj | 266 + .../HttpClient/cpp/HttpClient.vcxproj.filters | 32 + .../HttpClient/cpp/PurchaseOrder.wsdl | 106 + Samples/WebServices/HttpClient/readme.txt | 57 + .../HttpClientWithKerberosOverSsl/README.md | 58 + .../cpp/HttpClientWithKerberosOverSsl.cpp | 429 + .../cpp/HttpClientWithKerberosOverSsl.sln | 32 + .../cpp/HttpClientWithKerberosOverSsl.vcxproj | 266 + ...pClientWithKerberosOverSsl.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpClientWithKerberosOverSsl/readme.txt | 62 + .../WebServices/HttpClientWithSsl/README.md | 62 + .../cpp/HttpClientWithSsl.cpp | 388 + .../cpp/HttpClientWithSsl.sln | 32 + .../cpp/HttpClientWithSsl.vcxproj | 266 + .../cpp/HttpClientWithSsl.vcxproj.filters | 32 + .../HttpClientWithSsl/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/HttpClientWithSsl/readme.txt | 57 + .../HttpClientWithSslAndClientCert/README.md | 58 + .../cpp/HttpClientWithSslAndClientCert.cpp | 399 + .../cpp/HttpClientWithSslAndClientCert.sln | 32 + .../HttpClientWithSslAndClientCert.vcxproj | 266 + ...ClientWithSslAndClientCert.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpClientWithSslAndClientCert/readme.txt | 57 + .../HttpClientWithUsernameOverSsl/README.md | 58 + .../cpp/HttpClientWithUsernameOverSsl.cpp | 402 + .../cpp/HttpClientWithUsernameOverSsl.sln | 32 + .../cpp/HttpClientWithUsernameOverSsl.vcxproj | 266 + ...pClientWithUsernameOverSsl.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpClientWithUsernameOverSsl/readme.txt | 62 + .../README.md | 48 + .../cpp/HttpCustomHeaderClient.cpp | 255 + .../HttpCustomHeaderPurchaseOrderClient.sln | 32 + ...ttpCustomHeaderPurchaseOrderClient.vcxproj | 268 + ...mHeaderPurchaseOrderClient.vcxproj.filters | 43 + .../cpp/OrderSessionHeader.xsd | 13 + .../cpp/PurchaseOrder.wsdl | 106 + .../readme.txt | 57 + .../README.md | 48 + .../HttpCustomHeaderPurchaseOrderService.sln | 32 + ...tpCustomHeaderPurchaseOrderService.vcxproj | 268 + ...HeaderPurchaseOrderService.vcxproj.filters | 43 + .../cpp/HttpCustomHeaderService.cpp | 345 + .../cpp/OrderSessionHeader.xsd | 13 + .../cpp/PurchaseOrder.wsdl | 106 + .../readme.txt | 57 + Samples/WebServices/HttpGetService/README.md | 62 + .../HttpGetService/cpp/HttpGetService.cpp | 764 ++ .../HttpGetService/cpp/HttpGetService.sln | 32 + .../HttpGetService/cpp/HttpGetService.vcxproj | 266 + .../cpp/HttpGetService.vcxproj.filters | 32 + .../HttpGetService/cpp/PurchaseOrder.wsdl | 106 + Samples/WebServices/HttpGetService/readme.txt | 59 + .../HttpPurchaseOrderClient/README.md | 56 + .../cpp/HttpPurchaseOrderClient.cpp | 279 + .../cpp/HttpPurchaseOrderClient.sln | 32 + .../cpp/HttpPurchaseOrderClient.vcxproj | 266 + .../HttpPurchaseOrderClient.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpPurchaseOrderClient/readme.txt | 62 + .../HttpPurchaseOrderService/README.md | 54 + .../cpp/HttpPurchaseOrderService.cpp | 353 + .../cpp/HttpPurchaseOrderService.sln | 32 + .../cpp/HttpPurchaseOrderService.vcxproj | 266 + .../HttpPurchaseOrderService.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpPurchaseOrderService/readme.txt | 62 + .../README.md | 54 + ...PurchaseOrderWithKerberosOverSslClient.sln | 32 + ...haseOrderWithKerberosOverSslClient.vcxproj | 266 + ...rWithKerberosOverSslClient.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../PurchaseOrderClientKerberosOverSsl.cpp | 327 + .../readme.txt | 62 + .../README.md | 52 + ...urchaseOrderWithKerberosOverSslService.sln | 32 + ...aseOrderWithKerberosOverSslService.vcxproj | 266 + ...WithKerberosOverSslService.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../PurchaseOrderServiceKerberosOverSsl.cpp | 365 + .../readme.txt | 60 + .../HttpPurchaseOrderWithSslClient/README.md | 52 + .../cpp/HttpPurchaseOrderClientWithSsl.cpp | 285 + .../cpp/HttpPurchaseOrderWithSslClient.sln | 32 + .../HttpPurchaseOrderWithSslClient.vcxproj | 266 + ...PurchaseOrderWithSslClient.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpPurchaseOrderWithSslClient/readme.txt | 57 + .../HttpPurchaseOrderWithSslService/README.md | 58 + .../cpp/HttpPurchaseOrderServiceWithSsl.cpp | 360 + .../cpp/HttpPurchaseOrderWithSslService.sln | 32 + .../HttpPurchaseOrderWithSslService.vcxproj | 266 + ...urchaseOrderWithSslService.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../readme.txt | 57 + .../README.md | 64 + ...urchaseOrderWithUserNameOverSslService.sln | 32 + ...aseOrderWithUserNameOverSslService.vcxproj | 266 + ...WithUserNameOverSslService.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../PurchaseOrderServiceUserNameOverSsl.cpp | 446 + .../readme.txt | 60 + .../README.md | 58 + ...PurchaseOrderWithUsernameOverSslClient.sln | 32 + ...haseOrderWithUsernameOverSslClient.vcxproj | 266 + ...rWithUsernameOverSslClient.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../PurchaseOrderClientUserNameOverSsl.cpp | 299 + .../readme.txt | 62 + Samples/WebServices/HttpRawClient/README.md | 54 + .../HttpRawClient/cpp/HttpRawClient.cpp | 217 + .../HttpRawClient/cpp/HttpRawClient.sln | 32 + .../HttpRawClient/cpp/HttpRawClient.vcxproj | 255 + .../cpp/HttpRawClient.vcxproj.filters | 21 + Samples/WebServices/HttpRawClient/readme.txt | 57 + Samples/WebServices/HttpRawService/README.md | 60 + .../HttpRawService/cpp/HttpRawService.cpp | 550 + .../HttpRawService/cpp/HttpRawService.sln | 32 + .../HttpRawService/cpp/HttpRawService.vcxproj | 255 + .../cpp/HttpRawService.vcxproj.filters | 21 + Samples/WebServices/HttpRawService/readme.txt | 57 + Samples/WebServices/HttpServer/README.md | 54 + .../WebServices/HttpServer/cpp/HttpServer.cpp | 434 + .../WebServices/HttpServer/cpp/HttpServer.sln | 32 + .../HttpServer/cpp/HttpServer.vcxproj | 266 + .../HttpServer/cpp/HttpServer.vcxproj.filters | 32 + .../HttpServer/cpp/PurchaseOrder.wsdl | 106 + Samples/WebServices/HttpServer/readme.txt | 58 + .../HttpServerWithKerberosOverSsl/README.md | 54 + .../cpp/HttpServerWithKerberosOverSsl.cpp | 454 + .../cpp/HttpServerWithKerberosOverSsl.sln | 32 + .../cpp/HttpServerWithKerberosOverSsl.vcxproj | 266 + ...pServerWithKerberosOverSsl.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpServerWithKerberosOverSsl/readme.txt | 62 + .../WebServices/HttpServerWithSsl/README.md | 54 + .../cpp/HttpServerWithSsl.cpp | 449 + .../cpp/HttpServerWithSsl.sln | 32 + .../cpp/HttpServerWithSsl.vcxproj | 266 + .../cpp/HttpServerWithSsl.vcxproj.filters | 32 + .../HttpServerWithSsl/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/HttpServerWithSsl/readme.txt | 58 + .../HttpServerWithSslAndClientCert/README.md | 37 + .../cpp/HttpServerWithSslAndClientCert.cpp | 566 + .../cpp/HttpServerWithSslAndClientCert.sln | 32 + .../HttpServerWithSslAndClientCert.vcxproj | 266 + ...ServerWithSslAndClientCert.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpServerWithSslAndClientCert/readme.txt | 58 + .../HttpServerWithUsernameOverSsl/README.md | 54 + .../cpp/HttpServerWithUsernameOverSsl.cpp | 506 + .../cpp/HttpServerWithUsernameOverSsl.sln | 32 + .../cpp/HttpServerWithUsernameOverSsl.vcxproj | 266 + ...pServerWithUsernameOverSsl.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../HttpServerWithUsernameOverSsl/readme.txt | 62 + Samples/WebServices/InsertElement/README.md | 46 + .../InsertElement/cpp/InsertElement.cpp | 261 + .../InsertElement/cpp/InsertElement.sln | 32 + .../InsertElement/cpp/InsertElement.vcxproj | 255 + .../cpp/InsertElement.vcxproj.filters | 21 + Samples/WebServices/InsertElement/readme.txt | 57 + Samples/WebServices/MessageEncoding/README.md | 66 + .../MessageEncoding/cpp/MessageEncoding.cpp | 301 + .../MessageEncoding/cpp/MessageEncoding.sln | 32 + .../cpp/MessageEncoding.vcxproj | 266 + .../cpp/MessageEncoding.vcxproj.filters | 32 + .../MessageEncoding/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/MessageEncoding/readme.txt | 57 + .../README.md | 62 + ...ataImportWithIssuedTokenOverSslExample.cpp | 599 + ...ataImportWithIssuedTokenOverSslExample.sln | 32 + ...mportWithIssuedTokenOverSslExample.vcxproj | 255 + ...hIssuedTokenOverSslExample.vcxproj.filters | 21 + .../readme.txt | 62 + .../README.md | 60 + ...tadataImportWithUsernameOverSslExample.cpp | 548 + ...tadataImportWithUsernameOverSslExample.sln | 32 + ...taImportWithUsernameOverSslExample.vcxproj | 255 + ...WithUsernameOverSslExample.vcxproj.filters | 21 + .../readme.txt | 59 + .../README.md | 58 + .../MetadataImportWithX509OverSslExample.cpp | 553 + .../MetadataImportWithX509OverSslExample.sln | 32 + ...tadataImportWithX509OverSslExample.vcxproj | 255 + ...portWithX509OverSslExample.vcxproj.filters | 21 + .../readme.txt | 59 + .../WebServices/MulticastUdpClient/README.md | 96 + .../cpp/MulticastUdpClient.cpp | 517 + .../cpp/MulticastUdpClient.sln | 32 + .../cpp/MulticastUdpClient.vcxproj | 266 + .../cpp/MulticastUdpClient.vcxproj.filters | 32 + .../MulticastUdpClient/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/MulticastUdpClient/readme.txt | 58 + .../WebServices/MulticastUdpClient6/README.md | 96 + .../cpp/MulticastUdpClient6.cpp | 524 + .../cpp/MulticastUdpClient6.sln | 32 + .../cpp/MulticastUdpClient6.vcxproj | 266 + .../cpp/MulticastUdpClient6.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../MulticastUdpClient6/readme.txt | 58 + .../WebServices/MulticastUdpServer/README.md | 86 + .../cpp/MulticastUdpServer.cpp | 428 + .../cpp/MulticastUdpServer.sln | 32 + .../cpp/MulticastUdpServer.vcxproj | 266 + .../cpp/MulticastUdpServer.vcxproj.filters | 32 + .../MulticastUdpServer/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/MulticastUdpServer/readme.txt | 58 + .../WebServices/MulticastUdpServer6/README.md | 86 + .../cpp/MulticastUdpServer6.cpp | 434 + .../cpp/MulticastUdpServer6.sln | 32 + .../cpp/MulticastUdpServer6.vcxproj | 266 + .../cpp/MulticastUdpServer6.vcxproj.filters | 32 + .../cpp/PurchaseOrder.wsdl | 106 + .../MulticastUdpServer6/readme.txt | 59 + Samples/WebServices/NavigateXml/README.md | 84 + .../NavigateXml/cpp/NavigateXml.cpp | 330 + .../NavigateXml/cpp/NavigateXml.sln | 32 + .../NavigateXml/cpp/NavigateXml.vcxproj | 255 + .../cpp/NavigateXml.vcxproj.filters | 21 + Samples/WebServices/NavigateXml/readme.txt | 57 + Samples/WebServices/OneWayTcpClient/README.md | 64 + .../OneWayTcpClient/cpp/OneWayTcpClient.cpp | 183 + .../OneWayTcpClient/cpp/OneWayTcpClient.sln | 32 + .../cpp/OneWayTcpClient.vcxproj | 266 + .../cpp/OneWayTcpClient.vcxproj.filters | 32 + .../OneWayTcpClient/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/OneWayTcpClient/readme.txt | 57 + Samples/WebServices/OneWayTcpServer/README.md | 78 + .../OneWayTcpServer/cpp/OneWayTcpServer.cpp | 242 + .../OneWayTcpServer/cpp/OneWayTcpServer.sln | 32 + .../cpp/OneWayTcpServer.vcxproj | 266 + .../cpp/OneWayTcpServer.vcxproj.filters | 32 + .../OneWayTcpServer/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/OneWayTcpServer/readme.txt | 58 + Samples/WebServices/OneWayUdpClient/README.md | 64 + .../OneWayUdpClient/cpp/OneWayUdpClient.cpp | 179 + .../OneWayUdpClient/cpp/OneWayUdpClient.sln | 32 + .../cpp/OneWayUdpClient.vcxproj | 266 + .../cpp/OneWayUdpClient.vcxproj.filters | 32 + .../OneWayUdpClient/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/OneWayUdpClient/readme.txt | 57 + Samples/WebServices/OneWayUdpServer/README.md | 78 + .../OneWayUdpServer/cpp/OneWayUdpServer.cpp | 255 + .../OneWayUdpServer/cpp/OneWayUdpServer.sln | 32 + .../cpp/OneWayUdpServer.vcxproj | 266 + .../cpp/OneWayUdpServer.vcxproj.filters | 32 + .../OneWayUdpServer/cpp/PurchaseOrder.wsdl | 106 + .../WebServices/OneWayUdpServer/readme.txt | 58 + Samples/WebServices/PolicyTemplate/README.md | 56 + .../PolicyTemplate/cpp/PolicyTemplate.sln | 32 + .../PolicyTemplate/cpp/PolicyTemplate.vcxproj | 255 + .../cpp/PolicyTemplate.vcxproj.filters | 21 + .../PolicyTemplate/cpp/policytemplate.cpp | 168 + Samples/WebServices/PolicyTemplate/readme.txt | 58 + Samples/WebServices/ReadAttribute/README.md | 70 + .../ReadAttribute/cpp/ReadAttribute.cpp | 195 + .../ReadAttribute/cpp/ReadAttribute.sln | 32 + .../ReadAttribute/cpp/ReadAttribute.vcxproj | 255 + .../cpp/ReadAttribute.vcxproj.filters | 21 + Samples/WebServices/ReadAttribute/readme.txt | 57 + Samples/WebServices/ReadWriteArray/README.md | 76 + .../ReadWriteArray/cpp/ReadWriteArray.cpp | 220 + .../ReadWriteArray/cpp/ReadWriteArray.sln | 32 + .../ReadWriteArray/cpp/ReadWriteArray.vcxproj | 255 + .../cpp/ReadWriteArray.vcxproj.filters | 21 + Samples/WebServices/ReadWriteArray/readme.txt | 57 + .../WebServices/ReadWriteBytesXml/README.md | 82 + .../cpp/ReadWriteBytesXml.cpp | 356 + .../cpp/ReadWriteBytesXml.sln | 32 + .../cpp/ReadWriteBytesXml.vcxproj | 255 + .../cpp/ReadWriteBytesXml.vcxproj.filters | 21 + .../WebServices/ReadWriteBytesXml/readme.txt | 57 + Samples/WebServices/ReadWriteRawXml/README.md | 64 + .../ReadWriteRawXml/cpp/ReadWriteRawXml.cpp | 291 + .../ReadWriteRawXml/cpp/ReadWriteRawXml.sln | 32 + .../cpp/ReadWriteRawXml.vcxproj | 255 + .../cpp/ReadWriteRawXml.vcxproj.filters | 21 + .../WebServices/ReadWriteRawXml/readme.txt | 57 + Samples/WebServices/ReadWriteXml/README.md | 96 + .../ReadWriteXml/cpp/PurchaseOrder.wsdl | 106 + .../ReadWriteXml/cpp/ReadWriteXml.cpp | 432 + .../ReadWriteXml/cpp/ReadWriteXml.sln | 32 + .../ReadWriteXml/cpp/ReadWriteXml.vcxproj | 266 + .../cpp/ReadWriteXml.vcxproj.filters | 32 + Samples/WebServices/ReadWriteXml/readme.txt | 57 + Samples/WebServices/ReadXml/README.md | 60 + Samples/WebServices/ReadXml/cpp/ReadXml.cpp | 477 + Samples/WebServices/ReadXml/cpp/ReadXml.sln | 32 + .../WebServices/ReadXml/cpp/ReadXml.vcxproj | 255 + .../ReadXml/cpp/ReadXml.vcxproj.filters | 21 + Samples/WebServices/ReadXml/readme.txt | 57 + Samples/WebServices/ReadXmlSimple/README.md | 62 + .../ReadXmlSimple/cpp/ReadXmlSimple.cpp | 188 + .../ReadXmlSimple/cpp/ReadXmlSimple.sln | 32 + .../ReadXmlSimple/cpp/ReadXmlSimple.vcxproj | 255 + .../cpp/ReadXmlSimple.vcxproj.filters | 21 + Samples/WebServices/ReadXmlSimple/readme.txt | 57 + .../RequestReplyNamedPipeClient/README.md | 58 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/RequestReplyNamedPipeClient.cpp | 380 + .../cpp/RequestReplyNamedPipeClient.sln | 32 + .../cpp/RequestReplyNamedPipeClient.vcxproj | 266 + ...equestReplyNamedPipeClient.vcxproj.filters | 32 + .../RequestReplyNamedPipeClient/readme.txt | 57 + .../README.md | 58 + .../cpp/PurchaseOrder.wsdl | 106 + ...PipeClientWithWindowsTransportSecurity.cpp | 414 + ...PipeClientWithWindowsTransportSecurity.sln | 32 + ...ClientWithWindowsTransportSecurity.vcxproj | 266 + ...thWindowsTransportSecurity.vcxproj.filters | 32 + .../readme.txt | 57 + .../RequestReplyNamedPipeServer/README.md | 70 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/RequestReplyNamedPipeServer.cpp | 433 + .../cpp/RequestReplyNamedPipeServer.sln | 32 + .../cpp/RequestReplyNamedPipeServer.vcxproj | 266 + ...equestReplyNamedPipeServer.vcxproj.filters | 32 + .../RequestReplyNamedPipeServer/readme.txt | 58 + .../README.md | 70 + .../cpp/PurchaseOrder.wsdl | 106 + ...PipeServerWithWindowsTransportSecurity.cpp | 446 + ...PipeServerWithWindowsTransportSecurity.sln | 32 + ...ServerWithWindowsTransportSecurity.vcxproj | 266 + ...thWindowsTransportSecurity.vcxproj.filters | 32 + .../readme.txt | 58 + .../RequestReplyTcpClient/README.md | 58 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/RequestReplyTcpClient.cpp | 380 + .../cpp/RequestReplyTcpClient.sln | 32 + .../cpp/RequestReplyTcpClient.vcxproj | 266 + .../cpp/RequestReplyTcpClient.vcxproj.filters | 32 + .../RequestReplyTcpClient/readme.txt | 57 + .../README.md | 58 + .../cpp/PurchaseOrder.wsdl | 106 + ...yTcpClientWithWindowsTransportSecurity.cpp | 414 + ...yTcpClientWithWindowsTransportSecurity.sln | 32 + ...ClientWithWindowsTransportSecurity.vcxproj | 266 + ...thWindowsTransportSecurity.vcxproj.filters | 32 + .../readme.txt | 57 + .../RequestReplyTcpServer/README.md | 70 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/RequestReplyTcpServer.cpp | 433 + .../cpp/RequestReplyTcpServer.sln | 32 + .../cpp/RequestReplyTcpServer.vcxproj | 266 + .../cpp/RequestReplyTcpServer.vcxproj.filters | 32 + .../RequestReplyTcpServer/readme.txt | 58 + .../README.md | 70 + .../cpp/PurchaseOrder.wsdl | 106 + ...yTcpServerWithWindowsTransportSecurity.cpp | 446 + ...yTcpServerWithWindowsTransportSecurity.sln | 32 + ...ServerWithWindowsTransportSecurity.vcxproj | 266 + ...thWindowsTransportSecurity.vcxproj.filters | 32 + .../readme.txt | 58 + .../WebServices/ServiceCancelClient/README.md | 50 + .../cpp/BlockUnBlockService.wsdl | 76 + .../ServiceCancelClient/cpp/ServiceCancel.cpp | 161 + .../cpp/ServiceCancelClient.sln | 32 + .../cpp/ServiceCancelClient.vcxproj | 266 + .../cpp/ServiceCancelClient.vcxproj.filters | 32 + .../ServiceCancelClient/readme.txt | 57 + .../SessionfullCalculatorClient/README.md | 54 + .../cpp/SessionBasedCalculatorService.wsdl | 126 + .../cpp/SessionfullCalculatorClient.cpp | 249 + .../cpp/SessionfullCalculatorClient.sln | 32 + .../cpp/SessionfullCalculatorClient.vcxproj | 266 + ...essionfullCalculatorClient.vcxproj.filters | 32 + .../SessionfullCalculatorClient/readme.txt | 57 + .../SessionfullCalculatorService/README.md | 54 + .../cpp/SessionBasedCalculatorService.wsdl | 126 + .../cpp/SessionfullCalculatorService.cpp | 376 + .../cpp/SessionfullCalculatorService.sln | 32 + .../cpp/SessionfullCalculatorService.vcxproj | 266 + ...ssionfullCalculatorService.vcxproj.filters | 32 + .../SessionfullCalculatorService/readme.txt | 57 + .../WebServices/StreamingHttpClient/README.md | 62 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/StreamingHttpClient.cpp | 390 + .../cpp/StreamingHttpClient.sln | 32 + .../cpp/StreamingHttpClient.vcxproj | 266 + .../cpp/StreamingHttpClient.vcxproj.filters | 32 + .../StreamingHttpClient/readme.txt | 58 + .../WebServices/StreamingHttpServer/README.md | 68 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/StreamingHttpServer.cpp | 408 + .../cpp/StreamingHttpServer.sln | 32 + .../cpp/StreamingHttpServer.vcxproj | 266 + .../cpp/StreamingHttpServer.vcxproj.filters | 32 + .../StreamingHttpServer/readme.txt | 58 + .../StreamingNamedPipeClient/README.md | 70 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/StreamingNamedPipeClient.cpp | 241 + .../cpp/StreamingNamedPipeClient.sln | 32 + .../cpp/StreamingNamedPipeClient.vcxproj | 266 + .../StreamingNamedPipeClient.vcxproj.filters | 32 + .../StreamingNamedPipeClient/readme.txt | 58 + .../StreamingNamedPipeServer/README.md | 70 + .../cpp/PurchaseOrder.wsdl | 106 + .../cpp/StreamingNamedPipeServer.cpp | 314 + .../cpp/StreamingNamedPipeServer.sln | 32 + .../cpp/StreamingNamedPipeServer.vcxproj | 266 + .../StreamingNamedPipeServer.vcxproj.filters | 32 + .../StreamingNamedPipeServer/readme.txt | 58 + .../WebServices/StreamingTcpClient/README.md | 66 + .../StreamingTcpClient/cpp/PurchaseOrder.wsdl | 106 + .../cpp/StreamingTcpClient.cpp | 241 + .../cpp/StreamingTcpClient.sln | 32 + .../cpp/StreamingTcpClient.vcxproj | 266 + .../cpp/StreamingTcpClient.vcxproj.filters | 32 + .../WebServices/StreamingTcpClient/readme.txt | 60 + .../WebServices/StreamingTcpServer/README.md | 72 + .../StreamingTcpServer/cpp/PurchaseOrder.wsdl | 106 + .../cpp/StreamingTcpServer.cpp | 314 + .../cpp/StreamingTcpServer.sln | 32 + .../cpp/StreamingTcpServer.vcxproj | 266 + .../cpp/StreamingTcpServer.vcxproj.filters | 32 + .../WebServices/StreamingTcpServer/readme.txt | 60 + Samples/WebServices/UnTypedClient/README.md | 60 + .../UnTypedClient/cpp/PurchaseOrder.wsdl | 106 + .../UnTypedClient/cpp/UnTypedClient.cpp | 238 + .../UnTypedClient/cpp/UnTypedClient.sln | 32 + .../UnTypedClient/cpp/UnTypedClient.vcxproj | 266 + .../cpp/UnTypedClient.vcxproj.filters | 32 + Samples/WebServices/UnTypedClient/readme.txt | 57 + Samples/WebServices/UnTypedService/README.md | 68 + .../UnTypedService/cpp/PurchaseOrder.wsdl | 106 + .../UnTypedService/cpp/UnTypedService.cpp | 324 + .../UnTypedService/cpp/UnTypedService.sln | 32 + .../UnTypedService/cpp/UnTypedService.vcxproj | 266 + .../cpp/UnTypedService.vcxproj.filters | 32 + Samples/WebServices/UnTypedService/readme.txt | 58 + .../WcfPublicServiceClient/README.md | 58 + .../cpp/WcfPublicServiceClient.cpp | 174 + .../cpp/WcfPublicServiceClient.sln | 32 + .../cpp/WcfPublicServiceClient.vcxproj | 270 + .../WcfPublicServiceClient.vcxproj.filters | 54 + ...as.microsoft.com.2003.10.Serialization.xsd | 40 + .../cpp/tempuri.org.wsdl | 57 + .../cpp/tempuri.org.xsd | 29 + .../WcfPublicServiceClient/readme.txt | 57 + Samples/WebServices/WriteXmlSimple/README.md | 58 + .../WriteXmlSimple/cpp/WriteXmlSimple.cpp | 176 + .../WriteXmlSimple/cpp/WriteXmlSimple.sln | 32 + .../WriteXmlSimple/cpp/WriteXmlSimple.vcxproj | 255 + .../cpp/WriteXmlSimple.vcxproj.filters | 21 + Samples/WebServices/WriteXmlSimple/readme.txt | 57 + Samples/WebServices/XmlBuffer/README.md | 64 + .../WebServices/XmlBuffer/cpp/XmlBuffer.cpp | 310 + .../WebServices/XmlBuffer/cpp/XmlBuffer.sln | 32 + .../XmlBuffer/cpp/XmlBuffer.vcxproj | 255 + .../XmlBuffer/cpp/XmlBuffer.vcxproj.filters | 21 + Samples/WebServices/XmlBuffer/readme.txt | 57 + Samples/WebServices/XmlDictionary/README.md | 80 + .../XmlDictionary/cpp/XmlDictionary.cpp | 546 + .../XmlDictionary/cpp/XmlDictionary.sln | 32 + .../XmlDictionary/cpp/XmlDictionary.vcxproj | 255 + .../cpp/XmlDictionary.vcxproj.filters | 21 + Samples/WebServices/XmlDictionary/readme.txt | 57 + .../FileService/README.md | 58 + .../FileService/cpp/FileService.sln | 51 + .../cpp/FileServiceClient/Client.cpp | 665 + .../cpp/FileServiceClient/Client.h | 170 + .../FileServiceClient.vcxproj | 143 + .../FileServiceContract/CodeGen_All.config | 582 + .../FileServiceContract/CodeGen_Client.config | 418 + .../FileServiceContract/CodeGen_Host.config | 410 + .../cpp/FileServiceContract/FileService.idl | 178 + .../cpp/FileServiceContract/FileService.wsdl | 199 + .../FileServiceContract.vcxproj | 144 + .../FileServiceContract/FileServiceProxy.cpp | 1076 ++ .../FileServiceContract/FileServiceProxy.h | 164 + .../FileServiceContract/FileServiceStub.cpp | 281 + .../FileServiceContract/FileServiceTypes.cpp | 347 + .../FileServiceContract/FileServiceTypes.h | 279 + .../FileServiceService.vcxproj | 143 + .../cpp/FileServiceService/Service.cpp | 1337 ++ .../cpp/FileServiceService/Service.h | 205 + .../FileService/readme.txt | 173 + .../FileServiceSecure/README.md | 71 + .../cpp/FileServiceSecure.sln | 51 + .../FileServiceSecureClient.vcxproj | 143 + .../FileServiceSecureClient/SecureClient.cpp | 1024 ++ .../FileServiceSecureClient/SecureClient.h | 92 + .../CodeGen_All.config | 637 + .../CodeGen_Client.config | 437 + .../CodeGen_Host.config | 467 + .../FileServiceSecure.idl | 227 + .../FileServiceSecure.wsdl | 159 + .../FileServiceSecureContract.vcxproj | 145 + .../FileServiceSecureProxy.cpp | 1517 +++ .../FileServiceSecureProxy.h | 182 + .../FileServiceSecureStub.cpp | 334 + .../FileServiceSecureTypes.cpp | 319 + .../FileServiceSecureTypes.h | 273 + .../FileServiceSecureService.vcxproj | 143 + .../SecureService.cpp | 1925 +++ .../FileServiceSecureService/SecureService.h | 153 + .../FileServiceSecure/readme.txt | 293 + .../StockQuote/README.md | 65 + .../StockQuote/cpp/StockQuote.sln | 51 + .../cpp/StockQuoteClient/Client.cpp | 145 + .../StockQuote/cpp/StockQuoteClient/Client.h | 14 + .../StockQuoteClient/StockQuoteClient.vcxproj | 143 + .../cpp/StockQuoteContract/CodeGen_All.config | 430 + .../StockQuoteContract/CodeGen_Client.config | 336 + .../StockQuoteContract/CodeGen_Host.config | 258 + .../cpp/StockQuoteContract/StockQuote.idl | 114 + .../cpp/StockQuoteContract/StockQuote.wsdl | 55 + .../StockQuoteContract.vcxproj | 145 + .../StockQuoteContract/StockQuoteProxy.cpp | 640 + .../cpp/StockQuoteContract/StockQuoteProxy.h | 89 + .../cpp/StockQuoteContract/StockQuoteStub.cpp | 206 + .../StockQuoteContract/StockQuoteTypes.cpp | 254 + .../cpp/StockQuoteContract/StockQuoteTypes.h | 184 + .../cpp/StockQuoteContract/stockquote.xsd | 27 + .../StockQuoteContract/stockquoteservice.wsdl | 46 + .../cpp/StockQuoteService/Service.cpp | 288 + .../cpp/StockQuoteService/Service.h | 80 + .../StockQuoteService.vcxproj | 143 + .../StockQuote/readme.txt | 122 + .../WSDiscovery/README.md | 67 + .../WSDiscovery/cpp/Client/Client.cpp | 658 + .../WSDiscovery/cpp/Client/Client.h | 67 + .../WSDiscovery/cpp/Client/Client.vcxproj | 189 + .../cpp/Client/ClientNotificationSink.cpp | 251 + .../cpp/Client/ClientNotificationSink.h | 114 + .../WSDiscovery/cpp/Common/Common.cpp | 902 ++ .../WSDiscovery/cpp/Common/Common.h | 146 + .../WSDiscovery/cpp/Common/Common.vcxproj | 165 + .../WSDiscovery/cpp/Service/Service.cpp | 345 + .../WSDiscovery/cpp/Service/Service.h | 21 + .../WSDiscovery/cpp/Service/Service.vcxproj | 189 + .../WSDiscovery/cpp/Service/TargetService.cpp | 1177 ++ .../WSDiscovery/cpp/Service/TargetService.h | 216 + .../WSDiscovery/cpp/wsdiscovery.sln | 51 + .../WSDiscovery/readme.txt | 53 + .../README.md | 36 + .../cpp/shellClient.cpp | 791 ++ .../cpp/shellClient.sln | 22 + .../cpp/shellClient.vcxproj | 96 + .../cpp/stdafx.cpp | 8 + .../cpp/stdafx.h | 16 + .../cpp/targetver.h | 8 + Samples/Websocket/README.md | 66 + Samples/Websocket/cpp/List.cpp | 96 + Samples/Websocket/cpp/List.h | 50 + Samples/Websocket/cpp/Main.cpp | 408 + Samples/Websocket/cpp/Transport.cpp | 109 + Samples/Websocket/cpp/Transport.h | 27 + Samples/Websocket/cpp/Websocket.sln | 20 + Samples/Websocket/cpp/Websocket.vcxproj | 98 + .../Websocket/cpp/Websocket.vcxproj.filters | 39 + .../FilterProvider/README.md | 57 + .../FilterProvider/cpp/FilterProv.cpp | 451 + .../FilterProvider/cpp/FilterProv.def | 7 + .../FilterProvider/cpp/FilterProv.h | 103 + .../FilterProvider/cpp/FilterProv.sln | 26 + .../FilterProvider/cpp/FilterProv.vcxproj | 178 + .../FilterProvider/cpp/README.txt | 148 + .../ImageEnumeration/README.md | 61 + .../ImageEnumeration/cpp/ImgEnum.sln | 20 + .../ImageEnumeration/cpp/ImgEnum.vcxproj | 99 + .../ImageEnumeration/cpp/README.txt | 173 + .../ImageEnumeration/cpp/imgenum.cpp | 321 + .../ImageEnumeration/cpp/imgenum.rc | 39 + .../ImageEnumeration/cpp/resource.h | 26 + .../Management/WDSTransportManager/README.md | 55 + .../WDSTransportManager/cpp/ReadMe.txt | 111 + .../cpp/WdsTransportManager.cpp | 741 ++ .../cpp/WdsTransportManager.h | 153 + .../cpp/WdsTransportManager.sln | 20 + .../cpp/WdsTransportManager.vcxproj | 108 + .../WDSTransportManager/cpp/stdafx.cpp | 24 + .../WDSTransportManager/cpp/stdafx.h | 53 + .../Multicast/Consumer/README.md | 52 + .../Multicast/Consumer/cpp/README.txt | 84 + .../Multicast/Consumer/cpp/consumer.sln | 20 + .../Multicast/Consumer/cpp/consumer.vcxproj | 103 + .../Multicast/Consumer/cpp/main.cpp | 338 + .../Multicast/Consumer/cpp/wdsscon.rc | 25 + .../Multicast/WdsProvider/README.md | 51 + .../Multicast/WdsProvider/cpp/README.txt | 71 + .../Multicast/WdsProvider/cpp/main.c | 662 + .../Multicast/WdsProvider/cpp/provider.sln | 20 + .../WdsProvider/cpp/provider.vcxproj | 106 + .../Multicast/WdsProvider/cpp/wdscp.def | 6 + .../Multicast/WdsProvider/cpp/wdscp.rc | 24 + .../SampleProvider/README.md | 57 + .../SampleProvider/cpp/README.txt | 114 + .../SampleProvider/cpp/SampProv.cpp | 904 ++ .../SampleProvider/cpp/SampProv.def | 7 + .../SampleProvider/cpp/SampProv.h | 117 + .../SampleProvider/cpp/SampProv.sln | 26 + .../SampleProvider/cpp/SampProv.vcxproj | 176 + Samples/WinhttpProxy/README.md | 63 + Samples/WinhttpProxy/Readme.txt | 72 + Samples/WinhttpProxy/cpp/GetProxy.cpp | 1040 ++ Samples/WinhttpProxy/cpp/GetProxy.h | 201 + .../WinhttpProxy/cpp/WinhttpProxySample.cpp | 543 + .../WinhttpProxy/cpp/WinhttpProxySample.sln | 20 + .../cpp/WinhttpProxySample.vcxproj | 99 + .../cpp/WinhttpProxySample.vcxproj.filters | 30 + Samples/WinhttpWebsocket/README.md | 93 + .../WinhttpWebsocket/cpp/WinhttpWebsocket.cpp | 252 + .../WinhttpWebsocket/cpp/WinhttpWebsocket.sln | 20 + .../cpp/WinhttpWebsocket.vcxproj | 89 + .../cpp/WinhttpWebsocket.vcxproj.filters | 22 + .../cpp/server/RemoveServer.ps1 | 47 + .../cpp/server/SetupServer.ps1 | 61 + .../cpp/server/website/EchoWebSocket.ashx | 101 + Samples/WinsockBluetoothConnection/README.md | 50 + .../WinsockBluetoothConnection/cpp/BthCxn.rc | 13 + .../WinsockBluetoothConnection/cpp/bthcxn.cpp | 863 ++ .../WinsockBluetoothConnection/cpp/bthcxn.sln | 20 + .../cpp/bthcxn.vcxproj | 101 + .../WinsockBluetoothConnection/cpp/readme.txt | 31 + Samples/XmlHttpRequest2GetRequest/README.md | 55 + Samples/XmlHttpRequest2GetRequest/Readme.txt | 38 + .../cpp/XMLHttpRequest2Callback.cpp | 410 + .../cpp/XMLHttpRequest2Callback.h | 96 + .../cpp/XMLHttpRequestGet.cpp | 156 + .../cpp/XMLHttpRequestGet.sln | 22 + .../cpp/XMLHttpRequestGet.vcxproj | 93 + .../cpp/XMLHttpRequestGet.vcxproj.filters | 26 + Samples/XmlHttpRequest2PostRequest/README.md | 55 + .../cpp/XMLHttpRequest2Callback.cpp | 410 + .../cpp/XMLHttpRequest2Callback.h | 96 + .../cpp/XMLHttpRequestPost.cpp | 187 + .../cpp/XMLHttpRequestPost.sln | 22 + .../cpp/XMLHttpRequestPost.vcxproj | 95 + .../cpp/XMLHttpRequestPost.vcxproj.filters | 48 + .../cpp/XMLHttpRequestPostStream.cpp | 235 + .../cpp/XMLHttpRequestPostStream.h | 60 + Samples/XmlHttpRequest3GetRequest/README.md | 49 + Samples/XmlHttpRequest3GetRequest/Readme.txt | 38 + .../cpp/XMLHttpRequest3Callback.cpp | 953 ++ .../cpp/XMLHttpRequest3Callback.h | 162 + .../cpp/XMLHttpRequest3Get.cpp | 238 + .../cpp/XMLHttpRequest3Get.sln | 22 + .../cpp/XMLHttpRequest3Get.vcxproj | 93 + .../cpp/XMLHttpRequest3Get.vcxproj.filters | 26 + Samples/XmlLiteChunkReader/README.md | 41 + .../cpp/XmlLiteChunkReader.cpp | 325 + Samples/XmlLiteChunkReader/cpp/chunks.xml | 6 + .../cpp/xmllitechunkreader.sln | 20 + .../cpp/xmllitechunkreader.vcxproj | 75 + .../cpp/xmllitechunkreader.vcxproj.filters | 22 + Samples/XmlLiteLimitedReader/README.md | 39 + .../cpp/XmlLiteLimitedReader.cpp | 343 + .../XmlLiteLimitedReader/cpp/verylongname.xml | 2 + .../cpp/xmllitelimitedreader.sln | 20 + .../cpp/xmllitelimitedreader.vcxproj | 75 + .../cpp/xmllitelimitedreader.vcxproj.filters | 22 + Samples/XmlLiteNamespaceReader/README.md | 37 + .../cpp/XmlLiteNamespaceReader.cpp | 320 + .../XmlLiteNamespaceReader/cpp/namespaces.xml | 7 + .../cpp/xmllitenamespacereader.sln | 20 + .../cpp/xmllitenamespacereader.vcxproj | 75 + .../xmllitenamespacereader.vcxproj.filters | 22 + Samples/XmlLiteNamespaceWriter1/README.md | 37 + .../cpp/XmlLiteNamespaceWriter1.cpp | 254 + .../cpp/xmllitenamespacewriter1.sln | 20 + .../cpp/xmllitenamespacewriter1.vcxproj | 75 + .../xmllitenamespacewriter1.vcxproj.filters | 22 + Samples/XmlLiteNamespaceWriter2/README.md | 37 + .../cpp/XmlLiteNamespaceWriter2.cpp | 255 + .../cpp/xmllitenamespacewriter2.sln | 20 + .../cpp/xmllitenamespacewriter2.vcxproj | 75 + .../xmllitenamespacewriter2.vcxproj.filters | 22 + Samples/XmlLiteNamespaceWriter3/README.md | 37 + .../cpp/XmlLiteNamespaceWriter3.cpp | 254 + .../cpp/xmllitenamespacewriter3.sln | 20 + .../cpp/xmllitenamespacewriter3.vcxproj | 75 + .../xmllitenamespacewriter3.vcxproj.filters | 22 + Samples/XmlLiteNamespaceWriter4/README.md | 37 + .../cpp/XmlLiteNamespaceWriter4.cpp | 266 + .../cpp/xmllitenamespacewriter4.sln | 20 + .../cpp/xmllitenamespacewriter4.vcxproj | 75 + .../xmllitenamespacewriter4.vcxproj.filters | 22 + .../README.md | 37 + .../cpp/FileStreamWithEPending.cpp | 221 + .../cpp/FileStreamWithEPending.hpp | 92 + .../cpp/InterleavedXML.xml | 14 + .../cpp/InterleavedXmlReader.sln | 20 + .../cpp/InterleavedXmlReader.vcxproj | 79 + .../cpp/InterleavedXmlReader.vcxproj.filters | 30 + .../cpp/Main.cpp | 105 + Samples/XmlLiteNonBlockingRssReader/README.md | 37 + .../XmlLiteNonBlockingRssReader/cpp/Main.cpp | 86 + .../cpp/RssReader.cpp | 272 + .../cpp/RssReader.hpp | 45 + .../cpp/RssReader.sln | 20 + .../cpp/RssReader.vcxproj | 79 + .../cpp/RssReader.vcxproj.filters | 30 + Samples/XmlLiteReadExternalEntities/README.md | 39 + .../cpp/XmlLiteReadExternalEntities.cpp | 362 + .../XmlLiteReadExternalEntities/cpp/date.xml | 4 + .../cpp/xmllitereadexternalentities.sln | 20 + .../cpp/xmllitereadexternalentities.vcxproj | 75 + ...mllitereadexternalentities.vcxproj.filters | 22 + Samples/XmlLiteReadWithEncoding/README.md | 39 + .../cpp/XmlLiteReadWithEncoding.cpp | 380 + .../XmlLiteReadWithEncoding/cpp/encoded.xml | Bin 0 -> 204 bytes .../cpp/xmllitereadwithencoding.sln | 20 + .../cpp/xmllitereadwithencoding.vcxproj | 75 + .../xmllitereadwithencoding.vcxproj.filters | 22 + Samples/XmlLiteReader/README.md | 37 + Samples/XmlLiteReader/cpp/XmlLiteReader.cpp | 220 + Samples/XmlLiteReader/cpp/stocks.xml | 23 + Samples/XmlLiteReader/cpp/xmllitereader.sln | 20 + .../XmlLiteReader/cpp/xmllitereader.vcxproj | 75 + .../cpp/xmllitereader.vcxproj.filters | 22 + Samples/XmlLiteReaderWriter/README.md | 37 + .../cpp/XmlLiteReaderWriter.cpp | 447 + Samples/XmlLiteReaderWriter/cpp/books.xml | 8 + .../cpp/xmllitereaderwriter.sln | 20 + .../cpp/xmllitereaderwriter.vcxproj | 75 + .../cpp/xmllitereaderwriter.vcxproj.filters | 22 + Samples/XmlLiteWriteDocType/README.md | 37 + .../cpp/XmlLiteWriteDocType.cpp | 473 + .../cpp/xmllitewritedoctype.sln | 20 + .../cpp/xmllitewritedoctype.vcxproj | 75 + .../cpp/xmllitewritedoctype.vcxproj.filters | 22 + Samples/XmlLiteWriteWithEncoding/README.md | 37 + .../cpp/XmlLiteWriteWithEncoding.cpp | 272 + .../cpp/xmllitewritewithencoding.sln | 20 + .../cpp/xmllitewritewithencoding.vcxproj | 75 + .../xmllitewritewithencoding.vcxproj.filters | 22 + Samples/XmlLiteWriter/README.md | 37 + Samples/XmlLiteWriter/cpp/XmlLiteWriter.cpp | 316 + Samples/XmlLiteWriter/cpp/xmllitewriter.sln | 20 + .../XmlLiteWriter/cpp/xmllitewriter.vcxproj | 75 + .../cpp/xmllitewriter.vcxproj.filters | 22 + 3255 files changed, 501621 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Samples/AmbientLightAware/README.md create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.cpp create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.h create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.ico create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.rc create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.rc2 create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.sln create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAware.vcxproj create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.cpp create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.h create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.cpp create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.h create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.cpp create mode 100644 Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.h create mode 100644 Samples/AmbientLightAware/cpp/ReadMe.txt create mode 100644 Samples/AmbientLightAware/cpp/resource.h create mode 100644 Samples/AmbientLightAware/cpp/stdafx.cpp create mode 100644 Samples/AmbientLightAware/cpp/stdafx.h create mode 100644 Samples/AppVisibility/README.md create mode 100644 Samples/AppVisibility/cpp/AppVisibilitySample.cpp create mode 100644 Samples/AppVisibility/cpp/AppVisibilitySample.sln create mode 100644 Samples/AppVisibility/cpp/AppVisibilitySample.vcxproj create mode 100644 Samples/AppxPackingCreateAppx/README.md create mode 100644 Samples/AppxPackingCreateAppx/cpp/CreateAppx.cpp create mode 100644 Samples/AppxPackingCreateAppx/cpp/CreateAppx.h create mode 100644 Samples/AppxPackingCreateAppx/cpp/CreateAppx.sln create mode 100644 Samples/AppxPackingCreateAppx/cpp/CreateAppx.vcxproj create mode 100644 Samples/AppxPackingCreateAppx/cpp/Data/AppTile.png create mode 100644 Samples/AppxPackingCreateAppx/cpp/Data/AppxManifest.xml create mode 100644 Samples/AppxPackingCreateAppx/cpp/Data/Default.html create mode 100644 Samples/AppxPackingCreateAppx/cpp/Data/Error.html create mode 100644 Samples/AppxPackingCreateAppx/cpp/Data/images/smiley.jpg create mode 100644 Samples/AppxPackingCreateAppx/cpp/readme.txt create mode 100644 Samples/AppxPackingCreateBundle/README.md create mode 100644 Samples/AppxPackingCreateBundle/cpp/CreateBundle.cpp create mode 100644 Samples/AppxPackingCreateBundle/cpp/CreateBundle.h create mode 100644 Samples/AppxPackingCreateBundle/cpp/CreateBundle.sln create mode 100644 Samples/AppxPackingCreateBundle/cpp/CreateBundle.vcxproj create mode 100644 Samples/AppxPackingCreateBundle/cpp/Data/MainAppPackage.appx create mode 100644 Samples/AppxPackingCreateBundle/cpp/Data/ResourcePackage.lang-de.appx create mode 100644 Samples/AppxPackingCreateBundle/cpp/readme.txt create mode 100644 Samples/AppxPackingDescribeAppx/README.md create mode 100644 Samples/AppxPackingDescribeAppx/cpp/Data/SamplePackage.appx create mode 100644 Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.cpp create mode 100644 Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.h create mode 100644 Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.sln create mode 100644 Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.vcxproj create mode 100644 Samples/AppxPackingDescribeAppx/cpp/readme.txt create mode 100644 Samples/AppxPackingDescribeBundle/README.md create mode 100644 Samples/AppxPackingDescribeBundle/cpp/Data/sample.appxbundle create mode 100644 Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.cpp create mode 100644 Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.h create mode 100644 Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.sln create mode 100644 Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.vcxproj create mode 100644 Samples/AppxPackingDescribeBundle/cpp/readme.txt create mode 100644 Samples/AppxPackingExtractAppx/README.md create mode 100644 Samples/AppxPackingExtractAppx/cpp/Data/HelloWorld.appx create mode 100644 Samples/AppxPackingExtractAppx/cpp/ExtractAppx.cpp create mode 100644 Samples/AppxPackingExtractAppx/cpp/ExtractAppx.h create mode 100644 Samples/AppxPackingExtractAppx/cpp/ExtractAppx.sln create mode 100644 Samples/AppxPackingExtractAppx/cpp/ExtractAppx.vcxproj create mode 100644 Samples/AppxPackingExtractAppx/cpp/readme.txt create mode 100644 Samples/AppxPackingExtractBundle/README.md create mode 100644 Samples/AppxPackingExtractBundle/cpp/Data/sample.appxbundle create mode 100644 Samples/AppxPackingExtractBundle/cpp/ExtractBundle.cpp create mode 100644 Samples/AppxPackingExtractBundle/cpp/ExtractBundle.h create mode 100644 Samples/AppxPackingExtractBundle/cpp/ExtractBundle.sln create mode 100644 Samples/AppxPackingExtractBundle/cpp/ExtractBundle.vcxproj create mode 100644 Samples/AppxPackingExtractBundle/cpp/readme.txt create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/README.md create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.cpp create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.sln create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.vcxproj create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.cpp create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.h create mode 100644 Samples/BacgroundIntelligenceTransferServicePolicy/cpp/targetver.h create mode 100644 Samples/BackgroundCopyFileProperties/README.md create mode 100644 Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.cpp create mode 100644 Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.sln create mode 100644 Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.vcxproj create mode 100644 Samples/BackgroundCopyFileProperties/cpp/stdafx.cpp create mode 100644 Samples/BackgroundCopyFileProperties/cpp/stdafx.h create mode 100644 Samples/BackgroundCopyFileProperties/cpp/targetver.h create mode 100644 Samples/BasicPlugins/README.md create mode 100644 Samples/BasicPlugins/cs/AssemblyInfo.cs create mode 100644 Samples/BasicPlugins/cs/BasicPlugins.csproj create mode 100644 Samples/BasicPlugins/cs/BasicPlugins.sln create mode 100644 Samples/BasicPlugins/cs/CustomAuthorization.cs create mode 100644 Samples/BasicPlugins/cs/SessionConfiguration.cs create mode 100644 Samples/BasicPlugins/cs/setup/InstallModata.ps1 create mode 100644 Samples/BasicPlugins/cs/setup/Microsoft.Management.Odata.svc create mode 100644 Samples/BasicPlugins/cs/setup/Readme.txt create mode 100644 Samples/BasicPlugins/cs/setup/Schema.mof create mode 100644 Samples/BasicPlugins/cs/setup/Schema.xml create mode 100644 Samples/BasicPlugins/cs/setup/SetupEndpoint.ps1 create mode 100644 Samples/BasicPlugins/cs/setup/SetupIISConfig.ps1 create mode 100644 Samples/BasicPlugins/cs/setup/Web.config create mode 100644 Samples/CaptureEngineVideoCapture/README.md create mode 100644 Samples/CaptureEngineVideoCapture/cpp/Capture.cpp create mode 100644 Samples/CaptureEngineVideoCapture/cpp/Capture.h create mode 100644 Samples/CaptureEngineVideoCapture/cpp/Capture.rc create mode 100644 Samples/CaptureEngineVideoCapture/cpp/CaptureEngine.sln create mode 100644 Samples/CaptureEngineVideoCapture/cpp/CaptureEngine.vcxproj create mode 100644 Samples/CaptureEngineVideoCapture/cpp/PreviewWnd.cpp create mode 100644 Samples/CaptureEngineVideoCapture/cpp/resource.h create mode 100644 Samples/CaptureEngineVideoCapture/cpp/utils.cpp create mode 100644 Samples/CaptureEngineVideoCapture/cpp/winmain.cpp create mode 100644 Samples/CauSamplePlugin/README.md create mode 100644 Samples/CauSamplePlugin/cs/AssemblyInfo.cs create mode 100644 Samples/CauSamplePlugin/cs/CauSamplePlugin.csproj create mode 100644 Samples/CauSamplePlugin/cs/CauSamplePlugin.rc create mode 100644 Samples/CauSamplePlugin/cs/CauSamplePlugin.sln create mode 100644 Samples/CauSamplePlugin/cs/FabrikamCauPlugin.cs create mode 100644 Samples/ClsIDCallback/README.md create mode 100644 Samples/ClsIDCallback/cpp/ClsIDCallback.cpp create mode 100644 Samples/ClsIDCallback/cpp/ClsIDCallback.sln create mode 100644 Samples/ClsIDCallback/cpp/ClsIDCallback.vcxproj create mode 100644 Samples/ClsIDCallback/cpp/NotifyInterfaceImp.cpp create mode 100644 Samples/ClsIDCallback/cpp/NotifyInterfaceImp.h create mode 100644 Samples/ClsIDCallback/cpp/ReadMe.txt create mode 100644 Samples/ClsIDCallback/cpp/stdafx.cpp create mode 100644 Samples/ClsIDCallback/cpp/stdafx.h create mode 100644 Samples/ClsIDCallback/cpp/targetver.h create mode 100644 Samples/ClsIDCallback/cpp/utils.cpp create mode 100644 Samples/ClsIDCallback/cpp/utils.h create mode 100644 Samples/ConnectionManagerCost/README.md create mode 100644 Samples/ConnectionManagerCost/Readme.txt create mode 100644 Samples/ConnectionManagerCost/cpp/Utils.cpp create mode 100644 Samples/ConnectionManagerCost/cpp/Utils.h create mode 100644 Samples/ConnectionManagerCost/cpp/WcmCostSample.sln create mode 100644 Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj create mode 100644 Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj.filters create mode 100644 Samples/ConnectionManagerCost/cpp/Wcmcostsample.cpp create mode 100644 Samples/ConnectionManagerCost/cpp/Wcmcostsample.h create mode 100644 Samples/CredentialProvider/README.md create mode 100644 Samples/CredentialProvider/cpp/CSampleCredential.cpp create mode 100644 Samples/CredentialProvider/cpp/CSampleCredential.h create mode 100644 Samples/CredentialProvider/cpp/CSampleProvider.cpp create mode 100644 Samples/CredentialProvider/cpp/CSampleProvider.h create mode 100644 Samples/CredentialProvider/cpp/Dll.cpp create mode 100644 Samples/CredentialProvider/cpp/Dll.h create mode 100644 Samples/CredentialProvider/cpp/SampleV2CredentialProvider.sln create mode 100644 Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj create mode 100644 Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj.filters create mode 100644 Samples/CredentialProvider/cpp/Unregister.reg create mode 100644 Samples/CredentialProvider/cpp/common.h create mode 100644 Samples/CredentialProvider/cpp/guid.cpp create mode 100644 Samples/CredentialProvider/cpp/guid.h create mode 100644 Samples/CredentialProvider/cpp/helpers.cpp create mode 100644 Samples/CredentialProvider/cpp/helpers.h create mode 100644 Samples/CredentialProvider/cpp/register.reg create mode 100644 Samples/CredentialProvider/cpp/resource.h create mode 100644 Samples/CredentialProvider/cpp/resources.rc create mode 100644 Samples/CredentialProvider/cpp/samplev2credentialprovider.def create mode 100644 Samples/CredentialProvider/cpp/tileimage.bmp create mode 100644 Samples/CustomResourceManager/README.md create mode 100644 Samples/CustomResourceManager/cpp/CSecInfo.cpp create mode 100644 Samples/CustomResourceManager/cpp/CSecInfo.h create mode 100644 Samples/CustomResourceManager/cpp/CustomResourceManager.sln create mode 100644 Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj create mode 100644 Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj.filters create mode 100644 Samples/CustomResourceManager/cpp/SecurityInformation1.cpp create mode 100644 Samples/CustomResourceManager/cpp/main.cpp create mode 100644 Samples/CustomResourceManager/cpp/resource.cpp create mode 100644 Samples/CustomResourceManager/cpp/resource.h create mode 100644 Samples/CustomResourceManager/cpp/utility.cpp create mode 100644 Samples/CustomResourceManager/cpp/utility.h create mode 100644 Samples/D2DPrintingFromDesktopApps/README.md create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.cpp create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.h create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.cpp create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.h create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.sln create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.vcxproj create mode 100644 Samples/D2DPrintingFromDesktopApps/cpp/sampleimage.jpg create mode 100644 Samples/DCompV2BackfaceandD2DBatching/README.md create mode 100644 Samples/DCompV2BackfaceandD2DBatching/cpp/Application.cpp create mode 100644 Samples/DCompV2BackfaceandD2DBatching/cpp/Application.h create mode 100644 Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.sln create mode 100644 Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.vcxproj create mode 100644 Samples/DCompV2BackfaceandD2DBatching/cpp/Main.cpp create mode 100644 Samples/DHCP/AddPolicyRange/README.md create mode 100644 Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.cpp create mode 100644 Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.sln create mode 100644 Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.vcxproj create mode 100644 Samples/DHCP/AddScopeToRelationship/README.md create mode 100644 Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.cpp create mode 100644 Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.sln create mode 100644 Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.vcxproj create mode 100644 Samples/DHCP/CreatePolicy/README.md create mode 100644 Samples/DHCP/CreatePolicy/cpp/createpolicy.cpp create mode 100644 Samples/DHCP/CreatePolicy/cpp/createpolicy.sln create mode 100644 Samples/DHCP/CreatePolicy/cpp/createpolicy.vcxproj create mode 100644 Samples/DHCP/CreateRelationship/README.md create mode 100644 Samples/DHCP/CreateRelationship/cpp/createrelationship.cpp create mode 100644 Samples/DHCP/CreateRelationship/cpp/createrelationship.sln create mode 100644 Samples/DHCP/CreateRelationship/cpp/createrelationship.vcxproj create mode 100644 Samples/DHCP/DeletePolicy/README.md create mode 100644 Samples/DHCP/DeletePolicy/cpp/deletepolicy.cpp create mode 100644 Samples/DHCP/DeletePolicy/cpp/deletepolicy.sln create mode 100644 Samples/DHCP/DeletePolicy/cpp/deletepolicy.vcxproj create mode 100644 Samples/DHCP/DeleteRelationship/README.md create mode 100644 Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.cpp create mode 100644 Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.sln create mode 100644 Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.vcxproj create mode 100644 Samples/DHCP/DeleteScopeFromRelationship/README.md create mode 100644 Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.cpp create mode 100644 Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.sln create mode 100644 Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.vcxproj create mode 100644 Samples/DHCP/EnumPolicy/README.md create mode 100644 Samples/DHCP/EnumPolicy/cpp/enumpolicy.cpp create mode 100644 Samples/DHCP/EnumPolicy/cpp/enumpolicy.sln create mode 100644 Samples/DHCP/EnumPolicy/cpp/enumpolicy.vcxproj create mode 100644 Samples/DHCP/EnumRelationship/README.md create mode 100644 Samples/DHCP/EnumRelationship/cpp/EnumRelationship.cpp create mode 100644 Samples/DHCP/EnumRelationship/cpp/EnumRelationship.sln create mode 100644 Samples/DHCP/EnumRelationship/cpp/EnumRelationship.vcxproj create mode 100644 Samples/DHCP/EnumSubnetClients/README.md create mode 100644 Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.cpp create mode 100644 Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.sln create mode 100644 Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.vcxproj create mode 100644 Samples/DHCP/EnumSubnetReservations/README.md create mode 100644 Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.cpp create mode 100644 Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.sln create mode 100644 Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.vcxproj create mode 100644 Samples/DHCP/GetAddressStatus/README.md create mode 100644 Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.cpp create mode 100644 Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.sln create mode 100644 Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.vcxproj create mode 100644 Samples/DHCP/GetClientInfo/README.md create mode 100644 Samples/DHCP/GetClientInfo/cpp/GetClientInfo.cpp create mode 100644 Samples/DHCP/GetClientInfo/cpp/GetClientInfo.sln create mode 100644 Samples/DHCP/GetClientInfo/cpp/GetClientInfo.vcxproj create mode 100644 Samples/DHCP/GetPolicy/README.md create mode 100644 Samples/DHCP/GetPolicy/cpp/getpolicy.cpp create mode 100644 Samples/DHCP/GetPolicy/cpp/getpolicy.sln create mode 100644 Samples/DHCP/GetPolicy/cpp/getpolicy.vcxproj create mode 100644 Samples/DHCP/GetRelationship/README.md create mode 100644 Samples/DHCP/GetRelationship/cpp/GetRelationship.cpp create mode 100644 Samples/DHCP/GetRelationship/cpp/GetRelationship.sln create mode 100644 Samples/DHCP/GetRelationship/cpp/GetRelationship.vcxproj create mode 100644 Samples/DHCP/GetScopeRelationship/README.md create mode 100644 Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.cpp create mode 100644 Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.sln create mode 100644 Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.vcxproj create mode 100644 Samples/DHCP/GetScopeStatistics/README.md create mode 100644 Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.cpp create mode 100644 Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.sln create mode 100644 Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.vcxproj create mode 100644 Samples/DHCP/GetStatelessStatistics/README.md create mode 100644 Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.cpp create mode 100644 Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.sln create mode 100644 Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.vcxproj create mode 100644 Samples/DHCP/GetStatelessStoreParams/README.md create mode 100644 Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.cpp create mode 100644 Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.sln create mode 100644 Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.vcxproj create mode 100644 Samples/DHCP/GetSystemTime/README.md create mode 100644 Samples/DHCP/GetSystemTime/cpp/GetSystemTime.cpp create mode 100644 Samples/DHCP/GetSystemTime/cpp/GetSystemTime.sln create mode 100644 Samples/DHCP/GetSystemTime/cpp/GetSystemTime.vcxproj create mode 100644 Samples/DHCP/HlprAddPolicyCondition/README.md create mode 100644 Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.cpp create mode 100644 Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.sln create mode 100644 Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.vcxproj create mode 100644 Samples/DHCP/HlprAddPolicyExpr/README.md create mode 100644 Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.cpp create mode 100644 Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.sln create mode 100644 Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.vcxproj create mode 100644 Samples/DHCP/HlprAddPolicyRange/README.md create mode 100644 Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.cpp create mode 100644 Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.sln create mode 100644 Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.vcxproj create mode 100644 Samples/DHCP/HlprCreatePolicy/README.md create mode 100644 Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.cpp create mode 100644 Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.sln create mode 100644 Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.vcxproj create mode 100644 Samples/DHCP/HlprIsPolicySingleUC/README.md create mode 100644 Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.cpp create mode 100644 Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.sln create mode 100644 Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.vcxproj create mode 100644 Samples/DHCP/HlprIsPolicyWellFormed/README.md create mode 100644 Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.cpp create mode 100644 Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.sln create mode 100644 Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.vcxproj create mode 100644 Samples/DHCP/HlprModifyPolicyExpr/README.md create mode 100644 Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.cpp create mode 100644 Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.sln create mode 100644 Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.vcxproj create mode 100644 Samples/DHCP/HlprResetPolicyExpr/README.md create mode 100644 Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.cpp create mode 100644 Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.sln create mode 100644 Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.vcxproj create mode 100644 Samples/DHCP/HlprisPolicyValid/README.md create mode 100644 Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.cpp create mode 100644 Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.sln create mode 100644 Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.vcxproj create mode 100644 Samples/DHCP/QueryPolicyEnforcement/README.md create mode 100644 Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.cpp create mode 100644 Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.sln create mode 100644 Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.vcxproj create mode 100644 Samples/DHCP/RemovePolicyRange/README.md create mode 100644 Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.cpp create mode 100644 Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.sln create mode 100644 Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.vcxproj create mode 100644 Samples/DHCP/SetPolicy/README.md create mode 100644 Samples/DHCP/SetPolicy/cpp/setpolicy.cpp create mode 100644 Samples/DHCP/SetPolicy/cpp/setpolicy.sln create mode 100644 Samples/DHCP/SetPolicy/cpp/setpolicy.vcxproj create mode 100644 Samples/DHCP/SetPolicyEnforcement/README.md create mode 100644 Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.cpp create mode 100644 Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.sln create mode 100644 Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.vcxproj create mode 100644 Samples/DHCP/SetRelationship/README.md create mode 100644 Samples/DHCP/SetRelationship/cpp/setrelationship.cpp create mode 100644 Samples/DHCP/SetRelationship/cpp/setrelationship.sln create mode 100644 Samples/DHCP/SetRelationship/cpp/setrelationship.vcxproj create mode 100644 Samples/DHCP/SetStatelessStoreParams/README.md create mode 100644 Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.cpp create mode 100644 Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.sln create mode 100644 Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.vcxproj create mode 100644 Samples/DHCP/TriggerAddrAllocation/README.md create mode 100644 Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.cpp create mode 100644 Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.sln create mode 100644 Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.vcxproj create mode 100644 Samples/DHCP/V4CreateClientInfo/README.md create mode 100644 Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.cpp create mode 100644 Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.sln create mode 100644 Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.vcxproj create mode 100644 Samples/DHCP/V4GetAllOptionValue/README.md create mode 100644 Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.cpp create mode 100644 Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.sln create mode 100644 Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.vcxproj create mode 100644 Samples/DHCP/V4GetClientInfo/README.md create mode 100644 Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.cpp create mode 100644 Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.sln create mode 100644 Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.vcxproj create mode 100644 Samples/DHCP/V4GetFreeIPAddress/README.md create mode 100644 Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.cpp create mode 100644 Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.sln create mode 100644 Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.vcxproj create mode 100644 Samples/DHCP/V6CreateClientInfo/README.md create mode 100644 Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.cpp create mode 100644 Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.sln create mode 100644 Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.vcxproj create mode 100644 Samples/DHCP/V6GetFreeIPAddress/README.md create mode 100644 Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.cpp create mode 100644 Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.sln create mode 100644 Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.vcxproj create mode 100644 Samples/DHCP/v4GetOptionValue/README.md create mode 100644 Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.cpp create mode 100644 Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.sln create mode 100644 Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.vcxproj create mode 100644 Samples/DHCP/v4RemoveOptionValue/README.md create mode 100644 Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.cpp create mode 100644 Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.sln create mode 100644 Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.vcxproj create mode 100644 Samples/DHCP/v4SetOptionValue/README.md create mode 100644 Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.cpp create mode 100644 Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.sln create mode 100644 Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.vcxproj create mode 100644 Samples/DHCP/v4SetOptionValues/README.md create mode 100644 Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.cpp create mode 100644 Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.sln create mode 100644 Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.vcxproj create mode 100644 Samples/DNSAsyncNetworkNameResolution/README.md create mode 100644 Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.cpp create mode 100644 Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.sln create mode 100644 Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.vcxproj create mode 100644 Samples/DNSAsyncQuery/README.md create mode 100644 Samples/DNSAsyncQuery/cpp/DnsQueryEx.cpp create mode 100644 Samples/DNSAsyncQuery/cpp/DnsQueryEx.sln create mode 100644 Samples/DNSAsyncQuery/cpp/DnsQueryEx.vcxproj create mode 100644 Samples/DNSAsyncQuery/cpp/ParseArgs.cpp create mode 100644 Samples/DNSAsyncQuery/cpp/PrintDnsRecord.cpp create mode 100644 Samples/DPIAwarenessPerMonitor/README.md create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.cpp create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.h create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.ico create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.rc create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.sln create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.vcxproj create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.vcxproj.filters create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/Resource.h create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/scaled100.bmp create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/scaled125.bmp create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/scaled150.bmp create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/scaled200.bmp create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/small.ico create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/stdafx.cpp create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/stdafx.h create mode 100644 Samples/DPIAwarenessPerMonitor/cpp/targetver.h create mode 100644 Samples/DX11VideoRenderer/README.md create mode 100644 Samples/DX11VideoRenderer/cpp/Activate.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/Activate.h create mode 100644 Samples/DX11VideoRenderer/cpp/ClassFactory.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/ClassFactory.h create mode 100644 Samples/DX11VideoRenderer/cpp/Common.h create mode 100644 Samples/DX11VideoRenderer/cpp/DLLMain.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.def create mode 100644 Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.h create mode 100644 Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.sln create mode 100644 Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.vcxproj create mode 100644 Samples/DX11VideoRenderer/cpp/MFAttributesImpl.h create mode 100644 Samples/DX11VideoRenderer/cpp/Marker.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/Marker.h create mode 100644 Samples/DX11VideoRenderer/cpp/MediaSink.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/MediaSink.h create mode 100644 Samples/DX11VideoRenderer/cpp/Presenter.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/Presenter.h create mode 100644 Samples/DX11VideoRenderer/cpp/Scheduler.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/Scheduler.h create mode 100644 Samples/DX11VideoRenderer/cpp/StaticAsyncCallback.h create mode 100644 Samples/DX11VideoRenderer/cpp/StreamSink.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/StreamSink.h create mode 100644 Samples/DX11VideoRenderer/cpp/display.cpp create mode 100644 Samples/DX11VideoRenderer/cpp/display.h create mode 100644 Samples/DX11VideoRenderer/cpp/linklist.h create mode 100644 Samples/DXGIDesktopDuplication/README.md create mode 100644 Samples/DXGIDesktopDuplication/cpp/CommonTypes.h create mode 100644 Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.cpp create mode 100644 Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.sln create mode 100644 Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.vcxproj create mode 100644 Samples/DXGIDesktopDuplication/cpp/DisplayManager.cpp create mode 100644 Samples/DXGIDesktopDuplication/cpp/DisplayManager.h create mode 100644 Samples/DXGIDesktopDuplication/cpp/DuplicationManager.cpp create mode 100644 Samples/DXGIDesktopDuplication/cpp/DuplicationManager.h create mode 100644 Samples/DXGIDesktopDuplication/cpp/OutputManager.cpp create mode 100644 Samples/DXGIDesktopDuplication/cpp/OutputManager.h create mode 100644 Samples/DXGIDesktopDuplication/cpp/PixelShader.hlsl create mode 100644 Samples/DXGIDesktopDuplication/cpp/ThreadManager.cpp create mode 100644 Samples/DXGIDesktopDuplication/cpp/ThreadManager.h create mode 100644 Samples/DXGIDesktopDuplication/cpp/VertexShader.hlsl create mode 100644 Samples/DataDedupBackupRestore/README.md create mode 100644 Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.cpp create mode 100644 Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.sln create mode 100644 Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.vcxproj create mode 100644 Samples/DesktopAutomationDismiss/README.md create mode 100644 Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.sln create mode 100644 Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.vcxproj create mode 100644 Samples/DesktopAutomationDismiss/cpp/ShowDesktop.cpp create mode 100644 Samples/DesktopAutomationDismiss/cpp/readme.txt create mode 100644 Samples/DesktopToasts/README.md create mode 100644 Samples/DesktopToasts/cpp/DesktopToastsSample.cpp create mode 100644 Samples/DesktopToasts/cpp/DesktopToastsSample.h create mode 100644 Samples/DesktopToasts/cpp/DesktopToastsSample.sln create mode 100644 Samples/DesktopToasts/cpp/DesktopToastsSample.vcxproj create mode 100644 Samples/DesktopToasts/cpp/Product.wxs create mode 100644 Samples/DesktopToasts/cpp/StringReferenceWrapper.h create mode 100644 Samples/DesktopToasts/cpp/ToastEventHandler.cpp create mode 100644 Samples/DesktopToasts/cpp/ToastEventHandler.h create mode 100644 Samples/DesktopToasts/cpp/stdafx.cpp create mode 100644 Samples/DesktopToasts/cpp/stdafx.h create mode 100644 Samples/DesktopToasts/cpp/toastImageAndText.png create mode 100644 Samples/DesktopToasts/cs/App.config create mode 100644 Samples/DesktopToasts/cs/App.xaml create mode 100644 Samples/DesktopToasts/cs/App.xaml.cs create mode 100644 Samples/DesktopToasts/cs/DesktopToastsSample.csproj create mode 100644 Samples/DesktopToasts/cs/DesktopToastsSample.sln create mode 100644 Samples/DesktopToasts/cs/MainWindow.xaml create mode 100644 Samples/DesktopToasts/cs/MainWindow.xaml.cs create mode 100644 Samples/DesktopToasts/cs/Product.wxs create mode 100644 Samples/DesktopToasts/cs/Properties/AssemblyInfo.cs create mode 100644 Samples/DesktopToasts/cs/Properties/Resources.Designer.cs create mode 100644 Samples/DesktopToasts/cs/Properties/Resources.resx create mode 100644 Samples/DesktopToasts/cs/Properties/Settings.Designer.cs create mode 100644 Samples/DesktopToasts/cs/Properties/Settings.settings create mode 100644 Samples/DesktopToasts/cs/ShellHelpers.cs create mode 100644 Samples/DesktopToasts/cs/toastImageAndText.png create mode 100644 Samples/DetectBootSector/README.md create mode 100644 Samples/DetectBootSector/cpp/DetectBootSector.cpp create mode 100644 Samples/DetectBootSector/cpp/DetectBootSector.sln create mode 100644 Samples/DetectBootSector/cpp/DetectBootSector.vcxproj create mode 100644 Samples/DirectCompositionEffects/README.md create mode 100644 Samples/DirectCompositionEffects/cpp/Application.cpp create mode 100644 Samples/DirectCompositionEffects/cpp/Application.h create mode 100644 Samples/DirectCompositionEffects/cpp/Application.rc create mode 100644 Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.sln create mode 100644 Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.vcxproj create mode 100644 Samples/DirectCompositionEffects/cpp/Main.cpp create mode 100644 Samples/DirectCompositionEffects/cpp/resource.h create mode 100644 Samples/DirectCompositionLayeredChildWindow/README.md create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.cpp create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.h create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.manifest create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.rc create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.sln create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.vcxproj create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/media/TallShip-medium.wmv create mode 100644 Samples/DirectCompositionLayeredChildWindow/cpp/resource.h create mode 100644 Samples/DirectCompositionWindowsAnimationManager/README.md create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/220Strawberry.png create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/Application.rc create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/DirectComposition_WAM.cpp create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/DirectComposition_WAM.h create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/DirectComposition_WAM.sln create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/DirectComposition_WAM.vcxproj create mode 100644 Samples/DirectCompositionWindowsAnimationManager/cpp/resource.h create mode 100644 Samples/DirectXTextureConverter/Cpp/BC.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/BC.h create mode 100644 Samples/DirectXTextureConverter/Cpp/BC4BC5.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/BC6HBC7.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DDS.h create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTex.h create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTex.inl create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexCompress.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexConvert.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexD3D11.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexDDS.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexFlipRotate.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexImage.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexMipMaps.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexMisc.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexNormalMaps.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexPMAlpha.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexResize.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexTGA.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexUtil.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexWIC.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/DirectXTexp.h create mode 100644 Samples/DirectXTextureConverter/Cpp/Texconv.sln create mode 100644 Samples/DirectXTextureConverter/Cpp/Texconv.vcxproj create mode 100644 Samples/DirectXTextureConverter/Cpp/Texconv.vcxproj.filters create mode 100644 Samples/DirectXTextureConverter/Cpp/filters.h create mode 100644 Samples/DirectXTextureConverter/Cpp/scoped.h create mode 100644 Samples/DirectXTextureConverter/Cpp/texconv.cpp create mode 100644 Samples/DirectXTextureConverter/Cpp/texconv.rc create mode 100644 Samples/DirectXTextureConverter/README.md create mode 100644 Samples/DynamicDPI/README.md create mode 100644 Samples/DynamicDPI/cpp/Application.cpp create mode 100644 Samples/DynamicDPI/cpp/Application.h create mode 100644 Samples/DynamicDPI/cpp/ColorToolbarIcons.ttf create mode 100644 Samples/DynamicDPI/cpp/DeviceResources.cpp create mode 100644 Samples/DynamicDPI/cpp/DeviceResources.h create mode 100644 Samples/DynamicDPI/cpp/DirectXHelper.h create mode 100644 Samples/DynamicDPI/cpp/DynamicDPI.rc create mode 100644 Samples/DynamicDPI/cpp/DynamicDPI.sln create mode 100644 Samples/DynamicDPI/cpp/DynamicDPI.vcxproj create mode 100644 Samples/DynamicDPI/cpp/DynamicDPI.vcxproj.filters create mode 100644 Samples/DynamicDPI/cpp/FontFileStream.cpp create mode 100644 Samples/DynamicDPI/cpp/FontFileStream.h create mode 100644 Samples/DynamicDPI/cpp/FontLoader.cpp create mode 100644 Samples/DynamicDPI/cpp/FontLoader.h create mode 100644 Samples/DynamicDPI/cpp/LinearEaseInOutAnimation.cpp create mode 100644 Samples/DynamicDPI/cpp/LinearEaseInOutAnimation.h create mode 100644 Samples/DynamicDPI/cpp/SampleCustomColorFontButton.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleCustomColorFontButton.h create mode 100644 Samples/DynamicDPI/cpp/SampleDesktopWindow.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleDesktopWindow.h create mode 100644 Samples/DynamicDPI/cpp/SampleDynamicDpiWindow.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleDynamicDpiWindow.h create mode 100644 Samples/DynamicDPI/cpp/SampleElementAnimation.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleElementAnimation.h create mode 100644 Samples/DynamicDPI/cpp/SampleElementBase.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleElementBase.h create mode 100644 Samples/DynamicDPI/cpp/SampleElementTextBlock.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleElementTextBlock.h create mode 100644 Samples/DynamicDPI/cpp/SampleEngine.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleEngine.h create mode 100644 Samples/DynamicDPI/cpp/SampleHoverElement.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleHoverElement.h create mode 100644 Samples/DynamicDPI/cpp/SampleMultiDpiImage.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleMultiDpiImage.h create mode 100644 Samples/DynamicDPI/cpp/SampleRichEditControl.cpp create mode 100644 Samples/DynamicDPI/cpp/SampleRichEditControl.h create mode 100644 Samples/DynamicDPI/cpp/SlimRWLock.cpp create mode 100644 Samples/DynamicDPI/cpp/SlimRWLock.h create mode 100644 Samples/DynamicDPI/cpp/pch.cpp create mode 100644 Samples/DynamicDPI/cpp/pch.h create mode 100644 Samples/DynamicDPI/cpp/png100.png create mode 100644 Samples/DynamicDPI/cpp/png125.png create mode 100644 Samples/DynamicDPI/cpp/png150.png create mode 100644 Samples/DynamicDPI/cpp/png200.png create mode 100644 Samples/DynamicDPI/cpp/resource.h create mode 100644 Samples/EapHostClientMethod/README.md create mode 100644 Samples/EapHostClientMethod/Readme.txt create mode 100644 Samples/EapHostClientMethod/cpp/DllMain.cpp create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethod.cpp create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethod.h create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethod.rc create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethodConfig.rc create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethodSample.def create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethodSample.sln create mode 100644 Samples/EapHostClientMethod/cpp/EapHostClientMethodSample.vcxproj create mode 100644 Samples/EapHostClientMethod/cpp/EapHostCommon.cpp create mode 100644 Samples/EapHostClientMethod/cpp/EapHostCommon.h create mode 100644 Samples/EapHostClientMethod/cpp/memory.cpp create mode 100644 Samples/EapHostClientMethod/cpp/memory.h create mode 100644 Samples/EapHostClientMethod/cpp/resource.h create mode 100644 Samples/EapHostServerMethod/README.md create mode 100644 Samples/EapHostServerMethod/Readme.txt create mode 100644 Samples/EapHostServerMethod/cpp/DllMain.cpp create mode 100644 Samples/EapHostServerMethod/cpp/EapHostCommon.cpp create mode 100644 Samples/EapHostServerMethod/cpp/EapHostCommon.h create mode 100644 Samples/EapHostServerMethod/cpp/EapHostServerMethod.cpp create mode 100644 Samples/EapHostServerMethod/cpp/EapHostServerMethod.h create mode 100644 Samples/EapHostServerMethod/cpp/EapHostServerMethodConfig.rc create mode 100644 Samples/EapHostServerMethod/cpp/EapHostServerMethodSample.def create mode 100644 Samples/EapHostServerMethod/cpp/EapHostServerMethodSample.sln create mode 100644 Samples/EapHostServerMethod/cpp/EapHostServerMethodSample.vcxproj create mode 100644 Samples/EapHostServerMethod/cpp/memory.cpp create mode 100644 Samples/EapHostServerMethod/cpp/memory.h create mode 100644 Samples/EapHostServerMethod/cpp/resource.h create mode 100644 Samples/EapHostSupplicant/README.md create mode 100644 Samples/EapHostSupplicant/Readme.txt create mode 100644 Samples/EapHostSupplicant/cpp/EapHostCommon.cpp create mode 100644 Samples/EapHostSupplicant/cpp/EapHostCommon.h create mode 100644 Samples/EapHostSupplicant/cpp/EapHostConn.xml create mode 100644 Samples/EapHostSupplicant/cpp/EapHostSupplicant.cpp create mode 100644 Samples/EapHostSupplicant/cpp/EapHostSupplicant.h create mode 100644 Samples/EapHostSupplicant/cpp/EapHostSupplicant.rc create mode 100644 Samples/EapHostSupplicant/cpp/EapHostSupplicantMain.cpp create mode 100644 Samples/EapHostSupplicant/cpp/EapHostSupplicantSample.sln create mode 100644 Samples/EapHostSupplicant/cpp/EapHostSupplicantSample.vcxproj create mode 100644 Samples/EapHostSupplicant/cpp/EapHostUser.xml create mode 100644 Samples/EapHostSupplicant/cpp/memory.cpp create mode 100644 Samples/EapHostSupplicant/cpp/memory.h create mode 100644 Samples/EapHostSupplicant/cpp/resource.h create mode 100644 Samples/FmapiVersionCheck/README.md create mode 100644 Samples/FmapiVersionCheck/cpp/FmapiVersionCheck.cpp create mode 100644 Samples/FmapiVersionCheck/cpp/FmapiVersionCheck.sln create mode 100644 Samples/FmapiVersionCheck/cpp/FmapiVersionCheck.vcxproj create mode 100644 Samples/HangulDecomposition/README.md create mode 100644 Samples/HangulDecomposition/cpp/HangulDecomposition.cpp create mode 100644 Samples/HangulDecomposition/cpp/HangulDecomposition.sln create mode 100644 Samples/HangulDecomposition/cpp/HangulDecomposition.vcxproj create mode 100644 Samples/HangulDecomposition/cpp/HangulDecomposition.vcxproj.filters create mode 100644 Samples/HttpInternationalDomainName/README.md create mode 100644 Samples/HttpInternationalDomainName/cpp/IdnSample.cpp create mode 100644 Samples/HttpInternationalDomainName/cpp/IdnSample.sln create mode 100644 Samples/HttpInternationalDomainName/cpp/IdnSample.vcxproj create mode 100644 Samples/HttpSSLConfig/README.md create mode 100644 Samples/HttpSSLConfig/cpp/SslConfig.cpp create mode 100644 Samples/HttpSSLConfig/cpp/SslConfig.sln create mode 100644 Samples/HttpSSLConfig/cpp/SslConfig.vcxproj create mode 100644 Samples/Hyper-V/AppHealth/README.md create mode 100644 Samples/Hyper-V/AppHealth/cs/AppHealth.csproj create mode 100644 Samples/Hyper-V/AppHealth/cs/AppHealth.sln create mode 100644 Samples/Hyper-V/AppHealth/cs/AppHealthStatus.cs create mode 100644 Samples/Hyper-V/AppHealth/cs/Program.cs create mode 100644 Samples/Hyper-V/AppHealth/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/AppHealth/desktop.ico create mode 100644 Samples/Hyper-V/DynamicMemory/README.md create mode 100644 Samples/Hyper-V/DynamicMemory/cs/DynMem.csproj create mode 100644 Samples/Hyper-V/DynamicMemory/cs/DynMem.sln create mode 100644 Samples/Hyper-V/DynamicMemory/cs/Program.cs create mode 100644 Samples/Hyper-V/DynamicMemory/cs/Slp.cs create mode 100644 Samples/Hyper-V/DynamicMemory/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/DynamicMemory/desktop.ico create mode 100644 Samples/Hyper-V/EnhancedSession/README.md create mode 100644 Samples/Hyper-V/EnhancedSession/cs/Available.cs create mode 100644 Samples/Hyper-V/EnhancedSession/cs/Enable.cs create mode 100644 Samples/Hyper-V/EnhancedSession/cs/EnhancedSession.csproj create mode 100644 Samples/Hyper-V/EnhancedSession/cs/EnhancedSession.sln create mode 100644 Samples/Hyper-V/EnhancedSession/cs/Program.cs create mode 100644 Samples/Hyper-V/EnhancedSession/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/EnhancedSession/desktop.ico create mode 100644 Samples/Hyper-V/FibreChannel/README.md create mode 100644 Samples/Hyper-V/FibreChannel/cs/ConfigureWwnGenerator.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/CreateSan.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/CreateVirtualFcPort.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/DeleteSan.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/DeleteVirtualFcPort.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/EnumerateFcPorts.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/FibreChannel.csproj create mode 100644 Samples/Hyper-V/FibreChannel/cs/FibreChannel.sln create mode 100644 Samples/Hyper-V/FibreChannel/cs/FibreChannelUtilities.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/ModifySanName.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/ModifySanPorts.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/Program.cs create mode 100644 Samples/Hyper-V/FibreChannel/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/FibreChannel/desktop.ico create mode 100644 Samples/Hyper-V/Generation2VM/README.md create mode 100644 Samples/Hyper-V/Generation2VM/cs/CreateVM.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/Generation2VM.csproj create mode 100644 Samples/Hyper-V/Generation2VM/cs/Generation2VM.sln create mode 100644 Samples/Hyper-V/Generation2VM/cs/GetBootOrder.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/GetPauseAfterBootFailure.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/GetSecureBoot.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/GetVMGeneration.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/Program.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/SetBootOrder.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/SetBootProtocol.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/SetPauseAfterBootFailure.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/SetSecureBoot.cs create mode 100644 Samples/Hyper-V/Generation2VM/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Generation2VM/desktop.ico create mode 100644 Samples/Hyper-V/IntegrationServices/README.md create mode 100644 Samples/Hyper-V/IntegrationServices/cs/GuestServiceInterface.cs create mode 100644 Samples/Hyper-V/IntegrationServices/cs/IntegrationServices.csproj create mode 100644 Samples/Hyper-V/IntegrationServices/cs/IntegrationServices.sln create mode 100644 Samples/Hyper-V/IntegrationServices/cs/Program.cs create mode 100644 Samples/Hyper-V/IntegrationServices/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/IntegrationServices/desktop.ico create mode 100644 Samples/Hyper-V/Metrics/README.md create mode 100644 Samples/Hyper-V/Metrics/cs/ControlMetrics.cs create mode 100644 Samples/Hyper-V/Metrics/cs/EnumerateMetrics.cs create mode 100644 Samples/Hyper-V/Metrics/cs/MetricUtilities.cs create mode 100644 Samples/Hyper-V/Metrics/cs/Metrics.csproj create mode 100644 Samples/Hyper-V/Metrics/cs/Metrics.sln create mode 100644 Samples/Hyper-V/Metrics/cs/ModifyServiceSettings.cs create mode 100644 Samples/Hyper-V/Metrics/cs/Program.cs create mode 100644 Samples/Hyper-V/Metrics/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Metrics/desktop.ico create mode 100644 Samples/Hyper-V/Migration/README.md create mode 100644 Samples/Hyper-V/Migration/cs/Migration.csproj create mode 100644 Samples/Hyper-V/Migration/cs/Migration.sln create mode 100644 Samples/Hyper-V/Migration/cs/MigrationCommon.cs create mode 100644 Samples/Hyper-V/Migration/cs/MigrationSettings.cs create mode 100644 Samples/Hyper-V/Migration/cs/Program.cs create mode 100644 Samples/Hyper-V/Migration/cs/StorageMigration.cs create mode 100644 Samples/Hyper-V/Migration/cs/VmAndStorageMigration.cs create mode 100644 Samples/Hyper-V/Migration/cs/VmMigration.cs create mode 100644 Samples/Hyper-V/Migration/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Migration/desktop.ico create mode 100644 Samples/Hyper-V/Networking/README.md create mode 100644 Samples/Hyper-V/Networking/cs/AddAndRemovePorts.cs create mode 100644 Samples/Hyper-V/Networking/cs/AdvancedConnectionProperties.cs create mode 100644 Samples/Hyper-V/Networking/cs/AdvancedSwitchProperties.cs create mode 100644 Samples/Hyper-V/Networking/cs/ConnectVmToSwitch.cs create mode 100644 Samples/Hyper-V/Networking/cs/ConnectVmUsingResourcePool.cs create mode 100644 Samples/Hyper-V/Networking/cs/CreateSwitch.cs create mode 100644 Samples/Hyper-V/Networking/cs/DeleteSwitch.cs create mode 100644 Samples/Hyper-V/Networking/cs/EnumerateSwitch.cs create mode 100644 Samples/Hyper-V/Networking/cs/ManageExtension.cs create mode 100644 Samples/Hyper-V/Networking/cs/ModifyPorts.cs create mode 100644 Samples/Hyper-V/Networking/cs/ModifySwitch.cs create mode 100644 Samples/Hyper-V/Networking/cs/Networking.csproj create mode 100644 Samples/Hyper-V/Networking/cs/Networking.sln create mode 100644 Samples/Hyper-V/Networking/cs/NetworkingUtilities.cs create mode 100644 Samples/Hyper-V/Networking/cs/Program.cs create mode 100644 Samples/Hyper-V/Networking/cs/SetRequiredFeature.cs create mode 100644 Samples/Hyper-V/Networking/cs/SupportsTrunkMode.cs create mode 100644 Samples/Hyper-V/Networking/cs/SyntheticEthernetPortProperties.cs create mode 100644 Samples/Hyper-V/Networking/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Networking/desktop.ico create mode 100644 Samples/Hyper-V/Pvm/README.md create mode 100644 Samples/Hyper-V/Pvm/cs/FixUpUtilities.cs create mode 100644 Samples/Hyper-V/Pvm/cs/ImportUtilities.cs create mode 100644 Samples/Hyper-V/Pvm/cs/PVM.csproj create mode 100644 Samples/Hyper-V/Pvm/cs/PVM.sln create mode 100644 Samples/Hyper-V/Pvm/cs/Program.cs create mode 100644 Samples/Hyper-V/Pvm/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Pvm/desktop.ico create mode 100644 Samples/Hyper-V/Replica/README.md create mode 100644 Samples/Hyper-V/Replica/cs/ManageReplication.cs create mode 100644 Samples/Hyper-V/Replica/cs/ModifyServiceSettings.cs create mode 100644 Samples/Hyper-V/Replica/cs/Program.cs create mode 100644 Samples/Hyper-V/Replica/cs/Replica.csproj create mode 100644 Samples/Hyper-V/Replica/cs/Replica.sln create mode 100644 Samples/Hyper-V/Replica/cs/ReplicaUtilities.cs create mode 100644 Samples/Hyper-V/Replica/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Replica/desktop.ico create mode 100644 Samples/Hyper-V/ResourcePools/README.md create mode 100644 Samples/Hyper-V/ResourcePools/cs/MsvmResourceAllocationSettingData.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/MsvmResourcePool.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/MsvmResourcePoolConfigurationService.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/MsvmResourcePoolSettingData.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/Program.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/ResourcePoolUtilities.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/ResourcePools.csproj create mode 100644 Samples/Hyper-V/ResourcePools/cs/ResourcePools.sln create mode 100644 Samples/Hyper-V/ResourcePools/cs/ResourceUtilities.cs create mode 100644 Samples/Hyper-V/ResourcePools/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/ResourcePools/desktop.ico create mode 100644 Samples/Hyper-V/Storage/README.md create mode 100644 Samples/Hyper-V/Storage/cpp/AddVirtualDiskParent.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/AttachVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/CreateVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/DeleteUserMetaData.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/DetachVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/EnumerateUserMetaData.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/GetAllAttachedVirtualDiskPhysicalPaths.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/GetStorageDependencyInformation.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/GetUserMetaData.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/GetVirtualDiskInformation.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/MergeVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/MirrorVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/Program.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/RawIO.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/ResizeVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/SetUserMetaData.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/SetVirtualDiskInformation.cpp create mode 100644 Samples/Hyper-V/Storage/cpp/Storage.h create mode 100644 Samples/Hyper-V/Storage/cpp/Storage.sln create mode 100644 Samples/Hyper-V/Storage/cpp/Storage.vcxproj create mode 100644 Samples/Hyper-V/Storage/cpp/compactVirtualDisk.cpp create mode 100644 Samples/Hyper-V/Storage/cs/AttachVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/CompactVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/ConvertVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/CreateVirtualFloppyDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/CreateVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/DetachVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/GetVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/MergeVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/Program.cs create mode 100644 Samples/Hyper-V/Storage/cs/ResizeVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/SetParentVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/SetVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/Storage.csproj create mode 100644 Samples/Hyper-V/Storage/cs/Storage.sln create mode 100644 Samples/Hyper-V/Storage/cs/StorageUtilities.cs create mode 100644 Samples/Hyper-V/Storage/cs/ValidateVirtualHardDisk.cs create mode 100644 Samples/Hyper-V/Storage/cs/VirtualHardDiskSettingData.cs create mode 100644 Samples/Hyper-V/Storage/cs/VirtualHardDiskState.cs create mode 100644 Samples/Hyper-V/Storage/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/Storage/desktop.ico create mode 100644 Samples/Hyper-V/StorageQoS/README.md create mode 100644 Samples/Hyper-V/StorageQoS/cs/Program.cs create mode 100644 Samples/Hyper-V/StorageQoS/cs/StorageQoS.cs create mode 100644 Samples/Hyper-V/StorageQoS/cs/StorageQoS.csproj create mode 100644 Samples/Hyper-V/StorageQoS/cs/StorageQoS.sln create mode 100644 Samples/Hyper-V/StorageQoS/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/StorageQoS/desktop.ico create mode 100644 Samples/Hyper-V/VmOperations/README.md create mode 100644 Samples/Hyper-V/VmOperations/cs/LinuxAffinityUtilities.cs create mode 100644 Samples/Hyper-V/VmOperations/cs/Program.cs create mode 100644 Samples/Hyper-V/VmOperations/cs/VmOperations.csproj create mode 100644 Samples/Hyper-V/VmOperations/cs/VmOperations.sln create mode 100644 Samples/Hyper-V/VmOperations/cs/WmiUtilities.cs create mode 100644 Samples/Hyper-V/VmOperations/desktop.ico create mode 100644 Samples/IME/README.md create mode 100644 Samples/IME/cpp/SampleIME.sln create mode 100644 Samples/IME/cpp/SampleIME/ActiveLanguageProfileNotifySink.cpp create mode 100644 Samples/IME/cpp/SampleIME/BaseDictionaryEngine.cpp create mode 100644 Samples/IME/cpp/SampleIME/BaseDictionaryEngine.h create mode 100644 Samples/IME/cpp/SampleIME/BaseWindow.cpp create mode 100644 Samples/IME/cpp/SampleIME/BaseWindow.h create mode 100644 Samples/IME/cpp/SampleIME/ButtonWindow.cpp create mode 100644 Samples/IME/cpp/SampleIME/ButtonWindow.h create mode 100644 Samples/IME/cpp/SampleIME/CandidateListUIPresenter.cpp create mode 100644 Samples/IME/cpp/SampleIME/CandidateListUIPresenter.h create mode 100644 Samples/IME/cpp/SampleIME/CandidateWindow.cpp create mode 100644 Samples/IME/cpp/SampleIME/CandidateWindow.h create mode 100644 Samples/IME/cpp/SampleIME/Compartment.cpp create mode 100644 Samples/IME/cpp/SampleIME/Compartment.h create mode 100644 Samples/IME/cpp/SampleIME/Composition.cpp create mode 100644 Samples/IME/cpp/SampleIME/CompositionProcessorEngine.cpp create mode 100644 Samples/IME/cpp/SampleIME/CompositionProcessorEngine.h create mode 100644 Samples/IME/cpp/SampleIME/Define.h create mode 100644 Samples/IME/cpp/SampleIME/Dictionary/SampleIMESimplifiedQuanPin.txt create mode 100644 Samples/IME/cpp/SampleIME/DictionaryParser.cpp create mode 100644 Samples/IME/cpp/SampleIME/DictionaryParser.h create mode 100644 Samples/IME/cpp/SampleIME/DictionarySearch.cpp create mode 100644 Samples/IME/cpp/SampleIME/DictionarySearch.h create mode 100644 Samples/IME/cpp/SampleIME/DisplayAttribute.cpp create mode 100644 Samples/IME/cpp/SampleIME/DisplayAttributeInfo.cpp create mode 100644 Samples/IME/cpp/SampleIME/DisplayAttributeInfo.h create mode 100644 Samples/IME/cpp/SampleIME/DisplayAttributeProvider.cpp create mode 100644 Samples/IME/cpp/SampleIME/DisplayString.h create mode 100644 Samples/IME/cpp/SampleIME/DllMain.cpp create mode 100644 Samples/IME/cpp/SampleIME/EditSession.cpp create mode 100644 Samples/IME/cpp/SampleIME/EditSession.h create mode 100644 Samples/IME/cpp/SampleIME/EndComposition.cpp create mode 100644 Samples/IME/cpp/SampleIME/EnumDisplayAttributeInfo.cpp create mode 100644 Samples/IME/cpp/SampleIME/EnumDisplayAttributeInfo.h create mode 100644 Samples/IME/cpp/SampleIME/EnumTfCandidates.cpp create mode 100644 Samples/IME/cpp/SampleIME/EnumTfCandidates.h create mode 100644 Samples/IME/cpp/SampleIME/File.cpp create mode 100644 Samples/IME/cpp/SampleIME/File.h create mode 100644 Samples/IME/cpp/SampleIME/FileMapping.cpp create mode 100644 Samples/IME/cpp/SampleIME/FileMapping.h create mode 100644 Samples/IME/cpp/SampleIME/FunctionProviderSink.cpp create mode 100644 Samples/IME/cpp/SampleIME/GetTextExtentEditSession.cpp create mode 100644 Samples/IME/cpp/SampleIME/GetTextExtentEditSession.h create mode 100644 Samples/IME/cpp/SampleIME/Globals.cpp create mode 100644 Samples/IME/cpp/SampleIME/Globals.h create mode 100644 Samples/IME/cpp/SampleIME/KeyEventSink.cpp create mode 100644 Samples/IME/cpp/SampleIME/KeyHandler.cpp create mode 100644 Samples/IME/cpp/SampleIME/KeyHandlerEditSession.cpp create mode 100644 Samples/IME/cpp/SampleIME/KeyHandlerEditSession.h create mode 100644 Samples/IME/cpp/SampleIME/KeyStateCategory.cpp create mode 100644 Samples/IME/cpp/SampleIME/KeyStateCategory.h create mode 100644 Samples/IME/cpp/SampleIME/LanguageBar.cpp create mode 100644 Samples/IME/cpp/SampleIME/LanguageBar.h create mode 100644 Samples/IME/cpp/SampleIME/Private.h create mode 100644 Samples/IME/cpp/SampleIME/RegKey.cpp create mode 100644 Samples/IME/cpp/SampleIME/RegKey.h create mode 100644 Samples/IME/cpp/SampleIME/Register.cpp create mode 100644 Samples/IME/cpp/SampleIME/SampleIME.cpp create mode 100644 Samples/IME/cpp/SampleIME/SampleIME.def create mode 100644 Samples/IME/cpp/SampleIME/SampleIME.h create mode 100644 Samples/IME/cpp/SampleIME/SampleIME.rc create mode 100644 Samples/IME/cpp/SampleIME/SampleIME.vcxproj create mode 100644 Samples/IME/cpp/SampleIME/SampleIME.vcxproj.filters create mode 100644 Samples/IME/cpp/SampleIME/SampleIMEBaseStructure.cpp create mode 100644 Samples/IME/cpp/SampleIME/SampleIMEBaseStructure.h create mode 100644 Samples/IME/cpp/SampleIME/SampleIMEStructureArray.h create mode 100644 Samples/IME/cpp/SampleIME/ScrollBarWindow.cpp create mode 100644 Samples/IME/cpp/SampleIME/ScrollBarWindow.h create mode 100644 Samples/IME/cpp/SampleIME/SearchCandidateProvider.cpp create mode 100644 Samples/IME/cpp/SampleIME/SearchCandidateProvider.h create mode 100644 Samples/IME/cpp/SampleIME/Server.cpp create mode 100644 Samples/IME/cpp/SampleIME/ShadowWindow.cpp create mode 100644 Samples/IME/cpp/SampleIME/ShadowWindow.h create mode 100644 Samples/IME/cpp/SampleIME/StartComposition.cpp create mode 100644 Samples/IME/cpp/SampleIME/TableDictionaryEngine.cpp create mode 100644 Samples/IME/cpp/SampleIME/TableDictionaryEngine.h create mode 100644 Samples/IME/cpp/SampleIME/TextEditSink.cpp create mode 100644 Samples/IME/cpp/SampleIME/TfInputProcessorProfile.cpp create mode 100644 Samples/IME/cpp/SampleIME/TfInputProcessorProfile.h create mode 100644 Samples/IME/cpp/SampleIME/TfTextLayoutSink.cpp create mode 100644 Samples/IME/cpp/SampleIME/TfTextLayoutSink.h create mode 100644 Samples/IME/cpp/SampleIME/ThreadFocusSink.cpp create mode 100644 Samples/IME/cpp/SampleIME/ThreadMgrEventSink.cpp create mode 100644 Samples/IME/cpp/SampleIME/TipCandidateList.cpp create mode 100644 Samples/IME/cpp/SampleIME/TipCandidateList.h create mode 100644 Samples/IME/cpp/SampleIME/TipCandidateString.cpp create mode 100644 Samples/IME/cpp/SampleIME/TipCandidateString.h create mode 100644 Samples/IME/cpp/SampleIME/image/DoubleSingleByteOff.ico create mode 100644 Samples/IME/cpp/SampleIME/image/DoubleSingleByteOn.ico create mode 100644 Samples/IME/cpp/SampleIME/image/ImeModeOff.ico create mode 100644 Samples/IME/cpp/SampleIME/image/ImeModeOn.ico create mode 100644 Samples/IME/cpp/SampleIME/image/PunctuationOff.ico create mode 100644 Samples/IME/cpp/SampleIME/image/PunctuationOn.ico create mode 100644 Samples/IME/cpp/SampleIME/image/SampleIme.ico create mode 100644 Samples/IME/cpp/SampleIME/resource.h create mode 100644 Samples/IME/cpp/SampleIME/stdafx.h create mode 100644 Samples/IdentifyInputSource/README.md create mode 100644 Samples/IdentifyInputSource/cpp/InputSource.cpp create mode 100644 Samples/IdentifyInputSource/cpp/InputSource.rc create mode 100644 Samples/IdentifyInputSource/cpp/InputSource.sln create mode 100644 Samples/IdentifyInputSource/cpp/InputSource.vcxproj create mode 100644 Samples/IdentifyInputSource/cpp/stdafx.cpp create mode 100644 Samples/IdentifyInputSource/cpp/stdafx.h create mode 100644 Samples/InjectTouchPointerInput/README.md create mode 100644 Samples/InjectTouchPointerInput/cpp/InjectTouch.cpp create mode 100644 Samples/InjectTouchPointerInput/cpp/InjectTouch.rc create mode 100644 Samples/InjectTouchPointerInput/cpp/InjectTouch.sln create mode 100644 Samples/InjectTouchPointerInput/cpp/InjectTouch.vcxproj create mode 100644 Samples/InjectTouchPointerInput/cpp/stdafx.cpp create mode 100644 Samples/InjectTouchPointerInput/cpp/stdafx.h create mode 100644 Samples/InteractionContextProduceTouchInput/README.md create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/Application.cpp create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/Application.h create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/DeviceResources.cpp create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/DeviceResources.h create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/DirectXHelper.h create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/InteractionContextSample.cpp create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/InteractionContextSample.h create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/InteractionContextSample.sln create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/InteractionContextSample.vcxproj create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/SampleDesktopWindow.cpp create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/SampleDesktopWindow.h create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/pch.cpp create mode 100644 Samples/InteractionContextProduceTouchInput/cpp/pch.h create mode 100644 Samples/LocationAwarenessEvents/README.md create mode 100644 Samples/LocationAwarenessEvents/cpp/LocationCallback.cpp create mode 100644 Samples/LocationAwarenessEvents/cpp/LocationCallback.h create mode 100644 Samples/LocationAwarenessEvents/cpp/LocationEvents.cpp create mode 100644 Samples/LocationAwarenessEvents/cpp/LocationEvents.sln create mode 100644 Samples/LocationAwarenessEvents/cpp/LocationEvents.vcxproj create mode 100644 Samples/LocationAwarenessEvents/cpp/Readme.txt create mode 100644 Samples/LocationSetDefault/README.md create mode 100644 Samples/LocationSetDefault/cpp/LocationReportObject.cpp create mode 100644 Samples/LocationSetDefault/cpp/LocationReportObject.h create mode 100644 Samples/LocationSetDefault/cpp/ReadMe.txt create mode 100644 Samples/LocationSetDefault/cpp/SetLocation.cpp create mode 100644 Samples/LocationSetDefault/cpp/SetLocation.sln create mode 100644 Samples/LocationSetDefault/cpp/SetLocation.vcxproj create mode 100644 Samples/LocationSynchronousAccess/README.md create mode 100644 Samples/LocationSynchronousAccess/cpp/ReadMe.txt create mode 100644 Samples/LocationSynchronousAccess/cpp/SimpleLocation.cpp create mode 100644 Samples/LocationSynchronousAccess/cpp/SimpleLocation.sln create mode 100644 Samples/LocationSynchronousAccess/cpp/SimpleLocation.vcxproj create mode 100644 Samples/MSXML/DynamDom/README.md create mode 100644 Samples/MSXML/DynamDom/cpp/dynamDOM.cpp create mode 100644 Samples/MSXML/DynamDom/cpp/dynamdom.sln create mode 100644 Samples/MSXML/DynamDom/cpp/dynamdom.vcxproj create mode 100644 Samples/MSXML/DynamDom/cpp/dynamdom.vcxproj.filters create mode 100644 Samples/MSXML/LoadDom/README.md create mode 100644 Samples/MSXML/LoadDom/cpp/loadDom.cpp create mode 100644 Samples/MSXML/LoadDom/cpp/loaddom.sln create mode 100644 Samples/MSXML/LoadDom/cpp/loaddom.vcxproj create mode 100644 Samples/MSXML/LoadDom/cpp/loaddom.vcxproj.filters create mode 100644 Samples/MSXML/LoadDom/cpp/stocks.xml create mode 100644 Samples/MSXML/QueryNodes/README.md create mode 100644 Samples/MSXML/QueryNodes/cpp/queryNodes.cpp create mode 100644 Samples/MSXML/QueryNodes/cpp/querynodes.sln create mode 100644 Samples/MSXML/QueryNodes/cpp/querynodes.vcxproj create mode 100644 Samples/MSXML/QueryNodes/cpp/querynodes.vcxproj.filters create mode 100644 Samples/MSXML/QueryNodes/cpp/stocks.xml create mode 100644 Samples/MSXML/SaveDom/README.md create mode 100644 Samples/MSXML/SaveDom/cpp/saveDom.cpp create mode 100644 Samples/MSXML/SaveDom/cpp/savedom.sln create mode 100644 Samples/MSXML/SaveDom/cpp/savedom.vcxproj create mode 100644 Samples/MSXML/SaveDom/cpp/savedom.vcxproj.filters create mode 100644 Samples/MSXML/Xslt/README.md create mode 100644 Samples/MSXML/Xslt/cpp/XSLT.cpp create mode 100644 Samples/MSXML/Xslt/cpp/stocks.xml create mode 100644 Samples/MSXML/Xslt/cpp/stocks.xsl create mode 100644 Samples/MSXML/Xslt/cpp/xslt.sln create mode 100644 Samples/MSXML/Xslt/cpp/xslt.vcxproj create mode 100644 Samples/MSXML/Xslt/cpp/xslt.vcxproj.filters create mode 100644 Samples/Magnification/README.md create mode 100644 Samples/Magnification/cpp/Fullscreen/FullscreenMagnifierSample.cpp create mode 100644 Samples/Magnification/cpp/Fullscreen/FullscreenMagnifierSample.rc create mode 100644 Samples/Magnification/cpp/Fullscreen/FullscreenMagnifierSample.vcxproj create mode 100644 Samples/Magnification/cpp/Fullscreen/resource.h create mode 100644 Samples/Magnification/cpp/MagnifierSample.sln create mode 100644 Samples/Magnification/cpp/Windowed/MagnifierSample.cpp create mode 100644 Samples/Magnification/cpp/Windowed/MagnifierSample.vcxproj create mode 100644 Samples/ManagementInfrastructure/README.md create mode 100644 Samples/ManagementInfrastructure/cpp/DecoupledHost/DecoupledHost.c create mode 100644 Samples/ManagementInfrastructure/cpp/DecoupledHost/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/DecoupledHost/dcuphost.vcxproj create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/CIMCmdlet/Indication.ps1 create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/ManagedClient/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/NativeClient/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/CIM_Indication.h create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/CIM_InstIndication.h create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/CIM_InstModification.h create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/MSFT_WindowsServiceStarted.c create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/MSFT_WindowsServiceStarted.h create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/MSFT_WindowsServiceStopped.c create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/MSFT_WindowsServiceStopped.h create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/Provider.DEF create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/WMIAdapter.c create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/WindowsService.c create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/WindowsService.h create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/module.c create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/schema.c create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/Provider/svcind.vcxproj create mode 100644 Samples/ManagementInfrastructure/cpp/Indication/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/MSFT_Qualifiers.mof create mode 100644 Samples/ManagementInfrastructure/cpp/Process/CIM-BasedCmdlet/WindowsProcess/WindowsProcess.cdxml create mode 100644 Samples/ManagementInfrastructure/cpp/Process/CIM-BasedCmdlet/WindowsProcess/WindowsProcess.format.ps1xml create mode 100644 Samples/ManagementInfrastructure/cpp/Process/CIM-BasedCmdlet/WindowsProcess/WindowsProcess.psd1 create mode 100644 Samples/ManagementInfrastructure/cpp/Process/CIM-BasedCmdlet/WindowsProcess/WindowsProcess.types.ps1xml create mode 100644 Samples/ManagementInfrastructure/cpp/Process/CIMCmdlet/Process.ps1 create mode 100644 Samples/ManagementInfrastructure/cpp/Process/ManagedClient/Main.cs create mode 100644 Samples/ManagementInfrastructure/cpp/Process/ManagedClient/Properties/AssemblyInfo.cs create mode 100644 Samples/ManagementInfrastructure/cpp/Process/ManagedClient/SampleCimOperation.cs create mode 100644 Samples/ManagementInfrastructure/cpp/Process/ManagedClient/SampleDotNetClient.csproj create mode 100644 Samples/ManagementInfrastructure/cpp/Process/ManagedClient/TestObserver.cs create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/CimClient.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/SampleNativeMiClient.vcxproj create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/SampleNativeMiClient.vcxproj.filters create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/association.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/create.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/delete.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/enumerate.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/get.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/invoke.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/modify.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/operations.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/operations.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/query.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/reference.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/subscribe.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/utilities.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/NativeClient/utilities.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_ConcreteJob.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_EnabledLogicalElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_Error.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_Job.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_LogicalElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_ManagedElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_ManagedSystemElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_Process.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_Service.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/CIM_ServiceProcess.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/Helper.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/MSFT_WindowsProcess.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/MSFT_WindowsProcess.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/MSFT_WindowsServiceProcess.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/MSFT_WindowsServiceProcess.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/Provider.DEF create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/WMIAdapter.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/WindowsProcess.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/WindowsProcess.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/WindowsServiceProcess.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/WindowsServiceProcess.h create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/helper.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/module.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/process.vcxproj create mode 100644 Samples/ManagementInfrastructure/cpp/Process/Provider/schema.c create mode 100644 Samples/ManagementInfrastructure/cpp/Process/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/Sample.mof create mode 100644 Samples/ManagementInfrastructure/cpp/Service/CIM-BasedCmdlet/WindowsService/WindowsService.cdxml create mode 100644 Samples/ManagementInfrastructure/cpp/Service/CIM-BasedCmdlet/WindowsService/WindowsService.format.ps1xml create mode 100644 Samples/ManagementInfrastructure/cpp/Service/CIM-BasedCmdlet/WindowsService/WindowsService.psd1 create mode 100644 Samples/ManagementInfrastructure/cpp/Service/CIMCmdlet/Service.ps1 create mode 100644 Samples/ManagementInfrastructure/cpp/Service/ManagedClient/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/Service/NativeClient/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_ConcreteJob.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_EnabledLogicalElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_Error.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_Job.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_LogicalElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_ManagedElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_ManagedSystemElement.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/CIM_Service.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/MSFT_WindowsService.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/MSFT_WindowsService.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/MSFT_WindowsServiceManager.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/MSFT_WindowsServiceManager.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/Provider.DEF create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/WMIAdapter.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/WindowsService.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/WindowsService.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/WindowsServiceManager.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/WindowsServiceManager.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/module.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/mui.rcconfig create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/schema.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/service.vcxproj create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/strings.rc create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/util.c create mode 100644 Samples/ManagementInfrastructure/cpp/Service/Provider/util.h create mode 100644 Samples/ManagementInfrastructure/cpp/Service/ReadMe.txt create mode 100644 Samples/ManagementInfrastructure/cpp/misample.sln create mode 100644 Samples/MediaFoundationTransformDecoder/README.md create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CAutoLock.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CAutoLock.h create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT.h create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_DebugLogger.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_DebugLogger.h create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_DecodeTask.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_DecodeTask.h create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_IMFAsyncCallback_Impl.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_IMFMediaEventGenerator_Impl.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_IMFShutdown_Impl.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_IMFTransform_Impl.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CHWMFT_IUnknown_Impl.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CSampleQueue.cpp create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/CSampleQueue.h create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/IMYMFT.h create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/MFHMFT.def create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/MFHMFT.sln create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/MFHMFT.vcxproj create mode 100644 Samples/MediaFoundationTransformDecoder/cpp/dllmain.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/README.md create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/DebugHelper/DebugHelper.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/DebugHelper/DebugHelper.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/DebugHelper/DebugHelper.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/ComponentInfo.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/ComponentInfo.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/Messages.mc create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/SdkShaInfo.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/SdkShaInfo.def create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/SdkShaInfo.rc create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/SdkShaInfo.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/SdkShaInfoCF.H create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/SdkShaInfoCF.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/dllmain.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/dllmain.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/icon1.ico create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/DLL/resource.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/Callback.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/Callback.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/Messages.mc create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/SdkSha.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/SdkShaModule.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/SdkShaModule.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/Sha.H create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/Sha.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHA/EXE/resource.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SampleShv.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SampleShv.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShv.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShv.def create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShv.rc create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShv.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShvCF.H create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShvCF.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShvModule.H create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/SdkShvModule.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SHV/resource.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/Registration.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/Registration.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/Regutil.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/Regutil.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/resource.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/sampleshvui.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/sdkshv.ico create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/shvui.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/shvui.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/shvui.rc create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/shvuicf.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SampleShvUi/shvuicf.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SdkCommon/SdkCommon.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SdkCommon/SdkCommon.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SdkCommon/SdkCommon.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/SdkSamples.sln create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/QEC.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/QEC.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/QecCallback.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/QecCallback.h create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/SdkQec.vcxproj create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/SdkQecModule.H create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/SdkQecModule.cpp create mode 100644 Samples/NetworkAccessProtectionExtensions/cpp/sdkqec/resource.h create mode 100644 Samples/NetworkCost/README.md create mode 100644 Samples/NetworkCost/Readme.txt create mode 100644 Samples/NetworkCost/cpp/NetCostEventSink.cpp create mode 100644 Samples/NetworkCost/cpp/NetCostEventSink.h create mode 100644 Samples/NetworkCost/cpp/NetCostSample.cpp create mode 100644 Samples/NetworkCost/cpp/NetCostSample.h create mode 100644 Samples/NetworkCost/cpp/NetCostSample.sln create mode 100644 Samples/NetworkCost/cpp/NetCostSample.vcxproj create mode 100644 Samples/NetworkCost/cpp/NetCostSample.vcxproj.filters create mode 100644 Samples/NetworkCost/cpp/Utils.cpp create mode 100644 Samples/NetworkCost/cpp/Utils.h create mode 100644 Samples/ODataEntitiesAssociation/README.md create mode 100644 Samples/ODataEntitiesAssociation/cs/AssemblyInfo.cs create mode 100644 Samples/ODataEntitiesAssociation/cs/AssociationClient.csproj create mode 100644 Samples/ODataEntitiesAssociation/cs/AssociationClient.sln create mode 100644 Samples/ODataEntitiesAssociation/cs/OdataJsonRequest.cs create mode 100644 Samples/ODataEntitiesAssociation/cs/Program.cs create mode 100644 Samples/ODataEntitiesAssociation/cs/setup/HostVMSystem.xml create mode 100644 Samples/ODataEntitiesAssociation/cs/setup/ReadMe.txt create mode 100644 Samples/ODataEntitiesAssociation/cs/setup/VMSystem.mof create mode 100644 Samples/ODataEntitiesAssociation/cs/setup/VMSystem.psm1 create mode 100644 Samples/ODataEntitiesAssociation/cs/setup/VMSystem.xml create mode 100644 Samples/ODataEntitiesAssociation/cs/setup/Web.config create mode 100644 Samples/OpenDatabaseConnectivity/README.md create mode 100644 Samples/OpenDatabaseConnectivity/cpp/Readme.txt create mode 100644 Samples/OpenDatabaseConnectivity/cpp/odbcsql.cpp create mode 100644 Samples/OpenDatabaseConnectivity/cpp/odbcsql.sln create mode 100644 Samples/OpenDatabaseConnectivity/cpp/odbcsql.vcxproj create mode 100644 Samples/PackageManagerAddPackage/README.md create mode 100644 Samples/PackageManagerAddPackage/cpp/AddPackageSample.cpp create mode 100644 Samples/PackageManagerAddPackage/cpp/AddPackageSample.sln create mode 100644 Samples/PackageManagerAddPackage/cpp/AddPackageSample.vcxproj create mode 100644 Samples/PackageManagerAddPackage/cpp/README.txt create mode 100644 Samples/PackageManagerAddPackage/cs/AddPackageSample.cs create mode 100644 Samples/PackageManagerAddPackage/cs/AddPackageSample.csproj create mode 100644 Samples/PackageManagerAddPackage/cs/AddPackageSample.sln create mode 100644 Samples/PackageManagerAddPackage/cs/README.txt create mode 100644 Samples/PackageManagerAddPackage/cs/app.config create mode 100644 Samples/PackageManagerFindPackages/README.md create mode 100644 Samples/PackageManagerFindPackages/cpp/FindPackagesSample.cpp create mode 100644 Samples/PackageManagerFindPackages/cpp/FindPackagesSample.sln create mode 100644 Samples/PackageManagerFindPackages/cpp/FindPackagesSample.vcxproj create mode 100644 Samples/PackageManagerFindPackages/cpp/README.txt create mode 100644 Samples/PackageManagerFindPackages/cs/FindPackagesSample.cs create mode 100644 Samples/PackageManagerFindPackages/cs/FindPackagesSample.csproj create mode 100644 Samples/PackageManagerFindPackages/cs/FindPackagesSample.sln create mode 100644 Samples/PackageManagerFindPackages/cs/README.txt create mode 100644 Samples/PackageManagerFindPackages/cs/app.config create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/README.md create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cpp/FindPackagesByNameAndPublisherSample.cpp create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cpp/FindPackagesByNameAndPublisherSample.sln create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cpp/FindPackagesByNameAndPublisherSample.vcxproj create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cpp/README.txt create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cs/FindPackagesByNameAndPublisherSample.cs create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cs/FindPackagesByNameAndPublisherSample.csproj create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cs/FindPackagesByNameAndPublisherSample.sln create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cs/README.txt create mode 100644 Samples/PackageManagerFindPackagesByNameAndPublisher/cs/app.config create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/README.md create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cpp/FindPackagesByUserSecurityIdSample.cpp create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cpp/FindPackagesByUserSecurityIdSample.sln create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cpp/FindPackagesByUserSecurityIdSample.vcxproj create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cpp/README.txt create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cs/FindPackagesByUserSecurityIdSample.cs create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cs/FindPackagesByUserSecurityIdSample.csproj create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cs/FindPackagesByUserSecurityIdSample.sln create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cs/README.txt create mode 100644 Samples/PackageManagerFindPackagesByUserSecurityId/cs/app.config create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/README.md create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cpp/FindPackagesWithPackageTypesSample.cpp create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cpp/FindPackagesWithPackageTypesSample.sln create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cpp/FindPackagesWithPackageTypesSample.vcxproj create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cpp/README.txt create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cs/FindPackagesWithPackageTypesSample.cs create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cs/FindPackagesWithPackageTypesSample.csproj create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cs/FindPackagesWithPackageTypesSample.sln create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cs/README.txt create mode 100644 Samples/PackageManagerFindPackagesWithPackageTypes/cs/app.config create mode 100644 Samples/PackageManagerRemovePackage/README.md create mode 100644 Samples/PackageManagerRemovePackage/cpp/README.txt create mode 100644 Samples/PackageManagerRemovePackage/cpp/RemovePackageSample.cpp create mode 100644 Samples/PackageManagerRemovePackage/cpp/RemovePackageSample.sln create mode 100644 Samples/PackageManagerRemovePackage/cpp/RemovePackageSample.vcxproj create mode 100644 Samples/PackageManagerRemovePackage/cs/README.txt create mode 100644 Samples/PackageManagerRemovePackage/cs/RemovePackageSample.cs create mode 100644 Samples/PackageManagerRemovePackage/cs/RemovePackageSample.csproj create mode 100644 Samples/PackageManagerRemovePackage/cs/RemovePackageSample.sln create mode 100644 Samples/PackageManagerRemovePackage/cs/app.config create mode 100644 Samples/PerMonitorDPIAware/README.md create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/AssemblyInfo.cpp create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/NativeHelpers.vcxproj create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/NativeHelpers.vcxproj.filters create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/PerMonitorDPIHelpers.cpp create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/PerMonitorDPIHelpers.h create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/PerMonitorDPIWindow.cpp create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/PerMonitorDPIWindow.h create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/pch.cpp create mode 100644 Samples/PerMonitorDPIAware/cs/NativeHelpers/pch.h create mode 100644 Samples/PerMonitorDPIAware/cs/PerMonitorAwareWPFApplication.sln create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/App.config create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/App.xaml create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/App.xaml.cs create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/PerMonitorAwareWPFWindow.xaml create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/PerMonitorAwareWPFWindow.xaml.cs create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/Properties/AssemblyInfo.cs create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/Properties/Resources.Designer.cs create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/Properties/Resources.resx create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/Properties/Settings.Designer.cs create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/Properties/Settings.settings create mode 100644 Samples/PerMonitorDPIAware/cs/WpfApplication/WpfApplication.csproj create mode 100644 Samples/PortableDeviceCOM/README.md create mode 100644 Samples/PortableDeviceCOM/cpp/CommonFunctions.h create mode 100644 Samples/PortableDeviceCOM/cpp/ContentEnumeration.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/ContentProperties.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/ContentTransfer.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/DeviceCapabilities.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/DeviceEnumeration.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/DeviceEvents.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/ReadMe.txt create mode 100644 Samples/PortableDeviceCOM/cpp/WpdApiSample.cpp create mode 100644 Samples/PortableDeviceCOM/cpp/WpdApiSample.sln create mode 100644 Samples/PortableDeviceCOM/cpp/WpdApiSample.vcxproj create mode 100644 Samples/PortableDeviceCOM/cpp/stdafx.h create mode 100644 Samples/PortableDeviceServices/README.md create mode 100644 Samples/PortableDeviceServices/cpp/CommonFunctions.h create mode 100644 Samples/PortableDeviceServices/cpp/ContentEnumeration.cpp create mode 100644 Samples/PortableDeviceServices/cpp/ContentProperties.cpp create mode 100644 Samples/PortableDeviceServices/cpp/ReadMe.txt create mode 100644 Samples/PortableDeviceServices/cpp/ServiceCapabilities.cpp create mode 100644 Samples/PortableDeviceServices/cpp/ServiceEnumeration.cpp create mode 100644 Samples/PortableDeviceServices/cpp/ServiceMethods.cpp create mode 100644 Samples/PortableDeviceServices/cpp/WpdServicesApiSample.cpp create mode 100644 Samples/PortableDeviceServices/cpp/WpdServicesApiSample.sln create mode 100644 Samples/PortableDeviceServices/cpp/WpdServicesApiSample.vcxproj create mode 100644 Samples/PortableDeviceServices/cpp/stdafx.h create mode 100644 Samples/PowerShell/AbstractSyntaxTreeProfiler/README.md create mode 100644 Samples/PowerShell/AbstractSyntaxTreeProfiler/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/AbstractSyntaxTreeProfiler/cs/PSProfiler.cs create mode 100644 Samples/PowerShell/AbstractSyntaxTreeProfiler/cs/PSProfiler.csproj create mode 100644 Samples/PowerShell/AbstractSyntaxTreeProfiler/cs/PSProfiler.sln create mode 100644 Samples/PowerShell/AbstractSyntaxTreeProfiler/cs/Readme.txt create mode 100644 Samples/PowerShell/ActivityGenerator/README.md create mode 100644 Samples/PowerShell/ActivityGenerator/cs/ActivityGenerator.csproj create mode 100644 Samples/PowerShell/ActivityGenerator/cs/ActivityGenerator.sln create mode 100644 Samples/PowerShell/ActivityGenerator/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/ActivityGenerator/cs/Math.cdxml create mode 100644 Samples/PowerShell/ActivityGenerator/cs/New-PSActivity.ps1 create mode 100644 Samples/PowerShell/ActivityGenerator/cs/Program.cs create mode 100644 Samples/PowerShell/ActivityGenerator/cs/Readme.txt create mode 100644 Samples/PowerShell/ContainerActivity/README.md create mode 100644 Samples/PowerShell/ContainerActivity/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/ContainerActivity/cs/ContainerActivity.cs create mode 100644 Samples/PowerShell/ContainerActivity/cs/ContainerActivity.csproj create mode 100644 Samples/PowerShell/ContainerActivity/cs/ContainerActivity.sln create mode 100644 Samples/PowerShell/ContainerActivity/cs/Invoke-ContainerActivity.ps1 create mode 100644 Samples/PowerShell/ContainerActivity/cs/Readme.txt create mode 100644 Samples/PowerShell/Debugger/README.md create mode 100644 Samples/PowerShell/Debugger/cs/App.config create mode 100644 Samples/PowerShell/Debugger/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Debugger/cs/DebuggerSample.cs create mode 100644 Samples/PowerShell/Debugger/cs/DebuggerSample.csproj create mode 100644 Samples/PowerShell/Debugger/cs/DebuggerSample.sln create mode 100644 Samples/PowerShell/Debugger/cs/Readme.txt create mode 100644 Samples/PowerShell/EventNotification/README.md create mode 100644 Samples/PowerShell/EventNotification/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/EventNotification/cs/Events02.cs create mode 100644 Samples/PowerShell/EventNotification/cs/Events02.csproj create mode 100644 Samples/PowerShell/EventNotification/cs/Events02.sln create mode 100644 Samples/PowerShell/EventNotification/cs/Readme.txt create mode 100644 Samples/PowerShell/EventRegistration/README.md create mode 100644 Samples/PowerShell/EventRegistration/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/EventRegistration/cs/Events01.cs create mode 100644 Samples/PowerShell/EventRegistration/cs/Events01.csproj create mode 100644 Samples/PowerShell/EventRegistration/cs/Events01.sln create mode 100644 Samples/PowerShell/EventRegistration/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host01/README.md create mode 100644 Samples/PowerShell/Host/Host01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Host/Host01/cs/Host01.cs create mode 100644 Samples/PowerShell/Host/Host01/cs/Host01.csproj create mode 100644 Samples/PowerShell/Host/Host01/cs/Host01.sln create mode 100644 Samples/PowerShell/Host/Host01/cs/MyHost.cs create mode 100644 Samples/PowerShell/Host/Host01/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host02/README.md create mode 100644 Samples/PowerShell/Host/Host02/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Host/Host02/cs/Host02.cs create mode 100644 Samples/PowerShell/Host/Host02/cs/Host02.csproj create mode 100644 Samples/PowerShell/Host/Host02/cs/Host02.sln create mode 100644 Samples/PowerShell/Host/Host02/cs/MyHost.cs create mode 100644 Samples/PowerShell/Host/Host02/cs/MyHostUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host02/cs/MyRawUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host02/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host03/README.md create mode 100644 Samples/PowerShell/Host/Host03/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Host/Host03/cs/Host03.cs create mode 100644 Samples/PowerShell/Host/Host03/cs/Host03.csproj create mode 100644 Samples/PowerShell/Host/Host03/cs/Host03.sln create mode 100644 Samples/PowerShell/Host/Host03/cs/MyHost.cs create mode 100644 Samples/PowerShell/Host/Host03/cs/MyHostUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host03/cs/MyRawUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host03/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host04/README.md create mode 100644 Samples/PowerShell/Host/Host04/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Host/Host04/cs/Host04.cs create mode 100644 Samples/PowerShell/Host/Host04/cs/Host04.csproj create mode 100644 Samples/PowerShell/Host/Host04/cs/Host04.sln create mode 100644 Samples/PowerShell/Host/Host04/cs/HostUtilities.cs create mode 100644 Samples/PowerShell/Host/Host04/cs/MyHost.cs create mode 100644 Samples/PowerShell/Host/Host04/cs/MyHostUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host04/cs/MyRawUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host04/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host05/README.md create mode 100644 Samples/PowerShell/Host/Host05/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Host/Host05/cs/Host05.cs create mode 100644 Samples/PowerShell/Host/Host05/cs/Host05.csproj create mode 100644 Samples/PowerShell/Host/Host05/cs/Host05.sln create mode 100644 Samples/PowerShell/Host/Host05/cs/HostUtilities.cs create mode 100644 Samples/PowerShell/Host/Host05/cs/MyHost.cs create mode 100644 Samples/PowerShell/Host/Host05/cs/MyHostUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host05/cs/MyRawUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host05/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host06/README.md create mode 100644 Samples/PowerShell/Host/Host06/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Host/Host06/cs/Host06.cs create mode 100644 Samples/PowerShell/Host/Host06/cs/Host06.csproj create mode 100644 Samples/PowerShell/Host/Host06/cs/Host06.sln create mode 100644 Samples/PowerShell/Host/Host06/cs/HostUtilities.cs create mode 100644 Samples/PowerShell/Host/Host06/cs/MyHost.cs create mode 100644 Samples/PowerShell/Host/Host06/cs/MyHostUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host06/cs/MyRawUserInterface.cs create mode 100644 Samples/PowerShell/Host/Host06/cs/Readme.txt create mode 100644 Samples/PowerShell/Host/Host06/cs/readline.cs create mode 100644 Samples/PowerShell/InitialSessionState/README.md create mode 100644 Samples/PowerShell/InitialSessionState/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/InitialSessionState/cs/PowerShell01.cs create mode 100644 Samples/PowerShell/InitialSessionState/cs/PowerShell01.csproj create mode 100644 Samples/PowerShell/InitialSessionState/cs/PowerShell01.sln create mode 100644 Samples/PowerShell/InitialSessionState/cs/Readme.txt create mode 100644 Samples/PowerShell/JobSourceAdapter/README.md create mode 100644 Samples/PowerShell/JobSourceAdapter/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/JobSourceAdapter/cs/JobSourceAdapter.csproj create mode 100644 Samples/PowerShell/JobSourceAdapter/cs/JobSourceAdapter.sln create mode 100644 Samples/PowerShell/JobSourceAdapter/cs/JobSourceAdapterSample.cs create mode 100644 Samples/PowerShell/JobSourceAdapter/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/GetProcess01/README.md create mode 100644 Samples/PowerShell/Process/GetProcess01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/GetProcess01/cs/GetProcessSample01.cs create mode 100644 Samples/PowerShell/Process/GetProcess01/cs/GetProcessSample01.csproj create mode 100644 Samples/PowerShell/Process/GetProcess01/cs/GetProcessSample01.sln create mode 100644 Samples/PowerShell/Process/GetProcess01/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/GetProcess02/README.md create mode 100644 Samples/PowerShell/Process/GetProcess02/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/GetProcess02/cs/GetProcessSample02.cs create mode 100644 Samples/PowerShell/Process/GetProcess02/cs/GetProcessSample02.csproj create mode 100644 Samples/PowerShell/Process/GetProcess02/cs/GetProcessSample02.sln create mode 100644 Samples/PowerShell/Process/GetProcess02/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/GetProcess03/README.md create mode 100644 Samples/PowerShell/Process/GetProcess03/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/GetProcess03/cs/GetProcessSample03.cs create mode 100644 Samples/PowerShell/Process/GetProcess03/cs/GetProcessSample03.csproj create mode 100644 Samples/PowerShell/Process/GetProcess03/cs/GetProcessSample03.sln create mode 100644 Samples/PowerShell/Process/GetProcess03/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/GetProcess04/README.md create mode 100644 Samples/PowerShell/Process/GetProcess04/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/GetProcess04/cs/GetProcessSample04.cs create mode 100644 Samples/PowerShell/Process/GetProcess04/cs/GetProcessSample04.csproj create mode 100644 Samples/PowerShell/Process/GetProcess04/cs/GetProcessSample04.sln create mode 100644 Samples/PowerShell/Process/GetProcess04/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/GetProcess05/README.md create mode 100644 Samples/PowerShell/Process/GetProcess05/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/GetProcess05/cs/GetProcessSample05.cs create mode 100644 Samples/PowerShell/Process/GetProcess05/cs/GetProcessSample05.csproj create mode 100644 Samples/PowerShell/Process/GetProcess05/cs/GetProcessSample05.sln create mode 100644 Samples/PowerShell/Process/GetProcess05/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/StopProcessSample01/README.md create mode 100644 Samples/PowerShell/Process/StopProcessSample01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample01/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/StopProcessSample01/cs/StopProcessSample01.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample01/cs/StopProcessSample01.csproj create mode 100644 Samples/PowerShell/Process/StopProcessSample01/cs/StopProcessSample01.sln create mode 100644 Samples/PowerShell/Process/StopProcessSample02/README.md create mode 100644 Samples/PowerShell/Process/StopProcessSample02/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample02/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/StopProcessSample02/cs/StopProcessSample02.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample02/cs/StopProcessSample02.csproj create mode 100644 Samples/PowerShell/Process/StopProcessSample02/cs/StopProcessSample02.sln create mode 100644 Samples/PowerShell/Process/StopProcessSample03/README.md create mode 100644 Samples/PowerShell/Process/StopProcessSample03/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample03/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/StopProcessSample03/cs/StopProcessSample03.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample03/cs/StopProcessSample03.csproj create mode 100644 Samples/PowerShell/Process/StopProcessSample03/cs/StopProcessSample03.sln create mode 100644 Samples/PowerShell/Process/StopProcessSample04/README.md create mode 100644 Samples/PowerShell/Process/StopProcessSample04/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample04/cs/Readme.txt create mode 100644 Samples/PowerShell/Process/StopProcessSample04/cs/StopProcessSample04.cs create mode 100644 Samples/PowerShell/Process/StopProcessSample04/cs/StopProcessSample04.csproj create mode 100644 Samples/PowerShell/Process/StopProcessSample04/cs/StopProcessSample04.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider01/README.md create mode 100644 Samples/PowerShell/Provider/AccessDBProvider01/cs/AccessDBProviderSample01.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider01/cs/AccessDBProviderSample01.csproj create mode 100644 Samples/PowerShell/Provider/AccessDBProvider01/cs/AccessDBProviderSample01.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider01/cs/Readme.txt create mode 100644 Samples/PowerShell/Provider/AccessDBProvider02/README.md create mode 100644 Samples/PowerShell/Provider/AccessDBProvider02/cs/AccessDBProviderSample02.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider02/cs/AccessDBProviderSample02.csproj create mode 100644 Samples/PowerShell/Provider/AccessDBProvider02/cs/AccessDBProviderSample02.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider02/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider02/cs/Readme.txt create mode 100644 Samples/PowerShell/Provider/AccessDBProvider03/README.md create mode 100644 Samples/PowerShell/Provider/AccessDBProvider03/cs/AccessDBProviderSample03.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider03/cs/AccessDBProviderSample03.csproj create mode 100644 Samples/PowerShell/Provider/AccessDBProvider03/cs/AccessDBProviderSample03.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider03/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider03/cs/Readme.txt create mode 100644 Samples/PowerShell/Provider/AccessDBProvider04/README.md create mode 100644 Samples/PowerShell/Provider/AccessDBProvider04/cs/AccessDBProviderSample04.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider04/cs/AccessDBProviderSample04.csproj create mode 100644 Samples/PowerShell/Provider/AccessDBProvider04/cs/AccessDBProviderSample04.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider04/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider04/cs/Readme.txt create mode 100644 Samples/PowerShell/Provider/AccessDBProvider05/README.md create mode 100644 Samples/PowerShell/Provider/AccessDBProvider05/cs/AccessDBProviderSample05.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider05/cs/AccessDBProviderSample05.csproj create mode 100644 Samples/PowerShell/Provider/AccessDBProvider05/cs/AccessDBProviderSample05.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider05/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider05/cs/Readme.txt create mode 100644 Samples/PowerShell/Provider/AccessDBProvider06/README.md create mode 100644 Samples/PowerShell/Provider/AccessDBProvider06/cs/AccessDBProviderSample06.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider06/cs/AccessDBProviderSample06.csproj create mode 100644 Samples/PowerShell/Provider/AccessDBProvider06/cs/AccessDBProviderSample06.sln create mode 100644 Samples/PowerShell/Provider/AccessDBProvider06/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Provider/AccessDBProvider06/cs/Readme.txt create mode 100644 Samples/PowerShell/Remoting/RemoteRunspace01/README.md create mode 100644 Samples/PowerShell/Remoting/RemoteRunspace01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Remoting/RemoteRunspace01/cs/Readme.txt create mode 100644 Samples/PowerShell/Remoting/RemoteRunspace01/cs/RemoteRunspace01.cs create mode 100644 Samples/PowerShell/Remoting/RemoteRunspace01/cs/RemoteRunspace01.csproj create mode 100644 Samples/PowerShell/Remoting/RemoteRunspace01/cs/RemoteRunspace01.sln create mode 100644 Samples/PowerShell/Remoting/RemoteRunspacePool01/README.md create mode 100644 Samples/PowerShell/Remoting/RemoteRunspacePool01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Remoting/RemoteRunspacePool01/cs/Readme.txt create mode 100644 Samples/PowerShell/Remoting/RemoteRunspacePool01/cs/RemoteRunspacePool01.cs create mode 100644 Samples/PowerShell/Remoting/RemoteRunspacePool01/cs/RemoteRunspacePool01.csproj create mode 100644 Samples/PowerShell/Remoting/RemoteRunspacePool01/cs/RemoteRunspacePool01.sln create mode 100644 Samples/PowerShell/Remoting/RemotingDisconnectConnect01/README.md create mode 100644 Samples/PowerShell/Remoting/RemotingDisconnectConnect01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Remoting/RemotingDisconnectConnect01/cs/Readme.txt create mode 100644 Samples/PowerShell/Remoting/RemotingDisconnectConnect01/cs/RemotingDisconnectConnect01.cs create mode 100644 Samples/PowerShell/Remoting/RemotingDisconnectConnect01/cs/RemotingDisconnectConnect01.csproj create mode 100644 Samples/PowerShell/Remoting/RemotingDisconnectConnect01/cs/RemotingDisconnectConnect01.sln create mode 100644 Samples/PowerShell/Runspace/Runspace01/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace01/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace01/cs/Runspace01.cs create mode 100644 Samples/PowerShell/Runspace/Runspace01/cs/Runspace01.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace01/cs/Runspace01.sln create mode 100644 Samples/PowerShell/Runspace/Runspace02/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace02/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace02/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace02/cs/Runspace02.cs create mode 100644 Samples/PowerShell/Runspace/Runspace02/cs/Runspace02.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace02/cs/Runspace02.sln create mode 100644 Samples/PowerShell/Runspace/Runspace03/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace03/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace03/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace03/cs/Runspace03.cs create mode 100644 Samples/PowerShell/Runspace/Runspace03/cs/Runspace03.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace03/cs/Runspace03.sln create mode 100644 Samples/PowerShell/Runspace/Runspace04/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace04/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace04/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace04/cs/Runspace04.cs create mode 100644 Samples/PowerShell/Runspace/Runspace04/cs/Runspace04.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace04/cs/Runspace04.sln create mode 100644 Samples/PowerShell/Runspace/Runspace05/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace05/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace05/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace05/cs/Runspace05.cs create mode 100644 Samples/PowerShell/Runspace/Runspace05/cs/Runspace05.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace05/cs/Runspace05.sln create mode 100644 Samples/PowerShell/Runspace/Runspace06/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace06/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace06/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace06/cs/Runspace06.cs create mode 100644 Samples/PowerShell/Runspace/Runspace06/cs/Runspace06.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace06/cs/Runspace06.sln create mode 100644 Samples/PowerShell/Runspace/Runspace07/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace07/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace07/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace07/cs/Runspace07.cs create mode 100644 Samples/PowerShell/Runspace/Runspace07/cs/Runspace07.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace07/cs/Runspace07.sln create mode 100644 Samples/PowerShell/Runspace/Runspace08/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace08/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace08/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace08/cs/Runspace08.cs create mode 100644 Samples/PowerShell/Runspace/Runspace08/cs/Runspace08.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace08/cs/Runspace08.sln create mode 100644 Samples/PowerShell/Runspace/Runspace09/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace09/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace09/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace09/cs/Runspace09.cs create mode 100644 Samples/PowerShell/Runspace/Runspace09/cs/Runspace09.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace09/cs/Runspace09.sln create mode 100644 Samples/PowerShell/Runspace/Runspace10/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace10/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace10/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace10/cs/Runspace10.cs create mode 100644 Samples/PowerShell/Runspace/Runspace10/cs/Runspace10.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace10/cs/Runspace10.sln create mode 100644 Samples/PowerShell/Runspace/Runspace11/README.md create mode 100644 Samples/PowerShell/Runspace/Runspace11/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Runspace/Runspace11/cs/Readme.txt create mode 100644 Samples/PowerShell/Runspace/Runspace11/cs/Runspace11.cs create mode 100644 Samples/PowerShell/Runspace/Runspace11/cs/Runspace11.csproj create mode 100644 Samples/PowerShell/Runspace/Runspace11/cs/Runspace11.sln create mode 100644 Samples/PowerShell/RunspacePool/README.md create mode 100644 Samples/PowerShell/RunspacePool/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/RunspacePool/cs/PowerShell02.cs create mode 100644 Samples/PowerShell/RunspacePool/cs/PowerShell02.csproj create mode 100644 Samples/PowerShell/RunspacePool/cs/PowerShell02.sln create mode 100644 Samples/PowerShell/RunspacePool/cs/Readme.txt create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/README.md create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/cs/ObjectCommandComparer.cs create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/cs/Readme.txt create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/cs/SelectObject01.cs create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/cs/SelectObject01.csproj create mode 100644 Samples/PowerShell/SelectObject/SelectObject01/cs/SelectObject01.sln create mode 100644 Samples/PowerShell/SelectString/SelectStrCommand/README.md create mode 100644 Samples/PowerShell/SelectString/SelectStrCommand/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/SelectString/SelectStrCommand/cs/Readme.txt create mode 100644 Samples/PowerShell/SelectString/SelectStrCommand/cs/SelectStrCommandSample.cs create mode 100644 Samples/PowerShell/SelectString/SelectStrCommand/cs/SelectStrCommandSample.csproj create mode 100644 Samples/PowerShell/SelectString/SelectStrCommand/cs/SelectStrCommandSample.sln create mode 100644 Samples/PowerShell/Serialization/Serialization01/README.md create mode 100644 Samples/PowerShell/Serialization/Serialization01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Serialization/Serialization01/cs/Readme.txt create mode 100644 Samples/PowerShell/Serialization/Serialization01/cs/Serialization01.cs create mode 100644 Samples/PowerShell/Serialization/Serialization01/cs/Serialization01.csproj create mode 100644 Samples/PowerShell/Serialization/Serialization01/cs/Serialization01.sln create mode 100644 Samples/PowerShell/Serialization/Serialization01/cs/Serialization01.types.ps1xml create mode 100644 Samples/PowerShell/Serialization/Serialization02/README.md create mode 100644 Samples/PowerShell/Serialization/Serialization02/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Serialization/Serialization02/cs/Readme.txt create mode 100644 Samples/PowerShell/Serialization/Serialization02/cs/Serialization02.cs create mode 100644 Samples/PowerShell/Serialization/Serialization02/cs/Serialization02.csproj create mode 100644 Samples/PowerShell/Serialization/Serialization02/cs/Serialization02.sln create mode 100644 Samples/PowerShell/Serialization/Serialization02/cs/Serialization02.types.ps1xml create mode 100644 Samples/PowerShell/Serialization/Serialization03/README.md create mode 100644 Samples/PowerShell/Serialization/Serialization03/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Serialization/Serialization03/cs/Readme.txt create mode 100644 Samples/PowerShell/Serialization/Serialization03/cs/Serialization03.cs create mode 100644 Samples/PowerShell/Serialization/Serialization03/cs/Serialization03.csproj create mode 100644 Samples/PowerShell/Serialization/Serialization03/cs/Serialization03.sln create mode 100644 Samples/PowerShell/Serialization/Serialization03/cs/Serialization03.types.ps1xml create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/README.md create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/GetNumbersCommand.cs create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/Readme.txt create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/Result.cs create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/SupportsPaging01.csproj create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/SupportsPaging01.ps1 create mode 100644 Samples/PowerShell/SupportsPaging/SupportsPaging01/cs/SupportsPaging01.sln create mode 100644 Samples/PowerShell/TemplateProvider/TemplateProvider01/README.md create mode 100644 Samples/PowerShell/TemplateProvider/TemplateProvider01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/TemplateProvider/TemplateProvider01/cs/Readme.txt create mode 100644 Samples/PowerShell/TemplateProvider/TemplateProvider01/cs/TemplateProvider01.cs create mode 100644 Samples/PowerShell/TemplateProvider/TemplateProvider01/cs/TemplateProvider01.csproj create mode 100644 Samples/PowerShell/TemplateProvider/TemplateProvider01/cs/TemplateProvider01.sln create mode 100644 Samples/PowerShell/Transactions/Transactions01/README.md create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/AddTransactedCommentCommand.cs create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/ClearTransactedCommentCommand.cs create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/GetTransactedCommentCommand.cs create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/Readme.txt create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/TransactedComment.cs create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/TransactedComment.csproj create mode 100644 Samples/PowerShell/Transactions/Transactions01/cs/TransactedComment.sln create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/README.md create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/ActivityControllerExtensibilitySample.csproj create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/ActivityControllerExtensibilitySample.sln create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/CustomWorkflowEndpointSetup.ps1 create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/Program.cs create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/Readme.txt create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/SampleActivityController.cs create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/SampleConfigurationProvider.cs create mode 100644 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs/SampleWorkflow.xaml create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/README.md create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/AssemblyInfo.cs create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/Program.cs create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/Readme.txt create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/SampleConfigurationProvider.cs create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/SampleWorkflow.xaml create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/SimpleExtensibilitySample.csproj create mode 100644 Samples/PowerShellWorkflow/SimpleExtensibility/cs/SimpleExtensibilitySample.sln create mode 100644 Samples/RoleBasedPlugins/README.md create mode 100644 Samples/RoleBasedPlugins/cs/AssemblyInfo.cs create mode 100644 Samples/RoleBasedPlugins/cs/CustomAuthorization.cs create mode 100644 Samples/RoleBasedPlugins/cs/NativeMethods.cs create mode 100644 Samples/RoleBasedPlugins/cs/Rbac.xsd create mode 100644 Samples/RoleBasedPlugins/cs/RbacConfiguration.cs create mode 100644 Samples/RoleBasedPlugins/cs/RbacGroup.cs create mode 100644 Samples/RoleBasedPlugins/cs/RbacQuota.cs create mode 100644 Samples/RoleBasedPlugins/cs/RbacSystem.cs create mode 100644 Samples/RoleBasedPlugins/cs/RbacUser.cs create mode 100644 Samples/RoleBasedPlugins/cs/Resources.Designer.cs create mode 100644 Samples/RoleBasedPlugins/cs/Resources.resx create mode 100644 Samples/RoleBasedPlugins/cs/RoleBasedPlugins.csproj create mode 100644 Samples/RoleBasedPlugins/cs/RoleBasedPlugins.sln create mode 100644 Samples/RoleBasedPlugins/cs/SessionConfiguration.cs create mode 100644 Samples/RoleBasedPlugins/cs/Utils.cs create mode 100644 Samples/RoleBasedPlugins/cs/WindowsIdentityHelper.cs create mode 100644 Samples/RoleBasedPlugins/cs/setup/InstallModata.ps1 create mode 100644 Samples/RoleBasedPlugins/cs/setup/Microsoft.Management.Odata.svc create mode 100644 Samples/RoleBasedPlugins/cs/setup/RbacConfiguration.xml create mode 100644 Samples/RoleBasedPlugins/cs/setup/Readme.txt create mode 100644 Samples/RoleBasedPlugins/cs/setup/Schema.mof create mode 100644 Samples/RoleBasedPlugins/cs/setup/Schema.xml create mode 100644 Samples/RoleBasedPlugins/cs/setup/SetupEndpoint.ps1 create mode 100644 Samples/RoleBasedPlugins/cs/setup/SetupIISConfig.ps1 create mode 100644 Samples/RoleBasedPlugins/cs/setup/Web.config create mode 100644 Samples/RoutingandRemoteAccessService/README.md create mode 100644 Samples/RoutingandRemoteAccessService/Readme.txt create mode 100644 Samples/RoutingandRemoteAccessService/cpp/InterfaceConfiguration.cpp create mode 100644 Samples/RoutingandRemoteAccessService/cpp/InterfaceConfiguration.h create mode 100644 Samples/RoutingandRemoteAccessService/cpp/MprApiSample.sln create mode 100644 Samples/RoutingandRemoteAccessService/cpp/MprApiSample.vcxproj create mode 100644 Samples/RoutingandRemoteAccessService/cpp/ServerConfiguration.cpp create mode 100644 Samples/RoutingandRemoteAccessService/cpp/ServerConfiguration.h create mode 100644 Samples/RoutingandRemoteAccessService/cpp/Utils.cpp create mode 100644 Samples/RoutingandRemoteAccessService/cpp/Utils.h create mode 100644 Samples/RoutingandRemoteAccessService/cpp/VpnConnection.cpp create mode 100644 Samples/RoutingandRemoteAccessService/cpp/VpnConnection.h create mode 100644 Samples/RoutingandRemoteAccessService/cpp/main.cpp create mode 100644 Samples/ScanRestorableFiles/README.md create mode 100644 Samples/ScanRestorableFiles/cpp/ScanRestorableFiles.cpp create mode 100644 Samples/ScanRestorableFiles/cpp/ScanRestorableFiles.sln create mode 100644 Samples/ScanRestorableFiles/cpp/ScanRestorableFiles.vcxproj create mode 100644 Samples/Security/CipherEncryptionDecryption/README.md create mode 100644 Samples/Security/CipherEncryptionDecryption/cpp/CipherEncryptionDecryption.cpp create mode 100644 Samples/Security/CipherEncryptionDecryption/cpp/CipherEncryptionDecryption.sln create mode 100644 Samples/Security/CipherEncryptionDecryption/cpp/CipherEncryptionDecryption.vcxproj create mode 100644 Samples/Security/CodeSigning/README.md create mode 100644 Samples/Security/CodeSigning/cpp/codesigning.cpp create mode 100644 Samples/Security/CodeSigning/cpp/codesigning.sln create mode 100644 Samples/Security/CodeSigning/cpp/codesigning.vcxproj create mode 100644 Samples/Security/CodeSigning/cpp/codesigning.vcxproj.filters create mode 100644 Samples/Security/DataProtection/README.md create mode 100644 Samples/Security/DataProtection/cpp/DataProtection.cpp create mode 100644 Samples/Security/DataProtection/cpp/DataProtection.sln create mode 100644 Samples/Security/DataProtection/cpp/DataProtection.vcxproj create mode 100644 Samples/Security/DhOakleyGroup1/README.md create mode 100644 Samples/Security/DhOakleyGroup1/cpp/DhOakleyGroup1.cpp create mode 100644 Samples/Security/DhOakleyGroup1/cpp/DhOakleyGroup1.sln create mode 100644 Samples/Security/DhOakleyGroup1/cpp/DhOakleyGroup1.vcxproj create mode 100644 Samples/Security/EffectiveAccessRights/README.md create mode 100644 Samples/Security/EffectiveAccessRights/cs/App.config create mode 100644 Samples/Security/EffectiveAccessRights/cs/AvailableCentralPolicies.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/EffectiveAccess.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/EffectiveAccess.csproj create mode 100644 Samples/Security/EffectiveAccessRights/cs/EffectiveAccess.sln create mode 100644 Samples/Security/EffectiveAccessRights/cs/GlobalSuppressions.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Groups.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Program.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Properties/AssemblyInfo.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/SecurityAttribute.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Utility/Helper.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Utility/SafeHandleEx.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Utility/TokenPrivilege.cs create mode 100644 Samples/Security/EffectiveAccessRights/cs/Utility/Win32.cs create mode 100644 Samples/Security/GetAppliedCentralPolicies/README.md create mode 100644 Samples/Security/GetAppliedCentralPolicies/cpp/GetAppliedCentralPolicies.cpp create mode 100644 Samples/Security/GetAppliedCentralPolicies/cpp/GetAppliedCentralPolicies.sln create mode 100644 Samples/Security/GetAppliedCentralPolicies/cpp/GetAppliedCentralPolicies.vcxproj create mode 100644 Samples/Security/GetAppliedCentralPolicies/cpp/GetAppliedCentralPolicies.vcxproj.filters create mode 100644 Samples/Security/HashComputation/README.md create mode 100644 Samples/Security/HashComputation/cpp/HashComputation.cpp create mode 100644 Samples/Security/HashComputation/cpp/HashComputation.sln create mode 100644 Samples/Security/HashComputation/cpp/HashComputation.vcxproj create mode 100644 Samples/Security/KeyDerivation/README.md create mode 100644 Samples/Security/KeyDerivation/cpp/KeyDerivation.cpp create mode 100644 Samples/Security/KeyDerivation/cpp/KeyDerivation.h create mode 100644 Samples/Security/KeyDerivation/cpp/KeyDerivation.sln create mode 100644 Samples/Security/KeyDerivation/cpp/KeyDerivation.vcxproj create mode 100644 Samples/Security/KeyDerivationWithPersistedKeys/README.md create mode 100644 Samples/Security/KeyDerivationWithPersistedKeys/cpp/KeyDerivationWithPersistedKeys.cpp create mode 100644 Samples/Security/KeyDerivationWithPersistedKeys/cpp/KeyDerivationWithPersistedKeys.sln create mode 100644 Samples/Security/KeyDerivationWithPersistedKeys/cpp/KeyDerivationWithPersistedKeys.vcxproj create mode 100644 Samples/Security/RSACapiAndCngInterop/README.md create mode 100644 Samples/Security/RSACapiAndCngInterop/cpp/RSACapiAndCngInterop.cpp create mode 100644 Samples/Security/RSACapiAndCngInterop/cpp/RSACapiAndCngInterop.sln create mode 100644 Samples/Security/RSACapiAndCngInterop/cpp/RSACapiAndCngInterop.vcxproj create mode 100644 Samples/Security/RandomNumGeneration/README.md create mode 100644 Samples/Security/RandomNumGeneration/cpp/RandomNumGeneration.cpp create mode 100644 Samples/Security/RandomNumGeneration/cpp/RandomNumGeneration.sln create mode 100644 Samples/Security/RandomNumGeneration/cpp/RandomNumGeneration.vcxproj create mode 100644 Samples/Security/ResourceAttributes/README.md create mode 100644 Samples/Security/ResourceAttributes/cpp/ResourceAttributesSample.cpp create mode 100644 Samples/Security/ResourceAttributes/cpp/ResourceAttributesSample.h create mode 100644 Samples/Security/ResourceAttributes/cpp/ResourceAttributesSample.sln create mode 100644 Samples/Security/ResourceAttributes/cpp/ResourceAttributesSample.vcxproj create mode 100644 Samples/Security/ResourceAttributes/cpp/ResourceAttributesSample.vcxproj.filters create mode 100644 Samples/Security/SHA1-HMACComputation/README.md create mode 100644 Samples/Security/SHA1-HMACComputation/cpp/HmacComputation.cpp create mode 100644 Samples/Security/SHA1-HMACComputation/cpp/HmacComputation.sln create mode 100644 Samples/Security/SHA1-HMACComputation/cpp/HmacComputation.vcxproj create mode 100644 Samples/Security/SecretAgreementWithPersistedKeys/README.md create mode 100644 Samples/Security/SecretAgreementWithPersistedKeys/cpp/SecretAgreementWithPersistedKeys.cpp create mode 100644 Samples/Security/SecretAgreementWithPersistedKeys/cpp/SecretAgreementWithPersistedKeys.sln create mode 100644 Samples/Security/SecretAgreementWithPersistedKeys/cpp/SecretAgreementWithPersistedKeys.vcxproj create mode 100644 Samples/Security/SignHashAndVerifySignature/README.md create mode 100644 Samples/Security/SignHashAndVerifySignature/cpp/SignHashAndVerifySignature.cpp create mode 100644 Samples/Security/SignHashAndVerifySignature/cpp/SignHashAndVerifySignature.sln create mode 100644 Samples/Security/SignHashAndVerifySignature/cpp/SignHashAndVerifySignature.vcxproj create mode 100644 Samples/Security/SignHashWithPersistedKeys/README.md create mode 100644 Samples/Security/SignHashWithPersistedKeys/cpp/SignHashWithPersistedKeys.cpp create mode 100644 Samples/Security/SignHashWithPersistedKeys/cpp/SignHashWithPersistedKeys.sln create mode 100644 Samples/Security/SignHashWithPersistedKeys/cpp/SignHashWithPersistedKeys.vcxproj create mode 100644 Samples/Security/StrongKeyProtection/README.md create mode 100644 Samples/Security/StrongKeyProtection/cpp/StrongKeyProtection.cpp create mode 100644 Samples/Security/StrongKeyProtection/cpp/StrongKeyProtection.sln create mode 100644 Samples/Security/StrongKeyProtection/cpp/StrongKeyProtection.vcxproj create mode 100644 Samples/ServerEssentialsDashboard/README.md create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSDashboard.sln create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/StandaloneXml/Image.png create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/StandaloneXml/WindowsUpdatesHomePageTask.home create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/StandaloneXml/readme.txt create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/XmlInDll/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/XmlInDll/WindowsUpdates.home create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/XmlInDll/WindowsUpdates.home.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/XmlInDll/WindowsUpdates.home.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/XmlInDll/WindowsUpdatesTask.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommonTasks/XmlInDll/pics/Windows_update_icon.png create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommunity/Sample.home create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageCommunity/readme.txt create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/CancellableAsyncQuickStatus/CancellableAsyncQuickStatus.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/CancellableAsyncQuickStatus/CancellableAsyncQuickStatus.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/CancellableAsyncQuickStatus/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/CustomQuickStatus.home create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/SyncQuickStatus/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/SyncQuickStatus/Resources.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/SyncQuickStatus/Resources.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/SyncQuickStatus/SyncQuickStatus.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSHomepageQuickStatus/SyncQuickStatus/SyncQuickStatus.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/MyBusinessObject.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabDetails.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabListColumns.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabListGroupings.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabListProvider.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/SubTabTasks.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabListviewSample/WSSSubTabListviewSample.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/MyCustomWPFControl/MyControlHost.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/MyCustomWPFControl/MyControlHost.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/MyCustomWPFControl/MyControlHost.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/MyCustomWPFControl/MyCustomWPFControl.xaml create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/MyCustomWPFControl/MyCustomWPFControl.xaml.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/SubTabAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWPFSample/WSSSubTabWPFSample.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWinFormsSample/MyCustomWinformControl/MyCustomWinformControl.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWinFormsSample/MyCustomWinformControl/MyCustomWinformControl.designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWinFormsSample/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWinFormsSample/SubTabAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWinFormsSample/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSSubTabWinFormsSample/WSSSubTabWinFormsSample.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTabExtenderSample/ListAdorner.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTabExtenderSample/PageAdorner.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTabExtenderSample/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTabExtenderSample/TabExtensionAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTabExtenderSample/WSSTabExtenderSample.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/ListViewSubTab.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/MyBusinessObject.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/SubTabDetails.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/SubTabListColumns.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/SubTabListGroupings.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/SubTabListProvider.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/ListViewSubTab/SubTabTasks.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/Resources/GenericIcon.ico create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/TopLevelAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/TopLevelTab.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/TopLevelTab.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/WSSTopLevelTabListView.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabListViewSample/TopLevelTab/WSSTopLevelTabListView.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/ListViewSubTab.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/MyBusinessObject.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/SubTabDetails.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/SubTabListColumns.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/SubTabListGroupings.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/SubTabListProvider.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/ListViewSubTab/SubTabTasks.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/CustomSubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/MyCustomWinformControl/MyCustomWinformControl.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/MyCustomWinformControl/MyCustomWinformControl.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/Resources/GenericIcon.ico create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/TopLevelAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/TopLevelTab.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/TopLevelTab.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/WSSTopLevelTwoSubTabsSample.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabTwoSubTabsSample/TopLevelTab/WSSTopLevelTwoSubTabsSample.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/MyCustomWPFControl/MyControlHost.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/MyCustomWPFControl/MyControlHost.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/MyCustomWPFControl/MyControlHost.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/MyCustomWPFControl/MyCustomWPFControl.xaml create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/MyCustomWPFControl/MyCustomWPFControl.xaml.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/Resources/GenericIcon.ico create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/TopLevelTab.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/TopLevelTabResources.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/TopLevelTabResources.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/WSSTopLevelTabWPFSample.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWPFSample/WSSTopLevelTabWPFSample.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/MyCustomWinformControl/MyCustomWinformControl.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/MyCustomWinformControl/MyCustomWinformControl.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/Resources/GenericIcon.ico create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/SubTabPage.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/TopLevelAddinConfig.addin create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/TopLevelTab.Designer.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/TopLevelTab.cs create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/TopLevelTab.resx create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSTopLevelTabWinformsSample/WSSTopLevelTabWinformsSample.csproj create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSUserExtensions/Sample.proplink create mode 100644 Samples/ServerEssentialsDashboard/cs/WSSUserExtensions/readme.txt create mode 100644 Samples/ServerEssentialsHostedEmail/README.md create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoCustomAction/ContosoCustomAction.csproj create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoCustomAction/CustomAction.config create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoCustomAction/CustomAction.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoCustomAction/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoHostedEmail.sln create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoHostedEmailAdaptorLogMonitor/ContosoHostedEmailAdaptorLogMonitor.csproj create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoHostedEmailAdaptorLogMonitor/Program.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoHostedEmailAdaptorLogMonitor/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/AccountManager.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/AccountManagerExceptions.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/CSVUtil.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/Constants.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/ContosoMockEmailService.csproj create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/DataConverter.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/EmailServiceConfiguration.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/LogManager.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/MockEmailService.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/MockEmailServiceConfiguration.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/MockEmailServiceConfiguration.xml create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/MockEmailServiceConfiguration.xsd create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/Resources.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/ContosoMockEmailService/Resources.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/ContosoHostedEmail.home create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/ContosoHostedEmail.home.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/ContosoHostedEmail.home.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/ContosoHostedEmailHomepageAddin.csproj create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/LearnMore.png create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/Logo.png create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HomepageAddin/Wssg.HostedEmailConfigureWizard.vbs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/Adaptor/ContosoHostedEmailAdaptor.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/Adaptor/CredentialManager.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/AddinFiles/ContosoDistributionGroupAddin.addin create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/AddinFiles/ContosoHostedEmail.addin create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/AddinFiles/ContosoTopLevelDashboard.addin create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/AddinFiles/ContosoUserPropertyAdvanced.addin create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/ContosoHostedEmailAddin.csproj create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DGSelectCtrl.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DGSelectCtrl.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DGSelectCtrl.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DistributionGroupAdorner.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DistributionGroupControl.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DistributionGroupControl.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/DistributionGroup/DistributionGroupControl.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/Resources.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/Resources.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/Schema/HosteEmailAddinSchema.xsd create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/AdvancedPage.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/GlobalTasks.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/HostedEmailAddinWinform/SampleAddinForm.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/HostedEmailAddinWinform/SampleAddinForm.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/HostedEmailAddinWinform/SampleAddinForm.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/HostedEmailAddinWinform/UserPropertyAdvancedForm.Designer.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/HostedEmailAddinWinform/UserPropertyAdvancedForm.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/HostedEmailAddinWinform/UserPropertyAdvancedForm.resx create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/SubTabPage.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/TopLevelTab.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/UIConstants.cs create mode 100644 Samples/ServerEssentialsHostedEmail/cs/HostedEmailAddin/UI/Wssg.HostedEmailConfigureWizard.Reset.vbs create mode 100644 Samples/ServerEssentialsLaunchpad/README.md create mode 100644 Samples/ServerEssentialsLaunchpad/cs/Content.launchpad create mode 100644 Samples/ServerEssentialsLaunchpad/cs/Launchpad.Designer.cs create mode 100644 Samples/ServerEssentialsLaunchpad/cs/Launchpad.resx create mode 100644 Samples/ServerEssentialsLaunchpad/cs/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsLaunchpad/cs/WSSLaunchpadAddinWithResource.csproj create mode 100644 Samples/ServerEssentialsLaunchpad/cs/WSSLaunchpadAddinWithResource.sln create mode 100644 Samples/ServerEssentialsProvider/README.md create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider.sln create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/ChatProvider.ObjectModel.csproj create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/ChatReceivedEventArgs.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/IProvider.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/IProviderCallback.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/ObjectModel.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/ObjectModelImplementation.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider.ObjectModel/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider/ChatProvider.csproj create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider/Program.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider/ProviderCore.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider/ProviderService.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatProvider/ChatProvider/app.config create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/App.xaml create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/App.xaml.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/ChatWindow.csproj create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/MainWindow.xaml create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/MainWindow.xaml.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/Properties/AssemblyInfo.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/Properties/Resources.Designer.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/Properties/Resources.resx create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/Properties/Settings.Designer.cs create mode 100644 Samples/ServerEssentialsProvider/cs/ChatWindow/Properties/Settings.settings create mode 100644 Samples/ServerManagerDeploymentCIM/README.md create mode 100644 Samples/ServerManagerDeploymentCIM/cs/AddRoleSample.cs create mode 100644 Samples/ServerManagerDeploymentCIM/cs/AssemblyInfo.cs create mode 100644 Samples/ServerManagerDeploymentCIM/cs/GetRoleSample.cs create mode 100644 Samples/ServerManagerDeploymentCIM/cs/Program.cs create mode 100644 Samples/ServerManagerDeploymentCIM/cs/RemoveRoleSample.cs create mode 100644 Samples/ServerManagerDeploymentCIM/cs/SMDSampleApp.csproj create mode 100644 Samples/ServerManagerDeploymentCIM/cs/SMDSampleApp.sln create mode 100644 Samples/SpellCheckerClient/README.md create mode 100644 Samples/SpellCheckerClient/cpp/Readme.txt create mode 100644 Samples/SpellCheckerClient/cpp/SampleSpellingClient.cpp create mode 100644 Samples/SpellCheckerClient/cpp/SampleSpellingClient.sln create mode 100644 Samples/SpellCheckerClient/cpp/SampleSpellingClient.vcxproj create mode 100644 Samples/SpellCheckerClient/cpp/SampleSpellingClient.vcxproj.filters create mode 100644 Samples/SpellCheckerClient/cpp/commands.h create mode 100644 Samples/SpellCheckerClient/cpp/onspellcheckerchanged.h create mode 100644 Samples/SpellCheckerClient/cpp/resources.rc create mode 100644 Samples/SpellCheckerClient/cpp/spellprint.h create mode 100644 Samples/SpellCheckerClient/cpp/util.h create mode 100644 Samples/SpellCheckerProvider/README.md create mode 100644 Samples/SpellCheckerProvider/cpp/EnumSpellingError.cpp create mode 100644 Samples/SpellCheckerProvider/cpp/EnumSpellingError.h create mode 100644 Samples/SpellCheckerProvider/cpp/EnumString.h create mode 100644 Samples/SpellCheckerProvider/cpp/OptionDescription.cpp create mode 100644 Samples/SpellCheckerProvider/cpp/OptionDescription.h create mode 100644 Samples/SpellCheckerProvider/cpp/Readme.txt create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellCheckProvider.cpp create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellCheckProvider.h create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellCheckProviderFactory.cpp create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellCheckProviderFactory.h create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellChecker.def create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellChecker.idl create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellChecker.rgs create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellCheckerModule.cpp create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellingProvider.sln create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellingProvider.vcxproj create mode 100644 Samples/SpellCheckerProvider/cpp/SampleSpellingProvider.vcxproj.filters create mode 100644 Samples/SpellCheckerProvider/cpp/SpellingError.cpp create mode 100644 Samples/SpellCheckerProvider/cpp/SpellingError.h create mode 100644 Samples/SpellCheckerProvider/cpp/currentuser.reg create mode 100644 Samples/SpellCheckerProvider/cpp/engineoptions.h create mode 100644 Samples/SpellCheckerProvider/cpp/localmachine.reg create mode 100644 Samples/SpellCheckerProvider/cpp/resource.h create mode 100644 Samples/SpellCheckerProvider/cpp/resources.rc create mode 100644 Samples/SpellCheckerProvider/cpp/sampleengine.h create mode 100644 Samples/SpellCheckerProvider/cpp/util.h create mode 100644 Samples/StorageManagement/README.md create mode 100644 Samples/StorageManagement/cpp/StorageManagementApplication.cpp create mode 100644 Samples/StorageManagement/cpp/StorageManagementApplication.h create mode 100644 Samples/StorageManagement/cpp/StorageManagementApplication.sln create mode 100644 Samples/StorageManagement/cpp/StorageManagementApplication.vcxproj create mode 100644 Samples/StorageManagement/cpp/StorageManagementApplication.vcxproj.filters create mode 100644 Samples/TimerCoalescence/README.md create mode 100644 Samples/TimerCoalescence/cpp/timer.cpp create mode 100644 Samples/TimerCoalescence/cpp/timer.rc create mode 100644 Samples/TimerCoalescence/cpp/timer.sln create mode 100644 Samples/TimerCoalescence/cpp/timer.vcxproj create mode 100644 Samples/TouchHitTesting/README.md create mode 100644 Samples/TouchHitTesting/cpp/D2DDriver.cpp create mode 100644 Samples/TouchHitTesting/cpp/D2DDriver.h create mode 100644 Samples/TouchHitTesting/cpp/Program.cpp create mode 100644 Samples/TouchHitTesting/cpp/Program.h create mode 100644 Samples/TouchHitTesting/cpp/Shape.cpp create mode 100644 Samples/TouchHitTesting/cpp/Shape.h create mode 100644 Samples/TouchHitTesting/cpp/ShapesPuzzleDesktop.cpp create mode 100644 Samples/TouchHitTesting/cpp/ShapesPuzzleDesktop.rc create mode 100644 Samples/TouchHitTesting/cpp/ShapesPuzzleDesktop.sln create mode 100644 Samples/TouchHitTesting/cpp/ShapesPuzzleDesktop.vcxproj create mode 100644 Samples/TouchHitTesting/cpp/resource.h create mode 100644 Samples/TouchInputDirectManipulation/README.md create mode 100644 Samples/TouchInputDirectManipulation/cpp/AppWindow.cpp create mode 100644 Samples/TouchInputDirectManipulation/cpp/AppWindow.h create mode 100644 Samples/TouchInputDirectManipulation/cpp/Circles.png create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.cpp create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.h create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.ico create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.rc create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.sln create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.vcxproj create mode 100644 Samples/TouchInputDirectManipulation/cpp/DirectManipulationSample.vcxproj.filters create mode 100644 Samples/TouchInputDirectManipulation/cpp/Resource.h create mode 100644 Samples/TouchInputDirectManipulation/cpp/ViewportEventHandler.cpp create mode 100644 Samples/TouchInputDirectManipulation/cpp/ViewportEventHandler.h create mode 100644 Samples/TouchInputDirectManipulation/cpp/small.ico create mode 100644 Samples/TouchInputDirectManipulation/cpp/stdafx.cpp create mode 100644 Samples/TouchInputDirectManipulation/cpp/stdafx.h create mode 100644 Samples/TouchInputDirectManipulation/cpp/targetver.h create mode 100644 Samples/UIAutomationCleanShutdown/README.md create mode 100644 Samples/UIAutomationCleanShutdown/ReadMe.txt create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdown.sln create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownControl/UiaCleanShutdownControl.cpp create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownControl/UiaCleanShutdownControl.def create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownControl/UiaCleanShutdownControl.h create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownControl/UiaCleanShutdownControl.vcxproj create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownControl/UiaProvider.cpp create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownControl/UiaProvider.h create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownHost/UiaCleanShutdownHost.cpp create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownHost/UiaCleanShutdownHost.exe.manifest create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownHost/UiaCleanShutdownHost.rc create mode 100644 Samples/UIAutomationCleanShutdown/cpp/UiaCleanShutdownHost/UiaCleanShutdownHost.vcxproj create mode 100644 Samples/UIAutomationDocumentClient/README.md create mode 100644 Samples/UIAutomationDocumentClient/ReadMe.txt create mode 100644 Samples/UIAutomationDocumentClient/cpp/UiaDocumentClient.cpp create mode 100644 Samples/UIAutomationDocumentClient/cpp/UiaDocumentClient.sln create mode 100644 Samples/UIAutomationDocumentClient/cpp/UiaDocumentClient.vcxproj create mode 100644 Samples/UIAutomationDocumentProvider/README.md create mode 100644 Samples/UIAutomationDocumentProvider/ReadMe.txt create mode 100644 Samples/UIAutomationDocumentProvider/cpp/AnnotatedTextControl.cpp create mode 100644 Samples/UIAutomationDocumentProvider/cpp/AnnotatedTextControl.h create mode 100644 Samples/UIAutomationDocumentProvider/cpp/AnnotationProvider.cpp create mode 100644 Samples/UIAutomationDocumentProvider/cpp/AnnotationProvider.h create mode 100644 Samples/UIAutomationDocumentProvider/cpp/FrameProvider.cpp create mode 100644 Samples/UIAutomationDocumentProvider/cpp/FrameProvider.h create mode 100644 Samples/UIAutomationDocumentProvider/cpp/TextAreaProvider.cpp create mode 100644 Samples/UIAutomationDocumentProvider/cpp/TextAreaProvider.h create mode 100644 Samples/UIAutomationDocumentProvider/cpp/UiaDocumentProvider.cpp create mode 100644 Samples/UIAutomationDocumentProvider/cpp/UiaDocumentProvider.sln create mode 100644 Samples/UIAutomationDocumentProvider/cpp/UiaDocumentProvider.vcxproj create mode 100644 Samples/UIAutomationDocumentProvider/cpp/UiaDocumentProviderSample.partial.manifest create mode 100644 Samples/UIAutomationFragmentProvider/README.md create mode 100644 Samples/UIAutomationFragmentProvider/cpp/CustomControl.cpp create mode 100644 Samples/UIAutomationFragmentProvider/cpp/CustomControl.h create mode 100644 Samples/UIAutomationFragmentProvider/cpp/ListItemProvider.cpp create mode 100644 Samples/UIAutomationFragmentProvider/cpp/ListProvider.cpp create mode 100644 Samples/UIAutomationFragmentProvider/cpp/UIAFragmentProvider.cpp create mode 100644 Samples/UIAutomationFragmentProvider/cpp/UIAFragmentProvider.ico create mode 100644 Samples/UIAutomationFragmentProvider/cpp/UIAFragmentProvider.rc create mode 100644 Samples/UIAutomationFragmentProvider/cpp/UIAFragmentProvider.sln create mode 100644 Samples/UIAutomationFragmentProvider/cpp/UIAFragmentProvider.vcxproj create mode 100644 Samples/UIAutomationFragmentProvider/cpp/UIAProviders.h create mode 100644 Samples/UIAutomationFragmentProvider/cpp/resource.h create mode 100644 Samples/UIAutomationFragmentProvider/cpp/stdafx.h create mode 100644 Samples/UIAutomationSimpleProvider/README.md create mode 100644 Samples/UIAutomationSimpleProvider/cpp/Control.cpp create mode 100644 Samples/UIAutomationSimpleProvider/cpp/Control.h create mode 100644 Samples/UIAutomationSimpleProvider/cpp/Provider.cpp create mode 100644 Samples/UIAutomationSimpleProvider/cpp/Provider.h create mode 100644 Samples/UIAutomationSimpleProvider/cpp/UiaSimpleProvider.cpp create mode 100644 Samples/UIAutomationSimpleProvider/cpp/UiaSimpleProvider.ico create mode 100644 Samples/UIAutomationSimpleProvider/cpp/UiaSimpleProvider.rc create mode 100644 Samples/UIAutomationSimpleProvider/cpp/UiaSimpleProvider.sln create mode 100644 Samples/UIAutomationSimpleProvider/cpp/UiaSimpleProvider.vcxproj create mode 100644 Samples/UIAutomationSimpleProvider/cpp/resource.h create mode 100644 Samples/UIAutomationSimpleProvider/cpp/stdafx.h create mode 100644 Samples/UPnPDimmerService/README.md create mode 100644 Samples/UPnPDimmerService/Readme.txt create mode 100644 Samples/UPnPDimmerService/cpp/DeviceDll.cpp create mode 100644 Samples/UPnPDimmerService/cpp/DeviceDll.def create mode 100644 Samples/UPnPDimmerService/cpp/DeviceDll.h create mode 100644 Samples/UPnPDimmerService/cpp/DimmerDevice.idl create mode 100644 Samples/UPnPDimmerService/cpp/DimmerDeviceDCO.cpp create mode 100644 Samples/UPnPDimmerService/cpp/DimmerDeviceDCO.h create mode 100644 Samples/UPnPDimmerService/cpp/DimmerDeviceDCO.rgs create mode 100644 Samples/UPnPDimmerService/cpp/DimmerService.cpp create mode 100644 Samples/UPnPDimmerService/cpp/DimmerService.h create mode 100644 Samples/UPnPDimmerService/cpp/UPNPSampleDimmerDevice.rc create mode 100644 Samples/UPnPDimmerService/cpp/UPNPSampleDimmerDevice.sln create mode 100644 Samples/UPnPDimmerService/cpp/UPNPSampleDimmerDevice.vcxproj create mode 100644 Samples/UPnPDimmerService/cpp/resource.h create mode 100644 Samples/UPnPGenericUCP/README.md create mode 100644 Samples/UPnPGenericUCP/Readme.txt create mode 100644 Samples/UPnPGenericUCP/cpp/CAsyncResult.h create mode 100644 Samples/UPnPGenericUCP/cpp/GenericUCPDlg.cpp create mode 100644 Samples/UPnPGenericUCP/cpp/SCPDDisplay.cpp create mode 100644 Samples/UPnPGenericUCP/cpp/SCPDDisplay.h create mode 100644 Samples/UPnPGenericUCP/cpp/Util.cpp create mode 100644 Samples/UPnPGenericUCP/cpp/Util.h create mode 100644 Samples/UPnPGenericUCP/cpp/deviceprop.cpp create mode 100644 Samples/UPnPGenericUCP/cpp/deviceprop.h create mode 100644 Samples/UPnPGenericUCP/cpp/devtype.txt create mode 100644 Samples/UPnPGenericUCP/cpp/genericucp.cpp create mode 100644 Samples/UPnPGenericUCP/cpp/genericucp.h create mode 100644 Samples/UPnPGenericUCP/cpp/genericucp.ico create mode 100644 Samples/UPnPGenericUCP/cpp/genericucp.rc create mode 100644 Samples/UPnPGenericUCP/cpp/genericucp.sln create mode 100644 Samples/UPnPGenericUCP/cpp/genericucp.vcxproj create mode 100644 Samples/UPnPGenericUCP/cpp/genericucpdlg.h create mode 100644 Samples/UPnPGenericUCP/cpp/resource.h create mode 100644 Samples/UPnPGenericUCP/cpp/stdafx.cpp create mode 100644 Samples/UPnPGenericUCP/cpp/stdafx.h create mode 100644 Samples/UPnPGenericUCP/cpp/udn.txt create mode 100644 Samples/UPnPRegisterDevice/README.md create mode 100644 Samples/UPnPRegisterDevice/Readme.txt create mode 100644 Samples/UPnPRegisterDevice/cpp/DimmerDevice-Desc.xml create mode 100644 Samples/UPnPRegisterDevice/cpp/DimmerPresentation.htm create mode 100644 Samples/UPnPRegisterDevice/cpp/DimmingService_SCPD.xml create mode 100644 Samples/UPnPRegisterDevice/cpp/RegDevice.cpp create mode 100644 Samples/UPnPRegisterDevice/cpp/RegDevice.sln create mode 100644 Samples/UPnPRegisterDevice/cpp/RegDevice.vcxproj create mode 100644 Samples/VShadowVolumeShadowCopy/README.md create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/break.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/create.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/delete.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/expose.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/macros.h create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/query.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/readme.html create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/readme.txt create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/revert.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/select.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/shadow.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/shadow.h create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/stdafx.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/stdafx.h create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/tracing.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/tracing.h create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/util.h create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/vshadow.rc create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/vshadow.sln create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/vshadow.vcxproj create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/vshadow.vcxproj.filters create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/vssclient.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/vssclient.h create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/writer.cpp create mode 100644 Samples/VShadowVolumeShadowCopy/cpp/writer.h create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/README.md create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/ExpressW.sln create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/ExpressW.vcxproj create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/ExpressW.vcxproj.filters create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/helpers.cpp create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/helpers.h create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/main.cpp create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/readme.txt create mode 100644 Samples/VolumeShadowCopyServiceExpressWriter/cpp/stdafx.h create mode 100644 Samples/VolumeShadowCopyServiceProvider/README.md create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/VssSampleProvider.vcxproj create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/VssSampleProvider.vcxproj.filters create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/async.h create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/eventlogmsgs.mc create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/install-sampleprovider.cmd create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/readme.txt create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/resource.h create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/sampleprovider.cpp create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/sampleprovider.h create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/sampleprovider.rgs create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/setup.txt create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/stdafx.cpp create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/stdafx.h create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/uninstall-sampleprovider.cmd create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/utility.cpp create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/utility.h create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vsssampleprovider.cpp create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vsssampleprovider.def create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vsssampleprovider.idl create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vsssampleprovider.rc create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vsssampleprovider.rgs create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vsssampleprovider.sln create mode 100644 Samples/VolumeShadowCopyServiceProvider/cpp/vstorinterface.h create mode 100644 Samples/VolumeShadowCopyServiceWriter/README.md create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/SampleWriter.sln create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/SampleWriter.vcxproj create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/SampleWriter.vcxproj.filters create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/main.cpp create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/main.h create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/stdafx.h create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/swriter.cpp create mode 100644 Samples/VolumeShadowCopyServiceWriter/cpp/swriter.h create mode 100644 Samples/WebSecurityCenter/README.md create mode 100644 Samples/WebSecurityCenter/cpp/WscApiSample.cpp create mode 100644 Samples/WebSecurityCenter/cpp/WscApiSample.sln create mode 100644 Samples/WebSecurityCenter/cpp/WscApiSample.vcxproj create mode 100644 Samples/WebSecurityCenter/cpp/WscApiSample.vcxproj.filters create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/README.md create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/cpp/AsmxCustomProxyClient.cpp create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/cpp/AsmxPublicServiceSampleWithCustomProxy.sln create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/cpp/AsmxPublicServiceSampleWithCustomProxy.vcxproj create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/cpp/AsmxPublicServiceSampleWithCustomProxy.vcxproj.filters create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/cpp/terraservice-usa.com.wsdl create mode 100644 Samples/WebServices/AsmxPublicServiceWithCustomProxy/readme.txt create mode 100644 Samples/WebServices/AsyncAdd3Explicit/README.md create mode 100644 Samples/WebServices/AsyncAdd3Explicit/cpp/AsyncAdd3Explicit.cpp create mode 100644 Samples/WebServices/AsyncAdd3Explicit/cpp/AsyncAdd3Explicit.sln create mode 100644 Samples/WebServices/AsyncAdd3Explicit/cpp/AsyncAdd3Explicit.vcxproj create mode 100644 Samples/WebServices/AsyncAdd3Explicit/cpp/AsyncAdd3Explicit.vcxproj.filters create mode 100644 Samples/WebServices/AsyncAdd3Explicit/readme.txt create mode 100644 Samples/WebServices/AsyncAdd3Implicit/README.md create mode 100644 Samples/WebServices/AsyncAdd3Implicit/cpp/AsyncAdd3Implicit.cpp create mode 100644 Samples/WebServices/AsyncAdd3Implicit/cpp/AsyncAdd3Implicit.sln create mode 100644 Samples/WebServices/AsyncAdd3Implicit/cpp/AsyncAdd3Implicit.vcxproj create mode 100644 Samples/WebServices/AsyncAdd3Implicit/cpp/AsyncAdd3Implicit.vcxproj.filters create mode 100644 Samples/WebServices/AsyncAdd3Implicit/readme.txt create mode 100644 Samples/WebServices/AsyncModel/README.md create mode 100644 Samples/WebServices/AsyncModel/cpp/AsyncModel.cpp create mode 100644 Samples/WebServices/AsyncModel/cpp/AsyncModel.sln create mode 100644 Samples/WebServices/AsyncModel/cpp/AsyncModel.vcxproj create mode 100644 Samples/WebServices/AsyncModel/cpp/AsyncModel.vcxproj.filters create mode 100644 Samples/WebServices/AsyncModel/readme.txt create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/README.md create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/cpp/AsyncStreamingTcpClient.cpp create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/cpp/AsyncStreamingTcpClient.sln create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/cpp/AsyncStreamingTcpClient.vcxproj create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/cpp/AsyncStreamingTcpClient.vcxproj.filters create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/AsyncStreamingTcpClient/readme.txt create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/README.md create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/cpp/AsyncStreamingTcpServer.cpp create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/cpp/AsyncStreamingTcpServer.sln create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/cpp/AsyncStreamingTcpServer.vcxproj create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/cpp/AsyncStreamingTcpServer.vcxproj.filters create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/AsyncStreamingTcpServer/readme.txt create mode 100644 Samples/WebServices/CallAbandon/README.md create mode 100644 Samples/WebServices/CallAbandon/cpp/AbandonCallClient.cpp create mode 100644 Samples/WebServices/CallAbandon/cpp/BlockUnBlockService.wsdl create mode 100644 Samples/WebServices/CallAbandon/cpp/CallAbandon.sln create mode 100644 Samples/WebServices/CallAbandon/cpp/CallAbandon.vcxproj create mode 100644 Samples/WebServices/CallAbandon/cpp/CallAbandon.vcxproj.filters create mode 100644 Samples/WebServices/CallAbandon/readme.txt create mode 100644 Samples/WebServices/CancellingService/README.md create mode 100644 Samples/WebServices/CancellingService/cpp/BlockUnBlockService.wsdl create mode 100644 Samples/WebServices/CancellingService/cpp/CancellingService.cpp create mode 100644 Samples/WebServices/CancellingService/cpp/CancellingService.sln create mode 100644 Samples/WebServices/CancellingService/cpp/CancellingService.vcxproj create mode 100644 Samples/WebServices/CancellingService/cpp/CancellingService.vcxproj.filters create mode 100644 Samples/WebServices/CancellingService/readme.txt create mode 100644 Samples/WebServices/CustomHeader/README.md create mode 100644 Samples/WebServices/CustomHeader/cpp/CustomHeader.cpp create mode 100644 Samples/WebServices/CustomHeader/cpp/CustomHeader.sln create mode 100644 Samples/WebServices/CustomHeader/cpp/CustomHeader.vcxproj create mode 100644 Samples/WebServices/CustomHeader/cpp/CustomHeader.vcxproj.filters create mode 100644 Samples/WebServices/CustomHeader/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/CustomHeader/readme.txt create mode 100644 Samples/WebServices/DerivedType/README.md create mode 100644 Samples/WebServices/DerivedType/cpp/DerivedType.cpp create mode 100644 Samples/WebServices/DerivedType/cpp/DerivedType.sln create mode 100644 Samples/WebServices/DerivedType/cpp/DerivedType.vcxproj create mode 100644 Samples/WebServices/DerivedType/cpp/DerivedType.vcxproj.filters create mode 100644 Samples/WebServices/DerivedType/cpp/DerivedType.xsd create mode 100644 Samples/WebServices/DerivedType/readme.txt create mode 100644 Samples/WebServices/FileRepService/README.md create mode 100644 Samples/WebServices/FileRepService/cpp/CChannelManager.cpp create mode 100644 Samples/WebServices/FileRepService/cpp/CFileRep.cpp create mode 100644 Samples/WebServices/FileRepService/cpp/CFileRepClient.cpp create mode 100644 Samples/WebServices/FileRepService/cpp/CFileRepServer.cpp create mode 100644 Samples/WebServices/FileRepService/cpp/CRequest.cpp create mode 100644 Samples/WebServices/FileRepService/cpp/FileRep.mc create mode 100644 Samples/WebServices/FileRepService/cpp/FileRep.rc create mode 100644 Samples/WebServices/FileRepService/cpp/FileRepService.sln create mode 100644 Samples/WebServices/FileRepService/cpp/FileRepService.vcxproj create mode 100644 Samples/WebServices/FileRepService/cpp/FileRepService.vcxproj.filters create mode 100644 Samples/WebServices/FileRepService/cpp/Service.cpp create mode 100644 Samples/WebServices/FileRepService/cpp/Service.h create mode 100644 Samples/WebServices/FileRepService/cpp/common.h create mode 100644 Samples/WebServices/FileRepService/readme.txt create mode 100644 Samples/WebServices/FileRepTool/README.md create mode 100644 Samples/WebServices/FileRepTool/cpp/FileRepTool.sln create mode 100644 Samples/WebServices/FileRepTool/cpp/FileRepTool.vcxproj create mode 100644 Samples/WebServices/FileRepTool/cpp/FileRepTool.vcxproj.filters create mode 100644 Samples/WebServices/FileRepTool/cpp/Tool.cpp create mode 100644 Samples/WebServices/FileRepTool/cpp/common.h create mode 100644 Samples/WebServices/FileRepTool/readme.txt create mode 100644 Samples/WebServices/ForwardMessage/README.md create mode 100644 Samples/WebServices/ForwardMessage/cpp/ForwardMessage.cpp create mode 100644 Samples/WebServices/ForwardMessage/cpp/ForwardMessage.sln create mode 100644 Samples/WebServices/ForwardMessage/cpp/ForwardMessage.vcxproj create mode 100644 Samples/WebServices/ForwardMessage/cpp/ForwardMessage.vcxproj.filters create mode 100644 Samples/WebServices/ForwardMessage/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/ForwardMessage/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorClient/cpp/HttpCalculatorClient.cpp create mode 100644 Samples/WebServices/HttpCalculatorClient/cpp/HttpCalculatorClient.sln create mode 100644 Samples/WebServices/HttpCalculatorClient/cpp/HttpCalculatorClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorClient/cpp/HttpCalculatorClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorService/README.md create mode 100644 Samples/WebServices/HttpCalculatorService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorService/cpp/HttpCalculatorService.cpp create mode 100644 Samples/WebServices/HttpCalculatorService/cpp/HttpCalculatorService.sln create mode 100644 Samples/WebServices/HttpCalculatorService/cpp/HttpCalculatorService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorService/cpp/HttpCalculatorService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/cpp/HttpCalculatorWithBasicOverSslClient.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/cpp/HttpCalculatorWithBasicOverSslClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/cpp/HttpCalculatorWithBasicOverSslClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/cpp/HttpCalculatorWithBasicOverSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/cpp/HttpCalculatorWithBasicOverSslService.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/cpp/HttpCalculatorWithBasicOverSslService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/cpp/HttpCalculatorWithBasicOverSslService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/cpp/HttpCalculatorWithBasicOverSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithBasicOverSslService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/EncodedChannel.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/EncodedChannel.h create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/HttpCalculatorWithEncodedChannelClient.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/HttpCalculatorWithEncodedChannelClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/HttpCalculatorWithEncodedChannelClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/cpp/HttpCalculatorWithEncodedChannelClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/EncodedChannel.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/EncodedChannel.h create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/HttpCalculatorWithEncodedChannelService.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/HttpCalculatorWithEncodedChannelService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/HttpCalculatorWithEncodedChannelService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/cpp/HttpCalculatorWithEncodedChannelService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithEncodedChannelService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/cpp/CalculatorClientKerberosOverSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/cpp/HttpCalculatorWithKerberosOverSslClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/cpp/HttpCalculatorWithKerberosOverSslClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/cpp/HttpCalculatorWithKerberosOverSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/cpp/CalculatorServiceKerberosOverSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/cpp/HttpCalculatorWithKerberosOverSslService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/cpp/HttpCalculatorWithKerberosOverSslService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/cpp/HttpCalculatorWithKerberosOverSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithKerberosOverSslService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/HttpCalculatorWithLayeredChannelClient.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/HttpCalculatorWithLayeredChannelClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/HttpCalculatorWithLayeredChannelClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/HttpCalculatorWithLayeredChannelClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/LayeredChannel.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/cpp/LayeredChannel.h create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/HttpCalculatorWithLayeredChannelService.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/HttpCalculatorWithLayeredChannelService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/HttpCalculatorWithLayeredChannelService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/HttpCalculatorWithLayeredChannelService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/LayeredChannel.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/LayeredChannel.h create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/LayeredListener.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/cpp/LayeredListener.h create mode 100644 Samples/WebServices/HttpCalculatorWithLayeredChannelService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/cpp/HttpCalculatorClientWithSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/cpp/HttpCalculatorWithSslClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/cpp/HttpCalculatorWithSslClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/cpp/HttpCalculatorWithSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithSslClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/cpp/CalculatorServiceWithPolicy.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/cpp/HttpCalculatorWithSslPolicyClient.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/cpp/HttpCalculatorWithSslPolicyClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/cpp/HttpCalculatorWithSslPolicyClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/cpp/HttpCalculatorWithSslPolicyClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/cpp/CalculatorServiceWithPolicy.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/cpp/HttpCalculatorWithSslPolicyService.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/cpp/HttpCalculatorWithSslPolicyService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/cpp/HttpCalculatorWithSslPolicyService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/cpp/HttpCalculatorWithSslPolicyService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithSslPolicyService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/cpp/HttpCalculatorServiceWithSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/cpp/HttpCalculatorWithSslService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/cpp/HttpCalculatorWithSslService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/cpp/HttpCalculatorWithSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithSslService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/cpp/CalculatorServiceUserNameOverSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/cpp/HttpCalculatorWithUserNameOverSslService.sln create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/cpp/HttpCalculatorWithUserNameOverSslService.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/cpp/HttpCalculatorWithUserNameOverSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithUserNameOverSslService/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/cpp/CalculatorClientUserNameOverSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/cpp/HttpCalculatorWithUsernameOverSslClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/cpp/HttpCalculatorWithUsernameOverSslClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/cpp/HttpCalculatorWithUsernameOverSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameOverSslClient/readme.txt create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/README.md create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/cpp/CalculatorClientUserNameXmlTokenOverSsl.cpp create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/cpp/CalculatorService.wsdl create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/cpp/HttpCalculatorWithUsernameXmlTokenOverSslClient.sln create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/cpp/HttpCalculatorWithUsernameXmlTokenOverSslClient.vcxproj create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/cpp/HttpCalculatorWithUsernameXmlTokenOverSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCalculatorWithUsernameXmlTokenOverSslClient/readme.txt create mode 100644 Samples/WebServices/HttpClient/README.md create mode 100644 Samples/WebServices/HttpClient/cpp/HttpClient.cpp create mode 100644 Samples/WebServices/HttpClient/cpp/HttpClient.sln create mode 100644 Samples/WebServices/HttpClient/cpp/HttpClient.vcxproj create mode 100644 Samples/WebServices/HttpClient/cpp/HttpClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpClient/readme.txt create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/README.md create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/cpp/HttpClientWithKerberosOverSsl.cpp create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/cpp/HttpClientWithKerberosOverSsl.sln create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/cpp/HttpClientWithKerberosOverSsl.vcxproj create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/cpp/HttpClientWithKerberosOverSsl.vcxproj.filters create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpClientWithKerberosOverSsl/readme.txt create mode 100644 Samples/WebServices/HttpClientWithSsl/README.md create mode 100644 Samples/WebServices/HttpClientWithSsl/cpp/HttpClientWithSsl.cpp create mode 100644 Samples/WebServices/HttpClientWithSsl/cpp/HttpClientWithSsl.sln create mode 100644 Samples/WebServices/HttpClientWithSsl/cpp/HttpClientWithSsl.vcxproj create mode 100644 Samples/WebServices/HttpClientWithSsl/cpp/HttpClientWithSsl.vcxproj.filters create mode 100644 Samples/WebServices/HttpClientWithSsl/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpClientWithSsl/readme.txt create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/README.md create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/cpp/HttpClientWithSslAndClientCert.cpp create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/cpp/HttpClientWithSslAndClientCert.sln create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/cpp/HttpClientWithSslAndClientCert.vcxproj create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/cpp/HttpClientWithSslAndClientCert.vcxproj.filters create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpClientWithSslAndClientCert/readme.txt create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/README.md create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/cpp/HttpClientWithUsernameOverSsl.cpp create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/cpp/HttpClientWithUsernameOverSsl.sln create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/cpp/HttpClientWithUsernameOverSsl.vcxproj create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/cpp/HttpClientWithUsernameOverSsl.vcxproj.filters create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpClientWithUsernameOverSsl/readme.txt create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/README.md create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/cpp/HttpCustomHeaderClient.cpp create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/cpp/HttpCustomHeaderPurchaseOrderClient.sln create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/cpp/HttpCustomHeaderPurchaseOrderClient.vcxproj create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/cpp/HttpCustomHeaderPurchaseOrderClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/cpp/OrderSessionHeader.xsd create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderClient/readme.txt create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/README.md create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/cpp/HttpCustomHeaderPurchaseOrderService.sln create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/cpp/HttpCustomHeaderPurchaseOrderService.vcxproj create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/cpp/HttpCustomHeaderPurchaseOrderService.vcxproj.filters create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/cpp/HttpCustomHeaderService.cpp create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/cpp/OrderSessionHeader.xsd create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpCustomHeaderPurchaseOrderService/readme.txt create mode 100644 Samples/WebServices/HttpGetService/README.md create mode 100644 Samples/WebServices/HttpGetService/cpp/HttpGetService.cpp create mode 100644 Samples/WebServices/HttpGetService/cpp/HttpGetService.sln create mode 100644 Samples/WebServices/HttpGetService/cpp/HttpGetService.vcxproj create mode 100644 Samples/WebServices/HttpGetService/cpp/HttpGetService.vcxproj.filters create mode 100644 Samples/WebServices/HttpGetService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpGetService/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/cpp/HttpPurchaseOrderClient.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/cpp/HttpPurchaseOrderClient.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/cpp/HttpPurchaseOrderClient.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/cpp/HttpPurchaseOrderClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderClient/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderService/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderService/cpp/HttpPurchaseOrderService.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderService/cpp/HttpPurchaseOrderService.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderService/cpp/HttpPurchaseOrderService.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderService/cpp/HttpPurchaseOrderService.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderService/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/cpp/HttpPurchaseOrderWithKerberosOverSslClient.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/cpp/HttpPurchaseOrderWithKerberosOverSslClient.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/cpp/HttpPurchaseOrderWithKerberosOverSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/cpp/PurchaseOrderClientKerberosOverSsl.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslClient/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/cpp/HttpPurchaseOrderWithKerberosOverSslService.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/cpp/HttpPurchaseOrderWithKerberosOverSslService.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/cpp/HttpPurchaseOrderWithKerberosOverSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/cpp/PurchaseOrderServiceKerberosOverSsl.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderWithKerberosOverSslService/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/cpp/HttpPurchaseOrderClientWithSsl.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/cpp/HttpPurchaseOrderWithSslClient.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/cpp/HttpPurchaseOrderWithSslClient.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/cpp/HttpPurchaseOrderWithSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslClient/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/cpp/HttpPurchaseOrderServiceWithSsl.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/cpp/HttpPurchaseOrderWithSslService.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/cpp/HttpPurchaseOrderWithSslService.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/cpp/HttpPurchaseOrderWithSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderWithSslService/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/cpp/HttpPurchaseOrderWithUserNameOverSslService.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/cpp/HttpPurchaseOrderWithUserNameOverSslService.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/cpp/HttpPurchaseOrderWithUserNameOverSslService.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/cpp/PurchaseOrderServiceUserNameOverSsl.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUserNameOverSslService/readme.txt create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/README.md create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/cpp/HttpPurchaseOrderWithUsernameOverSslClient.sln create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/cpp/HttpPurchaseOrderWithUsernameOverSslClient.vcxproj create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/cpp/HttpPurchaseOrderWithUsernameOverSslClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/cpp/PurchaseOrderClientUserNameOverSsl.cpp create mode 100644 Samples/WebServices/HttpPurchaseOrderWithUsernameOverSslClient/readme.txt create mode 100644 Samples/WebServices/HttpRawClient/README.md create mode 100644 Samples/WebServices/HttpRawClient/cpp/HttpRawClient.cpp create mode 100644 Samples/WebServices/HttpRawClient/cpp/HttpRawClient.sln create mode 100644 Samples/WebServices/HttpRawClient/cpp/HttpRawClient.vcxproj create mode 100644 Samples/WebServices/HttpRawClient/cpp/HttpRawClient.vcxproj.filters create mode 100644 Samples/WebServices/HttpRawClient/readme.txt create mode 100644 Samples/WebServices/HttpRawService/README.md create mode 100644 Samples/WebServices/HttpRawService/cpp/HttpRawService.cpp create mode 100644 Samples/WebServices/HttpRawService/cpp/HttpRawService.sln create mode 100644 Samples/WebServices/HttpRawService/cpp/HttpRawService.vcxproj create mode 100644 Samples/WebServices/HttpRawService/cpp/HttpRawService.vcxproj.filters create mode 100644 Samples/WebServices/HttpRawService/readme.txt create mode 100644 Samples/WebServices/HttpServer/README.md create mode 100644 Samples/WebServices/HttpServer/cpp/HttpServer.cpp create mode 100644 Samples/WebServices/HttpServer/cpp/HttpServer.sln create mode 100644 Samples/WebServices/HttpServer/cpp/HttpServer.vcxproj create mode 100644 Samples/WebServices/HttpServer/cpp/HttpServer.vcxproj.filters create mode 100644 Samples/WebServices/HttpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpServer/readme.txt create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/README.md create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/cpp/HttpServerWithKerberosOverSsl.cpp create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/cpp/HttpServerWithKerberosOverSsl.sln create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/cpp/HttpServerWithKerberosOverSsl.vcxproj create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/cpp/HttpServerWithKerberosOverSsl.vcxproj.filters create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpServerWithKerberosOverSsl/readme.txt create mode 100644 Samples/WebServices/HttpServerWithSsl/README.md create mode 100644 Samples/WebServices/HttpServerWithSsl/cpp/HttpServerWithSsl.cpp create mode 100644 Samples/WebServices/HttpServerWithSsl/cpp/HttpServerWithSsl.sln create mode 100644 Samples/WebServices/HttpServerWithSsl/cpp/HttpServerWithSsl.vcxproj create mode 100644 Samples/WebServices/HttpServerWithSsl/cpp/HttpServerWithSsl.vcxproj.filters create mode 100644 Samples/WebServices/HttpServerWithSsl/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpServerWithSsl/readme.txt create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/README.md create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/cpp/HttpServerWithSslAndClientCert.cpp create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/cpp/HttpServerWithSslAndClientCert.sln create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/cpp/HttpServerWithSslAndClientCert.vcxproj create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/cpp/HttpServerWithSslAndClientCert.vcxproj.filters create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpServerWithSslAndClientCert/readme.txt create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/README.md create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/cpp/HttpServerWithUsernameOverSsl.cpp create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/cpp/HttpServerWithUsernameOverSsl.sln create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/cpp/HttpServerWithUsernameOverSsl.vcxproj create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/cpp/HttpServerWithUsernameOverSsl.vcxproj.filters create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/HttpServerWithUsernameOverSsl/readme.txt create mode 100644 Samples/WebServices/InsertElement/README.md create mode 100644 Samples/WebServices/InsertElement/cpp/InsertElement.cpp create mode 100644 Samples/WebServices/InsertElement/cpp/InsertElement.sln create mode 100644 Samples/WebServices/InsertElement/cpp/InsertElement.vcxproj create mode 100644 Samples/WebServices/InsertElement/cpp/InsertElement.vcxproj.filters create mode 100644 Samples/WebServices/InsertElement/readme.txt create mode 100644 Samples/WebServices/MessageEncoding/README.md create mode 100644 Samples/WebServices/MessageEncoding/cpp/MessageEncoding.cpp create mode 100644 Samples/WebServices/MessageEncoding/cpp/MessageEncoding.sln create mode 100644 Samples/WebServices/MessageEncoding/cpp/MessageEncoding.vcxproj create mode 100644 Samples/WebServices/MessageEncoding/cpp/MessageEncoding.vcxproj.filters create mode 100644 Samples/WebServices/MessageEncoding/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/MessageEncoding/readme.txt create mode 100644 Samples/WebServices/MetadataImportWithIssuedTokenOverSslExample/README.md create mode 100644 Samples/WebServices/MetadataImportWithIssuedTokenOverSslExample/cpp/MetadataImportWithIssuedTokenOverSslExample.cpp create mode 100644 Samples/WebServices/MetadataImportWithIssuedTokenOverSslExample/cpp/MetadataImportWithIssuedTokenOverSslExample.sln create mode 100644 Samples/WebServices/MetadataImportWithIssuedTokenOverSslExample/cpp/MetadataImportWithIssuedTokenOverSslExample.vcxproj create mode 100644 Samples/WebServices/MetadataImportWithIssuedTokenOverSslExample/cpp/MetadataImportWithIssuedTokenOverSslExample.vcxproj.filters create mode 100644 Samples/WebServices/MetadataImportWithIssuedTokenOverSslExample/readme.txt create mode 100644 Samples/WebServices/MetadataImportWithUsernameOverSslExample/README.md create mode 100644 Samples/WebServices/MetadataImportWithUsernameOverSslExample/cpp/MetadataImportWithUsernameOverSslExample.cpp create mode 100644 Samples/WebServices/MetadataImportWithUsernameOverSslExample/cpp/MetadataImportWithUsernameOverSslExample.sln create mode 100644 Samples/WebServices/MetadataImportWithUsernameOverSslExample/cpp/MetadataImportWithUsernameOverSslExample.vcxproj create mode 100644 Samples/WebServices/MetadataImportWithUsernameOverSslExample/cpp/MetadataImportWithUsernameOverSslExample.vcxproj.filters create mode 100644 Samples/WebServices/MetadataImportWithUsernameOverSslExample/readme.txt create mode 100644 Samples/WebServices/MetadataImportWithX509OverSslExample/README.md create mode 100644 Samples/WebServices/MetadataImportWithX509OverSslExample/cpp/MetadataImportWithX509OverSslExample.cpp create mode 100644 Samples/WebServices/MetadataImportWithX509OverSslExample/cpp/MetadataImportWithX509OverSslExample.sln create mode 100644 Samples/WebServices/MetadataImportWithX509OverSslExample/cpp/MetadataImportWithX509OverSslExample.vcxproj create mode 100644 Samples/WebServices/MetadataImportWithX509OverSslExample/cpp/MetadataImportWithX509OverSslExample.vcxproj.filters create mode 100644 Samples/WebServices/MetadataImportWithX509OverSslExample/readme.txt create mode 100644 Samples/WebServices/MulticastUdpClient/README.md create mode 100644 Samples/WebServices/MulticastUdpClient/cpp/MulticastUdpClient.cpp create mode 100644 Samples/WebServices/MulticastUdpClient/cpp/MulticastUdpClient.sln create mode 100644 Samples/WebServices/MulticastUdpClient/cpp/MulticastUdpClient.vcxproj create mode 100644 Samples/WebServices/MulticastUdpClient/cpp/MulticastUdpClient.vcxproj.filters create mode 100644 Samples/WebServices/MulticastUdpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/MulticastUdpClient/readme.txt create mode 100644 Samples/WebServices/MulticastUdpClient6/README.md create mode 100644 Samples/WebServices/MulticastUdpClient6/cpp/MulticastUdpClient6.cpp create mode 100644 Samples/WebServices/MulticastUdpClient6/cpp/MulticastUdpClient6.sln create mode 100644 Samples/WebServices/MulticastUdpClient6/cpp/MulticastUdpClient6.vcxproj create mode 100644 Samples/WebServices/MulticastUdpClient6/cpp/MulticastUdpClient6.vcxproj.filters create mode 100644 Samples/WebServices/MulticastUdpClient6/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/MulticastUdpClient6/readme.txt create mode 100644 Samples/WebServices/MulticastUdpServer/README.md create mode 100644 Samples/WebServices/MulticastUdpServer/cpp/MulticastUdpServer.cpp create mode 100644 Samples/WebServices/MulticastUdpServer/cpp/MulticastUdpServer.sln create mode 100644 Samples/WebServices/MulticastUdpServer/cpp/MulticastUdpServer.vcxproj create mode 100644 Samples/WebServices/MulticastUdpServer/cpp/MulticastUdpServer.vcxproj.filters create mode 100644 Samples/WebServices/MulticastUdpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/MulticastUdpServer/readme.txt create mode 100644 Samples/WebServices/MulticastUdpServer6/README.md create mode 100644 Samples/WebServices/MulticastUdpServer6/cpp/MulticastUdpServer6.cpp create mode 100644 Samples/WebServices/MulticastUdpServer6/cpp/MulticastUdpServer6.sln create mode 100644 Samples/WebServices/MulticastUdpServer6/cpp/MulticastUdpServer6.vcxproj create mode 100644 Samples/WebServices/MulticastUdpServer6/cpp/MulticastUdpServer6.vcxproj.filters create mode 100644 Samples/WebServices/MulticastUdpServer6/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/MulticastUdpServer6/readme.txt create mode 100644 Samples/WebServices/NavigateXml/README.md create mode 100644 Samples/WebServices/NavigateXml/cpp/NavigateXml.cpp create mode 100644 Samples/WebServices/NavigateXml/cpp/NavigateXml.sln create mode 100644 Samples/WebServices/NavigateXml/cpp/NavigateXml.vcxproj create mode 100644 Samples/WebServices/NavigateXml/cpp/NavigateXml.vcxproj.filters create mode 100644 Samples/WebServices/NavigateXml/readme.txt create mode 100644 Samples/WebServices/OneWayTcpClient/README.md create mode 100644 Samples/WebServices/OneWayTcpClient/cpp/OneWayTcpClient.cpp create mode 100644 Samples/WebServices/OneWayTcpClient/cpp/OneWayTcpClient.sln create mode 100644 Samples/WebServices/OneWayTcpClient/cpp/OneWayTcpClient.vcxproj create mode 100644 Samples/WebServices/OneWayTcpClient/cpp/OneWayTcpClient.vcxproj.filters create mode 100644 Samples/WebServices/OneWayTcpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/OneWayTcpClient/readme.txt create mode 100644 Samples/WebServices/OneWayTcpServer/README.md create mode 100644 Samples/WebServices/OneWayTcpServer/cpp/OneWayTcpServer.cpp create mode 100644 Samples/WebServices/OneWayTcpServer/cpp/OneWayTcpServer.sln create mode 100644 Samples/WebServices/OneWayTcpServer/cpp/OneWayTcpServer.vcxproj create mode 100644 Samples/WebServices/OneWayTcpServer/cpp/OneWayTcpServer.vcxproj.filters create mode 100644 Samples/WebServices/OneWayTcpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/OneWayTcpServer/readme.txt create mode 100644 Samples/WebServices/OneWayUdpClient/README.md create mode 100644 Samples/WebServices/OneWayUdpClient/cpp/OneWayUdpClient.cpp create mode 100644 Samples/WebServices/OneWayUdpClient/cpp/OneWayUdpClient.sln create mode 100644 Samples/WebServices/OneWayUdpClient/cpp/OneWayUdpClient.vcxproj create mode 100644 Samples/WebServices/OneWayUdpClient/cpp/OneWayUdpClient.vcxproj.filters create mode 100644 Samples/WebServices/OneWayUdpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/OneWayUdpClient/readme.txt create mode 100644 Samples/WebServices/OneWayUdpServer/README.md create mode 100644 Samples/WebServices/OneWayUdpServer/cpp/OneWayUdpServer.cpp create mode 100644 Samples/WebServices/OneWayUdpServer/cpp/OneWayUdpServer.sln create mode 100644 Samples/WebServices/OneWayUdpServer/cpp/OneWayUdpServer.vcxproj create mode 100644 Samples/WebServices/OneWayUdpServer/cpp/OneWayUdpServer.vcxproj.filters create mode 100644 Samples/WebServices/OneWayUdpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/OneWayUdpServer/readme.txt create mode 100644 Samples/WebServices/PolicyTemplate/README.md create mode 100644 Samples/WebServices/PolicyTemplate/cpp/PolicyTemplate.sln create mode 100644 Samples/WebServices/PolicyTemplate/cpp/PolicyTemplate.vcxproj create mode 100644 Samples/WebServices/PolicyTemplate/cpp/PolicyTemplate.vcxproj.filters create mode 100644 Samples/WebServices/PolicyTemplate/cpp/policytemplate.cpp create mode 100644 Samples/WebServices/PolicyTemplate/readme.txt create mode 100644 Samples/WebServices/ReadAttribute/README.md create mode 100644 Samples/WebServices/ReadAttribute/cpp/ReadAttribute.cpp create mode 100644 Samples/WebServices/ReadAttribute/cpp/ReadAttribute.sln create mode 100644 Samples/WebServices/ReadAttribute/cpp/ReadAttribute.vcxproj create mode 100644 Samples/WebServices/ReadAttribute/cpp/ReadAttribute.vcxproj.filters create mode 100644 Samples/WebServices/ReadAttribute/readme.txt create mode 100644 Samples/WebServices/ReadWriteArray/README.md create mode 100644 Samples/WebServices/ReadWriteArray/cpp/ReadWriteArray.cpp create mode 100644 Samples/WebServices/ReadWriteArray/cpp/ReadWriteArray.sln create mode 100644 Samples/WebServices/ReadWriteArray/cpp/ReadWriteArray.vcxproj create mode 100644 Samples/WebServices/ReadWriteArray/cpp/ReadWriteArray.vcxproj.filters create mode 100644 Samples/WebServices/ReadWriteArray/readme.txt create mode 100644 Samples/WebServices/ReadWriteBytesXml/README.md create mode 100644 Samples/WebServices/ReadWriteBytesXml/cpp/ReadWriteBytesXml.cpp create mode 100644 Samples/WebServices/ReadWriteBytesXml/cpp/ReadWriteBytesXml.sln create mode 100644 Samples/WebServices/ReadWriteBytesXml/cpp/ReadWriteBytesXml.vcxproj create mode 100644 Samples/WebServices/ReadWriteBytesXml/cpp/ReadWriteBytesXml.vcxproj.filters create mode 100644 Samples/WebServices/ReadWriteBytesXml/readme.txt create mode 100644 Samples/WebServices/ReadWriteRawXml/README.md create mode 100644 Samples/WebServices/ReadWriteRawXml/cpp/ReadWriteRawXml.cpp create mode 100644 Samples/WebServices/ReadWriteRawXml/cpp/ReadWriteRawXml.sln create mode 100644 Samples/WebServices/ReadWriteRawXml/cpp/ReadWriteRawXml.vcxproj create mode 100644 Samples/WebServices/ReadWriteRawXml/cpp/ReadWriteRawXml.vcxproj.filters create mode 100644 Samples/WebServices/ReadWriteRawXml/readme.txt create mode 100644 Samples/WebServices/ReadWriteXml/README.md create mode 100644 Samples/WebServices/ReadWriteXml/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/ReadWriteXml/cpp/ReadWriteXml.cpp create mode 100644 Samples/WebServices/ReadWriteXml/cpp/ReadWriteXml.sln create mode 100644 Samples/WebServices/ReadWriteXml/cpp/ReadWriteXml.vcxproj create mode 100644 Samples/WebServices/ReadWriteXml/cpp/ReadWriteXml.vcxproj.filters create mode 100644 Samples/WebServices/ReadWriteXml/readme.txt create mode 100644 Samples/WebServices/ReadXml/README.md create mode 100644 Samples/WebServices/ReadXml/cpp/ReadXml.cpp create mode 100644 Samples/WebServices/ReadXml/cpp/ReadXml.sln create mode 100644 Samples/WebServices/ReadXml/cpp/ReadXml.vcxproj create mode 100644 Samples/WebServices/ReadXml/cpp/ReadXml.vcxproj.filters create mode 100644 Samples/WebServices/ReadXml/readme.txt create mode 100644 Samples/WebServices/ReadXmlSimple/README.md create mode 100644 Samples/WebServices/ReadXmlSimple/cpp/ReadXmlSimple.cpp create mode 100644 Samples/WebServices/ReadXmlSimple/cpp/ReadXmlSimple.sln create mode 100644 Samples/WebServices/ReadXmlSimple/cpp/ReadXmlSimple.vcxproj create mode 100644 Samples/WebServices/ReadXmlSimple/cpp/ReadXmlSimple.vcxproj.filters create mode 100644 Samples/WebServices/ReadXmlSimple/readme.txt create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/README.md create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/cpp/RequestReplyNamedPipeClient.cpp create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/cpp/RequestReplyNamedPipeClient.sln create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/cpp/RequestReplyNamedPipeClient.vcxproj create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/cpp/RequestReplyNamedPipeClient.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyNamedPipeClient/readme.txt create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/README.md create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeClientWithWindowsTransportSecurity.cpp create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeClientWithWindowsTransportSecurity.sln create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeClientWithWindowsTransportSecurity.vcxproj create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeClientWithWindowsTransportSecurity.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyNamedPipeClientWithWindowsTransportSecurity/readme.txt create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/README.md create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/cpp/RequestReplyNamedPipeServer.cpp create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/cpp/RequestReplyNamedPipeServer.sln create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/cpp/RequestReplyNamedPipeServer.vcxproj create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/cpp/RequestReplyNamedPipeServer.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyNamedPipeServer/readme.txt create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/README.md create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeServerWithWindowsTransportSecurity.cpp create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeServerWithWindowsTransportSecurity.sln create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeServerWithWindowsTransportSecurity.vcxproj create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/cpp/RequestReplyNamedPipeServerWithWindowsTransportSecurity.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyNamedPipeServerWithWindowsTransportSecurity/readme.txt create mode 100644 Samples/WebServices/RequestReplyTcpClient/README.md create mode 100644 Samples/WebServices/RequestReplyTcpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyTcpClient/cpp/RequestReplyTcpClient.cpp create mode 100644 Samples/WebServices/RequestReplyTcpClient/cpp/RequestReplyTcpClient.sln create mode 100644 Samples/WebServices/RequestReplyTcpClient/cpp/RequestReplyTcpClient.vcxproj create mode 100644 Samples/WebServices/RequestReplyTcpClient/cpp/RequestReplyTcpClient.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyTcpClient/readme.txt create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/README.md create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/cpp/RequestReplyTcpClientWithWindowsTransportSecurity.cpp create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/cpp/RequestReplyTcpClientWithWindowsTransportSecurity.sln create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/cpp/RequestReplyTcpClientWithWindowsTransportSecurity.vcxproj create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/cpp/RequestReplyTcpClientWithWindowsTransportSecurity.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyTcpClientWithWindowsTransportSecurity/readme.txt create mode 100644 Samples/WebServices/RequestReplyTcpServer/README.md create mode 100644 Samples/WebServices/RequestReplyTcpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyTcpServer/cpp/RequestReplyTcpServer.cpp create mode 100644 Samples/WebServices/RequestReplyTcpServer/cpp/RequestReplyTcpServer.sln create mode 100644 Samples/WebServices/RequestReplyTcpServer/cpp/RequestReplyTcpServer.vcxproj create mode 100644 Samples/WebServices/RequestReplyTcpServer/cpp/RequestReplyTcpServer.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyTcpServer/readme.txt create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/README.md create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/cpp/RequestReplyTcpServerWithWindowsTransportSecurity.cpp create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/cpp/RequestReplyTcpServerWithWindowsTransportSecurity.sln create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/cpp/RequestReplyTcpServerWithWindowsTransportSecurity.vcxproj create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/cpp/RequestReplyTcpServerWithWindowsTransportSecurity.vcxproj.filters create mode 100644 Samples/WebServices/RequestReplyTcpServerWithWindowsTransportSecurity/readme.txt create mode 100644 Samples/WebServices/ServiceCancelClient/README.md create mode 100644 Samples/WebServices/ServiceCancelClient/cpp/BlockUnBlockService.wsdl create mode 100644 Samples/WebServices/ServiceCancelClient/cpp/ServiceCancel.cpp create mode 100644 Samples/WebServices/ServiceCancelClient/cpp/ServiceCancelClient.sln create mode 100644 Samples/WebServices/ServiceCancelClient/cpp/ServiceCancelClient.vcxproj create mode 100644 Samples/WebServices/ServiceCancelClient/cpp/ServiceCancelClient.vcxproj.filters create mode 100644 Samples/WebServices/ServiceCancelClient/readme.txt create mode 100644 Samples/WebServices/SessionfullCalculatorClient/README.md create mode 100644 Samples/WebServices/SessionfullCalculatorClient/cpp/SessionBasedCalculatorService.wsdl create mode 100644 Samples/WebServices/SessionfullCalculatorClient/cpp/SessionfullCalculatorClient.cpp create mode 100644 Samples/WebServices/SessionfullCalculatorClient/cpp/SessionfullCalculatorClient.sln create mode 100644 Samples/WebServices/SessionfullCalculatorClient/cpp/SessionfullCalculatorClient.vcxproj create mode 100644 Samples/WebServices/SessionfullCalculatorClient/cpp/SessionfullCalculatorClient.vcxproj.filters create mode 100644 Samples/WebServices/SessionfullCalculatorClient/readme.txt create mode 100644 Samples/WebServices/SessionfullCalculatorService/README.md create mode 100644 Samples/WebServices/SessionfullCalculatorService/cpp/SessionBasedCalculatorService.wsdl create mode 100644 Samples/WebServices/SessionfullCalculatorService/cpp/SessionfullCalculatorService.cpp create mode 100644 Samples/WebServices/SessionfullCalculatorService/cpp/SessionfullCalculatorService.sln create mode 100644 Samples/WebServices/SessionfullCalculatorService/cpp/SessionfullCalculatorService.vcxproj create mode 100644 Samples/WebServices/SessionfullCalculatorService/cpp/SessionfullCalculatorService.vcxproj.filters create mode 100644 Samples/WebServices/SessionfullCalculatorService/readme.txt create mode 100644 Samples/WebServices/StreamingHttpClient/README.md create mode 100644 Samples/WebServices/StreamingHttpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/StreamingHttpClient/cpp/StreamingHttpClient.cpp create mode 100644 Samples/WebServices/StreamingHttpClient/cpp/StreamingHttpClient.sln create mode 100644 Samples/WebServices/StreamingHttpClient/cpp/StreamingHttpClient.vcxproj create mode 100644 Samples/WebServices/StreamingHttpClient/cpp/StreamingHttpClient.vcxproj.filters create mode 100644 Samples/WebServices/StreamingHttpClient/readme.txt create mode 100644 Samples/WebServices/StreamingHttpServer/README.md create mode 100644 Samples/WebServices/StreamingHttpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/StreamingHttpServer/cpp/StreamingHttpServer.cpp create mode 100644 Samples/WebServices/StreamingHttpServer/cpp/StreamingHttpServer.sln create mode 100644 Samples/WebServices/StreamingHttpServer/cpp/StreamingHttpServer.vcxproj create mode 100644 Samples/WebServices/StreamingHttpServer/cpp/StreamingHttpServer.vcxproj.filters create mode 100644 Samples/WebServices/StreamingHttpServer/readme.txt create mode 100644 Samples/WebServices/StreamingNamedPipeClient/README.md create mode 100644 Samples/WebServices/StreamingNamedPipeClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/StreamingNamedPipeClient/cpp/StreamingNamedPipeClient.cpp create mode 100644 Samples/WebServices/StreamingNamedPipeClient/cpp/StreamingNamedPipeClient.sln create mode 100644 Samples/WebServices/StreamingNamedPipeClient/cpp/StreamingNamedPipeClient.vcxproj create mode 100644 Samples/WebServices/StreamingNamedPipeClient/cpp/StreamingNamedPipeClient.vcxproj.filters create mode 100644 Samples/WebServices/StreamingNamedPipeClient/readme.txt create mode 100644 Samples/WebServices/StreamingNamedPipeServer/README.md create mode 100644 Samples/WebServices/StreamingNamedPipeServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/StreamingNamedPipeServer/cpp/StreamingNamedPipeServer.cpp create mode 100644 Samples/WebServices/StreamingNamedPipeServer/cpp/StreamingNamedPipeServer.sln create mode 100644 Samples/WebServices/StreamingNamedPipeServer/cpp/StreamingNamedPipeServer.vcxproj create mode 100644 Samples/WebServices/StreamingNamedPipeServer/cpp/StreamingNamedPipeServer.vcxproj.filters create mode 100644 Samples/WebServices/StreamingNamedPipeServer/readme.txt create mode 100644 Samples/WebServices/StreamingTcpClient/README.md create mode 100644 Samples/WebServices/StreamingTcpClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/StreamingTcpClient/cpp/StreamingTcpClient.cpp create mode 100644 Samples/WebServices/StreamingTcpClient/cpp/StreamingTcpClient.sln create mode 100644 Samples/WebServices/StreamingTcpClient/cpp/StreamingTcpClient.vcxproj create mode 100644 Samples/WebServices/StreamingTcpClient/cpp/StreamingTcpClient.vcxproj.filters create mode 100644 Samples/WebServices/StreamingTcpClient/readme.txt create mode 100644 Samples/WebServices/StreamingTcpServer/README.md create mode 100644 Samples/WebServices/StreamingTcpServer/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/StreamingTcpServer/cpp/StreamingTcpServer.cpp create mode 100644 Samples/WebServices/StreamingTcpServer/cpp/StreamingTcpServer.sln create mode 100644 Samples/WebServices/StreamingTcpServer/cpp/StreamingTcpServer.vcxproj create mode 100644 Samples/WebServices/StreamingTcpServer/cpp/StreamingTcpServer.vcxproj.filters create mode 100644 Samples/WebServices/StreamingTcpServer/readme.txt create mode 100644 Samples/WebServices/UnTypedClient/README.md create mode 100644 Samples/WebServices/UnTypedClient/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/UnTypedClient/cpp/UnTypedClient.cpp create mode 100644 Samples/WebServices/UnTypedClient/cpp/UnTypedClient.sln create mode 100644 Samples/WebServices/UnTypedClient/cpp/UnTypedClient.vcxproj create mode 100644 Samples/WebServices/UnTypedClient/cpp/UnTypedClient.vcxproj.filters create mode 100644 Samples/WebServices/UnTypedClient/readme.txt create mode 100644 Samples/WebServices/UnTypedService/README.md create mode 100644 Samples/WebServices/UnTypedService/cpp/PurchaseOrder.wsdl create mode 100644 Samples/WebServices/UnTypedService/cpp/UnTypedService.cpp create mode 100644 Samples/WebServices/UnTypedService/cpp/UnTypedService.sln create mode 100644 Samples/WebServices/UnTypedService/cpp/UnTypedService.vcxproj create mode 100644 Samples/WebServices/UnTypedService/cpp/UnTypedService.vcxproj.filters create mode 100644 Samples/WebServices/UnTypedService/readme.txt create mode 100644 Samples/WebServices/WcfPublicServiceClient/README.md create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/WcfPublicServiceClient.cpp create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/WcfPublicServiceClient.sln create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/WcfPublicServiceClient.vcxproj create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/WcfPublicServiceClient.vcxproj.filters create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/schemas.microsoft.com.2003.10.Serialization.xsd create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/tempuri.org.wsdl create mode 100644 Samples/WebServices/WcfPublicServiceClient/cpp/tempuri.org.xsd create mode 100644 Samples/WebServices/WcfPublicServiceClient/readme.txt create mode 100644 Samples/WebServices/WriteXmlSimple/README.md create mode 100644 Samples/WebServices/WriteXmlSimple/cpp/WriteXmlSimple.cpp create mode 100644 Samples/WebServices/WriteXmlSimple/cpp/WriteXmlSimple.sln create mode 100644 Samples/WebServices/WriteXmlSimple/cpp/WriteXmlSimple.vcxproj create mode 100644 Samples/WebServices/WriteXmlSimple/cpp/WriteXmlSimple.vcxproj.filters create mode 100644 Samples/WebServices/WriteXmlSimple/readme.txt create mode 100644 Samples/WebServices/XmlBuffer/README.md create mode 100644 Samples/WebServices/XmlBuffer/cpp/XmlBuffer.cpp create mode 100644 Samples/WebServices/XmlBuffer/cpp/XmlBuffer.sln create mode 100644 Samples/WebServices/XmlBuffer/cpp/XmlBuffer.vcxproj create mode 100644 Samples/WebServices/XmlBuffer/cpp/XmlBuffer.vcxproj.filters create mode 100644 Samples/WebServices/XmlBuffer/readme.txt create mode 100644 Samples/WebServices/XmlDictionary/README.md create mode 100644 Samples/WebServices/XmlDictionary/cpp/XmlDictionary.cpp create mode 100644 Samples/WebServices/XmlDictionary/cpp/XmlDictionary.sln create mode 100644 Samples/WebServices/XmlDictionary/cpp/XmlDictionary.vcxproj create mode 100644 Samples/WebServices/XmlDictionary/cpp/XmlDictionary.vcxproj.filters create mode 100644 Samples/WebServices/XmlDictionary/readme.txt create mode 100644 Samples/WebServicesDevicesApi/FileService/README.md create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileService.sln create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceClient/Client.cpp create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceClient/Client.h create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceClient/FileServiceClient.vcxproj create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/CodeGen_All.config create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/CodeGen_Client.config create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/CodeGen_Host.config create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileService.idl create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileService.wsdl create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileServiceContract.vcxproj create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileServiceProxy.cpp create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileServiceProxy.h create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileServiceStub.cpp create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileServiceTypes.cpp create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceContract/FileServiceTypes.h create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceService/FileServiceService.vcxproj create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceService/Service.cpp create mode 100644 Samples/WebServicesDevicesApi/FileService/cpp/FileServiceService/Service.h create mode 100644 Samples/WebServicesDevicesApi/FileService/readme.txt create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/README.md create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecure.sln create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureClient/FileServiceSecureClient.vcxproj create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureClient/SecureClient.cpp create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureClient/SecureClient.h create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/CodeGen_All.config create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/CodeGen_Client.config create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/CodeGen_Host.config create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecure.idl create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecure.wsdl create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecureContract.vcxproj create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecureProxy.cpp create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecureProxy.h create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecureStub.cpp create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecureTypes.cpp create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureContract/FileServiceSecureTypes.h create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureService/FileServiceSecureService.vcxproj create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureService/SecureService.cpp create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/cpp/FileServiceSecureService/SecureService.h create mode 100644 Samples/WebServicesDevicesApi/FileServiceSecure/readme.txt create mode 100644 Samples/WebServicesDevicesApi/StockQuote/README.md create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuote.sln create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteClient/Client.cpp create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteClient/Client.h create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteClient/StockQuoteClient.vcxproj create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/CodeGen_All.config create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/CodeGen_Client.config create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/CodeGen_Host.config create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuote.idl create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuote.wsdl create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuoteContract.vcxproj create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuoteProxy.cpp create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuoteProxy.h create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuoteStub.cpp create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuoteTypes.cpp create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/StockQuoteTypes.h create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/stockquote.xsd create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteContract/stockquoteservice.wsdl create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteService/Service.cpp create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteService/Service.h create mode 100644 Samples/WebServicesDevicesApi/StockQuote/cpp/StockQuoteService/StockQuoteService.vcxproj create mode 100644 Samples/WebServicesDevicesApi/StockQuote/readme.txt create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/README.md create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Client/Client.cpp create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Client/Client.h create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Client/Client.vcxproj create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Client/ClientNotificationSink.cpp create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Client/ClientNotificationSink.h create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Common/Common.cpp create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Common/Common.h create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Common/Common.vcxproj create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Service/Service.cpp create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Service/Service.h create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Service/Service.vcxproj create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Service/TargetService.cpp create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/Service/TargetService.h create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/cpp/wsdiscovery.sln create mode 100644 Samples/WebServicesDevicesApi/WSDiscovery/readme.txt create mode 100644 Samples/WebServicesManagementShellClient/README.md create mode 100644 Samples/WebServicesManagementShellClient/cpp/shellClient.cpp create mode 100644 Samples/WebServicesManagementShellClient/cpp/shellClient.sln create mode 100644 Samples/WebServicesManagementShellClient/cpp/shellClient.vcxproj create mode 100644 Samples/WebServicesManagementShellClient/cpp/stdafx.cpp create mode 100644 Samples/WebServicesManagementShellClient/cpp/stdafx.h create mode 100644 Samples/WebServicesManagementShellClient/cpp/targetver.h create mode 100644 Samples/Websocket/README.md create mode 100644 Samples/Websocket/cpp/List.cpp create mode 100644 Samples/Websocket/cpp/List.h create mode 100644 Samples/Websocket/cpp/Main.cpp create mode 100644 Samples/Websocket/cpp/Transport.cpp create mode 100644 Samples/Websocket/cpp/Transport.h create mode 100644 Samples/Websocket/cpp/Websocket.sln create mode 100644 Samples/Websocket/cpp/Websocket.vcxproj create mode 100644 Samples/Websocket/cpp/Websocket.vcxproj.filters create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/README.md create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/cpp/FilterProv.cpp create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/cpp/FilterProv.def create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/cpp/FilterProv.h create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/cpp/FilterProv.sln create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/cpp/FilterProv.vcxproj create mode 100644 Samples/WindowsDeploymentServices/FilterProvider/cpp/README.txt create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/README.md create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/cpp/ImgEnum.sln create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/cpp/ImgEnum.vcxproj create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/cpp/README.txt create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/cpp/imgenum.cpp create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/cpp/imgenum.rc create mode 100644 Samples/WindowsDeploymentServices/ImageEnumeration/cpp/resource.h create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/README.md create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/ReadMe.txt create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/WdsTransportManager.cpp create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/WdsTransportManager.h create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/WdsTransportManager.sln create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/WdsTransportManager.vcxproj create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/stdafx.cpp create mode 100644 Samples/WindowsDeploymentServices/Management/WDSTransportManager/cpp/stdafx.h create mode 100644 Samples/WindowsDeploymentServices/Multicast/Consumer/README.md create mode 100644 Samples/WindowsDeploymentServices/Multicast/Consumer/cpp/README.txt create mode 100644 Samples/WindowsDeploymentServices/Multicast/Consumer/cpp/consumer.sln create mode 100644 Samples/WindowsDeploymentServices/Multicast/Consumer/cpp/consumer.vcxproj create mode 100644 Samples/WindowsDeploymentServices/Multicast/Consumer/cpp/main.cpp create mode 100644 Samples/WindowsDeploymentServices/Multicast/Consumer/cpp/wdsscon.rc create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/README.md create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/cpp/README.txt create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/cpp/main.c create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/cpp/provider.sln create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/cpp/provider.vcxproj create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/cpp/wdscp.def create mode 100644 Samples/WindowsDeploymentServices/Multicast/WdsProvider/cpp/wdscp.rc create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/README.md create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/cpp/README.txt create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/cpp/SampProv.cpp create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/cpp/SampProv.def create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/cpp/SampProv.h create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/cpp/SampProv.sln create mode 100644 Samples/WindowsDeploymentServices/SampleProvider/cpp/SampProv.vcxproj create mode 100644 Samples/WinhttpProxy/README.md create mode 100644 Samples/WinhttpProxy/Readme.txt create mode 100644 Samples/WinhttpProxy/cpp/GetProxy.cpp create mode 100644 Samples/WinhttpProxy/cpp/GetProxy.h create mode 100644 Samples/WinhttpProxy/cpp/WinhttpProxySample.cpp create mode 100644 Samples/WinhttpProxy/cpp/WinhttpProxySample.sln create mode 100644 Samples/WinhttpProxy/cpp/WinhttpProxySample.vcxproj create mode 100644 Samples/WinhttpProxy/cpp/WinhttpProxySample.vcxproj.filters create mode 100644 Samples/WinhttpWebsocket/README.md create mode 100644 Samples/WinhttpWebsocket/cpp/WinhttpWebsocket.cpp create mode 100644 Samples/WinhttpWebsocket/cpp/WinhttpWebsocket.sln create mode 100644 Samples/WinhttpWebsocket/cpp/WinhttpWebsocket.vcxproj create mode 100644 Samples/WinhttpWebsocket/cpp/WinhttpWebsocket.vcxproj.filters create mode 100644 Samples/WinhttpWebsocket/cpp/server/RemoveServer.ps1 create mode 100644 Samples/WinhttpWebsocket/cpp/server/SetupServer.ps1 create mode 100644 Samples/WinhttpWebsocket/cpp/server/website/EchoWebSocket.ashx create mode 100644 Samples/WinsockBluetoothConnection/README.md create mode 100644 Samples/WinsockBluetoothConnection/cpp/BthCxn.rc create mode 100644 Samples/WinsockBluetoothConnection/cpp/bthcxn.cpp create mode 100644 Samples/WinsockBluetoothConnection/cpp/bthcxn.sln create mode 100644 Samples/WinsockBluetoothConnection/cpp/bthcxn.vcxproj create mode 100644 Samples/WinsockBluetoothConnection/cpp/readme.txt create mode 100644 Samples/XmlHttpRequest2GetRequest/README.md create mode 100644 Samples/XmlHttpRequest2GetRequest/Readme.txt create mode 100644 Samples/XmlHttpRequest2GetRequest/cpp/XMLHttpRequest2Callback.cpp create mode 100644 Samples/XmlHttpRequest2GetRequest/cpp/XMLHttpRequest2Callback.h create mode 100644 Samples/XmlHttpRequest2GetRequest/cpp/XMLHttpRequestGet.cpp create mode 100644 Samples/XmlHttpRequest2GetRequest/cpp/XMLHttpRequestGet.sln create mode 100644 Samples/XmlHttpRequest2GetRequest/cpp/XMLHttpRequestGet.vcxproj create mode 100644 Samples/XmlHttpRequest2GetRequest/cpp/XMLHttpRequestGet.vcxproj.filters create mode 100644 Samples/XmlHttpRequest2PostRequest/README.md create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequest2Callback.cpp create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequest2Callback.h create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequestPost.cpp create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequestPost.sln create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequestPost.vcxproj create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequestPost.vcxproj.filters create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequestPostStream.cpp create mode 100644 Samples/XmlHttpRequest2PostRequest/cpp/XMLHttpRequestPostStream.h create mode 100644 Samples/XmlHttpRequest3GetRequest/README.md create mode 100644 Samples/XmlHttpRequest3GetRequest/Readme.txt create mode 100644 Samples/XmlHttpRequest3GetRequest/cpp/XMLHttpRequest3Callback.cpp create mode 100644 Samples/XmlHttpRequest3GetRequest/cpp/XMLHttpRequest3Callback.h create mode 100644 Samples/XmlHttpRequest3GetRequest/cpp/XMLHttpRequest3Get.cpp create mode 100644 Samples/XmlHttpRequest3GetRequest/cpp/XMLHttpRequest3Get.sln create mode 100644 Samples/XmlHttpRequest3GetRequest/cpp/XMLHttpRequest3Get.vcxproj create mode 100644 Samples/XmlHttpRequest3GetRequest/cpp/XMLHttpRequest3Get.vcxproj.filters create mode 100644 Samples/XmlLiteChunkReader/README.md create mode 100644 Samples/XmlLiteChunkReader/cpp/XmlLiteChunkReader.cpp create mode 100644 Samples/XmlLiteChunkReader/cpp/chunks.xml create mode 100644 Samples/XmlLiteChunkReader/cpp/xmllitechunkreader.sln create mode 100644 Samples/XmlLiteChunkReader/cpp/xmllitechunkreader.vcxproj create mode 100644 Samples/XmlLiteChunkReader/cpp/xmllitechunkreader.vcxproj.filters create mode 100644 Samples/XmlLiteLimitedReader/README.md create mode 100644 Samples/XmlLiteLimitedReader/cpp/XmlLiteLimitedReader.cpp create mode 100644 Samples/XmlLiteLimitedReader/cpp/verylongname.xml create mode 100644 Samples/XmlLiteLimitedReader/cpp/xmllitelimitedreader.sln create mode 100644 Samples/XmlLiteLimitedReader/cpp/xmllitelimitedreader.vcxproj create mode 100644 Samples/XmlLiteLimitedReader/cpp/xmllitelimitedreader.vcxproj.filters create mode 100644 Samples/XmlLiteNamespaceReader/README.md create mode 100644 Samples/XmlLiteNamespaceReader/cpp/XmlLiteNamespaceReader.cpp create mode 100644 Samples/XmlLiteNamespaceReader/cpp/namespaces.xml create mode 100644 Samples/XmlLiteNamespaceReader/cpp/xmllitenamespacereader.sln create mode 100644 Samples/XmlLiteNamespaceReader/cpp/xmllitenamespacereader.vcxproj create mode 100644 Samples/XmlLiteNamespaceReader/cpp/xmllitenamespacereader.vcxproj.filters create mode 100644 Samples/XmlLiteNamespaceWriter1/README.md create mode 100644 Samples/XmlLiteNamespaceWriter1/cpp/XmlLiteNamespaceWriter1.cpp create mode 100644 Samples/XmlLiteNamespaceWriter1/cpp/xmllitenamespacewriter1.sln create mode 100644 Samples/XmlLiteNamespaceWriter1/cpp/xmllitenamespacewriter1.vcxproj create mode 100644 Samples/XmlLiteNamespaceWriter1/cpp/xmllitenamespacewriter1.vcxproj.filters create mode 100644 Samples/XmlLiteNamespaceWriter2/README.md create mode 100644 Samples/XmlLiteNamespaceWriter2/cpp/XmlLiteNamespaceWriter2.cpp create mode 100644 Samples/XmlLiteNamespaceWriter2/cpp/xmllitenamespacewriter2.sln create mode 100644 Samples/XmlLiteNamespaceWriter2/cpp/xmllitenamespacewriter2.vcxproj create mode 100644 Samples/XmlLiteNamespaceWriter2/cpp/xmllitenamespacewriter2.vcxproj.filters create mode 100644 Samples/XmlLiteNamespaceWriter3/README.md create mode 100644 Samples/XmlLiteNamespaceWriter3/cpp/XmlLiteNamespaceWriter3.cpp create mode 100644 Samples/XmlLiteNamespaceWriter3/cpp/xmllitenamespacewriter3.sln create mode 100644 Samples/XmlLiteNamespaceWriter3/cpp/xmllitenamespacewriter3.vcxproj create mode 100644 Samples/XmlLiteNamespaceWriter3/cpp/xmllitenamespacewriter3.vcxproj.filters create mode 100644 Samples/XmlLiteNamespaceWriter4/README.md create mode 100644 Samples/XmlLiteNamespaceWriter4/cpp/XmlLiteNamespaceWriter4.cpp create mode 100644 Samples/XmlLiteNamespaceWriter4/cpp/xmllitenamespacewriter4.sln create mode 100644 Samples/XmlLiteNamespaceWriter4/cpp/xmllitenamespacewriter4.vcxproj create mode 100644 Samples/XmlLiteNamespaceWriter4/cpp/xmllitenamespacewriter4.vcxproj.filters create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/README.md create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/FileStreamWithEPending.cpp create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/FileStreamWithEPending.hpp create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/InterleavedXML.xml create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/InterleavedXmlReader.sln create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/InterleavedXmlReader.vcxproj create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/InterleavedXmlReader.vcxproj.filters create mode 100644 Samples/XmlLiteNonBlockingInterleavedXmlReader/cpp/Main.cpp create mode 100644 Samples/XmlLiteNonBlockingRssReader/README.md create mode 100644 Samples/XmlLiteNonBlockingRssReader/cpp/Main.cpp create mode 100644 Samples/XmlLiteNonBlockingRssReader/cpp/RssReader.cpp create mode 100644 Samples/XmlLiteNonBlockingRssReader/cpp/RssReader.hpp create mode 100644 Samples/XmlLiteNonBlockingRssReader/cpp/RssReader.sln create mode 100644 Samples/XmlLiteNonBlockingRssReader/cpp/RssReader.vcxproj create mode 100644 Samples/XmlLiteNonBlockingRssReader/cpp/RssReader.vcxproj.filters create mode 100644 Samples/XmlLiteReadExternalEntities/README.md create mode 100644 Samples/XmlLiteReadExternalEntities/cpp/XmlLiteReadExternalEntities.cpp create mode 100644 Samples/XmlLiteReadExternalEntities/cpp/date.xml create mode 100644 Samples/XmlLiteReadExternalEntities/cpp/xmllitereadexternalentities.sln create mode 100644 Samples/XmlLiteReadExternalEntities/cpp/xmllitereadexternalentities.vcxproj create mode 100644 Samples/XmlLiteReadExternalEntities/cpp/xmllitereadexternalentities.vcxproj.filters create mode 100644 Samples/XmlLiteReadWithEncoding/README.md create mode 100644 Samples/XmlLiteReadWithEncoding/cpp/XmlLiteReadWithEncoding.cpp create mode 100644 Samples/XmlLiteReadWithEncoding/cpp/encoded.xml create mode 100644 Samples/XmlLiteReadWithEncoding/cpp/xmllitereadwithencoding.sln create mode 100644 Samples/XmlLiteReadWithEncoding/cpp/xmllitereadwithencoding.vcxproj create mode 100644 Samples/XmlLiteReadWithEncoding/cpp/xmllitereadwithencoding.vcxproj.filters create mode 100644 Samples/XmlLiteReader/README.md create mode 100644 Samples/XmlLiteReader/cpp/XmlLiteReader.cpp create mode 100644 Samples/XmlLiteReader/cpp/stocks.xml create mode 100644 Samples/XmlLiteReader/cpp/xmllitereader.sln create mode 100644 Samples/XmlLiteReader/cpp/xmllitereader.vcxproj create mode 100644 Samples/XmlLiteReader/cpp/xmllitereader.vcxproj.filters create mode 100644 Samples/XmlLiteReaderWriter/README.md create mode 100644 Samples/XmlLiteReaderWriter/cpp/XmlLiteReaderWriter.cpp create mode 100644 Samples/XmlLiteReaderWriter/cpp/books.xml create mode 100644 Samples/XmlLiteReaderWriter/cpp/xmllitereaderwriter.sln create mode 100644 Samples/XmlLiteReaderWriter/cpp/xmllitereaderwriter.vcxproj create mode 100644 Samples/XmlLiteReaderWriter/cpp/xmllitereaderwriter.vcxproj.filters create mode 100644 Samples/XmlLiteWriteDocType/README.md create mode 100644 Samples/XmlLiteWriteDocType/cpp/XmlLiteWriteDocType.cpp create mode 100644 Samples/XmlLiteWriteDocType/cpp/xmllitewritedoctype.sln create mode 100644 Samples/XmlLiteWriteDocType/cpp/xmllitewritedoctype.vcxproj create mode 100644 Samples/XmlLiteWriteDocType/cpp/xmllitewritedoctype.vcxproj.filters create mode 100644 Samples/XmlLiteWriteWithEncoding/README.md create mode 100644 Samples/XmlLiteWriteWithEncoding/cpp/XmlLiteWriteWithEncoding.cpp create mode 100644 Samples/XmlLiteWriteWithEncoding/cpp/xmllitewritewithencoding.sln create mode 100644 Samples/XmlLiteWriteWithEncoding/cpp/xmllitewritewithencoding.vcxproj create mode 100644 Samples/XmlLiteWriteWithEncoding/cpp/xmllitewritewithencoding.vcxproj.filters create mode 100644 Samples/XmlLiteWriter/README.md create mode 100644 Samples/XmlLiteWriter/cpp/XmlLiteWriter.cpp create mode 100644 Samples/XmlLiteWriter/cpp/xmllitewriter.sln create mode 100644 Samples/XmlLiteWriter/cpp/xmllitewriter.vcxproj create mode 100644 Samples/XmlLiteWriter/cpp/xmllitewriter.vcxproj.filters diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..5aec15cd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,37 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +# Declare files that will always have CRLF line endings on checkout. +*.appxmanifest text eol=crlf +*.c text eol=crlf +*.cpp text eol=crlf +*.cs text eol=crlf +*.csproj text eol=crlf +*.css text eol=crlf +*.def text eol=crlf +*.filters text eol=crlf +*.h text eol=crlf +*.htm text eol=crlf +*.html text eol=crlf +*.idl text eol=crlf +*.inf text eol=crlf +*.inx text eol=crlf +*.js text eol=crlf +*.jsproj text eol=crlf +*.rc text eol=crlf +*.rgs text eol=crlf +*.sln text eol=crlf +*.vcxproj text eol=crlf +*.xaml text eol=crlf + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +*.cs diff=csharp + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b315b7c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,200 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +[Gg]enerated Files/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.[Cc]ache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Custom ignores +gallery.xml diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..701b8330 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/README.md b/README.md index a996ce04..c411c26b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ -# Windows-classic-samples +# Windows classic samples + This repo contains samples that demonstrate the API used in Windows classic desktop applications. + +These samples in order to indicate or demonstrate the functionality of the programming models and feature APIs for 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). + +Most of these samples were created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but some were created with earlier versions, or with specific SKU and other requirements. In many cases, the samples will also work on later versions than the ones indicated. If you cannot get a sample to work as expected, it might have platform, version, or SKU-specific requirements. If you have any issues with the samples, please provide feedback using the Issues list. + +To get a copy of 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). + diff --git a/Samples/AmbientLightAware/README.md b/Samples/AmbientLightAware/README.md new file mode 100644 index 00000000..533561ee --- /dev/null +++ b/Samples/AmbientLightAware/README.md @@ -0,0 +1,49 @@ +Ambient light sensor sample +=========================== + +This sample demonstrates how to optimize a label's font size, based on light conditions reported by an Ambient Light sensor. + +The sample creates a smaller font when it detects indoor lighting conditions. It creates a larger font when it detects outdoor lighting conditions. + +**Note** + +This sample is not optimized for light conditions. It is intended to demonstrate one use of the sensor platform. + +Related topics +-------------- + +[Sensor API](http://msdn.microsoft.com/en-us/library/windows/desktop/dd318953) + +Operating system requirements +----------------------------- + +Client + +Windows 7 + +Server + +None supported + +Build the sample +---------------- + +To build the sample by using Visual Studio 2013 or later (preferred method): + +1. Open Windows Explorer and navigate to the directory. +2. Double-click the icon for the **.sln** (solution) file to open the file in Visual Studio. +3. In the **Build** menu, select **Build Solution**. The application is built in the default \\Debug or \\Release directory. + +To build the sample by using the command line: + +1. Open the **Command Prompt** window and navigate to the directory. +2. Type **msbuild ambientlightaware.sln**. + +Run the sample +-------------- + +To run the sample: + +1. Navigate to the directory that contains the new executable, by using the command prompt. +2. Type **ambientlightaware.exe** at the command line. + diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.cpp b/Samples/AmbientLightAware/cpp/AmbientLightAware.cpp new file mode 100644 index 00000000..5b15ef3f --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAware.cpp @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAware.cpp +// +// Description: +// Dialog for Ambient Light Aware SDK Sample +// +// Comments: +// Standard vc++ dialog created by VS 2005 wizard. +// This code just creates a dialog and cleans it up when finished. +// +//----------------------------------------------------------------------------- + +#include "stdafx.h" +#include "AmbientLightAware.h" +#include "AmbientLightAwareSensorEvents.h" +#include "AmbientLightAwareSensorManagerEvents.h" +#include "AmbientLightAwareDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CAmbientLightAwareApp + +BEGIN_MESSAGE_MAP(CAmbientLightAwareApp, CWinApp) + ON_COMMAND(ID_HELP, &CWinApp::OnHelp) +END_MESSAGE_MAP() + + +// CAmbientLightAwareApp construction +// Wizard generated constructor +CAmbientLightAwareApp::CAmbientLightAwareApp() +{ + // Place all significant initialization in InitInstance + + // Protect against heap corruption + (void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); +} + + +// The one and only CAmbientLightAwareApp object +CAmbientLightAwareApp theApp; + + +// CAmbientLightAwareApp initialization +BOOL CAmbientLightAwareApp::InitInstance() +{ + // InitCommonControlsEx() is required on Windows XP if an application + // manifest specifies use of ComCtl32.dll version 6 or later to enable + // visual styles. Otherwise, any window creation will fail. + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + // Set this to include all the common control classes you want to use + // in your application. + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + CWinApp::InitInstance(); + + // ************************************************************************ + // Added COM initialization, dialog cleanup, and COM uninitialization. + // ************************************************************************ + ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // Initializes COM + CAmbientLightAwareDlg dlg; + m_pMainWnd = &dlg; + dlg.DoModal(); + dlg.CleanUp(); // Once the dialog has returned, clean up its private members + ::CoUninitialize(); // Uninitializes COM + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.h b/Samples/AmbientLightAware/cpp/AmbientLightAware.h new file mode 100644 index 00000000..4eb42d71 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAware.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAware.h +// +// Description: +// Dialog for Ambient Light Aware SDK Sample +// +// Comments: +// Standard vc++ dialog created by VS 2005 wizard. +// +//----------------------------------------------------------------------------- + +#pragma once + +#ifndef __AFXWIN_H__ +#error "include 'stdafx.h' before including this file for PCH" +#endif + +#include "resource.h" // main symbols + + +// CAmbientLightAwareApp: +// See AmbientLightAware.cpp for the implementation of this class +// + +class CAmbientLightAwareApp : public CWinApp +{ +public: + CAmbientLightAwareApp(); + + // Overrides +public: + virtual BOOL InitInstance(); + + // Implementation + + DECLARE_MESSAGE_MAP() +}; + +extern CAmbientLightAwareApp theApp; \ No newline at end of file diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.ico b/Samples/AmbientLightAware/cpp/AmbientLightAware.ico new file mode 100644 index 0000000000000000000000000000000000000000..8a84ca3d34597ada57e4c79ef62b28cf07b5ed9a GIT binary patch literal 21630 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 V7_3;)FxY%t!w{8u!r68W{|isv(C`2N literal 0 HcmV?d00001 diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.rc b/Samples/AmbientLightAware/cpp/AmbientLightAware.rc new file mode 100644 index 00000000..e3ed2849 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAware.rc @@ -0,0 +1,168 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#include ""res\\AmbientLightAware.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "AmbientLightAware.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_AMBIENTLIGHTAWARE_DIALOG DIALOGEX 0, 0, 207, 88 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Ambient Light Aware SDK Sample" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Done",IDOK,7,65,50,16 + LTEXT "Ambient light level: lux",IDC_STATIC_LUX,7,7,193,12 + LTEXT "Sample Optimized Text",IDC_STATIC_SAMPLE,7,33,193,32 + LTEXT "Sensors: 0",IDC_STATIC_SENSORS,7,18,193,9 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Microsoft" + VALUE "FileDescription", "AmbientLightAware" + VALUE "FileVersion", "1.0.0.1" + VALUE "InternalName", "AmbientLightAware.exe" + VALUE "LegalCopyright", "(c) Microsoft. All rights reserved." + VALUE "OriginalFilename", "AmbientLightAware.exe" + VALUE "ProductName", "AmbientLightAware" + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_AMBIENTLIGHTAWARE_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 200 + TOPMARGIN, 7 + BOTTOMMARGIN, 81 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#include "AmbientLightAware.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.rc2 b/Samples/AmbientLightAware/cpp/AmbientLightAware.rc2 new file mode 100644 index 00000000..c54b7625 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAware.rc2 @@ -0,0 +1,13 @@ +// +// AmbientLightAware.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.sln b/Samples/AmbientLightAware/cpp/AmbientLightAware.sln new file mode 100644 index 00000000..0e94a287 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAware.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmbientLightAware", "AmbientLightAware.vcxproj", "{D3528BE0-D48A-4240-95FD-7724D6BAA755}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|Win32.ActiveCfg = Debug|Win32 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|Win32.Build.0 = Debug|Win32 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|x64.ActiveCfg = Debug|x64 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Debug|x64.Build.0 = Debug|x64 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|Win32.ActiveCfg = Release|Win32 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|Win32.Build.0 = Release|Win32 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|x64.ActiveCfg = Release|x64 + {D3528BE0-D48A-4240-95FD-7724D6BAA755}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAware.vcxproj b/Samples/AmbientLightAware/cpp/AmbientLightAware.vcxproj new file mode 100644 index 00000000..757f3c54 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAware.vcxproj @@ -0,0 +1,256 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + $(VCTargetsPath11) + + + {D3528BE0-D48A-4240-95FD-7724D6BAA755} + AmbientLightAware + MFCProj + + + + Application + v110 + Dynamic + Unicode + true + + + Application + v110 + Dynamic + Unicode + + + Application + v110 + Dynamic + Unicode + true + + + Application + v110 + Dynamic + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.50214.1 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + + + + _DEBUG;%(PreprocessorDefinitions) + false + false + + + Disabled + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level4 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + sensorsapi.lib;%(AdditionalDependencies) + true + Windows + false + + MachineX86 + + + + + NDEBUG;%(PreprocessorDefinitions) + false + false + + + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + false + MultiThreadedDLL + Use + Level4 + true + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + sensorsapi.lib;%(AdditionalDependencies) + true + Windows + true + true + false + + MachineX86 + + + + + _DEBUG;%(PreprocessorDefinitions) + false + X64 + + + Disabled + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level4 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + sensorsapi.lib;%(AdditionalDependencies) + true + Windows + false + + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + false + X64 + + + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + false + MultiThreadedDLL + Use + Level4 + true + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + sensorsapi.lib;%(AdditionalDependencies) + true + Windows + true + true + false + + MachineX64 + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.cpp b/Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.cpp new file mode 100644 index 00000000..27098845 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.cpp @@ -0,0 +1,277 @@ +//----------------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAwareDlg.cpp +// +// Description: +// Dialog for Ambient Light Aware SDK Sample +// +// Comments: +// Standard vc++ dialog created by VS 2005 wizard. +// +//----------------------------------------------------------------------------- + +#include "stdafx.h" +#include "AmbientLightAware.h" +#include "AmbientLightAwareSensorEvents.h" +#include "AmbientLightAwareSensorManagerEvents.h" +#include "AmbientLightAwareDlg.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +// Wizard generated constructor +CAmbientLightAwareDlg::CAmbientLightAwareDlg(CWnd* pParent /*=NULL*/) +: CDialog(CAmbientLightAwareDlg::IDD, pParent) +{ + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); + m_pSensorManagerEvents = NULL; + ZeroMemory(&m_lfLogFont, sizeof(LOGFONT)); +} + +// Wizard generated destructor +CAmbientLightAwareDlg::~CAmbientLightAwareDlg() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareDlg::CleanUp +// +// Description of function/method: +// Helper function, called by main winapp to do clean up of private +// members +// +// Parameters: +// none +// +// Return Values: +// S_OK +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareDlg::CleanUp() +{ + HRESULT hr = S_OK; + + hr = m_pSensorManagerEvents->Uninitialize(); + + if (NULL != m_pSensorManagerEvents) + { + delete m_pSensorManagerEvents; + m_pSensorManagerEvents = NULL; + } + + return hr; +} + +// Wizard generated function +void CAmbientLightAwareDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CAmbientLightAwareDlg, CDialog) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +// CAmbientLightAwareDlg message handlers +// Wizard generated function. Added helper function call inside. +BOOL CAmbientLightAwareDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // ************************************************************************ + // Added this helper function call to initialize sensor events + // ************************************************************************ + InitAmbientLightAware(); + + return TRUE; // return TRUE unless you set the focus to a control +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. +// Wizard generated function. Added font size change for optimized text. +void CAmbientLightAwareDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + + // ******************************************************************** + // Change the font size for the optimzed text. + // ******************************************************************** + CFont fontOptimzed; + BOOL fRet = fontOptimzed.CreateFontIndirect(&m_lfLogFont); + if (fRet) + { + CWnd* pStaticTextSample = GetDlgItem(IDC_STATIC_SAMPLE); + if (NULL != pStaticTextSample) + { + pStaticTextSample->SetFont(&fontOptimzed); + } + } + } +} + +// The system calls this function to obtain the cursor to display while the user drags +// the minimized window. +// Wizard generated function +HCURSOR CAmbientLightAwareDlg::OnQueryDragIcon() +{ + return static_cast(m_hIcon); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareDlg::InitAmbientLightAware +// +// Description of function/method: +// Helper function, initializes sensor events class +// +// Parameters: +// none +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareDlg::InitAmbientLightAware() +{ + HRESULT hr = S_OK; + + // save the font so we can easily change the text size in UpdateLux + CFont* pFont; + CWnd* pWnd = GetDlgItem(IDC_STATIC_SAMPLE); + if (NULL != pWnd) + { + pFont = pWnd->GetFont(); + if (NULL != pFont) + { + LONG lRet = pFont->GetLogFont(&m_lfLogFont); + if (0 != lRet) + { + m_pSensorManagerEvents = new CAmbientLightAwareSensorManagerEvents(this); + hr = m_pSensorManagerEvents->Initialize(); + } + else + { + hr = E_FAIL; + } + } + else + { + hr = E_POINTER; + } + } + else + { + hr = E_POINTER; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareDlg::UpdateLux +// +// Description of function/method: +// Callback function. This function is called by the events class when +// new data has been received. This function then uses this information +// to change the font size to be optimized for the current brightness +// (lux). +// +// This sample is not meant to be an ideal implementation, but just +// showing how sensor data can be collected and processed. +// +// Parameters: +// lux: The average lux value for all sensors +// numSensors: The number of sensors reporting data +// +// Return Values: +// TRUE on success, FALSE on failure +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareDlg::UpdateLux(float lux, int numSensors) +{ + HRESULT hr = S_OK; + CString strLux, strSensors; + CFont fontSample; + + if(lux < 10.0) + { + // Darkness + m_lfLogFont.lfHeight = 12; // A sample font size for dark environments + } + else if(lux < 300) + { + // Dim Indoors + m_lfLogFont.lfHeight = 12; // A sample font size for dim indoor environments + } + else if(lux < 800) + { + // Normal Indoors + m_lfLogFont.lfHeight = 12; // A sample font size for indoor environments + } + else if(lux < 10000) + { + // Bright Indoors + m_lfLogFont.lfHeight = 16; // A sample font size for bright indoor environments + } + else if(lux < 30000) + { + // Overcast Outdoors + m_lfLogFont.lfHeight = 20; // A sample font size for overcast environments + } + else + { + // Direct Sunlight + m_lfLogFont.lfHeight = 30; // A sample font size for sunny environments + } + + strLux.Format(_T("Ambient light level: %.2f lux"), lux); + SetDlgItemText(IDC_STATIC_LUX, strLux); + + strSensors.Format(_T("Sensors: %i"), numSensors); + SetDlgItemText(IDC_STATIC_SENSORS, strSensors); + + // Force OnPaint which changes the text font to be optimized for this lux + Invalidate(); + UpdateWindow(); + + return hr; +} \ No newline at end of file diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.h b/Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.h new file mode 100644 index 00000000..21bba045 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAwareDlg.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAwareDlg.h +// +// Description: +// Dialog for Ambient Light Aware SDK Sample +// +// Comments: +// Standard vc++ dialog created by VS 2005 wizard. +// +//----------------------------------------------------------------------------- + +#pragma once + +// CAmbientLightAwareDlg dialog +class CAmbientLightAwareDlg : public CDialog +{ + // Construction +public: + // standard constructor + CAmbientLightAwareDlg(CWnd* pParent = NULL); + virtual ~CAmbientLightAwareDlg(); + + // Dialog Data + enum { IDD = IDD_AMBIENTLIGHTAWARE_DIALOG }; + + // Our callback function from CAmbientLightAwareEvents + HRESULT UpdateLux(float lux, int numSensors); + // Clean up function called by parent winapp + HRESULT CleanUp(); + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + // Implementation +protected: + HICON m_hIcon; + + // Generated message map functions + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + DECLARE_MESSAGE_MAP() + +private: + // helper function + HRESULT InitAmbientLightAware(); + + CAmbientLightAwareSensorManagerEvents* m_pSensorManagerEvents; // events class + LOGFONT m_lfLogFont; // font to be adjusted for current brightness +}; diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.cpp b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.cpp new file mode 100644 index 00000000..d63d8157 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.cpp @@ -0,0 +1,436 @@ +//----------------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAwareSensorEvents.cpp +// +// Description: +// Implementation of ISensorManagerEvents +// +// Comments: +// This is a standard c++ class, but needs to support IUnknown methods +// to be properly implemented. This class overrides ISensorEvents +// functions to receive updated information from the Sensors API when it +// is published. +// +//----------------------------------------------------------------------------- + +#include "StdAfx.h" +#include "Resource.h" +#include "AmbientLightAwareSensorEvents.h" +#include "AmbientLightAwareDlg.h" +#include "AmbientLightAwareSensorManagerEvents.h" + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::CAmbientLightAwareSensorEvents +// +// Description of function/method: +// Constructor. +// +// Parameters: +// CAmbientLightAwareDlg* dlg: Parent dialog for callbacks +// CAmbientLightAwareSensorManagerEvents* sensorManagerEvents: +// Parent class for callbacks +// +// Return Values: +// None +// +/////////////////////////////////////////////////////////////////////////////// +CAmbientLightAwareSensorEvents::CAmbientLightAwareSensorEvents(CAmbientLightAwareDlg* dlg, CAmbientLightAwareSensorManagerEvents* sensorManagerEvents) +{ + m_lRefCount = 1; //ref count initialized to 1 + m_pParentDlg = dlg; + m_pSensorManagerEvents = sensorManagerEvents; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::~CAmbientLightAwareSensorEvents +// +// Description of function/method: +// Destructor. Clean up stored data. +// +// Parameters: +// none +// +// Return Values: +// None +// +/////////////////////////////////////////////////////////////////////////////// +CAmbientLightAwareSensorEvents::~CAmbientLightAwareSensorEvents() +{ + m_mapLux.RemoveAll(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::QueryInterface +// +// Description of function/method: +// IUnknown method, need to implement to support COM classes that +// are inherited. +// +// Parameters: +// REFIID riid: Input. ID of the interface being requested. Either +// IUnknown or one of the two classes we inherit. +// void** ppObject: Output. Address of pointer variable that receives +// the interface pointer requested in riid. Upon +// successful return, *ppvObject contains the requested +// interface pointer to the object. If the object does +// not support the interface specified in iid, +// *ppvObject is set to NULL. +// +// Return Values: +// S_OK on success, else E_NOINTERFACE +// +/////////////////////////////////////////////////////////////////////////////// +STDMETHODIMP CAmbientLightAwareSensorEvents::QueryInterface(REFIID riid, void** ppObject) +{ + HRESULT hr = S_OK; + + *ppObject = NULL; + if (riid == __uuidof(ISensorEvents)) + { + *ppObject = reinterpret_cast(this); + } + else if (riid == IID_IUnknown) + { + *ppObject = reinterpret_cast(this); + } + else + { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr)) + { + (reinterpret_cast(*ppObject))->AddRef(); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::AddRef +// +// Description of function/method: +// Increments the reference count for an interface on an object. +// +// Parameters: +// none +// +// Return Values: +// Returns an integer from 1 to n, the value of the new reference count. +// +/////////////////////////////////////////////////////////////////////////////// +ULONG _stdcall CAmbientLightAwareSensorEvents::AddRef() +{ + m_lRefCount++; + return m_lRefCount; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::Release +// +// Description of function/method: +// Decrements the reference count for the calling interface on a object. +// If the reference count on the object falls to 0, the object is freed +// from memory. +// +// Parameters: +// none +// +// Return Values: +// Returns an integer from 1 to n, the value of the new reference count. +// +/////////////////////////////////////////////////////////////////////////////// +ULONG _stdcall CAmbientLightAwareSensorEvents::Release() +{ + ULONG lRet = --m_lRefCount; + + if (m_lRefCount == 0) + { + delete this; + } + + return lRet; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::OnStateChanged +// +// Description of function/method: +// Implementation of ISensor.OnStateChanged. Called when permissions of +// the sensor have changed, such as the sensor being disabled in control +// panel. If the sensor is not SENSOR_STATE_READY then its lux value +// should be ignored. +// +// Parameters: +// ISensor* pSensor: Sensor that has changed +// SensorState state: State of the sensor +// +// Return Values: +// S_OK +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::OnStateChanged(__RPC__in_opt ISensor *pSensor, SensorState state) +{ + HRESULT hr = S_OK; + + if (NULL != pSensor) + { + SENSOR_ID idSensor = GUID_NULL; + hr = pSensor->GetID(&idSensor); + if (SUCCEEDED(hr)) + { + if (SENSOR_STATE_READY == state) + { + hr = GetSensorData(pSensor); + } + else + { + // If the sensor is not ready, its lux value is ignored + m_mapLux[idSensor] = -1.0; + hr = UpdateLux(); + } + } + } + else + { + hr = E_POINTER; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::OnDataUpdated +// +// Description of function/method: +// Implementation of ISensor.OnDataUpdated. Called when the sensor has +// published new data. This reads in the lux value from the report. +// +// Parameters: +// ISensor* pSensor: Sensor that has updated data. +// ISensorDataReport *pNewData: New data to be read +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::OnDataUpdated(__RPC__in_opt ISensor *pSensor, __RPC__in_opt ISensorDataReport *pNewData) +{ + HRESULT hr = S_OK; + + if ((NULL != pSensor) && (NULL != pNewData)) + { + hr = GetSensorData(pSensor, pNewData); + } + else + { + hr = E_UNEXPECTED; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::OnEvent +// +// Description of function/method: +// Implementation of ISensor.OnEevent, a generic or custom sensor event. +// OnDataUpdated is the event this sample uses to get sensor +// information. +// +// Parameters: +// ISensor* pSensor: Sensor that has the event. +// GUID& eventID: Type of event. +// IPortableDeviceValues *pEventData: Data to be read. +// +// Return Values: +// S_OK +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::OnEvent(__RPC__in_opt ISensor* /*pSensor*/, __RPC__in REFGUID /*eventID*/, __RPC__in_opt IPortableDeviceValues* /*pEventData*/) +{ + // Not implemented + return E_NOTIMPL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::OnLeave +// +// Description of function/method: +// Implementation of ISensor.OnLeave. This sensor is being removed, so +// it needs to be deleted and freed. +// +// Parameters: +// REFSENSOR_ID sensorID: +// +// Return Values: +// S_OK +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::OnLeave(__RPC__in REFSENSOR_ID sensorID) +{ + HRESULT hr = S_OK; + + hr = m_pSensorManagerEvents->RemoveSensor(sensorID); // Callback into parent + if (SUCCEEDED(hr)) + { + // Remove the data for this device + if (m_mapLux.RemoveKey(sensorID)) + { + hr = UpdateLux(); + } + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::UpdateLux +// +// Description of function/method: +// Helper function, calculates average lux and does a callback to the +// parent dialog. +// +// Parameters: +// none +// +// Return Values: +// none +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::UpdateLux() +{ + HRESULT hr = S_OK; + + float fpLux = 0.0; + float fpLuxTemp = 0.0; + float count = 0; + + POSITION pos = m_mapLux.GetStartPosition(); + while (NULL != pos) + { + fpLuxTemp = m_mapLux.GetNextValue(pos); + if (fpLuxTemp >= 0) + { + count++; + fpLux += fpLuxTemp; + } + } + + if (count > 0) + { + fpLux = fpLux / count; + } + + hr = m_pParentDlg->UpdateLux(fpLux, (int) count); + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::GetSensorData +// +// Description of function/method: +// Helper function, get data from a sensor and updates the lux +// +// Parameters: +// ISensor* pSensor: Input sensor +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::GetSensorData(ISensor* pSensor) +{ + HRESULT hr = S_OK; + + if (NULL != pSensor) + { + CComPtr spDataReport; + hr = pSensor->GetData(&spDataReport); + if (SUCCEEDED(hr)) + { + hr = GetSensorData(pSensor, spDataReport); + } + else + { + SENSOR_ID idSensor = GUID_NULL; + hr = pSensor->GetID(&idSensor); + if (SUCCEEDED(hr)) + { + m_mapLux[idSensor] = -1.0; + hr = UpdateLux(); + } + } + } + else + { + hr = E_POINTER; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorEvents::GetSensorData +// +// Description of function/method: +// Helper function, get data from a sensor and updates the lux +// +// Parameters: +// ISensor *pSensor: Input sensor +// ISensorDataReport* pDataReport: The data to be read +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorEvents::GetSensorData(ISensor *pSensor, ISensorDataReport *pDataReport) +{ + HRESULT hr = S_OK; + + if (NULL != pSensor && NULL != pDataReport) + { + SENSOR_ID idSensor = GUID_NULL; + hr = pSensor->GetID(&idSensor); + if (SUCCEEDED(hr)) + { + PROPVARIANT pvLux; + PropVariantInit(&pvLux); + hr = pDataReport->GetSensorValue(SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, &pvLux); + if (SUCCEEDED(hr)) + { + // Save the lux value into our member variable + m_mapLux[idSensor] = V_R4(&pvLux); + + hr = UpdateLux(); + } + PropVariantClear(&pvLux); + } + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} \ No newline at end of file diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.h b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.h new file mode 100644 index 00000000..4b404bde --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorEvents.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAwareSensorEvents.h +// +// Description: +// Implementation of ISensorEvents +// +// Comments: +// This is a standard c++ class, but needs to support IUnknown methods +// to be properly implemented. This class overrides ISensorEvents and +// functions to receive updated information from Sensors API when it +// is published. +// +//----------------------------------------------------------------------- +#pragma once + +// Forward declarations. +class CAmbientLightAwareDlg; +class CAmbientLightAwareSensorManagerEvents; + +class CAmbientLightAwareSensorEvents : + public ISensorEvents +{ +public: + // These three methods are for IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppObject ); + ULONG _stdcall AddRef(); + ULONG _stdcall Release(); + + // Constructor and destructor + CAmbientLightAwareSensorEvents(CAmbientLightAwareDlg* dlg, CAmbientLightAwareSensorManagerEvents* sensorManagerEvents); + virtual ~CAmbientLightAwareSensorEvents(); + + // ISensorEvents method overrides + STDMETHOD(OnStateChanged)(__RPC__in_opt ISensor* pSensor, SensorState state); + STDMETHOD(OnDataUpdated)(__RPC__in_opt ISensor* pSensor, __RPC__in_opt ISensorDataReport* pNewData); + STDMETHOD(OnEvent)(__RPC__in_opt ISensor* pSensor, __RPC__in REFGUID eventID, __RPC__in_opt IPortableDeviceValues* pEventData); + STDMETHOD(OnLeave)(__RPC__in REFSENSOR_ID sensorID); + + // Helper functions, also called by parent SensorManagerEvents class + HRESULT GetSensorData(ISensor* pSensor); + +private: + // Member variable to implement IUnknown reference count + LONG m_lRefCount; + + // Helper functions + HRESULT UpdateLux(); + HRESULT GetSensorData(ISensor* pSensor, ISensorDataReport* pDataReport); + + CAmbientLightAwareDlg* m_pParentDlg; // Parent dialog used for callbacks + CAmbientLightAwareSensorManagerEvents* m_pSensorManagerEvents; // Parent class for callbacks + CAtlMap m_mapLux; // Map to store lux values for each sensor +}; diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.cpp b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.cpp new file mode 100644 index 00000000..142ef287 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.cpp @@ -0,0 +1,417 @@ +//----------------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAwareSensorManagerEvents.cpp +// +// Description: +// Implementation of ISensorManagerEvents +// +// Comments: +// This is a standard c++ class, but needs to support IUnknown methods +// to be properly implemented. This class overrides +// ISensorManagerEvents functions to receive updated information from +// the Sensors API when it is published. +// +//----------------------------------------------------------------------------- + +#include "StdAfx.h" +#include "Resource.h" +#include "AmbientLightAwareSensorEvents.h" +#include "AmbientLightAwareSensorManagerEvents.h" +#include "AmbientLightAwareDlg.h" + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::CAmbientLightAwareSensorManagerEvents +// +// Description of function/method: +// Constructor. +// +// Parameters: +// CAmbientLightAwareDlg* dlg: pointer to parent dialog for callbacks +// +// Return Values: +// None +// +/////////////////////////////////////////////////////////////////////////////// +CAmbientLightAwareSensorManagerEvents::CAmbientLightAwareSensorManagerEvents(CAmbientLightAwareDlg* dlg) +{ + m_lRefCount = 1; //ref count initialized to 1 + m_pSensorEvents = new CAmbientLightAwareSensorEvents(dlg, this); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::~CAmbientLightAwareSensorManagerEvents +// +// Description of function/method: +// Destructor. Clean up stored data. +// +// Parameters: +// none +// +// Return Values: +// None +// +/////////////////////////////////////////////////////////////////////////////// +CAmbientLightAwareSensorManagerEvents::~CAmbientLightAwareSensorManagerEvents() +{ + if (NULL != m_pSensorEvents) + { + delete m_pSensorEvents; + m_pSensorEvents = NULL; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::QueryInterface +// +// Description of function/method: +// IUnknown method, need to implement to support COM classes that +// are inherited. +// +// Parameters: +// REFIID riid: Input. ID of the interface being requested. Either +// IUnknown or one of the two classes we inherit. +// void** ppObject: Output. Address of pointer variable that receives +// the interface pointer requested in riid. Upon +// successful return, *ppvObject contains the requested +// interface pointer to the object. If the object does +// not support the interface specified in iid, +// *ppvObject is set to NULL. +// +// Return Values: +// S_OK on success, else E_NOINTERFACE +// +/////////////////////////////////////////////////////////////////////////////// +STDMETHODIMP CAmbientLightAwareSensorManagerEvents::QueryInterface(REFIID riid, void** ppObject) +{ + HRESULT hr = S_OK; + + *ppObject = NULL; + if (riid == __uuidof(ISensorManagerEvents)) + { + *ppObject = reinterpret_cast(this); + } + else if (riid == IID_IUnknown) + { + *ppObject = reinterpret_cast(this); + } + else + { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr)) + { + (reinterpret_cast(*ppObject))->AddRef(); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::AddRef +// +// Description of function/method: +// Increments the reference count for an interface on an object. +// +// Parameters: +// none +// +// Return Values: +// Returns an integer from 1 to n, the value of the new reference count. +// +/////////////////////////////////////////////////////////////////////////////// +ULONG _stdcall CAmbientLightAwareSensorManagerEvents::AddRef() +{ + m_lRefCount++; + return m_lRefCount; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::Release +// +// Description of function/method: +// Decrements the reference count for the calling interface on a object. +// If the reference count on the object falls to 0, the object is freed +// from memory. +// +// Parameters: +// none +// +// Return Values: +// Returns an integer from 1 to n, the value of the new reference count. +// +/////////////////////////////////////////////////////////////////////////////// +ULONG _stdcall CAmbientLightAwareSensorManagerEvents::Release() +{ + ULONG lRet = --m_lRefCount; + + if (m_lRefCount == 0) + { + delete this; + } + + return lRet; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::Initialize +// +// Description of function/method: +// Initialize the sensor data. +// +// Parameters: +// none +// +// Return Values: +// HRESULT S_OK on success +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorManagerEvents::Initialize() +{ + HRESULT hr; + + hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager); + if (SUCCEEDED(hr)) + { + hr = m_spISensorManager->SetEventSink(this); + if (SUCCEEDED(hr)) + { + // Find all Ambient Light Sensors + CComPtr spSensors; + hr = m_spISensorManager->GetSensorsByType(SENSOR_TYPE_AMBIENT_LIGHT, &spSensors); + if (SUCCEEDED(hr) && NULL != spSensors) + { + ULONG ulCount = 0; + hr = spSensors->GetCount(&ulCount); + if (SUCCEEDED(hr)) + { + for(ULONG i=0; i < ulCount; i++) + { + CComPtr spSensor; + hr = spSensors->GetAt(i, &spSensor); + if (SUCCEEDED(hr)) + { + hr = AddSensor(spSensor); + if (SUCCEEDED(hr)) + { + hr = m_pSensorEvents->GetSensorData(spSensor); + } + } + } + } + } + } + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::Uninitialize +// +// Description of function/method: +// Uninitialize the sensor data. +// +// Parameters: +// none +// +// Return Values: +// HRESULT S_OK on success +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorManagerEvents::Uninitialize() +{ + HRESULT hr = S_OK; + + POSITION pos = m_Sensors.GetStartPosition(); + while (NULL != pos) + { + ISensor* pSensor = m_Sensors.GetNextValue(pos); + RemoveSensor(pSensor); + } + + if (NULL != m_spISensorManager) + { + hr = m_spISensorManager->SetEventSink(NULL); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::OnSensorEnter +// +// Description of function/method: +// Implementation of ISensorManager.OnSensorEnter. Check if the sensor +// is an Ambient Light Sensor and if so then add the sensor. +// +// Parameters: +// ISensor* pSensor: Sensor that has been installed +// SensorState state: State of the sensor +// +// Return Values: +// S_OK on success, else an error. +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorManagerEvents::OnSensorEnter(__RPC__in_opt ISensor* pSensor, SensorState state) +{ + HRESULT hr = S_OK; + + if (NULL != pSensor) + { + SENSOR_TYPE_ID idType = GUID_NULL; + hr = pSensor->GetType(&idType); + if (SUCCEEDED(hr)) + { + if (IsEqualIID(idType, SENSOR_TYPE_AMBIENT_LIGHT)) + { + hr = AddSensor(pSensor); + if (SUCCEEDED(hr)) + { + if (SENSOR_STATE_READY == state) + { + hr = m_pSensorEvents->GetSensorData(pSensor); + } + } + } + } + } + else + { + hr = E_POINTER; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::AddSensor +// +// Description of function/method: +// Helper function, sets up event sinking for a sensor and saves the +// sensor. +// +// Parameters: +// ISensor *pSensor: Input sensor +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorManagerEvents::AddSensor(ISensor *pSensor) +{ + HRESULT hr = S_OK; + + if (NULL != pSensor) + { + hr = pSensor->SetEventSink(m_pSensorEvents); + if (SUCCEEDED(hr)) + { + // Get the sensor's ID to be used as a key to store the sensor + SENSOR_ID idSensor = GUID_NULL; + hr = pSensor->GetID(&idSensor); + if (SUCCEEDED(hr)) + { + // Enter the sensor into the map and take the ownership of its lifetime + pSensor->AddRef(); // the sensor is released in the destructor + m_Sensors[idSensor] = pSensor; + } + } + } + else + { + hr = E_POINTER; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::RemoveSensor +// +// Description of function/method: +// Helper function, clears the event sink for the sensor and then +// releases the sensor. +// +// Parameters: +// ISensor *pSensor: Input sensor +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorManagerEvents::RemoveSensor(ISensor* pSensor) +{ + HRESULT hr = S_OK; + + // Release the event and ISensor objecets + if (NULL != pSensor) + { + hr = pSensor->SetEventSink(NULL); // This also decreases the ref count of the sink object. + + SENSOR_ID idSensor = GUID_NULL; + hr = pSensor->GetID(&idSensor); + if (SUCCEEDED(hr)) + { + m_Sensors.RemoveKey(idSensor); + } + + pSensor->Release(); + } + else + { + hr = E_POINTER; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CAmbientLightAwareSensorManagerEvents::RemoveSensor +// +// Description of function/method: +// Helper function, clears the event sink for the sensor and then +// releases the sensor. +// +// Parameters: +// REFSENSOR_ID sensorID: Input sensor +// +// Return Values: +// S_OK on success, else an error +// +/////////////////////////////////////////////////////////////////////////////// +HRESULT CAmbientLightAwareSensorManagerEvents::RemoveSensor(REFSENSOR_ID sensorID) +{ + HRESULT hr = S_OK; + + if (m_Sensors.Lookup(sensorID)) + { + ISensor* pSensor = m_Sensors[sensorID]; + m_Sensors.RemoveKey(sensorID); + pSensor->Release(); + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + } + + return hr; +} \ No newline at end of file diff --git a/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.h b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.h new file mode 100644 index 00000000..83985f48 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/AmbientLightAwareSensorManagerEvents.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------- +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. +// +// Module: +// AmbientLightAwareSensorManagerEvents.h +// +// Description: +// Implementation of ISensorManagerEvents +// +// Comments: +// This is a standard c++ class, but needs to support IUnknown methods +// to be properly implemented. This class overrides +// ISensorManagerEvents functions to receive updated information from +// the Sensors API when it is published. +// +//----------------------------------------------------------------------- +#pragma once + +// Forward declaration. +class CAmbientLightAwareDlg; + +class CAmbientLightAwareSensorManagerEvents : + public ISensorManagerEvents +{ +public: + // These three methods are for IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppObject ); + ULONG _stdcall AddRef(); + ULONG _stdcall Release(); + + // Constructor and destructor + CAmbientLightAwareSensorManagerEvents(CAmbientLightAwareDlg* dlg); + virtual ~CAmbientLightAwareSensorManagerEvents(); + + // Initialize and Uninitialize called by parent dialog + HRESULT Initialize(); + HRESULT Uninitialize(); + + // ISensorManagerEvents method override + STDMETHOD(OnSensorEnter)(__RPC__in_opt ISensor* pSensor, SensorState state); + + // Is a callback from child SensorEvents + HRESULT RemoveSensor(REFSENSOR_ID sensorID); + +private: + // Member variable to implement IUnknown reference count + LONG m_lRefCount; + + // Helper functions + HRESULT AddSensor(ISensor* pSensor); + HRESULT RemoveSensor(ISensor* pSensor); + + CAmbientLightAwareSensorEvents* m_pSensorEvents; // Sensor Events class used for event sinking + CComPtr m_spISensorManager; // Global to keep reference for life of class + CAtlMap m_Sensors; // Map to store sensors for life of class +}; diff --git a/Samples/AmbientLightAware/cpp/ReadMe.txt b/Samples/AmbientLightAware/cpp/ReadMe.txt new file mode 100644 index 00000000..3867b405 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/ReadMe.txt @@ -0,0 +1,57 @@ +========================= +Ambient Light Aware +Windows 7 Sensor Platform +========================= +This MFC sample shows how to use the Sensor Platform by reading data from Ambient Light Sensors on the computer and changing a label's font size to be optimized for the reported light conditions. Such as smaller font while inside and larger font while outside in a sunny environment. The sample is not meant to be perfect in optimizing for light conditions, but done to show the usage of the Sensor Platform. This sample requires Visual Studio to be built. + +=============================== +Sample Language Implementations +=============================== + This sample is available in the following language implementations: + C++ + +===== +Files +===== +AmbientLightAware.cpp The main CWinApp file +AmbientLightAware.h Header file +AmbientLightAware.rc Resource file for MFC +AmbientLightAware.sln Solution for the project +AmbientLightAware.vcproj VS Project file +AmbientLightAwareDlg.cpp Dialog class +AmbientLightAwareDlg.h Header file +AmbientLightAwareSensorManagerEvents.cpp Custom class to handle ISensorManager events +AmbientLightAwareSensorManagerEvents.h Header file +AmbientLightAwareSensorEvents.cpp Custom class to handle ISensor events +AmbientLightAwareSensorEvents.h Header file +ReadMe.txt This ReadMe +resource.h Resource file +stdafx.cpp Precompiled file +stdafx.h Precompiled header + +============= +Prerequisites +============= +Windows 7 +Visual Studio 2008 + +======== +Building +======== +This sample cannot be built in the SDK environment. Visual Studio must be used. +To build the sample using Visual Studio 2008: + 1. Run the Windows SDK Configuration Tool provided with the SDK to add SDK include directories to Visual Studio + 2. Open File Explorer and navigate to the directory. + 3. Double-click the icon for the .sln (solution) file to open the file in Visual Studio. + 4. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + +======= +Running +======= +To run the sample: + 1. Navigate to the directory that contains the new executable, using the command prompt or File Explorer. + 2. Type AmbientLightAware.exe at the command line, or double-click the icon for AmbientLightAware.exe to launch it from File Explorer. + +To run from Visual Studio: + 1. Press F5 or Click menu + Debug->Start Debugging \ No newline at end of file diff --git a/Samples/AmbientLightAware/cpp/resource.h b/Samples/AmbientLightAware/cpp/resource.h new file mode 100644 index 00000000..c1b5bade --- /dev/null +++ b/Samples/AmbientLightAware/cpp/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by AmbientLightAware.rc +// +#define IDD_AMBIENTLIGHTAWARE_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDC_STATIC_LUX 1001 +#define IDC_STATIC_SAMPLE 1002 +#define IDC_STATIC_LUX_SENSORS 1003 +#define IDC_STATIC_SENSORS 1003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Samples/AmbientLightAware/cpp/stdafx.cpp b/Samples/AmbientLightAware/cpp/stdafx.cpp new file mode 100644 index 00000000..0a2acb61 --- /dev/null +++ b/Samples/AmbientLightAware/cpp/stdafx.cpp @@ -0,0 +1,14 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. + +// stdafx.cpp : source file that includes just the standard includes +// AmbientLightAware.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + diff --git a/Samples/AmbientLightAware/cpp/stdafx.h b/Samples/AmbientLightAware/cpp/stdafx.h new file mode 100644 index 00000000..aa55f42c --- /dev/null +++ b/Samples/AmbientLightAware/cpp/stdafx.h @@ -0,0 +1,90 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright Microsoft Corporation. All rights reserved. + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +// Suppress warning that CComCritSecLock::Lock "Possibly failing to release lock" +#pragma warning(disable: 26165) + +// Suppress warning that CComCritSecLock::Unlock "Possibly releasing unheld lock" +#pragma warning(disable: 26167) + +#ifndef _SECURE_ATL +#define _SECURE_ATL 1 +#endif + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0601 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0601 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions + + + + + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC support for Internet Explorer 4 Common Controls +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + + + + + + + + +#ifdef _UNICODE +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif + +// **************************************************************************** +// Sensors related includes +// **************************************************************************** +#include +#include +#include \ No newline at end of file diff --git a/Samples/AppVisibility/README.md b/Samples/AppVisibility/README.md new file mode 100644 index 00000000..6ea1a86e --- /dev/null +++ b/Samples/AppVisibility/README.md @@ -0,0 +1,50 @@ +Start screen visibility sample +============================== + +This sample shows how to get information about monitors that are displaying Windows Store apps or the Start screen. It also demonstrates how to receive notifications when the state of a monitor changes or when the visibility of the Start screen changes. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. + +This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**IAppVisibility**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119) + +[**IAppVisibilityEvents**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj554120) + +[**MONITOR\_APP\_VISIBILITY**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj152046) + +Related technologies +-------------------- + +[**IAppVisibility**](http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the solution (.sln) file titled AppVisibilitySample.sln from Visual Studio Professional 2012, Visual Studio 2013, or a later version (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. + +**Warning** This sample requires Visual Studio Professional 2012, Visual Studio 2013, or later versions of Visual Studio (any SKU) and doesn't compile in Microsoft Visual Studio Express 2013 for Windows + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio. (Or select the corresponding options from the **Debug** menu.) When the app is running, switch to the Start screen and back to the desktop. + diff --git a/Samples/AppVisibility/cpp/AppVisibilitySample.cpp b/Samples/AppVisibility/cpp/AppVisibilitySample.cpp new file mode 100644 index 00000000..73cba127 --- /dev/null +++ b/Samples/AppVisibility/cpp/AppVisibilitySample.cpp @@ -0,0 +1,167 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +#include +#include +#include +#include +#include +#include + +// Simple helper function to turn a MONITOR_APP_VISIBILITY enumeration into a string +PCWSTR const _GetMonitorAppVisibilityString(MONITOR_APP_VISIBILITY monitorAppVisibility) +{ + PCWSTR pszAppVisibilityString = nullptr; + switch (monitorAppVisibility) + { + case MAV_NO_APP_VISIBLE: + pszAppVisibilityString = L"no apps visible"; + break; + + case MAV_APP_VISIBLE: + pszAppVisibilityString = L"a visible app"; + break; + + case MAV_UNKNOWN: + __fallthrough; + default: + pszAppVisibilityString = L"unknown"; + break; + } + return pszAppVisibilityString; +} + +// This class will implement the IAppVisibilityEvents interface and will receive notifications +// from the AppVisibility COM object. +class CAppVisibilityNotificationSubscriber : + public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags, + IAppVisibilityEvents> +{ +public: + CAppVisibilityNotificationSubscriber(); + + // AppVisibilityOnMonitorChanged will be called when applications appear or disappear on a monitor + IFACEMETHODIMP AppVisibilityOnMonitorChanged(_In_ HMONITOR hMonitor, + MONITOR_APP_VISIBILITY previousAppVisibility, + MONITOR_APP_VISIBILITY currentAppVisibility); + + // LauncherVisibilityChange will be called whenever the Start menu becomes visible or hidden + IFACEMETHODIMP LauncherVisibilityChange(BOOL currentVisibleState); + +private: + ~CAppVisibilityNotificationSubscriber(); + + // This variable will be used to trigger this program's message loop + // to exit. The variable will be incremented when the launcher becomes visible. + // When the launcher becomes visible five times, the program will exit. + unsigned int _cLauncherChanges; + +}; + +CAppVisibilityNotificationSubscriber::CAppVisibilityNotificationSubscriber() : _cLauncherChanges(0) +{ +} + +CAppVisibilityNotificationSubscriber::~CAppVisibilityNotificationSubscriber() +{ +} + +// Implementation of IAppVisibilityEvents +IFACEMETHODIMP CAppVisibilityNotificationSubscriber::AppVisibilityOnMonitorChanged(_In_ HMONITOR hMonitor, + MONITOR_APP_VISIBILITY previousAppVisibility, + MONITOR_APP_VISIBILITY currentAppVisibility) +{ + wprintf_s(L"Monitor %p previously had %s and now has %s\r\n", + hMonitor, + _GetMonitorAppVisibilityString(previousAppVisibility), + _GetMonitorAppVisibilityString(currentAppVisibility)); + return S_OK; +} + +IFACEMETHODIMP CAppVisibilityNotificationSubscriber::LauncherVisibilityChange(BOOL currentVisibleState) +{ + wprintf_s(L"The Start menu is now %s\r\n", currentVisibleState ? L"visible" : L"not visible"); + if (currentVisibleState) + { + _cLauncherChanges++; + if (_cLauncherChanges == 5) + { + PostQuitMessage(0); + } + } + return S_OK; +} + +BOOL CALLBACK DisplayMonitorEnumProc(_In_ HMONITOR hMonitor, + _In_ HDC /*hdcMonitor*/, + _In_ LPRECT /*lprcMonitor*/, + _In_ LPARAM dwData) +{ + IAppVisibility *pAppVisibility = reinterpret_cast(dwData); + + MONITOR_APP_VISIBILITY monitorAppVisibility; + HRESULT hr = pAppVisibility->GetAppVisibilityOnMonitor(hMonitor, &monitorAppVisibility); + if (SUCCEEDED(hr)) + { + wprintf_s(L"\tMonitor %p has %s\r\n", hMonitor, _GetMonitorAppVisibilityString(monitorAppVisibility)); + } + return TRUE; +} + +int __cdecl wmain() +{ + wprintf_s(L"Toggle Start menu visibility 5 times to exit\r\n"); + + // Initialization of COM is required to use the AppVisibility (CLSID_AppVisibility) object + HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(hr)) + { + // Create the App Visibility component + Microsoft::WRL::ComPtr spAppVisibility; + hr = CoCreateInstance(CLSID_AppVisibility, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spAppVisibility)); + if (SUCCEEDED(hr)) + { + // Enumerate the current display devices and display app visibility status + wprintf_s(L"Current app visibility status is:\r\n"); + EnumDisplayMonitors(nullptr, nullptr, DisplayMonitorEnumProc, reinterpret_cast(spAppVisibility.Get())); + wprintf_s(L"\r\n\r\n"); + + // Display the current launcher visibility + BOOL launcherVisibility; + if (SUCCEEDED(spAppVisibility->IsLauncherVisible(&launcherVisibility))) + { + wprintf_s(L"The Start menu is currently %s\r\n", launcherVisibility ? L"visible" : L"not visible"); + } + + // Create an object that implements IAppVisibilityEvents that will receive + // callbacks when either app visibility or Start menu visibility changes. + Microsoft::WRL::ComPtr spSubscriber = Microsoft::WRL::Details::Make(); + + // Advise to receive change notifications from the AppVisibility object + // NOTE: There must be a reference held on the AppVisibility object in order to continue + // NOTE: receiving notifications on the implementation of the IAppVisibilityEvents object + DWORD dwCookie; + hr = spAppVisibility->Advise(spSubscriber.Get(), &dwCookie); + if (SUCCEEDED(hr)) + { + // Since the visibility notifications are delivered via COM, a message loop must + // be employed in order to receive notifications + MSG msg; + while (GetMessage(&msg, nullptr, 0, 0)) + { + DispatchMessage(&msg); + } + + // Unadvise from the AppVisibility component to stop receiving notifications + spAppVisibility->Unadvise(dwCookie); + } + } + CoUninitialize(); + } + return 0; +} diff --git a/Samples/AppVisibility/cpp/AppVisibilitySample.sln b/Samples/AppVisibility/cpp/AppVisibilitySample.sln new file mode 100644 index 00000000..1a5d7565 --- /dev/null +++ b/Samples/AppVisibility/cpp/AppVisibilitySample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppVisibilitySample", "AppVisibilitySample.vcxproj", "{99AAE228-9918-411F-8509-D60947940800}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99AAE228-9918-411F-8509-D60947940800}.Debug|Win32.ActiveCfg = Debug|Win32 + {99AAE228-9918-411F-8509-D60947940800}.Debug|Win32.Build.0 = Debug|Win32 + {99AAE228-9918-411F-8509-D60947940800}.Release|Win32.ActiveCfg = Release|Win32 + {99AAE228-9918-411F-8509-D60947940800}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppVisibility/cpp/AppVisibilitySample.vcxproj b/Samples/AppVisibility/cpp/AppVisibilitySample.vcxproj new file mode 100644 index 00000000..a4a11ca8 --- /dev/null +++ b/Samples/AppVisibility/cpp/AppVisibilitySample.vcxproj @@ -0,0 +1,75 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {99AAE228-9918-411F-8509-D60947940800} + AppVisibilitySample + + + + Application + true + v110 + MultiByte + + + Application + false + v110 + true + MultiByte + + + + + + + + + + + + + + + Level4 + Disabled + true + + + true + + + + + Level4 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingCreateAppx/README.md b/Samples/AppxPackingCreateAppx/README.md new file mode 100644 index 00000000..2f6594b1 --- /dev/null +++ b/Samples/AppxPackingCreateAppx/README.md @@ -0,0 +1,93 @@ +Create app package sample +========================= + +This sample shows you how to create an app package by using the app [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766). + +Users acquire your app as an app package. Windows uses the information in an app package to install the app on a per-user basis, and ensure that all traces of the app are gone from the device after all users who installed the app uninstall it. Each package consists of the files that constitute the app, along with a package manifest file that describes the app to Windows. + +The sample covers the following tasks: + +- Use [**IAppxFactory::CreatePackageWriter**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446679) to create a package writer +- Use [**IAppxPackageWriter::AddPayloadFile**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446763) to add the payload files to the package +- Create an input stream and use [**IAppxPackageWriter::Close**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446764) to write the manifest at the end of the package + +**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU); it doesn't compile with Microsoft Visual Studio Express 2013 for Windows. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +**Sample** + +[Extract app package contents sample](http://go.microsoft.com/fwlink/p/?linkid=106455) + +**Tasks** + +[How to create a package](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446616) + +**Concepts** + +[App packages and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh464929) + +**Reference** + +[**IAppxFactory::CreatePackageWriter**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446679) + +[**IAppxPackageWriter**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446762) + +Related technologies +-------------------- + +[App packaging and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446593) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +### From the Command window + +1. Open a Command window. + +2. Go to the directory where you downloaded the CreateAppx sample. + +3. Run the following command: + + **msbuild CreateAppx.sln** + +### From Visual Studio + +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. + +2. Go to the directory where you downloaded the CreateAppx sample and double-click its Microsoft Visual Studio Solution (.sln) file. + +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution**. + +Run the sample +-------------- + +1. Open a Command window. + +2. Go to the CreateAppx\\Data directory. + +3. Run the following command (where \ is "..\\debug\\CreateAppx" or "..\\release\\CreateAppx"): + + **\\\CreateAppx** + + This command creates an app package named HelloWorld.appx from the contents of the CreateAppx\\Data directory. + + diff --git a/Samples/AppxPackingCreateAppx/cpp/CreateAppx.cpp b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.cpp new file mode 100644 index 00000000..ece7b6dc --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.cpp @@ -0,0 +1,266 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx packaging APIs to produce +// an Appx package from a list of files on disk. +// +// For the sake of simplicity, the list of files to be packaged is hard coded +// in this sample. A fully functional application might read its list of +// files from user input, or even generate content dynamically. + +#include +#include +#include +#include + +#include // For Appx Packaging APIs + +#include "CreateAppx.h" + +// Path where all input files are stored +const LPCWSTR DataPath = L"Data\\"; + +// The produced Appx package's content consists of these files, with +// corresponding content types and compression options. +const int PayloadFilesCount = 4; +const LPCWSTR PayloadFilesName[PayloadFilesCount] = { + L"AppTile.png", + L"Default.html", + L"images\\smiley.jpg", + L"Error.html", +}; +const LPCWSTR PayloadFilesContentType[PayloadFilesCount] = { + L"image/png", + L"text/html", + L"image/jpeg", + L"text/html", +}; +const APPX_COMPRESSION_OPTION PayloadFilesCompression[PayloadFilesCount] = { + APPX_COMPRESSION_OPTION_NONE, + APPX_COMPRESSION_OPTION_NORMAL, + APPX_COMPRESSION_OPTION_NONE, + APPX_COMPRESSION_OPTION_NORMAL, +}; + +// The Appx package's manifest is read from this file +const LPCWSTR ManifestFileName = L"AppxManifest.xml"; + +// The hash algorithm to be used for the package's block map is SHA2-256 +const LPCWSTR Sha256AlgorithmUri = L"http://www.w3.org/2001/04/xmlenc#sha256"; + +// The produced package will be stored under this file name +const LPCWSTR OutputPackagePath = L"HelloWorld.appx"; + +// +// Function to create a readable IStream over the file whose name is the +// concatenation of the path and fileName parameters. For simplicity, file +// names including path are assumed to be 100 characters or less. A real +// application should be able to handle longer names and allocate the +// necessary buffer dynamically. +// +// Parameters: +// path - Path of the folder containing the file to be opened, ending with a +// slash ('\') character +// fileName - Name, not including path, of the file to be opened +// stream - Output parameter pointing to the created instance of IStream over +// the specified file when this function succeeds. +// +HRESULT GetFileStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream) +{ + HRESULT hr = S_OK; + const int MaxFileNameLength = 100; + WCHAR fullFileName[MaxFileNameLength + 1]; + + // Create full file name by concatenating path and fileName + hr = StringCchCopyW(fullFileName, MaxFileNameLength, path); + if (SUCCEEDED(hr)) + { + hr = StringCchCat(fullFileName, MaxFileNameLength, fileName); + } + + // Create stream for reading the file + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + fullFileName, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + FALSE, // do not create new file + NULL, // no template + stream); + } + return hr; +} + +// +// Function to create an Appx package writer with default settings, given the +// output file name. +// +// Parameters: +// outputFileName - Name including path to the Appx package (.appx file) to be +// created. +// writer - Output parameter pointing to the created instance of +// IAppxPackageWriter when this function succeeds. +// +HRESULT GetPackageWriter( + _In_ LPCWSTR outputFileName, + _Outptr_ IAppxPackageWriter** writer) +{ + HRESULT hr = S_OK; + IStream* outputStream = NULL; + IUri* hashMethod = NULL; + APPX_PACKAGE_SETTINGS packageSettings = {0}; + IAppxFactory* appxFactory = NULL; + + // Create a stream over the output file where the package will be written + hr = SHCreateStreamOnFileEx( + outputFileName, + STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + TRUE, // create file if it does not exist + NULL, // no template + &outputStream); + + // Create default package writer settings, including hash algorithm URI + // and Zip format. + if (SUCCEEDED(hr)) + { + hr = CreateUri( + Sha256AlgorithmUri, + Uri_CREATE_CANONICALIZE, + 0, // reserved parameter + &hashMethod); + } + + if (SUCCEEDED(hr)) + { + packageSettings.forceZip32 = TRUE; + packageSettings.hashMethod = hashMethod; + } + + // Create a new Appx factory + if (SUCCEEDED(hr)) + { + hr = CoCreateInstance( + __uuidof(AppxFactory), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppxFactory), + (LPVOID*)(&appxFactory)); + } + + // Create a new package writer using the factory + if (SUCCEEDED(hr)) + { + hr = appxFactory->CreatePackageWriter( + outputStream, + &packageSettings, + writer); + } + + // Clean up allocated resources + if (appxFactory != NULL) + { + appxFactory->Release(); + appxFactory = NULL; + } + if (hashMethod != NULL) + { + hashMethod->Release(); + hashMethod = NULL; + } + if (outputStream != NULL) + { + outputStream->Release(); + outputStream = NULL; + } + return hr; +} + +// +// Main entry point of the sample +// +int wmain() +{ + wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n"); + wprintf(L"CreateAppx sample\n\n"); + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + + if (SUCCEEDED(hr)) + { + // Create a package writer + IAppxPackageWriter* packageWriter = NULL; + IStream* manifestStream = NULL; + + wprintf(L"\nCreating package writer\n\n"); + + hr = GetPackageWriter(OutputPackagePath, &packageWriter); + + // Add all payload files to the package writer + for (int i = 0; SUCCEEDED(hr) && (i < PayloadFilesCount); i++) + { + IStream* fileStream = NULL; + + wprintf(L"Adding file: %s\n", PayloadFilesName[i]); + + hr = GetFileStream(DataPath, PayloadFilesName[i], &fileStream); + + if (SUCCEEDED(hr)) + { + packageWriter->AddPayloadFile( + PayloadFilesName[i], + PayloadFilesContentType[i], + PayloadFilesCompression[i], + fileStream); + } + + if (fileStream != NULL) + { + fileStream->Release(); + fileStream = NULL; + } + } + + // Add manifest to package and close package writer + if (SUCCEEDED(hr)) + { + wprintf(L"\nClosing package writer and adding AppxManifest.xml as the package manifest\n"); + hr = GetFileStream(DataPath, ManifestFileName, &manifestStream); + } + if (SUCCEEDED(hr)) + { + hr = packageWriter->Close(manifestStream); + } + + // Clean up allocated resources + if (manifestStream != NULL) + { + manifestStream->Release(); + manifestStream = NULL; + } + if (packageWriter != NULL) + { + packageWriter->Release(); + packageWriter = NULL; + } + CoUninitialize(); + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nPackage successfully saved to %s.\n", OutputPackagePath); + } + else + { + wprintf(L"\nPackage creation failed with HRESULT 0x%08X.\n", hr); + } + return SUCCEEDED(hr) ? 0 : 1; +} diff --git a/Samples/AppxPackingCreateAppx/cpp/CreateAppx.h b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.h new file mode 100644 index 00000000..5fd6b957 --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.h @@ -0,0 +1,31 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx packaging APIs to produce +// an Appx package from a list of files on disk. + +#pragma once + +// +// Function to create a readable IStream over the file whose name is the +// concatenation of the path and fileName parameters. For simplicity, file +// names including path are assumed to be 100 characters or less. A real +// application should be able to handle longer names and allocate the +// necessary buffer dynamically. +// +HRESULT GetFileStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream); + +// +// Function to create an Appx package writer with default settings, given the +// output file name. +// +HRESULT GetPackageWriter( + _In_ LPCWSTR outputFileName, + _Outptr_ IAppxPackageWriter** writer); diff --git a/Samples/AppxPackingCreateAppx/cpp/CreateAppx.sln b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.sln new file mode 100644 index 00000000..c72b0eb4 --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CreateAppx", "CreateAppx.vcxproj", "{EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Debug|Win32.ActiveCfg = Debug|Win32 + {EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Debug|Win32.Build.0 = Debug|Win32 + {EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Release|Win32.ActiveCfg = Release|Win32 + {EA7812FB-A528-41CC-96D8-AE3BA89ACA4C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppxPackingCreateAppx/cpp/CreateAppx.vcxproj b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.vcxproj new file mode 100644 index 00000000..0fcc6006 --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/CreateAppx.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {EA7812FB-A528-41CC-96D8-AE3BA89ACA4C} + CreateAppx + Win32Proj + + + + Application + v110 + false + Unicode + true + + + Application + v110 + false + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.40602.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + true + + + urlmon.lib;shlwapi.lib;%(AdditionalDependencies) + true + Console + false + + MachineX86 + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level4 + true + ProgramDatabase + + + urlmon.lib;shlwapi.lib;%(AdditionalDependencies) + true + Console + true + true + false + + MachineX86 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingCreateAppx/cpp/Data/AppTile.png b/Samples/AppxPackingCreateAppx/cpp/Data/AppTile.png new file mode 100644 index 0000000000000000000000000000000000000000..1efdcfd94c07fd5221a4f6fffee5330b6d4001af GIT binary patch literal 1023 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1C&WbK~#8N?V3++ z^B@q#dyp)9nyz}5E^?MiIZBkHI5)_m%A%?iskO}?0|uLChG2c)i@Iqva^S~%Gr;)e zc6jAqCV`jCIEM8E2n#S4VG&lHL`-E-SyWc@icA~QhO{AV2)KZ-2&+!Ypt7heDyz8* znh$`RQXmfy7Gc#%np75*MP;!X0xlpd!m5)ps4Oar%4+U{<^$lS6vzX+fOS9rx}V4A zdsIZ3Vf6%v!+JYC+?jQ!ufzLy=YDnlegl@PpIat{%&>nPmYv?$=e4JvQWhE}P7PPq zQ0bJEd?@V|%kaq$vTfY>K12kZFb{c6z?T7_0sR*=h_;h&FDkBGoh51D^f z-Mwnt5?Ik8O>3z0amYold35Lku#Ax1=UaR~A6VrH@Ku8q6wNup(rK0WhGQ;NQf$3KhCAenJ0$`2#JCeLStz}Zk z3^Oy|(LSrF0Ozmd-Xd`u7My1GHhFYBgax>Sun4P8uAs80EGi2vUgGhzA#F$-ZtL#2 z=cH#Jq`f|vIq1#~ZrIICW^y4cAZ3)a!W8IdE9IKybmfK;qAjV0mX**Y-SzW0RR(NGN=d}nc-G6If zL$mC|9L5EFbVHxc{`+e$B%!X9f2XJbDJT#uQv}=!Gtqx~&NAG|xAGT!&ug!Hn4R1UQIvTljr@QxB2iTQDT2)C{=@w3_oMo=n zyK65fCG2tZ*T?wck#P;!l@fuKd`ME}`Lf!mEVFxX+L=?vnUV$8l@ft9l~K2YJEi;v zIqRl(4{qVJ1M>RJ!Ja$Xl}g6=#VfnJv)q46^sDo>fm?Exg%xRJM$+@jK1&+bR7UOE z*nQUc&Gw_%HdtHEC{T9TXE0#_3r|>tm6xzlvr}1A7L|p%Mm(N2qz!39aa*Aeqz!39 z+7NY(csy-L8`6g2wn86B8`6ffA?h0Oc-oLQqz%Pwg+7orqz!39)HUMqv>|Os8;aWs teIRW}8`6fTYsBMeL)wrw6t@-nz&}IZQdGKS>52dV002ovPDHLkV1n04;5h&Q literal 0 HcmV?d00001 diff --git a/Samples/AppxPackingCreateAppx/cpp/Data/AppxManifest.xml b/Samples/AppxPackingCreateAppx/cpp/Data/AppxManifest.xml new file mode 100644 index 00000000..e49eb09c --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/Data/AppxManifest.xml @@ -0,0 +1,42 @@ + + + + + + + HelloWorld + Sample package containing a "Hello World!" application + AppTile.png + Microsoft + + + + + + + + + + + + + + + + + + 6.2.1 + 6.2.1 + + diff --git a/Samples/AppxPackingCreateAppx/cpp/Data/Default.html b/Samples/AppxPackingCreateAppx/cpp/Data/Default.html new file mode 100644 index 00000000..e4c1861f --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/Data/Default.html @@ -0,0 +1,8 @@ + + + +Hello World + +

Hello world!

+ + diff --git a/Samples/AppxPackingCreateAppx/cpp/Data/Error.html b/Samples/AppxPackingCreateAppx/cpp/Data/Error.html new file mode 100644 index 00000000..eaf691f6 --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/Data/Error.html @@ -0,0 +1 @@ +Error! \ No newline at end of file diff --git a/Samples/AppxPackingCreateAppx/cpp/Data/images/smiley.jpg b/Samples/AppxPackingCreateAppx/cpp/Data/images/smiley.jpg new file mode 100644 index 0000000000000000000000000000000000000000..afc0c2b1046a0c09f90628d27cc2ed742b68bf0a GIT binary patch literal 8052 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 literal 0 HcmV?d00001 diff --git a/Samples/AppxPackingCreateAppx/cpp/readme.txt b/Samples/AppxPackingCreateAppx/cpp/readme.txt new file mode 100644 index 00000000..37a86d21 --- /dev/null +++ b/Samples/AppxPackingCreateAppx/cpp/readme.txt @@ -0,0 +1,72 @@ + +Appx Package Creation Sample +============================ + + This sample demonstrates how to use Appx packaging APIs to produce an Appx package from a collection of files on disk. + + The package created using data files supplied with this sample is a valid Windows Modern Application. It can be installed in Windows 8 or above if it is signed with a valid developer test certificate. + + +Prerequisites +============= + + This sample requires Windows 8 or higher, and an installation of Visual Studio 2012 Ultimate. + + +Sample Language Implementations +=============================== + + This sample is available in the following language implementations: + + C++ + + +Files +===== + + CreateAppx.cpp - main entry point for the sample application + + CreateAppx.h - main header file + + CreateAppx.vcxproj - build configuration for this sample + + CreateAppx.sln - Visual Studio 2012 Solution file for this sample + + Data\AppxManifest.xml - A sample Appx package manifest for the package to be produced + + Data\AppTile.png + Data\Default.html + Data\Error.html + Data\images\smiley.jpg - Sample data (payload) files for the package to be produced + + +To build the sample using the command prompt: +============================================= + + 1. Open the Command Prompt window and navigate to the directory containing CreateAppx.vcxproj + + 2. Type: msbuild CreateAppx.vcxproj + + +To build the sample using Visual Studio 2012 Ultimate (preferred method): +========================================================================= + + 1. Open File Explorer and navigate to the directory containing CreateAppx.vcxproj. + + 2. Double-click the icon for the CreateAppx.vcxproj file to open the file in Visual Studio. + + 3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + + +To run the sample: +================== + + 1. Open a command prompt window and navigate to the directory containing the Data folder for this sample. + + 2. Type the command: + + \CreateAppx.exe + + where is the full or relative path to where CreateAppx.exe is built. If CreateAppx.exe is built using Visual Studio, then is usually "Debug" or "Release" depending on the configuration used. + + 3. When the application exits successfully, an Appx package named "HelloWorld.appx" should be created. diff --git a/Samples/AppxPackingCreateBundle/README.md b/Samples/AppxPackingCreateBundle/README.md new file mode 100644 index 00000000..88357064 --- /dev/null +++ b/Samples/AppxPackingCreateBundle/README.md @@ -0,0 +1,43 @@ +Create app bundle sample +======================== + +This sample shows you how to create an app bundle using the [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766). + +The sample covers these tasks: + +- Use [**IAppxBundleFactory::CreateBundleWriter**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280280) to create a bundle writer +- Use [**IAppxBundleWriter::AddPayloadPackage**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280303) to add the payload packages to the bundle +- Create an input stream and use [**IAppxBundleWriter::Close**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280304) to flush the stream + +Related topics +-------------- + +**Reference** + +[**IAppxBundleFactory::CreateBundleWriter**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280280) + +[**IAppxBundleWriter**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280302) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/AppxPackingCreateBundle/cpp/CreateBundle.cpp b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.cpp new file mode 100644 index 00000000..8c750928 --- /dev/null +++ b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.cpp @@ -0,0 +1,209 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx Bundle APIs to produce +// an Appx Bundle from a list of app packages and resource packages on disk. +// +// For simplicity, the list of packages to be bundled is hard coded in this +// sample. A fully functional application might get its input from other +// sources. + +#include +#include +#include +#include + +#include // For Appx Bundle APIs + +#include "CreateBundle.h" + +// Path where all input files are stored +const LPCWSTR DataPath = L"Data\\"; + +// The produced bundle's content consists of these files taken from the data folder +const int PayloadPackagesCount = 2; +const LPCWSTR PayloadPackagesName[PayloadPackagesCount] = { + L"MainAppPackage.appx", + L"ResourcePackage.lang-de.appx" +}; + +// The produced package will be stored under this file name +const LPCWSTR OutputBundlePath = L"sample.appxbundle"; + +// +// Function to create a readable IStream over the file whose name is the +// concatenation of the path and fileName parameters. For simplicity, file +// names including path are assumed to be 100 characters or less. A real +// application should be able to handle longer names and allocate the +// necessary buffer dynamically. +// +// Parameters: +// path - Path of the folder containing the file to be opened, ending with a +// slash ('\') character +// fileName - Name, not including path, of the file to be opened +// stream - Output parameter pointing to the created instance of IStream over +// the specified file when this function succeeds. +// +HRESULT GetFileStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream) +{ + HRESULT hr = S_OK; + const int MaxFileNameLength = 100; + WCHAR fullFileName[MaxFileNameLength + 1]; + + // Create full file name by concatenating path and fileName + hr = StringCchCopyW(fullFileName, MaxFileNameLength, path); + if (SUCCEEDED(hr)) + { + hr = StringCchCat(fullFileName, MaxFileNameLength, fileName); + } + + // Create stream for reading the file + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + fullFileName, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + FALSE, // do not create new file + NULL, // no template + stream); + } + return hr; +} + +// +// Function to create an Appx Bundle writer with default settings, given the +// output file name. +// +// Parameters: +// outputFileName - Name including path to the bundle (.appxbundle file) to +// be created. +// writer - Output parameter pointing to the created instance of +// IAppxBundleWriter when this function succeeds. +// +HRESULT GetBundleWriter( + _In_ LPCWSTR outputFileName, + _Outptr_ IAppxBundleWriter** writer) +{ + HRESULT hr = S_OK; + IStream* outputStream = NULL; + IAppxBundleFactory* appxBundleFactory = NULL; + + // Create a stream over the output file where the bundle will be written + hr = SHCreateStreamOnFileEx( + outputFileName, + STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + TRUE, // create file if it does not exist + NULL, // no template + &outputStream); + + // Create a new Appx Bundle factory + if (SUCCEEDED(hr)) + { + hr = CoCreateInstance( + __uuidof(AppxBundleFactory), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppxBundleFactory), + (LPVOID*)(&appxBundleFactory)); + } + + // Create a new bundle writer using the factory + if (SUCCEEDED(hr)) + { + hr = appxBundleFactory->CreateBundleWriter( + outputStream, + 0, // by specifying 0, the bundle will have an automatically + // generated version number based on the current time + writer); + } + + // Clean up allocated resources + if (appxBundleFactory != NULL) + { + appxBundleFactory->Release(); + appxBundleFactory = NULL; + } + if (outputStream != NULL) + { + outputStream->Release(); + outputStream = NULL; + } + return hr; +} + +// +// Main entry point of the sample +// +int wmain() +{ + wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n"); + wprintf(L"CreateBundle sample\n\n"); + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + + if (SUCCEEDED(hr)) + { + // Create a bundle writer object + IAppxBundleWriter* bundleWriter = NULL; + + wprintf(L"\nCreating bundle writer\n\n"); + + hr = GetBundleWriter(OutputBundlePath, &bundleWriter); + + // Add all payload packages to the package writer + for (int i = 0; SUCCEEDED(hr) && (i < PayloadPackagesCount); i++) + { + IStream* payloadPackageStream = NULL; + + wprintf(L"Adding payload package: %s\n", PayloadPackagesName[i]); + + hr = GetFileStream(DataPath, PayloadPackagesName[i], &payloadPackageStream); + + if (SUCCEEDED(hr)) + { + bundleWriter->AddPayloadPackage( + PayloadPackagesName[i], + payloadPackageStream); + } + + if (payloadPackageStream != NULL) + { + payloadPackageStream->Release(); + payloadPackageStream = NULL; + } + } + + // Close the bundle writer to flush the output stream + if (SUCCEEDED(hr)) + { + hr = bundleWriter->Close(); + } + + // Clean up allocated resources + if (bundleWriter != NULL) + { + bundleWriter->Release(); + bundleWriter = NULL; + } + CoUninitialize(); + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nBundle successfully saved to %s.\n", OutputBundlePath); + } + else + { + wprintf(L"\nBundle creation failed with HRESULT 0x%08X.\n", hr); + } + return SUCCEEDED(hr) ? 0 : 1; +} diff --git a/Samples/AppxPackingCreateBundle/cpp/CreateBundle.h b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.h new file mode 100644 index 00000000..878f1ca7 --- /dev/null +++ b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.h @@ -0,0 +1,31 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx Bundle APIs to produce +// an Appx Bundle from a list of app packages and resource packages on disk. + +#pragma once + +// +// Function to create a readable IStream over the file whose name is the +// concatenation of the path and fileName parameters. For simplicity, file +// names including path are assumed to be 100 characters or less. A real +// application should be able to handle longer names and allocate the +// necessary buffer dynamically. +// +HRESULT GetFileStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream); + +// +// Function to create an Appx Bundle writer with default settings, given the +// output file name. +// +HRESULT GetBundleWriter( + _In_ LPCWSTR outputFileName, + _Outptr_ IAppxBundleWriter** writer); diff --git a/Samples/AppxPackingCreateBundle/cpp/CreateBundle.sln b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.sln new file mode 100644 index 00000000..78b97fe4 --- /dev/null +++ b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CreateBundle", "CreateBundle.vcxproj", "{C6FF9AF7-D75B-4BF7-AA7B-78AA33906FED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C6FF9AF7-D75B-4BF7-AA7B-78AA33906FED}.Debug|Win32.ActiveCfg = Debug|Win32 + {C6FF9AF7-D75B-4BF7-AA7B-78AA33906FED}.Debug|Win32.Build.0 = Debug|Win32 + {C6FF9AF7-D75B-4BF7-AA7B-78AA33906FED}.Release|Win32.ActiveCfg = Release|Win32 + {C6FF9AF7-D75B-4BF7-AA7B-78AA33906FED}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppxPackingCreateBundle/cpp/CreateBundle.vcxproj b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.vcxproj new file mode 100644 index 00000000..abfaa189 --- /dev/null +++ b/Samples/AppxPackingCreateBundle/cpp/CreateBundle.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {C6FF9AF7-D75B-4BF7-AA7B-78AA33906FED} + CreateBundle + Win32Proj + + + + Application + v110 + false + Unicode + true + + + Application + v110 + false + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.40602.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + true + + + urlmon.lib;shlwapi.lib;%(AdditionalDependencies) + true + Console + false + + MachineX86 + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level4 + true + ProgramDatabase + + + urlmon.lib;shlwapi.lib;%(AdditionalDependencies) + true + Console + true + true + false + + MachineX86 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingCreateBundle/cpp/Data/MainAppPackage.appx b/Samples/AppxPackingCreateBundle/cpp/Data/MainAppPackage.appx new file mode 100644 index 0000000000000000000000000000000000000000..5785928347537fac63d98ad227da5c35b6956ed9 GIT binary patch literal 11953 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 literal 0 HcmV?d00001 diff --git a/Samples/AppxPackingCreateBundle/cpp/readme.txt b/Samples/AppxPackingCreateBundle/cpp/readme.txt new file mode 100644 index 00000000..651a03cb --- /dev/null +++ b/Samples/AppxPackingCreateBundle/cpp/readme.txt @@ -0,0 +1,68 @@ + +Appx Bundle Creation Sample +=========================== + + This sample demonstrates how to use Appx Bundle APIs to produce an Appx Bundle from a collection of packages on disk. + + The bundle created using data packages supplied with this sample is a valid Windows Modern Application Bundle. It can be installed in Windows 8.1 or above if it is signed with a valid developer test certificate. + + +Prerequisites +============= + + This sample requires Windows 8.1 or higher, and an installation of Visual Studio 2012 Ultimate. + + +Sample Language Implementations +=============================== + + This sample is available in the following language implementations: + + C++ + + +Files +===== + + CreateBundle.cpp - main entry point for the sample application + + CreateBundle.h - main header file + + CreateBundle.vcxproj - build configuration for this sample + + CreateBundle.sln - Visual Studio 2012 Solution file for this sample + + Data\MainAppPackage.appx + Data\ResourcePackage.lang-de.appx - Sample data (payload) packages for the bundle to be produced + + +To build the sample using the command prompt: +============================================= + + 1. Open the Command Prompt window and navigate to the directory containing CreateBundle.vcxproj + + 2. Type: msbuild CreateBundle.vcxproj + + +To build the sample using Visual Studio 2012 Ultimate (preferred method): +========================================================================= + + 1. Open File Explorer and navigate to the directory containing CreateBundle.vcxproj. + + 2. Double-click the icon for the CreateBundle.vcxproj file to open the file in Visual Studio. + + 3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + + +To run the sample: +================== + + 1. Open a command prompt window and navigate to the directory containing the Data folder for this sample. + + 2. Type the command: + + \CreateBundle.exe + + where is the full or relative path to where CreateBundle.exe is built. If CreateBundle.exe is built using Visual Studio, then is usually "Debug" or "Release" depending on the configuration used. + + 3. When the application exits successfully, an Appx Bundle named "sample.appxbundle" should be created. diff --git a/Samples/AppxPackingDescribeAppx/README.md b/Samples/AppxPackingDescribeAppx/README.md new file mode 100644 index 00000000..1b41bc41 --- /dev/null +++ b/Samples/AppxPackingDescribeAppx/README.md @@ -0,0 +1,95 @@ +Query app package and app manifest sample +========================================= + +This sample shows how to query info about an app package using the app [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766). + +Users acquire your app as an app package. Windows uses the information in an app package to install the app on a per-user basis, and ensure that all traces of the app are gone from the device after all users who installed the app uninstall it. Each package consists of the files that constitute the app, along with a package manifest file that describes the app to Windows. + +The sample covers the following tasks: + +- Use [**IAppxFactory::CreatePackageReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446677) to create a package manifest reader +- Use [**IAppxManifestReader::GetPackageId**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446745) to get an [**IAppxManifestPackageId**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446717) to read package identity info +- Use [**IAppxManifestReader::GetProperties**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446748) to get an [**IAppxManifestProperties**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446731) to read package properties + +The sample covers this new task for Windows 8.1: + +- Use [**IAppxManifestReader2::GetQualifiedResources**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280313) to get [**IAppxManifestQualifiedResourcesEnumerator**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280306) to iterate through all qualified resources defined in the manifest, not just language resources. Then, use [**IAppxManifestQualifiedResource**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280305) to get info about each resource. + +**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU); it doesn't compile with Microsoft Visual Studio Express 2013 for Windows. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +**Tasks** + +[Quickstart: Read app package manifest info](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446622) + +**Concepts** + +[App packages and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh464929) + +**Reference** + +[**IAppxBlockMapReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446651) + +[**IAppxManifestReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446737) + +[**IAppxPackageReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446756) + +Related technologies +-------------------- + +[App packaging and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446593) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +### From the Command window + +1. Open a Command window. + +2. Go to the directory where you downloaded the DescribeAppx sample. + +3. Run the following command: + + **msbuild DescribeAppx.sln** + +### From Visual Studio + +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. + +2. Go to the directory where you downloaded the DescribeAppx sample and double-click its Microsoft Visual Studio Solution (.sln) file. + +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution**. + +Run the sample +-------------- + +1. Open a Command window. + +2. Go to the directory that contains DescribeAppx.exe. + +3. Run the following command: + + **DescribeAppx** *appPackage***.appx** + + For testing purposes, you can specify Data\\SamplePackage.appx as the package. + + diff --git a/Samples/AppxPackingDescribeAppx/cpp/Data/SamplePackage.appx b/Samples/AppxPackingDescribeAppx/cpp/Data/SamplePackage.appx new file mode 100644 index 0000000000000000000000000000000000000000..befe0db788238303c8b263e1b00f3821baf14642 GIT binary patch literal 59971 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 VfcwCUcG`5cI2KG2HhBes{vY|JBV7Oh literal 0 HcmV?d00001 diff --git a/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.cpp b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.cpp new file mode 100644 index 00000000..296d9e28 --- /dev/null +++ b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.cpp @@ -0,0 +1,620 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx manifest and block map +// APIs to read metadata from an Appx package. + +#include +#include +#include +#include + +#include // For Appx Packaging APIs + +#include "DescribeAppx.h" + +// +// Function to read a subset of attributes from the manifest element. +// +// Parameters: +// packageId - Instance of IAppxManifestPackageId obtained from a package +// manfest using the IAppxManifestReader::GetPackageId method. +// +HRESULT ReadManifestPackageId( + _In_ IAppxManifestPackageId* packageId) +{ + HRESULT hr = S_OK; + LPWSTR packageFullName = NULL; + LPWSTR packageName = NULL; + UINT64 packageVersion = 0; + + hr = packageId->GetPackageFullName(&packageFullName); + + if (SUCCEEDED(hr)) + { + hr = packageId->GetName(&packageName); + } + if (SUCCEEDED(hr)) + { + hr = packageId->GetVersion(&packageVersion); + } + if (SUCCEEDED(hr)) + { + wprintf(L"Package full name: %s\n", packageFullName); + wprintf(L"Package name: %s\n", packageName); + wprintf(L"Package version: "); + + // Convert version number from 64-bit integer to dot-quad form + for (int bitPosition = 0x30; bitPosition >= 0; bitPosition -= 0x10) + { + UINT64 versionWord = (packageVersion >> bitPosition) & 0xFFFF; + wprintf(L"%llu.", versionWord); + } + wprintf(L"\n"); + } + + // Free all string buffers returned from the manifest API + CoTaskMemFree(packageFullName); + CoTaskMemFree(packageName); + return hr; +} + +// +// Function to read a subset of attributes from the manifest element. +// +// Parameters: +// properties - Instance of IAppxManifestProperties obtained from a package manifest +// using the IAppxManifestReader::GetProperties method. +// +HRESULT ReadManifestProperties( + _In_ IAppxManifestProperties* properties) +{ + HRESULT hr = S_OK; + LPWSTR displayName = NULL; + LPWSTR description = NULL; + + hr = properties->GetStringValue(L"DisplayName", &displayName); + + if (SUCCEEDED(hr)) + { + hr = properties->GetStringValue(L"Description", &description); + } + if (SUCCEEDED(hr)) + { + wprintf(L"Display name: %s\n", displayName); + wprintf(L"Description: %s\n", description); + } + + // Free all string buffers returned from the manifest API + CoTaskMemFree(displayName); + CoTaskMemFree(description); + return hr; +} + +// +// Function to read a subset of attributes from the manifest element. +// +// Parameters: +// applications - Instance of IAppxManifestApplicationsEnumerator obtained from a +// package manifest using the IAppxManifestReader::GetApplications +// method. +// +HRESULT ReadManifestApplications( + _In_ IAppxManifestApplicationsEnumerator* applications) +{ + HRESULT hr = S_OK; + BOOL hasCurrent = FALSE; + UINT32 applicationsCount = 0; + + hr = applications->GetHasCurrent(&hasCurrent); + + while (SUCCEEDED(hr) && hasCurrent) + { + IAppxManifestApplication* application = NULL; + LPWSTR applicationName = NULL; + + hr = applications->GetCurrent(&application); + if (SUCCEEDED(hr)) + { + application->GetStringValue(L"DisplayName", &applicationName); + } + if (SUCCEEDED(hr)) + { + applicationsCount++; + wprintf(L"Application #%u: %s\n", applicationsCount, applicationName); + } + + if (SUCCEEDED(hr)) + { + hr = applications->MoveNext(&hasCurrent); + } + if (application != NULL) + { + application->Release(); + application = NULL; + } + CoTaskMemFree(applicationName); + } + + wprintf(L"Package contains %u application(s)\n", applicationsCount); + return hr; +} + +// +// Function to read attributes from the manifest element. +// +// Parameters: +// resources - Instance of IAppxManifestQualifiedResourcesEnumerator obtained from a +// package manifest using the IAppxManifestReader2::GetQualifiedResources +// method. +// +// Note: IAppxManifestReader2::GetQualifiedResources differs from the +// IAppxManifestReader::GetResources method in that the latter returns an +// IAppxManifestResourcesEnumerator object, which can only enumerate over +// Language attributes specified on a Resource element. To read all the +// attributes on the Resource element we need to use the +// IAppxManifestReader2::GetQualifiedResources method. +// +HRESULT ReadManifestQualifiedResources( + _In_ IAppxManifestQualifiedResourcesEnumerator* resources) +{ + HRESULT hr = S_OK; + BOOL hasCurrent = FALSE; + UINT32 resourcesCount = 0; + + hr = resources->GetHasCurrent(&hasCurrent); + + while (SUCCEEDED(hr) && hasCurrent) + { + IAppxManifestQualifiedResource* resource = NULL; + LPWSTR resourceLanguage = NULL; + LPWSTR dxFeatureLevelString = NULL; + UINT32 resourceScale = 0; + DX_FEATURE_LEVEL dxFeatureLevel = DX_FEATURE_LEVEL_UNSPECIFIED; + + hr = resources->GetCurrent(&resource); + if (SUCCEEDED(hr)) + { + resourcesCount++; + wprintf(L"Resource #%u: ", resourcesCount); + + // Resource elements can only specify one resource qualifier + // value at a time. The code below checks to see which of the + // following three qualifiers is specified - 'Language', 'Scale' + // or 'DXFeatureLevel - and prints its value. + + // Check if 'Language' is specified. + hr = resource->GetLanguage(&resourceLanguage); + if (SUCCEEDED(hr)) + { + if (resourceLanguage != NULL) + { + wprintf(L"Language:%s\n", resourceLanguage); + } + else + { + // Check if 'Scale' is specified. + hr = resource->GetScale(&resourceScale); + if (SUCCEEDED(hr)) + { + if (resourceScale != 0) + { + wprintf(L"Scale:%u\n", resourceScale); + } + else + { + // Check if 'DXFeatureLevel' is specified. + hr = resource->GetDXFeatureLevel(&dxFeatureLevel); + if (SUCCEEDED(hr)) + { + switch(dxFeatureLevel) + { + case DX_FEATURE_LEVEL_9: + dxFeatureLevelString = L"DX_FEATURE_LEVEL_9"; + break; + case DX_FEATURE_LEVEL_10: + dxFeatureLevelString = L"DX_FEATURE_LEVEL_10"; + break; + case DX_FEATURE_LEVEL_11: + dxFeatureLevelString = L"DX_FEATURE_LEVEL_11"; + break; + default: + hr = E_UNEXPECTED; + } + if (SUCCEEDED(hr)) + { + wprintf(L"DXFeatureLevel:%s\n", dxFeatureLevelString); + } + } + } + } + } + } + } + + if (SUCCEEDED(hr)) + { + hr = resources->MoveNext(&hasCurrent); + } + if (resource != NULL) + { + resource->Release(); + resource = NULL; + } + CoTaskMemFree(resourceLanguage); + } + + wprintf(L"Package contains %u resource(s)\n", resourcesCount); + return hr; +} + +// +// Function to print a subset of information from a manifest reader. Many +// methods in the manifest API have similar usage patterns. To reduce +// redundancy, only a representative subset of manifest API methods are shown. +// +// Parameters: +// manifestReader - Instance of IAppxManifestReader created from an Appx packge +// manifest, containing the manifest data to be read. +// +HRESULT ReadManifest( + _In_ IAppxManifestReader* manifestReader) +{ + HRESULT hr = S_OK; + IAppxManifestPackageId* packageId = NULL; + IAppxManifestProperties* properties = NULL; + IAppxManifestApplicationsEnumerator* applications = NULL; + IAppxManifestReader2* manifestReader2 = NULL; + IAppxManifestQualifiedResourcesEnumerator* resources = NULL; + + wprintf(L"\nReading manifest\n"); + + // Get elements and attributes from the manifest reader + wprintf(L"\nReading element\n"); + hr = manifestReader->GetPackageId(&packageId); + if (SUCCEEDED(hr)) + { + hr = ReadManifestPackageId(packageId); + } + + wprintf(L"\nReading element\n"); + if (SUCCEEDED(hr)) + { + hr = manifestReader->GetProperties(&properties); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifestProperties(properties); + } + + wprintf(L"\nReading elements\n"); + if (SUCCEEDED(hr)) + { + hr = manifestReader->GetApplications(&applications); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifestApplications(applications); + } + + wprintf(L"\nReading elements\n"); + // QueryInterface for the IAppxManifestReader2 interface + if (SUCCEEDED(hr)) + { + hr = manifestReader->QueryInterface(__uuidof(IAppxManifestReader2), (void**)&manifestReader2); + } + if (SUCCEEDED(hr)) + { + hr = manifestReader2->GetQualifiedResources(&resources); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifestQualifiedResources(resources); + } + + // Clean up allocated resources + if (packageId != NULL) + { + packageId->Release(); + packageId = NULL; + } + if (properties != NULL) + { + properties->Release(); + properties = NULL; + } + if (applications != NULL) + { + applications->Release(); + applications = NULL; + } + if (resources != NULL) + { + resources->Release(); + resources = NULL; + } + if (manifestReader2 != NULL) + { + manifestReader2->Release(); + manifestReader2 = NULL; + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nManifest read successfully.\n"); + } + else + { + wprintf(L"\nFailed to read manifest with HRESULT 0x%08X.\n", hr); + } + return hr; +} + +// +// Function to print a subset of information from a block map reader +// +// Parameters: +// blockMapReader - Instance of IAppxBlockMapReader created from an Appx +// block map, containing the block map data to be read. +// +HRESULT ReadBlockMap( + _In_ IAppxBlockMapReader* blockMapReader) +{ + HRESULT hr = S_OK; + IAppxBlockMapFilesEnumerator* blockMapFiles = NULL; + BOOL hasCurrentFile = FALSE; + UINT32 fileCount = 0; + + wprintf(L"\nReading block map\n"); + + // Get an enumerator of all files in the block map and enumerate through + // them all. + hr = blockMapReader->GetFiles(&blockMapFiles); + + if (SUCCEEDED(hr)) + { + hr = blockMapFiles->GetHasCurrent(&hasCurrentFile); + } + while (SUCCEEDED(hr) && hasCurrentFile) + { + IAppxBlockMapFile* file = NULL; + LPWSTR fileName = NULL; + UINT64 uncompressedSize = 0; + UINT64 compressedSize = 0; + UINT32 blockCount = 0; + + IAppxBlockMapBlocksEnumerator* blocks = NULL; + BOOL hasCurrentBlock = FALSE; + + hr = blockMapFiles->GetCurrent(&file); + fileCount++; + + // Get name and uncompressed size from the block map file item + if (SUCCEEDED(hr)) + { + hr = file->GetName(&fileName); + } + if (SUCCEEDED(hr)) + { + hr = file->GetUncompressedSize(&uncompressedSize); + } + + // Get total compressed size of file by iterating through all blocks + // of the file and adding the compressed size of each block + if (SUCCEEDED(hr)) + { + hr = file->GetBlocks(&blocks); + } + if (SUCCEEDED(hr)) + { + hr = blocks->GetHasCurrent(&hasCurrentBlock); + } + while (SUCCEEDED(hr) && hasCurrentBlock) + { + IAppxBlockMapBlock* block = NULL; + UINT32 blockCompressedSize = 0; + + hr = blocks->GetCurrent(&block); + + if (SUCCEEDED(hr)) + { + hr = block->GetCompressedSize(&blockCompressedSize); + compressedSize += blockCompressedSize; + } + + if (SUCCEEDED(hr)) + { + hr = blocks->MoveNext(&hasCurrentBlock); + blockCount++; + } + if (block != NULL) + { + block->Release(); + block = NULL; + } + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nFile #%u\n", fileCount); + wprintf(L"Name: %s\n", fileName); + wprintf(L"Uncompressed size: %llu bytes\n", uncompressedSize); + wprintf(L"Stored in %u block(s)\n", blockCount); + wprintf(L"Compressed size: %llu bytes\n", compressedSize); + } + if (SUCCEEDED(hr)) + { + hr = blockMapFiles->MoveNext(&hasCurrentFile); + } + + // Clean up allocated resources + if (blocks != NULL) + { + blocks->Release(); + blocks = NULL; + } + if (file != NULL) + { + file->Release(); + file = NULL; + } + CoTaskMemFree(fileName); + } + wprintf(L"\nThe block map contains %u file(s).\n", fileCount); + + if (blockMapFiles != NULL) + { + blockMapFiles->Release(); + blockMapFiles = NULL; + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nBlock map read successfully.\n"); + } + else + { + wprintf(L"\nFailed to read block map with HRESULT 0x%08X.\n", hr); + } + return hr; +} + +// +// Function to create an Appx package reader given the input file name. +// +// Parameters: +// inputFileName - Path to the Appx package (.appx file) to be opened. +// reader - Output parameter pointing to the created instance of +// IAppxPackageReader when this function succeeds. +// +HRESULT GetPackageReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxPackageReader** reader) +{ + HRESULT hr = S_OK; + IAppxFactory* appxFactory = NULL; + IStream* inputStream = NULL; + + // Create a new Appx factory + hr = CoCreateInstance( + __uuidof(AppxFactory), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppxFactory), + (LPVOID*)(&appxFactory)); + + // Create a stream over the input Appx package + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + inputFileName, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + FALSE, // do not create new file + NULL, // no template + &inputStream); + } + + // Create a new package reader using the factory. + if (SUCCEEDED(hr)) + { + hr = appxFactory->CreatePackageReader( + inputStream, + reader); + } + + // Clean up allocated resources + if (inputStream != NULL) + { + inputStream->Release(); + inputStream = NULL; + } + if (appxFactory != NULL) + { + appxFactory->Release(); + appxFactory = NULL; + } + return hr; +} + +// +// Main entry point of the sample +// +int wmain( + _In_ int argc, + _In_reads_(argc) wchar_t** argv) +{ + wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n"); + wprintf(L"DescribeAppx sample\n\n"); + + if (argc != 2) + { + wprintf(L"Usage: DescribeAppx.exe inputFile\n"); + wprintf(L" inputFile: Path to the Appx package to read\n"); + return 2; + } + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + + if (SUCCEEDED(hr)) + { + // Create a package reader using the file name given in command line + IAppxPackageReader* packageReader = NULL; + IAppxManifestReader* manifestReader = NULL; + IAppxBlockMapReader* blockMapReader = NULL; + + hr = GetPackageReader(argv[1], &packageReader); + + // Get manifest reader for the package and read from the manifest + if (SUCCEEDED(hr)) + { + hr = packageReader->GetManifest(&manifestReader); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifest(manifestReader); + } + + // Get block map reader for the package and read from the block map + if (SUCCEEDED(hr)) + { + hr = packageReader->GetBlockMap(&blockMapReader); + } + if (SUCCEEDED(hr)) + { + hr = ReadBlockMap(blockMapReader); + } + + // Clean up allocated resources + if (blockMapReader != NULL) + { + blockMapReader->Release(); + blockMapReader = NULL; + } + if (manifestReader != NULL) + { + manifestReader->Release(); + manifestReader = NULL; + } + if (packageReader != NULL) + { + packageReader->Release(); + packageReader = NULL; + } + CoUninitialize(); + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nPackage metadata read successfully.\n"); + } + else + { + wprintf(L"\nFailed to read package metadata with HRESULT 0x%08X.\n", hr); + } + return SUCCEEDED(hr) ? 0 : 1; +} diff --git a/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.h b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.h new file mode 100644 index 00000000..7a852de6 --- /dev/null +++ b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.h @@ -0,0 +1,56 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx package manifest and +// block map APIs to read metadata from an Appx package on disk. + +#pragma once + +// +// Function to read a subset of attributes from the manifest element. +// +HRESULT ReadManifestPackageId( + _In_ IAppxManifestPackageId* packageId); + +// +// Function to read a subset of attributes from the manifest element. +// +HRESULT ReadManifestProperties( + _In_ IAppxManifestProperties* properties); + +// +// Function to read a subset of attributes from the manifest element. +// +HRESULT ReadManifestApplications( + _In_ IAppxManifestApplicationsEnumerator* applications); + +// +// Function to read attributes from the manifest element. +// +HRESULT ReadManifestQualifiedResources( + _In_ IAppxManifestQualifiedResourcesEnumerator* resources); + +// +// Function to print a subset of information from a manifest reader. Many +// methods in the manifest API have similar usage patterns. To reduce +// redundancy, only a representative subset of manifest API methods are shown. +// +HRESULT ReadManifest( + _In_ IAppxManifestReader* manifestReader); + +// +// Function to print a subset of information from a block map reader +// +HRESULT ReadBlockMap( + _In_ IAppxBlockMapReader* blockMapReader); + +// +// Function to create an Appx package reader given the input file name. +// +HRESULT GetPackageReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxPackageReader** reader); diff --git a/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.sln b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.sln new file mode 100644 index 00000000..3eab37a0 --- /dev/null +++ b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DescribeAppx", "DescribeAppx.vcxproj", "{AD1B4804-C6BB-4282-A3CF-3DE43173AB44}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AD1B4804-C6BB-4282-A3CF-3DE43173AB44}.Debug|Win32.ActiveCfg = Debug|Win32 + {AD1B4804-C6BB-4282-A3CF-3DE43173AB44}.Debug|Win32.Build.0 = Debug|Win32 + {AD1B4804-C6BB-4282-A3CF-3DE43173AB44}.Release|Win32.ActiveCfg = Release|Win32 + {AD1B4804-C6BB-4282-A3CF-3DE43173AB44}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.vcxproj b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.vcxproj new file mode 100644 index 00000000..280ed72e --- /dev/null +++ b/Samples/AppxPackingDescribeAppx/cpp/DescribeAppx.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {AD1B4804-C6BB-4282-A3CF-3DE43173AB44} + DescribeAppx + Win32Proj + + + + Application + v120 + false + Unicode + true + + + Application + v120 + false + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.40602.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + true + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + false + + MachineX86 + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level4 + true + ProgramDatabase + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + true + true + false + + MachineX86 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingDescribeAppx/cpp/readme.txt b/Samples/AppxPackingDescribeAppx/cpp/readme.txt new file mode 100644 index 00000000..a447e989 --- /dev/null +++ b/Samples/AppxPackingDescribeAppx/cpp/readme.txt @@ -0,0 +1,63 @@ + +Appx Package Description Sample +=============================== + + This sample demonstrates how to use Appx Manifest and Blockmap APIs to get a description of the Appx package's payload files and manifest attributes. + + +Prerequisites +============= + + This sample requires Windows 8.1 or higher, and an installation of Visual Studio 2012 Ultimate. + + +Sample Language Implementations +=============================== + + This sample is available in the following language implementations: + + C++ + + +Files +===== + + DescribeAppx.cpp - main entry point for the sample application + + DescribeAppx.h - main header file + + DescribeAppx.vcxproj - build configuration for this sample + + DescribeAppx.sln - Visual Studio 2012 Solution file for this sample + + Data\SamplePackage.appx - A sample Appx package containing manifest and block map to be read + + +To build the sample using the command prompt: +============================================= + + 1. Open the Command Prompt window and navigate to the directory containing DescribeAppx.vcxproj + + 2. Type: msbuild DescribeAppx.vcxproj + + +To build the sample using Visual Studio 2012 Ultimate (preferred method): +========================================================================= + + 1. Open File Explorer and navigate to the directory containing DescribeAppx.vcxproj. + + 2. Double-click the icon for the DescribeAppx.vcxproj file to open the file in Visual Studio. + + 3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + + +To run the sample: +================== + + 1. Open a command prompt window and navigate to the directory where DescribeAppx.exe is built. + + 2. Type the command: + + DescribeAppx.exe inputFile + + inputFile: path to an Appx package that can be read, for example "data\SamplePackage.appx" diff --git a/Samples/AppxPackingDescribeBundle/README.md b/Samples/AppxPackingDescribeBundle/README.md new file mode 100644 index 00000000..7f71a103 --- /dev/null +++ b/Samples/AppxPackingDescribeBundle/README.md @@ -0,0 +1,47 @@ +Query app bundle info sample +============================ + +This sample shows how to query info about a bundle package using the [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766). + +The sample covers these tasks: + +- Use [**IAppxBundleFactory::CreateBundleReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280279) to create a bundle reader, and then [**IAppxBundleReader::GetManifest**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280299) to get [**IAppxBundleManifestReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280292) for the bundle manifest reader +- Use [**IAppxBundleManifestReader::GetPackageId**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280293) to get an [**IAppxManifestPackageId**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446717) to read package identity info +- Use [**IAppxBundleManifestReader::GetPackageInfoItems**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280294) to get [**IAppxBundleManifestPackageInfoEnumerator**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280282) to iterate through the list of payload packages that are described in a bundle package manifest. Then, use [**IAppxBundleManifestPackageInfo**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280281) to get info about each package. + +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 +-------------- + +**Reference** + +[**IAppxBundleManifestReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280292) + +[**IAppxBundleReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280296) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/AppxPackingDescribeBundle/cpp/Data/sample.appxbundle b/Samples/AppxPackingDescribeBundle/cpp/Data/sample.appxbundle new file mode 100644 index 0000000000000000000000000000000000000000..5ed41644ff0b9448f67b1f13e779b53d7333d3f5 GIT binary patch literal 18898 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 literal 0 HcmV?d00001 diff --git a/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.cpp b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.cpp new file mode 100644 index 00000000..19c43f0a --- /dev/null +++ b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.cpp @@ -0,0 +1,321 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx Bundle Manifest APIs +// to read metadata from an Appx Bundle on disk. + +#include +#include +#include +#include + +#include // For Appx Bundle APIs + +#include "DescribeBundle.h" + +// +// Function to read a subset of attributes from the identity of either a bundle +// or a payload package in the bundle. +// +// Parameters: +// identity - Instance of IAppxManifestPackageId obtained from the bundle manifest +// using either the IAppxBundleManifestReader::GetPackageId or the +// IAppxBundleManifestPackageInfo::GetPackageId method. +// +HRESULT ReadManifestIdentity( + _In_ IAppxManifestPackageId* identity) +{ + HRESULT hr = S_OK; + LPWSTR packageFullName = NULL; + LPWSTR packageName = NULL; + UINT64 packageVersion = 0; + + hr = identity->GetPackageFullName(&packageFullName); + + if (SUCCEEDED(hr)) + { + hr = identity->GetName(&packageName); + } + if (SUCCEEDED(hr)) + { + hr = identity->GetVersion(&packageVersion); + } + if (SUCCEEDED(hr)) + { + wprintf(L"Full name: %s\n", packageFullName); + wprintf(L"Name: %s\n", packageName); + wprintf(L"Version: "); + + // Convert version number from 64-bit integer to dot-quad form + for (int bitPosition = 0x30; bitPosition >= 0; bitPosition -= 0x10) + { + UINT64 versionWord = (packageVersion >> bitPosition) & 0xFFFF; + wprintf(L"%llu.", versionWord); + } + wprintf(L"\n"); + } + + // Free all string buffers returned from the manifest API + CoTaskMemFree(packageFullName); + CoTaskMemFree(packageName); + return hr; +} + +// +// Function to read a subset of attributes from the bundle manifest's +// element. +// +// Parameters: +// packages - Instance of IAppxBundleManifestPackageInfoEnumerator obtained +// from a bundle manifest using the +// IAppxBundleManifestReader::GetPackageInfoItems method. +// +HRESULT ReadManifestPackages( + _In_ IAppxBundleManifestPackageInfoEnumerator* packages) +{ + HRESULT hr = S_OK; + BOOL hasCurrent = FALSE; + UINT32 packagesCount = 0; + + hr = packages->GetHasCurrent(&hasCurrent); + + while (SUCCEEDED(hr) && hasCurrent) + { + IAppxBundleManifestPackageInfo* packageInfo = NULL; + LPWSTR packageFileName = NULL; + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION; + IAppxManifestPackageId* packageIdentity = NULL; + + hr = packages->GetCurrent(&packageInfo); + if (SUCCEEDED(hr)) + { + hr = packageInfo->GetFileName(&packageFileName); + } + if (SUCCEEDED(hr)) + { + packagesCount++; + wprintf(L"Package #%u: %s\n", packagesCount, packageFileName); + } + + // Read the payload package's type + if (SUCCEEDED(hr)) + { + hr = packageInfo->GetPackageType(&packageType); + } + if (SUCCEEDED(hr)) + { + if (packageType == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) + { + wprintf(L"This is an app package.\n"); + } + else if (packageType == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE) + { + wprintf(L"This is a resource package.\n"); + } + } + + // Read the payload package's identity + if (SUCCEEDED(hr)) + { + hr = packageInfo->GetPackageId(&packageIdentity); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifestIdentity(packageIdentity); + } + wprintf(L"\n"); + + if (SUCCEEDED(hr)) + { + hr = packages->MoveNext(&hasCurrent); + } + if (packageInfo != NULL) + { + packageInfo->Release(); + packageInfo = NULL; + } + if (packageIdentity != NULL) + { + packageIdentity->Release(); + packageIdentity = NULL; + } + CoTaskMemFree(packageFileName); + } + + wprintf(L"The bundle contains %u package(s)\n", packagesCount); + return hr; +} + +// +// Function to print a subset of information from a bundle manifest reader. +// Many methods in the bundle manifest API have similar usage patterns. +// Only a representative subset of API methods are shown here. +// +// Parameters: +// manifestReader - Instance of IAppxBundleManifestReader created from a +// bundle manifest. +// +HRESULT ReadManifest( + _In_ IAppxBundleManifestReader* manifestReader) +{ + HRESULT hr = S_OK; + IAppxManifestPackageId* bundleId = NULL; + IAppxBundleManifestPackageInfoEnumerator* packages = NULL; + + wprintf(L"\nReading element\n"); + hr = manifestReader->GetPackageId(&bundleId); + if (SUCCEEDED(hr)) + { + hr = ReadManifestIdentity(bundleId); + } + + wprintf(L"\nReading element\n"); + if (SUCCEEDED(hr)) + { + hr = manifestReader->GetPackageInfoItems(&packages); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifestPackages(packages); + } + + // Clean up allocated resources + if (bundleId != NULL) + { + bundleId->Release(); + bundleId = NULL; + } + if (packages != NULL) + { + packages->Release(); + packages = NULL; + } + + return hr; +} + +// +// Function to create an Appx Bundle reader given the input file name. +// +// Parameters: +// inputFileName - Path to the Appx Bundle (.appxbundle file) to be opened. +// reader - Output parameter pointing to the created instance of +// IAppxBundleReader when this function succeeds. +// +HRESULT GetBundleReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxBundleReader** reader) +{ + HRESULT hr = S_OK; + IAppxBundleFactory* appxBundleFactory = NULL; + IStream* inputStream = NULL; + + // Create a new Appx bundle factory + hr = CoCreateInstance( + __uuidof(AppxBundleFactory), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppxBundleFactory), + (LPVOID*)(&appxBundleFactory)); + + // Create a stream over the input bundle file + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + inputFileName, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + FALSE, // do not create new file + NULL, // no template + &inputStream); + } + + // Create a new bundle reader using the factory + if (SUCCEEDED(hr)) + { + hr = appxBundleFactory->CreateBundleReader( + inputStream, + reader); + } + + // Clean up allocated resources + if (inputStream != NULL) + { + inputStream->Release(); + inputStream = NULL; + } + if (appxBundleFactory != NULL) + { + appxBundleFactory->Release(); + appxBundleFactory = NULL; + } + return hr; +} + +// +// Main entry point of the sample +// +int wmain( + _In_ int argc, + _In_reads_(argc) wchar_t** argv) +{ + wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n"); + wprintf(L"DescribeBundle sample\n\n"); + + if (argc != 2) + { + wprintf(L"Usage: DescribeBundle.exe inputFile\n"); + wprintf(L" inputFile: Path to the Appx Bundle to read\n"); + return 2; + } + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + + if (SUCCEEDED(hr)) + { + // Create a bundle reader using the file name given in command line + IAppxBundleReader* bundleReader = NULL; + IAppxBundleManifestReader* manifestReader = NULL; + + hr = GetBundleReader(argv[1], &bundleReader); + + wprintf(L"\nReading the bundle manifest\n"); + + // Get manifest reader for the bundle and read from the manifest + if (SUCCEEDED(hr)) + { + hr = bundleReader->GetManifest(&manifestReader); + } + if (SUCCEEDED(hr)) + { + hr = ReadManifest(manifestReader); + } + + // Clean up allocated resources + if (manifestReader != NULL) + { + manifestReader->Release(); + manifestReader = NULL; + } + if (bundleReader != NULL) + { + bundleReader->Release(); + bundleReader = NULL; + } + CoUninitialize(); + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nBundle metadata read successfully.\n"); + } + else + { + wprintf(L"\nFailed to read bundle metadata with HRESULT 0x%08X.\n", hr); + } + return SUCCEEDED(hr) ? 0 : 1; +} diff --git a/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.h b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.h new file mode 100644 index 00000000..7485d445 --- /dev/null +++ b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.h @@ -0,0 +1,40 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx Bundle Manifest APIs +// to read metadata from an Appx Bundle on disk. + +#pragma once + +// +// Function to read a subset of attributes from the identity of either a +// bundle or a payload package in the bundle. +// +HRESULT ReadManifestIdentity( + _In_ IAppxManifestPackageId* identity); + +// +// Function to read a subset of attributes from the bundle manifest's +// element. +// +HRESULT ReadManifestPackages( + _In_ IAppxBundleManifestPackageInfoEnumerator* packages); + +// +// Function to print a subset of information from a bundle manifest reader. +// Many methods in the bundle manifest API have similar usage patterns. +// Only a representative subset of API methods are shown here. +// +HRESULT ReadManifest( + _In_ IAppxBundleManifestReader* manifestReader); + +// +// Function to create an Appx Bundle reader given the input file name. +// +HRESULT GetBundleReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxBundleReader** reader); diff --git a/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.sln b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.sln new file mode 100644 index 00000000..11a613fa --- /dev/null +++ b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DescribeBundle", "DescribeBundle.vcxproj", "{E13F6E2C-9E69-4240-8B5C-5C65109ECA35}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E13F6E2C-9E69-4240-8B5C-5C65109ECA35}.Debug|Win32.ActiveCfg = Debug|Win32 + {E13F6E2C-9E69-4240-8B5C-5C65109ECA35}.Debug|Win32.Build.0 = Debug|Win32 + {E13F6E2C-9E69-4240-8B5C-5C65109ECA35}.Release|Win32.ActiveCfg = Release|Win32 + {E13F6E2C-9E69-4240-8B5C-5C65109ECA35}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.vcxproj b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.vcxproj new file mode 100644 index 00000000..aa1af090 --- /dev/null +++ b/Samples/AppxPackingDescribeBundle/cpp/DescribeBundle.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {E13F6E2C-9E69-4240-8B5C-5C65109ECA35} + DescribeBundle + Win32Proj + + + + Application + v110 + false + Unicode + true + + + Application + v110 + false + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.40602.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + true + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + false + + MachineX86 + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level4 + true + ProgramDatabase + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + true + true + false + + MachineX86 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingDescribeBundle/cpp/readme.txt b/Samples/AppxPackingDescribeBundle/cpp/readme.txt new file mode 100644 index 00000000..1b5eaee9 --- /dev/null +++ b/Samples/AppxPackingDescribeBundle/cpp/readme.txt @@ -0,0 +1,63 @@ + +Appx Bundle Description Sample +============================== + + This sample demonstrates how to use Appx Bundle Manifest APIs to get a description of the Appx Bundle's identity and payload packages. + + +Prerequisites +============= + + This sample requires Windows 8.1 or higher, and an installation of Visual Studio 2012 Ultimate. + + +Sample Language Implementations +=============================== + + This sample is available in the following language implementations: + + C++ + + +Files +===== + + DescribeBundle.cpp - main entry point for the sample application + + DescribeBundle.h - main header file + + DescribeBundle.vcxproj - build configuration for this sample + + DescribeBundle.sln - Visual Studio 2012 Solution file for this sample + + Data\sample.appxbundle - A sample Appx Bundle containing the manifest to be read + + +To build the sample using the command prompt: +============================================= + + 1. Open the Command Prompt window and navigate to the directory containing DescribeBundle.vcxproj + + 2. Type: msbuild DescribeBundle.vcxproj + + +To build the sample using Visual Studio 2012 Ultimate (preferred method): +========================================================================= + + 1. Open File Explorer and navigate to the directory containing DescribeBundle.vcxproj. + + 2. Double-click the icon for the DescribeBundle.vcxproj file to open the file in Visual Studio. + + 3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + + +To run the sample: +================== + + 1. Open a command prompt window and navigate to the directory where DescribeBundle.exe is built. + + 2. Type the command: + + DescribeBundle.exe inputFile + + inputFile: path to an Appx Bundle that can be read, for example "Data\sample.appxbundle" diff --git a/Samples/AppxPackingExtractAppx/README.md b/Samples/AppxPackingExtractAppx/README.md new file mode 100644 index 00000000..8dfb3468 --- /dev/null +++ b/Samples/AppxPackingExtractAppx/README.md @@ -0,0 +1,93 @@ +Extract app package contents sample +=================================== + +This sample demonstrates how to read an app package and extract its contents to disk by using the app [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766). + +Users acquire your app as an app package. Windows uses the information in an app package to install the app on a per-user basis, and ensure that all traces of the app are gone from the device after all users who installed the app uninstall it. Each package consists of the files that constitute the app, along with a package manifest file that describes the app to Windows. + +The sample covers the following tasks: + +- Use [**IAppxFactory::CreatePackageReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446677) to create a package reader +- Use [**IAppxPackageReader::GetFootprintFile**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446758) to get each footprint file +- Use [**IAppxPackageReader::GetPayloadFiles**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446761) to enumerate the payload files + +**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU); it doesn't compile with Microsoft Visual Studio Express 2013 for Windows. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +**Samples** + +[Create app package sample](http://go.microsoft.com/fwlink/p/?linkid=236965) + +**Tasks** + +[Quickstart: Extract app package contents](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446618) + +**Concepts** + +[App packages and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh464929) + +**Reference** + +[**IAppxFactory::CreatePackageReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446677) + +[**IAppxPackageReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446756) + +Related technologies +-------------------- + +[App packaging and deployment](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446593) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +### From the Command window + +1. Open a Command Prompt window. + +2. Go to the directory where you downloaded the ExtractAppx sample. + +3. Run the following command: + + **msbuild ExtractAppx.sln** + +### From Visual Studio + +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. + +2. Go to the directory where you downloaded the ExtractAppx sample and double-click its Microsoft Visual Studio Solution (.sln) file. + +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution**. + +Run the sample +-------------- + +1. Open a Command Prompt window. + +2. Go to the directory that contains ExtractAppx.exe. + +3. Run the following command: + + **ExtractAppx** *appPackage***.appx** *outputFolder* + + For testing purposes, you can specify Data\\HelloWorld.appx as the package. The contents of this package are written to the *outputFolder* directory. + + diff --git a/Samples/AppxPackingExtractAppx/cpp/Data/HelloWorld.appx b/Samples/AppxPackingExtractAppx/cpp/Data/HelloWorld.appx new file mode 100644 index 0000000000000000000000000000000000000000..7259a3a3f9fab731887621b4626c302c69d1a750 GIT binary patch literal 11463 zcmbVy2S8Ix({^ZrRFS5DMCnKsX#x@z=~AV)h=>?4^eQD+q(~PK5Kxc~B1C#8(mM#! zkrsLzw#mPQgPe+Z8nw=W>l}A z+uzp)9#|SngSVjot}nW%o4JEP^sVQGq|>2 zZnZ;^yN3$D_N**wJ9$oO6F$Ayeo{n)qP4H!}o#xso$)0a($ zZfH9e9JqF=Abma7NWVqBn_0E+hk#9&FYXz=VPWpSGm#k;sw^IwTd4@W*e{IDE(-eM z+$v$z4^!D!za_#qJu$12MSL&lSjxW9Y~xq*)YROJvA(ch*+lP{^E32>9O_=yrIcI9CG_#7+a>!BD-Q4@Tw;F7;7m`2nZjRCZ-&f&DVQ?r_556)>+`fz7$ zfZl1M|Iu@|8zR^3-dD6Ruh|Q4R(ULcXewaV=1%brE_uSyEbsHMq2%Gm#VL5W_iDCS zZC;gLMf*4UUKHB~#VB>sv`yvp4vjA`1(VNaR)v?0eeC2`E2)HM5ROlj%ePuNJ1G1; zlrsj1r;g&hnI-QL`2`>$!Al~K$$wGb9zwhtklb~>0*CH6q_1Y9=AW4KwDhbA@g^p2 z#fwM_-*$8bSJ_b_`#qKDoE2&1*=s%W>yOMSClVi+8)=xXv+5Lmv@02{cN7=o+j2b| z@5G_wTGJ({4SlSU;RcQ7k}Z-W}Y{L(?U7f z{z+eRy24bVW(TfaxW2yp7eec>=%DJggh{z`z!`_8 zYB3XK))k0PM>;ZStd z1MqoWabtrW<1_URXx9!8Q97?-$|KVM7@&x0>VWHiYhU2lwg^1noeXm|%gJ|$@|=NT zo!xo_Flj*=Dmo8K9y|%s)1stWS6GcY1Lpa8(fbE(Q2hsP&;nc!?Vj6szVr}#;Q@as z5>rnfB*7f&%`}(k(aHaaze>cqzvuThrh?Ion{QVCiqaZt{3*_Wv6qFYzDbEYlMVgCLRMb?I zl+<+8)HJjJQC_5HprfTf|9<|EbM|vC;7vXNW@Wo_m7R}YKv3wWl(dYj+#Px4hbpRS z>KdAl4ULRVOwG(~pV>XPe*trF_we-c_VIo7CO9NC>}_~Ne8T(0q~s4Nsae@Mxq0~o zgM`v-@=u}8S$lXJO9 zKxBUx>tB-n7r7V#xk!OAAg4T+i-go0C}fP}6gO^NxO`uq(#DmETkr}sI~hHG+zQfbUXu`?bLz3=GfNNTsh@Qex%lSPUQJj*JP+I7!-*Rc0E$U*EJxcd&GI^*v@AXJEe76>A!U~PN4b>^rmhn@FMQZ7cue4Cj2g~L;UiRhGph0x?qjkSNky%UGB!&iHil}@XFJ=Z|Q|r zNH1N(O2?`kqn5FJyt?#8D&)B!@*Tt$f)f|t%0Kl$*qix4(5qpGNTv)-qLVv<1|g;tcLOpuhuS` z!HJq*V|ZIv{TA7vf!=)$DNRpsliFswU(E~kAv|peUrAkN!Kc{Kfw*Ccn|>O$F>fk_5obJOtL|Czx?4;DR4cio8vyp=-MEpUS$`x4d^EfPN zUuP=O5|g}sJIN(cWBICxZFr~ZhQ{3F@GF?i*JV-9;Ag3@LQPRK0+&(i?^{AfMLVsS zz>Jl_K}7HwXwTWY==34}aRNGQJ0D};2EOL+>A8Z$-c8SScg{9#`)P%m97fCxVqJdb z4Bda3D3ca)$|D|tsm>y}cu3L?G19-YjLF*4It=+JRR>~AZXI}B`$EWTLJE54(^Km97h zHMsZNgq?$g#?j`{4zs?BKgksE3G)AR`tS_YOn(NlLr!V6KJC=UDK9wF%velYHrp5Y zs80Gr+@BxZM1G3Yi_^g*8sB&4EXV=B4|AClfI-V3+rZ=^S3Wh)J{9-Be+CL!-g9Uj z1VAFh9qpstH{}6YKY)jh_dS@VE#i?$lWrI{k>uYrF=`Ji)rXe5h{yWdw~U&Mmbw*d z72oV12|e;>AVAeyBR^Gyf}U@~V1N<+f}tsD1H ziy^6l^ttm4EEdv@8l zAPRxuoDpe1Fiu(NhT4i2Wn_hxx&d}a+37~O_z3dk<;CUi56VR%z6HmaCeC@MA(|B+ z^NmV^gkYi|>;lZ(0@*&19nd|G@ojP0XvHTdVL@jgTixKgP4l%tx`;!y z0$jO)dSYL4o&X=8#6YMT-CORAuBzwpT4{Ay2HYJsY!QZSJK$6s55Pqb!e4Ck5a$%g zXKCS(aoPDYjYYRq{gq{{ULV!dkXzlf#$|K8B&NA>m)lfsn0*3oi%(W#1NY{(3isGr z5cK{$a4eL;2cjLRT`|L{A==S=@JoA{n@3kTImv{oekpDusua15%o&fWtkD$-)k+vy z?m!zICmpU^ec@Z z|NM6Wleh^;>wu#nQp5LHb*XT5kgXYK?E^7IS+thV!{jD#-4hZ!@>t1>GM|%3o1YmO zP^-sjfrpq)@)PXkw(_rON%lI_85JtM=uyZ&$uHMg&-A&!@N`yS zni)3nB3d8%Bx8jL`C?z41Euk|%Ozh}3$uTHd zB)c3xfTdrV#7GGVr_eQEcfPYBe;+kNnFTR}^vaSj)kfKFb74EF1hOJA$tl7_TdeV=(OD}6s-?Lvu^CS-yFXN zvD+R_)34ZM=`gG`F_h*Ye5(T_Kw3wQ2SSNAU(Y}=1kN6T<8hAm*z`kPf}Nn+=}dI? z;2~p);)%=0Wof+yJDl?0s#809_9>~sh;+vH*|mBMv4D&-P%>O3HVf0)ftnUZn@s0p zj@q|ht*ZZwDz)Y-F8LVC{8Kco|MqcJ`ir13z8leX>q_QbZW|DT%`V6j@yS;V6ZKee z9DJ`u@a5CGz4UNe_LQ=kRPZASuDP0-PoMbm$?jUB+JjFfISSS)>+n#$};ykg4^>{G_oZLJ&C+bAS;i(wLlqD6imp z7h*e$c0&;5W4UJ_s-;=-k-Sn2B)p`eM$E3UDY(I4V!G9nBdeJyl;Jl2I`94E#BkYP z;5`*xoLpxIl&R^iDPEY6=_!s=U%|}g(#3`W^i>=!KyG!kXi zcrqj^berb7AoF#Qy$8GDXCMYZ%QJrHjFx`Nb_lbg5JuUeeiZq#;**RP!J_pfx-Z^R zoB7@Mko3{XoELdUEetanp^V*t8Iy|vrp)HAi+g>lvj$-%3au##;h+n;Aty6=#ddZ@ zurgDJ+3O?loEY?#>`)Kdq=H@!t=nRpfg6gY@#>Hv@D>9V1kL7$_%$~%H|2*i$Bs>5 zu^(rD>R7nB9b#W)&}<**ZgW|APj5}{Pp=+8GUWxcPy>rQL8VIk{;ESw4E}N$%E$&a zU&5z_T^d-md{d$Kvf`XwWp#LNs&-tF0{o$ErC}*xQ4!N67K_O(+Omtl%+tN%!(f(v zGOdoO3itawr~Par`PO|;vSyx#179;+x-^rFL9gGbv5W>qQ@+hB)&An&n^HXDTwFai zUX_-hZne!?Ixtdx==rH}Vg_gq3}|i`h)25=Io#*L*Oal)s6d9Ffir%d&hWC{wkknP zi}U;IljIxwZDp9#zeLIGEUr)P9bV;fX^_+peWb8Q!;2AgD5v2j4nV5XE7W9SnZA{f$ zk57;mwebdqC@zczv2d&uT7cb%`= z;V|kJYQAZz8ZRlkEq%%pI5H$v=ajM6*;xux5~vwsNI+jR(MegXlX3kv!S~11)JEKu z+>}d%+GL97?_<}`Kv~XL4SVFq?pQ9Letl`l-t-ZpQ-i2^p0V-+W{jDcgp`%KaQt} z6{G9;E{Hx~kHKZE#$1+QNjw8REyC0j>7C9%?_&T%lSORh{5k`z|7=ZMbYq z3sMR7ffx)+2XO03|J+K}Ex7+|*v6Eyzj3(*?$UeOKk@5J>#jL2nMf}V^hL)1=^3a- zoR}eXLZEChFVF8dRxIq!|NVtV4SvluuaO-tJt`B!*)Q;>2(g^JH27l|Cs5rk>b)4d zMY9L#XcB57j$j~BO5ip5S)|`mC*{5 znH5^DONd9(0HSA&H4;%%<@oB~(Xdb|0%qsav@{Kmj8Z%8!)&!n~pZkbV{d$4PP zVF+8Q84`V2^0_kp$gn(4{Off|9mU)jt@;-{Ztbd_i1gcGW*>RvYPzlN{t$rcrz~VJ z!J4G^W;4F7O@+i1=QxZF%}&gj>6A}fH*<%@nC3h%8XA2gEOb4HN>2J!6C2=$JRlBN z0gOcA_^RJzj_^0tjuJU62j|neSF1y*mb8pwv{c@z9K|bK-9n3PlngS5RD(Ye*N}UQ zkvOj^;M2I67c+k zn1S&5LENL?H*#TMXD=}9!=iiD5C0mTU+H#jX*Q94+B<3EO1akePwj~yZE& zfdY|mhyz^RV6v5CX-vZpPrEobG$)~WA1bH=~FXX242b0c1&kM=Fc zsxwZA4bLXNFt-(EgP6|u4 znSL6+-)5VnR&%>w;TT%{jEl?WTMb_ZCTBIYx&Bm6wU_DbD~rho4n3)j%f?!97Kzr{ z7JbN=_xW2c;hI*^$=D(*|7wU1fKvGPhb<^c$ovK!!e|un6dVS)ar|w+0!v&z8r;Ug zLE}ufo}jS7#UCQN6C0mYnjyK)y1k`z?<;vfyyM_nVA}Y~TxY-~0Hc%vYynRmEEv6Y zMA8NJy>iE^Vnq92vnJPBVR2&fF{&9tigZ%u)QQ!q0oCRB`64Mu1A*P=Rh}c7o-)x| z>du$$DXd=PGD1FvnjoH6rD%PT`|P=q?G05GJ@oZcz(n{Q)80QUY9MYZPLB zfzG1Ycnmy=0G)vxkz%W@DEqSgt;1sd6$JkPguh=uaL`X`tQ$^49y)GV7H`i-5%|?a z2#DrO0N~JHgYFr}PE0@Eb52|!$f9M!(|~cqB^Xr4p-Pdms&*mi+`JZk1&jN3SK>@= z^)GAjGLm3W_)Ez|YBj%8OFT^j&JM$urh;4F^F@90B=9^=TK4>;IyIsO8gb&O<$96P zKSS3gvQ?gUwBIzuX^R7|`z;u07{+oe|ER05d8+}3-!Q@#>sS>t$OPomtZ2?XF2FCI zAjfx=4zePIaU!S6Ola9w2p!&L555|vXth9KYFFYK@d`j{jcz?{Dyy5=2gBqcO!FRsP47z$AUBRSVwp(=*P){S#DOA!az$NN~g|UlZ114)dx_o`ij@ ziMnuz40I)qfMgxqXmMKnJ~IDsdV+fq$Jh)RLoTtXPUn}sRsxIf9WBkx<^ucB*f zGqw;8<*Dmf-=G<;J|WH!4ZYl5T%;q`^$e6Lyy#54c!(mJnrz%R0+I3hUz4>2Yl^4qU%7qdx=EAtDFD*QJU5ql3_O5Q0zk)|Gf+YxA(<$H zw;}eOf!-aR$W9{46bEtGGf=GH?vZc3z!}JF*|z)Gd%5bVkJiFCo*5WK-DU9@MYF8H z9teY{sLZg2$-N53Oo3NkObfomhWpA`un~)w z-oF^}Gb$E(`bDMqaYR8PA1^kr*U?I*_RXnMu^Ms6ta8$?Xm1>&WJw5y%*Q}T5cBDQ zDuB^72oZ|VIB!I|37Sn?+3f1U_>sX&(`}Te3r2P_JF@Rymaatf=3loiE0K|iS2y7Jhd{X4x82I&a4jqeCpY&;nvGk!E`Uxy}+ObnFa(wKx8w& zfW+O@4GJW~v3UcF20P>%^BgW-TpXH4i*sVbB#tJLb^TR&$2RSH-2iL#Gq<0!mS27; zJH?Cdf`jn_xjr;4b7#Zr3{s96} z0}+@~WIF5ULJU_DEamZXyR9gHs)Jr$6II1;19+{5Z@aWl#zzd-(^8gEc_&OP`ULgk z2QZ0F{x}9IAYAIrzyVPY{<5+$F5?NR61uhNhT3*(ckpgt${# zuWP&0l?Hq;<3ck#sz$i%i9icRjOC*4-aO2G&|sL!`%@eE>wc+2STXx6DY@?U1C`0_ zeH8JcHUKPU!-)CMvrMD@x6yE+1~Sag?;_a1+k19P1{S(-5d&YzU(@a4yAPF|yD&}9 zs@}cL8F-rHj1&eot>=rud-pTwh_iu`8H;SK;w+np3lNw#k7oS1I_7zp|4Beosh~;> z??{yJ>KUluKs2O{wk+o{2#uC|`iDP!&yh%@jS#{czw5@>c z7PBZ|XA2~l)xd-WqT`?xJP>3B`QhL@O?*B*9jzwu6Tc>KUcCfyi;-rts6eAH*Lvcm z8{)q1AG=%x87FEW)r7h+lX*AgMCzixj3x~QTjmfockxjhqakv&BVN|_jpK{?cxE0V zH6sR0q`7#i2A(*=-i1unsTQr=UxZw3R#3C?eE#+FDuIv8*Zh%RP``Z8_{(0}o9o=g zt6B?i1}tzo@aDbvsxIX(Xkb6E&&Sd}Pza|CpS)V>%&Nx8JuDiC|v=h?pvR#TZukXhHE>8y~laj_hTOmt#7@W>G_3X{D@(w zjLZxf@(ds-Mx7sgm~3&(&*Au2w_+C{AxgAmKZiwGhh@h+75tRp0^!oimqo{NCCj^r z&jwPchvmY_U2ib9Mci$P5I!|LzW&#>1`={06O%EgQ}2AuR6s1s7=+}7yVnNcdR zO;?QPZyKrUX`;hO!4X+jn$JIJYPpf870*}Ix{_K>&h(V=FUqVdcHy?6SYR0(6h>@y zM?Aq>6XFDL^SNod!-^VvW3XJSN9KV$j+;3Z5qlkC-mScje2sBuAaim{NtIJS6@N-L zACne;U4h4n-yavr+6~&XCs~NYD6dX>tyF8LDY(=o2{7bdt*CcuTFu1SEo9&n*s!qi z295lQ86R&nG1Ae`os-Fdtxhy@+LTAaI8~o+3kVIhBw}R!g{Ho`Fd)xBZ2*v$Rufpo z@fE)ZiOR^4-3aJKyfCH{IPzk}AVd8jiwv|5>CkD9XlI=;y>IpVOJ=qQ*Hg@8r@48e zzc0k8FOgXTo8k1I2uYB&DTFV?6(T< zSRTc5+l8*^$17&&0+yR5r5o#h4U7#Wd~A~Ux5Xru5z3BKB6VU|E5AYGwZ2Yrtho!EJB*`dR_ZtJT@MoeC0um#zEhD#tkGW`yhiv)mW{CMUg^ivGQ{m> zeDlV$Pwp{bpJMnrqlm)&0jC=NIwMZ@jZI^U_D;ORIqAl=2Yl>~4TZv83CIuQ@m63N zmZaM>oD4tNg^$v&%zq3E6C^-+S{{E+$CqjvoPn5|gb>sH=`uWQ=JhMZ{DcR9H!ZjW z_|(7ct&{#YYlgGQ^CNq&-A}t7z(MwT`R9@Sf2JjzCoZYDxjDQ2Eh(X_Td=#ov|OV{ zx3I!p^k$E^LB$ZI`^&>-Nub%kk^$1|MBTW7>+3-IKR@{ra2H6F^3k?&f<3o$_Ym`e zzl<`}a+;Q4{zch!?TT00TQ61>{kPPH^(t@V!4F{#&kOCt1y#QAj>_BjW~ptkXm+3c z(4jM&qT20m7^E$Ph@%#Z;Cw^662>o7Fp8-*e1wrTzxY+DM(bD14A#amCUO^b- z8&t-eJTSU@v9uvLVzS`!uNOtKV(2>VuO-z>ZZa8h5kjRTo8QEP^!z`)acjAoZDCB( zF3Tfq5!h{Nr1fpc{+$7`GR}AIa`ni1t!(O>%Bh^tjaRoY-p>e z&aHyTj;AA}>H;Mu9nMB?TuEP+@pNd}ICiI7e=m#B38OKg0 zWz{d)*q5$WgGpbs8xG;LFHEXKd7gR1c}xKgrA@C0pTnb?V%ss}4P?&PM0@D3-waP^ zuEA+cgm%YXzKL)UrN(~Fj4w$3C95D2@XCBakiJ4OqVFdE@>wg{bZBOvr}A&g`7ObN zHl~#*-lOTZ3Lv;1p_H{|8J9g@Y31VQQOAl z+$25Xt(>QTJe*yDZOFq}yGmXimnTe_+%&Z6OjO!WK6%-GKX$mBHo+%^YJ%lU-kZsd z#iy_O+8sHkaVOK~poK)WL3S+aIlqRj%scq0-eAVL-qn0xreCe#{L+81rLcb;-q} z|1o3s(JhFm%Of1vx+2^Dj%_}$Sc0vx&Ir?pYnFdrXXWhIc;>A4?rzLjr;2Pttr^ud zGvOEGAB-k?!NkV_hDH^2f+f&PqrzGDR1RJwGzNT7X+vc@PK#gTF4(!$*4ti-e5AE(C*Ydlyf z2i5JbZolwL{zbXbO%kANf4K*Us~P|#`lq3!y1h2q1d@7$|F6kfOaO<4va^$ios$RD z(AUMz-Rj&{qT{-C+9WPLM6~a-@X>Q#dZ3}&>ScR}7W_l*Q`>E8bJyFFh}hfrIj^g8 z*4J4lE|`mb-|Xa7vpaFD z+e6U$30lA<#b|n~q4YkO>vhkWJ*xjL*~x%$eq=?)x$E$86H;3ORDc2$rKd$gDhm2D z7xu5&Zs)nM|4x6&jQx}G?_TGxDP-r#aDS2 +#include +#include +#include + +#include // For Appx Packaging APIs + +#include "ExtractAppx.h" + +// Types of footprint files in an Appx package +const int FootprintFilesCount = 4; +const APPX_FOOTPRINT_FILE_TYPE FootprintFilesType[FootprintFilesCount] = { + APPX_FOOTPRINT_FILE_TYPE_MANIFEST, + APPX_FOOTPRINT_FILE_TYPE_BLOCKMAP, + APPX_FOOTPRINT_FILE_TYPE_SIGNATURE, + APPX_FOOTPRINT_FILE_TYPE_CODEINTEGRITY +}; +const LPCWSTR FootprintFilesName[FootprintFilesCount] = { + L"manifest", + L"block map", + L"digital signature", + L"code integrity catalog" +}; + +// +// Function to create a writable IStream over a file with the specified name +// under the specified path. This function will also create intermediate +// subdirectories if necessary. For simplicity, file names including path are +// assumed to be 200 characters or less. A real application should be able to +// handle longer names and allocate the necessary buffer dynamically. +// +// Parameters: +// path - Path of the folder containing the file to be opened. This should NOT +// end with a slash ('\') character. +// fileName - Name, not including path, of the file to be opened +// stream - Output parameter pointing to the created instance of IStream over +// the specified file when this function succeeds. +// +HRESULT GetOutputStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream) +{ + HRESULT hr = S_OK; + const int MaxFileNameLength = 200; + WCHAR fullFileName[MaxFileNameLength + 1]; + + // Create full file name by concatenating path and fileName + hr = StringCchCopyW(fullFileName, MaxFileNameLength, path); + + if (SUCCEEDED(hr)) + { + hr = StringCchCat(fullFileName, MaxFileNameLength, L"\\"); + } + if (SUCCEEDED(hr)) + { + hr = StringCchCat(fullFileName, MaxFileNameLength, fileName); + } + + // Search through fullFileName for the '\' character which denotes + // subdirectory and create each subdirectory in order of depth. + for (int i = 0; SUCCEEDED(hr) && (i < MaxFileNameLength); i++) + { + if (fullFileName[i] == L'\0') + { + break; + } + else if (fullFileName[i] == L'\\') + { + // Temporarily set string to terminate at the '\' character + // to obtain name of the subdirectory to create + fullFileName[i] = L'\0'; + + if (!CreateDirectory(fullFileName, NULL)) + { + DWORD lastError = GetLastError(); + + // It is normal for CreateDirectory to fail if the subdirectory + // already exists. Other errors should not be ignored. + if (lastError != ERROR_ALREADY_EXISTS) + { + hr = HRESULT_FROM_WIN32(lastError); + } + } + + // Restore original string + fullFileName[i] = L'\\'; + } + } + + // Create stream for writing the file + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + fullFileName, + STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + TRUE, // create new file if it does not exist + NULL, // no template + stream); + } + return hr; +} + +// +// Function to print some basic information about an IAppxFile, and write +// it to disk under the given path. +// +// Parameters: +// file - Instance of IAppxFile obtained from IAppxPackageReader representing +// a footprint or payload file in the package. +// outputPath - Path of the folder where extracted files should be placed +// +HRESULT ExtractFile( + _In_ IAppxFile* file, + _In_ LPCWSTR outputPath) +{ + HRESULT hr = S_OK; + LPWSTR fileName = NULL; + LPWSTR contentType = NULL; + UINT64 fileSize = 0; + IStream* fileStream = NULL; + IStream* outputStream = NULL; + ULARGE_INTEGER fileSizeLargeInteger = {0}; + + // Get basic information about the file + hr = file->GetName(&fileName); + + if (SUCCEEDED(hr)) + { + hr = file->GetContentType(&contentType); + } + if (SUCCEEDED(hr)) + { + hr = file->GetSize(&fileSize); + fileSizeLargeInteger.QuadPart = fileSize; + } + if (SUCCEEDED(hr)) + { + wprintf(L"\nFile name: %s\n", fileName); + wprintf(L"Content type: %s\n", contentType); + wprintf(L"Size: %llu bytes\n", fileSize); + } + + // Write the file out to disk + if (SUCCEEDED(hr)) + { + hr = file->GetStream(&fileStream); + } + if (SUCCEEDED(hr) && (fileName != NULL)) + { + hr = GetOutputStream(outputPath, fileName, &outputStream); + } + if (SUCCEEDED(hr) && (outputStream != NULL)) + { + hr = fileStream->CopyTo(outputStream, fileSizeLargeInteger, NULL, NULL); + } + + // String buffers obtained from the packaging APIs must be freed + CoTaskMemFree(fileName); + CoTaskMemFree(contentType); + + // Clean up other allocated resources + if (outputStream != NULL) + { + outputStream->Release(); + outputStream = NULL; + } + if (fileStream != NULL) + { + fileStream->Release(); + fileStream = NULL; + } + return hr; +} + +// +// Function to extract all footprint files from a package reader. +// +// Parameters: +// packageReader - Instance of IAppxPackageReader over the Appx package whose +// footprint files are to be extracted. +// outputPath - Path of the folder where all extracted footprint files should +// be placed. +// +HRESULT ExtractFootprintFiles( + _In_ IAppxPackageReader* packageReader, + _In_ LPCWSTR outputPath) +{ + HRESULT hr = S_OK; + wprintf(L"\nExtracting footprint files from the package\n"); + + for (int i = 0; SUCCEEDED(hr) && (i < FootprintFilesCount); i++) + { + IAppxFile* footprintFile = NULL; + + hr = packageReader->GetFootprintFile(FootprintFilesType[i], &footprintFile); + + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + // Some footprint files are optional, it is normal for the GetFootprintFile + // call to fail when the file is not present. + wprintf(L"\nThe package does not contain a %s.\n", FootprintFilesName[i]); + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + hr = ExtractFile(footprintFile, outputPath); + } + + if (footprintFile != NULL) + { + footprintFile->Release(); + footprintFile = NULL; + } + } + return hr; +} + +// +// Function to extract all payload files from a package reader. +// +// Parameters: +// packageReader - Instance of IAppxPackageReader over the Appx package whose +// payload files are to be extracted. +// outputPath - Path of the folder where all extracted payload files should be +// placed. +// +HRESULT ExtractPayloadFiles( + _In_ IAppxPackageReader* packageReader, + _In_ LPCWSTR outputPath) +{ + HRESULT hr = S_OK; + IAppxFilesEnumerator* payloadFiles = NULL; + wprintf(L"\nExtracting payload files from the package\n"); + + // Get an enumerator of all payload files from the package reader and iterate + // through all files. + hr = packageReader->GetPayloadFiles(&payloadFiles); + + if (SUCCEEDED(hr)) + { + BOOL hasCurrent = FALSE; + hr = payloadFiles->GetHasCurrent(&hasCurrent); + + while (SUCCEEDED(hr) && hasCurrent) + { + IAppxFile* payloadFile = NULL; + + hr = payloadFiles->GetCurrent(&payloadFile); + + if (SUCCEEDED(hr)) + { + hr = ExtractFile(payloadFile, outputPath); + } + if (SUCCEEDED(hr)) + { + hr = payloadFiles->MoveNext(&hasCurrent); + } + + if (payloadFile != NULL) + { + payloadFile->Release(); + payloadFile = NULL; + } + } + } + + if (payloadFiles != NULL) + { + payloadFiles->Release(); + payloadFiles = NULL; + } + return hr; +} + +// +// Function to create an Appx package reader given the input file name. +// +// Parameters: +// inputFileName - Name including path to the Appx package (.appx file) to +// be opened. +// reader - Output parameter pointing to the created instance of +// IAppxPackageReader when this function succeeds. +// +HRESULT GetPackageReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxPackageReader** reader) +{ + HRESULT hr = S_OK; + IAppxFactory* appxFactory = NULL; + IStream* inputStream = NULL; + + // Create a new Appx factory + hr = CoCreateInstance( + __uuidof(AppxFactory), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppxFactory), + (LPVOID*)(&appxFactory)); + + // Create a stream over the input Appx package + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + inputFileName, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + FALSE, // do not create new file + NULL, // no template + &inputStream); + } + + // Create a new package reader using the factory. + if (SUCCEEDED(hr)) + { + hr = appxFactory->CreatePackageReader( + inputStream, + reader); + } + + // Clean up allocated resources + if (inputStream != NULL) + { + inputStream->Release(); + inputStream = NULL; + } + if (appxFactory != NULL) + { + appxFactory->Release(); + appxFactory = NULL; + } + return hr; +} + +// +// Main entry point of the sample +// +int wmain( + _In_ int argc, + _In_reads_(argc) wchar_t** argv) +{ + wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n"); + wprintf(L"ExtractAppx sample\n\n"); + + if (argc != 3) + { + wprintf(L"Usage: ExtractAppx.exe inputFile outputPath\n"); + wprintf(L" inputFile: Path to the Appx package to extract\n"); + wprintf(L" outputPath: Path to the folder to store extracted package contents\n"); + return 2; + } + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + + if (SUCCEEDED(hr)) + { + // Create a package reader using the file name given in command line + IAppxPackageReader* packageReader = NULL; + + hr = GetPackageReader(argv[1], &packageReader); + + // Print information about all footprint files, and extract them to disk + if (SUCCEEDED(hr)) + { + hr = ExtractFootprintFiles(packageReader, argv[2]); + } + + // Print information about all payload files, and extract them to disk + if (SUCCEEDED(hr)) + { + hr = ExtractPayloadFiles(packageReader, argv[2]); + } + + // Clean up allocated resources + if (packageReader != NULL) + { + packageReader->Release(); + packageReader = NULL; + } + CoUninitialize(); + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nPackage extracted successfully.\n"); + } + else + { + wprintf(L"\nPackage extraction failed with HRESULT 0x%08X.\n", hr); + } + return SUCCEEDED(hr) ? 0 : 1; +} diff --git a/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.h b/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.h new file mode 100644 index 00000000..5f128d39 --- /dev/null +++ b/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.h @@ -0,0 +1,52 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx packaging APIs to read +// contents of an Appx package, and extract its contents to a folder on disk. + +#pragma once + +// +// Function to create a writable IStream over a file with the specified name +// under the specified path. This function will also create intermediate +// subdirectories if necessary. For simplicity, file names including path are +// assumed to be 200 characters or less. A real application should be able to +// handle longer names and allocate the necessary buffer dynamically. +// +HRESULT GetOutputStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream); + +// +// Function to print some basic information about an IAppxFile, and write +// it to disk under the given path. +// +HRESULT ExtractFile( + _In_ IAppxFile* file, + _In_ LPCWSTR outputPath); + +// +// Function to extract all footprint files from a package reader. +// +HRESULT ExtractFootprintFiles( + _In_ IAppxPackageReader* packageReader, + _In_ LPCWSTR outputPath); + +// +// Function to extract all payload files from a package reader. +// +HRESULT ExtractPayloadFiles( + _In_ IAppxPackageReader* packageReader, + _In_ LPCWSTR outputPath); + +// +// Function to create an Appx package reader given the input file name. +// +HRESULT GetPackageReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxPackageReader** reader); diff --git a/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.sln b/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.sln new file mode 100644 index 00000000..09343f9c --- /dev/null +++ b/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtractAppx", "ExtractAppx.vcxproj", "{27920714-71BD-431D-B220-EF54CF083172}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {27920714-71BD-431D-B220-EF54CF083172}.Debug|Win32.ActiveCfg = Debug|Win32 + {27920714-71BD-431D-B220-EF54CF083172}.Debug|Win32.Build.0 = Debug|Win32 + {27920714-71BD-431D-B220-EF54CF083172}.Release|Win32.ActiveCfg = Release|Win32 + {27920714-71BD-431D-B220-EF54CF083172}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.vcxproj b/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.vcxproj new file mode 100644 index 00000000..6e6b06b5 --- /dev/null +++ b/Samples/AppxPackingExtractAppx/cpp/ExtractAppx.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {27920714-71BD-431D-B220-EF54CF083172} + ExtractAppx + Win32Proj + + + + Application + v110 + false + Unicode + true + + + Application + v110 + false + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.40602.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + true + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + false + + MachineX86 + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level4 + true + ProgramDatabase + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + true + true + false + + MachineX86 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingExtractAppx/cpp/readme.txt b/Samples/AppxPackingExtractAppx/cpp/readme.txt new file mode 100644 index 00000000..8f851a7d --- /dev/null +++ b/Samples/AppxPackingExtractAppx/cpp/readme.txt @@ -0,0 +1,69 @@ + +Appx Package Extraction Sample +============================== + + This sample demonstrates how to use Appx packaging APIs to read an Appx package and extract its contents to disk. + + +Prerequisites +============= + + This sample requires Windows 8 or higher, and an installation of Visual Studio 2012 Ultimate. + + +Sample Language Implementations +=============================== + + This sample is available in the following language implementations: + + C++ + + +Files +===== + + ExtractAppx.cpp - main entry point for the sample application + + ExtractAppx.h - main header file + + ExtractAppx.vcxproj - build configuration for this sample + + ExtractAppx.sln - Visual Studio 2012 Solution file for this sample + + Data\HelloWorld.appx - A sample Appx package that can be used as input for this sample + + +To build the sample using the command prompt: +============================================= + + 1. Open the Command Prompt window and navigate to the directory containing ExtractAppx.vcxproj + + 2. Type: msbuild ExtractAppx.vcxproj + + +To build the sample using Visual Studio 2012 Ultimate (preferred method): +========================================================================= + + 1. Open File Explorer and navigate to the directory containing ExtractAppx.vcxproj. + + 2. Double-click the icon for the ExtractAppx.vcxproj file to open the file in Visual Studio. + + 3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + + +To run the sample: +================== + + 1. Open a command prompt window and navigate to the directory where ExtractAppx.exe is built. + + 2. Type the command: + + ExtractAppx.exe inputFile outputPath + + inputFile: the full or relative path to an Appx package that can be read + + outputPath: the full or relative path where extracted package contents can be written. This path should be 150 characters or less to avoid hitting limitations of this sample. + + Example: ExtractAppx.exe "data\HelloWorld.appx" "outputFolder" + + 3. When the application exits successfully, the output folder should contain all payload and footprint files extracted from the input package. diff --git a/Samples/AppxPackingExtractBundle/README.md b/Samples/AppxPackingExtractBundle/README.md new file mode 100644 index 00000000..5575ba6d --- /dev/null +++ b/Samples/AppxPackingExtractBundle/README.md @@ -0,0 +1,41 @@ +Extract app bundle contents sample +================================== + +This sample shows how to extract info about a bundle package using the [Packaging API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446766). + +The sample covers these tasks: + +- Use [**IAppxBundleFactory::CreateBundleReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280279) to create a bundle reader +- Use [**IAppxBundleReader::GetFootprintFile**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280298) to extract footprint files from the bundle reader +- Use [**IAppxBundleReader::GetPayloadPackages**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280301) to get [**IAppxFilesEnumerator**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446685) to iterate through the list of payload packages. Then, use [**IAppxFile**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh446683) to get info about each package. + +Related topics +-------------- + +**Reference** + +[**IAppxBundleReader**](http://msdn.microsoft.com/en-us/library/windows/desktop/dn280296) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/AppxPackingExtractBundle/cpp/Data/sample.appxbundle b/Samples/AppxPackingExtractBundle/cpp/Data/sample.appxbundle new file mode 100644 index 0000000000000000000000000000000000000000..5ed41644ff0b9448f67b1f13e779b53d7333d3f5 GIT binary patch literal 18898 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 literal 0 HcmV?d00001 diff --git a/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.cpp b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.cpp new file mode 100644 index 00000000..6efa268f --- /dev/null +++ b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.cpp @@ -0,0 +1,401 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx Bundle APIs to read the +// contents of an Appx bundle, and extract its contents to a folder on disk. + +#include +#include +#include +#include + +#include // For Appx Bundle APIs + +#include "ExtractBundle.h" + +// Types of footprint files in a bundle +const int FootprintFilesCount = 3; +const APPX_BUNDLE_FOOTPRINT_FILE_TYPE FootprintFilesType[FootprintFilesCount] = { + APPX_BUNDLE_FOOTPRINT_FILE_TYPE_MANIFEST, + APPX_BUNDLE_FOOTPRINT_FILE_TYPE_BLOCKMAP, + APPX_BUNDLE_FOOTPRINT_FILE_TYPE_SIGNATURE +}; +const LPCWSTR FootprintFilesName[FootprintFilesCount] = { + L"manifest", + L"block map", + L"digital signature" +}; + +// +// Function to create a writable IStream over a file with the specified name +// under the specified path. This function will also create intermediate +// subdirectories if necessary. For simplicity, file names including path are +// assumed to be 200 characters or less. A real application should be able to +// handle longer names and allocate the necessary buffer dynamically. +// +// Parameters: +// path - Path of the folder containing the file to be opened. This should NOT +// end with a slash ('\') character. +// fileName - Name, not including path, of the file to be opened +// stream - Output parameter pointing to the created instance of IStream over +// the specified file when this function succeeds. +// +HRESULT GetOutputStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream) +{ + HRESULT hr = S_OK; + const int MaxFileNameLength = 200; + WCHAR fullFileName[MaxFileNameLength + 1]; + + // Create full file name by concatenating path and fileName + hr = StringCchCopyW(fullFileName, MaxFileNameLength, path); + + if (SUCCEEDED(hr)) + { + hr = StringCchCat(fullFileName, MaxFileNameLength, L"\\"); + } + if (SUCCEEDED(hr)) + { + hr = StringCchCat(fullFileName, MaxFileNameLength, fileName); + } + + // Search through fullFileName for the '\' character which denotes + // subdirectory and create each subdirectory in order of depth. + for (int i = 0; SUCCEEDED(hr) && (i < MaxFileNameLength); i++) + { + if (fullFileName[i] == L'\0') + { + break; + } + else if (fullFileName[i] == L'\\') + { + // Temporarily set string to terminate at the '\' character + // to obtain name of the subdirectory to create + fullFileName[i] = L'\0'; + + if (!CreateDirectory(fullFileName, NULL)) + { + DWORD lastError = GetLastError(); + + // It is normal for CreateDirectory to fail if the subdirectory + // already exists. Other errors should not be ignored. + if (lastError != ERROR_ALREADY_EXISTS) + { + hr = HRESULT_FROM_WIN32(lastError); + } + } + + // Restore original string + fullFileName[i] = L'\\'; + } + } + + // Create stream for writing the file + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + fullFileName, + STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + TRUE, // create new file if it does not exist + NULL, // no template + stream); + } + return hr; +} + +// +// Function to print some basic information about an IAppxFile object, and +// write it to disk under the given path. +// +// Parameters: +// file - Instance of IAppxFile obtained from IAppxBundleReader representing +// a footprint file or payload package in the bundle. +// outputPath - Path of the folder where extracted files should be placed +// +HRESULT ExtractFile( + _In_ IAppxFile* file, + _In_ LPCWSTR outputPath) +{ + HRESULT hr = S_OK; + LPWSTR fileName = NULL; + LPWSTR contentType = NULL; + UINT64 fileSize = 0; + IStream* fileStream = NULL; + IStream* outputStream = NULL; + ULARGE_INTEGER fileSizeLargeInteger = {0}; + + // Get basic information about the file + hr = file->GetName(&fileName); + + if (SUCCEEDED(hr)) + { + hr = file->GetContentType(&contentType); + } + if (SUCCEEDED(hr)) + { + hr = file->GetSize(&fileSize); + fileSizeLargeInteger.QuadPart = fileSize; + } + if (SUCCEEDED(hr)) + { + wprintf(L"\nFile name: %s\n", fileName); + wprintf(L"Content type: %s\n", contentType); + wprintf(L"Size: %llu bytes\n", fileSize); + } + + // Write the file out to disk + if (SUCCEEDED(hr)) + { + hr = file->GetStream(&fileStream); + } + if (SUCCEEDED(hr) && (fileName != NULL)) + { + hr = GetOutputStream(outputPath, fileName, &outputStream); + } + if (SUCCEEDED(hr) && (outputStream != NULL)) + { + hr = fileStream->CopyTo(outputStream, fileSizeLargeInteger, NULL, NULL); + } + + // String buffers obtained from the bundle APIs must be freed + CoTaskMemFree(fileName); + CoTaskMemFree(contentType); + + // Clean up other allocated resources + if (outputStream != NULL) + { + outputStream->Release(); + outputStream = NULL; + } + if (fileStream != NULL) + { + fileStream->Release(); + fileStream = NULL; + } + return hr; +} + +// +// Function to extract all footprint files from a bundle reader. +// +// Parameters: +// bundleReader - Instance of IAppxBundleReader over the bundle whose footprint +// files are to be extracted. +// outputPath - Path of the folder where all extracted footprint files should +// be placed. +// +HRESULT ExtractFootprintFiles( + _In_ IAppxBundleReader* bundleReader, + _In_ LPCWSTR outputPath) +{ + HRESULT hr = S_OK; + wprintf(L"\nExtracting footprint files from the bundle\n"); + + for (int i = 0; SUCCEEDED(hr) && (i < FootprintFilesCount); i++) + { + IAppxFile* footprintFile = NULL; + + hr = bundleReader->GetFootprintFile(FootprintFilesType[i], &footprintFile); + + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + // Some footprint files are optional, it's normal for the GetFootprintFile + // call to fail when the file is not present. + wprintf(L"\nThe bundle doesn't contain a %s.\n", FootprintFilesName[i]); + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + hr = ExtractFile(footprintFile, outputPath); + } + + if (footprintFile != NULL) + { + footprintFile->Release(); + footprintFile = NULL; + } + } + return hr; +} + +// +// Function to extract all payload packages from a bundle reader. +// +// Parameters: +// bundleReader - Instance of IAppxBundleReader over the bundle whose payload +// packages are to be extracted. +// outputPath - Path of the folder where all extracted payload packages should +// be placed. +// +HRESULT ExtractPayloadPackages( + _In_ IAppxBundleReader* bundleReader, + _In_ LPCWSTR outputPath) +{ + HRESULT hr = S_OK; + IAppxFilesEnumerator* payloadPackages = NULL; + wprintf(L"\nExtracting payload packages from the bundle\n"); + + // Get an enumerator of all payload packages from the bundle reader and + // iterate through all of them. + hr = bundleReader->GetPayloadPackages(&payloadPackages); + + if (SUCCEEDED(hr)) + { + BOOL hasCurrent = FALSE; + hr = payloadPackages->GetHasCurrent(&hasCurrent); + + while (SUCCEEDED(hr) && hasCurrent) + { + IAppxFile* payloadPackage = NULL; + + hr = payloadPackages->GetCurrent(&payloadPackage); + + if (SUCCEEDED(hr)) + { + hr = ExtractFile(payloadPackage, outputPath); + } + if (SUCCEEDED(hr)) + { + hr = payloadPackages->MoveNext(&hasCurrent); + } + + if (payloadPackage != NULL) + { + payloadPackage->Release(); + payloadPackage = NULL; + } + } + } + + if (payloadPackages != NULL) + { + payloadPackages->Release(); + payloadPackages = NULL; + } + return hr; +} + +// +// Function to create an Appx Bundle reader given the input file name. +// +// Parameters: +// inputFileName - Name including path to the bundle (.appxbundle file) +// to be opened. +// bundleReader - Output parameter pointing to the created instance of +// IAppxBundleReader when this function succeeds. +// +HRESULT GetBundleReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxBundleReader** bundleReader) +{ + HRESULT hr = S_OK; + IAppxBundleFactory* appxBundleFactory = NULL; + IStream* inputStream = NULL; + + // Create a new Appx bundle factory + hr = CoCreateInstance( + __uuidof(AppxBundleFactory), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppxBundleFactory), + (LPVOID*)(&appxBundleFactory)); + + // Create a stream over the input Appx bundle + if (SUCCEEDED(hr)) + { + hr = SHCreateStreamOnFileEx( + inputFileName, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, // default file attributes + FALSE, // do not create new file + NULL, // no template + &inputStream); + } + + // Create a new bundle reader using the factory + if (SUCCEEDED(hr)) + { + hr = appxBundleFactory->CreateBundleReader( + inputStream, + bundleReader); + } + + // Clean up allocated resources + if (inputStream != NULL) + { + inputStream->Release(); + inputStream = NULL; + } + if (appxBundleFactory != NULL) + { + appxBundleFactory->Release(); + appxBundleFactory = NULL; + } + return hr; +} + +// +// Main entry point of the sample +// +int wmain( + _In_ int argc, + _In_reads_(argc) wchar_t** argv) +{ + wprintf(L"Copyright (c) Microsoft Corporation. All rights reserved.\n"); + wprintf(L"ExtractBundle sample\n\n"); + + if (argc != 3) + { + wprintf(L"Usage: ExtractBundle.exe inputFile outputPath\n"); + wprintf(L" inputFile: Path to the bundle to extract\n"); + wprintf(L" outputPath: Path to the folder to store extracted contents\n"); + return 2; + } + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + + if (SUCCEEDED(hr)) + { + // Create a bundle reader using the file name given in command line + IAppxBundleReader* bundleReader = NULL; + + hr = GetBundleReader(argv[1], &bundleReader); + + // Print information about all footprint files, and extract them to disk + if (SUCCEEDED(hr)) + { + hr = ExtractFootprintFiles(bundleReader, argv[2]); + } + + // Print information about all payload files, and extract them to disk + if (SUCCEEDED(hr)) + { + hr = ExtractPayloadPackages(bundleReader, argv[2]); + } + + // Clean up allocated resources + if (bundleReader != NULL) + { + bundleReader->Release(); + bundleReader = NULL; + } + CoUninitialize(); + } + + if (SUCCEEDED(hr)) + { + wprintf(L"\nBundle extracted successfully.\n"); + } + else + { + wprintf(L"\nBundle extraction failed with HRESULT 0x%08X.\n", hr); + } + return SUCCEEDED(hr) ? 0 : 1; +} diff --git a/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.h b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.h new file mode 100644 index 00000000..13f886da --- /dev/null +++ b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.h @@ -0,0 +1,52 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +// This is a simple application which uses the Appx Bundle APIs to read the +// contents of an Appx bundle, and extract its contents to a folder on disk. + +#pragma once + +// +// Function to create a writable IStream over a file with the specified name +// under the specified path. This function will also create intermediate +// subdirectories if necessary. For simplicity, file names including path are +// assumed to be 200 characters or less. A real application should be able to +// handle longer names and allocate the necessary buffer dynamically. +// +HRESULT GetOutputStream( + _In_ LPCWSTR path, + _In_ LPCWSTR fileName, + _Outptr_ IStream** stream); + +// +// Function to print some basic information about an IAppxFile object, and +// write it to disk under the given path. +// +HRESULT ExtractFile( + _In_ IAppxFile* file, + _In_ LPCWSTR outputPath); + +// +// Function to extract all footprint files from a bundle reader. +// +HRESULT ExtractFootprintFiles( + _In_ IAppxBundleReader* bundleReader, + _In_ LPCWSTR outputPath); + +// +// Function to extract all payload packages from a bundle reader. +// +HRESULT ExtractPayloadPackages( + _In_ IAppxBundleReader* bundleReader, + _In_ LPCWSTR outputPath); + +// +// Function to create an Appx Bundle reader given the input file name. +// +HRESULT GetBundleReader( + _In_ LPCWSTR inputFileName, + _Outptr_ IAppxBundleReader** bundleReader); diff --git a/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.sln b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.sln new file mode 100644 index 00000000..7912d8b2 --- /dev/null +++ b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtractBundle", "ExtractBundle.vcxproj", "{40EA740C-AC27-4767-953A-53A161FCC7DB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {40EA740C-AC27-4767-953A-53A161FCC7DB}.Debug|Win32.ActiveCfg = Debug|Win32 + {40EA740C-AC27-4767-953A-53A161FCC7DB}.Debug|Win32.Build.0 = Debug|Win32 + {40EA740C-AC27-4767-953A-53A161FCC7DB}.Release|Win32.ActiveCfg = Release|Win32 + {40EA740C-AC27-4767-953A-53A161FCC7DB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.vcxproj b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.vcxproj new file mode 100644 index 00000000..95f6ee06 --- /dev/null +++ b/Samples/AppxPackingExtractBundle/cpp/ExtractBundle.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {40EA740C-AC27-4767-953A-53A161FCC7DB} + ExtractBundle + Win32Proj + + + + Application + v110 + false + Unicode + true + + + Application + v110 + false + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.40602.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + true + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + false + + MachineX86 + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level4 + true + ProgramDatabase + + + shlwapi.lib;%(AdditionalDependencies) + true + Console + true + true + false + + MachineX86 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/AppxPackingExtractBundle/cpp/readme.txt b/Samples/AppxPackingExtractBundle/cpp/readme.txt new file mode 100644 index 00000000..9504d5b7 --- /dev/null +++ b/Samples/AppxPackingExtractBundle/cpp/readme.txt @@ -0,0 +1,69 @@ + +Appx Bundle Extraction Sample +============================= + + This sample demonstrates how to use Appx Bundle APIs to read an Appx Bundle and extract its contents to disk. + + +Prerequisites +============= + + This sample requires Windows 8.1 or higher, and an installation of Visual Studio 2012 Ultimate. + + +Sample Language Implementations +=============================== + + This sample is available in the following language implementations: + + C++ + + +Files +===== + + ExtractBundle.cpp - main entry point for the sample application + + ExtractBundle.h - main header file + + ExtractBundle.vcxproj - build configuration for this sample + + ExtractBundle.sln - Visual Studio 2012 Solution file for this sample + + Data\sample.appxbundle - A sample Appx Bundle that can be used as input for this sample + + +To build the sample using the command prompt: +============================================= + + 1. Open the Command Prompt window and navigate to the directory containing ExtractBundle.vcxproj + + 2. Type: msbuild ExtractBundle.vcxproj + + +To build the sample using Visual Studio 2012 Ultimate (preferred method): +========================================================================= + + 1. Open File Explorer and navigate to the directory containing ExtractBundle.vcxproj. + + 2. Double-click the icon for the ExtractBundle.vcxproj file to open the file in Visual Studio. + + 3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory. + + +To run the sample: +================== + + 1. Open a command prompt window and navigate to the directory where ExtractBundle.exe is built. + + 2. Type the command: + + ExtractBundle.exe inputFile outputPath + + inputFile: the full or relative path to an Appx Bundle that can be read + + outputPath: the full or relative path where contents extracted from the bundle can be written. This path should be 150 characters or less to avoid hitting limitations of this sample. + + Example: ExtractBundle.exe "Data\sample.appxbundle" "outputFolder" + + 3. When the application exits successfully, the output folder should contain all payload packages and footprint files extracted from the input bundle. diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/README.md b/Samples/BacgroundIntelligenceTransferServicePolicy/README.md new file mode 100644 index 00000000..7d6aef1f --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/README.md @@ -0,0 +1,34 @@ +Background Intelligent Transfer Service transfer policy sample +============================================================== + +This sample demonstrates how to block a Background Intelligent Transfer Service (BITS) job from downloading over expensive connections such as a roaming cellular link. BITS provides a COM interface for asynchronous downloads and uploads over HTTP or Server Message Block (SMB) protocols. Progress is saved periodically so that transfers can resume after the computer is restarted. An application can control whether BITS transfers data when the network usage may be more expensive, such as when a cellular modem is roaming or the cellular account has exceeded its monthly data limit. This sample shows how to use the BITS API to create a BITS transfer and configure its network cost policy to prevent these costly scenarios. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +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 F6 for Visual Studio 2013) or use **Build \> Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.cpp b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.cpp new file mode 100644 index 00000000..773b94a8 --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.cpp @@ -0,0 +1,101 @@ +// 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" + + +int _tmain() +{ + HRESULT hr = S_OK; + GUID guidJob; + IBackgroundCopyJob5* pBackgroundCopyJob5; + IBackgroundCopyJob* pBackgroundCopyJob; + IBackgroundCopyManager* pQueueMgr; + BITS_JOB_PROPERTY_VALUE propval; + + //Specify the COM threading model. + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(hr)) + { + //The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE. + hr = CoInitializeSecurity(NULL, -1, NULL, NULL, + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE, 0); + + if (SUCCEEDED(hr)) + { + hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL, + CLSCTX_LOCAL_SERVER, + __uuidof(IBackgroundCopyManager), + (void **)&pQueueMgr); + + if (FAILED(hr)) + { + // Failed to connect to BITS + wprintf(L"Failed to connect to BITS with error %x\n",hr); + goto done; + } + + // Create a Job + wprintf(L"Creating Job...\n"); + + hr = pQueueMgr->CreateJob(L"TransferPolicy", + BG_JOB_TYPE_DOWNLOAD, + &guidJob, + (IBackgroundCopyJob **)&pBackgroundCopyJob); + + if(FAILED(hr)) + { + wprintf(L"Failed to Create Job, error = %x\n",hr); + goto cancel; + } + + wprintf(L" Job is succesfully created ...\n"); + + // Set Transfer Policy for the job + propval.Dword = BITS_COST_STATE_USAGE_BASED | BITS_COST_STATE_OVERCAP_THROTTLED| BITS_COST_STATE_BELOW_CAP| BITS_COST_STATE_CAPPED_USAGE_UNKNOWN| BITS_COST_STATE_UNRESTRICTED; + + hr = pBackgroundCopyJob->QueryInterface( + __uuidof(IBackgroundCopyJob5), + reinterpret_cast(&pBackgroundCopyJob5) + ); + + if(FAILED(hr)) + { + wprintf(L"Failed to Create Job, error = %x\n",hr); + goto cancel; + } + pBackgroundCopyJob5->SetProperty(BITS_JOB_PROPERTY_ID_COST_FLAGS, propval); + + // get Transfer Policy for the new job + BITS_JOB_PROPERTY_VALUE actual_propval; + + wprintf(L"Getting TransferPolicy Property ...\n"); + + hr = pBackgroundCopyJob5->GetProperty( BITS_JOB_PROPERTY_ID_COST_FLAGS, &actual_propval ); + if (FAILED(hr)) + { + //SetSSLSecurityFlags Failed + wprintf(L"GetProperty failed with error %x\n",hr); + goto cancel; + } + + DWORD job_transferpolicy = actual_propval.Dword; + wprintf(L"get TransferPolicy Property returned %#x\n", job_transferpolicy); + } +done: + CoUninitialize(); + } + return 1; + +cancel: + pBackgroundCopyJob->Cancel(); + pBackgroundCopyJob->Release(); + goto done; +} + diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.sln b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.sln new file mode 100644 index 00000000..ab41d8f3 --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TRANSFERPOLICY", "TRANSFERPOLICY.vcxproj", "{669A975F-4443-4DAE-88C3-AD3758B0BE60}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {669A975F-4443-4DAE-88C3-AD3758B0BE60}.Debug|Win32.ActiveCfg = Debug|Win32 + {669A975F-4443-4DAE-88C3-AD3758B0BE60}.Debug|Win32.Build.0 = Debug|Win32 + {669A975F-4443-4DAE-88C3-AD3758B0BE60}.Debug|Win32.Deploy.0 = Debug|Win32 + {669A975F-4443-4DAE-88C3-AD3758B0BE60}.Release|Win32.ActiveCfg = Release|Win32 + {669A975F-4443-4DAE-88C3-AD3758B0BE60}.Release|Win32.Build.0 = Release|Win32 + {669A975F-4443-4DAE-88C3-AD3758B0BE60}.Release|Win32.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.vcxproj b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.vcxproj new file mode 100644 index 00000000..1c803360 --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/TransferPolicy.vcxproj @@ -0,0 +1,96 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {669A975F-4443-4DAE-88C3-AD3758B0BE60} + Win32Proj + TRANSFERPOLICY + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + Create + Create + + + + + + + \ No newline at end of file diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.cpp b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.cpp new file mode 100644 index 00000000..3f2bb4a4 --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// TRANSFERPOLICY.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.h b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.h new file mode 100644 index 00000000..9694b2c9 --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/stdafx.h @@ -0,0 +1,17 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include +#include +#include +#include + + +// TODO: reference additional headers your program requires here diff --git a/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/targetver.h b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/targetver.h new file mode 100644 index 00000000..87c0086d --- /dev/null +++ b/Samples/BacgroundIntelligenceTransferServicePolicy/cpp/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/Samples/BackgroundCopyFileProperties/README.md b/Samples/BackgroundCopyFileProperties/README.md new file mode 100644 index 00000000..52120a43 --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/README.md @@ -0,0 +1,36 @@ +Background Intelligent Transfer Service IBackgroundCopyFile5 API sample +======================================================================= + +This sample demonstrates how to use the new IBackgroundCopyFile5 interface's GetProperty method to obtain the last set of HTTP headers received for each file in a Background Intelligent Transfer Service (BITS) download job. The information in the HTTP header could be used, for example, to determine the file type or when it last changed on the server. Prior to Windows 8.1 and Windows Server 2012 R2, BITS did not provide a means by which the application could retrieve and inspect the HTTP response headers of a completed download. This sample illustrates how to use the BITS API to create a BITS job with multiple URLs to download, list the URLs in a job, and retrieve the HTTP response headers for each URL. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +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 F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.cpp b/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.cpp new file mode 100644 index 00000000..62a7d998 --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.cpp @@ -0,0 +1,473 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. + + +/** + * This sample demonstrates how to use the GetProperty method on the new + * IBackgroundCopyFile5 interface to obtain the last set HTTP headers + * received for each file in a download job. + * + * The information in the HTTP headers could be used, fo example, to + * determine the file type or when it last changed on the server. + */ + + +#include "stdafx.h" + +#include +#include + + +#define ARRAY_LENGTH(x) (sizeof(x) / sizeof( *(x) )) + + +/** + * Definition of constants + */ +static const unsigned int HALF_SECOND_AS_MILLISECONDS = 500; +static const unsigned int TWO_SECOND_LOOP = 2000 / HALF_SECOND_AS_MILLISECONDS; + + +/** + * Simple data structure containing the remote and local names for a file. + */ +typedef struct +{ + LPWSTR RemoteFile; + LPWSTR LocalFile; +} DOWNLOAD_FILE; + + +/** + * Array containing multiple DOWNLOAD_FILE data structures representing the files + * that will be added to the download job. + */ +DOWNLOAD_FILE FileList[] = +{ + { + L"http://download.microsoft.com/download/8/5/5/8551E67C-3D6E-4EAA-891B-6B46A97F179F/Live_Meeting_2007_Getting_Started_Guide_Service.doc", + L"c:\\temp\\data\\Getting started with Microsoft Office Live Meeting.doc" + }, + { + L"http://download.microsoft.com/download/3/0/9/309778fd-659e-4853-b556-a14931cc3a2a/Live_Meeting_2007_Service_Quick_Reference_Card.doc", + L"c:\\temp\\data\\Live_Meeting_2007_Service_Quick_Reference_Card.doc" + }, + { + L"http://download.microsoft.com/download/D/2/2/D22D16C3-7637-41D3-99DA-10E7CEBAD290/SQL2008UpgradeTechnicalReferenceGuide.docx", + L"c:\\temp\\data\\SQL2008UpgradeTechnicalReferenceGuide.docx" + } +}; + + +/** + * Forward declaration of functions + */ + +HRESULT GetBackgroundCopyManager(_Out_ IBackgroundCopyManager **Manager); +HRESULT CreateDownloadJob(_In_ LPCWSTR Name, _In_ IBackgroundCopyManager *Manager, _Out_ IBackgroundCopyJob **Job); +HRESULT MonitorJobProgress( _In_ IBackgroundCopyJob *Job ); +HRESULT DisplayFileHeaders( _In_ IBackgroundCopyJob *Job ); +VOID DisplayProgress( _In_ IBackgroundCopyJob *Job ); +VOID DisplayHeaders( _In_ LPWSTR Headers ); +VOID DisplayError( _In_ IBackgroundCopyJob *Job ); + + + +/* + * Main program entry point + */ +int _tmain(int argc, _TCHAR* argv[]) +{ + HRESULT hr; + IBackgroundCopyManager *Manager; + + // Get the BITS Background Copy Manager + hr = GetBackgroundCopyManager(&Manager); + if( SUCCEEDED( hr ) ) + { + IBackgroundCopyJob *Job; + + // Create a new download job + hr = CreateDownloadJob( L"MyJob", Manager, &Job ); + if( SUCCEEDED(hr) ) + { + // Add the files to the job + for( int i=0; iAddFile( + FileList[i].RemoteFile, + FileList[i].LocalFile + ); + + if( FAILED(hr) ) + { + printf( + "Error: Unable to add remote file '%ws' to the download job (error %08X).\n", + FileList[i].RemoteFile, + hr + ); + } + else + { + printf( + "Downloading remote file '%ws' to local file '%ws'\n", + FileList[i].RemoteFile, + FileList[i].LocalFile + ); + } + } + + + // Start the job and display its progress + hr = Job->Resume(); + if( FAILED(hr) ) + { + printf( "ERROR: Unable to start the BITS download job (error code %08X).\n", hr ); + } + else + { + MonitorJobProgress( Job ); + } + + // Release the BITS IBackgroundCopyJob interface + Job->Release(); + Job = NULL; + } + + // Release the IBackgroundCopyManager interface + Manager->Release(); + Manager = NULL; + } + + return 0; +} + + + +/** + * Gets a pointer to the BITS Background Copy Manager. + * + * If successful, it returns a success code and sets the + * referenced IBackgroundCopyFileManager interface pointer + * to a reference counted instance of the Background Copy Manager + * interface. + */ +HRESULT +GetBackgroundCopyManager(_Out_ IBackgroundCopyManager **Manager) +{ + HRESULT hr; + + //Specify the appropriate COM threading model for your application. + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(hr)) + { + hr = CoCreateInstance( + __uuidof(BackgroundCopyManager), + NULL, + CLSCTX_LOCAL_SERVER, + __uuidof(IBackgroundCopyManager), + (void**) Manager + ); + } + else + { + printf( "ERROR: Unable to initialize COM (error code %08X).\n", hr ); + } + + return hr; +} + + + +/** + * Creates a new download job with the specified name. + */ +HRESULT +CreateDownloadJob(_In_ LPCWSTR Name, _In_ IBackgroundCopyManager *Manager, _Out_ IBackgroundCopyJob **Job) +{ + HRESULT hr; + GUID guid; + + hr = Manager->CreateJob( + Name, + BG_JOB_TYPE_DOWNLOAD, + &guid, + Job + ); + + return hr; +} + + + +/** + * Monitors and displays the progress of the download job. + * + * A new status message is output whenever the job's status changes or, + * when transferring data, every 2 seconds displays how much data + * has been transferred. + */ +HRESULT +MonitorJobProgress( _In_ IBackgroundCopyJob *Job ) +{ + HRESULT hr; + LPWSTR JobName; + BG_JOB_STATE State; + int PreviousState = -1; + bool Exit = false; + int ProgressCounter = 0; + + hr = Job->GetDisplayName( &JobName ); + printf( "Progress report for download job '%ws'.\n", JobName ); + + // display the download progress + while( !Exit ) + { + hr = Job->GetState( &State ); + + if( State != PreviousState ) + { + + switch( State ) + { + case BG_JOB_STATE_QUEUED: + printf( "Job is in the queue and waiting to run.\n" ); + break; + + case BG_JOB_STATE_CONNECTING: + printf( "BITS is trying to connect to the remote server.\n" ); + break; + + case BG_JOB_STATE_TRANSFERRING: + printf( "BITS has started downloading data.\n" ); + DisplayProgress( Job ); + break; + + case BG_JOB_STATE_ERROR: + printf( "ERROR: BITS has encountered a non-recoverable error (error code %08X).\n", GetLastError() ); + printf( " Exiting job.\n" ); + Exit = true; + break; + + case BG_JOB_STATE_TRANSIENT_ERROR: + printf( "ERROR: BITS has encountered a recoverable error.\n" ); + DisplayError( Job ); + printf( " Continuing to retry.\n" ); + break; + + case BG_JOB_STATE_TRANSFERRED: + DisplayProgress( Job ); + printf( "The job has been successfully completed.\n" ); + printf( "Finalizing local files.\n" ); + Job->Complete(); + break; + + case BG_JOB_STATE_ACKNOWLEDGED: + printf( "Finalization complete.\n" ); + Exit = true; + break; + + case BG_JOB_STATE_CANCELLED: + printf( "WARNING: The job has been cancelled.\n" ); + Exit = true; + break; + + default: + printf( "WARNING: Unknown BITS state %d.\n", State ); + Exit = true; + } + + PreviousState = State; + } + + else if (State == BG_JOB_STATE_TRANSFERRING ) + { + // display job progress every 2 seconds + if( ++ProgressCounter % TWO_SECOND_LOOP == 0 ) + { + DisplayProgress( Job ); + } + } + + Sleep(HALF_SECOND_AS_MILLISECONDS); + } + + printf("\n"); + + if( SUCCEEDED(hr) ) + { + hr = DisplayFileHeaders( Job ); + } + + return hr; +} + + + +/** + * For each file in the job, obtains the (final) HTTP headers received from the + * remote server that hosts the files and then displays the HTTP headers. + */ +HRESULT +DisplayFileHeaders( _In_ IBackgroundCopyJob *Job ) +{ + HRESULT hr; + IEnumBackgroundCopyFiles *FileEnumerator; + + printf( "Individual file information.\n" ); + + hr = Job->EnumFiles( &FileEnumerator ); + if( FAILED(hr) ) + { + printf( "WARNING: Unable to obtain an IEnumBackgroundCopyFiles interface.\n"); + printf( " No further information can be provided about the files in the job.\n"); + } + else + { + ULONG Count; + + hr = FileEnumerator->GetCount( &Count ); + if( FAILED(hr) ) + { + printf("WARNING: Unable to obtain a count of the number of files in the job.\n" ); + printf( " No further information can be provided about the files in the job.\n"); + } + else + { + for( ULONG i=0; i < Count; ++i ) + { + IBackgroundCopyFile *TempFile; + + hr = FileEnumerator->Next(1, &TempFile, NULL); + if( FAILED(hr) ) + { + printf("WARNING: Unable to obtain an IBackgroundCopyFile interface for the next file in the job.\n" ); + printf( " No further information can be provided about this file.\n"); + } + else + { + IBackgroundCopyFile5 *File; + hr = TempFile->QueryInterface( __uuidof( IBackgroundCopyFile5 ), (void **) &File ); + if( FAILED(hr) ) + { + printf("WARNING: Unable to obtain an IBackgroundCopyFile5 interface for the file.\n" ); + printf( " No further information can be provided about this file.\n"); + } + else + { + LPWSTR RemoteFileName; + hr = File->GetRemoteName( &RemoteFileName ); + if( FAILED(hr) ) + { + printf("WARNING: Unable to obtain the remote file name for this file.\n" ); + } + else + { + printf("HTTP headers for remote file '%ws'\n", RemoteFileName ); + CoTaskMemFree( RemoteFileName ); + RemoteFileName = NULL; + } + + BITS_FILE_PROPERTY_VALUE Value; + hr = File->GetProperty( + BITS_FILE_PROPERTY_ID_HTTP_RESPONSE_HEADERS, + &Value + ); + if( FAILED(hr) ) + { + printf("WARNING: Unable to obtain the HTTP headers for this file.\n" ); + } + else + { + if(Value.String) + { + DisplayHeaders( Value.String ); + CoTaskMemFree( Value.String ); + Value.String = NULL; + } + } + + File->Release(); + File = NULL; + } + + TempFile->Release(); + TempFile = NULL; + } + } + } + + FileEnumerator->Release(); + FileEnumerator = NULL; + } + + return S_OK; +} + + +/** + * Displays the current progress of the job in terms of the amount of data + * and number of files transferred. + */ +VOID +DisplayProgress( _In_ IBackgroundCopyJob *Job ) +{ + HRESULT hr; + BG_JOB_PROGRESS Progress; + + hr = Job->GetProgress( &Progress ); + if( SUCCEEDED(hr) ) + { + printf( + "%llu of %llu bytes transferred (%lu of %lu files).\n", + Progress.BytesTransferred, Progress.BytesTotal, + Progress.FilesTransferred, Progress.FilesTotal + ); + } + else + { + printf( "ERROR: Unable to get job progress (error code %08X).\n", hr ); + } +} + + + +/** + * Parses the provided string containing HTTP headers, + * splits them apart and displays them to the user. + */ +VOID +DisplayHeaders( _In_ LPWSTR Headers ) +{ + printf("Headers: %ws\n", Headers ); +} + + +VOID +DisplayError( _In_ IBackgroundCopyJob *Job ) +{ + HRESULT hr; + IBackgroundCopyError *Error; + LPWSTR ErrorDescription; + + hr = Job->GetError( &Error ); + if( FAILED(hr) ) + { + printf( "WARNING: Error details are not available.\n"); + } + else + { + hr = Error->GetErrorDescription( LANGIDFROMLCID(GetThreadLocale()), &ErrorDescription ); + if( SUCCEEDED(hr) ) + { + printf( " Error details: %ws\n", ErrorDescription ); + CoTaskMemFree( ErrorDescription ); + } + Error->Release(); + } +} + diff --git a/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.sln b/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.sln new file mode 100644 index 00000000..9d86b856 --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACKGROUNDCOPYFILEPROPERTIES", "BACKGROUNDCOPYFILEPROPERTIES.vcxproj", "{CC7D5649-E034-4A46-92E3-44F19B50433E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CC7D5649-E034-4A46-92E3-44F19B50433E}.Debug|Win32.ActiveCfg = Debug|Win32 + {CC7D5649-E034-4A46-92E3-44F19B50433E}.Debug|Win32.Build.0 = Debug|Win32 + {CC7D5649-E034-4A46-92E3-44F19B50433E}.Debug|Win32.Deploy.0 = Debug|Win32 + {CC7D5649-E034-4A46-92E3-44F19B50433E}.Release|Win32.ActiveCfg = Release|Win32 + {CC7D5649-E034-4A46-92E3-44F19B50433E}.Release|Win32.Build.0 = Release|Win32 + {CC7D5649-E034-4A46-92E3-44F19B50433E}.Release|Win32.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.vcxproj b/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.vcxproj new file mode 100644 index 00000000..0c6292af --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/cpp/BACKGROUNDCOPYFILEPROPERTIES.vcxproj @@ -0,0 +1,96 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {CC7D5649-E034-4A46-92E3-44F19B50433E} + Win32Proj + BACKGROUNDCOPYFILEPROPERTIES + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + Create + Create + + + + + + \ No newline at end of file diff --git a/Samples/BackgroundCopyFileProperties/cpp/stdafx.cpp b/Samples/BackgroundCopyFileProperties/cpp/stdafx.cpp new file mode 100644 index 00000000..f218b74d --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/cpp/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// BACKGROUNDCOPYFILEPROPERTIES.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Samples/BackgroundCopyFileProperties/cpp/stdafx.h b/Samples/BackgroundCopyFileProperties/cpp/stdafx.h new file mode 100644 index 00000000..b005a839 --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/cpp/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/Samples/BackgroundCopyFileProperties/cpp/targetver.h b/Samples/BackgroundCopyFileProperties/cpp/targetver.h new file mode 100644 index 00000000..87c0086d --- /dev/null +++ b/Samples/BackgroundCopyFileProperties/cpp/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/Samples/BasicPlugins/README.md b/Samples/BasicPlugins/README.md new file mode 100644 index 00000000..4f86369b --- /dev/null +++ b/Samples/BasicPlugins/README.md @@ -0,0 +1,53 @@ +Windows Powershell basic OData Web Service sample +================================================= + +This sample is an implementation of the two interfaces that authorize all incoming users and provides everyone default Windows PowerShell session configuration. Using the Management OData Web Service requires a third party to implement the Microsoft.Management.OData.CustomAuthorization and System.Management.Automation.Remoting.PSSessionConfiguration interfaces to expose PowerShell cmdlets. These interfaces perform user authorization and provide PowerShell session configuration. + +**Important** This sample requires Microsoft Visual Studio 2010, 2013, or later versions (any SKU). It doesn't compile in Microsoft Visual Studio Express 2013 for Windows. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Operating system requirements +----------------------------- + +Client + +None supported + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +This sample must be built on a computer that is running Windows Server 2012 R2 with the **Management OData IIS Extension** feature installed. To install this feature: + +1. Open an elevated PowerShell window. +2. Enter **Set-ExecutionPolicy -ExecutionPolicy Unrestricted**. +3. Enter *TargetDirectory* **PswsBasicPlugins\\C\#\\setup\\InstallModata.ps1**. + +To build the sample using Visual Studio: + +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 BasicPlugins.sln. + +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. + +To build the sample from a Command Prompt window: + +1. Open a Command Prompt window and navigate to the sample directory. +2. Enter **msbuild BasicPlugins.sln**. + +Run the sample +-------------- + +1. Open an elevated PowerShell window. +2. Navigate to the solution \\Debug or \\Release directory. +3. Enter **.\\setupEndPoint.ps1**. + diff --git a/Samples/BasicPlugins/cs/AssemblyInfo.cs b/Samples/BasicPlugins/cs/AssemblyInfo.cs new file mode 100644 index 00000000..71d014e9 --- /dev/null +++ b/Samples/BasicPlugins/cs/AssemblyInfo.cs @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2011 Microsoft Corporation +// +//----------------------------------------------------------------------- + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.Samples.Management.OData.BasicPlugins")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("BasicPlugins")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("64afdb50-5881-4d34-9017-c2fdc9155389")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Samples/BasicPlugins/cs/BasicPlugins.csproj b/Samples/BasicPlugins/cs/BasicPlugins.csproj new file mode 100644 index 00000000..c638072e --- /dev/null +++ b/Samples/BasicPlugins/cs/BasicPlugins.csproj @@ -0,0 +1,66 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {861C2EFA-3641-4648-BE54-54950B7824CB} + Library + Properties + Microsoft.Samples.Management.OData.BasicPlugins + Microsoft.Samples.Management.OData.BasicPlugins + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + + + + + + False + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/BasicPlugins/cs/BasicPlugins.sln b/Samples/BasicPlugins/cs/BasicPlugins.sln new file mode 100644 index 00000000..bb2a32f5 --- /dev/null +++ b/Samples/BasicPlugins/cs/BasicPlugins.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicPlugins", "BasicPlugins.csproj", "{861C2EFA-3641-4648-BE54-54950B7824CB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {861C2EFA-3641-4648-BE54-54950B7824CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {861C2EFA-3641-4648-BE54-54950B7824CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {861C2EFA-3641-4648-BE54-54950B7824CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {861C2EFA-3641-4648-BE54-54950B7824CB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/BasicPlugins/cs/CustomAuthorization.cs b/Samples/BasicPlugins/cs/CustomAuthorization.cs new file mode 100644 index 00000000..903c4b93 --- /dev/null +++ b/Samples/BasicPlugins/cs/CustomAuthorization.cs @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2011 Microsoft Corporation +// +//----------------------------------------------------------------------- + +namespace Microsoft.Samples.Management.OData.BasicPlugins +{ + using System.Configuration; + using System.Globalization; + using System.Security.Principal; + using Microsoft.Management.Odata; + + /// + /// Basic CustomAuthorization implementation + /// Management OData service uses Microsoft.Management.Odata.CustomAuthorization interface to authorize a user. + /// This is a pass-through implementation which means it authorizes all users. + /// It gives same quota values for all users. The quota values can be overridden by following application settings: + /// MaxConcurrentRequests: Overrides maximum number of concurrent requests for a user + /// MaxRequestsPerTimeslot: Overrides maximum number of requests in a time slot + /// TimeslotSize: Override size of time slot (in seconds) + /// + public class CustomAuthorization : Microsoft.Management.Odata.CustomAuthorization + { + /// + /// Default value of max concurrent requests + /// + private const int DefaultMaxConcurrentRequests = 10; + + /// + /// Default value of max request per time slot + /// + private const int DefaultMaxRequestsPerTimeslot = 4; + + /// + /// Default time slot size + /// + private const int DefaultTimeslotSize = 1; + + /// + /// Default managemnet system state key + /// + private const string DefaultManagementSystemStateId = "E7D438A1-C0BA-49D6-952E-EF7C45CB737D"; + + /// + /// Authorize a user. + /// + /// Sender information + /// User quota value + /// User context in which to execute PowerShell cmdlet + public override WindowsIdentity AuthorizeUser(SenderInfo senderInfo, out UserQuota userQuota) + { + var maxConcurrentRequests = ConfigurationManager.AppSettings["MaxConcurrentRequests"]; + var maxRequestsPerTimeslot = ConfigurationManager.AppSettings["MaxRequestsPerTimeslot"]; + var timeslotSize = ConfigurationManager.AppSettings["TimeslotSize"]; + + userQuota = new UserQuota( + maxConcurrentRequests != null ? int.Parse(maxConcurrentRequests, CultureInfo.CurrentUICulture) : DefaultMaxConcurrentRequests, + maxRequestsPerTimeslot != null ? int.Parse(maxRequestsPerTimeslot, CultureInfo.CurrentUICulture) : DefaultMaxRequestsPerTimeslot, + timeslotSize != null ? int.Parse(timeslotSize, CultureInfo.CurrentUICulture) : DefaultTimeslotSize); + + return WindowsIdentity.GetCurrent(); + } + + /// + /// Gets membership id + /// + /// Sender information + /// Always returns same membership id for all users which means all users are in same group + public override string GetMembershipId(SenderInfo senderInfo) + { + return DefaultManagementSystemStateId; + } + } +} \ No newline at end of file diff --git a/Samples/BasicPlugins/cs/SessionConfiguration.cs b/Samples/BasicPlugins/cs/SessionConfiguration.cs new file mode 100644 index 00000000..92134fd1 --- /dev/null +++ b/Samples/BasicPlugins/cs/SessionConfiguration.cs @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2011 Microsoft Corporation +// +//----------------------------------------------------------------------- + +namespace Microsoft.Samples.Management.OData.BasicPlugins +{ + using System.IO; + using System.Linq; + using System.Management.Automation; + using System.Management.Automation.Remoting; + using System.Management.Automation.Runspaces; + using System.Web; + + /// + /// PSSessionConfigruation implementation + /// Management OData serivce uses PSSessionConfiguration interface to get PowerShell session configuration for a user + /// This implementation gives same PowerShell session configuration for all users. + /// It adds all the PowerShell modules (*.psm1) and PowerShell scripts (*-*.ps1) files into the PowerShell session configuration. + /// + public class SessionConfiguration : PSSessionConfiguration + { + /// + /// Gets application private data + /// + /// Sender information + /// Always returns null + public override PSPrimitiveDictionary GetApplicationPrivateData(PSSenderInfo senderInfo) + { + return null; + } + + /// + /// Gets custom initial session state + /// + /// Sender information + /// Custom initial Session state + public override InitialSessionState GetInitialSessionState(PSSenderInfo senderInfo) + { + var initialSessionState = InitialSessionState.CreateDefault(); + + var dir = HttpContext.Current != null ? HttpContext.Current.Server.MapPath(".") : Directory.GetCurrentDirectory(); + + initialSessionState.ImportPSModule(Directory.EnumerateFiles(dir, "*.psm1") + .Select(s => Path.Combine(dir, Path.GetFileNameWithoutExtension(s))).ToArray()); + + foreach (var cmdletFileName in Directory.EnumerateFiles(dir, "*-*.ps1")) + { + initialSessionState.Commands.Add( + new SessionStateFunctionEntry(Path.GetFileNameWithoutExtension(cmdletFileName), File.ReadAllText(Path.Combine(dir, cmdletFileName)))); + } + + return initialSessionState; + } + } +} diff --git a/Samples/BasicPlugins/cs/setup/InstallModata.ps1 b/Samples/BasicPlugins/cs/setup/InstallModata.ps1 new file mode 100644 index 00000000..6d408584 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/InstallModata.ps1 @@ -0,0 +1,11 @@ +############################################################################### +# Installs Management OData Service optional component +############################################################################### + +&"$Env:SystemRoot\System32\Dism.exe" /online /enable-feature /FeatureName:ManagementOdata /all /Quiet /NoRestart + +&"$Env:SystemRoot\System32\Dism.exe" /online /enable-feature /featurename:WCF-HTTP-Activation45 /all /Quiet /NoRestart + +&"$Env:SystemRoot\System32\Dism.exe" /online /enable-feature /featurename:IIS-BasicAuthentication /featurename:IIS-WindowsAuthentication /all /Quiet /NoRestart + +&"$Env:SystemRoot\System32\Dism.exe" /online /enable-feature /featurename:IIS-WebServerManagementTools /featurename:IIS-ManagementConsole /featurename:IIS-ManagementScriptingTools /featurename:IIS-ManagementService /featurename:IIS-IIS6ManagementCompatibility /featurename:IIS-Metabase /featurename:IIS-WMICompatibility /featurename:IIS-LegacyScripts /featurename:IIS-LegacySnapIn /all /Quiet /NoRestart diff --git a/Samples/BasicPlugins/cs/setup/Microsoft.Management.Odata.svc b/Samples/BasicPlugins/cs/setup/Microsoft.Management.Odata.svc new file mode 100644 index 00000000..233b9fc6 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/Microsoft.Management.Odata.svc @@ -0,0 +1 @@ +<%@ ServiceHost Language="C#" Debug="true" Factory="System.Data.Services.DataServiceHostFactory, System.Data.Services, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Service="Microsoft.Management.Odata.DataService, Microsoft.Management.OData, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> \ No newline at end of file diff --git a/Samples/BasicPlugins/cs/setup/Readme.txt b/Samples/BasicPlugins/cs/setup/Readme.txt new file mode 100644 index 00000000..149b7b50 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/Readme.txt @@ -0,0 +1,6 @@ + +Instructions to setup Management OData web service endpoint: + +1. Copy the Microsoft.Samples.Management.OData.BasicPlugins.dll to current folder. Or build the sample. + +2. Execute .\setupEndPoint.ps1 diff --git a/Samples/BasicPlugins/cs/setup/Schema.mof b/Samples/BasicPlugins/cs/setup/Schema.mof new file mode 100644 index 00000000..eb469d15 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/Schema.mof @@ -0,0 +1,180 @@ + +class PswsTest_Service +{ + [Key] String ServiceName; + [Required] String DisplayName; + [Required] String MachineName; + [Required] String ServiceType; + [Required, EmbeddedInstance("PswsTest_DependentService")] String ServicesDependentOn []; + [Required] Boolean CanPauseAndContinue; + [Required] Boolean CanShutdown; + [Required] Boolean CanStop; + [Required, Etag] String Status; +}; + +class PswsTest_Process +{ + [Key] SInt32 Id; + [Required] SInt32 BasePriority; + [Required, EmbeddedInstance("PowerShell_PSCredential")] String Credential; + [Required, EmbeddedInstance("PswsTest_ProcessModule")] String Modules[]; + [Required] SInt32 HandleCount; + [Required] String MachineName; + [Required] SInt32 MainWindowHandle; + [Required] String MainWindowTitle; + [Required] SInt32 NonpagedSystemMemorySize; + [Required] SInt64 NonpagedSystemMemorySize64; + [Required] SInt32 PagedMemorySize; + [Required] SInt64 PagedMemorySize64; + [Required] SInt32 PagedSystemMemorySize; + [Required] SInt64 PagedSystemMemorySize64; + [Required] SInt32 PeakPagedMemorySize; + [Required] SInt64 PeakPagedMemorySize64; + [Required] SInt32 PeakWorkingSet; + [Required] SInt64 PeakWorkingSet64; + [Required] SInt32 PeakVirtualMemorySize; + [Required] SInt64 PeakVirtualMemorySize64; + [Required] SInt32 PrivateMemorySize; + [Required] SInt64 PrivateMemorySize64; + [Required] String ProcessName; + [Required] Boolean Responding; + [Required] SInt32 SessionId; + [Required, EmbeddedInstance("PswsTest_ProcessStartInfo")] String StartInfo; + [Required] SInt32 VirtualMemorySize; + [Required] SInt64 VirtualMemorySize64; + [Required] Boolean EnableRaisingEvents; + [Required] SInt32 WorkingSet; + [Required] SInt64 WorkingSet64; +}; + +[ComplexType] +class PswsTest_DependentService +{ + String ServiceName; +}; + +[ComplexType] +class PswsTest_ProcessModule +{ + String ModuleName; + String FileName; +}; + +[ComplexType] +class PswsTest_ProcessStartInfo +{ + String Verb; + String Arguments; + Boolean CreateNoWindow; + Boolean RedirectStandardInput; + Boolean RedirectStandardOutput ; + Boolean RedirectStandardError; + [EmbeddedInstance("PswsTest_Encoding")] String StandardErrorEncoding; + [EmbeddedInstance("PswsTest_Encoding")] String StandardOutputEncoding; + Boolean UseShellExecute; + String UserName ; + [EmbeddedInstance("PswsTest_SecureString")] String Password; + String Domain; + Boolean LoadUserProfile; + String FileName; + String WorkingDirectory ; + Boolean ErrorDialog ; + SInt32 ErrorDialogParentHandle; + String WindowStyle; +}; + +[ComplexType] +class PswsTest_FileVersionInfo +{ + String Comments; + String CompanyName; + SInt32 FileBuildPart; + String FileDescription; + sInt32 FileMajorPart; + SInt32 FileMinorPart; + String FileName; + SInt32 FilePrivatePart; + String FileVersion; + String InternalName; + Boolean IsDebug; + Boolean IsPatched; + Boolean IsPrivateBuild; + Boolean IsPreRelease; + Boolean IsSpecialBuild; + String Language; + String LegalCopyright; + String LegalTrademarks; + String OriginalFilename; + String PrivateBuild; + SInt32 ProductBuildPart; + SInt32 ProductMajorPart; + SInt32 ProductMinorPart; + String ProductName; + SInt32 ProductPrivatePart; + String ProductVersion; + String SpecialBuild; +}; + +[ComplexType] +class PswsTest_Encoding +{ + String BodyName; + String EncodingName; + String HeaderName; + String WebName; + SInt32 WindowsCodePage; + Boolean IsBrowserDisplay; + Boolean IsBrowserSave; + Boolean IsMailNewsDisplay; + Boolean IsMailNewsSave; + Boolean IsSingleByte; + [EmbeddedInstance("PswsTest_EncoderFallback")] String EncoderFallback; + [EmbeddedInstance("PswsTest_DecoderFallback")] String DecoderFallback; + Boolean IsReadOnly; + SInt32 CodePage; +}; + +[ComplexType] +class PswsTest_EncoderFallback +{ + SInt32 MaxCharCount; +}; + +[ComplexType] +class PswsTest_DecoderFallback +{ + SInt32 MaxCharCount; +}; + +[ComplexType] +class PswsTest_SecureString +{ + SInt32 Length; +}; + +[ComplexType] +class PswsTest_ProcessThread +{ + SInt32 BasePriority; + SInt32 CurrentPriority; + SInt32 Id; + SInt32 IdealProcessor; + String PriorityLevel; + SInt32 StartAddress; + String ThreadState; + String WaitReason; + SInt32 ProcessorAffinity; +}; + +[ComplexType] +class PswsTest_Stream +{ + Boolean CanRead; + Boolean CanSeek; + Boolean CanTimeout; + Boolean CanWrite; + SInt64 Length; + SInt64 Position; + SInt32 ReadTimeout; + SInt32 WriteTimeout; +}; diff --git a/Samples/BasicPlugins/cs/setup/Schema.xml b/Samples/BasicPlugins/cs/setup/Schema.xml new file mode 100644 index 00000000..4acccd79 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/Schema.xml @@ -0,0 +1,163 @@ + + + PswsTest + PSWSEntityContainer + + + Service + PswsTest_Service + + + Process + PswsTest_Process + + + + + PswsTest_Service + + + Get-Service + + + ServiceName + Name + + + + + Default + NameSystem.String[] + ComputerNameSystem.String[] + IncludeSystem.String[] + ExcludeSystem.String[] + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + DisplayName + DisplayNameSystem.String[] + ComputerNameSystem.String[] + IncludeSystem.String[] + ExcludeSystem.String[] + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + InputObject + ComputerNameSystem.String[] + IncludeSystem.String[] + ExcludeSystem.String[] + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + + + Set-Service + + + ServiceName + Name + + + + + Name + ComputerNameSystem.String[] + Name + DisplayName + Description + Status + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + InputObject + ComputerNameSystem.String[] + DisplayName + Description + + + + + New-Service + + + ServiceName + Name + + + + + __AllParameterSets + BinaryPathName + Name + DisplayName + Description + DependsOn + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + + + + + PswsTest_Process + + + Get-Process + + + ProcessName + Name + + + Id + Id + + + + + Name + NameSystem.String[] + ComputerNameSystem.String[] + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + Id + IdSystem.Int32[] + ComputerNameSystem.String[] + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + InputObject + ComputerNameSystem.String[] + ErrorVariable + WarningVariable + OutVariable + OutBuffer + + + + + + + diff --git a/Samples/BasicPlugins/cs/setup/SetupEndpoint.ps1 b/Samples/BasicPlugins/cs/setup/SetupEndpoint.ps1 new file mode 100644 index 00000000..c0ac1f16 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/SetupEndpoint.ps1 @@ -0,0 +1,33 @@ +############################################################################### +# Configures Management OData web service endpoint using the Basic plugins +# sample +############################################################################### + +# Test for presence of Microsoft.Samples.Management.OData.BasicPlugins.dll +$assemblyName = ".\Microsoft.Samples.Management.OData.BasicPlugins.dll" + +$customPluginAssembly = $assemblyName +if (!(Test-Path $customPluginAssembly)) +{ + $customPluginAssembly = "..\bin\Debug\$assemblyName" + + if (!(Test-Path $customPluginAssembly)) + { + $customPluginAssembly = "..\bin\Release\$assemblyName" + + if (!(Test-Path $customPluginAssembly)) + { + throw "ERROR: Custom plugin assembly $assemblyName not found. Please either put it in the current folder or build the sample (so that it can be picked from bin folder)"; + } + } +} + +# Installing Management OData optional component +Write-Host "Installing Management OData Service..." +.\installModata.ps1 + +# Setting up web service endpoint +Write-Host "Setting up web service endpoint..." +.\SetupIISConfig.ps1 -site MODataSvc -path $env:HOMEDRIVE\inetpub\wwwroot\Modata -cfgfile .\Web.config -port 7000 -app MODataSvc -svc .\Microsoft.Management.Odata.svc -schema .\Schema.mof -dispatchXml .\Schema.xml -customPluginAssembly $customPluginAssembly + +Write-Host "Web Service endpoint is setup. The source root URI is http://localhost:7000/MODataSvc/Microsoft.Management.Odata.svc" diff --git a/Samples/BasicPlugins/cs/setup/SetupIISConfig.ps1 b/Samples/BasicPlugins/cs/setup/SetupIISConfig.ps1 new file mode 100644 index 00000000..a94cb798 --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/SetupIISConfig.ps1 @@ -0,0 +1,332 @@ +############################################################################### +# Script to setup IIS endpoint +############################################################################### +param($site = $(throw " site is a required parameter."), +$path = $(throw " path is a required parameter."), +$cfgfile = $(throw " cfgfile is a required parameter."), +$port = $(throw " port is a required parameter."), +$app = $(throw " app is a required parameter."), +$svc = $(throw " WCF Web Service File is a required parameter."), +$schema = $(throw " schema is a required parameter."), +$dispatchXml = $(throw " Dispatch Xml is a required parameter."), +$customPluginAssembly = $(throw " Custom plugin assembly."), +[switch]$silent = $false) + +Function Log +{ + param($data = $(throw "data is a required parameter.")) + if (!($silent)) + { + $data | Out-Host + } +} + +Function ParseCommandLine +{ + param($site, + $path, + $cfgfile, + $port, + $app, + $svc, + $schema, + $dispatchXml, + $customPluginAssembly) + + if (!(Test-Path $cfgfile)) + { + Log "Web.Config file does not exist" + exit -1 + } + + if (!(Test-Path $svc)) + { + Log "WCF WebService File does not exist" + exit -1 + } + + if (!(Test-Path $schema)) + { + Log "Schema File does not exist" + exit -1 + } + + if (!(Test-Path $dispatchXml)) + { + Log "Dispatch Xml File does not exist" + exit -1 + } + + if (!(Test-Path $customPluginAssembly)) + { + Log "Custom plugin assembly file does not exist" + exit -1 + } + + IsIIsInstalled + + $appPool = "MOData" + + Log "Delete the App Pool if it exists." + DeleteAppPool -apppool $appPool + + Log "Delete the site if it exists." + ActionOneSite -site $site -siteaction delete + BackUpIISConfig + + # Create physical path dir if required and copy required files + if (!(Test-Path $path)) + { + New-Item -ItemType container -Path $path + } + + ValidateAndCopyFiles -path $path -cfgfile $cfgfile -svc $svc -schema $schema -dispatchXml $dispatchXml -customPluginAssembly $customPluginAssembly + + ActionAllSites stop + DefaultAppPool stop + DefaultAppPool start + + SetupWebSite -site $site -path $path -port $port -app $app -apppool $appPool +} + +function IsIIsInstalled +{ + if ($script:SrvMgr -eq $null) + { + Log "Checking IIS requirements" + + $e = $null + $WSRegKey = (Get-ItemProperty hklm:\SYSTEM\CurrentControlSet\Services\W3SVC -ErrorAction silentlycontinue -ErrorVariable e).ImagePath + + if ($WSRegKey -eq $null) + { + Log "ERROR: Cannot retrive W3SVC key. IIS Web Services may not be installed" + exit + } + else + { + Log "W3SVC key ................. OK" + } + + $e = $null + $e = [System.Reflection.Assembly]::LoadFrom( "$env:windir\system32\inetsrv\Microsoft.Web.Administration.dll" ) + + $script:SrvMgr = New-Object Microsoft.Web.Administration.ServerManager -ErrorAction silentlycontinue -ErrorVariable e + + if ($script:SrvMgr -eq $null) + { + Log "ERROR: Cannot retrieve Microsoft.Web.Administration.ServerManager Object. IIS may not be installed" + exit + } + else + { + Log "IIS ServerManager Object .. OK" + } + + if ( (get-service w3svc).Status -ne "running") + { + Log "ERROR: service W3SVC is not running" + exit + } + else + { + Log "W3SVC Service ............ OK" + } + } +} + +Function SiteIsThere +{ + PARAM($SiteName) + $retval = $false + $sitelist = @(& $script:appcmd list site) + $sitelist | % { if($_.Split('"')[1] -eq $sitename) {$retval = $true} } + return $retval +} + +Function ActionOneSite +{ + param($site,$siteaction) + $type=$site.GetType() + $temp = $null + Log "Trying to $siteaction site $site" + #check to see if we are getting in a site object or just a string...just need the name. + if ($site.GetType() -eq [System.String]) + { + $temp = $site + } + else + { + $temp = $site.Name + } + + if (SiteIsThere $temp) + { + & $script:appcmd $siteaction site $temp + } +} + +Function DeleteAppPool +{ + param($apppool = $(throw " appool is a required parameter.")) + + Log "Delete $apppool AppPool" + & $script:appcmd delete apppool $apppool +} + +Function ActionAllSites +{ + param($action) + foreach ($site in $script:SrvMgr.sites) + { + ActionOneSite $site $action + } +} + +Function DefaultAppPool +{ + param($action) + Log "Trying to $action the default app pool" + $null = & $script:appcmd $action apppool /apppool.name:DefaultAppPool +} + +Function BackUpIISConfig +{ + $dt = Get-Date + $backupID = "MODataIISSetup_" + $dt.Year + "-" + $dt.Month + "-" + $dt.Day + "-" + $dt.Hour + "-" + $dt.Minute + "-" + $dt.Second + Log "Backing up IIS configuration to $backupID" + $null = & $script:appcmd add backup $backupID +} + +Function GenerateSiteID +{ + return ($script:SrvMgr.Sites | % { $_.Id } | Measure-Object -Maximum).Maximum + 1 +} + +Function ValidateAndCopyFiles +{ + param ($path = $(throw "path is a requred parameter."), + $cfgfile = $(throw "cfgfile is a requred parameter."), + $svc = $(throw "svc is a requred parameter."), + $schema = $(throw "schema is a requred parameter."), + $dispatchXml = $(throw "dispatchXml is a requred parameter."), + $customPluginAssembly = $(throw "Custom plugins assembly is a requred parameter.")) + + if (!(Test-Path $cfgfile)) + { + throw "ERROR: $cfgfile does not exist" + } + + if (!(Test-Path $svc)) + { + throw "ERROR: $svc does not exist" + } + + if (!(Test-Path $schema)) + { + throw "ERROR: $schema does not exist" + } + + if (!(Test-Path $dispatchXml)) + { + throw "ERROR: $dispatchXml does not exist" + } + + if (!(Test-Path $path)) + { + New-Item -ItemType container $path + } + + Copy-Item $cfgfile (Join-Path $path "web.config") + Copy-Item $svc $path + Copy-Item $schema $path + Copy-Item $dispatchXml $path + Copy-Item $customPluginAssembly $path +} + +Function UnlockAuthSections +{ + Log "Unlocking auth sections" + & $script:appcmd unlock config -section:access + & $script:appcmd unlock config -section:anonymousAuthentication + & $script:appcmd unlock config -section:basicAuthentication + & $script:appcmd unlock config -section:windowsAuthentication +} + +Function SetRequiredAuth +{ + param($effVdir) + + Log "Setting auth schemes on $effVdir" + + & $script:appcmd set config $effVdir /section:system.webServer/security/authentication/anonymousAuthentication /enabled:false /commit:apphost + & $script:appcmd set config $effVdir /section:system.webServer/security/authentication/basicAuthentication /enabled:true /commit:apphost + & $script:appcmd set config $effVdir /section:system.webServer/security/authentication/windowsAuthentication /enabled:true /commit:apphost +} + +Function SetupWebSite +{ + param($site = $(throw "site is a required parameter."), + $path = $(throw "path is a required parameter."), + $port = $(throw "port is a required parameter."), + $app = $(throw "app is a required paramater."), + $apppool = $(throw "apppool is a required paramater.")) + + $siteID = GenerateSiteID + + Log "Adding App Pool" + & $script:appcmd add apppool /name:$apppool + + Log "Set App Pool Properties" + & $script:appcmd set apppool /apppool.name:$apppool /managedRuntimeVersion:"v4.0" + + Log "Adding Site" + & $script:appcmd add site /name:$site /id:$siteID /bindings:http://*:$port /physicalPath:$ENV:systemdrive\inetpub\wwwroot + + Log "Set Site Properties" + & $script:appcmd set site /site.name:$site /[path=`'/`'].applicationPool:$apppool + + Log "Trying to delete application:$app." + $null=& $script:appcmd delete app $site/$app + + Log "Adding application:$app." + & $script:appcmd add app /site.name:$site /path:/$app /physicalPath:$path + + Log "Set application:$app." + & $script:appcmd set app /app.name:$site/$app /applicationPool:$apppool + + $effVdir = "$site" + + UnlockAuthSections + + SetRequiredAuth $effVdir + + ActionOneSite -site $site -siteaction start + +} + +Function CreateFirewallRule +{ + param($firewallPort) + + Log "Disable Inbound Firewall Notification" + & $script:netsh advfirewall set currentprofile settings inboundusernotification disable + + Log "Add Firewall Rule for port $firewallPort" + & $script:netsh advfirewall firewall add rule name=MOData_IIS_Port dir=in action=allow protocol=TCP localport=$firewallPort +} + + +$script:wshShell = New-Object -ComObject wscript.shell +$script:appcmd = "$env:windir\system32\inetsrv\appcmd.exe" +$script:SrvMgr = $null +$script:netsh ="$env:windir\system32\netsh.exe" + +Log ("Setting up test site at http://$ENV:COMPUTERNAME."+$ENV:USERDNSDOMAIN+":$port") +ParseCommandLine -site $site -path $path -cfgfile $cfgfile -port $port -app $app -svc $svc -schema $schema -dispatchXml $dispatchXml -customPluginAssembly $customPluginAssembly + +CreateFirewallRule $port + +ActionAllSites start + +Start-Sleep 10 \ No newline at end of file diff --git a/Samples/BasicPlugins/cs/setup/Web.config b/Samples/BasicPlugins/cs/setup/Web.config new file mode 100644 index 00000000..3293c98f --- /dev/null +++ b/Samples/BasicPlugins/cs/setup/Web.config @@ -0,0 +1,34 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CaptureEngineVideoCapture/README.md b/Samples/CaptureEngineVideoCapture/README.md new file mode 100644 index 00000000..5321691c --- /dev/null +++ b/Samples/CaptureEngineVideoCapture/README.md @@ -0,0 +1,76 @@ +CaptureEngine video capture sample +================================== + +This sample demonstrates how to use the [Media Foundation](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197) [**CaptureEngine**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh162749) to capture video from a capture device, such as a webcam. + +**Important** + +This is a desktop sample and not a Windows Store app sample. For information on video capture in a Windows Store app, see the [Windows 8 media capture sample](http://go.microsoft.com/fwlink/p/?linkid=241428). For information on creating Windows Store apps, see [Roadmap for apps using C++](http://msdn.microsoft.com/en-us/library/windows/desktop/hh700360), [Roadmap for apps using C\# and Visual Basic](http://msdn.microsoft.com/en-us/library/windows/desktop/br229583), and [Roadmap for apps using JavaScript](http://msdn.microsoft.com/en-us/library/windows/desktop/hh465037). + +**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. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +**Reference** + +[**CaptureEngine**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh162749) + +[Media Foundation](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197) + +[**Windows.Media.Capture**](http://msdn.microsoft.com/en-us/library/windows/desktop/br226738) + +**Roadmaps** + +[Roadmap for apps using C\# and Visual Basic](http://msdn.microsoft.com/en-us/library/windows/desktop/br229583) + +[Roadmap for apps using JavaScript](http://msdn.microsoft.com/en-us/library/windows/desktop/hh465037) + +[Roadmap for apps using C++](http://msdn.microsoft.com/en-us/library/windows/desktop/hh700360) + +[Designing UX for apps](http://msdn.microsoft.com/en-us/library/windows/desktop/hh767284) + +[Capturing or rendering audio, video, and images](http://msdn.microsoft.com/en-us/library/windows/desktop/hh465156) + +**Samples** + +[Media Control for Media Capture API sample](http://go.microsoft.com/fwlink/p/?linkid=241428) + +Related technologies +-------------------- + +[Media Foundation](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the 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 F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. + +**Warning** This sample requires Microsoft Visual Studio Professional 2012, Visual Studio 2013, or later versions of Visual Studio (any SKU) and will not compile in Visual Studio Express 2013 for Windows + +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/CaptureEngineVideoCapture/cpp/Capture.cpp b/Samples/CaptureEngineVideoCapture/cpp/Capture.cpp new file mode 100644 index 00000000..d82d06cf --- /dev/null +++ b/Samples/CaptureEngineVideoCapture/cpp/Capture.cpp @@ -0,0 +1,827 @@ +// 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 "Capture.h" +#include "resource.h" + +IMFDXGIDeviceManager* g_pDXGIMan = NULL; +ID3D11Device* g_pDX11Device = NULL; +UINT g_ResetToken = 0; + +STDMETHODIMP CaptureManager::CaptureEngineCB::QueryInterface(REFIID riid, void** ppv) +{ + static const QITAB qit[] = + { + QITABENT(CaptureEngineCB, IMFCaptureEngineOnEventCallback), + { 0 } + }; + return QISearch(this, qit, riid, ppv); +} + +STDMETHODIMP_(ULONG) CaptureManager::CaptureEngineCB::AddRef() +{ + return InterlockedIncrement(&m_cRef); +} + +STDMETHODIMP_(ULONG) CaptureManager::CaptureEngineCB::Release() +{ + LONG cRef = InterlockedDecrement(&m_cRef); + if (cRef == 0) + { + delete this; + } + return cRef; +} + +// Callback method to receive events from the capture engine. +STDMETHODIMP CaptureManager::CaptureEngineCB::OnEvent( _In_ IMFMediaEvent* pEvent) +{ + // Post a message to the application window, so the event is handled + // on the application's main thread. + + if (m_fSleeping && m_pManager != NULL) + { + // We're about to fall asleep, that means we've just asked the CE to stop the preview + // and record. We need to handle it here since our message pump may be gone. + GUID guidType; + HRESULT hrStatus; + HRESULT hr = pEvent->GetStatus(&hrStatus); + if (FAILED(hr)) + { + hrStatus = hr; + } + + hr = pEvent->GetExtendedType(&guidType); + if (SUCCEEDED(hr)) + { + if (guidType == MF_CAPTURE_ENGINE_PREVIEW_STOPPED) + { + m_pManager->OnPreviewStopped(hrStatus); + SetEvent(m_pManager->m_hEvent); + } + else if (guidType == MF_CAPTURE_ENGINE_RECORD_STOPPED) + { + m_pManager->OnRecordStopped(hrStatus); + SetEvent(m_pManager->m_hEvent); + } + else + { + // This is an event we don't know about, we don't really care and there's + // no clean way to report the error so just set the event and fall through. + SetEvent(m_pManager->m_hEvent); + } + } + + return S_OK; + } + else + { + pEvent->AddRef(); // The application will release the pointer when it handles the message. + PostMessage(m_hwnd, WM_APP_CAPTURE_EVENT, (WPARAM)pEvent, 0L); + } + + return S_OK; +} + +HRESULT CreateDX11Device(_Out_ ID3D11Device** ppDevice, _Out_ ID3D11DeviceContext** ppDeviceContext, _Out_ D3D_FEATURE_LEVEL* pFeatureLevel ) +{ + HRESULT hr = S_OK; + static const D3D_FEATURE_LEVEL levels[] = { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + + + hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + nullptr, + D3D11_CREATE_DEVICE_VIDEO_SUPPORT, + levels, + ARRAYSIZE(levels), + D3D11_SDK_VERSION, + ppDevice, + pFeatureLevel, + ppDeviceContext + ); + + if(SUCCEEDED(hr)) + { + ID3D10Multithread* pMultithread; + hr = ((*ppDevice)->QueryInterface(IID_PPV_ARGS(&pMultithread))); + + if(SUCCEEDED(hr)) + { + pMultithread->SetMultithreadProtected(TRUE); + } + + SafeRelease(&pMultithread); + + } + + return hr; +} + +HRESULT CreateD3DManager() +{ + HRESULT hr = S_OK; + D3D_FEATURE_LEVEL FeatureLevel; + ID3D11DeviceContext* pDX11DeviceContext; + + hr = CreateDX11Device(&g_pDX11Device, &pDX11DeviceContext, &FeatureLevel); + + if(SUCCEEDED(hr)) + { + hr = MFCreateDXGIDeviceManager(&g_ResetToken, &g_pDXGIMan); + } + + if(SUCCEEDED(hr)) + { + hr = g_pDXGIMan->ResetDevice(g_pDX11Device, g_ResetToken); + } + + SafeRelease(&pDX11DeviceContext); + + return hr; +} + +HRESULT +CaptureManager::InitializeCaptureManager(HWND hwndPreview, IUnknown* pUnk) +{ + HRESULT hr = S_OK; + IMFAttributes* pAttributes = NULL; + IMFCaptureEngineClassFactory* pFactory = NULL; + + DestroyCaptureEngine(); + + m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (NULL == m_hEvent) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto Exit; + } + + m_pCallback = new (std::nothrow) CaptureEngineCB(m_hwndEvent); + if (m_pCallback == NULL) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + + m_pCallback->m_pManager = this; + m_hwndPreview = hwndPreview; + + //Create a D3D Manager + hr = CreateD3DManager(); + if (FAILED(hr)) + { + goto Exit; + } + hr = MFCreateAttributes(&pAttributes, 1); + if (FAILED(hr)) + { + goto Exit; + } + hr = pAttributes->SetUnknown(MF_CAPTURE_ENGINE_D3D_MANAGER, g_pDXGIMan); + if (FAILED(hr)) + { + goto Exit; + } + + // Create the factory object for the capture engine. + hr = CoCreateInstance(CLSID_MFCaptureEngineClassFactory, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFactory)); + if (FAILED(hr)) + { + goto Exit; + } + + // Create and initialize the capture engine. + hr = pFactory->CreateInstance(CLSID_MFCaptureEngine, IID_PPV_ARGS(&m_pEngine)); + if (FAILED(hr)) + { + goto Exit; + } + hr = m_pEngine->Initialize(m_pCallback, pAttributes, NULL, pUnk); + if (FAILED(hr)) + { + goto Exit; + } + +Exit: + if (NULL != pAttributes) + { + pAttributes->Release(); + pAttributes = NULL; + } + if (NULL != pFactory) + { + pFactory->Release(); + pFactory = NULL; + } + return hr; +} + +// Handle an event from the capture engine. +// NOTE: This method is called from the application's UI thread. +HRESULT CaptureManager::OnCaptureEvent(WPARAM wParam, LPARAM lParam) +{ + GUID guidType; + HRESULT hrStatus; + + IMFMediaEvent *pEvent = reinterpret_cast(wParam); + + HRESULT hr = pEvent->GetStatus(&hrStatus); + if (FAILED(hr)) + { + hrStatus = hr; + } + + hr = pEvent->GetExtendedType(&guidType); + if (SUCCEEDED(hr)) + { + +#ifdef _DEBUG + LPOLESTR str; + if (SUCCEEDED(StringFromCLSID(guidType, &str))) + { + DBGMSG((L"MF_CAPTURE_ENGINE_EVENT: %s (hr = 0x%X)\n", str, hrStatus)); + CoTaskMemFree(str); + } +#endif + + if (guidType == MF_CAPTURE_ENGINE_INITIALIZED) + { + OnCaptureEngineInitialized(hrStatus); + SetErrorID(hrStatus, IDS_ERR_INITIALIZE); + } + else if (guidType == MF_CAPTURE_ENGINE_PREVIEW_STARTED) + { + OnPreviewStarted(hrStatus); + SetErrorID(hrStatus, IDS_ERR_PREVIEW); + } + else if (guidType == MF_CAPTURE_ENGINE_PREVIEW_STOPPED) + { + OnPreviewStopped(hrStatus); + SetErrorID(hrStatus, IDS_ERR_PREVIEW); + } + else if (guidType == MF_CAPTURE_ENGINE_RECORD_STARTED) + { + OnRecordStarted(hrStatus); + SetErrorID(hrStatus, IDS_ERR_RECORD); + } + else if (guidType == MF_CAPTURE_ENGINE_RECORD_STOPPED) + { + OnRecordStopped(hrStatus); + SetErrorID(hrStatus, IDS_ERR_RECORD); + } + else if (guidType == MF_CAPTURE_ENGINE_PHOTO_TAKEN) + { + m_bPhotoPending = false; + SetErrorID(hrStatus, IDS_ERR_PHOTO); + } + else if (guidType == MF_CAPTURE_ENGINE_ERROR) + { + DestroyCaptureEngine(); + SetErrorID(hrStatus, IDS_ERR_CAPTURE); + } + else if (FAILED(hrStatus)) + { + SetErrorID(hrStatus, IDS_ERR_CAPTURE); + } + } + + pEvent->Release(); + SetEvent(m_hEvent); + return hrStatus; +} + + +void CaptureManager::OnCaptureEngineInitialized(HRESULT& hrStatus) +{ + if (hrStatus == MF_E_NO_CAPTURE_DEVICES_AVAILABLE) + { + hrStatus = S_OK; // No capture device. Not an application error. + } +} + +void CaptureManager::OnPreviewStarted(HRESULT& hrStatus) +{ + m_bPreviewing = SUCCEEDED(hrStatus); +} + +void CaptureManager::OnPreviewStopped(HRESULT& hrStatus) +{ + m_bPreviewing = false; +} + +void CaptureManager::OnRecordStarted(HRESULT& hrStatus) +{ + m_bRecording = SUCCEEDED(hrStatus); +} + +void CaptureManager::OnRecordStopped(HRESULT& hrStatus) +{ + m_bRecording = false; +} + + +HRESULT CaptureManager::StartPreview() +{ + if (m_pEngine == NULL) + { + return MF_E_NOT_INITIALIZED; + } + + if (m_bPreviewing == true) + { + return S_OK; + } + + IMFCaptureSink *pSink = NULL; + IMFMediaType *pMediaType = NULL; + IMFMediaType *pMediaType2 = NULL; + IMFCaptureSource *pSource = NULL; + + HRESULT hr = S_OK; + + // Get a pointer to the preview sink. + if (m_pPreview == NULL) + { + hr = m_pEngine->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW, &pSink); + if (FAILED(hr)) + { + goto done; + } + + hr = pSink->QueryInterface(IID_PPV_ARGS(&m_pPreview)); + if (FAILED(hr)) + { + goto done; + } + + hr = m_pPreview->SetRenderHandle(m_hwndPreview); + if (FAILED(hr)) + { + goto done; + } + + hr = m_pEngine->GetSource(&pSource); + if (FAILED(hr)) + { + goto done; + } + + // Configure the video format for the preview sink. + hr = pSource->GetCurrentDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW , &pMediaType); + if (FAILED(hr)) + { + goto done; + } + + hr = CloneVideoMediaType(pMediaType, MFVideoFormat_RGB32, &pMediaType2); + if (FAILED(hr)) + { + goto done; + } + + hr = pMediaType2->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); + if (FAILED(hr)) + { + goto done; + } + + // Connect the video stream to the preview sink. + DWORD dwSinkStreamIndex; + hr = m_pPreview->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW, pMediaType2, NULL, &dwSinkStreamIndex); + if (FAILED(hr)) + { + goto done; + } + } + + + hr = m_pEngine->StartPreview(); + if (!m_fPowerRequestSet && m_hpwrRequest != INVALID_HANDLE_VALUE) + { + // NOTE: By calling this, on SOC systems (AOAC enabled), we're asking the system to not go + // into sleep/connected standby while we're streaming. However, since we don't want to block + // the device from ever entering connected standby/sleep, we're going to latch ourselves to + // the monitor on/off notification (RegisterPowerSettingNotification(GUID_MONITOR_POWER_ON)). + // On SOC systems, this notification will fire when the user decides to put the device in + // connected standby mode--we can trap this, turn off our media streams and clear this + // power set request to allow the device to go into the lower power state. + m_fPowerRequestSet = (TRUE == PowerSetRequest(m_hpwrRequest, PowerRequestExecutionRequired)); + } +done: + SafeRelease(&pSink); + SafeRelease(&pMediaType); + SafeRelease(&pMediaType2); + SafeRelease(&pSource); + + return hr; +} + +HRESULT CaptureManager::StopPreview() +{ + HRESULT hr = S_OK; + + if (m_pEngine == NULL) + { + return MF_E_NOT_INITIALIZED; + } + + if (!m_bPreviewing) + { + return S_OK; + } + hr = m_pEngine->StopPreview(); + if (FAILED(hr)) + { + goto done; + } + WaitForResult(); + + if (m_fPowerRequestSet && m_hpwrRequest != INVALID_HANDLE_VALUE) + { + PowerClearRequest(m_hpwrRequest, PowerRequestExecutionRequired); + m_fPowerRequestSet = false; + } +done: + return hr; +} + +// Helper function to get the frame size from a video media type. +inline HRESULT GetFrameSize(IMFMediaType *pType, UINT32 *pWidth, UINT32 *pHeight) +{ return MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, pWidth, pHeight);} + +// Helper function to get the frame rate from a video media type. +inline HRESULT GetFrameRate( + IMFMediaType *pType, + UINT32 *pNumerator, + UINT32 *pDenominator + ) +{ + return MFGetAttributeRatio( + pType, + MF_MT_FRAME_RATE, + pNumerator, + pDenominator + ); +} + + +HRESULT GetEncodingBitrate(IMFMediaType *pMediaType, UINT32 *uiEncodingBitrate) +{ + UINT32 uiWidth; + UINT32 uiHeight; + float uiBitrate; + UINT32 uiFrameRateNum; + UINT32 uiFrameRateDenom; + + HRESULT hr = GetFrameSize(pMediaType, &uiWidth, &uiHeight); + if (FAILED(hr)) + { + goto done; + } + + hr = GetFrameRate(pMediaType, &uiFrameRateNum, &uiFrameRateDenom); + if (FAILED(hr)) + { + goto done; + } + + uiBitrate = uiWidth / 3.0f * uiHeight * uiFrameRateNum / uiFrameRateDenom; + + *uiEncodingBitrate = (UINT32) uiBitrate; + +done: + + return hr; +} + +HRESULT ConfigureVideoEncoding(IMFCaptureSource *pSource, IMFCaptureRecordSink *pRecord, REFGUID guidEncodingType) +{ + IMFMediaType *pMediaType = NULL; + IMFMediaType *pMediaType2 = NULL; + GUID guidSubType = GUID_NULL; + + // Configure the video format for the recording sink. + HRESULT hr = pSource->GetCurrentDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_RECORD , &pMediaType); + if (FAILED(hr)) + { + goto done; + } + + hr = CloneVideoMediaType(pMediaType, guidEncodingType, &pMediaType2); + if (FAILED(hr)) + { + goto done; + } + + + hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubType); + if(FAILED(hr)) + { + goto done; + } + + if(guidSubType == MFVideoFormat_H264_ES || guidSubType == MFVideoFormat_H264) + { + //When the webcam supports H264_ES or H264, we just bypass the stream. The output from Capture engine shall be the same as the native type supported by the webcam + hr = pMediaType2->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); + } + else + { + UINT32 uiEncodingBitrate; + hr = GetEncodingBitrate(pMediaType2, &uiEncodingBitrate); + if (FAILED(hr)) + { + goto done; + } + + hr = pMediaType2->SetUINT32(MF_MT_AVG_BITRATE, uiEncodingBitrate); + } + + if (FAILED(hr)) + { + goto done; + } + + // Connect the video stream to the recording sink. + DWORD dwSinkStreamIndex; + hr = pRecord->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_RECORD, pMediaType2, NULL, &dwSinkStreamIndex); + +done: + SafeRelease(&pMediaType); + SafeRelease(&pMediaType2); + return hr; +} + +HRESULT ConfigureAudioEncoding(IMFCaptureSource *pSource, IMFCaptureRecordSink *pRecord, REFGUID guidEncodingType) +{ + IMFCollection *pAvailableTypes = NULL; + IMFMediaType *pMediaType = NULL; + IMFAttributes *pAttributes = NULL; + + // Configure the audio format for the recording sink. + + HRESULT hr = MFCreateAttributes(&pAttributes, 1); + if(FAILED(hr)) + { + goto done; + } + + // Enumerate low latency media types + hr = pAttributes->SetUINT32(MF_LOW_LATENCY, TRUE); + if(FAILED(hr)) + { + goto done; + } + + + // Get a list of encoded output formats that are supported by the encoder. + hr = MFTranscodeGetAudioOutputAvailableTypes(guidEncodingType, MFT_ENUM_FLAG_ALL | MFT_ENUM_FLAG_SORTANDFILTER, + pAttributes, &pAvailableTypes); + if (FAILED(hr)) + { + goto done; + } + + // Pick the first format from the list. + hr = GetCollectionObject(pAvailableTypes, 0, &pMediaType); + if (FAILED(hr)) + { + goto done; + } + + // Connect the audio stream to the recording sink. + DWORD dwSinkStreamIndex; + hr = pRecord->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_AUDIO, pMediaType, NULL, &dwSinkStreamIndex); + if(hr == MF_E_INVALIDSTREAMNUMBER) + { + //If an audio device is not present, allow video only recording + hr = S_OK; + } +done: + SafeRelease(&pAvailableTypes); + SafeRelease(&pMediaType); + SafeRelease(&pAttributes); + return hr; +} + +HRESULT CaptureManager::StartRecord(PCWSTR pszDestinationFile) +{ + if (m_pEngine == NULL) + { + return MF_E_NOT_INITIALIZED; + } + + if (m_bRecording == true) + { + return MF_E_INVALIDREQUEST; + } + + PWSTR pszExt = PathFindExtension(pszDestinationFile); + + GUID guidVideoEncoding; + GUID guidAudioEncoding; + + if (wcscmp(pszExt, L".mp4") == 0) + { + guidVideoEncoding = MFVideoFormat_H264; + guidAudioEncoding = MFAudioFormat_AAC; + } + else if (wcscmp(pszExt, L".wmv") == 0) + { + guidVideoEncoding = MFVideoFormat_WMV3; + guidAudioEncoding = MFAudioFormat_WMAudioV9; + } + else if (wcscmp(pszExt, L".wma") == 0) + { + guidVideoEncoding = GUID_NULL; + guidAudioEncoding = MFAudioFormat_WMAudioV9; + } + else + { + return MF_E_INVALIDMEDIATYPE; + } + + IMFCaptureSink *pSink = NULL; + IMFCaptureRecordSink *pRecord = NULL; + IMFCaptureSource *pSource = NULL; + + HRESULT hr = m_pEngine->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_RECORD, &pSink); + if (FAILED(hr)) + { + goto done; + } + + hr = pSink->QueryInterface(IID_PPV_ARGS(&pRecord)); + if (FAILED(hr)) + { + goto done; + } + + hr = m_pEngine->GetSource(&pSource); + if (FAILED(hr)) + { + goto done; + } + + // Clear any existing streams from previous recordings. + hr = pRecord->RemoveAllStreams(); + if (FAILED(hr)) + { + goto done; + } + + hr = pRecord->SetOutputFileName(pszDestinationFile); + if (FAILED(hr)) + { + goto done; + } + + // Configure the video and audio streams. + if (guidVideoEncoding != GUID_NULL) + { + hr = ConfigureVideoEncoding(pSource, pRecord, guidVideoEncoding); + if (FAILED(hr)) + { + goto done; + } + } + + if (guidAudioEncoding != GUID_NULL) + { + hr = ConfigureAudioEncoding(pSource, pRecord, guidAudioEncoding); + if (FAILED(hr)) + { + goto done; + } + } + + hr = m_pEngine->StartRecord(); + if (FAILED(hr)) + { + goto done; + } + + m_bRecording = true; + +done: + SafeRelease(&pSink); + SafeRelease(&pSource); + SafeRelease(&pRecord); + + return hr; +} + +HRESULT CaptureManager::StopRecord() +{ + HRESULT hr = S_OK; + + if (m_bRecording) + { + hr = m_pEngine->StopRecord(TRUE, FALSE); + WaitForResult(); + } + + return hr; +} + + +HRESULT CaptureManager::TakePhoto(PCWSTR pszFileName) +{ + IMFCaptureSink *pSink = NULL; + IMFCapturePhotoSink *pPhoto = NULL; + IMFCaptureSource *pSource; + IMFMediaType *pMediaType = 0; + IMFMediaType *pMediaType2 = 0; + bool bHasPhotoStream = true; + + // Get a pointer to the photo sink. + HRESULT hr = m_pEngine->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PHOTO, &pSink); + if (FAILED(hr)) + { + goto done; + } + + hr = pSink->QueryInterface(IID_PPV_ARGS(&pPhoto)); + if (FAILED(hr)) + { + goto done; + } + + hr = m_pEngine->GetSource(&pSource); + if (FAILED(hr)) + { + goto done; + } + + hr = pSource->GetCurrentDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO , &pMediaType); + if (FAILED(hr)) + { + goto done; + } + + //Configure the photo format + hr = CreatePhotoMediaType(pMediaType, &pMediaType2); + if (FAILED(hr)) + { + goto done; + } + + hr = pPhoto->RemoveAllStreams(); + if (FAILED(hr)) + { + goto done; + } + + DWORD dwSinkStreamIndex; + // Try to connect the first still image stream to the photo sink + if(bHasPhotoStream) + { + hr = pPhoto->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, pMediaType2, NULL, &dwSinkStreamIndex); + } + + if(FAILED(hr)) + { + goto done; + } + + hr = pPhoto->SetOutputFileName(pszFileName); + if (FAILED(hr)) + { + goto done; + } + + hr = m_pEngine->TakePhoto(); + if (FAILED(hr)) + { + goto done; + } + + m_bPhotoPending = true; + +done: + SafeRelease(&pSink); + SafeRelease(&pPhoto); + SafeRelease(&pSource); + SafeRelease(&pMediaType); + SafeRelease(&pMediaType2); + return hr; +} + + + + diff --git a/Samples/CaptureEngineVideoCapture/cpp/Capture.h b/Samples/CaptureEngineVideoCapture/cpp/Capture.h new file mode 100644 index 00000000..25200711 --- /dev/null +++ b/Samples/CaptureEngineVideoCapture/cpp/Capture.h @@ -0,0 +1,266 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. + +#ifndef CAPTURE_H +#define CAPTURE_H + +#ifndef UNICODE +#define UNICODE +#endif + +#if !defined( NTDDI_VERSION ) +#define NTDDI_VERSION NTDDI_WIN8 +#endif + +#if !defined( _WIN32_WINNT ) +#define _WIN32_WINNT _WIN32_WINNT_WIN8 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const UINT WM_APP_CAPTURE_EVENT = WM_APP + 1; + +HWND CreatePreviewWindow(HINSTANCE hInstance, HWND hParent); +HWND CreateMainWindow(HINSTANCE hInstance); +void SetMenuItemText(HMENU hMenu, UINT uItem, _In_ PWSTR pszText); +void ShowError(HWND hwnd, PCWSTR szMessage, HRESULT hr); +void ShowError(HWND hwnd, UINT id, HRESULT hr); +HRESULT CloneVideoMediaType(IMFMediaType *pSrcMediaType, REFGUID guidSubType, IMFMediaType **ppNewMediaType); +HRESULT CreatePhotoMediaType(IMFMediaType *pSrcMediaType, IMFMediaType **ppPhotoMediaType); + +// DXGI DevManager support +extern IMFDXGIDeviceManager* g_pDXGIMan; +extern ID3D11Device* g_pDX11Device; +extern UINT g_ResetToken; + +#ifdef _DEBUG +#define DBGMSG(x) { DbgPrint x;} +#else +#define DBGMSG(x) +#endif + +VOID DbgPrint(PCTSTR format, ...); + + +template void SafeRelease(T **ppT) +{ + if (*ppT) + { + (*ppT)->Release(); + *ppT = NULL; + } +} + +// Gets an interface pointer from a Media Foundation collection. +template +HRESULT GetCollectionObject(IMFCollection *pCollection, DWORD index, IFACE **ppObject) +{ + IUnknown *pUnk; + HRESULT hr = pCollection->GetElement(index, &pUnk); + if (SUCCEEDED(hr)) + { + hr = pUnk->QueryInterface(IID_PPV_ARGS(ppObject)); + pUnk->Release(); + } + return hr; +} + + +struct ChooseDeviceParam +{ + ChooseDeviceParam() : ppDevices(NULL), count(0) + { + } + ~ChooseDeviceParam() + { + for (DWORD i = 0; i < count; i++) + { + SafeRelease(&ppDevices[i]); + } + CoTaskMemFree(ppDevices); + } + + IMFActivate **ppDevices; + UINT32 count; + UINT32 selection; +}; + + + +// CaptureManager class +// Wraps the capture engine and implements the event callback. + +class CaptureManager +{ + // The event callback object. + class CaptureEngineCB : public IMFCaptureEngineOnEventCallback + { + long m_cRef; + HWND m_hwnd; + + public: + CaptureEngineCB(HWND hwnd) : m_cRef(1), m_hwnd(hwnd), m_fSleeping(false), m_pManager(NULL) {} + + // IUnknown + STDMETHODIMP QueryInterface(REFIID riid, void** ppv); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + // IMFCaptureEngineOnEventCallback + STDMETHODIMP OnEvent( _In_ IMFMediaEvent* pEvent); + + bool m_fSleeping; + CaptureManager* m_pManager; + }; + + HWND m_hwndEvent; + HWND m_hwndPreview; + + IMFCaptureEngine *m_pEngine; + IMFCapturePreviewSink *m_pPreview; + + CaptureEngineCB *m_pCallback; + + bool m_bPreviewing; + bool m_bRecording; + bool m_bPhotoPending; + + UINT m_errorID; + HANDLE m_hEvent; + HANDLE m_hpwrRequest; + bool m_fPowerRequestSet; + + CaptureManager(HWND hwnd) : + m_hwndEvent(hwnd), m_hwndPreview(NULL), m_pEngine(NULL), m_pPreview(NULL), + m_pCallback(NULL), m_bRecording(false), m_bPreviewing(false), m_bPhotoPending(false), m_errorID(0),m_hEvent(NULL) + ,m_hpwrRequest(INVALID_HANDLE_VALUE) + ,m_fPowerRequestSet(false) + { + REASON_CONTEXT pwrCtxt; + + pwrCtxt.Version = POWER_REQUEST_CONTEXT_VERSION; + pwrCtxt.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; + pwrCtxt.Reason.SimpleReasonString = L"CaptureEngine is recording!"; + + m_hpwrRequest = PowerCreateRequest(&pwrCtxt); + } + + void SetErrorID(HRESULT hr, UINT id) + { + m_errorID = SUCCEEDED(hr) ? 0 : id; + } + + // Capture Engine Event Handlers + void OnCaptureEngineInitialized(HRESULT& hrStatus); + void OnPreviewStarted(HRESULT& hrStatus); + void OnPreviewStopped(HRESULT& hrStatus); + void OnRecordStarted(HRESULT& hrStatus); + void OnRecordStopped(HRESULT& hrStatus); + void WaitForResult() + { + WaitForSingleObject(m_hEvent, INFINITE); + } +public: + ~CaptureManager() + { + DestroyCaptureEngine(); + } + + static HRESULT CreateInstance(HWND hwndEvent, CaptureManager **ppEngine) + { + HRESULT hr = S_OK; + *ppEngine = NULL; + + CaptureManager *pEngine = new (std::nothrow) CaptureManager(hwndEvent); + if (pEngine == NULL) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + *ppEngine = pEngine; + pEngine = NULL; + + Exit: + if (NULL != pEngine) + { + delete pEngine; + } + return hr; + } + + HRESULT InitializeCaptureManager(HWND hwndPreview, IUnknown* pUnk); + void DestroyCaptureEngine() + { + if (NULL != m_hEvent) + { + CloseHandle(m_hEvent); + m_hEvent = NULL; + } + SafeRelease(&m_pPreview); + SafeRelease(&m_pEngine); + SafeRelease(&m_pCallback); + + if(g_pDXGIMan) + { + g_pDXGIMan->ResetDevice(g_pDX11Device, g_ResetToken); + } + SafeRelease(&g_pDX11Device); + SafeRelease(&g_pDXGIMan); + + m_bPreviewing = false; + m_bRecording = false; + m_bPhotoPending = false; + m_errorID = 0; + } + + + + bool IsPreviewing() const { return m_bPreviewing; } + bool IsRecording() const { return m_bRecording; } + bool IsPhotoPending() const { return m_bPhotoPending; } + UINT ErrorID() const { return m_errorID; } + + HRESULT OnCaptureEvent(WPARAM wParam, LPARAM lParam); + HRESULT SetVideoDevice(IUnknown *pUnk); + HRESULT StartPreview(); + HRESULT StopPreview(); + HRESULT StartRecord(PCWSTR pszDestinationFile); + HRESULT StopRecord(); + HRESULT TakePhoto(PCWSTR pszFileName); + + void SleepState(bool fSleeping) + { + if (NULL != m_pCallback) + { + m_pCallback->m_fSleeping = fSleeping; + } + } + + HRESULT UpdateVideo() + { + if (m_pPreview) + { + return m_pPreview->UpdateVideo(NULL, NULL, NULL); + } + else + { + return S_OK; + } + } +}; + +#endif CAPTURE_H diff --git a/Samples/CaptureEngineVideoCapture/cpp/Capture.rc b/Samples/CaptureEngineVideoCapture/cpp/Capture.rc new file mode 100644 index 0000000000000000000000000000000000000000..8b5f0ee5de78e4030d37e3830fcf41c6ef512433 GIT binary patch literal 6382 zcmd^@TTdfL5QXbGQvSnac*!a&F3Yl)M=-Y6TH9E*VIe}Y2nK@UHOPi+6zy-{v!(PN%ppNtY>}Ow_R)4o(-&PRa$qcx2h$l^8l;_N#_#}`(wxB|;(vw+C+ z;}&a)OXtk|Y3vBL4|12Q4CoTpcZ>&)SgR>4NbE;eeau_%#2z*8ms5KY;lVWLRhQ0Q zKNP%ch{SEH!7J}oJv?Y1|Ei#Q0Kb}ClKYh_nLDzNj4mu5FsjY?7fx%F);6vCly%3{ z(Bk{mk=?*sKiErT_vp7niyu?&G2pBBYtI19Wj+JsAqULlBU*Q#T{MXMdEkUf-5b~} z-ZOFEcbI$K#R~OK?yh+3J+}3`_^b8v7Skw2mZ#{5#r%{wqn)4_aZ)=bb{*61<9~*8 z9;VGFVtTBe6&I6-U{;jzm!d>0;>_|btkQDDl{^|D)O#qE6KEH@y>AI~XuyarzTLX> zZZR*^)hEuh4*u7{YdiE#i6CE3PTJ6Xbdv%7{`I)5pFVi<)%0C=p7YC959mTE23=yg5!Sl6#~$V(yLjei z4ABmqaYW-A*r|ziwBH`Wk#)yI|J-EHc;ntT?44~o4a%#J7@<6J7uG40uF_URMw?PQ zfB4d(ZP&@K!G>+ezx?+a+7B5mIY-?7+b1VA9}OhYw+1g%R^Kl4_YwlbWrK3x6uD>E zN*q@lP=xu+oBmV$UXsn>ott$EVxj7}e0s!K&1`h<7q78a-d^kW2Nsj=c!ZMeYcNuo z$p`xEV=pmNGtre&|LAzHwNw2iJLN!+G_h5cwmN0tmuJHPBP#UKKU@?0WjvAhOP;LTah7`SeqLoZvO(KfM@$V- zAo#m-sK@2F%Cxm!T7TJGI>hj}t~jSP{^2O2Tspl&P_XEml*13&JRA zZwuTHy}Nw(94Yq~*WO3Rcz%@o$K{Lh-d|fYh&I6Vrl29?TUPu3Wr)fybjqV#LVpG) z_KS + + + + Debug + Win32 + + + Release + Win32 + + + + {6C7CAE9E-0988-4EDE-BA46-4C4A8445C1BD} + Win32Proj + CaptureEngine + + + + Application + true + Unicode + V110 + + + Application + false + true + Unicode + V110 + + + + + + + + + + + + + true + ..\..\..\..\sdpublic\sdk\inc;..\..\..\..\sdpublic\sdk\inc\minwin;..\..\..\..\sdpublic\sdk\inc\mincore;..\..\..\..\sdpublic\sdk\inc\crt;$(IncludePath) + D:\nt\sdpublic\sdk\lib\i386;$(LibraryPath) + + + false + ..\..\..\..\sdpublic\sdk\inc;..\..\..\..\sdpublic\sdk\inc\minwin;..\..\..\..\sdpublic\sdk\inc\mincore;..\..\..\..\sdpublic\sdk\inc\crt;$(IncludePath) + D:\nt\sdpublic\sdk\lib\i386;$(LibraryPath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + MultiThreadedDebug + Default + + + Windows + true + + + powrprof.lib;d3d11.lib;mf.lib;mfplat.lib;mfuuid.lib;shlwapi.lib;Comctl32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + powrprof.lib;d3d11.lib;mf.lib;mfplat.lib;mfuuid.lib;shlwapi.lib;Comctl32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/CaptureEngineVideoCapture/cpp/PreviewWnd.cpp b/Samples/CaptureEngineVideoCapture/cpp/PreviewWnd.cpp new file mode 100644 index 00000000..eba88222 --- /dev/null +++ b/Samples/CaptureEngineVideoCapture/cpp/PreviewWnd.cpp @@ -0,0 +1,91 @@ +// 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 "Capture.h" + +extern CaptureManager *g_pEngine; + + +// Implements the window procedure for the video preview window. + +namespace PreviewWnd +{ + HBRUSH hBackgroundBrush = 0; + + BOOL OnCreate(HWND /*hwnd*/, LPCREATESTRUCT /*lpCreateStruct*/) + { + hBackgroundBrush = CreateSolidBrush(RGB(0,0,0)); + return (hBackgroundBrush != NULL); + } + + void OnDestroy(HWND hwnd) + { + DeleteObject(hBackgroundBrush); + } + + void OnPaint(HWND hwnd) + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + if (g_pEngine->IsPreviewing()) + { + g_pEngine->UpdateVideo(); + } + else + { + FillRect(hdc, &ps.rcPaint, hBackgroundBrush); + } + EndPaint(hwnd, &ps); + } + + void OnSize(HWND hwnd, UINT state, int /*cx*/, int /*cy*/) + { + if (state == SIZE_RESTORED) + { + InvalidateRect(hwnd, NULL, FALSE); + } + } + + LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_CREATE, OnCreate); + HANDLE_MSG(hwnd, WM_PAINT, OnPaint); + HANDLE_MSG(hwnd, WM_SIZE, OnSize); + HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy); + + case WM_ERASEBKGND: + return 1; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +}; + + +HWND CreatePreviewWindow(HINSTANCE hInstance, HWND hParent) +{ + // Register the window class. + const wchar_t CLASS_NAME[] = L"Capture Engine Preview Window Class"; + + WNDCLASS wc = { }; + + wc.lpfnWndProc = PreviewWnd::WindowProc; + wc.hInstance = hInstance; + wc.lpszClassName = CLASS_NAME; + + RegisterClass(&wc); + + RECT rc; + GetClientRect(hParent, &rc); + + // Create the window. + return CreateWindowEx(0, CLASS_NAME, NULL, + WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, + hParent, NULL, hInstance, NULL); +}; diff --git a/Samples/CaptureEngineVideoCapture/cpp/resource.h b/Samples/CaptureEngineVideoCapture/cpp/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..2fc9636d65cc82691dea0ee033f108c0638cf828 GIT binary patch literal 2198 zcmb7`TW`}q5Ju-2iT_}UMZfwm{ z*e$X%WNRz!!mb&G_LLUbSDV|CXNCNh_Z6}Qk{Po~Msvmml52X;wsy#1`PrBD+wm^! zJA@L_9F3Nc#nGx2v`ROso$&^}D$a^yI1u3nB1r920mhucF(Ek^>MjR?;f2M-N$B?X#;FHw_h&z zD~}gs_>w%XTJXbFffDJOQ9+GZ@m4ne$@|7G?Hm0WbJxzpeO2)pcENnl3!JCu1~cM3 zCUSCq6Fg+>>@wIyhgK{b*65b{5XP(>+PU-YbE?4!k|CacD6{9Ay>r$?_8A>==RqlJ zlpB=Wb2L%T%;@jlzGCcMXR>nHh}LH})suQ|K<-ua)@8~=dW)X82+(<(={`3c_R>S_ a6nmy4cw0{`fyXhZF4p literal 0 HcmV?d00001 diff --git a/Samples/CaptureEngineVideoCapture/cpp/utils.cpp b/Samples/CaptureEngineVideoCapture/cpp/utils.cpp new file mode 100644 index 00000000..dfd81efa --- /dev/null +++ b/Samples/CaptureEngineVideoCapture/cpp/utils.cpp @@ -0,0 +1,176 @@ +// 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. + + +// Miscellaneous helper functions. + +#include "Capture.h" +#include + +HRESULT CopyAttribute(IMFAttributes *pSrc, IMFAttributes *pDest, const GUID& key) +{ + PROPVARIANT var; + PropVariantInit( &var ); + HRESULT hr = pSrc->GetItem(key, &var); + if (SUCCEEDED(hr)) + { + hr = pDest->SetItem(key, var); + PropVariantClear(&var); + } + return hr; +} + + +// Creates a compatible video format with a different subtype. + +HRESULT CloneVideoMediaType(IMFMediaType *pSrcMediaType, REFGUID guidSubType, IMFMediaType **ppNewMediaType) +{ + IMFMediaType *pNewMediaType = NULL; + + HRESULT hr = MFCreateMediaType(&pNewMediaType); + if (FAILED(hr)) + { + goto done; + } + + hr = pNewMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); + if (FAILED(hr)) + { + goto done; + } + + hr = pNewMediaType->SetGUID(MF_MT_SUBTYPE, guidSubType); + if (FAILED(hr)) + { + goto done; + } + + hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_FRAME_SIZE); + if (FAILED(hr)) + { + goto done; + } + + hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_FRAME_RATE); + if (FAILED(hr)) + { + goto done; + } + + hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_PIXEL_ASPECT_RATIO); + if (FAILED(hr)) + { + goto done; + } + + hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_INTERLACE_MODE); + if (FAILED(hr)) + { + goto done; + } + + *ppNewMediaType = pNewMediaType; + (*ppNewMediaType)->AddRef(); + +done: + SafeRelease(&pNewMediaType); + return hr; +} + +// Creates a JPEG image type that is compatible with a specified video media type. + +HRESULT CreatePhotoMediaType(IMFMediaType *pSrcMediaType, IMFMediaType **ppPhotoMediaType) +{ + *ppPhotoMediaType = NULL; + + const UINT32 uiFrameRateNumerator = 30; + const UINT32 uiFrameRateDenominator = 1; + + IMFMediaType *pPhotoMediaType = NULL; + + HRESULT hr = MFCreateMediaType(&pPhotoMediaType); + if (FAILED(hr)) + { + goto done; + } + + hr = pPhotoMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Image); + if (FAILED(hr)) + { + goto done; + } + + hr = pPhotoMediaType->SetGUID(MF_MT_SUBTYPE, GUID_ContainerFormatJpeg); + if (FAILED(hr)) + { + goto done; + } + + hr = CopyAttribute(pSrcMediaType, pPhotoMediaType, MF_MT_FRAME_SIZE); + if (FAILED(hr)) + { + goto done; + } + + *ppPhotoMediaType = pPhotoMediaType; + (*ppPhotoMediaType)->AddRef(); + +done: + SafeRelease(&pPhotoMediaType); + return hr; +} + +void ShowError(HWND hwnd, PCWSTR szMessage, HRESULT hr) +{ + wchar_t msg[256]; + + if (SUCCEEDED(StringCchPrintfW(msg, ARRAYSIZE(msg), L"%s (hr = 0x%X)", szMessage, hr))) + { + MessageBox(hwnd, msg, NULL, MB_OK | MB_ICONERROR); + } +} + + +void ShowError(HWND hwnd, UINT id, HRESULT hr) +{ + wchar_t msg[256]; + + if (0 != LoadString(GetModuleHandle(NULL), id, msg, ARRAYSIZE(msg))) + { + ShowError(hwnd, msg, hr); + } +} + + + +void SetMenuItemText(HMENU hMenu, UINT uItem, _In_ PWSTR pszText) +{ + MENUITEMINFO mii = {}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = pszText; + + SetMenuItemInfo(hMenu, uItem, FALSE, &mii); +} + + +VOID DbgPrint(PCTSTR format, ...) +{ + va_list args; + va_start(args, format); + + TCHAR string[MAX_PATH]; + + if (SUCCEEDED(StringCbVPrintf(string, sizeof(string), format, args))) + { + OutputDebugString(string); + } + else + { + DebugBreak(); + } +} diff --git a/Samples/CaptureEngineVideoCapture/cpp/winmain.cpp b/Samples/CaptureEngineVideoCapture/cpp/winmain.cpp new file mode 100644 index 00000000..5a956b83 --- /dev/null +++ b/Samples/CaptureEngineVideoCapture/cpp/winmain.cpp @@ -0,0 +1,757 @@ +// 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 "Capture.h" +#include "resource.h" + +#include +#include +#include + +// Include the v6 common controls in the manifest +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + +CaptureManager *g_pEngine = NULL; +HPOWERNOTIFY g_hPowerNotify = NULL; +HPOWERNOTIFY g_hPowerNotifyMonitor = NULL; +SYSTEM_POWER_CAPABILITIES g_pwrCaps; +bool g_fSleepState = false; + +INT_PTR CALLBACK ChooseDeviceDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + +INT WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ LPWSTR /*lpCmdLine*/, _In_ INT nCmdShow) +{ + bool bCoInit = false, bMFStartup = false; + + // Initialize the common controls + const INITCOMMONCONTROLSEX icex = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES }; + InitCommonControlsEx(&icex); + + // Note: The shell common File dialog requires apartment threading. + HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(hr)) + { + goto done; + } + bCoInit = true; + + hr = MFStartup(MF_VERSION); + if (FAILED(hr)) + { + goto done; + } + + bMFStartup = true; + + HWND hwnd = CreateMainWindow(hInstance); + if (hwnd == 0) + { + ShowError(NULL, L"CreateMainWindow failed.", hr); + goto done; + } + + ShowWindow(hwnd, nCmdShow); + + // Run the message loop. + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + +done: + if (FAILED(hr)) + { + ShowError(NULL, L"Failed to start application", hr); + } + if (bMFStartup) + { + MFShutdown(); + } + if (bCoInit) + { + CoUninitialize(); + } + return 0; +} + + +// Dialog functions + +HRESULT OnInitDialog(HWND hwnd, ChooseDeviceParam *pParam); +HRESULT OnOK(HWND hwnd, ChooseDeviceParam *pParam); + +// Window procedure for the "Choose Device" dialog. + +INT_PTR CALLBACK ChooseDeviceDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static ChooseDeviceParam *pParam = NULL; + + switch (msg) + { + case WM_INITDIALOG: + pParam = (ChooseDeviceParam*)lParam; + OnInitDialog(hwnd, pParam); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + OnOK(hwnd, pParam); + EndDialog(hwnd, LOWORD(wParam)); + return TRUE; + + case IDCANCEL: + EndDialog(hwnd, LOWORD(wParam)); + return TRUE; + } + break; + } + + return FALSE; +} + +// Handler for WM_INITDIALOG + +HRESULT OnInitDialog(HWND hwnd, ChooseDeviceParam *pParam) +{ + HRESULT hr = S_OK; + + HWND hList = GetDlgItem(hwnd, IDC_DEVICE_LIST); + + // Display a list of the devices. + + for (DWORD i = 0; i < pParam->count; i++) + { + WCHAR *szFriendlyName = NULL; + UINT32 cchName; + + hr = pParam->ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, + &szFriendlyName, &cchName); + if (FAILED(hr)) + { + break; + } + + int index = ListBox_AddString(hList, szFriendlyName); + + ListBox_SetItemData(hList, index, i); + + CoTaskMemFree(szFriendlyName); + } + + // Assume no selection for now. + pParam->selection = (UINT32)-1; + + if (pParam->count == 0) + { + // If there are no devices, disable the "OK" button. + EnableWindow(GetDlgItem(hwnd, IDOK), FALSE); + } + else + { + // Select the first device in the list. + ListBox_SetCurSel(hList, 0); + } + + return hr; +} + +// Handler for the OK button + +HRESULT OnOK(HWND hwnd, ChooseDeviceParam *pParam) +{ + HWND hList = GetDlgItem(hwnd, IDC_DEVICE_LIST); + + // Get the current selection and return it to the application. + int sel = ListBox_GetCurSel(hList); + + if (sel != LB_ERR) + { + pParam->selection = (UINT32)ListBox_GetItemData(hList, sel); + } + + return S_OK; +} + + +HWND CreateStatusBar(HWND hParent, UINT nID) +{ + return CreateStatusWindow(WS_CHILD | WS_VISIBLE, L"", hParent, nID); +} + +BOOL StatusSetText(HWND hwnd, int iPart, const TCHAR* szText, BOOL bNoBorders = FALSE, BOOL bPopOut = FALSE) +{ + UINT flags = 0; + if (bNoBorders) + { + flags |= SBT_NOBORDERS; + } + if (bPopOut) + { + flags |= SBT_POPOUT; + } + + return (BOOL)SendMessage(hwnd, SB_SETTEXT, (WPARAM)(iPart | flags), (LPARAM)szText); +} + + + +// Implements the window procedure for the main application window. + +namespace MainWindow +{ + HWND hPreview = NULL; + HWND hStatus = NULL; + bool bRecording = false; + bool bPreviewing = false; + IMFActivate* pSelectedDevice = NULL; + + wchar_t PhotoFileName[MAX_PATH]; + + inline void _SetStatusText(const WCHAR *szStatus) + { + StatusSetText(hStatus, 0, szStatus); + } + + void OnChooseDevice(HWND hwnd); + BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct); + void OnPaint(HWND hwnd); + void OnSize(HWND hwnd, UINT state, int cx, int cy); + void OnDestroy(HWND hwnd); + void OnChooseDevice(HWND hwnd); + void OnStartRecord(HWND hwnd); + void OnStopRecord(HWND hwnd); + void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify); + + void UpdateUI(HWND hwnd) + { + if (g_pEngine->IsRecording() != bRecording) + { + bRecording = g_pEngine->IsRecording(); + if (bRecording) + { + SetMenuItemText(GetMenu(hwnd), ID_CAPTURE_RECORD, L"Stop Recording"); + } + else + { + SetMenuItemText(GetMenu(hwnd), ID_CAPTURE_RECORD, L"Start Recording"); + } + } + + if (g_pEngine->IsPreviewing() != bPreviewing) + { + bPreviewing = g_pEngine->IsPreviewing(); + if (bPreviewing) + { + SetMenuItemText(GetMenu(hwnd), ID_CAPTURE_PREVIEW, L"Stop Preview"); + } + else + { + SetMenuItemText(GetMenu(hwnd), ID_CAPTURE_PREVIEW, L"Start Preview"); + } + } + BOOL bEnableRecording = TRUE; + BOOL bEnablePhoto = TRUE; + + if (bRecording) + { + _SetStatusText(L"Recording"); + } + else if (g_pEngine->IsPreviewing()) + { + _SetStatusText(L"Previewing"); + } + else + { + _SetStatusText(L"Please select a device or start preview (using the default device)."); + bEnableRecording = FALSE; + } + + if (!g_pEngine->IsPreviewing() || g_pEngine->IsPhotoPending()) + { + bEnablePhoto = FALSE; + } + + EnableMenuItem(GetMenu(hwnd), ID_CAPTURE_RECORD, bEnableRecording ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(GetMenu(hwnd), ID_CAPTURE_TAKEPHOTO, bEnablePhoto ? MF_ENABLED : MF_GRAYED); + } + + + BOOL OnCreate(HWND hwnd, LPCREATESTRUCT /*lpCreateStruct*/) + { + BOOL fSuccess = FALSE; + IMFAttributes* pAttributes = NULL; + HRESULT hr = S_OK; + + hPreview = CreatePreviewWindow(GetModuleHandle(NULL), hwnd); + if (hPreview == NULL) + { + goto done; + } + + hStatus = CreateStatusBar(hwnd, IDC_STATUS_BAR); + if (hStatus == NULL) + { + goto done; + } + + if (FAILED(CaptureManager::CreateInstance(hwnd, &g_pEngine))) + { + goto done; + } + + hr = g_pEngine->InitializeCaptureManager(hPreview, pSelectedDevice); + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_SET_DEVICE, hr); + goto done; + } + + // Register for connected standy changes. This should come through the normal + // WM_POWERBROADCAST messages that we're already handling below. + // We also want to hook into the monitor on/off notification for AOAC (SOC) systems. + g_hPowerNotify = RegisterSuspendResumeNotification((HANDLE)hwnd, DEVICE_NOTIFY_WINDOW_HANDLE); + g_hPowerNotifyMonitor = RegisterPowerSettingNotification((HANDLE)hwnd, &GUID_MONITOR_POWER_ON, DEVICE_NOTIFY_WINDOW_HANDLE); + ZeroMemory(&g_pwrCaps, sizeof(g_pwrCaps)); + GetPwrCapabilities(&g_pwrCaps); + + UpdateUI(hwnd); + fSuccess = TRUE; + + done: + SafeRelease(&pAttributes); + return fSuccess; + } + + void OnPaint(HWND hwnd) + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1)); + + EndPaint(hwnd, &ps); + } + + + void OnSize(HWND /*hwnd*/, UINT state, int cx, int cy) + { + if (state == SIZE_RESTORED || state == SIZE_MAXIMIZED) + { + // Resize the status bar. + SendMessageW(hStatus, WM_SIZE, 0, 0); + + // Resize the preview window. + RECT statusRect; + SendMessageW(hStatus, SB_GETRECT, 0, (LPARAM)&statusRect); + cy -= (statusRect.bottom - statusRect.top); + + MoveWindow(hPreview, 0, 0, cx, cy, TRUE); + } + } + + void OnDestroy(HWND hwnd) + { + delete g_pEngine; + g_pEngine = NULL; + if (g_hPowerNotify) + { + UnregisterSuspendResumeNotification (g_hPowerNotify); + g_hPowerNotify = NULL; + } + PostQuitMessage(0); + } + + void OnChooseDevice(HWND hwnd) + { + ChooseDeviceParam param; + + IMFAttributes *pAttributes = NULL; + + HRESULT hr = MFCreateAttributes(&pAttributes, 1); + if (FAILED(hr)) + { + goto done; + } + + // Ask for source type = video capture devices + hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, + MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); + if (FAILED(hr)) + { + goto done; + } + + // Enumerate devices. + hr = MFEnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count); + if (FAILED(hr)) + { + goto done; + } + + // Ask the user to select one. + INT_PTR result = DialogBoxParam(GetModuleHandle(NULL), + MAKEINTRESOURCE(IDD_CHOOSE_DEVICE), hwnd, + ChooseDeviceDlgProc, (LPARAM)¶m); + + if ((result == IDOK) && (param.selection != (UINT32)-1)) + { + UINT iDevice = param.selection; + + if (iDevice >= param.count) + { + hr = E_UNEXPECTED; + goto done; + } + + hr = g_pEngine->InitializeCaptureManager(hPreview, param.ppDevices[iDevice]); + if (FAILED(hr)) + { + goto done; + } + SafeRelease(&pSelectedDevice); + pSelectedDevice = param.ppDevices[iDevice]; + pSelectedDevice->AddRef(); + } + + done: + SafeRelease(&pAttributes); + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_SET_DEVICE, hr); + } + UpdateUI(hwnd); + } + + + void OnStartRecord(HWND hwnd) + { + IFileSaveDialog *pFileSave = NULL; + IShellItem *pItem = NULL; + PWSTR pszFileName = NULL; + + HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileSave)); + if (FAILED(hr)) + { + goto done; + } + hr = pFileSave->SetTitle(L"Select File Name"); + if (FAILED(hr)) + { + goto done; + } + + hr = pFileSave->SetFileName(L"MyVideo.mp4"); + if (FAILED(hr)) + { + goto done; + } + + hr = pFileSave->SetDefaultExtension(L"mp4"); + if (FAILED(hr)) + { + goto done; + } + + const COMDLG_FILTERSPEC rgSpec[] = + { + { L"MP4 (H.264/AAC)", L"*.mp4" }, + { L"Windows Media Video", L"*.wmv" }, + { L"All Files", L"*.*" }, + }; + hr = pFileSave->SetFileTypes(ARRAYSIZE(rgSpec), rgSpec); + if (FAILED(hr)) + { + goto done; + } + + hr = pFileSave->Show(hwnd); + if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) + { + hr = S_OK; // The user canceled the dialog. + goto done; + } + if (FAILED(hr)) + { + goto done; + } + + hr = pFileSave->GetResult(&pItem); + if (FAILED(hr)) + { + goto done; + } + + hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFileName); + if (FAILED(hr)) + { + goto done; + } + + hr = g_pEngine->StartRecord(pszFileName); + if (FAILED(hr)) + { + goto done; + } + +done: + CoTaskMemFree(pszFileName); + SafeRelease(&pItem); + SafeRelease(&pFileSave); + + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_RECORD, hr); + } + UpdateUI(hwnd); + } + + void OnStopRecord(HWND hwnd) + { + HRESULT hr = g_pEngine->StopRecord(); + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_RECORD, hr); + } + UpdateUI(hwnd); + } + void OnStopPreview(HWND hwnd) + { + HRESULT hr = g_pEngine->StopPreview(); + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_RECORD, hr); + } + UpdateUI(hwnd); + } + void OnStartPreview (HWND hwnd) + { + HRESULT hr = g_pEngine->StartPreview(); + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_RECORD, hr); + } + UpdateUI(hwnd); + } + void OnTakePhoto(HWND hwnd) + { + wchar_t filename[MAX_PATH]; + + // Get the path to the Documents folder. + IShellItem *psi = NULL; + PWSTR pszFolderPath = NULL; + + HRESULT hr = SHCreateItemInKnownFolder(FOLDERID_Documents, 0, NULL, IID_PPV_ARGS(&psi)); + if (FAILED(hr)) + { + goto done; + } + + hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszFolderPath); + if (FAILED(hr)) + { + goto done; + } + + // Construct a file name based on the current time. + + SYSTEMTIME time; + GetLocalTime(&time); + + hr = StringCchPrintf(filename, MAX_PATH, L"MyPhoto%04u_%02u%02u_%02u%02u%02u.jpg", + time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond); + if (FAILED(hr)) + { + goto done; + } + + LPTSTR path = PathCombine(PhotoFileName, pszFolderPath, filename); + if (path == NULL) + { + hr = E_FAIL; + goto done; + } + + hr = g_pEngine->TakePhoto(path); + if (FAILED(hr)) + { + goto done; + } + + _SetStatusText(path); + +done: + SafeRelease(&psi); + CoTaskMemFree(pszFolderPath); + + if (FAILED(hr)) + { + ShowError(hwnd, IDS_ERR_PHOTO, hr); + } + UpdateUI(hwnd); + } + + void OnCommand(HWND hwnd, int id, HWND /*hwndCtl*/, UINT /*codeNotify*/) + { + switch (id) + { + case ID_CAPTURE_CHOOSEDEVICE: + OnChooseDevice(hwnd); + break; + + case ID_CAPTURE_RECORD: + if (g_pEngine->IsRecording()) + { + OnStopRecord(hwnd); + } + else + { + OnStartRecord(hwnd); + } + break; + + case ID_CAPTURE_TAKEPHOTO: + OnTakePhoto(hwnd); + break; + case ID_CAPTURE_PREVIEW: + if (g_pEngine->IsPreviewing()) + { + OnStopPreview(hwnd); + } + else + { + OnStartPreview(hwnd); + } + break; + } + } + + + LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_CREATE, OnCreate); + HANDLE_MSG(hwnd, WM_PAINT, OnPaint); + HANDLE_MSG(hwnd, WM_SIZE, OnSize); + HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy); + HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); + + case WM_ERASEBKGND: + return 1; + + case WM_APP_CAPTURE_EVENT: + { + if (g_pEngine) + { + HRESULT hr = g_pEngine->OnCaptureEvent(wParam, lParam); + if (FAILED(hr)) + { + ShowError(hwnd, g_pEngine->ErrorID(), hr); + InvalidateRect(hwnd, NULL, FALSE); + } + } + + UpdateUI(hwnd); + } + return 0; + case WM_POWERBROADCAST: + { + switch (wParam) + { + case PBT_APMSUSPEND: + DbgPrint(L"++WM_POWERBROADCAST++ Stopping both preview & record stream.\n"); + g_fSleepState = true; + g_pEngine->SleepState(g_fSleepState); + g_pEngine->StopRecord(); + g_pEngine->StopPreview(); + g_pEngine->DestroyCaptureEngine(); + DbgPrint(L"++WM_POWERBROADCAST++ streams stopped, capture engine destroyed.\n"); + break; + case PBT_APMRESUMEAUTOMATIC: + DbgPrint(L"++WM_POWERBROADCAST++ Reinitializing capture engine.\n"); + g_fSleepState = false; + g_pEngine->SleepState(g_fSleepState); + g_pEngine->InitializeCaptureManager(hPreview, pSelectedDevice); + break; + case PBT_POWERSETTINGCHANGE: + { + // We should only be in here for GUID_MONITOR_POWER_ON. + POWERBROADCAST_SETTING* pSettings = (POWERBROADCAST_SETTING*)lParam; + + // If this is a SOC system (AoAc is true), we want to check our current + // sleep state and based on whether the monitor is being turned on/off, + // we can turn off our media streams and/or re-initialize the capture + // engine. + if (pSettings != NULL && g_pwrCaps.AoAc && pSettings->PowerSetting == GUID_MONITOR_POWER_ON) + { + DWORD dwData = *((DWORD*)pSettings->Data); + if (dwData == 0 && !g_fSleepState) + { + // This is a AOAC machine, and we're about to turn off our monitor, let's stop recording/preview. + DbgPrint(L"++WM_POWERBROADCAST++ Stopping both preview & record stream.\n"); + g_fSleepState = true; + g_pEngine->SleepState(g_fSleepState); + g_pEngine->StopRecord(); + g_pEngine->StopPreview(); + g_pEngine->DestroyCaptureEngine(); + DbgPrint(L"++WM_POWERBROADCAST++ streams stopped, capture engine destroyed.\n"); + } + else if (dwData != 0 && g_fSleepState) + { + DbgPrint(L"++WM_POWERBROADCAST++ Reinitializing capture engine.\n"); + g_fSleepState = false; + g_pEngine->SleepState(g_fSleepState); + g_pEngine->InitializeCaptureManager(hPreview, pSelectedDevice); + } + } + } + break; + case PBT_APMRESUMESUSPEND: + default: + // Don't care about this one, we always get the resume automatic so just + // latch onto that one. + DbgPrint(L"++WM_POWERBROADCAST++ (wParam=%u,lParam=%u)\n", wParam, lParam); + break; + } + } + return 1; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +}; + +HWND CreateMainWindow(HINSTANCE hInstance) +{ + // Register the window class. + const wchar_t CLASS_NAME[] = L"Capture Engine Window Class"; + + WNDCLASS wc = { }; + + wc.lpfnWndProc = MainWindow::WindowProc; + wc.hInstance = hInstance; + wc.lpszClassName = CLASS_NAME; + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); + + RegisterClass(&wc); + + // Create the window. + return CreateWindowEx(0, CLASS_NAME, L"Capture Application", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInstance, NULL); +}; diff --git a/Samples/CauSamplePlugin/README.md b/Samples/CauSamplePlugin/README.md new file mode 100644 index 00000000..589892a1 --- /dev/null +++ b/Samples/CauSamplePlugin/README.md @@ -0,0 +1,49 @@ +Cluster Aware Updating plug-in sample +===================================== + +This sample demonstrates a Cluster Aware Updating (CAU) plug-in that runs an arbitrary, administrator-specified, command on each cluster node. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related technologies +-------------------- + +[**ClusterAwareUpdating**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh873034) + +Operating system requirements +----------------------------- + +Client + +None supported + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +This sample requires the ClusterAwareUpdating.dll assembly which is available for Windows 8.1 in the RSAT package download. The FailOver Cluster feature must be installed in order to build this sample on Windows Server 2012 R2. + +To build this sample, open the solution (.sln) file titled CauSamplePlugin.sln from Visual Studio Professional 2012, Visual Studio 2013, or a later version (any SKU). Press F6 or go to **Build-\>Build Solution** from the top menu after the sample has loaded. + +**Warning** This sample requires Visual Studio Professional 2012, Visual Studio 2013, or later versions of Visual Studio (any SKU) and does not compile in Microsoft Visual Studio Express 2013 for Windows. It also requires .NET Framework 4.5. + +Run the sample +-------------- + +The CAU plug-in has one required argument, Command, which is the command that will be run. Here's an example command line. + +**Invoke-CauRun -ClusterName MyTestCluster -CauPluginName FabrikamCauPlugin -CauPluginArguments @{ "Command"="cmd.exe /c echo Hello." } -Verbose** + +**Important** The "Command" string is case-sensitive, so "command" returns an error. + +When the plug-in performs a scan, it detects a single "update," which is the command to run, applicable to each node. Staging doesn't do anything except report that it's ready to install the update (run the command). When the plug-in "installs" the update, it runs the command on the target machine using WMI, and waits for it to exit. If the remote process exits with a non-zero error code, the update is considered to have failed. + +Because this plug-in uses WMI, it requires that your firewalls on both the orchestrator machine and the cluster nodes have the appropriate rules enabled. It's easy to overlook that the orchestrator must allow inbound WMI connections in order to receive events from the cluster nodes when the commands finish. The plug-in tests its ability to use WMI with each node. + diff --git a/Samples/CauSamplePlugin/cs/AssemblyInfo.cs b/Samples/CauSamplePlugin/cs/AssemblyInfo.cs new file mode 100644 index 00000000..3f67845e --- /dev/null +++ b/Samples/CauSamplePlugin/cs/AssemblyInfo.cs @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "CauSamplePlugin" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] + diff --git a/Samples/CauSamplePlugin/cs/CauSamplePlugin.csproj b/Samples/CauSamplePlugin/cs/CauSamplePlugin.csproj new file mode 100644 index 00000000..111d5606 --- /dev/null +++ b/Samples/CauSamplePlugin/cs/CauSamplePlugin.csproj @@ -0,0 +1,57 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {97CFEA74-CC55-4C1B-A348-AB04028E7E95} + Library + Microsoft.Samples.ClusterAwareUpdating.CauSamplePlugin + CauSamplePlugin + v4.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + $(PUBLIC_ROOT)\internal\base\ref\clusterawareupdating.metadata_dll + + + + + + + + + + + + diff --git a/Samples/CauSamplePlugin/cs/CauSamplePlugin.rc b/Samples/CauSamplePlugin/cs/CauSamplePlugin.rc new file mode 100644 index 00000000..87fcc2e1 --- /dev/null +++ b/Samples/CauSamplePlugin/cs/CauSamplePlugin.rc @@ -0,0 +1,11 @@ +#include "windows.h" + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Cluster-Aware Updating Sample Plug-In" +#define VER_INTERNALNAME_STR "CauSamplePlugin.dll\0" + +#include "common.ver" + diff --git a/Samples/CauSamplePlugin/cs/CauSamplePlugin.sln b/Samples/CauSamplePlugin/cs/CauSamplePlugin.sln new file mode 100644 index 00000000..3735c6d3 --- /dev/null +++ b/Samples/CauSamplePlugin/cs/CauSamplePlugin.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CauSamplePlugin", "CauSamplePlugin.csproj", "{97CFEA74-CC55-4C1B-A348-AB04028E7E95}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {97CFEA74-CC55-4C1B-A348-AB04028E7E95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97CFEA74-CC55-4C1B-A348-AB04028E7E95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97CFEA74-CC55-4C1B-A348-AB04028E7E95}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {97CFEA74-CC55-4C1B-A348-AB04028E7E95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97CFEA74-CC55-4C1B-A348-AB04028E7E95}.Release|Any CPU.Build.0 = Release|Any CPU + {97CFEA74-CC55-4C1B-A348-AB04028E7E95}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/CauSamplePlugin/cs/FabrikamCauPlugin.cs b/Samples/CauSamplePlugin/cs/FabrikamCauPlugin.cs new file mode 100644 index 00000000..bd49dc45 --- /dev/null +++ b/Samples/CauSamplePlugin/cs/FabrikamCauPlugin.cs @@ -0,0 +1,478 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +using System; +using System.Collections; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Management; +using System.Management.Automation; +using System.Runtime.Serialization; +using System.Security; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ClusterAwareUpdating; + +namespace Microsoft.Samples.ClusterAwareUpdating.CauSamplePlugin +{ + // + // This code defines a CAU plugin that will run an arbitrary (administrator-specified) + // command on each cluster node. It has one required argument, "Command", which is the + // command that will be run. For example: + // + // Invoke-CauRun -ClusterName MyTestCluster -CauPluginName FabrikamCauPlugin -CauPluginArguments @{ "Command"="cmd.exe /c echo Hello." } -Verbose + // + // When the plugin performs a scan, it will detect a single "update" applicable to + // each node, which is the command to run. Staging doesn't do anything except report + // that it is ready to install the update (run the command). When the plugin + // "installs" the update, it runs the command on the target machine using WMI, and + // waits for it to exit. If the remote process exits with a non-zero error code, the + // update is considered failed. + // + // Because this plugin uses WMI, it requires that your firewalls on both the + // orchestrator machine and the cluster nodes have the appropriate rules enabled. An + // easy one to overlook is that the orchestrator must allow inbound WMI connections in + // order to receive events from the cluster nodes when the commands finish. The plugin + // will attempt to test its ability to use WMI with each node. + // + + // This attribute has the name of the plugin that gets registered when you use + // Register-CauPlugin. + [ClusterUpdatingPlugin( "FabrikamCauPlugin" )] + internal sealed class FabrikamCauPlugin : IClusterUpdatingPlugin + { + public FabrikamCauPlugin(string clusterName, + PSCredential credential, + Hashtable arguments, + CancellationToken cancelToken) + { + m_clusterName = clusterName; + m_credential = credential; + m_arguments = arguments; + m_cancelToken = cancelToken; + } + + private string m_clusterName; + private PSCredential m_credential; + private Hashtable m_arguments; + private CancellationToken m_cancelToken; + + + public IClusterNodeUpdater CreateUpdater( string machineName, + Guid runId ) + { + string command = m_arguments[ "Command" ] as string; + if( String.IsNullOrEmpty( command ) ) + { + string msg = "The Fabrikam CAU Plugin requires an Command argument which consists of a command to be run on each cluster node."; + throw new ClusterUpdateException( msg, + "MissingCommandArg", + ErrorCategory.InvalidArgument ); + } + + return new FabrikamUpdater( machineName, m_credential, m_cancelToken, runId, command ); + } + + public void Dispose() + { + // Code to clean up the plugin as a whole goes here. + } + } // end class FabrikamCauPlugin + + + [Serializable] + public class FabrikamException : Exception + { + public FabrikamException() : base() { } + public FabrikamException( string message ) : base( message ) { } + public FabrikamException( string message, Exception inner ) : base( message, inner ) { } + protected FabrikamException( SerializationInfo info, StreamingContext context ) : base( info, context ) { } + } // end class FabrikamException + + + // + // This class represents an object that is used to scan, stage, and update a + // specific cluster node. + // + internal sealed class FabrikamUpdater : IClusterNodeUpdater + { + private string m_machine; + private PSCredential m_cred; + private CancellationToken m_cancelToken; + private Guid m_runId; + private string m_command; + private UpdateInfo m_update; + + + public FabrikamUpdater( string machine, + PSCredential cred, + CancellationToken cancelToken, + Guid runId, + string command ) + { + if( String.IsNullOrEmpty( machine ) ) + throw new ArgumentException( "You must supply a machine name.", "machine" ); + + // If cred is null, that means just use the security context of the user + // running this process. + + if( String.IsNullOrEmpty( command ) ) + throw new ArgumentException( "You must supply a command to run.", "command" ); + + m_machine = machine; + m_cred = cred; + m_cancelToken = cancelToken; + m_runId = runId; + m_command = command; + + m_update = new UpdateInfo( m_machine, + m_command, + "Fabrikam CAU Command Update", + "This update will run the command specified by the administrator on each cluster node. The command is: " + m_command ); + + _TestWmiConnection(); + } // end constructor + + + public async Task ScanAsync( IScanCallback scanCallback ) + { + // Note that we only allow ClusterUpdateExceptions out; the CAU cmdlet will + // not handle other exception types, so if any other exception type flies out + // of here, it will cause an abnormal termination of the CAU cmdlet. (with the + // exception of OperationCanceledException) + try + { + await Task.Factory.StartNew( () => _DoScan( scanCallback ), m_cancelToken ); + } + catch( FabrikamException fe ) + { + throw new ClusterUpdateException( String.Format( CultureInfo.CurrentCulture, + "Scanning node \"{0}\" failed: {1}", + m_machine, + fe.Message ), + "ScanFailed", + ErrorCategory.NotSpecified, + fe ); + } + } // end ScanAsync() + + + // Our "scan" needs to detect the "update" just one time, because after installing + // updates, Invoke-CauRun will call ScanAsync again to look for "second-order" + // updates (updates that only become applicable after installing the first set of + // updates). + private bool m_alreadyReported; + + private void _DoScan( IScanCallback scanCallback ) + { + if( !m_alreadyReported ) + { + scanCallback.ReportApplicableUpdate( m_update ); + m_alreadyReported = true; + } + } // end _DoScan() + + + public async Task StageAsync( IStageCallback stageCallback ) + { + try + { + await Task.Factory.StartNew( () => _DoStaging( stageCallback ), m_cancelToken ); + } + catch( FabrikamException fe ) + { + // Note that if an "update" fails to stage, it is reported through the + // stageCallback.ReportStagingResult method. Only a more serious problem + // representing a complete infrastructure failure should be reported by + // throwing a ClusterUpdateException. + throw new ClusterUpdateException( String.Format( CultureInfo.CurrentCulture, + "Staging node \"{0}\" failed: {1}", + m_machine, + fe.Message ), + "StageFailed", + ErrorCategory.NotSpecified, + fe ); + } + } // end StageAsync() + + + private void _DoStaging( IStageCallback stageCallback ) + { + // Nothing to do except report that we're ready to run the command. + // All timestamps should be UTC. + UpdateStagingResult usr = new UpdateStagingResult( m_update, ResultCode.Succeeded, 0, DateTime.UtcNow ); + stageCallback.ReportStagingResult( usr ); + } // end _DoStaging() + + + public async Task InstallAsync( IInstallCallback installCallback ) + { + try + { + await Task.Factory.StartNew( () => _DoInstall( installCallback ), + m_cancelToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default ); + } + catch( FabrikamException fe ) + { + // Note that if an "update" fails to install, it is reported through the + // installCallback.ReportInstallResult method. Only a more serious problem + // representing a complete infrastructure failure should be reported by + // throwing a ClusterUpdateException. + throw new ClusterUpdateException( String.Format( CultureInfo.CurrentCulture, + "Installing node \"{0}\" failed: {1}", + m_machine, + fe.Message ), + "InstallFailed", + ErrorCategory.NotSpecified, + fe ); + } + } // end InstallAsync() + + + private void _DoInstall( IInstallCallback installCallback ) + { + installCallback.WriteVerbose( String.Format( CultureInfo.CurrentCulture, + "Attempting to run this command on {0}: {1}", + m_machine, + m_command ) ); + Exception e = null; + int errorCode = 0; + UpdateInstallResult uir = null; + try + { + errorCode = _RunCommand( m_command, false, installCallback ); + } + catch( Win32Exception w32e ) { e = w32e; } + catch( ManagementException me ) { e = me; } + catch( OperationCanceledException ) + { + uir = new UpdateInstallResult( m_update, + ResultCode.Canceled, + 0, // error code + false, // reboot required + false, // long reboot hint + DateTime.UtcNow ); // All timestamps should be UTC. + installCallback.ReportInstallResult( uir ); + throw; + } + + if( null != e ) + { + throw new FabrikamException( String.Format( CultureInfo.CurrentCulture, + "Failed to run command: {0}: {1}", + e.GetType().Name, + e.Message ), + e ); + } + + bool rebootRequired = false; + bool succeeded = false; + const int ERROR_SUCCESS_REBOOT_REQUIRED = 3010; + const int ERROR_SUCCESS_RESTART_REQUIRED = 3011; + const int ERROR_FAIL_REBOOT_REQUIRED = 3017; + + if( 0 == errorCode ) + { + succeeded = true; + } + else if( (ERROR_SUCCESS_REBOOT_REQUIRED == errorCode) || + (ERROR_SUCCESS_RESTART_REQUIRED == errorCode) ) + { + succeeded = true; + rebootRequired = true; + } + else if( 0 != errorCode ) + { + succeeded = false; + if( ERROR_FAIL_REBOOT_REQUIRED == errorCode ) + { + rebootRequired = true; + } + } + + uir = new UpdateInstallResult( m_update, + succeeded ? ResultCode.Succeeded : ResultCode.Failed, + errorCode, + rebootRequired, + false, + DateTime.UtcNow ); // All timestamps should be UTC. + installCallback.ReportInstallResult( uir ); + } // end _DoInstall() + + + // This can throw a Win32Exception, a ManagementException, or an + // OperationCanceledException. + private int _RunCommand( string command, bool instaKill, ICauPluginCallbackBase callback ) + { + int exitCode = -1; + int processId = 0; + string username = null; + SecureString password = null; + if( null != m_cred ) + { + username = m_cred.UserName; + password = m_cred.Password; + } + + object gate = new object(); + + ConnectionOptions co = new ConnectionOptions( null, // locale + username, + password, + null, // authority + ImpersonationLevel.Impersonate, + AuthenticationLevel.PacketPrivacy, + true, // enable privileges + null, // context + TimeSpan.Zero ); + string path = String.Format( CultureInfo.InvariantCulture, @"\\{0}\root\cimv2", m_machine ); + ManagementScope scope = new ManagementScope( path, co ); + ObjectGetOptions objGetOptions = new ObjectGetOptions(); + + scope.Connect(); + + // We start the query before launching the process to prevent any possibility + // of a timing or PID recycling problem. + WqlEventQuery query = new WqlEventQuery( "Win32_ProcessStopTrace" ); + EventWatcherOptions watcherOptions = new EventWatcherOptions( null, TimeSpan.MaxValue, 1 ); + using( ManagementEventWatcher watcher = new ManagementEventWatcher( scope, query, watcherOptions ) ) + { + watcher.EventArrived += (sender, arg) => + { + int stoppedProcId = (int) (uint) arg.NewEvent[ "ProcessID" ]; + if( stoppedProcId == processId ) + { + exitCode = (int) (uint) arg.NewEvent[ "ExitStatus" ]; + + if( null != callback ) + { + callback.WriteVerbose( String.Format( CultureInfo.CurrentCulture, + "Process ID {0} on {1} exited with code: {2}", + processId, + m_machine, + exitCode ) ); + } + + lock( gate ) + { + Monitor.PulseAll( gate ); + } + } + }; + + watcher.Start(); + + int timeout = Timeout.Infinite; + ManagementPath mPath = new ManagementPath( "Win32_Process" ); + using( ManagementClass mc = new ManagementClass( scope, mPath, objGetOptions ) ) + using( ManagementBaseObject inParams = mc.GetMethodParameters( "Create" ) ) + { + inParams[ "CommandLine" ] = command; + using( ManagementBaseObject outParams = mc.InvokeMethod( "Create", inParams, null ) ) + { + int err = (int) (uint) outParams[ "returnValue" ]; + if( 0 != err ) + { + throw new Win32Exception( err ); + } + processId = (int) (uint) outParams[ "processId" ]; + Debug.Assert( processId > 0 ); + } + } + + if( null != callback ) + { + callback.WriteVerbose( String.Format( CultureInfo.CurrentCulture, + "Process launched on {0} with ID: {1}", + m_machine, + processId ) ); + } + + // If instaKill is true, we are trying to test our ability to receive + // Win32_ProcessStopTrace events, so kill the process immediately. + if( instaKill ) + { + SelectQuery killQuery = new SelectQuery( "SELECT * FROM Win32_Process WHERE ProcessId = " + processId ); + using( ManagementObjectSearcher searcher = new ManagementObjectSearcher( scope, killQuery ) ) + { + foreach( ManagementObject obj in searcher.Get() ) + { + obj.InvokeMethod( "Terminate", new object[] { (uint) c_TestWmiExitCode } ); + obj.Dispose(); + } + } + + // If we don't receive the Win32_ProcessStopTrace event within 10 + // seconds, we'll assume it's not coming. In that case, there's + // probably a firewall problem blocking WMI. + timeout = 10000; + } + + // Wait until the process exits (or we get canceled). + lock( gate ) + { + // If we get canceled, we stop waiting for the remote process to + // finish and just leave it running. + using( m_cancelToken.Register( () => { lock( gate ) { Monitor.PulseAll( gate ); } } ) ) + { + if( !Monitor.Wait( gate, timeout ) ) + { + Debug.Assert( instaKill, "This call should not time out unless we are in the instaKill scenario." ); + throw new ClusterUpdateException( "The Fabrikam CAU plugin is able to create a process on cluster node \"{0}\" using WMI, but is not able to receive process lifetime events. Check the firewalls on both this computer and the target node and ensure that the appropriate WMI rules are enabled.", + "WmiTestReceiveEventFailed", + ErrorCategory.ResourceUnavailable ); + } + } + } + + watcher.Stop(); + m_cancelToken.ThrowIfCancellationRequested(); + } + + return exitCode; + } // end _RunCommand() + + + private const int c_TestWmiExitCode = 7; + + // + // This method tests our ability to create a process on the target node and + // monitor its exit. If we can't, it will throw a ClusterUpdateException. + // + private void _TestWmiConnection() + { + Exception e = null; + try + { + int exitCode = _RunCommand( "cmd.exe", true, null ); + Debug.Assert( c_TestWmiExitCode == exitCode ); + } + catch( Win32Exception w32e ) { e = w32e; } + catch( ManagementException me ) { e = me; } + + if( null != e ) + { + throw new ClusterUpdateException( String.Format( CultureInfo.CurrentCulture, + "The Fabrikam CAU plugin was unable to create a process on the cluster node \"{0}\". Check that the appropriate firewall rules are enabled on both this computer and the target node. The error received was a {1}: {2}", + m_machine, + e.GetType().Name, + e.Message ), + "WmiTestCreateProcessFailed", + ErrorCategory.OpenError, + e ); + } + } // end _TestWmiConnection() + + + public void Dispose() + { + // Cleanup code goes here. + } + } // end class FabrikamUpdater +} + diff --git a/Samples/ClsIDCallback/README.md b/Samples/ClsIDCallback/README.md new file mode 100644 index 00000000..48ddcd34 --- /dev/null +++ b/Samples/ClsIDCallback/README.md @@ -0,0 +1,34 @@ +Background Intelligent Transfer Service COM notification sample +=============================================================== + +This sample demonstrates how to use COM notifications to launch your application when the BITS job is finished downloading. There are multiple ways to wait for a BITS transfer to complete: synchronously poll for status, register a program that BITS will execute when the job is complete, register a COM interface pointer whose methods BITS will call when the job is complete, or register a COM class (an instance of which will be activated by BITS when the job is complete). This sample illustrates the latter scenario where the BITS API is used to register a COM class for notification upon job completion. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +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 F6 for Visual Studio 2013) or use **Build \> Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug \> Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug \> Start Without Debugging**. + diff --git a/Samples/ClsIDCallback/cpp/ClsIDCallback.cpp b/Samples/ClsIDCallback/cpp/ClsIDCallback.cpp new file mode 100644 index 00000000..1f54fcd9 --- /dev/null +++ b/Samples/ClsIDCallback/cpp/ClsIDCallback.cpp @@ -0,0 +1,188 @@ +// ClsIDSample.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "NotifyInterfaceImp.h" +#include "utils.h" + +DOWNLOAD_FILE FileList[] = +{ + { + L"http://download.microsoft.com/download/D/2/2/D22D16C3-7637-41D3-99DA-10E7CEBAD290/SQL2008UpgradeTechnicalReferenceGuide.docx", + L"C:\\BitsSample\\SQL2008UpgradeTechnicalReferenceGuide.docx" + } +}; + +int _tmain(int argc, _TCHAR* argv[]) +{ + MSG msg; + HRESULT hr = S_OK; + bool bRun = true; + BOOL bRet = FALSE; + + FormatObjectPath(); + if (_wcsicmp(argv[1], L"UnRegServer") == 0) + { + UnRegisterServer(); + return 0; + } + + if (_wcsicmp(argv[1], L"RegServer") == 0) + { + RegisterServer(); + return 0; + } + + //Specify the COM threading model. + hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + if (_wcsicmp(argv[1], L"Demo") == 0) + { + HRESULT result = S_OK; + GUID guidJob; + IBackgroundCopyJob5* pBackgroundCopyJob5 = NULL; + IBackgroundCopyJob* pBackgroundCopyJob = NULL; + IBackgroundCopyManager* pQueueMgr = NULL; + BITS_JOB_PROPERTY_VALUE propval; + + result = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL, + CLSCTX_LOCAL_SERVER, + __uuidof(IBackgroundCopyManager), + (void **)&pQueueMgr); + + if (FAILED(result)) + { + // Failed to connect to BITS + wprintf(L"Failed to connect to BITS with error %x\n",result); + goto cancel; + } + + // Create a Job + wprintf(L"Creating Job...\n"); + + result = pQueueMgr->CreateJob(L"BITS_CLSID_SAMPLE", + BG_JOB_TYPE_DOWNLOAD, + &guidJob, + (IBackgroundCopyJob **)&pBackgroundCopyJob); + + + if(FAILED(result)) + { + wprintf(L"Failed to Create Job, error = %x\n",result); + goto cancel; + } + + result = pBackgroundCopyJob->QueryInterface( + __uuidof(IBackgroundCopyJob5), + reinterpret_cast(&pBackgroundCopyJob5) + ); + + if(FAILED(result)) + { + wprintf(L"Failed to Get the Job Interface, error = %x\n",result); + goto cancel; + } + + // Set the CLS ID. + propval.ClsID = CLSID_CNotifyInterfaceImp; + + wprintf(L"Setting CLSID Callback Property ...\n"); + + result = pBackgroundCopyJob5->SetProperty(BITS_JOB_PROPERTY_NOTIFICATION_CLSID, propval); + if(FAILED(result)) + { + wprintf(L"Failed to Set the CLSID, error = %x\n",result); + goto cancel; + } + + // get CLSID for the new job + BITS_JOB_PROPERTY_VALUE actual_propval; + + result = pBackgroundCopyJob5->GetProperty( BITS_JOB_PROPERTY_NOTIFICATION_CLSID, &actual_propval ); + if (FAILED(result)) + { + wprintf(L"GetProperty failed with error %x\n",result); + goto cancel; + } + + // actual_propval.ClsID will contain the CLSID registered for the Job. + + wprintf(L"Setting notification flags ...\n"); + // Set appropriate notify flags for the Job + result = pBackgroundCopyJob5->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED | BG_NOTIFY_JOB_ERROR); + if(FAILED(result)) + { + wprintf(L"Failed to SetNotifyFlags the Job, error = %x\n",result); + goto cancel; + } + + wprintf(L"Adding Download files ...\n"); + // Now add one or more files to the Job using AddFile() and Resume() the job. + result = pBackgroundCopyJob5->AddFile(FileList[0].RemoteFile, FileList[0].LocalFile); + + if( FAILED(result) ) + { + wprintf(L"Error: Unable to add remote file to the download job (error %08X).\n",result); + goto cancel; + } + + // Start the download + result = pBackgroundCopyJob5->Resume(); + + if(FAILED(result)) + { + wprintf(L"Error: Unable to resume the download job (error %08X).\n",result); + goto cancel; + } + wprintf(L"Download started, terminating the process.\n"); + wprintf(L"BITS should start a new process when transfer is done.\n"); + + // It is OK to terminate the application after this. BITS will instantiate the + // CLSID to deliver the registered callbacks of the job. + + goto done; + + // NOTE: In actual scenario please do not call Cancel() until the Job is done with the download. +cancel: + if(pBackgroundCopyJob) + { + pBackgroundCopyJob->Cancel(); + pBackgroundCopyJob->Release(); + } + +done: + bRun = false; + } + + if (bRun) + { + DWORD dwCookie_ExeObj01 = 0; + DWORD dwCookie_CNotifyInterfaceImp = 0; + + g_dwMainThreadID = GetCurrentThreadId(); + + RegisterClassObject(CLSID_CNotifyInterfaceImp, &dwCookie_CNotifyInterfaceImp); + + ::CoResumeClassObjects(); + + while( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0) + { + if (bRet == -1) + { + break; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + ::CoRevokeClassObject(dwCookie_CNotifyInterfaceImp); + } + + ::CoUninitialize(); + + return 0; +} + diff --git a/Samples/ClsIDCallback/cpp/ClsIDCallback.sln b/Samples/ClsIDCallback/cpp/ClsIDCallback.sln new file mode 100644 index 00000000..97a6e794 --- /dev/null +++ b/Samples/ClsIDCallback/cpp/ClsIDCallback.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClsIDCallback", "ClsIDCallback.vcxproj", "{44102945-0486-46E7-B734-C791F068AD07}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {44102945-0486-46E7-B734-C791F068AD07}.Debug|Win32.ActiveCfg = Debug|Win32 + {44102945-0486-46E7-B734-C791F068AD07}.Debug|Win32.Build.0 = Debug|Win32 + {44102945-0486-46E7-B734-C791F068AD07}.Release|Win32.ActiveCfg = Release|Win32 + {44102945-0486-46E7-B734-C791F068AD07}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/ClsIDCallback/cpp/ClsIDCallback.vcxproj b/Samples/ClsIDCallback/cpp/ClsIDCallback.vcxproj new file mode 100644 index 00000000..1447482c --- /dev/null +++ b/Samples/ClsIDCallback/cpp/ClsIDCallback.vcxproj @@ -0,0 +1,104 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {44102945-0486-46E7-B734-C791F068AD07} + Win32Proj + ClsIDCallback + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + Create + Create + + + + + + + \ No newline at end of file diff --git a/Samples/ClsIDCallback/cpp/NotifyInterfaceImp.cpp b/Samples/ClsIDCallback/cpp/NotifyInterfaceImp.cpp new file mode 100644 index 00000000..5ca5991c --- /dev/null +++ b/Samples/ClsIDCallback/cpp/NotifyInterfaceImp.cpp @@ -0,0 +1,291 @@ +#include "StdAfx.h" +#include "NotifyInterfaceImp.h" + +CReferenceCountedObject::CReferenceCountedObject() : +m_cRef(1) +{ + // Increment the global count of objects. + InterlockedIncrement(&g_lObjsInUse); +} + +CReferenceCountedObject::~CReferenceCountedObject() +{ + // Decrement the global count of objects. + InterlockedDecrement(&g_lObjsInUse); + + CClassFactory::AttemptToTerminateServer(); +} + +STDMETHODIMP CReferenceCountedObject::QueryInterface(REFIID riid, void** ppvObject) +{ + if (riid == IID_IUnknown) + { + *ppvObject = (IUnknown*)this; + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CReferenceCountedObject::AddRef() +{ + InterlockedIncrement(&m_cRef); + + return m_cRef; +} + +STDMETHODIMP_(ULONG) CReferenceCountedObject::Release() +{ + InterlockedDecrement(&m_cRef); + + if (m_cRef == 0) + { + delete this; + return 0; + } + + return m_cRef; +} + +CClassFactory::CClassFactory() : +m_cRef(1) +{ +} + +CClassFactory::~CClassFactory() +{ +} + +STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void** ppvObject) +{ + if (riid == IID_IUnknown) + { + CReferenceCountedObject* pCReferenceCountedObject = (CReferenceCountedObject*)this; + + *ppvObject = (IUnknown*)pCReferenceCountedObject; + ((CReferenceCountedObject*)this) -> AddRef(); + return S_OK; + } + + if (riid == IID_IClassFactory) + { + *ppvObject = (IClassFactory*)this; + ((CReferenceCountedObject*)this) -> AddRef(); + return S_OK; + } + + *ppvObject = NULL; + + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CClassFactory::AddRef() +{ + InterlockedIncrement(&m_cRef); + + return m_cRef; +} + +STDMETHODIMP_(ULONG) CClassFactory::Release() +{ + InterlockedDecrement(&m_cRef); + + if (m_cRef == 0) + { + delete this; + return 0; + } + + return m_cRef; +} + +// IClassFactory method. +STDMETHODIMP CClassFactory::CreateInstance +( +IUnknown __RPC_FAR *pUnkOuter, +REFIID riid, +void __RPC_FAR *__RPC_FAR *ppvObject +) +{ + return E_NOTIMPL; +} + +// IClassFactory method. +STDMETHODIMP CClassFactory::LockServer +( +BOOL fLock +) +{ + if (fLock) + { + ::InterlockedIncrement(&g_lServerLocks) ; + } + else + { + ::InterlockedDecrement(&g_lServerLocks) ; + } + // If this is an out-of-proc server, check to see + // whether we should shut down. + AttemptToTerminateServer() ; //@local + + return S_OK ; +} + +// Shut down the application. +void CClassFactory::AttemptToTerminateServer() +{ + if ((g_lObjsInUse > 0) || (g_lServerLocks > 0)) + { + } + else + { + ::PostThreadMessage(g_dwMainThreadID, WM_QUIT, 0, 0); + } +} + +CNotifyInterfaceImp::CNotifyInterfaceImp() +{ +} + +CNotifyInterfaceImp::~CNotifyInterfaceImp() +{ +} + +STDMETHODIMP CNotifyInterfaceImp::QueryInterface(REFIID riid, void** ppvObject) +{ + if (riid == IID_IUnknown || riid == __uuidof(IBackgroundCopyCallback2)) + { + *ppvObject = (IBackgroundCopyCallback2*)this; + ((CReferenceCountedObject*)this) -> AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +// IUnknown method. +STDMETHODIMP_(ULONG) CNotifyInterfaceImp::AddRef() +{ + return CReferenceCountedObject::AddRef(); +} + +// IUnknown method. +STDMETHODIMP_(ULONG) CNotifyInterfaceImp::Release() +{ + return CReferenceCountedObject::Release(); +} + + +STDMETHODIMP CNotifyInterfaceImp::JobTransferred(IBackgroundCopyJob* pJob) +{ + printf("Job Transfred\n"); + pJob->Complete(); + printf("It is OK to close the command window.\n"); + return S_OK; +} + +STDMETHODIMP CNotifyInterfaceImp::JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError) +{ + printf("Job Failed\n"); + pJob->Cancel(); + printf("It is OK to close the command window.\n"); + return S_OK; +} + +STDMETHODIMP CNotifyInterfaceImp::JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved) +{ + return S_OK; +} + +STDMETHODIMP CNotifyInterfaceImp::FileTransferred(IBackgroundCopyJob* pJob, IBackgroundCopyFile* pFile) +{ + return S_OK; +} + +CNotifyInterfaceImp_Factory::CNotifyInterfaceImp_Factory() +{ +} + +CNotifyInterfaceImp_Factory::~CNotifyInterfaceImp_Factory() +{ +} + +// IUnknown method. Overridde QueryInterface() method. +STDMETHODIMP CNotifyInterfaceImp_Factory::QueryInterface(REFIID riid, void** ppvObject) +{ + if (riid == IID_IUnknown) + { + CReferenceCountedObject* pCReferenceCountedObject = (CReferenceCountedObject*)this; + + *ppvObject = (IUnknown*)pCReferenceCountedObject; + ((CReferenceCountedObject*)this) -> AddRef(); + return S_OK; + } + + if (riid == IID_IClassFactory) + { + *ppvObject = (IClassFactory*)this; + ((CReferenceCountedObject*)this) -> AddRef(); + return S_OK; + } + + *ppvObject = NULL; + + return E_NOINTERFACE; +} + +// IUnknown method. +STDMETHODIMP_(ULONG) CNotifyInterfaceImp_Factory::AddRef() +{ + return CClassFactory::AddRef(); +} + +// IUnknown method. +STDMETHODIMP_(ULONG) CNotifyInterfaceImp_Factory::Release() +{ + return CClassFactory::Release(); +} + +// IClassFactory method. +STDMETHODIMP CNotifyInterfaceImp_Factory::CreateInstance +( +IUnknown __RPC_FAR *pUnkOuter, +REFIID riid, +void __RPC_FAR *__RPC_FAR *ppvObject +) +{ + CNotifyInterfaceImp* pCExeObj01 = NULL; + + // Initialise the receiver. + *ppvObject = NULL; + + if (pUnkOuter != NULL) + { + return CLASS_E_NOAGGREGATION; + } + + // Create an instance of the component. + pCExeObj01 = new CNotifyInterfaceImp; + + if (pCExeObj01 == NULL) + { + return E_OUTOFMEMORY; + } + + pCExeObj01 -> QueryInterface (riid, ppvObject); + + pCExeObj01 -> Release(); + + printf("return a new callback instance\n"); + return S_OK; +} + +// IClassFactory method. +STDMETHODIMP CNotifyInterfaceImp_Factory::LockServer +( +BOOL fLock +) +{ + return CClassFactory::LockServer(fLock); +} diff --git a/Samples/ClsIDCallback/cpp/NotifyInterfaceImp.h b/Samples/ClsIDCallback/cpp/NotifyInterfaceImp.h new file mode 100644 index 00000000..d0b283a6 --- /dev/null +++ b/Samples/ClsIDCallback/cpp/NotifyInterfaceImp.h @@ -0,0 +1,133 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "Bits3_0.h" + +extern long g_lObjsInUse; +extern long g_lServerLocks; +extern DWORD g_dwMainThreadID; + +// This is the root class of all classes the objects of which are referenced counted. +class CReferenceCountedObject : public IUnknown +{ + public : + CReferenceCountedObject(); + virtual ~CReferenceCountedObject(); + + // IUnknown methods + STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + protected : + LONG m_cRef; +}; + + + +class CClassFactory : public IClassFactory +{ + public : + CClassFactory(); + virtual ~CClassFactory(); + + // IUnknown methods + STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + // IClassFactory methods. + STDMETHODIMP CreateInstance + ( + IUnknown __RPC_FAR *pUnkOuter, + REFIID riid, + void __RPC_FAR *__RPC_FAR *ppvObject + ); + + STDMETHODIMP LockServer + ( + BOOL fLock + ); + + protected : + LONG m_cRef; + + public : + // Shut down the application. + static void AttemptToTerminateServer(); +}; + +class CNotifyInterfaceImp : public CReferenceCountedObject, public IBackgroundCopyCallback2 +{ + public : + CNotifyInterfaceImp(); + ~CNotifyInterfaceImp(); + + // Overridden IUnknown methods + STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + public : + // IBackgroundCopyCallback2 interface impl. + STDMETHOD(JobTransferred)(IBackgroundCopyJob* pJob); + STDMETHOD(JobError)(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError); + STDMETHOD(JobModification)(IBackgroundCopyJob* pJob, DWORD dwReserved); + STDMETHOD(FileTransferred)(IBackgroundCopyJob* pJob, IBackgroundCopyFile* pFile); + + // IDispatch interface impl. + STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) + { + return E_NOTIMPL; + } + + STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) + { + return E_NOTIMPL; + } + + STDMETHOD(GetIDsOfNames)(REFIID riid, __in_ecount(cNames) LPOLESTR* rgszNames, UINT cNames, + LCID lcid, DISPID* rgdispid) + { + return E_NOTIMPL; + } + + STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, + EXCEPINFO* pexcepinfo, UINT* puArgErr) + { + return E_NOTIMPL; + } + +}; + +class CNotifyInterfaceImp_Factory : public CClassFactory +{ + public : + CNotifyInterfaceImp_Factory(); + ~CNotifyInterfaceImp_Factory(); + + // IUnknown methods + STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + // IClassFactory methods. + STDMETHODIMP CreateInstance + ( + IUnknown __RPC_FAR *pUnkOuter, + REFIID riid, + void __RPC_FAR *__RPC_FAR *ppvObject + ); + + STDMETHODIMP LockServer + ( + BOOL fLock + ); +}; + diff --git a/Samples/ClsIDCallback/cpp/ReadMe.txt b/Samples/ClsIDCallback/cpp/ReadMe.txt new file mode 100644 index 00000000..8611e445 --- /dev/null +++ b/Samples/ClsIDCallback/cpp/ReadMe.txt @@ -0,0 +1,43 @@ +Set\Get\Remove BITS CLSID callback Sample +================================ +This sample demonstrates how to set CLSID callback on the new IBackgroundCopyFile5 interface for a job. + +Sample Language Implementations +=============================== +C++ + +Files: +============================================= +ClsIDCallback.cpp +NotifyInterfaceImp.cpp +NotifyInterfaceImp.h +stdafx.cpp +stdafx.h +targetver.h +utils.cpp +utils.h +ReadMe.txt +ClsIDCallback.sln +ClsIDCallback.vcxproj + +To build the sample using the command prompt: +============================================= + 1. Open the Command Prompt window and navigate to the ClsIDCallback directory. + 2. Type msbuild ClsIDCallback.sln. + + +To build the sample using Visual Studio (preferred method): +=========================================================== + 1. Open Windows Explorer and navigate to the ClsIDCallback directory. + 2. Double-click the icon for the ShellStorage.sln 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. Create a directory "C:\BitsSample" This is the directory where the file will be downloaded. + 2. Execute "ClsIDCallback.exe RegServer" from the elevated command line to register the COM server. + 3. To execute the sample code, execute "ClsIDCallback.exe Demo" from a non-elevated command line. + 4. This sample assumes that the application is running in a non-elevated context, and will not complete successfully if run from an elevated command window. + 5. If the sample is executed successfully then you should see a command window with output "Job Transferred" and you should see a file C:\BitsSample\SQL2008UpgradeTechnicalReferenceGuide.docx + 6. To unregister the COM server execute "ClsIDCallback.exe UnRegServer" from an elevated command line. diff --git a/Samples/ClsIDCallback/cpp/stdafx.cpp b/Samples/ClsIDCallback/cpp/stdafx.cpp new file mode 100644 index 00000000..dfe386e5 --- /dev/null +++ b/Samples/ClsIDCallback/cpp/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// ClsIDSample.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Samples/ClsIDCallback/cpp/stdafx.h b/Samples/ClsIDCallback/cpp/stdafx.h new file mode 100644 index 00000000..b68e238b --- /dev/null +++ b/Samples/ClsIDCallback/cpp/stdafx.h @@ -0,0 +1,17 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/Samples/ClsIDCallback/cpp/targetver.h b/Samples/ClsIDCallback/cpp/targetver.h new file mode 100644 index 00000000..87c0086d --- /dev/null +++ b/Samples/ClsIDCallback/cpp/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/Samples/ClsIDCallback/cpp/utils.cpp b/Samples/ClsIDCallback/cpp/utils.cpp new file mode 100644 index 00000000..96e20328 --- /dev/null +++ b/Samples/ClsIDCallback/cpp/utils.cpp @@ -0,0 +1,167 @@ +#include "stdafx.h" +#include "utils.h" + +long g_lObjsInUse = 0; +long g_lServerLocks = 0; +DWORD g_dwMainThreadID = 0; + +TCHAR szClassKey[MAX_PATH]; +TCHAR szAppIDKey[MAX_PATH]; +TCHAR szClassRoot[] = _T("CLSID\\"); +TCHAR szAppIDRoot[] = _T("SOFTWARE\\Classes\\AppID\\"); +TCHAR szCLSID[] = _T("{C48FF713-B257-4242-B1FF-A86B61DF3B3E}"); + +void FormatObjectPath() +{ + HRESULT hr; + + // Compose the Classes Key of COM server + hr = StringCchPrintf(szClassKey,MAX_PATH,TEXT("%s%s"),szClassRoot,szCLSID); + + // Compose the AppID Key of COM server + hr = StringCchPrintf(szAppIDKey,MAX_PATH,TEXT("%s%s"),szAppIDRoot,szCLSID); +} + +// This code demonstrate the COM server registration code. Generally this happens during the installation of the component. +HRESULT RegisterServer() +{ + HKEY hCLSIDKey1 = NULL, hCLSIDKey2 = NULL, hInProcSvrKey = NULL, hImpCategoriesKey = NULL, hIIDMarshalKey = NULL; + LONG lRet; + HRESULT hr = S_OK; + TCHAR szModulePath [MAX_PATH]; + TCHAR szClassDescription[] = _T("NotifyInterfaceImp class"); + TCHAR szRunAs[] = _T("Interactive User"); + + try + { + // Create a key under CLSID for our COM server. + lRet = RegCreateKeyEx ( HKEY_CLASSES_ROOT, szClassKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_CREATE_SUB_KEY, + NULL, &hCLSIDKey1, NULL ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // The default value of the key is a human-readable description of the coclass. + lRet = RegSetValueEx ( hCLSIDKey1, NULL, 0, REG_SZ, (const BYTE*) szClassDescription, + sizeof(szClassDescription) ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // Create the "AppID" key + lRet = RegSetValueEx ( hCLSIDKey1, _T("AppID"), 0, REG_SZ, (const BYTE*) szCLSID, + sizeof(szCLSID) ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // Create the LocalServer32 key, which holds info about our coclass. + lRet = RegCreateKeyEx ( hCLSIDKey1, _T("LocalServer32"), 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, NULL, &hInProcSvrKey, NULL ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // The default value of the LocalServer32 key holds the full path to our executable. + GetModuleFileName (NULL, szModulePath, MAX_PATH ); + lRet = RegSetValueEx ( hInProcSvrKey, NULL, 0, REG_SZ, (const BYTE*) szModulePath, + sizeof(TCHAR) * (_tcslen(szModulePath)+1) ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // Create the "Implemented Categories" key + lRet = RegCreateKeyEx ( hCLSIDKey1, _T("Implemented Categories"), 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, NULL, &hImpCategoriesKey, NULL ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // Create the IID_IMarshal key + LPWSTR strIIDIMarshal = NULL; + StringFromCLSID(IID_IMarshal, &strIIDIMarshal); + + lRet = RegCreateKeyEx ( hImpCategoriesKey, strIIDIMarshal, 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, NULL, &hIIDMarshalKey, NULL ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + CoTaskMemFree(strIIDIMarshal); + + // Create a key under SOFTWARE\\Classes\\AppID for our COM server. + lRet = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, szAppIDKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_CREATE_SUB_KEY, + NULL, &hCLSIDKey2, NULL ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + // The default value of the key is a human-readable description of the coclass. + lRet = RegSetValueEx ( hCLSIDKey2, _T("RunAs"), 0, REG_SZ, (const BYTE*) szRunAs, sizeof(szRunAs) ); + + if ( ERROR_SUCCESS != lRet ) + { + throw lRet; + } + + hr = S_OK; + } + catch(HRESULT err) + { + printf("Registration failed - %x", err); + UnRegisterServer(); + } + + if ( NULL != hCLSIDKey1 ) + { + RegCloseKey ( hCLSIDKey1 ); + } + + if ( NULL != hCLSIDKey2 ) + { + RegCloseKey ( hCLSIDKey2 ); + } + + if ( NULL != hInProcSvrKey ) + { + RegCloseKey ( hInProcSvrKey ); + } + + if ( NULL != hImpCategoriesKey ) + { + RegCloseKey ( hImpCategoriesKey ); + } + + if ( NULL != hIIDMarshalKey ) + { + RegCloseKey ( hIIDMarshalKey ); + } + + return hr; +} + +HRESULT UnRegisterServer() +{ + //Delete the ClassID key + RegDeleteTree( HKEY_CLASSES_ROOT, szClassKey); + //Delete the AppID key + RegDeleteTree( HKEY_LOCAL_MACHINE, szAppIDKey); + return S_OK; +} diff --git a/Samples/ClsIDCallback/cpp/utils.h b/Samples/ClsIDCallback/cpp/utils.h new file mode 100644 index 00000000..1feaab7c --- /dev/null +++ b/Samples/ClsIDCallback/cpp/utils.h @@ -0,0 +1,61 @@ +#pragma once + +#include "stdafx.h" +#include "NotifyInterfaceImp.h" + +const CLSID CLSID_CNotifyInterfaceImp = {0xC48FF713,0xB257,0x4242,{0xB1,0xFF,0xA8,0x6B,0x61,0xDF,0x3B,0x3E}}; + +const WCHAR JOBTRANSFERRED_EVENTNAME[] = L"EVENT_CALLBACK_JOBTRANSFERRED"; +const WCHAR JOBERROR_EVENTNAME[] = L"EVENT_CALLBACK_JOBERROR"; + +HRESULT UnRegisterServer(); +void FormatObjectPath(); +HRESULT RegisterServer(); + +typedef struct +{ + LPWSTR RemoteFile; + LPWSTR LocalFile; +} DOWNLOAD_FILE; + +template +void RegisterClassObject(REFCLSID rclsid, LPDWORD lpdwCookieReceiver, T* pT_in = NULL) +{ + T* pT = NULL; + HRESULT hr = S_OK; + + if (pT_in) + { + pT = pT_in; + pT -> AddRef(); + } + else + { + pT = new T(); + } + + if (pT) + { + IUnknown* pIUnknown = NULL; + + pT -> QueryInterface(IID_IUnknown, (void**)&pIUnknown); + + if (pIUnknown) + { + hr = ::CoRegisterClassObject + ( + rclsid, + pIUnknown, + CLSCTX_LOCAL_SERVER, + REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, + lpdwCookieReceiver + ); + + pIUnknown -> Release(); + pIUnknown = NULL; + } + + pT -> Release(); + pT = NULL; + } +}; diff --git a/Samples/ConnectionManagerCost/README.md b/Samples/ConnectionManagerCost/README.md new file mode 100644 index 00000000..027c8966 --- /dev/null +++ b/Samples/ConnectionManagerCost/README.md @@ -0,0 +1,56 @@ +Windows Connection Manager WLAN cost sample +=========================================== + +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. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[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 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build the sample using Visual Studio (preferred method): + +1. Open **Windows Explorer** and navigate to the **\\cpp** directory. +2. Double-click the icon for the **.sln** (solution) file to open the file in Visual Studio. +3. In the **Build** menu, select **Build Solution**. The application will be built in the default **\\Debug** or **\\Release** directory. + +To 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**. + +Run the sample +-------------- + +To run the sample: + +1. Navigate to the directory that contains **wcmcostsample.exe**, using the **command prompt** or **Windows Explorer**. +2. Type **wcmcostsample.exe** at the **command prompt**, or double-click the icon for **wcmcostsample** to launch it from **Windows Explorer**. + diff --git a/Samples/ConnectionManagerCost/Readme.txt b/Samples/ConnectionManagerCost/Readme.txt new file mode 100644 index 00000000..c31b3af3 --- /dev/null +++ b/Samples/ConnectionManagerCost/Readme.txt @@ -0,0 +1,39 @@ +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/Utils.cpp b/Samples/ConnectionManagerCost/cpp/Utils.cpp new file mode 100644 index 00000000..422c1be7 --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/Utils.cpp @@ -0,0 +1,472 @@ +// 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 "Utils.h" + +//******************************************************************************************** +// Function: FlushCurrentLine +// +// Description: Clears any input lingering in the STDIN buffer +// +//******************************************************************************************** +void FlushCurrentLine() +{ + int i; + while ((i = getc(stdin)) != EOF && i != '\n') + { + continue; + } +} + +//******************************************************************************************** +// Function: GetInterfaceAndProfileName +// +// Description: Display the list of interfaces, and associated profile names, and get the user interested interface +// GUID and the profile name +// +//******************************************************************************************** +HRESULT GetInterfaceAndProfileName(_Out_ GUID *intfGuid, _Out_writes_(profNameLen) LPWSTR profName, _In_ DWORD profNameLen) +{ + DWORD dwRet = ERROR_SUCCESS; + DWORD dwCurVersion = 0; + HANDLE hWlan = NULL; + RPC_WSTR GuidString = NULL; + + int iIntf = 0; + int iProfile = 0; + + //variables used for WlanEnumInterfaces + WLAN_INTERFACE_INFO_LIST* pIfList = NULL; + WLAN_INTERFACE_INFO* pIfInfo = NULL; + + //variables used for WlanGetProfileList + PWLAN_PROFILE_INFO_LIST pProfileList = NULL; + PWLAN_PROFILE_INFO pProfile = NULL; + + //open handle to WLAN + dwRet = WlanOpenHandle(2, NULL, &dwCurVersion, &hWlan); + if (dwRet == ERROR_SUCCESS) + { + //Get the list of interfaces for WLAN + dwRet = WlanEnumInterfaces(hWlan, 0, &pIfList); + } + else + { + printf("Failed to open handle to WLAN. \n"); + } + if (dwRet == ERROR_SUCCESS) + { + for (int i = 0; i < (int) pIfList->dwNumberOfItems; i++) + { + pIfInfo = reinterpret_cast (&(pIfList->InterfaceInfo[i])); + dwRet = UuidToStringW(&(pIfInfo->InterfaceGuid), &GuidString); + if (dwRet == RPC_S_OK) + { + wprintf(L" Interface GUID [%lu]. %ws\n",i+1, GuidString); + + //Get list of profiles associated with this interface + dwRet = WlanGetProfileList(hWlan, &(pIfInfo->InterfaceGuid), NULL, &pProfileList); + + if (dwRet != ERROR_SUCCESS) + { + wprintf(L"WlanGetProfileList failed. \n"); + break; + } + for (int j = 0; j < (int) pProfileList->dwNumberOfItems; j++) + { + pProfile = reinterpret_cast (&(pProfileList->ProfileInfo[j])); + wprintf(L" Profile Name [%u]: %ws\n", j+1, pProfile->strProfileName); + } + } + else + { + wprintf(L"Cannot convert the GUID string.\n"); + break; + } + } + + if (dwRet == ERROR_SUCCESS) + { + if ((pIfList->dwNumberOfItems == 0) || (pProfileList->dwNumberOfItems == 0)) + { + dwRet = ERROR_NOT_FOUND; + wprintf(L"WLAN interface/profile not found! \n"); + } + else + { + //User input for interested interface Guid and Profile name + GetInterfaceIdAndProfileIndex((int) (pIfList->dwNumberOfItems), (int) (pProfileList->dwNumberOfItems), &iIntf, &iProfile); + //Get the interested Interface GUID and profile Name from the indices + pIfInfo = reinterpret_cast (&(pIfList->InterfaceInfo[iIntf-1])); + *intfGuid = pIfInfo -> InterfaceGuid; + pProfile = reinterpret_cast (&(pProfileList->ProfileInfo[iProfile-1])); + wmemcpy_s(profName, profNameLen, pProfile -> strProfileName, wcslen(pProfile -> strProfileName)); + profName[profNameLen-1] = '\0'; + } + } + } + else + { + wprintf(L"WlanEnumInterfaces failed. \n"); + } + + if (pProfileList != NULL) + { + //Free PWLAN_PROFILE_INFO_LIST + WlanFreeMemory(pProfileList); + pProfileList = NULL; + } + + if (pIfList != NULL) + { + //Free WLAN_INTERFACE_INFO_LIST + WlanFreeMemory(pIfList); + } + + if (hWlan != NULL) + { + WlanCloseHandle(hWlan, NULL); + } + + if (dwRet != ERROR_SUCCESS) + { + DisplayError(dwRet); + } + return HRESULT_FROM_WIN32(dwRet); +} + +//******************************************************************************************** +// Function: GetInterfaceIdAndProfileIndex +// +// Description: Choose indices for Interface Guids and Profile names displayed +// +//******************************************************************************************** + +void GetInterfaceIdAndProfileIndex(_In_ int numIntfItems, _In_ int numProfNames, _Out_ int *pIntf, _Out_ int *pProfile) +{ + //Get the interested interface GUID and profile name Indices + wprintf(L"The list of interfaces and profiles for each interface are listed as above.\n"); + do + { + wprintf(L"Choose an index for Interface GUID in the range [ 1 - %u ]: ", numIntfItems); + wscanf_s(L"%i", pIntf); + FlushCurrentLine(); + }while (((*pIntf) < 1)|| ((*pIntf) > numIntfItems)); + + do + { + wprintf(L"Choose an index for Profile Name in the range [ 1 - %u ] : ", numProfNames); + wscanf_s(L"%i", pProfile); + FlushCurrentLine(); + }while (((*pProfile) < 1)|| ((*pProfile) > numProfNames)); +} + +//******************************************************************************************** +// Function: DisplayCost +// +// Description: Displays meaningful cost values to the user +// +//******************************************************************************************** + +void DisplayCostDescription (_In_ DWORD cost) +{ + if (cost == WCM_CONNECTION_COST_UNKNOWN) + { + wprintf(L"Cost : Unknown\n"); + } + else if (cost & WCM_CONNECTION_COST_UNRESTRICTED) + { + wprintf(L"Cost : Unrestricted\n"); + } + else if (cost & WCM_CONNECTION_COST_FIXED) + { + wprintf(L"Cost : Fixed\n"); + } + else if (cost & WCM_CONNECTION_COST_VARIABLE) + { + wprintf(L"Cost : Variable\n"); + } + if (cost & WCM_CONNECTION_COST_OVERDATALIMIT) + { + wprintf(L"OverDataLimit : Yes\n"); + } + else + { + wprintf(L"OverDataLimit : No\n"); + } + + if (cost & WCM_CONNECTION_COST_APPROACHINGDATALIMIT) + { + wprintf(L"Approaching DataLimit : Yes\n"); + } + else + { + wprintf(L"Approaching DataLimit : No\n"); + } + + if (cost & WCM_CONNECTION_COST_CONGESTED) + { + wprintf(L"Congested : Yes\n"); + } + else + { + wprintf(L"Congested : No\n"); + } + + if (cost & WCM_CONNECTION_COST_ROAMING) + { + wprintf(L"Roaming : Yes\n"); + } + else + { + wprintf(L"Roaming : No\n"); + } +} + +//******************************************************************************************** +// Function: DisplayCostSource +// +// Description: Displays cost source to the user +// +//******************************************************************************************** + +void DisplayCostSource (_In_ WCM_CONNECTION_COST_SOURCE costSource) +{ + if (costSource == WCM_CONNECTION_COST_SOURCE_GP) + { + wprintf(L"Cost Source is Group Policy\n"); + } + + else if (costSource == WCM_CONNECTION_COST_SOURCE_USER) + { + wprintf(L"Cost Source is User\n"); + } + + else if (costSource == WCM_CONNECTION_COST_SOURCE_OPERATOR) + { + wprintf(L"Cost Source is Operator\n"); + } + + else if (costSource == WCM_CONNECTION_COST_SOURCE_DEFAULT) + { + wprintf(L"Cost Source is Default\n"); + } +} + + +//******************************************************************************************** +// Function: DisplayProfileData +// +// Description: Displays profile data values to the user +// +//******************************************************************************************** + +void DisplayProfileData (_In_ WCM_DATAPLAN_STATUS* pProfileData) +{ + if (FALSE == IsProfileDataAvailable(pProfileData)) + { + wprintf(L"Profile Data Unknown\n"); + } + else + { + //check for default or unknown value + if (pProfileData->UsageData.UsageInMegabytes != WCM_UNKNOWN_DATAPLAN_STATUS) + { + wprintf(L"Data Usage in MB : %d\n", pProfileData->UsageData.UsageInMegabytes); + } + + if ((pProfileData->UsageData.LastSyncTime.dwHighDateTime != 0) || (pProfileData->UsageData.LastSyncTime.dwLowDateTime != 0)) + { + wprintf(L"Last Sync Time : "); + PrintFileTime (pProfileData->UsageData.LastSyncTime); + } + if (pProfileData->DataLimitInMegabytes != WCM_UNKNOWN_DATAPLAN_STATUS) + { + wprintf(L"Data Limit value in MB : %d\n", pProfileData->DataLimitInMegabytes); + } + if (pProfileData->InboundBandwidthInKbps != WCM_UNKNOWN_DATAPLAN_STATUS) + { + wprintf(L"Inbound Bandwidth value in Kbps : %d\n", pProfileData->InboundBandwidthInKbps ); + } + if (pProfileData->OutboundBandwidthInKbps != WCM_UNKNOWN_DATAPLAN_STATUS) + { + wprintf(L"Outbound Bandwidth value in Kbps : %d\n", pProfileData->OutboundBandwidthInKbps ); + } + if ((pProfileData->BillingCycle.StartDate.dwHighDateTime!= 0) || (pProfileData->BillingCycle.StartDate.dwLowDateTime != 0)) + { + wprintf(L"Billing Cycle Start Date : "); + PrintFileTime (pProfileData->BillingCycle.StartDate); + if (IsProfilePlanDurationAvailable (pProfileData->BillingCycle.Duration)) + { + wprintf(L"Billing Cycle Duration : \n"); + DisplayProfilePlanDuration (pProfileData->BillingCycle.Duration); + } + + } + + if (pProfileData->MaxTransferSizeInMegabytes != WCM_UNKNOWN_DATAPLAN_STATUS) + { + wprintf(L"Maximum Transfer Size in MB : %d\n", pProfileData->MaxTransferSizeInMegabytes); + } + } + +} + +//******************************************************************************************** +// Function: IsProfilePlanDurationAvailable +// +// Description: Return TRUE if Profile Plan Duration is available +// +//******************************************************************************************** +BOOL IsProfilePlanDurationAvailable (_In_ WCM_TIME_INTERVAL Duration) +{ + BOOL isAvailable = FALSE; + if ((Duration.wYear > 0 )|| + (Duration.wMonth > 0) || + (Duration.wDay > 0) || + (Duration.wHour > 0) || + (Duration.wMinute > 0) || + (Duration.wSecond > 0) || + (Duration.wMilliseconds > 0)) + { + isAvailable = TRUE; + } + return isAvailable; +} + + +//******************************************************************************************** +// Function: DisplayProfilePlanDuration +// +// Description: Display the Profile Plan Duration +// +//******************************************************************************************** + +void DisplayProfilePlanDuration (_In_ WCM_TIME_INTERVAL Duration) +{ + if (Duration.wYear > 0) + { + wprintf(L"Years : %d\n", Duration.wYear); + } + + if (Duration.wMonth > 0) + { + wprintf(L"Months : %d\n", Duration.wMonth); + } + + if (Duration.wDay > 0) + { + wprintf(L"Days : %d\n", Duration.wDay); + } + + if (Duration.wHour > 0) + { + wprintf(L"Hours : %d\n", Duration.wHour); + } + + if (Duration.wMinute > 0) + { + wprintf(L"Minutes : %d\n", Duration.wMinute); + } + + if (Duration.wSecond > 0) + { + wprintf(L"Seconds : %d\n", Duration.wSecond); + } + + if (Duration.wMilliseconds > 0) + { + wprintf(L"Milliseconds : %d\n", Duration.wMilliseconds); + } + +} + + +//******************************************************************************************** +// Function: PrintFileTime +// +// Description: Converts file time to local time, to display to the user +// +//******************************************************************************************** + +void PrintFileTime(_In_ FILETIME time) +{ + SYSTEMTIME stUTC, stLocal; + + // Convert filetime to local time. + FileTimeToSystemTime(&time, &stUTC); + SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); + wprintf(L"%02d/%02d/%d %02d:%02d:%02d\n", + stLocal.wMonth, stLocal.wDay, stLocal.wYear,stLocal.wHour, stLocal.wMinute, stLocal.wSecond); +} + + +//******************************************************************************************** +// Function: IsProfileDataAvailable +// +// Description: Checks if the profile data values are default values, or provided by the MNO +// +//******************************************************************************************** +BOOL IsProfileDataAvailable(_In_ WCM_DATAPLAN_STATUS *pProfileData) +{ + BOOL isDefined = FALSE; + // + // usage data is valid only if both planUsage and lastUpdatedTime are valid + // + if (pProfileData->UsageData.UsageInMegabytes != WCM_UNKNOWN_DATAPLAN_STATUS + && (pProfileData->UsageData.LastSyncTime.dwHighDateTime != 0 + || pProfileData->UsageData.LastSyncTime.dwLowDateTime!= 0)) + { + isDefined = TRUE; + } + else if (pProfileData->DataLimitInMegabytes != WCM_UNKNOWN_DATAPLAN_STATUS) + { + isDefined = TRUE; + } + else if (pProfileData->InboundBandwidthInKbps != WCM_UNKNOWN_DATAPLAN_STATUS) + { + isDefined = TRUE; + } + else if (pProfileData->OutboundBandwidthInKbps != WCM_UNKNOWN_DATAPLAN_STATUS) + { + isDefined = TRUE; + } + else if (pProfileData->BillingCycle.StartDate.dwHighDateTime != 0 + || pProfileData->BillingCycle.StartDate.dwLowDateTime!= 0) + { + isDefined = TRUE; + + } + else if (pProfileData->MaxTransferSizeInMegabytes!= WCM_UNKNOWN_DATAPLAN_STATUS) + { + isDefined = TRUE; + } + return isDefined; +} + + +//******************************************************************************************** +// Function: DisplayError +// +// Description: Displays error description +// +//******************************************************************************************** +void DisplayError(_In_ DWORD dwError) +{ + if (dwError == REGKEY_NOT_FOUND) + { + wprintf(L"Registry key not found \n"); + } + else if (dwError == INVALID_PARAMETER) + { + wprintf(L"Invalid Parameter\n"); + } + else + { + wprintf(L"Error code: %u\n", dwError); + } +} diff --git a/Samples/ConnectionManagerCost/cpp/Utils.h b/Samples/ConnectionManagerCost/cpp/Utils.h new file mode 100644 index 00000000..9b6e3fb1 --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/Utils.h @@ -0,0 +1,79 @@ +// 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 "wcmapi.h" +#include +#include + + +#define CHOICE_EXIT 5 +#define REGKEY_NOT_FOUND 2 +#define INVALID_PARAMETER 87 + +// +// Display the list of interfaces, and associated profile names, and get the user interested interface +// GUID and the profile name +// +HRESULT GetInterfaceAndProfileName(_Out_ GUID *intfGuid, _Out_writes_(profNameLen) LPWSTR profName, _In_ DWORD profNameLen); + +// +// Displays meaningful cost values to the user +// +void DisplayCostDescription (_In_ DWORD cost); + +// +// Displays cost source to the user +// +void DisplayCostSource (_In_ WCM_CONNECTION_COST_SOURCE costSource); + +// +// Displays profile data values to the user +// +void DisplayProfileData (_In_ WCM_DATAPLAN_STATUS* pProfileData); + +// +// Display the Profile Plan Duration +// +void DisplayProfilePlanDuration (_In_ WCM_TIME_INTERVAL Duration); + +// +// Return TRUE if Profile Plan Duration is available +// +BOOL IsProfilePlanDurationAvailable (_In_ WCM_TIME_INTERVAL Duration); + +// +// Checks if the profile data values are default values, or provided by the MNO +// +BOOL IsProfileDataAvailable(_In_ WCM_DATAPLAN_STATUS *pProfileData); + +// +// Converts file time to local time, to display to the user +// +void PrintFileTime(_In_ FILETIME time); + +// +// Clears any input lingering in the STDIN buffer +// +void FlushCurrentLine(); + +// +// Displays error description +// +void DisplayError(_In_ DWORD dwError); + +// +// Choose indices for Interface Guids and Profile names displayed +// +void GetInterfaceIdAndProfileIndex(_In_ int numIntfItems, _In_ int numProfNames, _Out_ int *iIntf, _Out_ int *iProfile); diff --git a/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln b/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln new file mode 100644 index 00000000..52d3b9cf --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/WcmCostSample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +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 + 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 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj b/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj new file mode 100644 index 00000000..13ab969b --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj @@ -0,0 +1,96 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {C11BA656-32FE-4BE3-A3D8-943E832FFDB3} + Win32Proj + WcmCostSample + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + + + Console + 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) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj.filters b/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj.filters new file mode 100644 index 00000000..79015379 --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/WcmCostSample.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;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 + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Samples/ConnectionManagerCost/cpp/Wcmcostsample.cpp b/Samples/ConnectionManagerCost/cpp/Wcmcostsample.cpp new file mode 100644 index 00000000..801479f6 --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/Wcmcostsample.cpp @@ -0,0 +1,343 @@ +// 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 "WcmCostSample.h" +#include + +//******************************************************************************************** +// Function: WCMGetCost +// +// Description: Get cost based on interface GUID and profile name +// +//******************************************************************************************** +void WCMGetCost() +{ + GUID interfaceGUID = {0}; + WCHAR profileName[WLAN_MAX_NAME_LENGTH+1]; + DWORD dwRetCode = NO_ERROR; + DWORD dwSize = 0; + WCM_CONNECTION_COST_DATA *data = 0; + PBYTE pData = NULL; + HRESULT hr = S_OK; + + ZeroMemory(profileName, WLAN_MAX_NAME_LENGTH*sizeof(WCHAR)); + //Get interface GUID and profile name + hr = GetInterfaceAndProfileName(&interfaceGUID, profileName, WLAN_MAX_NAME_LENGTH); + if (hr == S_OK) + { + //Get Cost using WcmQueryProperty + dwRetCode = WcmQueryProperty(&interfaceGUID, + profileName, + wcm_intf_property_connection_cost, + NULL, + &dwSize, + &pData); + + if (dwRetCode == ERROR_SUCCESS) + { + if (pData == NULL) + { + wprintf(L"Cost data not available\n"); + } + else + { + data = reinterpret_cast (pData); + wprintf(L"Cost is: %d\n", (data->ConnectionCost)); + + //Display meaningful cost description + DisplayCostDescription (data->ConnectionCost); + DisplayCostSource (data->CostSource); + WcmFreeMemory(pData); + } + } + else + { + wprintf(L"WcmQueryProperty failed\n"); + //Error handling + DisplayError(dwRetCode); + } + } +} + + +//******************************************************************************************** +// Function: WCMGetProfileData +// +// Description: Get Profile data based on interface GUID and profile name +// +//******************************************************************************************** +void WCMGetProfileData() +{ + GUID interfaceGUID = {0}; + WCHAR profileName[WLAN_MAX_NAME_LENGTH+1]; + DWORD dwRetCode = NO_ERROR; + DWORD dwSize = 0; + PBYTE pData = NULL; + HRESULT hr = S_OK; + + ZeroMemory(profileName, WLAN_MAX_NAME_LENGTH*sizeof(WCHAR)); + //Get interface GUID and profile name + hr = GetInterfaceAndProfileName(&interfaceGUID, profileName, WLAN_MAX_NAME_LENGTH); + if (hr == S_OK) + { + //Get Profile Data using WcmQueryProperty + dwRetCode = WcmQueryProperty(&interfaceGUID, + profileName, + wcm_intf_property_dataplan_status, + NULL, + &dwSize, + &pData); + + if ((dwRetCode == ERROR_SUCCESS) && (pData != NULL)) + { + WCM_DATAPLAN_STATUS * data = reinterpret_cast (pData); + DisplayProfileData(data); + WcmFreeMemory(pData); + } + else + { + wprintf(L"WcmQueryProperty failed.\n"); + //Error handling + DisplayError(dwRetCode); + } + } +} + + +//******************************************************************************************** +// Function: WCMSetCost +// +// Description: Set cost based on interface GUID and profile name +// +//******************************************************************************************** +void WCMSetCost() +{ + DWORD dwNewCost = 0; + GUID interfaceGUID = {0}; + WCHAR profileName[WLAN_MAX_NAME_LENGTH+1]; + DWORD dwRetCode = NO_ERROR; + DWORD dwSize = 0; + PBYTE pData = NULL; + HRESULT hr = S_OK; + WCM_CONNECTION_COST_DATA wcmCostData = {0}; + + ZeroMemory(profileName, WLAN_MAX_NAME_LENGTH*sizeof(WCHAR)); + //Get interface GUID and profile name + hr = GetInterfaceAndProfileName(&interfaceGUID, profileName, WLAN_MAX_NAME_LENGTH); + + if (hr == S_OK) + { + wprintf(L"Enter the new cost:\n"); + wscanf_s(L"%u",&dwNewCost); + FlushCurrentLine(); + + wcmCostData.ConnectionCost = dwNewCost; + pData = (PBYTE)&wcmCostData; + dwSize = sizeof(wcmCostData); + + //Set cost using WcmSetProperty + dwRetCode = WcmSetProperty(&interfaceGUID, + profileName, + wcm_intf_property_connection_cost, + NULL, + dwSize, + pData + ); + if (dwRetCode == ERROR_SUCCESS) + { + wprintf(L"Cost set successfully\n"); + } + else + { + wprintf(L"WcmSetProperty failed \n"); + //Error handling + DisplayError(dwRetCode); + } + } +} + +//******************************************************************************************** +// Function: WCMSetProfileData +// +// Description: Set Profile data based on interface GUID and profile name +// +//******************************************************************************************** +void WCMSetProfileData() +{ + GUID interfaceGUID = {0}; + WCHAR profileName[WLAN_MAX_NAME_LENGTH+1]; + DWORD dwRetCode = NO_ERROR; + DWORD dwSize = 0; + DWORD profUsageInMegabytes = 0; + DWORD profDataLimitInMegabytes = 0; + DWORD profInboundBandwidthInKbps = 0; + DWORD profOutboundBandwidthInKbps = 0; + DWORD profMaxTransferSizeInMegabytes = 0; + PBYTE pData = NULL; + SYSTEMTIME currentTime = {0}; + HRESULT hr = S_OK; + + ZeroMemory(profileName, WLAN_MAX_NAME_LENGTH*sizeof(WCHAR)); + //Get interface GUID and profile name + hr = GetInterfaceAndProfileName(&interfaceGUID, profileName, WLAN_MAX_NAME_LENGTH); + + if (hr == S_OK) + { + //initialize Profile data values + WCM_DATAPLAN_STATUS wcmProfData = {0}; + wcmProfData.UsageData.UsageInMegabytes = WCM_UNKNOWN_DATAPLAN_STATUS; + wcmProfData.DataLimitInMegabytes = WCM_UNKNOWN_DATAPLAN_STATUS; + wcmProfData.InboundBandwidthInKbps = WCM_UNKNOWN_DATAPLAN_STATUS; + wcmProfData.OutboundBandwidthInKbps = WCM_UNKNOWN_DATAPLAN_STATUS; + wcmProfData.MaxTransferSizeInMegabytes = WCM_UNKNOWN_DATAPLAN_STATUS; + + //Set Profile data usage + wprintf(L"Enter Profile Usage value in Megabytes:\n"); + wscanf_s(L"%u", &profUsageInMegabytes); + FlushCurrentLine(); + wcmProfData.UsageData.UsageInMegabytes = profUsageInMegabytes; + GetSystemTime(¤tTime); + SystemTimeToFileTime(¤tTime, &wcmProfData.UsageData.LastSyncTime); + + //Set Profile cap value + wprintf(L"Enter Profile Data Limit value n Megabytes:\n"); + wscanf_s(L"%u", &profDataLimitInMegabytes); + FlushCurrentLine(); + wcmProfData.DataLimitInMegabytes = profDataLimitInMegabytes; + + + //Set Profile speed value + wprintf(L"Enter Profile Inbound Bandwidth value in Kbps:\n"); + wscanf_s(L"%u", &profInboundBandwidthInKbps); + FlushCurrentLine(); + wcmProfData.InboundBandwidthInKbps = profInboundBandwidthInKbps; + + wprintf(L"Enter Profile Outbound Bandwidth value in Kbps:\n"); + wscanf_s(L"%u", &profOutboundBandwidthInKbps); + FlushCurrentLine(); + wcmProfData.OutboundBandwidthInKbps = profOutboundBandwidthInKbps; + + //Set Profile speed value + wprintf(L"Enter Profile Max Transfer Size in Megabytes:\n"); + wscanf_s(L"%u", &profMaxTransferSizeInMegabytes); + FlushCurrentLine(); + wcmProfData.MaxTransferSizeInMegabytes = profMaxTransferSizeInMegabytes; + + dwSize = sizeof(wcmProfData); + pData = (PBYTE)&wcmProfData; + + //Set Profile Data using WcmSetProperty + dwRetCode = WcmSetProperty(&interfaceGUID, + profileName, + wcm_intf_property_dataplan_status, + NULL, + dwSize, + pData + ); + + if (dwRetCode == ERROR_SUCCESS) + { + wprintf(L"Profile Data set successfully\n"); + } + else + { + wprintf(L"WcmSetProperty failed\n"); + //Error handling + DisplayError(dwRetCode); + } + } +} + +//******************************************************************************************** +// Function: EvaluateUserChoice +// +// Description: Evaulates the user choice and calls the appropriate function. +// +//******************************************************************************************** + +void EvaluateUserChoice(_In_ int userchoice) +{ + switch (userchoice) + { + case 1: + WCMGetCost(); + break; + case 2: + WCMGetProfileData(); + break; + case 3: + WCMSetCost(); + break; + case 4: + WCMSetProfileData(); + break; + case 5: + break; + default: + wprintf(L"Invalid choice. Please enter a valid choice number \n"); + } +} + +//******************************************************************************************** +// Function: GetUserChoice +// +// Description: Presents an interactive menu to the user and calls the function EvaluateUserChoice to implement user's choice +// +// ******************************************************************************************** + +int GetUserChoice() +{ + int chr = -1; + int numchoices = 5; + PCWSTR choices[] = { + L"Get Cost", + L"Get Profile Data ", + L"Set Cost", + L"Set Profile Data", + L"Exit" }; + wprintf(L"---------------------------------------------------------\n"); + + for(int i=0; i 0 && chr <= numchoices) + { + EvaluateUserChoice(chr); + } + else + { + wprintf(L"Invalid Choice. Please enter a valid choice number\n"); + } + return chr; +} + + +//******************************************************************************************** +// Function: Main +// +// Description: The main function, calls GetUserChoice, to enable the user to play with the Sample SDK +// +//******************************************************************************************** + +void __cdecl main() +{ + int userChoice = -1; + + //Get user choice option to play with the WCM sample SDK + while (userChoice != CHOICE_EXIT) + { + userChoice = GetUserChoice(); + + } + wprintf(L"WCM Sample SDK exited\n"); +} diff --git a/Samples/ConnectionManagerCost/cpp/Wcmcostsample.h b/Samples/ConnectionManagerCost/cpp/Wcmcostsample.h new file mode 100644 index 00000000..ae29f15f --- /dev/null +++ b/Samples/ConnectionManagerCost/cpp/Wcmcostsample.h @@ -0,0 +1,37 @@ +// 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 "Utils.h" +// +// Get cost based on interface GUID and profile name +// +void WCMGetCost(); + +// +// Get Profile data based on interface GUID and profile name +// +void WCMGetProfileData(); + +// +// Set cost based on interface GUID and profile name +// +void WCMSetCost(); + +// +// Set Profile data based on interface GUID and profile name +// +void WCMSetProfileData(); + +// +// Evaulates the user choice and calls the appropriate function. +// +void EvaluateUserChoice(_In_ int userchoice); + +// +// Presents an interactive menu to the user and calls the function EvaluateUserChoice to implement user's choice +// +int GetUserChoice(); diff --git a/Samples/CredentialProvider/README.md b/Samples/CredentialProvider/README.md new file mode 100644 index 00000000..b32b9823 --- /dev/null +++ b/Samples/CredentialProvider/README.md @@ -0,0 +1,32 @@ +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). + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +1. Start Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/CredentialProvider/cpp/CSampleCredential.cpp b/Samples/CredentialProvider/cpp/CSampleCredential.cpp new file mode 100644 index 00000000..c1806d06 --- /dev/null +++ b/Samples/CredentialProvider/cpp/CSampleCredential.cpp @@ -0,0 +1,700 @@ +// +// 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. +// +// + +#ifndef WIN32_NO_STATUS +#include +#define WIN32_NO_STATUS +#endif +#include +#include "CSampleCredential.h" +#include "guid.h" + +CSampleCredential::CSampleCredential(): + _cRef(1), + _pCredProvCredentialEvents(nullptr), + _pszUserSid(nullptr), + _pszQualifiedUserName(nullptr), + _fIsLocalUser(false), + _fChecked(false), + _fShowControls(false), + _dwComboIndex(0) +{ + DllAddRef(); + + ZeroMemory(_rgCredProvFieldDescriptors, sizeof(_rgCredProvFieldDescriptors)); + ZeroMemory(_rgFieldStatePairs, sizeof(_rgFieldStatePairs)); + ZeroMemory(_rgFieldStrings, sizeof(_rgFieldStrings)); +} + +CSampleCredential::~CSampleCredential() +{ + if (_rgFieldStrings[SFI_PASSWORD]) + { + size_t lenPassword = wcslen(_rgFieldStrings[SFI_PASSWORD]); + SecureZeroMemory(_rgFieldStrings[SFI_PASSWORD], lenPassword * sizeof(*_rgFieldStrings[SFI_PASSWORD])); + } + for (int i = 0; i < ARRAYSIZE(_rgFieldStrings); i++) + { + CoTaskMemFree(_rgFieldStrings[i]); + CoTaskMemFree(_rgCredProvFieldDescriptors[i].pszLabel); + } + CoTaskMemFree(_pszUserSid); + CoTaskMemFree(_pszQualifiedUserName); + DllRelease(); +} + + +// Initializes one credential with the field information passed in. +// Set the value of the SFI_LARGE_TEXT field to pwzUsername. +HRESULT CSampleCredential::Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + _In_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR const *rgcpfd, + _In_ FIELD_STATE_PAIR const *rgfsp, + _In_ ICredentialProviderUser *pcpUser) +{ + HRESULT hr = S_OK; + _cpus = cpus; + + GUID guidProvider; + pcpUser->GetProviderID(&guidProvider); + _fIsLocalUser = (guidProvider == Identity_LocalUserProvider); + + // Copy the field descriptors for each field. This is useful if you want to vary the field + // descriptors based on what Usage scenario the credential was created for. + for (DWORD i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(_rgCredProvFieldDescriptors); i++) + { + _rgFieldStatePairs[i] = rgfsp[i]; + hr = FieldDescriptorCopy(rgcpfd[i], &_rgCredProvFieldDescriptors[i]); + } + + // Initialize the String value of all the fields. + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Sample Credential", &_rgFieldStrings[SFI_LABEL]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Sample Credential Provider", &_rgFieldStrings[SFI_LARGE_TEXT]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Edit Text", &_rgFieldStrings[SFI_EDIT_TEXT]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"", &_rgFieldStrings[SFI_PASSWORD]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Submit", &_rgFieldStrings[SFI_SUBMIT_BUTTON]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Checkbox", &_rgFieldStrings[SFI_CHECKBOX]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Combobox", &_rgFieldStrings[SFI_COMBOBOX]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Launch helper window", &_rgFieldStrings[SFI_LAUNCHWINDOW_LINK]); + } + if (SUCCEEDED(hr)) + { + hr = SHStrDupW(L"Hide additional controls", &_rgFieldStrings[SFI_HIDECONTROLS_LINK]); + } + if (SUCCEEDED(hr)) + { + hr = pcpUser->GetStringValue(PKEY_Identity_QualifiedUserName, &_pszQualifiedUserName); + } + if (SUCCEEDED(hr)) + { + PWSTR pszUserName; + pcpUser->GetStringValue(PKEY_Identity_UserName, &pszUserName); + if (pszUserName != nullptr) + { + wchar_t szString[256]; + StringCchPrintf(szString, ARRAYSIZE(szString), L"User Name: %s", pszUserName); + hr = SHStrDupW(szString, &_rgFieldStrings[SFI_FULLNAME_TEXT]); + CoTaskMemFree(pszUserName); + } + else + { + hr = SHStrDupW(L"User Name is NULL", &_rgFieldStrings[SFI_FULLNAME_TEXT]); + } + } + if (SUCCEEDED(hr)) + { + PWSTR pszDisplayName; + pcpUser->GetStringValue(PKEY_Identity_DisplayName, &pszDisplayName); + if (pszDisplayName != nullptr) + { + wchar_t szString[256]; + StringCchPrintf(szString, ARRAYSIZE(szString), L"Display Name: %s", pszDisplayName); + hr = SHStrDupW(szString, &_rgFieldStrings[SFI_DISPLAYNAME_TEXT]); + CoTaskMemFree(pszDisplayName); + } + else + { + hr = SHStrDupW(L"Display Name is NULL", &_rgFieldStrings[SFI_DISPLAYNAME_TEXT]); + } + } + if (SUCCEEDED(hr)) + { + PWSTR pszLogonStatus; + pcpUser->GetStringValue(PKEY_Identity_LogonStatusString, &pszLogonStatus); + if (pszLogonStatus != nullptr) + { + wchar_t szString[256]; + StringCchPrintf(szString, ARRAYSIZE(szString), L"Logon Status: %s", pszLogonStatus); + hr = SHStrDupW(szString, &_rgFieldStrings[SFI_LOGONSTATUS_TEXT]); + CoTaskMemFree(pszLogonStatus); + } + else + { + hr = SHStrDupW(L"Logon Status is NULL", &_rgFieldStrings[SFI_LOGONSTATUS_TEXT]); + } + } + + if (SUCCEEDED(hr)) + { + hr = pcpUser->GetSid(&_pszUserSid); + } + + return hr; +} + +// LogonUI calls this in order to give us a callback in case we need to notify it of anything. +HRESULT CSampleCredential::Advise(_In_ ICredentialProviderCredentialEvents *pcpce) +{ + if (_pCredProvCredentialEvents != nullptr) + { + _pCredProvCredentialEvents->Release(); + } + return pcpce->QueryInterface(IID_PPV_ARGS(&_pCredProvCredentialEvents)); +} + +// LogonUI calls this to tell us to release the callback. +HRESULT CSampleCredential::UnAdvise() +{ + if (_pCredProvCredentialEvents) + { + _pCredProvCredentialEvents->Release(); + } + _pCredProvCredentialEvents = nullptr; + return S_OK; +} + +// LogonUI calls this function when our tile is selected (zoomed) +// If you simply want fields to show/hide based on the selected state, +// there's no need to do anything here - you can set that up in the +// field definitions. But if you want to do something +// more complicated, like change the contents of a field when the tile is +// selected, you would do it here. +HRESULT CSampleCredential::SetSelected(_Out_ BOOL *pbAutoLogon) +{ + *pbAutoLogon = FALSE; + return S_OK; +} + +// Similarly to SetSelected, LogonUI calls this when your tile was selected +// and now no longer is. The most common thing to do here (which we do below) +// is to clear out the password field. +HRESULT CSampleCredential::SetDeselected() +{ + HRESULT hr = S_OK; + if (_rgFieldStrings[SFI_PASSWORD]) + { + size_t lenPassword = wcslen(_rgFieldStrings[SFI_PASSWORD]); + SecureZeroMemory(_rgFieldStrings[SFI_PASSWORD], lenPassword * sizeof(*_rgFieldStrings[SFI_PASSWORD])); + + CoTaskMemFree(_rgFieldStrings[SFI_PASSWORD]); + hr = SHStrDupW(L"", &_rgFieldStrings[SFI_PASSWORD]); + + if (SUCCEEDED(hr) && _pCredProvCredentialEvents) + { + _pCredProvCredentialEvents->SetFieldString(this, SFI_PASSWORD, _rgFieldStrings[SFI_PASSWORD]); + } + } + + return hr; +} + +// Get info for a particular field of a tile. Called by logonUI to get information +// to display the tile. +HRESULT CSampleCredential::GetFieldState(DWORD dwFieldID, + _Out_ CREDENTIAL_PROVIDER_FIELD_STATE *pcpfs, + _Out_ CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *pcpfis) +{ + HRESULT hr; + + // Validate our parameters. + if ((dwFieldID < ARRAYSIZE(_rgFieldStatePairs))) + { + *pcpfs = _rgFieldStatePairs[dwFieldID].cpfs; + *pcpfis = _rgFieldStatePairs[dwFieldID].cpfis; + hr = S_OK; + } + else + { + hr = E_INVALIDARG; + } + return hr; +} + +// Sets ppwsz to the string value of the field at the index dwFieldID +HRESULT CSampleCredential::GetStringValue(DWORD dwFieldID, _Outptr_result_nullonfailure_ PWSTR *ppwsz) +{ + HRESULT hr; + *ppwsz = nullptr; + + // Check to make sure dwFieldID is a legitimate index + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors)) + { + // Make a copy of the string and return that. The caller + // is responsible for freeing it. + hr = SHStrDupW(_rgFieldStrings[dwFieldID], ppwsz); + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Get the image to show in the user tile +HRESULT CSampleCredential::GetBitmapValue(DWORD dwFieldID, _Outptr_result_nullonfailure_ HBITMAP *phbmp) +{ + HRESULT hr; + *phbmp = nullptr; + + if ((SFI_TILEIMAGE == dwFieldID)) + { + HBITMAP hbmp = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_TILE_IMAGE)); + if (hbmp != nullptr) + { + hr = S_OK; + *phbmp = hbmp; + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Sets pdwAdjacentTo to the index of the field the submit button should be +// adjacent to. We recommend that the submit button is placed next to the last +// field which the user is required to enter information in. Optional fields +// should be below the submit button. +HRESULT CSampleCredential::GetSubmitButtonValue(DWORD dwFieldID, _Out_ DWORD *pdwAdjacentTo) +{ + HRESULT hr; + + if (SFI_SUBMIT_BUTTON == dwFieldID) + { + // pdwAdjacentTo is a pointer to the fieldID you want the submit button to + // appear next to. + *pdwAdjacentTo = SFI_PASSWORD; + hr = S_OK; + } + else + { + hr = E_INVALIDARG; + } + return hr; +} + +// Sets the value of a field which can accept a string as a value. +// This is called on each keystroke when a user types into an edit field +HRESULT CSampleCredential::SetStringValue(DWORD dwFieldID, _In_ PCWSTR pwz) +{ + HRESULT hr; + + // Validate parameters. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_EDIT_TEXT == _rgCredProvFieldDescriptors[dwFieldID].cpft || + CPFT_PASSWORD_TEXT == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + PWSTR *ppwszStored = &_rgFieldStrings[dwFieldID]; + CoTaskMemFree(*ppwszStored); + hr = SHStrDupW(pwz, ppwszStored); + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Returns whether a checkbox is checked or not as well as its label. +HRESULT CSampleCredential::GetCheckboxValue(DWORD dwFieldID, _Out_ BOOL *pbChecked, _Outptr_result_nullonfailure_ PWSTR *ppwszLabel) +{ + HRESULT hr; + *ppwszLabel = nullptr; + + // Validate parameters. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_CHECKBOX == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + *pbChecked = _fChecked; + hr = SHStrDupW(_rgFieldStrings[SFI_CHECKBOX], ppwszLabel); + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Sets whether the specified checkbox is checked or not. +HRESULT CSampleCredential::SetCheckboxValue(DWORD dwFieldID, BOOL bChecked) +{ + HRESULT hr; + + // Validate parameters. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_CHECKBOX == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + _fChecked = bChecked; + hr = S_OK; + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Returns the number of items to be included in the combobox (pcItems), as well as the +// currently selected item (pdwSelectedItem). +HRESULT CSampleCredential::GetComboBoxValueCount(DWORD dwFieldID, _Out_ DWORD *pcItems, _Deref_out_range_(<, *pcItems) _Out_ DWORD *pdwSelectedItem) +{ + HRESULT hr; + *pcItems = 0; + *pdwSelectedItem = 0; + + // Validate parameters. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_COMBOBOX == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + *pcItems = ARRAYSIZE(s_rgComboBoxStrings); + *pdwSelectedItem = 0; + hr = S_OK; + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Called iteratively to fill the combobox with the string (ppwszItem) at index dwItem. +HRESULT CSampleCredential::GetComboBoxValueAt(DWORD dwFieldID, DWORD dwItem, _Outptr_result_nullonfailure_ PWSTR *ppwszItem) +{ + HRESULT hr; + *ppwszItem = nullptr; + + // Validate parameters. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_COMBOBOX == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + hr = SHStrDupW(s_rgComboBoxStrings[dwItem], ppwszItem); + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Called when the user changes the selected item in the combobox. +HRESULT CSampleCredential::SetComboBoxSelectedValue(DWORD dwFieldID, DWORD dwSelectedItem) +{ + HRESULT hr; + + // Validate parameters. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_COMBOBOX == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + _dwComboIndex = dwSelectedItem; + hr = S_OK; + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Called when the user clicks a command link. +HRESULT CSampleCredential::CommandLinkClicked(DWORD dwFieldID) +{ + HRESULT hr = S_OK; + + CREDENTIAL_PROVIDER_FIELD_STATE cpfsShow = CPFS_HIDDEN; + + // Validate parameter. + if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && + (CPFT_COMMAND_LINK == _rgCredProvFieldDescriptors[dwFieldID].cpft)) + { + HWND hwndOwner = nullptr; + switch (dwFieldID) + { + case SFI_LAUNCHWINDOW_LINK: + if (_pCredProvCredentialEvents) + { + _pCredProvCredentialEvents->OnCreatingWindow(&hwndOwner); + } + + // Pop a messagebox indicating the click. + ::MessageBox(hwndOwner, L"Command link clicked", L"Click!", 0); + break; + case SFI_HIDECONTROLS_LINK: + _pCredProvCredentialEvents->BeginFieldUpdates(); + cpfsShow = _fShowControls ? CPFS_DISPLAY_IN_SELECTED_TILE : CPFS_HIDDEN; + _pCredProvCredentialEvents->SetFieldState(nullptr, SFI_FULLNAME_TEXT, cpfsShow); + _pCredProvCredentialEvents->SetFieldState(nullptr, SFI_DISPLAYNAME_TEXT, cpfsShow); + _pCredProvCredentialEvents->SetFieldState(nullptr, SFI_LOGONSTATUS_TEXT, cpfsShow); + _pCredProvCredentialEvents->SetFieldState(nullptr, SFI_CHECKBOX, cpfsShow); + _pCredProvCredentialEvents->SetFieldState(nullptr, SFI_EDIT_TEXT, cpfsShow); + _pCredProvCredentialEvents->SetFieldState(nullptr, SFI_COMBOBOX, cpfsShow); + _pCredProvCredentialEvents->SetFieldString(nullptr, SFI_HIDECONTROLS_LINK, _fShowControls? L"Hide additional controls" : L"Show additional controls"); + _pCredProvCredentialEvents->EndFieldUpdates(); + _fShowControls = !_fShowControls; + break; + default: + hr = E_INVALIDARG; + } + + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Collect the username and password into a serialized credential for the correct usage scenario +// (logon/unlock is what's demonstrated in this sample). LogonUI then passes these credentials +// back to the system to log on. +HRESULT CSampleCredential::GetSerialization(_Out_ CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpgsr, + _Out_ CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs, + _Outptr_result_maybenull_ PWSTR *ppwszOptionalStatusText, + _Out_ CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon) +{ + HRESULT hr = E_UNEXPECTED; + *pcpgsr = CPGSR_NO_CREDENTIAL_NOT_FINISHED; + *ppwszOptionalStatusText = nullptr; + *pcpsiOptionalStatusIcon = CPSI_NONE; + ZeroMemory(pcpcs, sizeof(*pcpcs)); + + // For local user, the domain and user name can be split from _pszQualifiedUserName (domain\username). + // CredPackAuthenticationBuffer() cannot be used because it won't work with unlock scenario. + if (_fIsLocalUser) + { + PWSTR pwzProtectedPassword; + hr = ProtectIfNecessaryAndCopyPassword(_rgFieldStrings[SFI_PASSWORD], _cpus, &pwzProtectedPassword); + if (SUCCEEDED(hr)) + { + PWSTR pszDomain; + PWSTR pszUsername; + hr = SplitDomainAndUsername(_pszQualifiedUserName, &pszDomain, &pszUsername); + if (SUCCEEDED(hr)) + { + KERB_INTERACTIVE_UNLOCK_LOGON kiul; + hr = KerbInteractiveUnlockLogonInit(pszDomain, pszUsername, pwzProtectedPassword, _cpus, &kiul); + if (SUCCEEDED(hr)) + { + // We use KERB_INTERACTIVE_UNLOCK_LOGON in both unlock and logon scenarios. It contains a + // KERB_INTERACTIVE_LOGON to hold the creds plus a LUID that is filled in for us by Winlogon + // as necessary. + hr = KerbInteractiveUnlockLogonPack(kiul, &pcpcs->rgbSerialization, &pcpcs->cbSerialization); + if (SUCCEEDED(hr)) + { + ULONG ulAuthPackage; + hr = RetrieveNegotiateAuthPackage(&ulAuthPackage); + if (SUCCEEDED(hr)) + { + pcpcs->ulAuthenticationPackage = ulAuthPackage; + pcpcs->clsidCredentialProvider = CLSID_CSample; + // At this point the credential has created the serialized credential used for logon + // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know + // that we have all the information we need and it should attempt to submit the + // serialized credential. + *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED; + } + } + } + CoTaskMemFree(pszDomain); + CoTaskMemFree(pszUsername); + } + CoTaskMemFree(pwzProtectedPassword); + } + } + else + { + DWORD dwAuthFlags = CRED_PACK_PROTECTED_CREDENTIALS | CRED_PACK_ID_PROVIDER_CREDENTIALS; + + // First get the size of the authentication buffer to allocate + if (!CredPackAuthenticationBuffer(dwAuthFlags, _pszQualifiedUserName, const_cast(_rgFieldStrings[SFI_PASSWORD]), nullptr, &pcpcs->cbSerialization) && + (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + pcpcs->rgbSerialization = static_cast(CoTaskMemAlloc(pcpcs->cbSerialization)); + if (pcpcs->rgbSerialization != nullptr) + { + hr = S_OK; + + // Retrieve the authentication buffer + if (CredPackAuthenticationBuffer(dwAuthFlags, _pszQualifiedUserName, const_cast(_rgFieldStrings[SFI_PASSWORD]), pcpcs->rgbSerialization, &pcpcs->cbSerialization)) + { + ULONG ulAuthPackage; + hr = RetrieveNegotiateAuthPackage(&ulAuthPackage); + if (SUCCEEDED(hr)) + { + pcpcs->ulAuthenticationPackage = ulAuthPackage; + pcpcs->clsidCredentialProvider = CLSID_CSample; + + // At this point the credential has created the serialized credential used for logon + // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know + // that we have all the information we need and it should attempt to submit the + // serialized credential. + *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED; + } + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + } + } + + if (FAILED(hr)) + { + CoTaskMemFree(pcpcs->rgbSerialization); + } + } + else + { + hr = E_OUTOFMEMORY; + } + } + } + return hr; +} + +struct REPORT_RESULT_STATUS_INFO +{ + NTSTATUS ntsStatus; + NTSTATUS ntsSubstatus; + PWSTR pwzMessage; + CREDENTIAL_PROVIDER_STATUS_ICON cpsi; +}; + +static const REPORT_RESULT_STATUS_INFO s_rgLogonStatusInfo[] = +{ + { STATUS_LOGON_FAILURE, STATUS_SUCCESS, L"Incorrect password or username.", CPSI_ERROR, }, + { STATUS_ACCOUNT_RESTRICTION, STATUS_ACCOUNT_DISABLED, L"The account is disabled.", CPSI_WARNING }, +}; + +// ReportResult is completely optional. Its purpose is to allow a credential to customize the string +// and the icon displayed in the case of a logon failure. For example, we have chosen to +// customize the error shown in the case of bad username/password and in the case of the account +// being disabled. +HRESULT CSampleCredential::ReportResult(NTSTATUS ntsStatus, + NTSTATUS ntsSubstatus, + _Outptr_result_maybenull_ PWSTR *ppwszOptionalStatusText, + _Out_ CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon) +{ + *ppwszOptionalStatusText = nullptr; + *pcpsiOptionalStatusIcon = CPSI_NONE; + + DWORD dwStatusInfo = (DWORD)-1; + + // Look for a match on status and substatus. + for (DWORD i = 0; i < ARRAYSIZE(s_rgLogonStatusInfo); i++) + { + if (s_rgLogonStatusInfo[i].ntsStatus == ntsStatus && s_rgLogonStatusInfo[i].ntsSubstatus == ntsSubstatus) + { + dwStatusInfo = i; + break; + } + } + + if ((DWORD)-1 != dwStatusInfo) + { + if (SUCCEEDED(SHStrDupW(s_rgLogonStatusInfo[dwStatusInfo].pwzMessage, ppwszOptionalStatusText))) + { + *pcpsiOptionalStatusIcon = s_rgLogonStatusInfo[dwStatusInfo].cpsi; + } + } + + // If we failed the logon, try to erase the password field. + if (FAILED(HRESULT_FROM_NT(ntsStatus))) + { + if (_pCredProvCredentialEvents) + { + _pCredProvCredentialEvents->SetFieldString(this, SFI_PASSWORD, L""); + } + } + + // Since nullptr is a valid value for *ppwszOptionalStatusText and *pcpsiOptionalStatusIcon + // this function can't fail. + return S_OK; +} + +// Gets the SID of the user corresponding to the credential. +HRESULT CSampleCredential::GetUserSid(_Outptr_result_nullonfailure_ PWSTR *ppszSid) +{ + *ppszSid = nullptr; + HRESULT hr = E_UNEXPECTED; + if (_pszUserSid != nullptr) + { + hr = SHStrDupW(_pszUserSid, ppszSid); + } + // Return S_FALSE with a null SID in ppszSid for the + // credential to be associated with an empty user tile. + + return hr; +} + +// GetFieldOptions to enable the password reveal button and touch keyboard auto-invoke in the password field. +HRESULT CSampleCredential::GetFieldOptions(DWORD dwFieldID, + _Out_ CREDENTIAL_PROVIDER_CREDENTIAL_FIELD_OPTIONS *pcpcfo) +{ + *pcpcfo = CPCFO_NONE; + + if (dwFieldID == SFI_PASSWORD) + { + *pcpcfo = CPCFO_ENABLE_PASSWORD_REVEAL; + } + else if (dwFieldID == SFI_TILEIMAGE) + { + *pcpcfo = CPCFO_ENABLE_TOUCH_KEYBOARD_AUTO_INVOKE; + } + + return S_OK; +} diff --git a/Samples/CredentialProvider/cpp/CSampleCredential.h b/Samples/CredentialProvider/cpp/CSampleCredential.h new file mode 100644 index 00000000..f898230d --- /dev/null +++ b/Samples/CredentialProvider/cpp/CSampleCredential.h @@ -0,0 +1,120 @@ +// +// 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. +// +// CSampleCredential is our implementation of ICredentialProviderCredential. +// ICredentialProviderCredential is what LogonUI uses to let a credential +// provider specify what a user tile looks like and then tell it what the +// user has entered into the tile. ICredentialProviderCredential is also +// responsible for packaging up the users credentials into a buffer that +// LogonUI then sends on to LSA. + +#pragma once + +#include +#include +#include +#include +#include "common.h" +#include "dll.h" +#include "resource.h" + +class CSampleCredential : public ICredentialProviderCredential2, ICredentialProviderCredentialWithFieldOptions +{ +public: + // IUnknown + IFACEMETHODIMP_(ULONG) AddRef() + { + return ++_cRef; + } + + IFACEMETHODIMP_(ULONG) Release() + { + long cRef = --_cRef; + if (!cRef) + { + delete this; + } + return cRef; + } + + IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) + { + static const QITAB qit[] = + { + QITABENT(CSampleCredential, ICredentialProviderCredential), // IID_ICredentialProviderCredential + QITABENT(CSampleCredential, ICredentialProviderCredential2), // IID_ICredentialProviderCredential2 + QITABENT(CSampleCredential, ICredentialProviderCredentialWithFieldOptions), //IID_ICredentialProviderCredentialWithFieldOptions + {0}, + }; + return QISearch(this, qit, riid, ppv); + } + public: + // ICredentialProviderCredential + IFACEMETHODIMP Advise(_In_ ICredentialProviderCredentialEvents *pcpce); + IFACEMETHODIMP UnAdvise(); + + IFACEMETHODIMP SetSelected(_Out_ BOOL *pbAutoLogon); + IFACEMETHODIMP SetDeselected(); + + IFACEMETHODIMP GetFieldState(DWORD dwFieldID, + _Out_ CREDENTIAL_PROVIDER_FIELD_STATE *pcpfs, + _Out_ CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *pcpfis); + + IFACEMETHODIMP GetStringValue(DWORD dwFieldID, _Outptr_result_nullonfailure_ PWSTR *ppwsz); + IFACEMETHODIMP GetBitmapValue(DWORD dwFieldID, _Outptr_result_nullonfailure_ HBITMAP *phbmp); + IFACEMETHODIMP GetCheckboxValue(DWORD dwFieldID, _Out_ BOOL *pbChecked, _Outptr_result_nullonfailure_ PWSTR *ppwszLabel); + IFACEMETHODIMP GetComboBoxValueCount(DWORD dwFieldID, _Out_ DWORD *pcItems, _Deref_out_range_(<, *pcItems) _Out_ DWORD *pdwSelectedItem); + IFACEMETHODIMP GetComboBoxValueAt(DWORD dwFieldID, DWORD dwItem, _Outptr_result_nullonfailure_ PWSTR *ppwszItem); + IFACEMETHODIMP GetSubmitButtonValue(DWORD dwFieldID, _Out_ DWORD *pdwAdjacentTo); + + IFACEMETHODIMP SetStringValue(DWORD dwFieldID, _In_ PCWSTR pwz); + IFACEMETHODIMP SetCheckboxValue(DWORD dwFieldID, BOOL bChecked); + IFACEMETHODIMP SetComboBoxSelectedValue(DWORD dwFieldID, DWORD dwSelectedItem); + IFACEMETHODIMP CommandLinkClicked(DWORD dwFieldID); + + IFACEMETHODIMP GetSerialization(_Out_ CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpgsr, + _Out_ CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs, + _Outptr_result_maybenull_ PWSTR *ppwszOptionalStatusText, + _Out_ CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon); + IFACEMETHODIMP ReportResult(NTSTATUS ntsStatus, + NTSTATUS ntsSubstatus, + _Outptr_result_maybenull_ PWSTR *ppwszOptionalStatusText, + _Out_ CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon); + + + // ICredentialProviderCredential2 + IFACEMETHODIMP GetUserSid(_Outptr_result_nullonfailure_ PWSTR *ppszSid); + + // ICredentialProviderCredentialWithFieldOptions + IFACEMETHODIMP GetFieldOptions(DWORD dwFieldID, + _Out_ CREDENTIAL_PROVIDER_CREDENTIAL_FIELD_OPTIONS *pcpcfo); + + public: + HRESULT Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + _In_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR const *rgcpfd, + _In_ FIELD_STATE_PAIR const *rgfsp, + _In_ ICredentialProviderUser *pcpUser); + CSampleCredential(); + + private: + + virtual ~CSampleCredential(); + long _cRef; + CREDENTIAL_PROVIDER_USAGE_SCENARIO _cpus; // The usage scenario for which we were enumerated. + CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR _rgCredProvFieldDescriptors[SFI_NUM_FIELDS]; // An array holding the type and name of each field in the tile. + FIELD_STATE_PAIR _rgFieldStatePairs[SFI_NUM_FIELDS]; // An array holding the state of each field in the tile. + PWSTR _rgFieldStrings[SFI_NUM_FIELDS]; // An array holding the string value of each field. This is different from the name of the field held in _rgCredProvFieldDescriptors. + PWSTR _pszUserSid; + PWSTR _pszQualifiedUserName; // The user name that's used to pack the authentication buffer + ICredentialProviderCredentialEvents2* _pCredProvCredentialEvents; // Used to update fields. + // CredentialEvents2 for Begin and EndFieldUpdates. + BOOL _fChecked; // Tracks the state of our checkbox. + DWORD _dwComboIndex; // Tracks the current index of our combobox. + bool _fShowControls; // Tracks the state of our show/hide controls link. + bool _fIsLocalUser; // If the cred prov is assosiating with a local user tile +}; diff --git a/Samples/CredentialProvider/cpp/CSampleProvider.cpp b/Samples/CredentialProvider/cpp/CSampleProvider.cpp new file mode 100644 index 00000000..d25ef1d4 --- /dev/null +++ b/Samples/CredentialProvider/cpp/CSampleProvider.cpp @@ -0,0 +1,279 @@ +// +// 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. +// +// CSampleProvider implements ICredentialProvider, which is the main +// interface that logonUI uses to decide which tiles to display. +// In this sample, we will display one tile that uses each of the nine +// available UI controls. + +#include +#include "CSampleProvider.h" +#include "CSampleCredential.h" +#include "guid.h" + +CSampleProvider::CSampleProvider(): + _cRef(1), + _pCredential(nullptr), + _pCredProviderUserArray(nullptr) +{ + DllAddRef(); +} + +CSampleProvider::~CSampleProvider() +{ + if (_pCredential != nullptr) + { + _pCredential->Release(); + _pCredential = nullptr; + } + if (_pCredProviderUserArray != nullptr) + { + _pCredProviderUserArray->Release(); + _pCredProviderUserArray = nullptr; + } + + DllRelease(); +} + +// SetUsageScenario is the provider's cue that it's going to be asked for tiles +// in a subsequent call. +HRESULT CSampleProvider::SetUsageScenario( + CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + DWORD /*dwFlags*/) +{ + HRESULT hr; + + // Decide which scenarios to support here. Returning E_NOTIMPL simply tells the caller + // that we're not designed for that scenario. + switch (cpus) + { + case CPUS_LOGON: + case CPUS_UNLOCK_WORKSTATION: + // The reason why we need _fRecreateEnumeratedCredentials is because ICredentialProviderSetUserArray::SetUserArray() is called after ICredentialProvider::SetUsageScenario(), + // while we need the ICredentialProviderUserArray during enumeration in ICredentialProvider::GetCredentialCount() + _cpus = cpus; + _fRecreateEnumeratedCredentials = true; + hr = S_OK; + break; + + case CPUS_CHANGE_PASSWORD: + case CPUS_CREDUI: + hr = E_NOTIMPL; + break; + + default: + hr = E_INVALIDARG; + break; + } + + return hr; +} + +// SetSerialization takes the kind of buffer that you would normally return to LogonUI for +// an authentication attempt. It's the opposite of ICredentialProviderCredential::GetSerialization. +// GetSerialization is implement by a credential and serializes that credential. Instead, +// SetSerialization takes the serialization and uses it to create a tile. +// +// SetSerialization is called for two main scenarios. The first scenario is in the credui case +// where it is prepopulating a tile with credentials that the user chose to store in the OS. +// The second situation is in a remote logon case where the remote client may wish to +// prepopulate a tile with a username, or in some cases, completely populate the tile and +// use it to logon without showing any UI. +// +// If you wish to see an example of SetSerialization, please see either the SampleCredentialProvider +// sample or the SampleCredUICredentialProvider sample. [The logonUI team says, "The original sample that +// this was built on top of didn't have SetSerialization. And when we decided SetSerialization was +// important enough to have in the sample, it ended up being a non-trivial amount of work to integrate +// it into the main sample. We felt it was more important to get these samples out to you quickly than to +// hold them in order to do the work to integrate the SetSerialization changes from SampleCredentialProvider +// into this sample.] +HRESULT CSampleProvider::SetSerialization( + _In_ CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION const * /*pcpcs*/) +{ + return E_NOTIMPL; +} + +// Called by LogonUI to give you a callback. Providers often use the callback if they +// some event would cause them to need to change the set of tiles that they enumerated. +HRESULT CSampleProvider::Advise( + _In_ ICredentialProviderEvents * /*pcpe*/, + _In_ UINT_PTR /*upAdviseContext*/) +{ + return E_NOTIMPL; +} + +// Called by LogonUI when the ICredentialProviderEvents callback is no longer valid. +HRESULT CSampleProvider::UnAdvise() +{ + return E_NOTIMPL; +} + +// Called by LogonUI to determine the number of fields in your tiles. This +// does mean that all your tiles must have the same number of fields. +// This number must include both visible and invisible fields. If you want a tile +// to have different fields from the other tiles you enumerate for a given usage +// scenario you must include them all in this count and then hide/show them as desired +// using the field descriptors. +HRESULT CSampleProvider::GetFieldDescriptorCount( + _Out_ DWORD *pdwCount) +{ + *pdwCount = SFI_NUM_FIELDS; + return S_OK; +} + +// Gets the field descriptor for a particular field. +HRESULT CSampleProvider::GetFieldDescriptorAt( + DWORD dwIndex, + _Outptr_result_nullonfailure_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd) +{ + HRESULT hr; + *ppcpfd = nullptr; + + // Verify dwIndex is a valid field. + if ((dwIndex < SFI_NUM_FIELDS) && ppcpfd) + { + hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpfd); + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +// Sets pdwCount to the number of tiles that we wish to show at this time. +// Sets pdwDefault to the index of the tile which should be used as the default. +// The default tile is the tile which will be shown in the zoomed view by default. If +// more than one provider specifies a default the last used cred prov gets to pick +// the default. If *pbAutoLogonWithDefault is TRUE, LogonUI will immediately call +// GetSerialization on the credential you've specified as the default and will submit +// that credential for authentication without showing any further UI. +HRESULT CSampleProvider::GetCredentialCount( + _Out_ DWORD *pdwCount, + _Out_ DWORD *pdwDefault, + _Out_ BOOL *pbAutoLogonWithDefault) +{ + *pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT; + *pbAutoLogonWithDefault = FALSE; + + if (_fRecreateEnumeratedCredentials) + { + _fRecreateEnumeratedCredentials = false; + _ReleaseEnumeratedCredentials(); + _CreateEnumeratedCredentials(); + } + + *pdwCount = 1; + + return S_OK; +} + +// Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate +// the tiles. +HRESULT CSampleProvider::GetCredentialAt( + DWORD dwIndex, + _Outptr_result_nullonfailure_ ICredentialProviderCredential **ppcpc) +{ + HRESULT hr = E_INVALIDARG; + *ppcpc = nullptr; + + if ((dwIndex == 0) && ppcpc) + { + hr = _pCredential->QueryInterface(IID_PPV_ARGS(ppcpc)); + } + return hr; +} + +// This function will be called by LogonUI after SetUsageScenario succeeds. +// Sets the User Array with the list of users to be enumerated on the logon screen. +HRESULT CSampleProvider::SetUserArray(_In_ ICredentialProviderUserArray *users) +{ + if (_pCredProviderUserArray) + { + _pCredProviderUserArray->Release(); + } + _pCredProviderUserArray = users; + _pCredProviderUserArray->AddRef(); + return S_OK; +} + +void CSampleProvider::_CreateEnumeratedCredentials() +{ + switch (_cpus) + { + case CPUS_LOGON: + case CPUS_UNLOCK_WORKSTATION: + { + _EnumerateCredentials(); + break; + } + default: + break; + } +} + +void CSampleProvider::_ReleaseEnumeratedCredentials() +{ + if (_pCredential != nullptr) + { + _pCredential->Release(); + _pCredential = nullptr; + } +} + +HRESULT CSampleProvider::_EnumerateCredentials() +{ + HRESULT hr = E_UNEXPECTED; + if (_pCredProviderUserArray != nullptr) + { + DWORD dwUserCount; + _pCredProviderUserArray->GetCount(&dwUserCount); + if (dwUserCount > 0) + { + ICredentialProviderUser *pCredUser; + hr = _pCredProviderUserArray->GetAt(0, &pCredUser); + if (SUCCEEDED(hr)) + { + _pCredential = new(std::nothrow) CSampleCredential(); + if (_pCredential != nullptr) + { + hr = _pCredential->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStatePairs, pCredUser); + if (FAILED(hr)) + { + _pCredential->Release(); + _pCredential = nullptr; + } + } + else + { + hr = E_OUTOFMEMORY; + } + pCredUser->Release(); + } + } + } + return hr; +} + +// Boilerplate code to create our provider. +HRESULT CSample_CreateInstance(_In_ REFIID riid, _Outptr_ void **ppv) +{ + HRESULT hr; + CSampleProvider *pProvider = new(std::nothrow) CSampleProvider(); + if (pProvider) + { + hr = pProvider->QueryInterface(riid, ppv); + pProvider->Release(); + } + else + { + hr = E_OUTOFMEMORY; + } + return hr; +} diff --git a/Samples/CredentialProvider/cpp/CSampleProvider.h b/Samples/CredentialProvider/cpp/CSampleProvider.h new file mode 100644 index 00000000..4b93a70f --- /dev/null +++ b/Samples/CredentialProvider/cpp/CSampleProvider.h @@ -0,0 +1,85 @@ +// +// 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 "helpers.h" +#include +#include +#include + +#include "CSampleCredential.h" + +class CSampleProvider : public ICredentialProvider, + public ICredentialProviderSetUserArray +{ + public: + // IUnknown + IFACEMETHODIMP_(ULONG) AddRef() + { + return ++_cRef; + } + + IFACEMETHODIMP_(ULONG) Release() + { + long cRef = --_cRef; + if (!cRef) + { + delete this; + } + return cRef; + } + + IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) + { + static const QITAB qit[] = + { + QITABENT(CSampleProvider, ICredentialProvider), // IID_ICredentialProvider + QITABENT(CSampleProvider, ICredentialProviderSetUserArray), // IID_ICredentialProviderSetUserArray + {0}, + }; + return QISearch(this, qit, riid, ppv); + } + + public: + IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD dwFlags); + IFACEMETHODIMP SetSerialization(_In_ CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION const *pcpcs); + + IFACEMETHODIMP Advise(_In_ ICredentialProviderEvents *pcpe, _In_ UINT_PTR upAdviseContext); + IFACEMETHODIMP UnAdvise(); + + IFACEMETHODIMP GetFieldDescriptorCount(_Out_ DWORD *pdwCount); + IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex, _Outptr_result_nullonfailure_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd); + + IFACEMETHODIMP GetCredentialCount(_Out_ DWORD *pdwCount, + _Out_ DWORD *pdwDefault, + _Out_ BOOL *pbAutoLogonWithDefault); + IFACEMETHODIMP GetCredentialAt(DWORD dwIndex, + _Outptr_result_nullonfailure_ ICredentialProviderCredential **ppcpc); + + IFACEMETHODIMP SetUserArray(_In_ ICredentialProviderUserArray *users); + + friend HRESULT CSample_CreateInstance(_In_ REFIID riid, _Outptr_ void** ppv); + + protected: + CSampleProvider(); + __override ~CSampleProvider(); + + private: + void _ReleaseEnumeratedCredentials(); + void _CreateEnumeratedCredentials(); + HRESULT _EnumerateEmpty(); + HRESULT _EnumerateCredentials(); + HRESULT _EnumerateEmptyTileCredential(); +private: + long _cRef; // Used for reference counting. + CSampleCredential *_pCredential; // SampleV2Credential + bool _fRecreateEnumeratedCredentials; + CREDENTIAL_PROVIDER_USAGE_SCENARIO _cpus; + ICredentialProviderUserArray *_pCredProviderUserArray; + +}; diff --git a/Samples/CredentialProvider/cpp/Dll.cpp b/Samples/CredentialProvider/cpp/Dll.cpp new file mode 100644 index 00000000..eb24f83c --- /dev/null +++ b/Samples/CredentialProvider/cpp/Dll.cpp @@ -0,0 +1,151 @@ +// +// 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. +// +// Standard dll required functions and class factory implementation. + +#include +#include +#include "Dll.h" +#include "helpers.h" + +static long g_cRef = 0; // global dll reference count +HINSTANCE g_hinst = NULL; // global dll hinstance + +extern HRESULT CSample_CreateInstance(__in REFIID riid, __deref_out void** ppv); +EXTERN_C GUID CLSID_CSample; + +class CClassFactory : public IClassFactory +{ +public: + CClassFactory() : _cRef(1) + { + } + + // IUnknown + IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void **ppv) + { + static const QITAB qit[] = + { + QITABENT(CClassFactory, IClassFactory), + { 0 }, + }; + return QISearch(this, qit, riid, ppv); + } + + IFACEMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&_cRef); + } + + IFACEMETHODIMP_(ULONG) Release() + { + long cRef = InterlockedDecrement(&_cRef); + if (!cRef) + delete this; + return cRef; + } + + // IClassFactory + IFACEMETHODIMP CreateInstance(__in IUnknown* pUnkOuter, __in REFIID riid, __deref_out void **ppv) + { + HRESULT hr; + if (!pUnkOuter) + { + hr = CSample_CreateInstance(riid, ppv); + } + else + { + *ppv = NULL; + hr = CLASS_E_NOAGGREGATION; + } + return hr; + } + + IFACEMETHODIMP LockServer(__in BOOL bLock) + { + if (bLock) + { + DllAddRef(); + } + else + { + DllRelease(); + } + return S_OK; + } + +private: + ~CClassFactory() + { + } + long _cRef; +}; + +HRESULT CClassFactory_CreateInstance(__in REFCLSID rclsid, __in REFIID riid, __deref_out void **ppv) +{ + *ppv = NULL; + + HRESULT hr; + + if (CLSID_CSample == rclsid) + { + CClassFactory* pcf = new CClassFactory(); + if (pcf) + { + hr = pcf->QueryInterface(riid, ppv); + pcf->Release(); + } + else + { + hr = E_OUTOFMEMORY; + } + } + else + { + hr = CLASS_E_CLASSNOTAVAILABLE; + } + return hr; +} + +void DllAddRef() +{ + InterlockedIncrement(&g_cRef); +} + +void DllRelease() +{ + InterlockedDecrement(&g_cRef); +} + +STDAPI DllCanUnloadNow() +{ + return (g_cRef > 0) ? S_FALSE : S_OK; +} + +STDAPI DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out void** ppv) +{ + return CClassFactory_CreateInstance(rclsid, riid, ppv); +} + +STDAPI_(BOOL) DllMain(__in HINSTANCE hinstDll, __in DWORD dwReason, __in void *) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDll); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + + g_hinst = hinstDll; + return TRUE; +} + diff --git a/Samples/CredentialProvider/cpp/Dll.h b/Samples/CredentialProvider/cpp/Dll.h new file mode 100644 index 00000000..a8efaf62 --- /dev/null +++ b/Samples/CredentialProvider/cpp/Dll.h @@ -0,0 +1,18 @@ +// +// 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 + +// global dll hinstance +extern HINSTANCE g_hinst; +#define HINST_THISDLL g_hinst + +void DllAddRef(); +void DllRelease(); diff --git a/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.sln b/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.sln new file mode 100644 index 00000000..f0cbe48b --- /dev/null +++ b/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleV2CredentialProvider", "SampleV2CredentialProvider.vcxproj", "{98E74D71-5237-41FA-8D36-206C0D110626}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {98E74D71-5237-41FA-8D36-206C0D110626}.Debug|Win32.ActiveCfg = Debug|Win32 + {98E74D71-5237-41FA-8D36-206C0D110626}.Debug|Win32.Build.0 = Debug|Win32 + {98E74D71-5237-41FA-8D36-206C0D110626}.Debug|x64.ActiveCfg = Debug|x64 + {98E74D71-5237-41FA-8D36-206C0D110626}.Debug|x64.Build.0 = Debug|x64 + {98E74D71-5237-41FA-8D36-206C0D110626}.Release|Win32.ActiveCfg = Release|Win32 + {98E74D71-5237-41FA-8D36-206C0D110626}.Release|Win32.Build.0 = Release|Win32 + {98E74D71-5237-41FA-8D36-206C0D110626}.Release|x64.ActiveCfg = Release|x64 + {98E74D71-5237-41FA-8D36-206C0D110626}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj b/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj new file mode 100644 index 00000000..2738e356 --- /dev/null +++ b/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj @@ -0,0 +1,183 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {98E74D71-5237-41FA-8D36-206C0D110626} + Win32Proj + SampleV2CredentialProvider + + + + DynamicLibrary + true + v110 + Unicode + + + DynamicLibrary + true + v110 + Unicode + + + DynamicLibrary + false + v110 + true + Unicode + + + DynamicLibrary + false + v110 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level4 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLEV2CREDENTIALPROVIDER_EXPORTS;%(PreprocessorDefinitions) + false + true + + + Windows + true + Credui.lib;Shlwapi.lib;Secur32.lib;%(AdditionalDependencies) + samplev2credentialprovider.def + + + + + NotUsing + Level4 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLEV2CREDENTIALPROVIDER_EXPORTS;%(PreprocessorDefinitions) + false + + + Windows + true + Credui.lib;Shlwapi.lib;Secur32.lib;%(AdditionalDependencies) + samplev2credentialprovider.def + + + + + Level4 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLEV2CREDENTIALPROVIDER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + Credui.lib;Shlwapi.lib;Secur32.lib;%(AdditionalDependencies) + samplev2credentialprovider.def + + + + + Level4 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLEV2CREDENTIALPROVIDER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + Credui.lib;Shlwapi.lib;Secur32.lib;%(AdditionalDependencies) + samplev2credentialprovider.def + + + + + + \ No newline at end of file diff --git a/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj.filters b/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj.filters new file mode 100644 index 00000000..9b27343e --- /dev/null +++ b/Samples/CredentialProvider/cpp/SampleV2CredentialProvider.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;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 + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/Samples/CredentialProvider/cpp/Unregister.reg b/Samples/CredentialProvider/cpp/Unregister.reg new file mode 100644 index 0000000000000000000000000000000000000000..bcf1355ad0c107405ba20efc9b5e0250a4684386 GIT binary patch literal 362 zcmY+A;YtEQ6h_Z)p?B~FRw7gCXGoEh6&8s!B2%li5WBEu5z?zyXSRrB7-qlk-1+9- z{ra3xP?A&e#)>v$7Ch>$c%kN9=U7^(Ds`J%c`Yr}rMgFlUDpn+X5W!<%9*#O%sJ6a8`Hj7)tny)wUI>6=0NzrSF@+KSpPO8Is-!KAhB(=SbF zQT@|vx|{Che>C#!1Xs>>t~Y05?#n6_wMMc Oxi!&*J|E1Q|MCr;z&{EA literal 0 HcmV?d00001 diff --git a/Samples/CredentialProvider/cpp/common.h b/Samples/CredentialProvider/cpp/common.h new file mode 100644 index 00000000..dfafe0cc --- /dev/null +++ b/Samples/CredentialProvider/cpp/common.h @@ -0,0 +1,95 @@ +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This file contains some global variables that describe what our +// sample tile looks like. For example, it defines what fields a tile has +// and which fields show in which states of LogonUI. This sample illustrates +// the use of each UI field type. + +#pragma once +#include "helpers.h" + +// The indexes of each of the fields in our credential provider's tiles. Note that we're +// using each of the nine available field types here. +enum SAMPLE_FIELD_ID +{ + SFI_TILEIMAGE = 0, + SFI_LABEL = 1, + SFI_LARGE_TEXT = 2, + SFI_PASSWORD = 3, + SFI_SUBMIT_BUTTON = 4, + SFI_LAUNCHWINDOW_LINK = 5, + SFI_HIDECONTROLS_LINK = 6, + SFI_FULLNAME_TEXT = 7, + SFI_DISPLAYNAME_TEXT = 8, + SFI_LOGONSTATUS_TEXT = 9, + SFI_CHECKBOX = 10, + SFI_EDIT_TEXT = 11, + SFI_COMBOBOX = 12, + SFI_NUM_FIELDS = 13, // Note: if new fields are added, keep NUM_FIELDS last. This is used as a count of the number of fields +}; + +// The first value indicates when the tile is displayed (selected, not selected) +// the second indicates things like whether the field is enabled, whether it has key focus, etc. +struct FIELD_STATE_PAIR +{ + CREDENTIAL_PROVIDER_FIELD_STATE cpfs; + CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE cpfis; +}; + +// These two arrays are seperate because a credential provider might +// want to set up a credential with various combinations of field state pairs +// and field descriptors. + +// The field state value indicates whether the field is displayed +// in the selected tile, the deselected tile, or both. +// The Field interactive state indicates when +static const FIELD_STATE_PAIR s_rgFieldStatePairs[] = +{ + { CPFS_DISPLAY_IN_BOTH, CPFIS_NONE }, // SFI_TILEIMAGE + { CPFS_HIDDEN, CPFIS_NONE }, // SFI_LABEL + { CPFS_DISPLAY_IN_BOTH, CPFIS_NONE }, // SFI_LARGE_TEXT + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_FOCUSED }, // SFI_PASSWORD + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_SUBMIT_BUTTON + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_LAUNCHWINDOW_LINK + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_HIDECONTROLS_LINK + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_FULLNAME_TEXT + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_DISPLAYNAME_TEXT + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_LOGONSTATUS_TEXT + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_CHECKBOX + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_EDIT_TEXT + { CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE }, // SFI_COMBOBOX +}; + +// Field descriptors for unlock and logon. +// The first field is the index of the field. +// The second is the type of the field. +// The third is the name of the field, NOT the value which will appear in the field. +static const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR s_rgCredProvFieldDescriptors[] = +{ + { SFI_TILEIMAGE, CPFT_TILE_IMAGE, L"Image", CPFG_CREDENTIAL_PROVIDER_LOGO }, + { SFI_LABEL, CPFT_SMALL_TEXT, L"Tooltip", CPFG_CREDENTIAL_PROVIDER_LABEL }, + { SFI_LARGE_TEXT, CPFT_LARGE_TEXT, L"Sample Credential Provider" }, + { SFI_PASSWORD, CPFT_PASSWORD_TEXT, L"Password text" }, + { SFI_SUBMIT_BUTTON, CPFT_SUBMIT_BUTTON, L"Submit" }, + { SFI_LAUNCHWINDOW_LINK, CPFT_COMMAND_LINK, L"Launch helper window" }, + { SFI_HIDECONTROLS_LINK, CPFT_COMMAND_LINK, L"Hide additional controls" }, + { SFI_FULLNAME_TEXT, CPFT_SMALL_TEXT, L"Full name: " }, + { SFI_DISPLAYNAME_TEXT, CPFT_SMALL_TEXT, L"Display name: " }, + { SFI_LOGONSTATUS_TEXT, CPFT_SMALL_TEXT, L"Logon status: " }, + { SFI_CHECKBOX, CPFT_CHECKBOX, L"Checkbox" }, + { SFI_EDIT_TEXT, CPFT_EDIT_TEXT, L"Edit text" }, + { SFI_COMBOBOX, CPFT_COMBOBOX, L"Combobox" }, +}; + +static const PWSTR s_rgComboBoxStrings[] = +{ + L"First", + L"Second", + L"Third", +}; diff --git a/Samples/CredentialProvider/cpp/guid.cpp b/Samples/CredentialProvider/cpp/guid.cpp new file mode 100644 index 00000000..0d656ad5 --- /dev/null +++ b/Samples/CredentialProvider/cpp/guid.cpp @@ -0,0 +1,11 @@ +// +// 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 +#include "guid.h" diff --git a/Samples/CredentialProvider/cpp/guid.h b/Samples/CredentialProvider/cpp/guid.h new file mode 100644 index 00000000..c78ee11f --- /dev/null +++ b/Samples/CredentialProvider/cpp/guid.h @@ -0,0 +1,11 @@ +// +// 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. +// + +// 5fd3d285-0dd9-4362-8855-e0abaacd4af6 +DEFINE_GUID(CLSID_CSample, 0x5fd3d285, 0x0dd9, 0x4362, 0x88, 0x55, 0xe0, 0xab, 0xaa, 0xcd, 0x4a, 0xf6); diff --git a/Samples/CredentialProvider/cpp/helpers.cpp b/Samples/CredentialProvider/cpp/helpers.cpp new file mode 100644 index 00000000..9f7dcc3f --- /dev/null +++ b/Samples/CredentialProvider/cpp/helpers.cpp @@ -0,0 +1,710 @@ +// +// 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. +// +// Helper functions for copying parameters and packaging the buffer +// for GetSerialization. + + +#include "helpers.h" +#include + +// +// Copies the field descriptor pointed to by rcpfd into a buffer allocated +// using CoTaskMemAlloc. Returns that buffer in ppcpfd. +// +HRESULT FieldDescriptorCoAllocCopy( + _In_ const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR &rcpfd, + _Outptr_result_nullonfailure_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd + ) +{ + HRESULT hr; + *ppcpfd = nullptr; + DWORD cbStruct = sizeof(**ppcpfd); + + CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *pcpfd = (CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR*)CoTaskMemAlloc(cbStruct); + if (pcpfd) + { + pcpfd->dwFieldID = rcpfd.dwFieldID; + pcpfd->cpft = rcpfd.cpft; + pcpfd->guidFieldType = rcpfd.guidFieldType; + + if (rcpfd.pszLabel) + { + hr = SHStrDupW(rcpfd.pszLabel, &pcpfd->pszLabel); + } + else + { + pcpfd->pszLabel = nullptr; + hr = S_OK; + } + } + else + { + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + *ppcpfd = pcpfd; + } + else + { + CoTaskMemFree(pcpfd); + } + + return hr; +} + +// +// Coppies rcpfd into the buffer pointed to by pcpfd. The caller is responsible for +// allocating pcpfd. This function uses CoTaskMemAlloc to allocate memory for +// pcpfd->pszLabel. +// +HRESULT FieldDescriptorCopy( + _In_ const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR &rcpfd, + _Out_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *pcpfd + ) +{ + HRESULT hr; + CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR cpfd; + + cpfd.dwFieldID = rcpfd.dwFieldID; + cpfd.cpft = rcpfd.cpft; + cpfd.guidFieldType = rcpfd.guidFieldType; + + if (rcpfd.pszLabel) + { + hr = SHStrDupW(rcpfd.pszLabel, &cpfd.pszLabel); + } + else + { + cpfd.pszLabel = nullptr; + hr = S_OK; + } + + if (SUCCEEDED(hr)) + { + *pcpfd = cpfd; + } + + return hr; +} + +// +// This function copies the length of pwz and the pointer pwz into the UNICODE_STRING structure +// This function is intended for serializing a credential in GetSerialization only. +// Note that this function just makes a copy of the string pointer. It DOES NOT ALLOCATE storage! +// Be very, very sure that this is what you want, because it probably isn't outside of the +// exact GetSerialization call where the sample uses it. +// +HRESULT UnicodeStringInitWithString( + _In_ PWSTR pwz, + _Out_ UNICODE_STRING *pus + ) +{ + HRESULT hr; + if (pwz) + { + size_t lenString = wcslen(pwz); + USHORT usCharCount; + hr = SizeTToUShort(lenString, &usCharCount); + if (SUCCEEDED(hr)) + { + USHORT usSize; + hr = SizeTToUShort(sizeof(wchar_t), &usSize); + if (SUCCEEDED(hr)) + { + hr = UShortMult(usCharCount, usSize, &(pus->Length)); // Explicitly NOT including NULL terminator + if (SUCCEEDED(hr)) + { + pus->MaximumLength = pus->Length; + pus->Buffer = pwz; + hr = S_OK; + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW); + } + } + } + } + else + { + hr = E_INVALIDARG; + } + return hr; +} + +// +// The following function is intended to be used ONLY with the Kerb*Pack functions. It does +// no bounds-checking because its callers have precise requirements and are written to respect +// its limitations. +// You can read more about the UNICODE_STRING type at: +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/unicode_string.asp +// +static void _UnicodeStringPackedUnicodeStringCopy( + __in const UNICODE_STRING& rus, + __in PWSTR pwzBuffer, + __out UNICODE_STRING *pus + ) +{ + pus->Length = rus.Length; + pus->MaximumLength = rus.Length; + pus->Buffer = pwzBuffer; + + CopyMemory(pus->Buffer, rus.Buffer, pus->Length); +} + +// +// Initialize the members of a KERB_INTERACTIVE_UNLOCK_LOGON with weak references to the +// passed-in strings. This is useful if you will later use KerbInteractiveUnlockLogonPack +// to serialize the structure. +// +// The password is stored in encrypted form for CPUS_LOGON and CPUS_UNLOCK_WORKSTATION +// because the system can accept encrypted credentials. It is not encrypted in CPUS_CREDUI +// because we cannot know whether our caller can accept encrypted credentials. +// +HRESULT KerbInteractiveUnlockLogonInit( + _In_ PWSTR pwzDomain, + _In_ PWSTR pwzUsername, + _In_ PWSTR pwzPassword, + _In_ CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + _Out_ KERB_INTERACTIVE_UNLOCK_LOGON *pkiul + ) +{ + KERB_INTERACTIVE_UNLOCK_LOGON kiul; + ZeroMemory(&kiul, sizeof(kiul)); + + KERB_INTERACTIVE_LOGON *pkil = &kiul.Logon; + + // Note: this method uses custom logic to pack a KERB_INTERACTIVE_UNLOCK_LOGON with a + // serialized credential. We could replace the calls to UnicodeStringInitWithString + // and KerbInteractiveUnlockLogonPack with a single cal to CredPackAuthenticationBuffer, + // but that API has a drawback: it returns a KERB_INTERACTIVE_UNLOCK_LOGON whose + // MessageType is always KerbInteractiveLogon. + // + // If we only handled CPUS_LOGON, this drawback would not be a problem. For + // CPUS_UNLOCK_WORKSTATION, we could cast the output buffer of CredPackAuthenticationBuffer + // to KERB_INTERACTIVE_UNLOCK_LOGON and modify the MessageType to KerbWorkstationUnlockLogon, + // but such a cast would be unsupported -- the output format of CredPackAuthenticationBuffer + // is not officially documented. + + // Initialize the UNICODE_STRINGS to share our username and password strings. + HRESULT hr = UnicodeStringInitWithString(pwzDomain, &pkil->LogonDomainName); + if (SUCCEEDED(hr)) + { + hr = UnicodeStringInitWithString(pwzUsername, &pkil->UserName); + if (SUCCEEDED(hr)) + { + hr = UnicodeStringInitWithString(pwzPassword, &pkil->Password); + if (SUCCEEDED(hr)) + { + // Set a MessageType based on the usage scenario. + switch (cpus) + { + case CPUS_UNLOCK_WORKSTATION: + pkil->MessageType = KerbWorkstationUnlockLogon; + hr = S_OK; + break; + + case CPUS_LOGON: + pkil->MessageType = KerbInteractiveLogon; + hr = S_OK; + break; + + case CPUS_CREDUI: + pkil->MessageType = (KERB_LOGON_SUBMIT_TYPE)0; // MessageType does not apply to CredUI + hr = S_OK; + break; + + default: + hr = E_FAIL; + break; + } + + if (SUCCEEDED(hr)) + { + // KERB_INTERACTIVE_UNLOCK_LOGON is just a series of structures. A + // flat copy will properly initialize the output parameter. + CopyMemory(pkiul, &kiul, sizeof(*pkiul)); + } + } + } + } + + return hr; +} + +// +// WinLogon and LSA consume "packed" KERB_INTERACTIVE_UNLOCK_LOGONs. In these, the PWSTR members of each +// UNICODE_STRING are not actually pointers but byte offsets into the overall buffer represented +// by the packed KERB_INTERACTIVE_UNLOCK_LOGON. For example: +// +// rkiulIn.Logon.LogonDomainName.Length = 14 -> Length is in bytes, not characters +// rkiulIn.Logon.LogonDomainName.Buffer = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON) -> LogonDomainName begins immediately +// after the KERB_... struct in the buffer +// rkiulIn.Logon.UserName.Length = 10 +// rkiulIn.Logon.UserName.Buffer = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON) + 14 -> UNICODE_STRINGS are NOT null-terminated +// +// rkiulIn.Logon.Password.Length = 16 +// rkiulIn.Logon.Password.Buffer = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON) + 14 + 10 +// +// THere's more information on this at: +// http://msdn.microsoft.com/msdnmag/issues/05/06/SecurityBriefs/#void +// + +HRESULT KerbInteractiveUnlockLogonPack( + _In_ const KERB_INTERACTIVE_UNLOCK_LOGON &rkiulIn, + _Outptr_result_bytebuffer_(*pcb) BYTE **prgb, + _Out_ DWORD *pcb + ) +{ + HRESULT hr; + + const KERB_INTERACTIVE_LOGON *pkilIn = &rkiulIn.Logon; + + // alloc space for struct plus extra for the three strings + DWORD cb = sizeof(rkiulIn) + + pkilIn->LogonDomainName.Length + + pkilIn->UserName.Length + + pkilIn->Password.Length; + + KERB_INTERACTIVE_UNLOCK_LOGON *pkiulOut = (KERB_INTERACTIVE_UNLOCK_LOGON*)CoTaskMemAlloc(cb); + if (pkiulOut) + { + ZeroMemory(&pkiulOut->LogonId, sizeof(pkiulOut->LogonId)); + + // + // point pbBuffer at the beginning of the extra space + // + BYTE *pbBuffer = (BYTE*)pkiulOut + sizeof(*pkiulOut); + + // + // set up the Logon structure within the KERB_INTERACTIVE_UNLOCK_LOGON + // + KERB_INTERACTIVE_LOGON *pkilOut = &pkiulOut->Logon; + + pkilOut->MessageType = pkilIn->MessageType; + + // + // copy each string, + // fix up appropriate buffer pointer to be offset, + // advance buffer pointer over copied characters in extra space + // + _UnicodeStringPackedUnicodeStringCopy(pkilIn->LogonDomainName, (PWSTR)pbBuffer, &pkilOut->LogonDomainName); + pkilOut->LogonDomainName.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkiulOut); + pbBuffer += pkilOut->LogonDomainName.Length; + + _UnicodeStringPackedUnicodeStringCopy(pkilIn->UserName, (PWSTR)pbBuffer, &pkilOut->UserName); + pkilOut->UserName.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkiulOut); + pbBuffer += pkilOut->UserName.Length; + + _UnicodeStringPackedUnicodeStringCopy(pkilIn->Password, (PWSTR)pbBuffer, &pkilOut->Password); + pkilOut->Password.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkiulOut); + + *prgb = (BYTE*)pkiulOut; + *pcb = cb; + + hr = S_OK; + } + else + { + hr = E_OUTOFMEMORY; + } + + return hr; +} + +// +// This function packs the string pszSourceString in pszDestinationString +// for use with LSA functions including LsaLookupAuthenticationPackage. +// +static HRESULT _LsaInitString( + __out PSTRING pszDestinationString, + __in PCSTR pszSourceString + ) +{ + size_t cchLength = strlen(pszSourceString); + USHORT usLength; + HRESULT hr = SizeTToUShort(cchLength, &usLength); + if (SUCCEEDED(hr)) + { + pszDestinationString->Buffer = (PCHAR)pszSourceString; + pszDestinationString->Length = usLength; + pszDestinationString->MaximumLength = pszDestinationString->Length+1; + hr = S_OK; + } + return hr; +} + +// +// Retrieves the 'negotiate' AuthPackage from the LSA. In this case, Kerberos +// For more information on auth packages see this msdn page: +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/msv1_0_lm20_logon.asp +// +HRESULT RetrieveNegotiateAuthPackage(_Out_ ULONG *pulAuthPackage) +{ + HRESULT hr; + HANDLE hLsa; + + NTSTATUS status = LsaConnectUntrusted(&hLsa); + if (SUCCEEDED(HRESULT_FROM_NT(status))) + { + ULONG ulAuthPackage; + LSA_STRING lsaszKerberosName; + _LsaInitString(&lsaszKerberosName, NEGOSSP_NAME_A); + + status = LsaLookupAuthenticationPackage(hLsa, &lsaszKerberosName, &ulAuthPackage); + if (SUCCEEDED(HRESULT_FROM_NT(status))) + { + *pulAuthPackage = ulAuthPackage; + hr = S_OK; + } + else + { + hr = HRESULT_FROM_NT(status); + } + LsaDeregisterLogonProcess(hLsa); + } + else + { + hr = HRESULT_FROM_NT(status); + } + + return hr; +} + +// +// Return a copy of pwzToProtect encrypted with the CredProtect API. +// +// pwzToProtect must not be NULL or the empty string. +// +static HRESULT _ProtectAndCopyString( + _In_ PCWSTR pwzToProtect, + _Outptr_result_nullonfailure_ PWSTR *ppwzProtected + ) +{ + *ppwzProtected = nullptr; + + // pwzToProtect is const, but CredProtect takes a non-const string. + // So, make a copy that we know isn't const. + PWSTR pwzToProtectCopy; + HRESULT hr = SHStrDupW(pwzToProtect, &pwzToProtectCopy); + if (SUCCEEDED(hr)) + { + // The first call to CredProtect determines the length of the encrypted string. + // Because we pass a NULL output buffer, we expect the call to fail. + // + // Note that the third parameter to CredProtect, the number of characters of pwzToProtectCopy + // to encrypt, must include the NULL terminator! + DWORD cchProtected = 0; + if (!CredProtectW(FALSE, pwzToProtectCopy, (DWORD)wcslen(pwzToProtectCopy)+1, nullptr, &cchProtected, nullptr)) + { + DWORD dwErr = GetLastError(); + + if ((ERROR_INSUFFICIENT_BUFFER == dwErr) && (0 < cchProtected)) + { + // Allocate a buffer long enough for the encrypted string. + PWSTR pwzProtected = (PWSTR)CoTaskMemAlloc(cchProtected * sizeof(wchar_t)); + if (pwzProtected) + { + // The second call to CredProtect actually encrypts the string. + if (CredProtectW(FALSE, pwzToProtectCopy, (DWORD)wcslen(pwzToProtectCopy)+1, pwzProtected, &cchProtected, nullptr)) + { + *ppwzProtected = pwzProtected; + hr = S_OK; + } + else + { + CoTaskMemFree(pwzProtected); + + dwErr = GetLastError(); + hr = HRESULT_FROM_WIN32(dwErr); + } + } + else + { + hr = E_OUTOFMEMORY; + } + } + else + { + hr = HRESULT_FROM_WIN32(dwErr); + } + } + else + { + hr = E_UNEXPECTED; + } + + CoTaskMemFree(pwzToProtectCopy); + } + + return hr; +} + +// +// If pwzPassword should be encrypted, return a copy encrypted with CredProtect. +// +// If not, just return a copy. +// +HRESULT ProtectIfNecessaryAndCopyPassword( + _In_ PCWSTR pwzPassword, + _In_ CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + _Outptr_result_nullonfailure_ PWSTR *ppwzProtectedPassword + ) +{ + *ppwzProtectedPassword = nullptr; + + HRESULT hr; + + // ProtectAndCopyString is intended for non-empty strings only. Empty passwords + // do not need to be encrypted. + if (pwzPassword && *pwzPassword) + { + // pwzPassword is const, but CredIsProtected takes a non-const string. + // So, ake a copy that we know isn't const. + PWSTR pwzPasswordCopy; + hr = SHStrDupW(pwzPassword, &pwzPasswordCopy); + if (SUCCEEDED(hr)) + { + bool bCredAlreadyEncrypted = false; + CRED_PROTECTION_TYPE protectionType; + + // If the password is already encrypted, we should not encrypt it again. + // An encrypted password may be received through SetSerialization in the + // CPUS_LOGON scenario during a Terminal Services connection, for instance. + if (CredIsProtectedW(pwzPasswordCopy, &protectionType)) + { + if (CredUnprotected != protectionType) + { + bCredAlreadyEncrypted = true; + } + } + + // Passwords should not be encrypted in the CPUS_CREDUI scenario. We + // cannot know if our caller expects or can handle an encryped password. + if (CPUS_CREDUI == cpus || bCredAlreadyEncrypted) + { + hr = SHStrDupW(pwzPasswordCopy, ppwzProtectedPassword); + } + else + { + hr = _ProtectAndCopyString(pwzPasswordCopy, ppwzProtectedPassword); + } + + CoTaskMemFree(pwzPasswordCopy); + } + } + else + { + hr = SHStrDupW(L"", ppwzProtectedPassword); + } + + return hr; +} + +// +// Unpack a KERB_INTERACTIVE_UNLOCK_LOGON *in place*. That is, reset the Buffers from being offsets to +// being real pointers. This means, of course, that passing the resultant struct across any sort of +// memory space boundary is not going to work -- repack it if necessary! +// +void KerbInteractiveUnlockLogonUnpackInPlace( + _Inout_updates_bytes_(cb) KERB_INTERACTIVE_UNLOCK_LOGON *pkiul, + DWORD cb + ) +{ + if (sizeof(*pkiul) <= cb) + { + KERB_INTERACTIVE_LOGON *pkil = &pkiul->Logon; + + // Sanity check: if the range described by each (Buffer + MaximumSize) falls within the total bytecount, + // we can be pretty confident that the Buffers are actually offsets and that this is a packed credential. + if (((ULONG_PTR)pkil->LogonDomainName.Buffer + pkil->LogonDomainName.MaximumLength <= cb) && + ((ULONG_PTR)pkil->UserName.Buffer + pkil->UserName.MaximumLength <= cb) && + ((ULONG_PTR)pkil->Password.Buffer + pkil->Password.MaximumLength <= cb)) + { + pkil->LogonDomainName.Buffer = pkil->LogonDomainName.Buffer + ? (PWSTR)((BYTE*)pkiul + (ULONG_PTR)pkil->LogonDomainName.Buffer) + : nullptr; + + pkil->UserName.Buffer = pkil->UserName.Buffer + ? (PWSTR)((BYTE*)pkiul + (ULONG_PTR)pkil->UserName.Buffer) + : nullptr; + + pkil->Password.Buffer = pkil->Password.Buffer + ? (PWSTR)((BYTE*)pkiul + (ULONG_PTR)pkil->Password.Buffer) + : nullptr; + } + } +} + +// +// Use the CredPackAuthenticationBuffer and CredUnpackAuthenticationBuffer to convert a 32 bit WOW +// cred blob into a 64 bit native blob by unpacking it and immediately repacking it. +// +HRESULT KerbInteractiveUnlockLogonRepackNative( + _In_reads_bytes_(cbWow) BYTE *rgbWow, + _In_ DWORD cbWow, + _Outptr_result_bytebuffer_(*pcbNative) BYTE **prgbNative, + _Out_ DWORD *pcbNative + ) +{ + HRESULT hr = E_OUTOFMEMORY; + PWSTR pszDomainUsername = nullptr; + DWORD cchDomainUsername = 0; + PWSTR pszPassword = nullptr; + DWORD cchPassword = 0; + + *prgbNative = nullptr; + *pcbNative = 0; + + // Unpack the 32 bit KERB structure + CredUnPackAuthenticationBufferW(CRED_PACK_WOW_BUFFER, rgbWow, cbWow, pszDomainUsername, &cchDomainUsername, nullptr, nullptr, pszPassword, &cchPassword); + if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) + { + pszDomainUsername = (PWSTR) LocalAlloc(0, cchDomainUsername * sizeof(wchar_t)); + if (pszDomainUsername) + { + pszPassword = (PWSTR) LocalAlloc(0, cchPassword * sizeof(wchar_t)); + if (pszPassword) + { + if (CredUnPackAuthenticationBufferW(CRED_PACK_WOW_BUFFER, rgbWow, cbWow, pszDomainUsername, &cchDomainUsername, nullptr, nullptr, pszPassword, &cchPassword)) + { + hr = S_OK; + } + else + { + hr = GetLastError(); + } + } + } + } + + // Repack native + if (SUCCEEDED(hr)) + { + hr = E_OUTOFMEMORY; + CredPackAuthenticationBufferW(0, pszDomainUsername, pszPassword, *prgbNative, pcbNative); + if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) + { + *prgbNative = (BYTE*) LocalAlloc(LMEM_ZEROINIT, *pcbNative); + if (*prgbNative) + { + if (CredPackAuthenticationBufferW(0, pszDomainUsername, pszPassword, *prgbNative, pcbNative)) + { + hr = S_OK; + } + else + { + LocalFree(*prgbNative); + } + } + } + } + + LocalFree(pszDomainUsername); + if (pszPassword) + { + SecureZeroMemory(pszPassword, cchPassword * sizeof(wchar_t)); + LocalFree(pszPassword); + } + return hr; +} + +// Concatonates pwszDomain and pwszUsername and places the result in *ppwszDomainUsername. +HRESULT DomainUsernameStringAlloc( + _In_ PCWSTR pwszDomain, + _In_ PCWSTR pwszUsername, + _Outptr_result_nullonfailure_ PWSTR *ppwszDomainUsername + ) +{ + HRESULT hr; + *ppwszDomainUsername = nullptr; + size_t cchDomain = wcslen(pwszDomain); + size_t cchUsername = wcslen(pwszUsername); + // Length of domain, 1 character for '\', length of Username, plus null terminator. + size_t cbLen = sizeof(wchar_t) * (cchDomain + 1 + cchUsername +1); + PWSTR pwszDest = (PWSTR)HeapAlloc(GetProcessHeap(), 0, cbLen); + if (pwszDest) + { + hr = StringCbPrintfW(pwszDest, cbLen, L"%s\\%s", pwszDomain, pwszUsername); + if (SUCCEEDED(hr)) + { + *ppwszDomainUsername = pwszDest; + } + else + { + HeapFree(GetProcessHeap(), 0, pwszDest); + } + } + else + { + hr = E_OUTOFMEMORY; + } + + return hr; +} + +HRESULT SplitDomainAndUsername(_In_ PCWSTR pszQualifiedUserName, _Outptr_result_nullonfailure_ PWSTR *ppszDomain, _Outptr_result_nullonfailure_ PWSTR *ppszUsername) +{ + HRESULT hr = E_UNEXPECTED; + *ppszDomain = nullptr; + *ppszUsername = nullptr; + PWSTR pszDomain; + PWSTR pszUsername; + const wchar_t *pchWhack = wcschr(pszQualifiedUserName, L'\\'); + const wchar_t *pchEnd = pszQualifiedUserName + wcslen(pszQualifiedUserName) - 1; + + if (pchWhack != nullptr) + { + const wchar_t *pchDomainBegin = pszQualifiedUserName; + const wchar_t *pchDomainEnd = pchWhack - 1; + const wchar_t *pchUsernameBegin = pchWhack + 1; + const wchar_t *pchUsernameEnd = pchEnd; + + size_t lenDomain = pchDomainEnd - pchDomainBegin + 1; // number of actual chars, NOT INCLUDING null terminated string + pszDomain = static_cast(CoTaskMemAlloc(sizeof(wchar_t) * (lenDomain + 1))); + if (pszDomain != nullptr) + { + hr = StringCchCopyN(pszDomain, lenDomain + 1, pchDomainBegin, lenDomain); + if (SUCCEEDED(hr)) + { + size_t lenUsername = pchUsernameEnd - pchUsernameBegin + 1; // number of actual chars, NOT INCLUDING null terminated string + pszUsername = static_cast(CoTaskMemAlloc(sizeof(wchar_t) * (lenUsername + 1))); + if (pszUsername != nullptr) + { + hr = StringCchCopyN(pszUsername, lenUsername + 1, pchUsernameBegin, lenUsername); + if (SUCCEEDED(hr)) + { + *ppszDomain = pszDomain; + *ppszUsername = pszUsername; + } + else + { + CoTaskMemFree(pszUsername); + } + } + else + { + hr = E_OUTOFMEMORY; + } + } + + if (FAILED(hr)) + { + CoTaskMemFree(pszDomain); + } + } + else + { + hr = E_OUTOFMEMORY; + } + } + return hr; +} \ No newline at end of file diff --git a/Samples/CredentialProvider/cpp/helpers.h b/Samples/CredentialProvider/cpp/helpers.h new file mode 100644 index 00000000..324ff072 --- /dev/null +++ b/Samples/CredentialProvider/cpp/helpers.h @@ -0,0 +1,101 @@ +// +// 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. +// +// Helper functions for copying parameters and packaging the buffer +// for GetSerialization. + +#pragma once + +#pragma warning(push) +#pragma warning(disable: 28251) +#include +#include +#pragma warning(pop) + +#define SECURITY_WIN32 +#include +#include + +#include +#include + +#pragma warning(push) +#pragma warning(disable: 4995) +#include +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable: 28301) +#include +#pragma warning(pop) + +//makes a copy of a field descriptor using CoTaskMemAlloc +HRESULT FieldDescriptorCoAllocCopy( + _In_ const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR &rcpfd, + _Outptr_result_nullonfailure_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd + ); + +//makes a copy of a field descriptor on the normal heap +HRESULT FieldDescriptorCopy( + _In_ const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR &rcpfd, + _Out_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *pcpfd + ); + +//creates a UNICODE_STRING from a NULL-terminated string +HRESULT UnicodeStringInitWithString( + _In_ PWSTR pwz, + _Out_ UNICODE_STRING *pus + ); + +//initializes a KERB_INTERACTIVE_UNLOCK_LOGON with weak references to the provided credentials +HRESULT KerbInteractiveUnlockLogonInit( + _In_ PWSTR pwzDomain, + _In_ PWSTR pwzUsername, + _In_ PWSTR pwzPassword, + _In_ CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + _Out_ KERB_INTERACTIVE_UNLOCK_LOGON *pkiul + ); + +//packages the credentials into the buffer that the system expects +HRESULT KerbInteractiveUnlockLogonPack( + _In_ const KERB_INTERACTIVE_UNLOCK_LOGON &rkiulIn, + _Outptr_result_bytebuffer_(*pcb) BYTE **prgb, + _Out_ DWORD *pcb + ); + +//get the authentication package that will be used for our logon attempt +HRESULT RetrieveNegotiateAuthPackage( + _Out_ ULONG *pulAuthPackage + ); + +//encrypt a password (if necessary) and copy it; if not, just copy it +HRESULT ProtectIfNecessaryAndCopyPassword( + _In_ PCWSTR pwzPassword, + _In_ CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, + _Outptr_result_nullonfailure_ PWSTR *ppwzProtectedPassword + ); + +HRESULT KerbInteractiveUnlockLogonRepackNative( + _In_reads_bytes_(cbWow) BYTE *rgbWow, + _In_ DWORD cbWow, + _Outptr_result_bytebuffer_(*pcbNative) BYTE **prgbNative, + _Out_ DWORD *pcbNative + ); + +void KerbInteractiveUnlockLogonUnpackInPlace( + _Inout_updates_bytes_(cb) KERB_INTERACTIVE_UNLOCK_LOGON *pkiul, + DWORD cb + ); + +HRESULT DomainUsernameStringAlloc( + _In_ PCWSTR pwszDomain, + _In_ PCWSTR pwszUsername, + _Outptr_result_nullonfailure_ PWSTR *ppwszDomainUsername + ); + +HRESULT SplitDomainAndUsername(_In_ PCWSTR pszQualifiedUserName, _Outptr_result_nullonfailure_ PWSTR *ppszDomain, _Outptr_result_nullonfailure_ PWSTR *ppszUsername); \ No newline at end of file diff --git a/Samples/CredentialProvider/cpp/register.reg b/Samples/CredentialProvider/cpp/register.reg new file mode 100644 index 0000000000000000000000000000000000000000..95141440f314ece8094ee35e0e3d7c5808b42063 GIT binary patch literal 926 zcmeH`TT8=05QWdP;D0E2Z;@7uJ_wemSZu8%Vi6-{ZBiSkiKG`1@vp1jB;t*}`6|n1 zGjnF=c4psRhf0+xR<1|QRa2lucj)F?sL&IdBhVBnN3Q7-yZ}v+GvpmLw8h%gM!Bzb zqEqf%X{4S8^3~xSsn6+yb#(?BDFi##g@)*ZQq#xh7~eVGb4`dCfqu^}!ow1af*dmN zpSeVMTB4nPpytgXSDD&fyBB|=PBZd9FC(t7GQ=v2^h{L~12^`e`yD+k(_N6k+6dLV8>?#;Cs{m#c*+gYEUcJLR{xsdJ# zbaOyAt;!ynt`7g}Sj$I5Z!$QrIUCa{<9t8hq7l+M)$*89Ki}826l$Txr literal 0 HcmV?d00001 diff --git a/Samples/CredentialProvider/cpp/resource.h b/Samples/CredentialProvider/cpp/resource.h new file mode 100644 index 00000000..f7015426 --- /dev/null +++ b/Samples/CredentialProvider/cpp/resource.h @@ -0,0 +1,10 @@ +// +// 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. +// + +#define IDB_TILE_IMAGE 101 diff --git a/Samples/CredentialProvider/cpp/resources.rc b/Samples/CredentialProvider/cpp/resources.rc new file mode 100644 index 00000000..ee51dd2a --- /dev/null +++ b/Samples/CredentialProvider/cpp/resources.rc @@ -0,0 +1,6 @@ +#include "Resource.h" + +// Bitmaps: +IDB_TILE_IMAGE BITMAP DISCARDABLE "tileimage.bmp" +END + diff --git a/Samples/CredentialProvider/cpp/samplev2credentialprovider.def b/Samples/CredentialProvider/cpp/samplev2credentialprovider.def new file mode 100644 index 00000000..68c8bf1b --- /dev/null +++ b/Samples/CredentialProvider/cpp/samplev2credentialprovider.def @@ -0,0 +1,5 @@ +LIBRARY SampleV2CredentialProvider.dll + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE diff --git a/Samples/CredentialProvider/cpp/tileimage.bmp b/Samples/CredentialProvider/cpp/tileimage.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d4b11ba053d63564ff8e58a86f34d0b211890c2e GIT binary patch literal 49206 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 Solution from the top menu after the sample has loaded. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio for Windows 8.1 (any SKU), or select the corresponding options from the Debug menu. You are presented with a list of options corresponding to the custom resources that this sample provides (which models an online forum): there is a single FORUMS object ("Contoso Forums"), multiple SECTIONS beneath that (for example, "Hobbies"), and multiple TOPICS beneath the SECTIONS (for example, "Snowboarding"). Choose a number 1-10 to edit the security of one of these resources, and use the Effective Access tab to verify whether certain users have access. + diff --git a/Samples/CustomResourceManager/cpp/CSecInfo.cpp b/Samples/CustomResourceManager/cpp/CSecInfo.cpp new file mode 100644 index 00000000..bde38739 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/CSecInfo.cpp @@ -0,0 +1,1089 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "CSecInfo.h" +#include "authz.h" +#include +#include "sddl.h" +#include +#include "utility.h" +#include + +CSecInfo::CSecInfo() : + m_cRef(0), + m_AccessTable(g_siForumsAccess), + m_AccessTableCount(ARRAYSIZE(g_siForumsAccess)), + m_DefaultAccess(0), // full control by default + m_defaultSecurityDescriptorSddl(L"O:WDG:BAD:AI(A;CIIO;FA;;;WD)(A;;FA;;;BA)" + L"S:AI(AU;SAFACIIO;FA;;;WD)"), + m_editingResource(0), + m_resources(0), + m_dwSIFlags(0), + m_bFailedToConstruct(false) +{ + HRESULT hr = S_OK; + PWSTR* allSDs; + PCWSTR noDaclOrSacl = L"O:WDG:BA"; + int parentIndex; + PSECURITY_DESCRIPTOR pSelfRelativeSD; + ULONG securityDescriptorSize = 0; + BOOL bResult; + + m_resources = (PRESOURCE*)LocalAlloc( + LPTR, + NUMBER_OF_RESOURCES * sizeof(PRESOURCE*)); + if ( !m_resources ) + { + m_bFailedToConstruct = true; + return; + } + + allSDs = (PWSTR *)LocalAlloc(LPTR, NUMBER_OF_RESOURCES * sizeof(PWSTR*)); + if ( !allSDs ) + { + m_bFailedToConstruct = true; + return; + } + + for ( int i = 0; i < NUMBER_OF_RESOURCES; i++ ) + { + hr = AllocAndCopyString(noDaclOrSacl, &allSDs[i]); + if ( !SUCCEEDED(hr) ) + { + m_bFailedToConstruct = true; + return; + } + } + + m_resources[CONTOSO_FORUMS] = new Resource(L"Contoso forums", FORUM, allSDs[CONTOSO_FORUMS], NONEXISTENT_OBJECT); + m_resources[SPORTS] = new Resource(L"Sports", SECTION, allSDs[SPORTS], CONTOSO_FORUMS); + m_resources[FAVORITE_TEAM] = new Resource(L"Favorite team", TOPIC, allSDs[FAVORITE_TEAM], SPORTS); + m_resources[UPCOMING_EVENTS] = new Resource(L"Upcoming events", TOPIC, allSDs[UPCOMING_EVENTS], SPORTS); + m_resources[MOVIES] = new Resource(L"Movies", SECTION, allSDs[MOVIES], CONTOSO_FORUMS); + m_resources[NEW_RELEASES] = new Resource(L"2012 releases", TOPIC, allSDs[NEW_RELEASES], MOVIES); + m_resources[CLASSICS] = new Resource(L"Classics", TOPIC, allSDs[CLASSICS], MOVIES); + m_resources[HOBBIES] = new Resource(L"Hobbies", SECTION, allSDs[HOBBIES], CONTOSO_FORUMS); + m_resources[LEARNING_TO_COOK] = new Resource(L"Learning to cook", TOPIC, allSDs[LEARNING_TO_COOK], HOBBIES); + m_resources[SNOWBOARDING] = new Resource(L"Snowboarding", TOPIC, allSDs[SNOWBOARDING], HOBBIES); + + // Associate parents with their children + for ( int i = 0; i < NUMBER_OF_RESOURCES; i++ ) + { + parentIndex = m_resources[i]->GetParentIndex(); + if ( parentIndex != NONEXISTENT_OBJECT ) + { + m_resources[parentIndex]->AddChild(i); + } + } + + m_objectTypeList.Level = ACCESS_OBJECT_GUID; + m_objectTypeList.Sbz = 0; + m_objectTypeList.ObjectType = nullptr; + + // Initialize to a sane value even if we won't be editing the grandparent + SetCurrentObject(0); + + bResult = ConvertStringSecurityDescriptorToSecurityDescriptor( + m_defaultSecurityDescriptorSddl, + SDDL_REVISION_1, + &pSelfRelativeSD, + &securityDescriptorSize + ); + if ( bResult == FALSE ) + { + wprintf(L"Error calling ConvertStringSecurityDescriptorToSecurityDescriptor" + L": %d\n", GetLastError()); + m_bFailedToConstruct = true; + return; + } + + // Call SetSecurity on the forums root so that + // everything gets an inherited DACL. + hr = SetSecurity(DACL_SECURITY_INFORMATION, pSelfRelativeSD); + LocalFree(pSelfRelativeSD); + if ( !SUCCEEDED(hr) ) + { + wprintf(L"Error calling SetSecurity: %d\n", GetLastError()); + m_bFailedToConstruct = true; + return; + } +} + +CSecInfo::~CSecInfo() +{ + if ( m_resources != nullptr ) + { + for ( int i = 0; i < NUMBER_OF_RESOURCES; i++ ) + { + delete m_resources[i]; + } + LocalFree(m_resources); + } + + assert(m_cRef == 0); +} + +/* IUnknown */ +IFACEMETHODIMP_(ULONG) +CSecInfo::AddRef(void) +{ + return ::InterlockedIncrement(&m_cRef); +} + +/* IUnknown */ +IFACEMETHODIMP_(ULONG) +CSecInfo::Release(void) +{ + return ::InterlockedDecrement(&m_cRef); +} + +/* IUnknown */ +IFACEMETHODIMP +CSecInfo::QueryInterface(_In_ REFIID riid, _Outptr_ void ** ppv) +{ + if ( !ARGUMENT_PRESENT(ppv) ) + { + return E_INVALIDARG; + } + + if (::IsEqualIID(riid, IID_IUnknown)) + { + *ppv = this; + } + else if(::IsEqualIID(riid, IID_ISecurityInformation)) + { + *ppv = static_cast(this); + } + else if(::IsEqualIID(riid, IID_ISecurityInformation3)) + { + *ppv = static_cast(this); + } + else if( ::IsEqualIID(riid, IID_IEffectivePermission2)) + { + *ppv = static_cast(this); + } + else if( ::IsEqualIID(riid, IID_ISecurityObjectTypeInfo)) + { + *ppv = static_cast(this); + } + else + { + *ppv = nullptr; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + +HRESULT CSecInfo::ConvertStringToAbsSD( + _In_ PWSTR stringSD, + _Outptr_ PSECURITY_DESCRIPTOR *ppSD) +{ + BOOL bResult = 0; + DWORD errorCode = 0; + HRESULT hr = S_OK; + PSECURITY_DESCRIPTOR pSelfRelativeSD; + ULONG securityDescriptorSize = 0; + + // Start by getting an SD from our string + bResult = ConvertStringSecurityDescriptorToSecurityDescriptor( + stringSD, + SDDL_REVISION_1, + &pSelfRelativeSD, + &securityDescriptorSize + ); + FailGracefullyGLE( + bResult, + L"ConvertStringSecurityDescriptorToSecurityDescriptor"); + + hr = ConvertSecurityDescriptor(pSelfRelativeSD, ppSD); +exit_gracefully: + return hr; +} + +HRESULT CSecInfo::OrderDacl(int childIndex, PACL *ppAcl) +{ + BOOL bResult; + HRESULT hr = S_OK; + DWORD errorCode = S_OK; + Resource *resourceToOrder; + PINHERITED_FROM pInheritArray; + PACL pOrderedAcl = nullptr; + ACL_SIZE_INFORMATION aclInformation; + ACL_SIZE_INFORMATION aclInformation2; + DWORD totalCount; + DWORD totalCount2; + DWORD dwSizeNeeded; + int parentIndex; + int grandparentIndex; + int numPasses; + LPVOID ace; + + if ( childIndex == 0 ) + { + // The base object (forums) can only have explicit ACEs since there's + // nothing above it (GetInheritSource would fail for the forums + // anyway because we return not impl) + return S_OK; + } + + if ( !ARGUMENT_PRESENT(*ppAcl) ) + { + return E_INVALIDARG; + } + + resourceToOrder = m_resources[childIndex]; + + // This call has to be made on the child, not the thing we're currently editing + hr = GetInheritSourceHelper( + childIndex, + DACL_SECURITY_INFORMATION, + *ppAcl, + &pInheritArray); + FailGracefully(hr, L"GetInheritSourceHelper"); + + bResult = GetAclInformation( + *ppAcl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount = aclInformation.AceCount; + dwSizeNeeded = aclInformation.AclBytesFree + aclInformation.AclBytesInUse; + pOrderedAcl = (PACL)LocalAlloc(LPTR, dwSizeNeeded); + if ( !pOrderedAcl ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + bResult = InitializeAcl( + pOrderedAcl, + dwSizeNeeded, + ACL_REVISION + ); + FailGracefullyGLE(bResult, L"InitializeAcl"); + + parentIndex = resourceToOrder->GetParentIndex(); + grandparentIndex = + parentIndex == NONEXISTENT_OBJECT + ? NONEXISTENT_OBJECT + : m_resources[parentIndex]->GetParentIndex(); + + // Do two passes for each set of ACEs: explicit, parent, grandparent. + // One pass is for deny ACEs, one is for allow. + // This gives us a total of 6 passes for TOPICs (because they have a + // grandparent), 4 passes for SECTIONs (because they only have a + // parent), and 2 passes for FORUMs. + numPasses = 2; + if ( parentIndex > -1 ) numPasses += 2; + if ( grandparentIndex > -1 ) numPasses += 2; + + for (int pass = 0; pass < numPasses; pass ++ ) + { + for ( DWORD aceIndex = 0; aceIndex < totalCount; aceIndex ++ ) + { + bResult = GetAce( + *ppAcl, + aceIndex, + &ace + ); + FailGracefullyGLE(bResult, L"GetAce"); + + BYTE aceType = ((PACE_HEADER)ace)->AceType; + if ( + // Pass 0: explicit deny ACEs + ( pass == 0 && + pInheritArray[aceIndex].GenerationGap == 0 && + aceType == ACCESS_DENIED_ACE_TYPE ) || + + // Pass 1: explicit allow ACEs + ( pass == 1 && + pInheritArray[aceIndex].GenerationGap == 0 && + IsAccessAllowedAce(aceType) ) || + + // Pass 2: inherited-from-parent deny ACEs + ( pass == 2 && + pInheritArray[aceIndex].GenerationGap == 1 && + aceType == ACCESS_DENIED_ACE_TYPE ) || + + // Pass 3: inherited-from-parent allow ACEs + ( pass == 3 && + pInheritArray[aceIndex].GenerationGap == 1 && + IsAccessAllowedAce(aceType) ) || + + // Pass 3: inherited-from-grandparent deny ACEs + ( pass == 4 && + pInheritArray[aceIndex].GenerationGap == 2 && + aceType == ACCESS_DENIED_ACE_TYPE ) || + + // Pass 3: inherited-from-grandparent allow ACEs + ( pass == 5 && + pInheritArray[aceIndex].GenerationGap == 2 && + IsAccessAllowedAce(aceType) ) + ) + { + // We COULD just use AddAce, because we're guaranteed not to + // overflow the ACL's size (since we allocated it to exactly + // the same size and we're going to add all of the ACEs) + hr = AddAceToAcl(ace, &pOrderedAcl, true); + FailGracefully(hr, L"AddAceToAcl"); + } + } + } + + bResult = GetAclInformation( + *ppAcl, + &aclInformation2, + sizeof(aclInformation2), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount2 = aclInformation2.AceCount; + + // Sanity check: ensure that we didn't leave out any ACEs + if ( totalCount != totalCount2 ) + { + wprintf(L"A different amount of ACEs exists in the ACL now. " + L"Before: %d after: %d\n", totalCount, totalCount2); + hr = E_FAIL; + goto exit_gracefully; + } + + // Sanity check: ensure that the ACLs are the same size + if ( aclInformation.AclBytesFree != aclInformation2.AclBytesFree || + aclInformation.AclBytesInUse != aclInformation2.AclBytesInUse ) + { + wprintf(L"Either AclBytesFree or AclBytesInUse doesn't match up\n"); + hr = E_FAIL; + goto exit_gracefully; + } + + // Now point the unordered ACL to the ordered one + LocalFree(*ppAcl); + *ppAcl = pOrderedAcl; + pOrderedAcl = nullptr; + +exit_gracefully: + LocalFree(pOrderedAcl); + return hr; +} + +// pSD represents the security descriptor of the parent +HRESULT CSecInfo::SetSecurityOfChildren( + int parentIndex, + SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR pSD) +{ + BOOL bResult = 0; + DWORD errorCode = 0; + HRESULT hr = S_OK; + BOOL bAclPresent = 0; + PACL acl = nullptr; + PACL pChildAcl = nullptr; + BOOL bAclDefaulted = 0; + Resource *parentResource = m_resources[parentIndex]; + std::list childIndices = parentResource->GetChildIndices(); + Resource *childResource; + PSECURITY_DESCRIPTOR childAbsoluteSD; + DWORD dwRevision; + SECURITY_DESCRIPTOR_CONTROL sdControl; + DWORD dwSizeNeeded = 0; + int childIndex; + PWSTR stringSD; + ULONG stringSDLen = 0; + std::list::iterator it; + + for(it = childIndices.begin(); it != childIndices.end(); ++it) + { + childIndex = *it; + childResource = m_resources[childIndex]; + + hr = ConvertStringToAbsSD(childResource->GetSD(), &childAbsoluteSD); + FailGracefully(hr, L"ConvertStringToAbsSD"); + + if ( IS_FLAG_SET(si, DACL_SECURITY_INFORMATION) ) + { + + // First of all, if the child has the protected bit set, + // then they aren't interested in inheriting anything. + bResult = GetSecurityDescriptorControl( + childAbsoluteSD, + &sdControl, + &dwRevision + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorControl"); + + // No need to set the security on the children if it's a protected DACL + if ( IS_FLAG_SET(sdControl, SE_DACL_PROTECTED) ) + { + return S_OK; + } + + // Get the DACL of the parent + bResult = GetSecurityDescriptorDacl( + pSD, + &bAclPresent, + &acl, + &bAclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + // If there was no supplied ACL, then there's nothing + // for the child to inherit + if ( !bAclPresent ) + { + return S_OK; + } + + // Now we know there's a DACL, but we don't know if there are + // any inheritable ACEs. + hr = GetSizeOfAllInheritableAces(acl, dwSizeNeeded); + FailGracefully(hr, L"GetSizeOfAllInheritableAces"); + + // At this point, we know that the parent has a DACL. + // We need to get the child's DACL too because + // we may need to delete or add entries + bResult = GetSecurityDescriptorDacl( + childAbsoluteSD, + &bAclPresent, + &pChildAcl, + &bAclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + if ( pChildAcl != nullptr ) + { + // Keep only the explicit ACEs. This way we don't need to do a + // differential thing and find out which inherited ACEs went + // away or which ones were added. We just wipe them all out + // and then add all the inheritable ACEs from the parent. + hr = RemoveAllInheritedAces(&pChildAcl); + FailGracefully(hr, L"RemoveAllInheritedAces"); + } + + // There are no inheritable ACEs, so we're done here. + if ( dwSizeNeeded == 0 ) + { + return S_OK; + } + + // At this point, we know that there is a parent DACL + // and that it contains inheritable entries. If the child's ACL + // is null, then we need to initialize it. + if ( pChildAcl == nullptr ) + { + // We know how much space we need, so we can allocate it. + // First though, align it to a DWORD (this is necessary) + dwSizeNeeded = (dwSizeNeeded + (sizeof(DWORD) - 1)) & 0xfffffffc; + + pChildAcl = (PACL)LocalAlloc(LPTR, dwSizeNeeded); + if ( pChildAcl == nullptr ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + bResult = InitializeAcl(pChildAcl, dwSizeNeeded, ACL_REVISION); + FailGracefullyGLE(bResult, L"InitializeAcl"); + } + + hr = AddInheritableAcesFromAcl(acl, &pChildAcl); + FailGracefully(hr, L"AddInheritableAcesFromAcl"); + + // Now, the ACL is fully formed, so set it on the child + hr = OrderDacl( + childIndex, + &pChildAcl + ); + FailGracefully(hr, L"OrderDacl"); + + bResult = SetSecurityDescriptorDacl( + childAbsoluteSD, + true, + pChildAcl, + false + ); + FailGracefullyGLE(bResult, L"SetSecurityDescriptorDacl"); + + bResult = SetSecurityDescriptorControl( + childAbsoluteSD, + SE_DACL_AUTO_INHERITED, + SE_DACL_AUTO_INHERITED + ); + FailGracefullyGLE(bResult, L"SetSecurityDescriptorControl"); + } + + // Finally, convert the SD back to a string + bResult = ConvertSecurityDescriptorToStringSecurityDescriptor( + childAbsoluteSD, + SDDL_REVISION_1, + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | + LABEL_SECURITY_INFORMATION | + ATTRIBUTE_SECURITY_INFORMATION | + SCOPE_SECURITY_INFORMATION, + &stringSD, + &stringSDLen + ); + FailGracefullyGLE( + bResult, + L"ConvertSecurityDescriptorToStringSecurityDescriptor"); + + childResource->FreeSD(); + childResource->SetSD(stringSD); + stringSD = nullptr; + + // Now, call SetSecurityOfChildren on the child + hr = SetSecurityOfChildren(childIndex, si, childAbsoluteSD); + FailGracefully(hr, L"SetSecurityOfChildren"); + } +exit_gracefully: + return hr; +} + +// ISecurityInformation3 +IFACEMETHODIMP +CSecInfo::GetFullResourceName(_Outptr_ LPWSTR *ppszResourceName) +{ + *ppszResourceName = m_resources[m_editingResource]->GetName(); + + return S_OK; +} +IFACEMETHODIMP +CSecInfo::OpenElevatedEditor(_In_ HWND hWnd, _In_ SI_PAGE_TYPE uPage) +{ + UNREFERENCED_PARAMETER(hWnd); + UNREFERENCED_PARAMETER(uPage); + return E_NOTIMPL; +} + +// IEffectivePermission2 +IFACEMETHODIMP CSecInfo::ComputeEffectivePermissionWithSecondarySecurity (THIS_ + _In_ PSID pSid, + _In_opt_ PSID pDeviceSid, + _In_ PCWSTR pszServerName, + _Inout_updates_(dwSecurityObjectCount) PSECURITY_OBJECT pSecurityObjects, + _In_ DWORD dwSecurityObjectCount, + _In_opt_ PTOKEN_GROUPS pUserGroups, + _When_(pUserGroups != nullptr && *pAuthzUserGroupsOperations != AUTHZ_SID_OPERATION_REPLACE_ALL, _In_reads_(pUserGroups->GroupCount)) + _In_opt_ PAUTHZ_SID_OPERATION pAuthzUserGroupsOperations, + _In_opt_ PTOKEN_GROUPS pDeviceGroups, + _When_(pDeviceGroups != nullptr && *pAuthzDeviceGroupsOperations != AUTHZ_SID_OPERATION_REPLACE_ALL, _In_reads_(pDeviceGroups->GroupCount)) + _In_opt_ PAUTHZ_SID_OPERATION pAuthzDeviceGroupsOperations, + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTES_INFORMATION pAuthzUserClaims, + _When_(pAuthzUserClaims != nullptr && *pAuthzUserClaimsOperations != AUTHZ_SECURITY_ATTRIBUTE_OPERATION_REPLACE_ALL, _In_reads_(pAuthzUserClaims->AttributeCount)) + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTE_OPERATION pAuthzUserClaimsOperations, + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTES_INFORMATION pAuthzDeviceClaims, + _When_(pAuthzDeviceClaims != nullptr && *pAuthzDeviceClaimsOperations != AUTHZ_SECURITY_ATTRIBUTE_OPERATION_REPLACE_ALL, _In_reads_(pAuthzDeviceClaims->AttributeCount)) + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTE_OPERATION pAuthzDeviceClaimsOperations, + _Inout_updates_(dwSecurityObjectCount) PEFFPERM_RESULT_LIST pEffpermResultLists) +{ + // The server name passed in should always be null + UNREFERENCED_PARAMETER(pszServerName); + + BOOL bResult; + DWORD errorCode = S_OK; + HRESULT hr = S_OK; + DWORD dwFlags = 0; + + // AuthZ context representing the client. + AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzUserContext = nullptr; + + // AuthZ context representing the device. + AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzDeviceContext = nullptr; + + // AuthZ context representing the combination of client and device. If no + // device SID is passed in to this function, then it only represents + // the user context. + AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzCompoundContext = nullptr; + + // Access request specifies the desired access mask, principal self sid, + // the object type list strucutre (if any). + AUTHZ_ACCESS_REQUEST request; + AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent = nullptr; + PSECURITY_DESCRIPTOR pSD; + PSECURITY_DESCRIPTOR *pOptionalSecurityDescriptorArray = nullptr; + DWORD dwOptionalSecurityDescriptorCount = 0; + AUTHZ_ACCESS_REPLY reply; + reply.Error = nullptr; + reply.GrantedAccessMask = nullptr; + bool needToFreeAccMask = true; + PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE phAccessCheckResults = nullptr; + AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager = nullptr; + + bool madeResourceManager = false; + LUID identifier; + + // There is no concept of shares or CAPs in this resource manager, + // so the only security object in pSecurityObjects will be + // the SD in question. The following checks aren't necessary when + // considering the sample code. + if ( dwSecurityObjectCount != 1 ) + { + wprintf(L"Unexpected effective permissions argument data: " + L"dwSecurityObjectCount==%d\n", dwSecurityObjectCount); + hr = E_FAIL; + goto exit_gracefully; + } + + if ( pSecurityObjects[0].Id != SECURITY_OBJECT_ID_OBJECT_SD ) + { + wprintf(L"Unexpected pSecurityObjects[0].Id: %d\n", pSecurityObjects[0].Id); + hr = E_FAIL; + goto exit_gracefully; + } + + if ( !ARGUMENT_PRESENT(pSid) ) + { + return E_INVALIDARG; + } + + bResult = AuthzInitializeResourceManager( + AUTHZ_RM_FLAG_NO_AUDIT, + nullptr, + nullptr, + nullptr, + L"SDK Sample Resource Manager", + &hAuthzResourceManager + ); + FailGracefullyGLE(bResult, L"AuthzInitializeResourceManager"); + madeResourceManager = true; + + // This is never interpreted by AuthZ + identifier.HighPart = 0; + identifier.LowPart = 0; + + bResult = AuthzInitializeContextFromSid( + 0, + pSid, // use the SID passed in to this function + hAuthzResourceManager, + nullptr, // token will never expire (this isn't enforced anyway) + identifier, // never interpreted by authz + nullptr, + &hAuthzUserContext + ); + FailGracefullyGLE(bResult, L"AuthzInitializeContextFromSid"); + + // Set up the different contexts + if ( pDeviceSid != nullptr ) + { + bResult = AuthzInitializeContextFromSid( + 0, + pDeviceSid, // use the device SID passed in to this function + hAuthzResourceManager, + nullptr, // token will never expire (this isn't enforced anyway) + identifier, // never interpreted by authz + nullptr, + &hAuthzDeviceContext + ); + + FailGracefullyGLE(bResult, L"AuthzInitializeContextFromSid (device)"); + + bResult = AuthzInitializeCompoundContext( + hAuthzUserContext, + hAuthzDeviceContext, + &hAuthzCompoundContext + ); + FailGracefullyGLE(bResult, L"AuthzInitializeCompoundContext"); + + // Add device claims + if ( pAuthzDeviceClaims != nullptr ) + { + bResult = AuthzModifyClaims( + hAuthzCompoundContext, + AuthzContextInfoDeviceClaims, + pAuthzDeviceClaimsOperations, + pAuthzDeviceClaims + ); + FailGracefullyGLE(bResult, L"AuthzModifyClaims (device claims)"); + } + } + else + { + hAuthzCompoundContext = hAuthzUserContext; + } + + // Add user claims + if ( pAuthzUserClaims != nullptr ) + { + bResult = AuthzModifyClaims( + hAuthzCompoundContext, + AuthzContextInfoUserClaims, + pAuthzUserClaimsOperations, + pAuthzUserClaims + ); + FailGracefullyGLE(bResult, L"AuthzModifyClaims (user claims)"); + } + + // Add "what-if" device groups + if ( pDeviceGroups != nullptr ) + { + bResult = AuthzModifySids( + hAuthzCompoundContext, + AuthzContextInfoDeviceSids, + pAuthzDeviceGroupsOperations, + pDeviceGroups + ); + FailGracefullyGLE(bResult, L"AuthzModifySids (device groups)"); + } + + // Add "what-if" user groups + if ( pUserGroups != nullptr && pAuthzUserGroupsOperations != nullptr ) + { + bResult = AuthzModifySids( + hAuthzCompoundContext, + AuthzContextInfoGroupsSids, + pAuthzUserGroupsOperations, + pUserGroups + ); + FailGracefullyGLE(bResult, L"AuthzModifySids (user groups)"); + } + + pSD = (PSECURITY_DESCRIPTOR)pSecurityObjects[0].pData; + + request.DesiredAccess = MAXIMUM_ALLOWED; + request.PrincipalSelfSid = nullptr; + request.ObjectTypeList = nullptr; + request.ObjectTypeListLength = 0; + request.OptionalArguments = nullptr; + + reply.ResultListLength = 1; + reply.SaclEvaluationResults = nullptr; + reply.GrantedAccessMask = (PACCESS_MASK)LocalAlloc( + LPTR, + sizeof(ACCESS_MASK) * reply.ResultListLength); + if ( !reply.GrantedAccessMask ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + reply.Error = (PDWORD)LocalAlloc( + LPTR, + sizeof(DWORD) * reply.ResultListLength); + if ( !reply.Error ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + // Finally, call access check. This is the heart of this function. + bResult = AuthzAccessCheck( + dwFlags, // deep copy the SD (default) + hAuthzCompoundContext, + &request, + hAuditEvent, + pSD, + pOptionalSecurityDescriptorArray, + dwOptionalSecurityDescriptorCount, + &reply, + phAccessCheckResults + ); + + FailGracefullyGLE(bResult, L"AuthzAccessCheck"); + needToFreeAccMask = false; + + // Only one security object is passed into this function + // (the object's SD), and we ensured that at the beginning. + pEffpermResultLists[0].fEvaluated = true; + pEffpermResultLists[0].pGrantedAccessList = reply.GrantedAccessMask; + + // We don't support object ACEs, so cObjectTypeListLength has to be 1 + // pObjectTypeList has to be the null GUID, and pGrantedAccessList + // should be a single DWORD + pEffpermResultLists[0].cObjectTypeListLength = 1; + + pEffpermResultLists[0].pObjectTypeList = &m_objectTypeList; + +exit_gracefully: + + if ( madeResourceManager ) + { + AuthzFreeResourceManager(hAuthzResourceManager); + } + + if ( phAccessCheckResults != nullptr ) + { + AuthzFreeHandle(*phAccessCheckResults); + phAccessCheckResults = nullptr; + } + + if (hAuthzUserContext != nullptr) + { + AuthzFreeContext(hAuthzUserContext); + hAuthzUserContext = nullptr; + } + + if (hAuthzDeviceContext != nullptr) + { + AuthzFreeContext(hAuthzDeviceContext); + hAuthzDeviceContext = nullptr; + + if (hAuthzCompoundContext != nullptr) + { + AuthzFreeContext(hAuthzCompoundContext); + hAuthzCompoundContext = nullptr; + } + } + + LocalFree(reply.Error); + + if ( needToFreeAccMask ) + { + LocalFree(reply.GrantedAccessMask); + } + + return hr; +} + +// ISecurityObjectTypeInfo +STDMETHODIMP +CSecInfo::GetInheritSource( + SECURITY_INFORMATION si, + PACL acl, + PINHERITED_FROM *ppInheritArray) +{ + return GetInheritSourceHelper(m_editingResource, si, acl, ppInheritArray); +} + +HRESULT CSecInfo::GetInheritSourceHelper( + int childIndex, + SECURITY_INFORMATION si, + PACL acl, + PINHERITED_FROM *ppInheritArray) +{ + HRESULT hr = S_OK; + BOOL bResult = FALSE; + DWORD errorCode = S_OK; + ACL_SIZE_INFORMATION aclInformation; + Resource *childResource = m_resources[childIndex]; + Resource *parentResource = nullptr; + int indexOfParent = childResource->GetParentIndex(); + DWORD totalCount; + LPVOID ace; + BYTE aceFlags; + BOOL alreadyExists = FALSE; + PSECURITY_DESCRIPTOR pParentSD; + int grandparentIndex; + PSECURITY_DESCRIPTOR pGrandparentSD; + Resource *grandparentResource; + ULONG defaultSecurityDescriptorSize = 0; + BOOL bDaclPresent = 0; + BOOL bDaclDefaulted = 0; + PACL pGrandparentDacl = nullptr; + PACL pParentDacl = nullptr; + + if ( !ARGUMENT_PRESENT(acl) ) + { + return E_INVALIDARG; + } + + // If there's no parent, just return E_NOTIMPL + if ( indexOfParent == NONEXISTENT_OBJECT ) + { + return E_NOTIMPL; + } + + *ppInheritArray = (PINHERITED_FROM)LocalAlloc( + LPTR, + acl->AceCount * sizeof(INHERITED_FROM) ); + if ( !(*ppInheritArray) ) + { + return E_OUTOFMEMORY; + } + + // Iterate over all of the ACEs. + bResult = GetAclInformation( + acl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount = aclInformation.AceCount; + + for ( DWORD aceIndex = 0; aceIndex < totalCount; aceIndex ++ ) + { + bResult = GetAce( + acl, + aceIndex, + &ace + ); + FailGracefullyGLE(bResult, L"GetAce"); + + aceFlags = ((PACE_HEADER)ace)->AceFlags; + + if ( indexOfParent != NONEXISTENT_OBJECT ) + { + parentResource = m_resources[indexOfParent]; + } + + // If we're a SECTION, then it could only have come from the FORUM + // (assuming it wasn't orphaned). If we're a TOPIC, then it could + // either be the parent SECTION or the grandparent FORUM. + if (IS_FLAG_SET(aceFlags,INHERITED_ACE)) + { + if ( childResource->GetType() == SECTION ) + { + // can't just assume that this ACE will be on the parent... + // need to check it; it may be an orphan + bResult = ConvertStringSecurityDescriptorToSecurityDescriptor( + parentResource->GetSD(), + SDDL_REVISION_1, + &pParentSD, + &defaultSecurityDescriptorSize); + FailGracefullyGLE( + bResult, + L"ConvertStringSecurityDescriptorToSecurityDescriptor"); + + alreadyExists = FALSE; + + if ( IS_FLAG_SET(si, DACL_SECURITY_INFORMATION) ) + { + bResult = GetSecurityDescriptorDacl( + pParentSD, + &bDaclPresent, + &pParentDacl, + &bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + hr = ACEAlreadyInACL( + pParentDacl, + ace, + &alreadyExists, + true + ); + FailGracefully(hr, L"ACEAlreadyInACL"); + } + + if ( alreadyExists != FALSE ) + { + (*ppInheritArray)[aceIndex].GenerationGap = 1; + (*ppInheritArray)[aceIndex].AncestorName = parentResource->GetName(); + } + else + { + (*ppInheritArray)[aceIndex].GenerationGap = 0; + (*ppInheritArray)[aceIndex].AncestorName = nullptr; + } + } + else + { + // We're a TOPIC. Check to see if this ACE is in the parent. + // If it isn't, then we check the grandparent. + // We can't skip that check because it may be possible that + // this ACE was orphaned, so it may not exist on any ancestor + grandparentIndex = parentResource->GetParentIndex(); + PSECURITY_DESCRIPTOR pParentSD; + ULONG defaultSecurityDescriptorSize = 0; + bResult = ConvertStringSecurityDescriptorToSecurityDescriptor( + parentResource->GetSD(), + SDDL_REVISION_1, + &pParentSD, + &defaultSecurityDescriptorSize); + FailGracefullyGLE( + bResult, + L"ConvertStringSecurityDescriptorToSecurityDescriptor"); + + if ( IS_FLAG_SET(si, DACL_SECURITY_INFORMATION) ) + { + bResult = GetSecurityDescriptorDacl( + pParentSD, + &bDaclPresent, + &pParentDacl, + &bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + hr = ACEAlreadyInACL( + pParentDacl, + ace, + &alreadyExists, + true + ); + FailGracefully(hr, L"ACEAlreadyInACL"); + } + + + if ( alreadyExists != FALSE ) + { + (*ppInheritArray)[aceIndex].GenerationGap = 1; + (*ppInheritArray)[aceIndex].AncestorName = parentResource->GetName(); + } + else + { + // The parent didn't have it, so check the grandparent. + grandparentResource = m_resources[grandparentIndex]; + defaultSecurityDescriptorSize = 0; + bResult = ConvertStringSecurityDescriptorToSecurityDescriptor( + grandparentResource->GetSD(), + SDDL_REVISION_1, + &pGrandparentSD, + &defaultSecurityDescriptorSize); + FailGracefullyGLE( + bResult, + L"ConvertStringSecurityDescriptorToSecurityDescriptor"); + + alreadyExists = FALSE; + if ( IS_FLAG_SET(si, DACL_SECURITY_INFORMATION) ) + { + bResult = GetSecurityDescriptorDacl( + pGrandparentSD, + &bDaclPresent, + &pGrandparentDacl, + &bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + hr = ACEAlreadyInACL( + pGrandparentDacl, + ace, + &alreadyExists, + true + ); + } + + if ( alreadyExists != FALSE ) + { + // It came from the grandparent + (*ppInheritArray)[aceIndex].GenerationGap = 2; + (*ppInheritArray)[aceIndex].AncestorName = grandparentResource->GetName(); + } + else + { + // This ACE did not come from a [grand]parent + (*ppInheritArray)[aceIndex].GenerationGap = 0; + (*ppInheritArray)[aceIndex].AncestorName = nullptr; + } + } + + } + } + else + { + // This ACE did not come from a [grand]parent + (*ppInheritArray)[aceIndex].GenerationGap = 0; + (*ppInheritArray)[aceIndex].AncestorName = nullptr; + } + } +exit_gracefully: + + return hr; +} diff --git a/Samples/CustomResourceManager/cpp/CSecInfo.h b/Samples/CustomResourceManager/cpp/CSecInfo.h new file mode 100644 index 00000000..c2063e31 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/CSecInfo.h @@ -0,0 +1,231 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +// +// This file contains the declarations for the CSecInfo class along +// with some helpful #defines and objects. +// +#ifndef _CSECINFO_H_ +#define _CSECINFO_H_ +#include +#include +#include +#include "resource.h" + +#define IS_FLAG_SET(dw,fl) (((dw) & (fl)) == fl) + +// Each individual permission for our resource manager +#define CREATE_PERM 0x0001 +#define READ_PERM 0x0002 +#define VOTE_PERM 0x0004 +#define UPDATE_OWN_PERM 0x0008 +#define UPDATE_OTHERS_PERM 0x0010 +#define HIDE_PERM 0x0020 +#define SHOW_PERM 0x0040 +#define LOCK_PERM 0x0080 +#define UNLOCK_PERM 0x0100 +#define DESTROY_PERM 0x0200 +#define VIEW_PERMS_PERM 0x0400 +#define CHANGE_PERMS_PERM 0x0800 + +// Each tier of permissions builds upon the last, but they don't have to. +#define GENERIC_POST_PERM (\ + CREATE_PERM |\ + READ_PERM |\ + VOTE_PERM |\ + UPDATE_OWN_PERM) +#define GENERIC_MOD_PERM (\ + GENERIC_POST_PERM |\ + UPDATE_OTHERS_PERM |\ + HIDE_PERM |\ + SHOW_PERM |\ + LOCK_PERM |\ + UNLOCK_PERM) +#define GENERIC_ADMIN_PERM (\ + GENERIC_MOD_PERM |\ + DESTROY_PERM |\ + VIEW_PERMS_PERM |\ + CHANGE_PERMS_PERM) + +#define INHERIT_FULL (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE) + +// Define the generic mapping array. This is used to denote the +// mapping of each generic access right to a specific access mask. +// This is used on the basic ACL Editor page. +static GENERIC_MAPPING ObjectMap = +{ + GENERIC_POST_PERM, + GENERIC_MOD_PERM, + GENERIC_ADMIN_PERM, +}; + +// ObjectInherit - applies to parent and only child OBJECTS (e.g. files) +// ContainerInherit - applies to parent and only child CONTAINERS (e.g. folders) +// InheritOnly - doesn't apply to parent, must be combined with something else +// NoPropagateInherit - only applies to child, not grandchildren +// +// Note: I only use container inheritance +static SI_INHERIT_TYPE siSDKInheritTypes[] = +{ + &GUID_NULL, 0, (L"This object only"), + &GUID_NULL, CONTAINER_INHERIT_ACE, (L"This object and children (sections/topics)"), + &GUID_NULL, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, (L"Children (sections/topics) only"), +}; + +class CSecInfo : public ISecurityInformation, public ISecurityInformation3, public IEffectivePermission2, public ISecurityObjectTypeInfo +{ +private: + unsigned long m_cRef; + const SI_ACCESS* m_AccessTable; + ULONG m_AccessTableCount; + ULONG m_DefaultAccess; + PCWSTR m_defaultSecurityDescriptorSddl; + OBJECT_TYPE_LIST m_objectTypeList; + + // This represents the index (see resource.h's ResourceIndices) + // of the resource that we're currently editing. + int m_editingResource; + + // This points to all of the resources that the sample keeps track of. + // The constructor sets these up. + PRESOURCE* m_resources; + + // Tell ACL UI what to show + DWORD m_dwSIFlags; + + // This function iterates over a container's children and sets their security. + // parentIndex represents the index of the parent (see ResourceIndices) + // si can include either DACL_SECURITY_INFORMATION, SACL_SECURITY_INFORMATION, or both + // pSD is the security descriptor of the parent + HRESULT SetSecurityOfChildren( + int parentIndex, + THIS_ SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR pSD); + + // Helper function for GetInheritSource so that we can call it on specific children + // and not just the object that we're currently editing. + // childIndex represents the index of the child (see ResourceIndices) + HRESULT GetInheritSourceHelper( + int childIndex, + SECURITY_INFORMATION psi, + PACL acl, +PINHERITED_FROM *inheritArray); + + // This orders a DACL canonically. For more information, see: + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa379298(v=vs.85).aspx + HRESULT OrderDacl(int childIndex, PACL *acl); + + // This function takes a string representing a security descriptor, + // converts it to a self-relative SD, then finally makes it absolute. + HRESULT ConvertStringToAbsSD(_In_ PWSTR stringSD, _Outptr_ PSECURITY_DESCRIPTOR *sd); +public: + // This will be set to true if our ctor produces an error. + bool m_bFailedToConstruct; + CSecInfo(); + virtual ~CSecInfo(); + + void SetCurrentObject(int index) + { + m_editingResource = index; + } + + PRESOURCE GetResource(int index) + { + return m_resources[index]; + } + + // IUnknown + IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void **ppv); + IFACEMETHODIMP_(ULONG) AddRef(); + IFACEMETHODIMP_(ULONG) Release(); + + // ISecurityInformation + IFACEMETHODIMP GetObjectInformation (THIS_ PSI_OBJECT_INFO pObjectInfo); + IFACEMETHODIMP GetSecurity ( + THIS_ SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR *sd, + BOOL fDefault); + IFACEMETHODIMP SetSecurity ( + THIS_ SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR sd); + IFACEMETHODIMP GetAccessRights ( + THIS_ const GUID* guidObjectType, + DWORD dwFlags, + PSI_ACCESS *access, + ULONG *accesses, ULONG *defaultAccess); + IFACEMETHODIMP MapGeneric ( + THIS_ const GUID *guidObjectType, + UCHAR *aceFlags, + ACCESS_MASK *mask); + IFACEMETHODIMP GetInheritTypes ( + THIS_ PSI_INHERIT_TYPE *inheritTypes, + ULONG *numInheritTypes); + IFACEMETHODIMP PropertySheetPageCallback ( + THIS_ HWND hwnd, + UINT uMsg, + SI_PAGE_TYPE uPage); + + // ISecurityInformation3 + IFACEMETHODIMP GetFullResourceName (THIS_ _Outptr_ LPWSTR *resourceName); + IFACEMETHODIMP OpenElevatedEditor ( + THIS_ _In_ HWND hWnd, + _In_ SI_PAGE_TYPE uPage); + + // IEffectivePermission2 + STDMETHOD(ComputeEffectivePermissionWithSecondarySecurity) (THIS_ + _In_ PSID pSid, + _In_opt_ PSID pDeviceSid, + _In_ PCWSTR pszServerName, + _Inout_updates_(dwSecurityObjectCount) PSECURITY_OBJECT pSecurityObjects, + _In_ DWORD dwSecurityObjectCount, + _In_opt_ PTOKEN_GROUPS pUserGroups, + _When_(pUserGroups != nullptr && *pAuthzUserGroupsOperations != AUTHZ_SID_OPERATION_REPLACE_ALL, _In_reads_(pUserGroups->GroupCount)) + _In_opt_ PAUTHZ_SID_OPERATION pAuthzUserGroupsOperations, + _In_opt_ PTOKEN_GROUPS pDeviceGroups, + _When_(pDeviceGroups != nullptr && *pAuthzDeviceGroupsOperations != AUTHZ_SID_OPERATION_REPLACE_ALL, _In_reads_(pDeviceGroups->GroupCount)) + _In_opt_ PAUTHZ_SID_OPERATION pAuthzDeviceGroupsOperations, + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTES_INFORMATION pAuthzUserClaims, + _When_(pAuthzUserClaims != nullptr && *pAuthzUserClaimsOperations != AUTHZ_SECURITY_ATTRIBUTE_OPERATION_REPLACE_ALL, _In_reads_(pAuthzUserClaims->AttributeCount)) + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTE_OPERATION pAuthzUserClaimsOperations, + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTES_INFORMATION pAuthzDeviceClaims, + _When_(pAuthzDeviceClaims != nullptr && *pAuthzDeviceClaimsOperations != AUTHZ_SECURITY_ATTRIBUTE_OPERATION_REPLACE_ALL, _In_reads_(pAuthzDeviceClaims->AttributeCount)) + _In_opt_ PAUTHZ_SECURITY_ATTRIBUTE_OPERATION pAuthzDeviceClaimsOperations, + _Inout_updates_(dwSecurityObjectCount) PEFFPERM_RESULT_LIST pEffpermResultLists); + + // ISecurityObjectTypeInfo + STDMETHOD(GetInheritSource)( + SECURITY_INFORMATION psi, + PACL acl, + PINHERITED_FROM *ppInheritArray); +}; + +const SI_ACCESS g_siForumsAccess[] = +{ + // This structure describes each flag in the file access mask. + // It is constant. ACLUI displays these strings in its UI. + { &GUID_NULL, GENERIC_ADMIN_PERM,L"Administer", SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC | INHERIT_FULL, }, + { &GUID_NULL, GENERIC_MOD_PERM, L"Moderate", SI_ACCESS_GENERAL | INHERIT_FULL }, + { &GUID_NULL, GENERIC_POST_PERM, L"Post", SI_ACCESS_GENERAL | INHERIT_FULL }, + + // Show advanced rights + { &GUID_NULL, CREATE_PERM, L"Create", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, READ_PERM, L"Read", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, VOTE_PERM, L"Vote", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, UPDATE_OWN_PERM, L"Update / edit own content", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, UPDATE_OTHERS_PERM, L"Update / edit others' content", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, HIDE_PERM, L"Hide", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, SHOW_PERM, L"Show", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, LOCK_PERM, L"Lock", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, UNLOCK_PERM, L"Unlock", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, DESTROY_PERM, L"Destroy / delete", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, VIEW_PERMS_PERM, L"View permissions", SI_ACCESS_SPECIFIC | INHERIT_FULL }, + { &GUID_NULL, CHANGE_PERMS_PERM, L"Change permissions", SI_ACCESS_SPECIFIC | INHERIT_FULL }, +}; + +#endif // _CSECINFO_H_ diff --git a/Samples/CustomResourceManager/cpp/CustomResourceManager.sln b/Samples/CustomResourceManager/cpp/CustomResourceManager.sln new file mode 100644 index 00000000..280f7372 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/CustomResourceManager.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomResourceManager", "CustomResourceManager.vcxproj", "{9B1A5249-B3DC-498D-9122-D7C2D75D8084}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9B1A5249-B3DC-498D-9122-D7C2D75D8084}.Debug|Win32.ActiveCfg = Debug|Win32 + {9B1A5249-B3DC-498D-9122-D7C2D75D8084}.Debug|Win32.Build.0 = Debug|Win32 + {9B1A5249-B3DC-498D-9122-D7C2D75D8084}.Release|Win32.ActiveCfg = Release|Win32 + {9B1A5249-B3DC-498D-9122-D7C2D75D8084}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj b/Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj new file mode 100644 index 00000000..9b2dfaec --- /dev/null +++ b/Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {9B1A5249-B3DC-498D-9122-D7C2D75D8084} + CustomResourceManager + + + + Application + true + v110 + MultiByte + + + Application + false + v110 + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + UNICODE=1;_MBCS;%(PreprocessorDefinitions) + + + true + authz.lib;aclui.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + UNICODE=1;_MBCS;%(PreprocessorDefinitions) + + + true + true + true + authz.lib;aclui.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj.filters b/Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj.filters new file mode 100644 index 00000000..a530d1ad --- /dev/null +++ b/Samples/CustomResourceManager/cpp/CustomResourceManager.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;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 + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + diff --git a/Samples/CustomResourceManager/cpp/SecurityInformation1.cpp b/Samples/CustomResourceManager/cpp/SecurityInformation1.cpp new file mode 100644 index 00000000..ceb5dfb5 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/SecurityInformation1.cpp @@ -0,0 +1,450 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +// +// This file contains the definitions for all of the ISecurityInformation +// functions from CSecInfo. This got its own file because the implementation +// of ISecurityInformation is the largest of the interfaces. +// +#include "CSecInfo.h" +#include "utility.h" +#include "authz.h" +#include +#include "sddl.h" +#include + +IFACEMETHODIMP CSecInfo::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo) +{ + Resource *currentResource; + + // SI_OBJECT_INFO: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379605(v=vs.85).aspx + m_dwSIFlags = 0 + | SI_ADVANCED // The "advanced" button is displayed on the basic + // security property page + | SI_EDIT_PERMS // The basic security property page always allows + // basic editing of the object's DACL + | SI_EDIT_OWNER // This lets you change the owner on the advanced page + | SI_PAGE_TITLE // Use pObjectInfo->pszPageTitle for the basic page's + // title + | SI_VIEW_ONLY // Displays a read-only version of the ACL Editor + // dialog boxes. This is required if you're + // implementing ISecurityInformation3. + | SI_EDIT_EFFECTIVE + | SI_ENABLE_EDIT_ATTRIBUTE_CONDITION + ; + + currentResource = m_resources[m_editingResource]; + + if ( currentResource->IsContainer() != FALSE) + { + // This will make ACL UI show the inheritance controls + m_dwSIFlags |= SI_CONTAINER; + } + + pObjectInfo->dwFlags = m_dwSIFlags; + pObjectInfo->hInstance = 0; + pObjectInfo->pszServerName = nullptr; + + // ACL Editor won't free this, so we don't need to make a copy + pObjectInfo->pszObjectName = currentResource->GetName(); + pObjectInfo->pszPageTitle = L"Forums Resource Manager"; + + return S_OK; +} + +IFACEMETHODIMP CSecInfo::GetSecurity( + SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR *ppSD, + BOOL fDefault) +{ + BOOL bResult = 0; + HRESULT hr = S_OK; + DWORD errorCode = 0; + Resource *currentResource = m_resources[m_editingResource]; + ULONG defaultSecurityDescriptorSize = 0; + + // This may be the default SD, or it may + // be the SD on the resource we're editing + PWSTR sdToEdit = NULL; + + if ( fDefault ) + { + hr = AllocAndCopyString(m_defaultSecurityDescriptorSddl, &sdToEdit); + FailGracefully(hr, L"AllocAndCopyString"); + } + else + { + hr = AllocAndCopyString( + const_cast(currentResource->GetSD()), + &sdToEdit); + FailGracefully(hr, L"AllocAndCopyString"); + } + + if ( + IS_FLAG_SET(si, DACL_SECURITY_INFORMATION) || + IS_FLAG_SET(si, OWNER_SECURITY_INFORMATION) || + IS_FLAG_SET(si, GROUP_SECURITY_INFORMATION) + ) + { + // The following function will populate the entire SD. + bResult = ConvertStringSecurityDescriptorToSecurityDescriptor( + sdToEdit, + SDDL_REVISION_1, + ppSD, + &defaultSecurityDescriptorSize); + + FailGracefullyGLE( + bResult, + L"ConvertStringSecurityDescriptorToSecurityDescriptor"); + } + +exit_gracefully: + LocalFree(sdToEdit); + + return hr; +} + + +IFACEMETHODIMP CSecInfo::SetSecurity( + SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR pSD) +{ + BOOL bResult = 0; + DWORD errorCode = 0; + HRESULT hr = S_OK; + PACL pDestDacl = nullptr; + BOOL bDaclPresent = 0; + BOOL bDaclDefaulted = 0; + PACL pSourceDacl = nullptr; + DWORD dwSizeNeeded; + SECURITY_DESCRIPTOR_CONTROL sdControl; + DWORD dwRevision; + int parentIndex; + PSECURITY_DESCRIPTOR pSDOfParent; + PSID group; + BOOL bGroupDefaulted = 0; + PSID owner; + BOOL bOwnerDefaulted = 0; + PWSTR stringSD; + ULONG stringSDLen = 0; + SECURITY_DESCRIPTOR_CONTROL currentObjectSDControl; + + PSECURITY_DESCRIPTOR absoluteCurrentSD; + Resource *currentResource = m_resources[m_editingResource]; + + hr = ConvertStringToAbsSD(currentResource->GetSD(), &absoluteCurrentSD); + FailGracefully(hr, L"ConvertStringToAbsSD"); + + if ( IS_FLAG_SET(si, DACL_SECURITY_INFORMATION) ) + { + bResult = GetSecurityDescriptorDacl( + pSD, + &bDaclPresent, + &pSourceDacl, + &bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + bResult = GetSecurityDescriptorDacl( + absoluteCurrentSD, + &bDaclPresent, + &pDestDacl, + &bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + + if ( pDestDacl == nullptr ) + { + // Align sizeNeeded to a DWORD + dwSizeNeeded = (sizeof(ACL) + (sizeof(DWORD) - 1)) & 0xfffffffc; + + pDestDacl = (PACL)LocalAlloc(LPTR, dwSizeNeeded); + if ( pDestDacl == nullptr ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + bResult = InitializeAcl(pDestDacl, dwSizeNeeded, ACL_REVISION); + FailGracefullyGLE(bResult, L"InitializeAcl"); + } + + // Before doing anything else, we need to change the protected + // bit in case we end up reenabling inheritance. + + // If the 'P' flag was set, e.g. D:PAR(A;CIIO;FA;;;WD) + // then we need to remove all inherited entries + bResult = GetSecurityDescriptorControl( + pSD, + &sdControl, + &dwRevision + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorControl"); + + bResult = GetSecurityDescriptorControl( + absoluteCurrentSD, + ¤tObjectSDControl, + &dwRevision + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorControl"); + BOOL currentObjectWasProtected = + IS_FLAG_SET(currentObjectSDControl, SE_DACL_PROTECTED) + ? TRUE + : FALSE; + + // Now that we've gotten the SE_DACL_PROTECTED bit off of the current + // object, we can set it to what it needs to be. We needed to capture + // it in the case that we're reenabling inheritance. + bResult = SetSecurityDescriptorControl( + absoluteCurrentSD, + SE_DACL_PROTECTED, + IS_FLAG_SET(sdControl, SE_DACL_PROTECTED) + ? SE_DACL_PROTECTED + : 0 + ); + FailGracefullyGLE(bResult, L"SetSecurityDescriptorControl"); + + if ( IS_FLAG_SET(sdControl, SE_DACL_PROTECTED) ) + { + hr = RemoveAllInheritedAces( + &pDestDacl + ); + FailGracefully(hr, L"RemoveAllInheritedAces"); + } + else + { + // The user reenabled inheritance (i.e. didn't pass in + // SE_DACL_PROTECTED, but the object used to have that flag). + if ( currentObjectWasProtected != FALSE ) + { + // This means we need to call SetSecurityOfChildren on the + // parent. This is why we disabled the SE_DACL_PROTECTED flag + // already - otherwise the function would exit immediately. + parentIndex = currentResource->GetParentIndex(); + if ( parentIndex != NONEXISTENT_OBJECT ) + { + Resource *parentResource = m_resources[parentIndex]; + // Because we're keeping SDs as strings, we need to do + // a bit of hackery here to set up for SetSecurityOfChildren. + + // First, save the current security descriptor to where + // SetSecurityOfChildren can pick it up + { + bResult = ConvertSecurityDescriptorToStringSecurityDescriptor( + absoluteCurrentSD, + SDDL_REVISION_1, + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | + LABEL_SECURITY_INFORMATION | + ATTRIBUTE_SECURITY_INFORMATION | + SCOPE_SECURITY_INFORMATION, + &stringSD, + &stringSDLen + ); + + FailGracefullyGLE(bResult, L"ConvertSecurityDescriptorToStringSecurityDescriptor"); + + currentResource->FreeSD(); + currentResource->SetSD(stringSD); + stringSD = nullptr; + } + + hr = ConvertStringToAbsSD( + parentResource->GetSD(), + &pSDOfParent); + FailGracefully(hr, L"ConvertStringToAbsSD"); + + hr = SetSecurityOfChildren( + parentIndex, + DACL_SECURITY_INFORMATION, + pSDOfParent); + FailGracefully(hr, L"SetSecurityOfChildren"); + // Now, the current resource's SD will be set to what we want... + // so we need to make sure we're working on that by making + // absoluteCurrentSD into that. + hr = ConvertStringToAbsSD( + currentResource->GetSD(), + &absoluteCurrentSD); + FailGracefully(hr, L"ConvertStringToAbsSD"); + + // The DACL probably just changed + bResult = GetSecurityDescriptorDacl( + absoluteCurrentSD, + &bDaclPresent, + &pDestDacl, + &bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorDacl"); + } + } + } + + hr = AddAllAcesFromAcl(pSourceDacl, &pDestDacl, TRUE); + FailGracefully(hr, L"AddAllAcesFromAcl"); + + // Finally, remove the explicit ACEs that don't appear in pSD. + // These are ACEs that used to be on the DACL, but the user just + // removed. + hr = RemoveExplicitUniqueAces( + pSourceDacl, + &pDestDacl + ); + FailGracefully(hr, L"RemoveExplicitUniqueAces"); + + hr = OrderDacl( + m_editingResource, + &pDestDacl + ); + FailGracefully(hr, L"OrderDacl"); + + bResult = SetSecurityDescriptorDacl( + absoluteCurrentSD, + true, + pDestDacl, + bDaclDefaulted + ); + FailGracefullyGLE(bResult, L"SetSecurityDescriptorDacl"); + + pDestDacl = nullptr; + } + if ( IS_FLAG_SET(si, GROUP_SECURITY_INFORMATION) ) + { + bResult = GetSecurityDescriptorGroup( + pSD, + &group, + &bGroupDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorGroup"); + + bResult = SetSecurityDescriptorGroup( + absoluteCurrentSD, + group, + bGroupDefaulted + ); + FailGracefullyGLE(bResult, L"SetSecurityDescriptorGroup"); + } + if ( IS_FLAG_SET(si, OWNER_SECURITY_INFORMATION) ) + { + bResult = GetSecurityDescriptorOwner( + pSD, + &owner, + &bOwnerDefaulted + ); + FailGracefullyGLE(bResult, L"GetSecurityDescriptorOwner"); + + bResult = SetSecurityDescriptorOwner( + absoluteCurrentSD, + owner, + bOwnerDefaulted + ); + FailGracefullyGLE(bResult, L"SetSecurityDescriptorOwner"); + } + + // Finally, convert whatever changes we made to the absolute SD back to a string + bResult = ConvertSecurityDescriptorToStringSecurityDescriptor( + absoluteCurrentSD, + SDDL_REVISION_1, + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | + LABEL_SECURITY_INFORMATION | + ATTRIBUTE_SECURITY_INFORMATION | + SCOPE_SECURITY_INFORMATION, + &stringSD, + &stringSDLen + ); + + FailGracefullyGLE(bResult, L"ConvertSecurityDescriptorToStringSecurityDescriptor"); + + currentResource->FreeSD(); + currentResource->SetSD(stringSD); + stringSD = nullptr; + + if ( currentResource->IsContainer() != FALSE) + { + hr = SetSecurityOfChildren(m_editingResource, si, absoluteCurrentSD); + FailGracefully(hr, L"SetSecurityOfChildren"); + } + +exit_gracefully: + + LocalFree(pDestDacl); + + return hr; +} + +IFACEMETHODIMP CSecInfo::GetAccessRights( + const GUID* pguidObjectType, + DWORD dwFlags, + PSI_ACCESS *ppAccess, + ULONG *pcAccesses, + ULONG *piDefaultAccess) +{ + UNREFERENCED_PARAMETER(dwFlags); + + if ( pguidObjectType == nullptr || *pguidObjectType == GUID_NULL ) + { + *ppAccess = const_cast(m_AccessTable); + *pcAccesses = m_AccessTableCount; + + // This is the index of the default access you want when you're + // adding a permission. It ends up indexing m_AccessTable, which + // is really g_siForumsAccess, so 0 is Full Control. + *piDefaultAccess = m_DefaultAccess; + } + + return S_OK; +} + +// This function requests that the generic access rights in an access mask +// be mapped to their corresponding standard and specific access rights. +IFACEMETHODIMP CSecInfo::MapGeneric( + const GUID *pguidObjectType, + UCHAR *pAceFlags, + ACCESS_MASK *pMask) +{ + if ( !pAceFlags || !pMask ) + { + return E_INVALIDARG; + } + + // This sample doesn't include object inheritance, so that bit can be + // safely removed. + *pAceFlags &= ~OBJECT_INHERIT_ACE; + MapGenericMask(pMask, &ObjectMap); + + UNREFERENCED_PARAMETER(pguidObjectType); + return S_OK; +} +IFACEMETHODIMP CSecInfo::GetInheritTypes( + PSI_INHERIT_TYPE *ppInheritTypes, + ULONG *pcInheritTypes) +{ + if ( m_resources[m_editingResource]->IsContainer() != FALSE) + { + *ppInheritTypes = siSDKInheritTypes; + *pcInheritTypes = ARRAYSIZE(siSDKInheritTypes); + return S_OK; + } + + return E_NOTIMPL; +} + +IFACEMETHODIMP CSecInfo::PropertySheetPageCallback( + HWND hwnd, + UINT uMsg, + SI_PAGE_TYPE uPage) +{ + UNREFERENCED_PARAMETER(hwnd); + UNREFERENCED_PARAMETER(uMsg); + UNREFERENCED_PARAMETER(uPage); + return E_NOTIMPL; +} diff --git a/Samples/CustomResourceManager/cpp/main.cpp b/Samples/CustomResourceManager/cpp/main.cpp new file mode 100644 index 00000000..8bbbf952 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/main.cpp @@ -0,0 +1,111 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include +#include +#include "CSecInfo.h" +#include "windows.h" +#include + +#pragma warning(push) +// C4127: conditional expression is constant (disabled for our input loop) +#pragma warning(disable : 4127) + +int __cdecl wmain( + _In_ int argc, + _In_reads_(argc) PCWSTR argv[]) +{ + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + + CSecInfo cSecInfo; + BOOL bResult; + if ( cSecInfo.m_bFailedToConstruct != FALSE) + { + wprintf(L"Couldn't construct our class. Exiting.\n"); + return 1; + } + + int choice; + do { + // Print the following: + // ------------------------------------ + // 1. Contoso forums + // 2. Sports + // 3. Favorite team + // 4. Upcoming events + // 5. Movies + // 6. 2012 releases + // 7. Classics + // 8. Hobbies + // 9. Learning to cook + // 10. Snowboarding + // 11. Help + // ------------------------------------ + wprintf(L"------------------------------------\n"); + wprintf(L"1. %s\n", cSecInfo.GetResource(0)->GetName()); + wprintf(L"2. \t%s\n", cSecInfo.GetResource(1)->GetName()); + wprintf(L"3. \t\t%s\n", cSecInfo.GetResource(2)->GetName()); + wprintf(L"4. \t\t%s\n", cSecInfo.GetResource(3)->GetName()); + wprintf(L"5. \t%s\n", cSecInfo.GetResource(4)->GetName()); + wprintf(L"6. \t\t%s\n", cSecInfo.GetResource(5)->GetName()); + wprintf(L"7. \t\t%s\n", cSecInfo.GetResource(6)->GetName()); + wprintf(L"8. \t%s\n", cSecInfo.GetResource(7)->GetName()); + wprintf(L"9. \t\t%s\n", cSecInfo.GetResource(8)->GetName()); + wprintf(L"10. \t\t%s\n", cSecInfo.GetResource(9)->GetName()); + wprintf(L"11. Help\n"); + wprintf(L"------------------------------------\n"); + wprintf(L"Input a number to view/edit the security descriptor " + L"for one of the above: "); + std::cin >> choice; + + if ( choice >= 1 && choice <= 10 ) + { + cSecInfo.SetCurrentObject(choice-1); + wprintf(L"You chose %s\n\n", + cSecInfo.GetResource(choice-1)->GetName()); + } + else if ( choice == 11 ) + { + wprintf(L"\n" + L"This resource manager example models a set of forums" + L". On the top level, there is a single FORUMS object " + L"(%s). It has three children, which are SECTIONs (%s," + L" %s, and %s), and they each have two children, which" + L" are TOPICs. Inheritable ACEs follow this inheritance" + L" hierarchy. Choose a number (1-%d) to edit any of " + L"their security descriptors.\n\n", + cSecInfo.GetResource(CONTOSO_FORUMS)->GetName(), + cSecInfo.GetResource(SPORTS)->GetName(), + cSecInfo.GetResource(MOVIES)->GetName(), + cSecInfo.GetResource(HOBBIES)->GetName(), + NUMBER_OF_RESOURCES); + continue; + } + else + { + break; + } + + // Suppress warning about the param being 0 + #pragma warning(suppress: 6387) + bResult = EditSecurity(nullptr, &cSecInfo); + if ( !bResult ) + { + wprintf(L"EditSecurity error %d\n", GetLastError()); + break; + } + + } while ( true ); + + return 0; +} + +#pragma warning(pop) diff --git a/Samples/CustomResourceManager/cpp/resource.cpp b/Samples/CustomResourceManager/cpp/resource.cpp new file mode 100644 index 00000000..985616f3 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/resource.cpp @@ -0,0 +1,70 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +// +// This file contains the definitions of the Resource class. +// +#include "resource.h" + +Resource::Resource(_In_ PWSTR name, _In_ ResourceType type, _In_ PWSTR sd, _In_ int parentIndex) : + name(name), + type(type), + sd(sd), + parentIndex(parentIndex) +{ +} + +void Resource::SetSD(_In_ PWSTR newSD) +{ + sd = newSD; +} +PWSTR Resource::GetSD() +{ + return sd; +} +bool Resource::IsContainer() +{ + // We could also implement this by checking to see if childIndices + // is non-empty. + return type == FORUM || type == SECTION; +} +PWSTR Resource::GetName() +{ + return name; +} +ResourceType Resource::GetType() +{ + return type; +} + +int Resource::GetParentIndex() +{ + return parentIndex; +} + +void Resource::FreeSD() +{ + LocalFree(sd); + sd = nullptr; +} + +Resource::~Resource() +{ + FreeSD(); +} + +void Resource::AddChild(int index) +{ + childIndices.push_back(index); +} + +std::list Resource::GetChildIndices() +{ + return childIndices; +} diff --git a/Samples/CustomResourceManager/cpp/resource.h b/Samples/CustomResourceManager/cpp/resource.h new file mode 100644 index 00000000..440523ac --- /dev/null +++ b/Samples/CustomResourceManager/cpp/resource.h @@ -0,0 +1,87 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#ifndef _RESOURCE_H_ +#define _RESOURCE_H_ + +#include +#include + +enum ResourceType +{ + FORUM, + SECTION, + TOPIC +}; + +#define NUMBER_OF_RESOURCES 10 + +enum ResourceIndices +{ + NONEXISTENT_OBJECT = -1, + CONTOSO_FORUMS, + SPORTS, + FAVORITE_TEAM, + UPCOMING_EVENTS, + MOVIES, + NEW_RELEASES, + CLASSICS, + HOBBIES, + LEARNING_TO_COOK, + SNOWBOARDING, +}; + +// This class represents a FORUM, SECTION, or TOPIC. +class Resource +{ + +public: + + Resource(_In_ PWSTR name, _In_ ResourceType type, _In_ PWSTR sd, _In_ int parentIndex); + + // The destructor will free the security descriptor if necessary + ~Resource(); + + // Adds to childIndices + void AddChild(int index); + + // Returns true if this is a FORUM or SECTION + bool IsContainer(); + + // Frees the security descriptor string + void FreeSD(); + + // All of these functions are basic accessors/mutators + void SetSD(_In_ PWSTR newSD); + PWSTR GetSD(); + PWSTR GetName(); + ResourceType GetType(); + int GetParentIndex(); + std::list GetChildIndices(); + +private: + // The name of this resource, e.g. "Sports" + PWSTR name; + + // Type of this resource (FORUM, SECTION, TOPIC) + ResourceType type; + + // The security descriptor for this resource. + PWSTR sd; + + // The index into CSecInfo's m_resources of the parent resource + int parentIndex; + + // Similarly to the parent index, this keeps track of all children + std::list childIndices; +}; + +typedef Resource* PRESOURCE; + +#endif //_RESOURCE_H_ diff --git a/Samples/CustomResourceManager/cpp/utility.cpp b/Samples/CustomResourceManager/cpp/utility.cpp new file mode 100644 index 00000000..ac4ee0db --- /dev/null +++ b/Samples/CustomResourceManager/cpp/utility.cpp @@ -0,0 +1,747 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "utility.h" +#include "CSecInfo.h" +#include "authz.h" +#include +#include // for StringCchCopy +#include // for UShortAdd, UShortMult +#include "sddl.h" +#include + +HRESULT AllocAndCopyString(_In_ PCWSTR source, _Outptr_ PWSTR *dest) +{ + HRESULT hr = S_OK; + size_t len; + + if ( !ARGUMENT_PRESENT(source) ) + { + return E_INVALIDARG; + } + + len = wcslen(source); + // Remember: wcslen excludes the null character when calculating the length. + // Also, StringCchCopyW takes the total length of the destination buffer + *dest = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((len + 1) * sizeof(wchar_t))); + if ( !(*dest) ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + hr = StringCchCopyW(*dest, len + 1, source); + FailGracefully(hr, L"StringCchCopyW"); + +exit_gracefully: + + if ( !SUCCEEDED(hr) ) + { + LocalFree(*dest); + } + + return hr; +} + +HRESULT RemoveAllInheritedAces(PACL *ppAcl) +{ + BOOL bResult = FALSE; + DWORD errorCode = S_OK; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + DWORD totalCount; + DWORD aceIndex = 0; + LPVOID ace = nullptr; + BYTE aceFlags = 0; + + if ( !ARGUMENT_PRESENT(*ppAcl) ) + { + return E_INVALIDARG; + } + + bResult = GetAclInformation( + *ppAcl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount = aclInformation.AceCount; + while ( aceIndex < totalCount ) + { + bResult = GetAce( + *ppAcl, + aceIndex, + &ace + ); + FailGracefullyGLE(bResult, L"GetAce"); + + aceFlags = ((PACE_HEADER)ace)->AceFlags; + + if (IS_FLAG_SET(aceFlags,INHERITED_ACE)) + { + bResult = DeleteAce( + *ppAcl, + aceIndex); + FailGracefullyGLE(bResult, L"DeleteAce"); + + totalCount--; + } + else + { + aceIndex++; + } + } + +exit_gracefully: + return hr; +} + +// Adds all ACEs from sourceAcl to ppDestAcl. +// If onlyAddUnique is specified, then this function will ensure that +// ACEs from sourceAcl aren't added if they already appear in ppDestAcl. +HRESULT AddAllAcesFromAcl(PACL sourceAcl, PACL *ppDestAcl, bool onlyAddUnique) +{ + BOOL bResult = 0; + DWORD errorCode = S_OK; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + LPVOID ace; + bool addIt = true; + BOOL alreadyExists = FALSE; + + if ( !ARGUMENT_PRESENT(sourceAcl) || !ARGUMENT_PRESENT(*ppDestAcl) ) + { + return E_INVALIDARG; + } + + bResult = GetAclInformation( + sourceAcl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + + FailGracefullyGLE(bResult, L"GetAclInformation"); + + for ( DWORD i = 0; i < aclInformation.AceCount; i ++ ) + { + bResult = GetAce( + sourceAcl, + i, + &ace + ); + + FailGracefullyGLE(bResult, L"GetAce"); + + // If we only want to add unique ACEs, then we + // need to make sure that this doesn't already exist + // in the destination. + addIt = true; + if ( onlyAddUnique ) + { + + hr = ACEAlreadyInACL( + *ppDestAcl, + ace, + &alreadyExists, + false + ); + + FailGracefully(hr, L"ACEAlreadyInACL"); + + if ( alreadyExists != FALSE ) + { + addIt = false; + } + } + + if ( addIt ) + { + hr = AddAceToAcl(ace, ppDestAcl, false); + FailGracefully(hr, L"AddAceToAcl"); + } + } +exit_gracefully: + + return hr; +} + +// This function will remove the noninherited ACEs from +// ppDestAcl that don't show up in 'acl'. This is needed for +// SetSecurity - inherited ACEs need to stay, and any ACEs that +// are being set need to stay, but all others need to go. +HRESULT RemoveExplicitUniqueAces(PACL acl, PACL *ppDestAcl) +{ + BOOL bResult = 0; + DWORD errorCode = S_OK; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + DWORD totalCount; + DWORD aceIndex = 0; + LPVOID ace; + BYTE aceFlags; + BOOL alreadyExists = FALSE; + + if ( !ARGUMENT_PRESENT(acl) || !ARGUMENT_PRESENT(*ppDestAcl) ) + { + return E_INVALIDARG; + } + + bResult = GetAclInformation( + *ppDestAcl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount = aclInformation.AceCount; + while ( aceIndex < totalCount ) + { + bResult = GetAce( + *ppDestAcl, + aceIndex, + &ace + ); + + FailGracefullyGLE(bResult, L"GetAce"); + + aceFlags = ((PACE_HEADER)ace)->AceFlags; + + // We only care about explcit (i.e. non-inherited) ACEs + if ( IS_FLAG_SET(aceFlags, INHERITED_ACE) ) + { + aceIndex++; + continue; + } + + hr = ACEAlreadyInACL( + acl, + ace, + &alreadyExists, + false + ); + + FailGracefully(hr, L"ACEAlreadyInACL"); + + // If it's not in 'acl', then it's unique + if ( alreadyExists == FALSE ) + { + bResult = DeleteAce(*ppDestAcl, aceIndex); + FailGracefullyGLE(bResult, L"DeleteAce"); + totalCount--; + } + else + { + aceIndex++; + } + } + +exit_gracefully: + return hr; +} + +// Go through all of the ACEs in the ACL and see if 'ace' is equal to any of them. +HRESULT ACEAlreadyInACL( + _In_ PACL acl, + _In_ LPVOID ace, + _Out_ LPBOOL lpbAcePresent, + _In_ bool forInheritancePurposes) +{ + BOOL bResult = 0; + DWORD errorCode = 0; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + BYTE aceType; + WORD aceSize; + BYTE aceFlags; + BYTE existingAceType; + WORD existingAceSize; + BYTE existingAceFlags; + DWORD totalCount; + LPVOID pExistingAce; + LPVOID sidStart1; + LPVOID sidStart2; + DWORD sidLength1; + DWORD sidLength2; + int result; + + if ( !ARGUMENT_PRESENT(acl) || !ARGUMENT_PRESENT(ace) ) + { + return E_INVALIDARG; + } + + aceType = ((PACE_HEADER)ace)->AceType; + aceSize = ((PACE_HEADER)ace)->AceSize; + aceFlags = ((PACE_HEADER)ace)->AceFlags; + + if ( forInheritancePurposes ) + { + // If the ACE wasn't inherited, then we don't care about it + if ( !IS_FLAG_SET(aceFlags, INHERITED_ACE) ) + { + *lpbAcePresent = FALSE; + return S_OK; + } + else + { + // It was inherited. Don't use that flag for comparison though + // because it won't appear on the source. + aceFlags &= ~INHERITED_ACE; + } + } + + bResult = GetAclInformation( + acl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount = aclInformation.AceCount; + for ( DWORD i = 0; i < totalCount; i ++ ) + { + bResult = GetAce( + acl, + i, + &pExistingAce + ); + FailGracefullyGLE(bResult, L"GetAce"); + + existingAceType = ((PACE_HEADER)pExistingAce)->AceType; + existingAceSize = ((PACE_HEADER)pExistingAce)->AceSize; + existingAceFlags = ((PACE_HEADER)pExistingAce)->AceFlags; + + if ( forInheritancePurposes ) + { + if ( !IsInheritableAce(existingAceFlags) ) + { + // We only care about inheritable ACEs + continue; + } + else + { + // Wipe out the inheritance flags that couldn't possibly be on the + // child. (e.g. when we have a NO_PROPAGATE_INHERIT_ACE, the ACE + // will make it to the child, but the flag will get unset in + // AddInheritableAcesFromAcl). + existingAceFlags &= ~INHERIT_ONLY_ACE; + + if ( IS_FLAG_SET(existingAceFlags, NO_PROPAGATE_INHERIT_ACE) ) + { + existingAceFlags &= ~NO_PROPAGATE_INHERIT_ACE; + + // The child doesn't get the [...]_INHERIT_ACE + // flag if NO_PROPAGATE was specified. + existingAceFlags &= ~CONTAINER_INHERIT_ACE; + existingAceFlags &= ~OBJECT_INHERIT_ACE; + } + } + } + + if ( existingAceFlags == aceFlags && + existingAceSize == aceSize && + existingAceType == aceType ) + { + // That was our quick check, now we should compare the + // actual contents (mask and SID) + sidStart1 = GetSidStart(aceType, pExistingAce); + sidStart2 = GetSidStart(aceType, ace); + sidLength1 = GetLengthSid((PSID)sidStart1); + sidLength2 = GetLengthSid((PSID)sidStart2); + + // This is needed even though we just compared the sizes because + // of callback aces - the size of the ACLs may coincidentally be + // the same because the sums of the sid length and condition + // sizes are equal + if ( sidLength1 != sidLength2 ) + { + continue; + } + + result = memcmp( + (PSID)sidStart1, + (PSID)sidStart2, + aceSize - sizeof(ACE_HEADER) - sizeof(ACCESS_MASK)); + if ( result == 0 ) + { + *lpbAcePresent = TRUE; + return S_OK; + } + } + } + + *lpbAcePresent = FALSE; +exit_gracefully: + return hr; +} + +// Add an ACE to an ACL, expanding the ACL if needed. +HRESULT AddAceToAcl(LPVOID pNewAce, PACL *ppAcl, bool bAddToEndOfList) +{ + DWORD addPosition = bAddToEndOfList ? MAXDWORD : 0; + BOOL bResult = FALSE; + DWORD errorCode = S_OK; + PACL biggerDACL = nullptr; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + WORD aceSize; + DWORD oldSize; + USHORT uSize; + DWORD dwNewSizeNeeded; + + if ( !ARGUMENT_PRESENT(pNewAce) || !ARGUMENT_PRESENT(*ppAcl) ) + { + return E_INVALIDARG; + } + + bResult = AddAce( + *ppAcl, + ACL_REVISION, + addPosition, + pNewAce, + ((PACE_HEADER)pNewAce)->AceSize + ); + + // See if we failed due to an insufficient buffer size + if ( !bResult ) + { + errorCode = GetLastError(); + if ( errorCode == ERROR_INSUFFICIENT_BUFFER ) + { + // Not enough space. Allocate a bigger ACL. + + bResult = GetAclInformation( + *ppAcl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + aceSize = ((PACE_HEADER)pNewAce)->AceSize; + oldSize = aclInformation.AclBytesInUse; + + // Can't overflow WORD boundary + hr = UShortAdd(aceSize, (USHORT)oldSize, &uSize); + FailGracefully(hr, L"UShortAdd"); + + // Give us some extra space so that we don't have to keep + // reallocating. + hr = UShortMult(uSize, 2, &uSize); + FailGracefully(hr, L"UShortMult"); + + dwNewSizeNeeded = (DWORD)uSize; + // Align to a DWORD + dwNewSizeNeeded = (dwNewSizeNeeded + (sizeof(DWORD) - 1)) & 0xfffffffc; + + // Make sure the alignment didn't overflow the size of a WORD + // (the process of aligning can add up to 3) + if ( dwNewSizeNeeded > USHORT_MAX ) + { + // It's safe to subtrat now (despite the "size needed" name) + // because we overestimated earlier by multiplying by 2. + dwNewSizeNeeded -= 4; + } + + biggerDACL = (PACL)LocalAlloc(LPTR, dwNewSizeNeeded); + if ( !biggerDACL ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + // Note: no need to initialize the new ACL + memcpy(biggerDACL, *ppAcl, oldSize); + + // This cast is safe because we checked for overflow earlier + biggerDACL->AclSize = (WORD)dwNewSizeNeeded; + + *ppAcl = biggerDACL; + + // Make sure this doesn't get freed later + biggerDACL = nullptr; + + bResult = AddAce( + *ppAcl, + ACL_REVISION, + addPosition, + pNewAce, + ((PACE_HEADER)pNewAce)->AceSize + ); + FailGracefullyGLE(bResult, L"AddAce"); + } + else + { + return HRESULT_FROM_WIN32(errorCode); + } + } +exit_gracefully: + LocalFree(biggerDACL); + + return hr; +} + +LPVOID GetSidStart(BYTE aceType, LPVOID ace) +{ + LONG offset = 0; + switch (aceType) + { + case ACCESS_ALLOWED_ACE_TYPE: + case ACCESS_DENIED_ACE_TYPE: + case SYSTEM_AUDIT_ACE_TYPE: + offset = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart); + break; + case SYSTEM_AUDIT_CALLBACK_ACE_TYPE: + offset = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_ACE, SidStart); + break; + case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: + offset = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_ACE, SidStart); + break; + default: + return 0; + } + + // We use PUCHAR so that we can add an offset to the pointer + return (PUCHAR)ace + offset; +} + +HRESULT ConvertSecurityDescriptor( + PSECURITY_DESCRIPTOR pSelfRelSD, + PSECURITY_DESCRIPTOR *ppAbsoluteSD) +{ + BOOL bResult; + PACL pDacl = nullptr; + PACL pSacl = nullptr; + PSID pOwner = nullptr; + PSID pPrimaryGroup = nullptr; + DWORD dwAbsoluteSDSize = 0; + DWORD dwDaclSize = 0; + DWORD dwSaclSize = 0; + DWORD dwOwnerSize = 0; + DWORD dwPrimaryGroupSize = 0; + size_t sizeNeeded = 0; + *ppAbsoluteSD = nullptr; + + // Confirm that pSelfRelSD is actually self relative + if( + !ARGUMENT_PRESENT(pSelfRelSD) || + !IS_FLAG_SET(((SECURITY_DESCRIPTOR*)(pSelfRelSD))->Control, SE_SELF_RELATIVE) + ) + { + return E_INVALIDARG; + } + + // Call it once so that the sizes will be set to the correct values. This + // will return a buffer-too-small error, so we don't check the return value + MakeAbsoluteSD( + pSelfRelSD, + nullptr, + &dwAbsoluteSDSize, + nullptr, + &dwDaclSize, + nullptr, + &dwSaclSize, + nullptr, + &dwOwnerSize, + nullptr, + &dwPrimaryGroupSize + ); + + sizeNeeded = + dwAbsoluteSDSize + + dwDaclSize + + dwSaclSize + + dwOwnerSize + + dwPrimaryGroupSize; + *ppAbsoluteSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, sizeNeeded); + + if ( !*ppAbsoluteSD ) + { + return E_OUTOFMEMORY; + } + + BYTE* position = (BYTE *)(*ppAbsoluteSD); + pDacl = reinterpret_cast(position += dwAbsoluteSDSize); + pSacl = reinterpret_cast(position += dwDaclSize); + pOwner = reinterpret_cast(position += dwSaclSize); + pPrimaryGroup = reinterpret_cast(position += dwOwnerSize); + + bResult = MakeAbsoluteSD( + pSelfRelSD, + *ppAbsoluteSD, + &dwAbsoluteSDSize, + pDacl, + &dwDaclSize, + pSacl, + &dwSaclSize, + pOwner, + &dwOwnerSize, + pPrimaryGroup, + &dwPrimaryGroupSize + ); + + if ( !bResult ) + { + LocalFree(*ppAbsoluteSD); + return HRESULT_FROM_WIN32(GetLastError()); + } + + return S_OK; +} + +// This goes through every ACE in 'acl', sums the size of the inheritable +// ACEs, and puts it in dwSizeNeeded. +HRESULT GetSizeOfAllInheritableAces(PACL acl, DWORD &dwSizeNeeded) +{ + BOOL bResult; + DWORD errorCode = S_OK; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + DWORD totalCount; + LPVOID ace; + BYTE aceFlags; + + if ( !ARGUMENT_PRESENT(acl) ) + { + return E_INVALIDARG; + } + + bResult = GetAclInformation( + acl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + totalCount = aclInformation.AceCount; + + // Start with zero as the size. We'll only initialize this + // to sizeof(ACL) if we find an inheritable ACE. + dwSizeNeeded = 0; + + for ( DWORD aceIndex = 0; aceIndex < totalCount; aceIndex ++ ) + { + bResult = GetAce( + acl, + aceIndex, + &ace + ); + FailGracefullyGLE(bResult, L"GetAce"); + + aceFlags = ((PACE_HEADER)ace)->AceFlags; + + // Only count the inheritable ACEs + if (IsInheritableAce(aceFlags)) + { + // Initialize the size now that we've found an inheritable ACE + if ( dwSizeNeeded == 0 ) + { + dwSizeNeeded = sizeof(ACL); + } + dwSizeNeeded += ((PACE_HEADER)ace)->AceSize; + } + } +exit_gracefully: + return hr; +} + +// Adds any inheritable ACEs from sourceAcl to ppDestAcl. +HRESULT AddInheritableAcesFromAcl(PACL sourceAcl, PACL *ppDestAcl) +{ + BOOL bResult = 0; + DWORD errorCode = S_OK; + HRESULT hr = S_OK; + ACL_SIZE_INFORMATION aclInformation; + LPVOID newAce = nullptr; + LPVOID ace; + BYTE aceFlags; + WORD aceSize; + + if ( !ARGUMENT_PRESENT(sourceAcl) || !ARGUMENT_PRESENT(*ppDestAcl) ) + { + return E_INVALIDARG; + } + + bResult = GetAclInformation( + sourceAcl, + &aclInformation, + sizeof(aclInformation), + AclSizeInformation + ); + FailGracefullyGLE(bResult, L"GetAclInformation"); + + for ( DWORD i = 0; i < aclInformation.AceCount; i ++ ) + { + bResult = GetAce( + sourceAcl, + i, + &ace + ); + + FailGracefullyGLE(bResult, L"GetAce"); + + aceFlags = ((PACE_HEADER)ace)->AceFlags; + + // We only care about the inheritable ACEs + if (IsInheritableAce(aceFlags)) + { + // We don't need to see if the ACE is already in the child's DACL + // because we always remove all inherited ACEs before calling this + // function, so an inheritable ACE can't exist in the child. + // + // The ACE that we add needs to have the "ID" flag set, + // but we don't want to modify the parent's ACE, so we + // need to make a new ACE. + aceSize = ((PACE_HEADER)ace)->AceSize; + newAce = (LPVOID)LocalAlloc(LPTR, aceSize); + if ( !newAce ) + { + wprintf(L"LocalAlloc failed.\n"); + hr = E_OUTOFMEMORY; + goto exit_gracefully; + } + + memcpy(newAce, ace, aceSize); + ((PACE_HEADER)newAce)->AceFlags |= INHERITED_ACE; + + // It's important that we unset the inherit-only flag, or this + // ACE will be overlooked by AccessCheck (likewise by effective + // access checks). + ((PACE_HEADER)newAce)->AceFlags &= ~INHERIT_ONLY; + + // NO_PROPAGATE_INHERIT_ACE means the inheritance only applies to + // the child, not the grandchildren, so we need to unset the + // applicable inheritance flags. + if ( IS_FLAG_SET(aceFlags, NO_PROPAGATE_INHERIT_ACE) ) + { + ((PACE_HEADER)newAce)->AceFlags &= ~NO_PROPAGATE_INHERIT_ACE; + ((PACE_HEADER)newAce)->AceFlags &= ~OBJECT_INHERIT_ACE; + ((PACE_HEADER)newAce)->AceFlags &= ~CONTAINER_INHERIT_ACE; + } + + hr = AddAceToAcl(newAce, ppDestAcl, false); + FailGracefully(hr, L"AddAceToAcl"); + + LocalFree(newAce); + newAce = nullptr; + } + } + +exit_gracefully: + + LocalFree(newAce); + return hr; +} diff --git a/Samples/CustomResourceManager/cpp/utility.h b/Samples/CustomResourceManager/cpp/utility.h new file mode 100644 index 00000000..46269cd1 --- /dev/null +++ b/Samples/CustomResourceManager/cpp/utility.h @@ -0,0 +1,77 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#ifndef _UTILITY_H_ +#define _UTILITY_H_ +#include +#include +#include +#include "resource.h" + +// INHERIT_ONLY_ACE and NO_PROPAGATE_INHERIT_ACE are inheritable ACEs, +// but if they don't have OBJECT or CONTAINER inheritance set, then +// they aren't considered. +#define IsInheritableAce(aceFlags) \ + (IS_FLAG_SET((aceFlags), OBJECT_INHERIT_ACE) || \ + IS_FLAG_SET((aceFlags), CONTAINER_INHERIT_ACE)) + +#define IsAccessAllowedAce(aceType) \ + ((aceType) == ACCESS_ALLOWED_CALLBACK_ACE_TYPE ||\ + (aceType) == ACCESS_ALLOWED_ACE_TYPE) + +#define FailGracefully(hr, text) \ + { if ( FAILED(hr) ) { wprintf(text); goto exit_gracefully; } } + +#define FailGracefullyGLE(bResult, text) \ + { if ( (bResult) == FALSE ) { errorCode = GetLastError(); \ + hr = HRESULT_FROM_WIN32(errorCode); \ + if ( FAILED(HRESULT_FROM_WIN32(hr)) ) { wprintf(text); \ + goto exit_gracefully; } } } + +#define ARGUMENT_PRESENT(ArgumentPointer) (\ + (CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) ) + +// Allocates space for 'dest' and copies 'source' into it +HRESULT AllocAndCopyString(_In_ PCWSTR source, _Outptr_ PWSTR *dest); + +// Removes all ACEs with the "ID" flag set from ppAcl. +HRESULT RemoveAllInheritedAces(PACL *acl); + +HRESULT AddAllAcesFromAcl(PACL sourceAcl, PACL *destAcl, bool onlyAddUnique); + +HRESULT RemoveExplicitUniqueAces(PACL acl, PACL *destAcl); + +// Determine if an ACE is in an ACL. +// acl - the ACL +// ace - the ACE to check for +// lpbAcePresent - this will be set to true if the ACE exists in the ACL +// forInheritancePurposes - if true, this will ignore the "ID" flag on the ACE +// and other inheritance flags on ACEs in the ACL +HRESULT ACEAlreadyInACL( + _In_ PACL acl, + _In_ LPVOID ace, + _Out_ LPBOOL lpbAcePresent, + _In_ bool forInheritancePurposes); + +HRESULT AddAceToAcl(LPVOID pNewAce, PACL *acl, bool bAddToEndOfList); + +LPVOID GetSidStart(BYTE aceType, LPVOID ace); + +HRESULT AddInheritableAcesFromAcl(PACL sourceAcl, PACL *destAcl); + +HRESULT GetSizeOfAllInheritableAces(PACL acl, DWORD &dwSizeNeeded); + +// Converts a self-relative security descriptor to absolute. +// Note: GetSecurityDescriptor* APIs work either with self-relative OR absolute, +// but SetSecurityDescriptorDacl will only work with absolute. +HRESULT ConvertSecurityDescriptor( + PSECURITY_DESCRIPTOR pSelfRelSD, + PSECURITY_DESCRIPTOR *absoluteSD); + +#endif // _UTILITY_H_ diff --git a/Samples/D2DPrintingFromDesktopApps/README.md b/Samples/D2DPrintingFromDesktopApps/README.md new file mode 100644 index 00000000..bd14b020 --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/README.md @@ -0,0 +1,40 @@ +Direct2D desktop app printing sample +==================================== + +This sample shows how to print [Direct2D](http://msdn.microsoft.com/en-us/library/windows/desktop/dd370990) content. + +For more information about the APIs used in this sample, see the following topics: + +- [Direct2D](http://msdn.microsoft.com/en-us/library/windows/desktop/dd370990) +- [**ID2D1PrintControl**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh847997) +- [**ID2D1CommandList**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404392) + +**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. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the solution (.sln) file from Visual Studio 2013 for Windows 8.1 (any SKU) or later versions of Visual Studio and Windows. Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. + +Run the sample +-------------- + +To run this sample after building it, go to the installation folder for this sample with Windows Explorer and open the executable file. Alternatively, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.cpp b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.cpp new file mode 100644 index 00000000..75cd7360 --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.cpp @@ -0,0 +1,338 @@ +//// 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 "D2DPrintJobChecker.h" + +#include + +D2DPrintJobChecker::D2DPrintJobChecker() : + m_eventCookie(0), + m_refcount(1), + m_completionEvent(nullptr), + m_connectionPoint(nullptr), + m_isInitialized(false) +{ + PrintDocumentPackageStatus status = {0}; + m_documentPackageStatus = status; + + // Initialize the critical section, one time only. + InitializeCriticalSection(&m_criticalSection); +} + +D2DPrintJobChecker::~D2DPrintJobChecker() +{ + ReleaseResources(); + + // Release resources used by the critical section object. + DeleteCriticalSection(&m_criticalSection); +} + +// Initialize this print job checker by registering a print document package target. +// This is required before the application can use this print job checker to monitor a print job. +HRESULT D2DPrintJobChecker::Initialize( + _In_ IPrintDocumentPackageTarget* documentPackageTarget + ) +{ + // Application can only initialize this job checker once. + if (m_isInitialized) + { + return E_FAIL; + } + + HRESULT hr = (documentPackageTarget != nullptr) ? S_OK : E_INVALIDARG; + + IConnectionPointContainer* connectionPointContainer = nullptr; + if (SUCCEEDED(hr)) + { + hr = documentPackageTarget->QueryInterface(IID_PPV_ARGS(&connectionPointContainer)); + } + + if (SUCCEEDED(hr)) + { + hr = connectionPointContainer->FindConnectionPoint( + __uuidof(IPrintDocumentPackageStatusEvent), + &m_connectionPoint + ); + } + + IUnknown* unknownEvent = nullptr; + if (SUCCEEDED(hr)) + { + hr = this->QueryInterface(IID_PPV_ARGS(&unknownEvent)); + } + + if (SUCCEEDED(hr)) + { + hr = m_connectionPoint->Advise(unknownEvent, &m_eventCookie); + } + + // Create an event handle for print job completion. + if (SUCCEEDED(hr)) + { + m_completionEvent = ::CreateEvent( + nullptr, // The handle cannot be inherited by child processes. + TRUE, // The event object requires the use of the ResetEvent function to set the event state to nonsignaled. + FALSE, // The initial state of the event object is nonsignaled. + nullptr // Name of the event object. + ); + hr = (!m_completionEvent) ? HRESULT_FROM_WIN32(::GetLastError()) : hr; + } + + if (unknownEvent) + { + unknownEvent->Release(); + unknownEvent = nullptr; + } + if (connectionPointContainer) + { + connectionPointContainer->Release(); + connectionPointContainer = nullptr; + } + + if (SUCCEEDED(hr)) + { + m_isInitialized = true; + } + else + { + ReleaseResources(); + } + + return hr; +} + +HRESULT STDMETHODCALLTYPE +D2DPrintJobChecker::QueryInterface( + REFIID iid, + _Out_ void** ppvObject + ) +{ + if (iid == __uuidof(IUnknown) || + iid == __uuidof(IPrintDocumentPackageStatusEvent)) + { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + else + { + *ppvObject = nullptr; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE +D2DPrintJobChecker::AddRef() +{ + return (ULONG)InterlockedIncrement(&m_refcount); +} + +ULONG STDMETHODCALLTYPE +D2DPrintJobChecker::Release() +{ + ULONG res = (ULONG)InterlockedDecrement(&m_refcount); + if (0 == res) + { + delete this; + } + return res; +} + +HRESULT D2DPrintJobChecker::GetTypeInfoCount( + _Out_ UINT* /* pctinfo */ + ) +{ + return E_NOTIMPL; +} + +HRESULT D2DPrintJobChecker::GetTypeInfo( + UINT /* iTInfo */, + LCID /* lcid */, + _Outptr_result_maybenull_ ITypeInfo** /* ppTInfo */ + ) +{ + return E_NOTIMPL; +} + +HRESULT D2DPrintJobChecker::GetIDsOfNames( + _In_ REFIID /* riid */, + _In_reads_(cNames) LPOLESTR* /* rgszNames */, + _In_range_(0, 16384) UINT cNames, + LCID /* lcid */, + __out_ecount_full(cNames) DISPID* /* rgDispId */ + ) +{ + UNREFERENCED_PARAMETER(cNames); + return E_NOTIMPL; +} + +HRESULT D2DPrintJobChecker::Invoke( + DISPID /* dispIdMember */, + REFIID /* riid */, + LCID /* lcid */, + WORD /* wFlags */, + DISPPARAMS* /* pDispParams */, + VARIANT* /* pVarResult */, + EXCEPINFO* /* pExcepInfo */, + UINT* /* puArgErr */ + ) +{ + return E_NOTIMPL; +} + +// Callback to indicate that the status of the package has changed. +STDMETHODIMP D2DPrintJobChecker::PackageStatusUpdated( + _In_ PrintDocumentPackageStatus* packageStatus + ) +{ + HRESULT hr = (packageStatus == nullptr) ? E_INVALIDARG : S_OK; + + if (SUCCEEDED(hr)) + { + // The package status update operation is guarded with a critical section, + // since PackageStatusUpdated may be called in a very short time slot. + EnterCriticalSection(&m_criticalSection); + m_documentPackageStatus = *packageStatus; + LeaveCriticalSection(&m_criticalSection); + } + + if (SUCCEEDED(hr)) + { + // Signal the print job complete event. + if (PrintDocumentPackageCompletion_InProgress != m_documentPackageStatus.Completion) + { + if (!SetEvent(m_completionEvent)) + { + hr = HRESULT_FROM_WIN32(::GetLastError()); + } + } + } + +#if defined(_DEBUG) + OutputPackageStatus(m_documentPackageStatus); +#endif + + return S_OK; +} + +// Return print document package status. +PrintDocumentPackageStatus D2DPrintJobChecker::GetStatus() +{ + return(m_documentPackageStatus); +} + +// Wait for job completion event to be signaled; in the meanwhile keep pumping messages to avoid deadlocks. +// +// This is an example for deadlock: when user print to a " Print To File" printer, the winspool.dll will try to pop +// up a modal dialog asking for file name. In order to show modal dialog, winspool will call EnableWindow(FALSE) to +// disable this window. Therefore, the winspool thread is waiting for us to process the message of disabling the +// window, while our thread is waiting for the winspool thread to complete. +HRESULT D2DPrintJobChecker::WaitForCompletion() +{ + // Return successfully if this job checker is not initialized. + if (!m_isInitialized) + { + return S_OK; + } + + HRESULT hr = S_OK; + + bool isWaiting = true; + while (isWaiting) + { + DWORD waitResult = ::MsgWaitForMultipleObjects( + 1, // Number of object handles in the array. + &m_completionEvent, // Array of object handles. + FALSE, // Function returns when the state of any one of the objects is set to signaled. + INFINITE, // Function will return only when the specified objects are signaled. + QS_ALLINPUT // Any message is in the queue. + ); + if (waitResult == WAIT_OBJECT_0 + 1) + { + // This is not the desired completion event. + MSG msg; + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + ::DispatchMessage(&msg); + } + if (msg.message == WM_QUIT) + { + isWaiting = false; + break; + } + } + else + { + isWaiting = false; + } + } + + return hr; +} + +// Output debug message for the print document package status. +void D2DPrintJobChecker::OutputPackageStatus( + _In_ PrintDocumentPackageStatus packageStatus + ) +{ + switch (packageStatus.Completion) + { + case PrintDocumentPackageCompletion_Completed: + OutputDebugString(L"PrintDocumentPackageCompletion_Completed; "); + break; + + case PrintDocumentPackageCompletion_Canceled: + OutputDebugString(L"PrintDocumentPackageCompletion_Canceled; "); + break; + + case PrintDocumentPackageCompletion_Failed: + OutputDebugString(L"PrintDocumentPackageCompletion_Failed; "); + break; + + case PrintDocumentPackageCompletion_InProgress: + OutputDebugString(L"PrintDocumentPackageCompletion_InProgress; "); + break; + + default: + OutputDebugString(L"PrintDocumentPackageStatus unknown! "); + break; + } + WCHAR messageBuffer[256] = {0}; + StringCchPrintf( + messageBuffer, + ARRAYSIZE(messageBuffer), + L"\tjobID:%3d, currentDoc:%3d, currentPage:%3d, currentPageTotal:%3d, packageStatus:0x%08X\n", + packageStatus.JobId, + packageStatus.CurrentDocument, + packageStatus.CurrentPage, + packageStatus.CurrentPageTotal, + packageStatus.PackageStatus + ); + OutputDebugString(messageBuffer); +} + +// Release resources. +void D2DPrintJobChecker::ReleaseResources() +{ + if (m_connectionPoint != nullptr) + { + if (m_eventCookie != 0) + { + m_connectionPoint->Unadvise(m_eventCookie); + } + m_connectionPoint->Release(); + m_connectionPoint = nullptr; + } + + if (m_completionEvent != nullptr) + { + ::CloseHandle(m_completionEvent); + m_completionEvent = nullptr; + } + + return; +} \ No newline at end of file diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.h b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.h new file mode 100644 index 00000000..1a5f4f50 --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintJobChecker.h @@ -0,0 +1,98 @@ +//// 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 + +#ifndef _DIRECT2D_PRINT_JOB_CHECKER_ +#define _DIRECT2D_PRINT_JOB_CHECKER_ + +#ifndef UNICODE +#define UNICODE +#endif + +// DirectX header files. +#include +#include +#include + +class D2DPrintJobChecker : public IPrintDocumentPackageStatusEvent +{ +public: + D2DPrintJobChecker(); + ~D2DPrintJobChecker(); + + // Implement virtual functions from interface IUnknown. + virtual + HRESULT STDMETHODCALLTYPE + QueryInterface( + REFIID iid, + _Out_ void** ppvObject + ); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + + // Implement virtual functions from interface IDispatch. + virtual STDMETHODIMP + GetTypeInfoCount( + _Out_ UINT *pctinfo + ); + virtual STDMETHODIMP + GetTypeInfo( + UINT iTInfo, + LCID lcid, + _Outptr_result_maybenull_ ITypeInfo **ppTInfo + ); + virtual STDMETHODIMP + GetIDsOfNames( + _In_ REFIID riid, + _In_reads_(cNames) LPOLESTR* rgszNames, + _In_range_(0, 16384) UINT cNames, + LCID lcid, + __out_ecount_full(cNames) DISPID* rgDispId + ); + virtual STDMETHODIMP + Invoke( + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr + ); + + // Implement virtual functions from interface IPrintDocumentPackageStatusEvent. + virtual STDMETHODIMP + PackageStatusUpdated( + _In_ PrintDocumentPackageStatus* packageStatus + ); + + // New functions in D2DPrintJobChecker. + HRESULT Initialize( + _In_ IPrintDocumentPackageTarget* documentPackageTarget + ); + PrintDocumentPackageStatus GetStatus(); + HRESULT WaitForCompletion(); + static void OutputPackageStatus( + _In_ PrintDocumentPackageStatus packageStatus + ); + +private: + void ReleaseResources(); + +private: + PrintDocumentPackageStatus m_documentPackageStatus; + DWORD m_eventCookie; + ULONG m_refcount; + HANDLE m_completionEvent; + CRITICAL_SECTION m_criticalSection; + IConnectionPoint* m_connectionPoint; + bool m_isInitialized; +}; + +#endif // _DIRECT2D_PRINT_JOB_CHECKER_ diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.cpp b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.cpp new file mode 100644 index 00000000..b8b7a0ea --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.cpp @@ -0,0 +1,1746 @@ +//// 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 "D2DPrintingFromDesktopApps.h" + +#include +#include +#include +#include +#include + +static const FLOAT PAGE_WIDTH_IN_DIPS = 8.5f * 96.0f; // 8.5 inches +static const FLOAT PAGE_HEIGHT_IN_DIPS = 11.0f * 96.0f; // 11 inches +static const FLOAT PAGE_MARGIN_IN_DIPS = 96.0f; // 1 inch +static const FLOAT FRAME_HEIGHT_IN_DIPS = 400.0f; // 400 DIPs +static const FLOAT HOURGLASS_SIZE = 200.0f; // 200 DIPs + +// Provides the main entry point to the application. +int WINAPI WinMain( + _In_ HINSTANCE /* hInstance */, + _In_opt_ HINSTANCE /* hPrevInstance */, + _In_ LPSTR /* lpCmdLine */, + _In_ int /* nCmdShow */ + ) +{ + // Ignore the return value because we want to continue running even in the + // unlikely event that HeapSetInformation fails. + BOOL succeded = HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0); + if (!succeded) + { + // Enable Heap Termination upon corruption failed. + // For this sample, we ignore when this fails and continue running. + } + + if (SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) + { + { + DemoApp app; + + if (SUCCEEDED(app.Initialize())) + { + app.RunMessageLoop(); + } + } + CoUninitialize(); + + return 0; + } + else + { + return -1; + } +} + +// The main window message loop. +void DemoApp::RunMessageLoop() +{ + MSG message; + + while (GetMessage(&message, nullptr, 0, 0)) + { + TranslateMessage(&message); + DispatchMessage(&message); + } +} + +// Initializes members. +DemoApp::DemoApp() : + m_resourcesValid(false), + m_parentHwnd(nullptr), + m_d2dHwnd(nullptr), + m_multiPageMode(TRUE), + m_currentScrollPosition(0), + m_d2dFactory(nullptr), + m_wicFactory(nullptr), + m_dwriteFactory(nullptr), + m_swapChain(nullptr), + m_d2dDevice(nullptr), + m_d2dContext(nullptr), + m_textFormat(nullptr), + m_smallTextFormat(nullptr), + m_pathGeometry(nullptr), + m_linearGradientBrush(nullptr), + m_blackBrush(nullptr), + m_gridPatternBrush(nullptr), + m_customBitmap(nullptr), + m_jobPrintTicketStream(nullptr), + m_printControl(nullptr), + m_documentTarget(nullptr), + m_printJobChecker(nullptr), + m_pageHeight(PAGE_HEIGHT_IN_DIPS), + m_pageWidth(PAGE_WIDTH_IN_DIPS) +{ +} + +// Releases resources. +DemoApp::~DemoApp() +{ + // Release device-independent resources. + SafeRelease(&m_textFormat); + SafeRelease(&m_smallTextFormat); + SafeRelease(&m_pathGeometry); + + // Release device-dependent resources. + SafeRelease(&m_linearGradientBrush); + SafeRelease(&m_blackBrush); + SafeRelease(&m_gridPatternBrush); + SafeRelease(&m_customBitmap); + SafeRelease(&m_swapChain); + SafeRelease(&m_d2dDevice); + SafeRelease(&m_d2dContext); + + // Release printing-specific resources. + SafeRelease(&m_jobPrintTicketStream); + SafeRelease(&m_printControl); + SafeRelease(&m_documentTarget); + SafeRelease(&m_printJobChecker); + + // Release factories. + SafeRelease(&m_d2dFactory); + SafeRelease(&m_wicFactory); + SafeRelease(&m_dwriteFactory); +} + +// Creates the application window and initializes +// device-independent and device-dependent resources. +HRESULT DemoApp::Initialize() +{ + // Initialize device-indpendent resources, such + // as the Direct2D factory. + HRESULT hr = CreateDeviceIndependentResources(); + + if (SUCCEEDED(hr)) + { + // Register the parent window class. + WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = DemoApp::ParentWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(LONG_PTR); + wcex.hInstance = HINST_THISCOMPONENT; + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = nullptr; + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = L"DemoAppWindow"; + + RegisterClassEx(&wcex); + + // Because the CreateWindow function takes its size in pixels, we + // obtain the system DPI and use it to scale the window size. + FLOAT dpiX, dpiY; + m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY); + + // Create the parent window. + m_parentHwnd = CreateWindow( + L"DemoAppWindow", + L"Direct2D desktop app printing sample - Press 'p' to print, press to toggle multi-page mode", + WS_OVERLAPPEDWINDOW | WS_VSCROLL, + CW_USEDEFAULT, + CW_USEDEFAULT, + static_cast(ceil(640.f * dpiX / 96.f)), + static_cast(ceil(480.f * dpiY / 96.f)), + nullptr, + nullptr, + HINST_THISCOMPONENT, + this + ); + + hr = m_parentHwnd ? S_OK : E_FAIL; + + if (SUCCEEDED(hr)) + { + ShowWindow(m_parentHwnd, SW_SHOWNORMAL); + UpdateWindow(m_parentHwnd); + } + } + + if (SUCCEEDED(hr)) + { + // Register the child window class (for D2D content). + WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = DemoApp::ChildWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(LONG_PTR); + wcex.hInstance = HINST_THISCOMPONENT; + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = nullptr; + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = L"D2DDemoApp"; + + RegisterClassEx(&wcex); + + D2D1_SIZE_U d2dWindowSize = CalculateD2DWindowSize(); + + // Create the child window. + m_d2dHwnd = CreateWindow( + L"D2DDemoApp", + L"", + WS_CHILDWINDOW | WS_VISIBLE, + 0, + 0, + d2dWindowSize.width, + d2dWindowSize.height, + m_parentHwnd, + nullptr, + HINST_THISCOMPONENT, + this + ); + + hr = m_d2dHwnd ? S_OK : E_FAIL; + } + + // Create D2D device context and device-dependent resources. + if (SUCCEEDED(hr)) + { + hr = CreateDeviceResources(); + } + + if (FAILED(hr)) + { + MessageBox( + m_d2dHwnd, + L"Failed to initialize the application. Sample will exit.", + L"Sample initialization error", + MB_OK | MB_ICONSTOP + ); + } + + return hr; +} + +// Calculates the size of the D2D (child) window. +D2D1_SIZE_U DemoApp::CalculateD2DWindowSize() +{ + RECT rc; + GetClientRect(m_parentHwnd, &rc); + + D2D1_SIZE_U d2dWindowSize = {0}; + d2dWindowSize.width = rc.right; + d2dWindowSize.height = rc.bottom; + + return d2dWindowSize; +} + +// Creates resources which are not bound to any device. +// Their lifetimes effectively extend for the duration +// of the app. +HRESULT DemoApp::CreateDeviceIndependentResources() +{ + HRESULT hr = S_OK; + + ID2D1GeometrySink* sink = nullptr; + + if (SUCCEEDED(hr)) + { + // Create a Direct2D factory. + D2D1_FACTORY_OPTIONS options; + ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); + +#if defined(_DEBUG) + // If the project is in a debug build, enable Direct2D debugging via SDK Layers + options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; +#endif + + hr = D2D1CreateFactory( + D2D1_FACTORY_TYPE_SINGLE_THREADED, + options, + &m_d2dFactory + ); + } + if (SUCCEEDED(hr)) + { + // Create a WIC factory. + hr = CoCreateInstance( + CLSID_WICImagingFactory, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&m_wicFactory) + ); + } + if (SUCCEEDED(hr)) + { + // Create a DirectWrite factory. + hr = DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast(&m_dwriteFactory) + ); + } + if (SUCCEEDED(hr)) + { + // Create a DirectWrite text format object. + hr = m_dwriteFactory->CreateTextFormat( + L"Verdana", + nullptr, + DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 50.0f, + L"en-us", + &m_textFormat + ); + } + if (SUCCEEDED(hr)) + { + // Center the text horizontally. + hr = m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); + } + if (SUCCEEDED(hr)) + { + // Center the text vertically. + hr = m_textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); + } + if (SUCCEEDED(hr)) + { + // Create a second DirectWrite text format for the multi-page text + hr = m_dwriteFactory->CreateTextFormat( + L"Verdana", + nullptr, + DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 12.0f, + L"en-us", + &m_smallTextFormat + ); + } + + // Create a path geometry for an hourglass shape. + if (SUCCEEDED(hr)) + { + // Create a path geometry. + hr = m_d2dFactory->CreatePathGeometry(&m_pathGeometry); + } + if (SUCCEEDED(hr)) + { + // Use the geometry sink to write to the path geometry. + hr = m_pathGeometry->Open(&sink); + } + if (SUCCEEDED(hr)) + { + // Write an hourglass shape to the geometry. + sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); + + sink->BeginFigure( + D2D1::Point2F(0.0f, 0.0f), + D2D1_FIGURE_BEGIN_FILLED + ); + + sink->AddLine(D2D1::Point2F(HOURGLASS_SIZE, 0.0f)); + + sink->AddBezier( + D2D1::BezierSegment( + D2D1::Point2F(HOURGLASS_SIZE / 4.0f * 3.0f, HOURGLASS_SIZE / 4.0f), + D2D1::Point2F(HOURGLASS_SIZE / 4.0f * 3.0f, HOURGLASS_SIZE / 4.0f * 3.0f), + D2D1::Point2F(HOURGLASS_SIZE, HOURGLASS_SIZE)) + ); + + sink->AddLine(D2D1::Point2F(0.0f, HOURGLASS_SIZE)); + + sink->AddBezier( + D2D1::BezierSegment( + D2D1::Point2F(HOURGLASS_SIZE / 4.0f, HOURGLASS_SIZE / 4.0f * 3.0f), + D2D1::Point2F(HOURGLASS_SIZE / 4.0f, HOURGLASS_SIZE / 4.0f), + D2D1::Point2F(0.0f, 0.0f)) + ); + + sink->EndFigure(D2D1_FIGURE_END_CLOSED); + + hr = sink->Close(); + } + SafeRelease(&sink); + + return hr; +} + +// Create D2D context for display (Direct3D) device +HRESULT DemoApp::CreateDeviceContext() +{ + HRESULT hr = S_OK; + + // Get the size of the child window. + D2D1_SIZE_U size = CalculateD2DWindowSize(); + + // Create a D3D device and a swap chain sized to the child window. + UINT createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + }; + UINT countOfDriverTypes = ARRAYSIZE(driverTypes); + + DXGI_SWAP_CHAIN_DESC swapDescription; + ZeroMemory(&swapDescription, sizeof(swapDescription)); + swapDescription.BufferDesc.Width = size.width; + swapDescription.BufferDesc.Height = size.height; + swapDescription.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swapDescription.BufferDesc.RefreshRate.Numerator = 60; + swapDescription.BufferDesc.RefreshRate.Denominator = 1; + swapDescription.SampleDesc.Count = 1; + swapDescription.SampleDesc.Quality = 0; + swapDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapDescription.BufferCount = 1; + swapDescription.OutputWindow = m_d2dHwnd; + swapDescription.Windowed = TRUE; + + ID3D11Device* d3dDevice = nullptr; + for (UINT driverTypeIndex = 0; driverTypeIndex < countOfDriverTypes; driverTypeIndex++) + { + hr = D3D11CreateDeviceAndSwapChain( + nullptr, // use default adapter + driverTypes[driverTypeIndex], + nullptr, // no external software rasterizer + createDeviceFlags, + nullptr, // use default set of feature levels + 0, + D3D11_SDK_VERSION, + &swapDescription, + &m_swapChain, + &d3dDevice, + nullptr, // do not care about what feature level is chosen + nullptr // do not retain D3D device context + ); + + if (SUCCEEDED(hr)) + { + break; + } + } + + IDXGIDevice* dxgiDevice = nullptr; + if (SUCCEEDED(hr)) + { + // Get a DXGI device interface from the D3D device. + hr = d3dDevice->QueryInterface(&dxgiDevice); + } + if (SUCCEEDED(hr)) + { + // Create a D2D device from the DXGI device. + hr = m_d2dFactory->CreateDevice( + dxgiDevice, + &m_d2dDevice + ); + } + if (SUCCEEDED(hr)) + { + // Create a device context from the D2D device. + hr = m_d2dDevice->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + &m_d2dContext + ); + } + + SafeRelease(&dxgiDevice); + SafeRelease(&d3dDevice); + return hr; +} + +// This method creates resources which are bound to a particular +// Direct3D device. It's all centralized here, in case the resources +// need to be recreated in case of Direct3D device loss (e.g. display +// change, remoting, removal of video card, etc). The resources created +// here can be used by multiple Direct2D device contexts (in this +// sample, one for display and another for print) which are created +// from the same Direct2D device. +HRESULT DemoApp::CreateDeviceResources() +{ + HRESULT hr = S_OK; + + if (!m_resourcesValid) + { + hr = CreateDeviceContext(); + + IDXGISurface* surface = nullptr; + if (SUCCEEDED(hr)) + { + // Get a surface from the swap chain. + hr = m_swapChain->GetBuffer( + 0, + IID_PPV_ARGS(&surface) + ); + } + ID2D1Bitmap1* bitmap = nullptr; + if (SUCCEEDED(hr)) + { + FLOAT dpiX, dpiY; + m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY); + + // Create a bitmap pointing to the surface. + D2D1_BITMAP_PROPERTIES1 properties = D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat( + DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_IGNORE + ), + dpiX, + dpiY + ); + + hr = m_d2dContext->CreateBitmapFromDxgiSurface( + surface, + &properties, + &bitmap + ); + } + if (SUCCEEDED(hr)) + { + // Set the bitmap as the target of our device context. + m_d2dContext->SetTarget(bitmap); + } + if (SUCCEEDED(hr)) + { + // Create a black brush. + hr = m_d2dContext->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::Black), + &m_blackBrush + ); + } + // Create a linear gradient for the hourglasses. + ID2D1GradientStopCollection* gradientStops = nullptr; + if (SUCCEEDED(hr)) + { + static const D2D1_GRADIENT_STOP stops[] = + { + { 0.f, { 0.f, 1.f, 1.f, 0.25f } }, + { 1.f, { 0.f, 0.f, 1.f, 1.f } }, + }; + + hr = m_d2dContext->CreateGradientStopCollection( + stops, + ARRAYSIZE(stops), + &gradientStops + ); + } + if (SUCCEEDED(hr)) + { + hr = m_d2dContext->CreateLinearGradientBrush( + D2D1::LinearGradientBrushProperties( + D2D1::Point2F(HOURGLASS_SIZE/2, 0), + D2D1::Point2F(HOURGLASS_SIZE/2, HOURGLASS_SIZE)), + D2D1::BrushProperties(), + gradientStops, + &m_linearGradientBrush + ); + } + SafeRelease(&gradientStops); + if (SUCCEEDED(hr)) + { + // Create a bitmap by loading it from a file. + hr = LoadBitmapFromFile( + m_d2dContext, + m_wicFactory, + L".\\sampleImage.jpg", + 100, + 0, + &m_customBitmap + ); + } + if (SUCCEEDED(hr)) + { + // Create a brush to use for the gridded background. + hr = CreateGridPatternBrush(&m_gridPatternBrush); + } + if (SUCCEEDED(hr)) + { + ResetScrollBar(); + } + + SafeRelease(&bitmap); + SafeRelease(&surface); + } + + if (FAILED(hr)) + { + DiscardDeviceResources(); + } + else + { + m_resourcesValid = true; + } + + return hr; +} + +// Creates a bitmap-backed pattern brush to be used for the grid +// background in the scene. +HRESULT DemoApp::CreateGridPatternBrush( + _Outptr_ ID2D1ImageBrush** imageBrush + ) +{ + HRESULT hr = S_OK; + + ID2D1CommandList* gridCommandList = nullptr; + if (SUCCEEDED(hr)) + { + // Create a command list that will store the grid pattern. + hr = m_d2dContext->CreateCommandList(&gridCommandList); + } + ID2D1SolidColorBrush* gridBrush = nullptr; + if (SUCCEEDED(hr)) + { + // Create a brush with which to draw the grid pattern. + hr = m_d2dContext->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF(0.93f, 0.94f, 0.96f, 1.0f)), + &gridBrush + ); + } + ID2D1Image* originalTarget = nullptr; + if (SUCCEEDED(hr)) + { + // Save the context's current target. + m_d2dContext->GetTarget(&originalTarget); + + // Put the new target in place. + m_d2dContext->SetTarget(gridCommandList); + + // Draw the grid pattern on the new target. + m_d2dContext->BeginDraw(); + m_d2dContext->FillRectangle(D2D1::RectF(0.0f, 0.0f, 10.0f, 1.0f), gridBrush); + m_d2dContext->FillRectangle(D2D1::RectF(0.0f, 0.1f, 1.0f, 10.0f), gridBrush); + hr = m_d2dContext->EndDraw(); + + // Restore the original target. + m_d2dContext->SetTarget(originalTarget); + } + if (SUCCEEDED(hr)) + { + hr = gridCommandList->Close(); + } + if (SUCCEEDED(hr)) + { + // Create image brush with the grid command list. + hr = m_d2dContext->CreateImageBrush( + gridCommandList, + D2D1::ImageBrushProperties( + D2D1::RectF(0, 0, 10, 10), + D2D1_EXTEND_MODE_WRAP, + D2D1_EXTEND_MODE_WRAP + ), + imageBrush + ); + } + + SafeRelease(&gridBrush); + SafeRelease(&originalTarget); + SafeRelease(&gridCommandList); + + return hr; +} + +// Discards device-specific resources which need to be recreated +// when a Direct3D device is lost. +void DemoApp::DiscardDeviceResources() +{ + SafeRelease(&m_swapChain); + SafeRelease(&m_d2dDevice); + SafeRelease(&m_d2dContext); + + SafeRelease(&m_customBitmap); + SafeRelease(&m_blackBrush); + SafeRelease(&m_linearGradientBrush); + SafeRelease(&m_gridPatternBrush); + + m_resourcesValid = false; +} + +// Draws the scene to a rendering device context or a printing device context. +// If the "printing" parameter is set, this function will add margins to +// the target and render the text across two pages. Otherwise, it fits the +// content to the target and renders the text in one block. +HRESULT DemoApp::DrawToContext( + _In_ ID2D1DeviceContext* d2dContext, + UINT pageNumber, + BOOL printing + ) +{ + HRESULT hr = S_OK; + + // Get the size of the displayed window. + D2D1_SIZE_U windowSize = CalculateD2DWindowSize(); + + // Compute the margin sizes. + FLOAT margin = PAGE_MARGIN_IN_DIPS; + + // Get the size of the destination context ("page"). + D2D1_SIZE_F targetSize = {0}; + if (printing) + { + targetSize.width = m_pageWidth - 2 * margin; + targetSize.height = m_pageHeight - 2 * margin; + } + else + { + targetSize.width = static_cast(windowSize.width); // assuming both in DIPs + targetSize.height = static_cast(windowSize.height); + } + + // Compute the size of the gridded background rectangle. + D2D1_SIZE_F frameSize = D2D1::SizeF( + targetSize.width, + FRAME_HEIGHT_IN_DIPS + ); + + // Compute the translation matrix that simulates scrolling or printing. + D2D1_MATRIX_3X2_F scrollTransform = printing ? + D2D1::Matrix3x2F::Translation(margin, margin) : + D2D1::Matrix3x2F::Translation(0.0f, static_cast(-m_currentScrollPosition)); + + d2dContext->BeginDraw(); + + d2dContext->SetTransform(scrollTransform); + + d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::White)); + + if (!printing || pageNumber == 1) + { + // Display geometries and text on screen. In printing case, display only on page 1. + + // Paint a grid background + d2dContext->FillRectangle( + D2D1::RectF(0.0f, 0.0f, frameSize.width, frameSize.height), + m_gridPatternBrush + ); + + // Draw a bitmap in the upper-left corner of the window. + D2D1_SIZE_F bitmapSize = m_customBitmap->GetSize(); + d2dContext->DrawBitmap( + m_customBitmap, + D2D1::RectF(0.0f, 0.0f, bitmapSize.width, bitmapSize.height) + ); + + // Draw a bitmap at the lower-right corner of the window. + d2dContext->DrawBitmap( + m_customBitmap, + D2D1::RectF( + frameSize.width - bitmapSize.width, + frameSize.height - bitmapSize.height, + frameSize.width, + frameSize.height + ) + ); + + // Draw the rotated "Hello world" message. + D2D1_MATRIX_3X2_F sidewaysTransform = D2D1::Matrix3x2F::Rotation( + 45, + D2D1::Point2F( + frameSize.width / 2, + frameSize.height / 2 + ) + ); + + d2dContext->SetTransform(sidewaysTransform * scrollTransform); + + static const WCHAR helloString[] = L"Hello, World!"; + + d2dContext->DrawText( + helloString, + ARRAYSIZE(helloString) - 1, + m_textFormat, + D2D1::RectF( + 0.0f, + 0.0f, + frameSize.width, + frameSize.height + ), + m_blackBrush + ); + + // Draw the hour glass in the bottom-left. + D2D1_MATRIX_3X2_F hourglassTransform = D2D1::Matrix3x2F::Translation(0.0f, frameSize.height - HOURGLASS_SIZE); + + d2dContext->SetTransform(hourglassTransform * scrollTransform); + + d2dContext->FillGeometry( + m_pathGeometry, + m_linearGradientBrush + ); + + // Draw the hour glass in the upper-right. + hourglassTransform = D2D1::Matrix3x2F::Translation(frameSize.width - HOURGLASS_SIZE, 0.0f); + + d2dContext->SetTransform(hourglassTransform * scrollTransform); + + d2dContext->FillGeometry( + m_pathGeometry, + m_linearGradientBrush + ); + } + + if (m_multiPageMode) + { + static const WCHAR longString[] = L"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tincidunt elementum diam. Sed semper ligula nec orci egestas sit amet tincidunt risus vulputate. Aliquam tempus quam nec neque facilisis vestibulum tristique est condimentum. Vestibulum ultrices tortor quis sapien dapibus non laoreet nunc posuere. Nullam semper, mi et consectetur mollis, dui ante vestibulum quam, quis fringilla diam purus nec urna. Nullam justo odio, posuere sed fringilla rutrum, ornare ac metus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum bibendum rutrum pharetra. Suspendisse eros est, porta ut adipiscing sed, rutrum quis augue. Ut lacinia, mi sit amet pretium dapibus, velit est scelerisque odio, ac viverra augue enim at eros. Donec consectetur, purus a ullamcorper venenatis, risus libero placerat ligula, et rutrum est justo at orci. Fusce fringilla tristique iaculis. Nulla facilisi. Maecenas et libero augue, sit amet luctus nisl.\r\n\r\nPellentesque ac est ac est mattis venenatis vitae sit amet ligula. Proin pharetra erat vel urna sagittis sed tincidunt est feugiat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed vitae eleifend massa. In ac orci turpis. Nam in erat nunc, vel rhoncus mauris. Ut fermentum, urna ac commodo tincidunt, orci enim consequat sem, ut fringilla enim quam non diam. Proin et ipsum nisi, sit amet ultricies nulla. Suspendisse eu dolor metus, ac consectetur ligula. Maecenas at est ligula.\r\n\r\nMauris sagittis, ligula sit amet vestibulum facilisis, lacus lorem porta neque, nec tristique leo mi vestibulum erat. Cras luctus sollicitudin nulla sed egestas. Aenean pellentesque suscipit sapien, vitae mollis sapien vehicula et. Proin feugiat leo et nulla porttitor facilisis. Nullam a lacus lorem. Praesent vitae mi dui, sit amet placerat mauris. Maecenas iaculis lacinia tellus sit amet egestas. Nam a metus orci. Cras non neque eget massa hendrerit accumsan a a tortor. Phasellus lacinia enim quam. Phasellus tristique suscipit nibh, sed molestie orci eleifend sed. Praesent lobortis tortor non mi ultrices euismod ut ac lectus. Quisque laoreet facilisis diam quis aliquam. Phasellus at quam non felis pretium mollis. Fusce vel posuere ipsum. Sed gravida tortor justo, ac volutpat velit.\r\n\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vitae convallis ipsum. Aliquam mauris dui, imperdiet eget porttitor ac, bibendum ac sapien. Praesent ut dignissim sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla id sapien facilisis nisi tristique venenatis. Donec vitae mauris sem. Sed condimentum erat tortor, sit amet commodo nibh. Nam euismod, magna et cursus auctor, enim dui condimentum felis, at aliquet ligula tellus ac est. Aenean viverra, urna at adipiscing dignissim, diam dui blandit sem, varius mollis enim ante sit amet ante. Curabitur lobortis condimentum odio non ultricies. Maecenas lorem elit, laoreet ut semper vel, egestas vel ipsum. Etiam adipiscing facilisis libero, sit amet placerat nisi aliquam id. Vestibulum fermentum quam a nisl semper gravida. Aliquam vestibulum interdum turpis. Pellentesque nunc nulla, aliquam vel consequat eu, aliquam vitae justo. Praesent iaculis, urna at ullamcorper placerat, neque lacus accumsan velit, eu mollis lacus leo nec nisl. Nulla massa risus, tincidunt vitae rhoncus et, feugiat a turpis. Phasellus orci quam, ultricies eu sollicitudin vel, vulputate eu lectus. Etiam quis velit ipsum, in rhoncus justo."; + static const UINT totalChars = ARRAYSIZE(longString) - 1; + static const UINT numberOfCharsFirstPage = 955; + + d2dContext->SetTransform(scrollTransform); + + if (printing) + { + // Lay out the text in parts, some on the first page, after + // the gridded rectangle, then some on the second page. + // A real application would contain much more robust layout logic. + // Here we simply render the first 955 characters on the first page and + // the remaining characters on the second page. + + if (pageNumber == 1) + { + d2dContext->DrawText( + longString, + numberOfCharsFirstPage, + m_smallTextFormat, + D2D1::RectF( + 0.0f, + frameSize.height + 5.0f, + frameSize.width, + targetSize.height + ), + m_blackBrush + ); + } + else if (pageNumber == 2) + { + d2dContext->DrawText( + longString + numberOfCharsFirstPage, + totalChars - numberOfCharsFirstPage, + m_smallTextFormat, + D2D1::RectF( + 0.0f, + 0.0f, + frameSize.width, + targetSize.height + ), + m_blackBrush + ); + } + } + else + { + // Lay out the text in a single, long rectangle. + d2dContext->DrawText( + longString, + totalChars, + m_smallTextFormat, + D2D1::RectF( + 0.0f, + frameSize.height + 5.0f, + targetSize.width, + targetSize.height + ), + m_blackBrush + ); + } + } + + hr = d2dContext->EndDraw(); + + return hr; +} + + +// Called whenever the application needs to display the client +// window. Draws a 2D scene onto the rendering device context. +// Note that this function will automatically discard device-specific +// resources if the Direct3D device disappears during function +// invocation and will recreate the resources the next time it's +// invoked. +HRESULT DemoApp::OnRender() +{ + HRESULT hr = S_OK; + + if (!m_resourcesValid) + { + hr = CreateDeviceResources(); + } + + if (SUCCEEDED(hr)) + { + // Render the scene on the device context tied to + // the swap chain (i.e. to the screen). + hr = DrawToContext(m_d2dContext, 1, FALSE); // FALSE specifies drawing to screen. + } + + if (SUCCEEDED(hr)) + { + // Present the swap chain immediately + hr = m_swapChain->Present(0, 0); + } + + if (hr == D2DERR_RECREATE_TARGET || hr == DXGI_ERROR_DEVICE_REMOVED) + { + hr = S_OK; + // Recreate device resources then force repaint. + DiscardDeviceResources(); + InvalidateRect(m_d2dHwnd, nullptr, FALSE); + } + + return hr; +} + +// Called whenever the application receives a keystroke (a +// WM_CHAR message). Starts printing or toggles multi-page +// mode, depending on the key pressed. +void DemoApp::OnChar(SHORT key) +{ + if ((key == 'p') || (key == 'P')) + { + OnPrint(); + } + else if (key == '\t') + { + ToggleMultiPageMode(); + } +} + +// Switches the application between single-page and multi-page mode. +void DemoApp::ToggleMultiPageMode() +{ + m_multiPageMode = !m_multiPageMode; + InvalidateRect(m_d2dHwnd, nullptr, FALSE); +} + +// Called whenever the application begins a print job. Initializes +// the printing subsystem, draws the scene to a printing device +// context, and commits the job to the printing subsystem. +HRESULT DemoApp::OnPrint() +{ + HRESULT hr = S_OK; + + if (!m_resourcesValid) + { + hr = CreateDeviceResources(); + } + + if (SUCCEEDED(hr)) + { + // Initialize printing-specific resources and prepare the + // printing subsystem for a job. + hr = InitializePrintJob(); + } + + ID2D1DeviceContext* d2dContextForPrint = nullptr; + if (SUCCEEDED(hr)) + { + // Create a D2D Device Context dedicated for the print job. + hr = m_d2dDevice->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + &d2dContextForPrint + ); + } + + if (SUCCEEDED(hr)) + { + ID2D1CommandList* commandList = nullptr; + + for (INT pageIndex = 1; pageIndex <= (m_multiPageMode ? 2 : 1); pageIndex++) + { + hr = d2dContextForPrint->CreateCommandList(&commandList); + + // Create, draw, and add a Direct2D Command List for each page. + if (SUCCEEDED(hr)) + { + d2dContextForPrint->SetTarget(commandList); + hr = DrawToContext(d2dContextForPrint, pageIndex, TRUE); // TRUE specifies rendering for printing + commandList->Close(); + } + + if (SUCCEEDED(hr)) + { + hr = m_printControl->AddPage(commandList, D2D1::SizeF(m_pageWidth, m_pageHeight), nullptr); + } + + SafeRelease(&commandList); + } + + // Release the print device context. + SafeRelease(&d2dContextForPrint); + + // Send the job to the printing subsystem and discard + // printing-specific resources. + HRESULT hrFinal = FinalizePrintJob(); + + if (SUCCEEDED(hr)) + { + hr = hrFinal; + } + } + + if (hr == D2DERR_RECREATE_TARGET) + { + DiscardDeviceResources(); + } + + return hr; +} + +// Brings up a Print Dialog to collect user print +// settings, then creates and initializes a print +// control object properly for a new print job. +HRESULT DemoApp::InitializePrintJob() +{ + HRESULT hr = S_OK; + WCHAR messageBuffer[512] = {0}; + + // Bring up Print Dialog and receive user print settings. + PRINTDLGEX printDialogEx = {0}; + printDialogEx.lStructSize = sizeof(PRINTDLGEX); + printDialogEx.Flags = PD_HIDEPRINTTOFILE | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE | PD_USEDEVMODECOPIESANDCOLLATE; + printDialogEx.hwndOwner = m_parentHwnd; + printDialogEx.nStartPage = START_PAGE_GENERAL; + + HRESULT hrPrintDlgEx = PrintDlgEx(&printDialogEx); + + if (FAILED(hrPrintDlgEx)) + { + // Error occured. + StringCchPrintf( + messageBuffer, + ARRAYSIZE(messageBuffer), + L"Error 0x%4X occured during printer selection and/or setup.", + hrPrintDlgEx + ); + MessageBox(m_parentHwnd, messageBuffer, L"Message", MB_OK); + hr = hrPrintDlgEx; + } + else if (printDialogEx.dwResultAction == PD_RESULT_APPLY) + { + // User clicks the Apply button and later clicks the Cancel button. + // For simpicity, this sample skips print settings recording. + hr = E_FAIL; + } + else if (printDialogEx.dwResultAction == PD_RESULT_CANCEL) + { + // User clicks the Cancel button. + hr = E_FAIL; + } + + // Retrieve DEVNAMES from print dialog. + DEVNAMES* devNames = nullptr; + if (SUCCEEDED(hr)) + { + if (printDialogEx.hDevNames != nullptr) + { + devNames = reinterpret_cast(GlobalLock(printDialogEx.hDevNames)); + if (devNames == nullptr) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + else + { + hr = E_HANDLE; + } + } + + // Retrieve user settings from print dialog. + DEVMODE* devMode = nullptr; + PCWSTR printerName = nullptr; + if (SUCCEEDED(hr)) + { + printerName = reinterpret_cast(devNames) + devNames->wDeviceOffset; + + if (printDialogEx.hDevMode != nullptr) + { + devMode = reinterpret_cast(GlobalLock(printDialogEx.hDevMode)); // retrieve DevMode + + if (devMode) + { + // Must check corresponding flags in devMode->dmFields + if ((devMode->dmFields & DM_PAPERLENGTH) && (devMode->dmFields & DM_PAPERWIDTH)) + { + // Convert 1/10 of a millimeter DEVMODE unit to 1/96 of inch D2D unit + m_pageHeight = devMode->dmPaperLength / 254.0f * 96.0f; + m_pageWidth = devMode->dmPaperWidth / 254.0f * 96.0f; + } + else + { + // Use default values if the user does not specify page size. + m_pageHeight = PAGE_HEIGHT_IN_DIPS; + m_pageWidth = PAGE_WIDTH_IN_DIPS; + } + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + else + { + hr = E_HANDLE; + } + } + + // Convert DEVMODE to a job print ticket stream. + if (SUCCEEDED(hr)) + { + hr = GetPrintTicketFromDevmode( + printerName, + devMode, + devMode->dmSize + devMode->dmDriverExtra, // Size of DEVMODE in bytes, including private driver data. + &m_jobPrintTicketStream + ); + } + + // Create a factory for document print job. + IPrintDocumentPackageTargetFactory* documentTargetFactory = nullptr; + if (SUCCEEDED(hr)) + { + hr = ::CoCreateInstance( + __uuidof(PrintDocumentPackageTargetFactory), + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&documentTargetFactory) + ); + } + + // Initialize the print subsystem and get a package target. + if (SUCCEEDED(hr)) + { + hr = documentTargetFactory->CreateDocumentPackageTargetForPrintJob( + printerName, // printer name + L"Direct2D desktop app printing sample", // job name + nullptr, // job output stream; when nullptr, send to printer + m_jobPrintTicketStream, // job print ticket + &m_documentTarget // result IPrintDocumentPackageTarget object + ); + } + + // Create a new print control linked to the package target. + if (SUCCEEDED(hr)) + { + hr = m_d2dDevice->CreatePrintControl( + m_wicFactory, + m_documentTarget, + nullptr, + &m_printControl + ); + } + + // Create and register a print job checker. + if (SUCCEEDED(hr)) + { + SafeRelease(&m_printJobChecker); + m_printJobChecker = new D2DPrintJobChecker; + hr = (m_printJobChecker != nullptr) ? S_OK : E_OUTOFMEMORY; + } + if (SUCCEEDED(hr)) + { + hr = m_printJobChecker->Initialize(m_documentTarget); + } + + // Release resources. + if (devMode) + { + GlobalUnlock(printDialogEx.hDevMode); + devMode = nullptr; + } + if (devNames) + { + GlobalUnlock(printDialogEx.hDevNames); + devNames = nullptr; + } + if (printDialogEx.hDevNames) + { + GlobalFree(printDialogEx.hDevNames); + } + if (printDialogEx.hDevMode) + { + GlobalFree(printDialogEx.hDevMode); + } + + SafeRelease(&documentTargetFactory); + + return hr; +} + +// Creates a print job ticket stream to define options for the next print job. +HRESULT DemoApp::GetPrintTicketFromDevmode( + _In_ PCTSTR printerName, + _In_reads_bytes_(devModesize) PDEVMODE devMode, + WORD devModesize, + _Out_ LPSTREAM* printTicketStream) +{ + HRESULT hr = S_OK; + HPTPROVIDER provider = nullptr; + + *printTicketStream = nullptr; + + // Allocate stream for print ticket. + hr = CreateStreamOnHGlobal(nullptr, TRUE, printTicketStream); + + if (SUCCEEDED(hr)) + { + hr = PTOpenProvider(printerName, 1, &provider); + } + + // Get PrintTicket from DEVMODE. + if (SUCCEEDED(hr)) + { + hr = PTConvertDevModeToPrintTicket(provider, devModesize, devMode, kPTJobScope, *printTicketStream); + } + + if (FAILED(hr) && printTicketStream != nullptr) + { + // Release printTicketStream if fails. + SafeRelease(printTicketStream); + } + + if (provider) + { + PTCloseProvider(provider); + } + + return hr; +} + + +// Commits the current print job to the printing subystem by +// closing the print control, and releases all printing- +// specific resources. +HRESULT DemoApp::FinalizePrintJob() +{ + // Send the print job to the print subsystem. (When this call + // returns, we are safe to release printing resources.) + HRESULT hr = m_printControl->Close(); + + SafeRelease(&m_jobPrintTicketStream); + SafeRelease(&m_printControl); + + return hr; +} + +// Called whenever the application window is resized. Recreates +// the swap chain with buffers sized to the new window. +void DemoApp::OnResize() +{ + if (m_d2dContext) + { + HRESULT hr = S_OK; + + D2D1_SIZE_U newSize = CalculateD2DWindowSize(); + + // Resize the child window. + MoveWindow(m_d2dHwnd, 0, 0, newSize.width, newSize.height, FALSE); + + // Remove the bitmap from rendering device context. + m_d2dContext->SetTarget(nullptr); + + // Resize the swap chain. + if (SUCCEEDED(hr)) + { + hr = m_swapChain->ResizeBuffers( + 0, + newSize.width, + newSize.height, + DXGI_FORMAT_B8G8R8A8_UNORM, + 0 + ); + } + + // Get a surface from the swap chain. + IDXGISurface* surface = nullptr; + if (SUCCEEDED(hr)) + { + hr = m_swapChain->GetBuffer( + 0, + IID_PPV_ARGS(&surface) + ); + } + + // Create a bitmap pointing to the surface. + ID2D1Bitmap1* bitmap = nullptr; + if (SUCCEEDED(hr)) + { + FLOAT dpiX, dpiY; + m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY); + D2D1_BITMAP_PROPERTIES1 properties = D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat( + DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_IGNORE + ), + dpiX, + dpiY + ); + hr = m_d2dContext->CreateBitmapFromDxgiSurface( + surface, + &properties, + &bitmap + ); + } + + // Set bitmap back onto device context. + if (SUCCEEDED(hr)) + { + m_d2dContext->SetTarget(bitmap); + } + + SafeRelease(&bitmap); + SafeRelease(&surface); + + ResetScrollBar(); + + // Force a repaint. + InvalidateRect(m_d2dHwnd, nullptr, FALSE); + } +} + +// The window message handler for the parent window. +LRESULT CALLBACK DemoApp::ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + + if (message == WM_CREATE) + { + LPCREATESTRUCT createStruct = reinterpret_cast(lParam); + DemoApp* demoApp = reinterpret_cast(createStruct->lpCreateParams); + + ::SetWindowLongPtrW( + hwnd, + GWLP_USERDATA, + reinterpret_cast(demoApp) + ); + + result = 1; + } + else + { + DemoApp* demoApp = reinterpret_cast( + static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)) + ); + + bool wasHandled = false; + + if (demoApp) + { + switch (message) + { + case WM_CHAR: + { + demoApp->OnChar(static_cast(wParam)); + } + result = 0; + wasHandled = true; + break; + + case WM_SIZE: + if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) + { + demoApp->OnResize(); + result = 0; + wasHandled = true; + } + break; + + case WM_VSCROLL: + { + demoApp->OnVScroll(wParam, lParam); + } + result = 0; + wasHandled = true; + break; + + case WM_MOUSEWHEEL: + { + demoApp->OnMouseWheel(wParam, lParam); + } + result = 0; + wasHandled = true; + break; + + case WM_CLOSE: + { + result = demoApp->OnClose(); + } + wasHandled = true; + break; + + case WM_DESTROY: + { + PostQuitMessage(0); + } + result = 1; + wasHandled = true; + break; + } + } + + if (!wasHandled) + { + result = DefWindowProc(hwnd, message, wParam, lParam); + } + } + + return result; +} + +// The window message handler for the child window (with the D2D content). +LRESULT CALLBACK DemoApp::ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + + if (message == WM_CREATE) + { + LPCREATESTRUCT createStruct = reinterpret_cast(lParam); + DemoApp* demoApp = reinterpret_cast(createStruct->lpCreateParams); + + ::SetWindowLongPtrW( + hwnd, + GWLP_USERDATA, + reinterpret_cast(demoApp) + ); + + result = 1; + } + else + { + DemoApp* demoApp = reinterpret_cast( + static_cast( + ::GetWindowLongPtrW(hwnd, GWLP_USERDATA) + ) + ); + + bool wasHandled = false; + + if (demoApp) + { + switch (message) + { + case WM_DISPLAYCHANGE: + { + InvalidateRect(hwnd, nullptr, FALSE); + } + result = 0; + wasHandled = true; + break; + + case WM_PAINT: + { + PAINTSTRUCT paintStruct; + BeginPaint(hwnd, &paintStruct); + demoApp->OnRender(); + EndPaint(hwnd, &paintStruct); + } + result = 0; + wasHandled = true; + break; + + case WM_DESTROY: + { + PostQuitMessage(0); + } + result = 1; + wasHandled = true; + break; + } + } + + if (!wasHandled) + { + result = DefWindowProc(hwnd, message, wParam, lParam); + } + } + + return result; +} + +// Creates a Direct2D bitmap from the specified file name. +HRESULT DemoApp::LoadBitmapFromFile( + _In_ ID2D1DeviceContext* d2dContext, + _In_ IWICImagingFactory* wicFactory, + _In_ PCWSTR uri, + UINT destinationWidth, + UINT destinationHeight, + _Outptr_ ID2D1Bitmap** bitmap + ) +{ + IWICBitmapDecoder* bitmapDecoder = nullptr; + HRESULT hr = wicFactory->CreateDecoderFromFilename( + uri, + nullptr, + GENERIC_READ, + WICDecodeMetadataCacheOnLoad, + &bitmapDecoder + ); + + IWICBitmapFrameDecode* frameDecode = nullptr; + if (SUCCEEDED(hr)) + { + // Create the initial frame. + hr = bitmapDecoder->GetFrame(0, &frameDecode); + } + + IWICFormatConverter* formatConverter = nullptr; + if (SUCCEEDED(hr)) + { + // Convert the image format to 32bppPBGRA + // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). + hr = wicFactory->CreateFormatConverter(&formatConverter); + } + + IWICBitmapScaler* bitmapScaler = nullptr; + if (SUCCEEDED(hr)) + { + if (destinationWidth == 0 && destinationHeight == 0) + { + // Don't scale the image. + hr = formatConverter->Initialize( + frameDecode, + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + nullptr, + 0.0f, + WICBitmapPaletteTypeMedianCut + ); + } + else + { + // If a new width or height was specified, create an + // IWICBitmapScaler and use it to resize the image. + UINT originalWidth; + UINT originalHeight; + hr = frameDecode->GetSize(&originalWidth, &originalHeight); + + if (SUCCEEDED(hr)) + { + if (destinationWidth == 0) + { + FLOAT scalar = static_cast(destinationHeight) / static_cast(originalHeight); + destinationWidth = static_cast(scalar * static_cast(originalWidth)); + } + else if (destinationHeight == 0) + { + FLOAT scalar = static_cast(destinationWidth) / static_cast(originalWidth); + destinationHeight = static_cast(scalar * static_cast(originalHeight)); + } + + hr = wicFactory->CreateBitmapScaler(&bitmapScaler); + + if (SUCCEEDED(hr)) + { + hr = bitmapScaler->Initialize( + frameDecode, + destinationWidth, + destinationHeight, + WICBitmapInterpolationModeCubic + ); + } + + if (SUCCEEDED(hr)) + { + hr = formatConverter->Initialize( + bitmapScaler, + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + nullptr, + 0.f, + WICBitmapPaletteTypeMedianCut + ); + } + } + } + } + + if (SUCCEEDED(hr)) + { + // Create a Direct2D bitmap from the WIC bitmap. + hr = d2dContext->CreateBitmapFromWicBitmap( + formatConverter, + nullptr, + bitmap + ); + } + + SafeRelease(&bitmapDecoder); + SafeRelease(&frameDecode); + SafeRelease(&formatConverter); + SafeRelease(&bitmapScaler); + + return hr; +} + +// Called when the application receives a WM_VSCROLL message is sent. +// Adjusts the application's scroll position so that subsequent renderings +// reveal a higher or lower section of the scene. +void DemoApp::OnVScroll(WPARAM wParam, LPARAM /* lParam */) +{ + INT newScrollPosition = m_currentScrollPosition; + + switch (LOWORD(wParam)) + { + case SB_LINEUP: + newScrollPosition -= 5; + break; + + case SB_LINEDOWN: + newScrollPosition += 5; + break; + + case SB_PAGEUP: + newScrollPosition -= static_cast(m_d2dContext->GetSize().height); + break; + + case SB_PAGEDOWN: + newScrollPosition += static_cast(m_d2dContext->GetSize().height); + break; + + case SB_THUMBTRACK: + { + SCROLLINFO scrollInfo = {0}; + scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; + BOOL succeeded = GetScrollInfo(m_parentHwnd, SB_VERT, &scrollInfo); + if (!succeeded) + { + Assert(succeeded); + return; + } + newScrollPosition = scrollInfo.nTrackPos; + } + break; + + default: + break; + } + + newScrollPosition = max(0, min(newScrollPosition, static_cast(m_scrollRange) - static_cast(m_d2dContext->GetSize().height))); + + m_currentScrollPosition = newScrollPosition; + + SCROLLINFO scrollInfo = {0}; + scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; + BOOL succeeded = GetScrollInfo(m_parentHwnd, SB_VERT, &scrollInfo); + if (!succeeded) + { + Assert(succeeded); + return; + } + + if (m_currentScrollPosition != scrollInfo.nPos) + { + scrollInfo.nPos = m_currentScrollPosition; + SetScrollInfo(m_parentHwnd, SB_VERT, &scrollInfo, TRUE); + + InvalidateRect(m_d2dHwnd, nullptr, FALSE); + } +} + +// Called when the mouse wheel is moved. Adjusts the application's +// scroll position. +void DemoApp::OnMouseWheel(WPARAM wParam, LPARAM /* lParam */) +{ + m_currentScrollPosition -= GET_WHEEL_DELTA_WPARAM(wParam); + m_currentScrollPosition = max(0, min(m_currentScrollPosition, static_cast(m_scrollRange) - static_cast(m_d2dContext->GetSize().height))); + + SCROLLINFO scrollInfo = {0}; + scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; + BOOL succeeded = GetScrollInfo(m_parentHwnd, SB_VERT, &scrollInfo); + if (!succeeded) + { + Assert(succeeded); + return; + } + + if (m_currentScrollPosition != scrollInfo.nPos) + { + scrollInfo.nPos = m_currentScrollPosition; + SetScrollInfo(m_parentHwnd, SB_VERT, &scrollInfo, TRUE); + + InvalidateRect(m_d2dHwnd, nullptr, FALSE); + } +} + +// Resets the scroll bar to represent the current size of the +// application window and the current scroll position. +void DemoApp::ResetScrollBar() +{ + INT scrollPos = static_cast(m_scrollRange - m_d2dContext->GetSize().height + 0.5); + m_currentScrollPosition = max(0, min(m_currentScrollPosition, scrollPos)); + + SCROLLINFO scrollInfo = {0}; + scrollInfo.cbSize = sizeof(scrollInfo); + scrollInfo.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE; + scrollInfo.nMin = 0; + scrollInfo.nMax = m_scrollRange; + scrollInfo.nPage = static_cast(m_d2dContext->GetSize().height); + scrollInfo.nPos = m_currentScrollPosition; + SetScrollInfo(m_parentHwnd, SB_VERT, &scrollInfo, TRUE); +} + +// Close the sample window after checking print job status. +LRESULT DemoApp::OnClose() +{ + bool close = true; + + if (m_printJobChecker != nullptr) + { + PrintDocumentPackageStatus status = m_printJobChecker->GetStatus(); + if (status.Completion == PrintDocumentPackageCompletion_InProgress) + { + int selection = MessageBox( + m_d2dHwnd, + L"Print job still in progress.\nYES to force to exit;\nNO to exit after print job is complete;\nCANCEL to return to sample.", + L"Sample exit error", + MB_YESNOCANCEL | MB_ICONSTOP + ); + switch (selection) + { + case IDYES: + // Force to exit. + break; + + case IDNO: + // Exit after print job is complete. + m_printJobChecker->WaitForCompletion(); + break; + + case IDCANCEL: + // Return to sample. + close = false; + break; + + default: + close = false; + break; + } + } + } + + if (close) + { + DestroyWindow(m_d2dHwnd); + DestroyWindow(m_parentHwnd); + } + + return close ? 0 : 1; +} diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.h b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.h new file mode 100644 index 00000000..31dfbf92 --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.h @@ -0,0 +1,195 @@ +//// 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 + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 7 or later. +#define WINVER 0x0800 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows 7 or later. +#define _WIN32_WINNT 0x0800 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef UNICODE +#define UNICODE +#endif + +// DirectX header files. +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "D2DPrintJobChecker.h" + +// SafeRelease inline function. +template inline void SafeRelease( + Interface** interfaceToRelease + ) +{ + if (*interfaceToRelease != nullptr) + { + (*interfaceToRelease)->Release(); + + (*interfaceToRelease) = nullptr; + } +} + +// Macros. +#ifndef Assert +#if defined(DEBUG) || defined(_DEBUG) || DBG +#define Assert(b) if (!(b)) { OutputDebugStringA("Assert: " #b "\n"); } +#else +#define Assert(b) +#endif // DEBUG || _DEBUG +#endif + +#ifndef HINST_THISCOMPONENT +EXTERN_C IMAGE_DOS_HEADER __ImageBase; +#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) +#endif + +// The main class for this sample application. +class DemoApp +{ +public: + DemoApp(); + + ~DemoApp(); + + HRESULT Initialize(); + + void RunMessageLoop(); + +private: + HRESULT CreateDeviceIndependentResources(); + + HRESULT CreateDeviceContext(); + + HRESULT CreateDeviceResources(); + + void DiscardDeviceResources(); + + HRESULT CreateGridPatternBrush( + _Outptr_ ID2D1ImageBrush** imageBrush + ); + + HRESULT OnRender(); + + HRESULT OnPrint(); + + HRESULT InitializePrintJob(); + + HRESULT GetPrintTicketFromDevmode( + _In_ PCTSTR printerName, + _In_reads_bytes_(devModeSize) PDEVMODE devMode, + WORD devModeSize, + _Out_ LPSTREAM* printTicketStream + ); + + HRESULT FinalizePrintJob(); + + HRESULT DrawToContext( + _In_ ID2D1DeviceContext* d2dContext, + UINT pageNumber, // 1-based page number + BOOL printing + ); + + void OnChar( + SHORT key + ); + + void ToggleMultiPageMode(); + + void OnResize(); + + void OnVScroll( + WPARAM wParam, + LPARAM lParam + ); + + void ResetScrollBar(); + + void OnMouseWheel( + WPARAM wParam, + LPARAM lParam + ); + + D2D1_SIZE_U CalculateD2DWindowSize(); + + static LRESULT CALLBACK ParentWndProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam + ); + + static LRESULT CALLBACK ChildWndProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam + ); + + static HRESULT LoadBitmapFromFile( + _In_ ID2D1DeviceContext* d2dContext, + _In_ IWICImagingFactory* wicFactory, + _In_ PCWSTR uri, + UINT destinationWidth, + UINT destinationHeight, + _Outptr_ ID2D1Bitmap** bitmap + ); + + LRESULT OnClose(); + +private: + bool m_resourcesValid; // Whether or not the device-dependent resources are ready to use. + + HWND m_parentHwnd; // The outer window containing the scroll bar and inner window. + HWND m_d2dHwnd; // The inner window onto which D2D renders. + bool m_multiPageMode; // Whether or not the application is currently in multi-page mode. + static const UINT m_scrollRange = 1100; // The maximum distance the user is allowed to scroll. + + // The current distance between the top of the scene and the top + // of the displayed rectangle. + INT m_currentScrollPosition; + + // Device-independent resources. + ID2D1Factory1* m_d2dFactory; + IWICImagingFactory2* m_wicFactory; + IDWriteFactory* m_dwriteFactory; + IDWriteTextFormat* m_textFormat; + IDWriteTextFormat* m_smallTextFormat; + ID2D1PathGeometry* m_pathGeometry; + + // Device-dependent resources. + IDXGISwapChain* m_swapChain; + ID2D1Device* m_d2dDevice; + ID2D1DeviceContext* m_d2dContext; + ID2D1LinearGradientBrush* m_linearGradientBrush; + ID2D1SolidColorBrush* m_blackBrush; + ID2D1ImageBrush* m_gridPatternBrush; + ID2D1Bitmap* m_customBitmap; + + // Printing-specific resources. + IStream* m_jobPrintTicketStream; + ID2D1PrintControl* m_printControl; + IPrintDocumentPackageTarget* m_documentTarget; + D2DPrintJobChecker* m_printJobChecker; + + // Page size (in DIPs). + float m_pageHeight; + float m_pageWidth; +}; diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.sln b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.sln new file mode 100644 index 00000000..382e6b7a --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D2DPrintingFromDesktopApps", "D2DPrintingFromDesktopApps.vcxproj", "{CCFA0DAB-ED82-44FD-952C-AC5F6825D905}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Debug|Win32.ActiveCfg = Debug|Win32 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Debug|Win32.Build.0 = Debug|Win32 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Debug|x64.ActiveCfg = Debug|x64 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Debug|x64.Build.0 = Debug|x64 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Release|Win32.ActiveCfg = Release|Win32 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Release|Win32.Build.0 = Release|Win32 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Release|x64.ActiveCfg = Release|x64 + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.vcxproj b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.vcxproj new file mode 100644 index 00000000..0f86c9ee --- /dev/null +++ b/Samples/D2DPrintingFromDesktopApps/cpp/D2DPrintingFromDesktopApps.vcxproj @@ -0,0 +1,129 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + {CCFA0DAB-ED82-44FD-952C-AC5F6825D905} + D2DPrintingFromDesktopApps + + + + Application + true + v120 + MultiByte + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + Disabled + + + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;d2d1.lib;dwrite.lib;d3d11.lib;Prntvpt.lib;%(AdditionalDependencies) + + + + + Disabled + + + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;d2d1.lib;dwrite.lib;d3d11.lib;Prntvpt.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + true + + + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;d2d1.lib;dwrite.lib;d3d11.lib;Prntvpt.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + true + + + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;d2d1.lib;dwrite.lib;d3d11.lib;Prntvpt.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/D2DPrintingFromDesktopApps/cpp/sampleimage.jpg b/Samples/D2DPrintingFromDesktopApps/cpp/sampleimage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..981b67d8e0d1f293d9543a5902fd2b422460b482 GIT binary patch literal 158728 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%0DiX&ZNF)$++xOcbPfoho8Xs!GK?cgV zO`s-*M~o?cpj{05YEA!TTFGdUeQv_(V{nzhCtv>73Z!GaXr;x6GXd@OgwnS#oqC2H z3Jp-8`)0X<1;&7E!2xQ}#i}%rhKh=VP@lVm%49rMfZ^E`AK&S@{kXkXL2o6=wH=BF z(80uu@!UrUE4;)lKON8O@v8)xMEsfkV+~=q8J=WXd^9b`@Mdf+ZkSVvVaNhd#tG;# zY9Gj<4v_7v?)>1BX<%pqFa34lDSqWODM7CUNW{n4L=`p(MD(t7ae*Fa?)SNz--U`G z+i;4JCN_6I`323dY_-Jprgfjw0>G*pr|+?~=c7nc(Iaz6k}Adt%vvFWlSIyMIti))RCjuK zR|6DFHc3nZu6ktu_G9gn*s(Ft>asud8{WkJ{(zxZq-I(+b8-1?3wM>&UIdZUGqf8? zj(-P3@;I;*$xbu12&$>OHT22xfm7r=w4!!f3X+AqS>l<~Ada z@+`XPu0M!Z{Bi*{hEzT4uz$8Lt!JD4ffwTaUZ@5^k9P=3%`5)-zri0?`DdbNj4AYG zMW5Lv4s5bd@V35MKS_bzwb~0%+B{e!E`{^vHix zU(cg@`t*_UNwwUbYtMzo!r&<6%9$*MpD70Q-D@zKU3GmG4sUlkQOuu9u_5Phhwasqlg zIf512a|PNvbp$<`@SohMzF9+)pVE3cgffc7`>&8DH*VsniULTLMB&K`R ztSg8zW({StrzG{_Vq!>R1IglsnY{`X6BKZz!{dU=O=GrI?$~5s1nlV7W3;C~F-B@$ zk*b(NyUJR@3D->ew+oyZY_IU(c5I*hR+B zFwFU`6I6drink-7DP*&Z=H%`q(Z}+k*#7bWhi7qqPgs<35@5h4v!-z7IvgAUjlIX? zKSJ%f`|~aJ*vf~kcBG@d)roy6*JrPsnoSd=Gz^Li`tvR;3hyD`v1HRlVM8WMk-;Xl zpwPMyZ%?P~{I-p--QMt={BWR#x`UbVO1*(ne)6J212DEJez21?Ze7)W2D`<#mN45* zI(TEMPO8X9r`5NP=KOtvg$Izay`b{}Gp(r``Jr1I+G^5eH^=}u4!jXBqDq5xikIn*;ZM@a0~mnLIlJEIN6MX!~$GKP+u zbirdj%j)zw2ykOey1=$HYiO@qyF984vfGl$;-C-V%7oEp`d5VwQ!@lWgOZhYORP-p zjMBciW(gX17n48|e`bHj*BcdV9zTu2ad``5p&Kq2WXbR3vZ>DoSYXqhEuxa~^gq%s zw9X*zr7I&YU#z4#`eSoL%6rpi4<+aSvai&>htg#&hrL1QWE7P^#kzhSwLxd_&EQEo zp6N=KSIU{77haAiJVP5DVK5Vu$!xI!6(hLekY*TQyO+;s{F{b{xr$^5Ne!~|bN1k) z=cQ|{k_!E|BcAD{UbQdAuNtNaAWq6j*9r{l?ZR@SEJ9)4;MxC*fZd9A{kTS#I(uV# zzV0STL!=O(2)V@^MGDQh`2e-hWASe zgR2@A*r3wN^WPj1=@IUt?klDmzS|HCnYgV}MEP=>6LbfgBBzzxH%tR<6#!-uyuANP znw;vVLY@?{8}0Shubr3$#)Z^X#xu~MK=tNlj*CXx*JS&ujLfT32WC+3gN;*qv$Y_g z-m2#fWQTyP<+i}IUK^-}IfoTL*|Fh{09+w6+ zUOKpnwe+%-f^Sa&t$9$mUhv;rfoP4Co{8W5b!?RDuyT@KgP?P(}b4SVrvLlo}~Zzy6evluK*c6YwGxZ@1g=|8p1O6NL80RE{e zJ$xGUlM2QIp~~z(ghSchSQ9m#N8)td#Gv*-icn5Cc}-DKQF{}>S!LC!W!{v%m!mG6 z3ak9N%Kwy;_;A3ciz1_i>NuMwC6U54xz5M2v9-085?RT=R;?&cvT>Z#&LD(3t{ zF;hc>ibw38U3%O#HH<8225LCHPd2ZF5XJoL`)0$UNdb^3xWsxoHHFV5CO*|^EsJVz z5(rvu+!FE7`;&YkAJrj$uY)V(G^CKc8QB?B1k7-D@LIw5f8OlfA`A>3_BH&2a z^CkVZwYv2<3KozZme)0T<4*G(N4l_w${~JX=jyo($t=3lqPC0Qn+Y|Rgae(k3jcpf zaFJ5gj6c6+_#21%*f7=jNIu0QHgg2miCnl=CX99XeW61nPSHmvt-Aax(iV0 zv(w?G1CQFR9{kBT^6=Go>8AwWhY5;=T?%`fYr~R;zREZ1T;N#peMW=Ep*D7Q|GsL~>|nD09Z)K^z}mXcuP7uG z`lQ6ygdZ%&lU`nOczvSo_BFe!wtu|7r?6LXi%HnjYxL>Bfe(L=FW)(>AAM^sU)lB3 z!tG;UcZRt3IH;OK*4uqNg8(tfy&I0c)izSy2vGOeX%$}#?WBLuwux?eY%xtfNY~w} zp>KcY*+-AzeC&=LF|a=}*j6sI?NzRU&{m0F;`s}KQ<|v<=ej*r@~u5%Z@1hGtp8YM zLHZPU^q=ZS8>bq!=;3^Wv8l|>8)cIu}>}}0-wxRx2gUm#Y7DckTnlT~nBOGq!;Yr#Uni)EE z7a>-8XzDik-sGLVM$* **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/DCompV2BackfaceandD2DBatching/cpp/Application.cpp b/Samples/DCompV2BackfaceandD2DBatching/cpp/Application.cpp new file mode 100644 index 00000000..e72880de --- /dev/null +++ b/Samples/DCompV2BackfaceandD2DBatching/cpp/Application.cpp @@ -0,0 +1,1227 @@ +// 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 "Application.h" +#include + +Application *Application::_application = nullptr; + +// Main window procedure +LRESULT CALLBACK Application::WindowProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + LRESULT result = 0; + + switch (msg) + { + case WM_POINTERUP: + { + result = _application->OnPointerUp(lparam); + break; + } + + case WM_CLOSE: + { + result = _application->OnClose(); + break; + } + + case WM_DESTROY: + { + result = _application->OnDestroy(); + break; + } + + default: + { + result = DefWindowProc(hWnd, msg, wparam, lparam); + break; + } + } + + return result; +} + +// Provides the entry point to the application and defines client size +Application::Application(HINSTANCE hInstance) : + _hInstance(hInstance), + _hWnd(NULL), + _hWndClientWidth(512), + _hWndClientHeight(512) +{ + _application = this; +} + +Application::~Application() +{ + _application = nullptr; +} + +// Runs the application +int Application::Run() +{ + int result = 0; + + if (SUCCEEDED(BeforeEnteringMessageLoop())) + { + result = EnterMessageLoop(); + } + + AfterLeavingMessageLoop(); + + return result; +} + +// Initialization for the application window, devices and +// DComp resources before entering the message loop +HRESULT Application::BeforeEnteringMessageLoop() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = CreateMainWindow(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateD3DDevice(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateD2DDevice(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDWriteFactory(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompDevice(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompVisualTree(); + } + + if (SUCCEEDED(hr)) + { + hr = ShowMainWindow(); + } + + if (SUCCEEDED(hr)) + { + hr = EnableMouseAsPointerDevice(); + } + + return hr; +} + +// Message loop +int Application::EnterMessageLoop() +{ + MSG message = { 0 }; + + while (GetMessage(&message, NULL, 0, 0)) + { + TranslateMessage(&message); + DispatchMessage(&message); + } + + return static_cast(message.wParam); +} + +// Destroys the application window, devices and DComp resources +void Application::AfterLeavingMessageLoop() +{ + DestroyDCompVisualTree(); + + DestroyDCompDevice(); + + DestroyDWriteFactory(); + + DestroyD2DDevice(); + + DestroyD3DDevice(); + + DestroyMainWindow(); +} + +// Creates the application window +HRESULT Application::CreateMainWindow() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + WNDCLASSEX wcex = { 0 }; + + wcex.cbSize = sizeof (wcex); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = Application::WindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = _hInstance; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = static_cast(GetStockObject(WHITE_BRUSH)); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = L"MainWindowClass"; + wcex.hIconSm = NULL; + + hr = (RegisterClassEx(&wcex) == 0) ? E_FAIL : S_OK; + + ShowMessageBoxIfFailed(hr, L"RegisterClassEx"); + } + + if (SUCCEEDED(hr)) + { + RECT windowRect = { 0, 0, _hWndClientWidth, _hWndClientHeight }; + + hr = (AdjustWindowRect(&windowRect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE) == FALSE) ? E_FAIL : S_OK; + + ShowMessageBoxIfFailed(hr, L"AdjustWindowRect"); + + if (SUCCEEDED(hr)) + { + _hWnd = CreateWindowExW( + 0, + L"MainWindowClass", + L"DirectComposition", + WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + 0, + 0, + windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top, + NULL, + NULL, + _hInstance, + nullptr); + + hr = (_hWnd == NULL) ? E_FAIL : S_OK; + + ShowMessageBoxIfFailed(hr, L"CreateWindowExW"); + } + } + + return hr; +} + +// Shows the application window +HRESULT Application::ShowMainWindow() +{ + HRESULT hr = (_hWnd == NULL) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + ShowWindow(_hWnd, SW_SHOW); + UpdateWindow(_hWnd); + } + + return hr; +} + +// Destroys the application window +void Application::DestroyMainWindow() +{ + if (_hWnd != NULL) + { + DestroyWindow(_hWnd); + _hWnd = NULL; + } +} + +// Enables mouse pointer device for hit-testing +HRESULT Application::EnableMouseAsPointerDevice() +{ + HRESULT hr = S_OK; + + if (!IsMouseInPointerEnabled()) + { + hr = (EnableMouseInPointer(TRUE) == FALSE) ? E_FAIL : S_OK; + } + + return hr; +} + +HRESULT Application::CreateD3DDevice() +{ + HRESULT hr = (_d3dDevice != nullptr) ? E_UNEXPECTED : S_OK;; + + ShowMessageBoxIfFailed(hr, L"(_d3dDevice != nullptr)"); + + if (SUCCEEDED(hr)) + { + D3D_DRIVER_TYPE driverTypes [] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP + }; + + D3D_FEATURE_LEVEL featureLevels [] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + + D3D_FEATURE_LEVEL featureLevelSupported; + + for (int i = 0; i < sizeof(driverTypes) / sizeof(driverTypes[0]); ++i) + { + Microsoft::WRL::ComPtr d3dDevice; + + hr = ::D3D11CreateDevice( + nullptr, + driverTypes[i], + NULL, + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + featureLevels, + sizeof(featureLevels) / sizeof(featureLevels[0]), + D3D11_SDK_VERSION, + &d3dDevice, + &featureLevelSupported, + nullptr); + + ShowMessageBoxIfFailed(hr, L"::D3D11CreateDevice"); + + if (SUCCEEDED(hr)) + { + _d3dDevice = d3dDevice.Detach(); + + break; + } + } + } + + return hr; +} + +void Application::DestroyD3DDevice() +{ + _d3dDevice = nullptr; +} + +HRESULT Application::CreateD2DDevice() +{ + HRESULT hr = ((_d3dDevice == nullptr) || (_d2dDevice != nullptr)) ? E_UNEXPECTED : S_OK; + + ShowMessageBoxIfFailed(hr, L"((_d3dDevice == nullptr) || (_d2dDevice != nullptr))"); + + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr dxgiDevice; + + hr = _d3dDevice.As(&dxgiDevice); + + ShowMessageBoxIfFailed(hr, L"_d3dDevice->QueryInterface"); + + if (SUCCEEDED(hr)) + { + hr = ::D2D1CreateDevice(dxgiDevice.Get(), nullptr, &_d2dDevice); + + ShowMessageBoxIfFailed(hr, L"::D2D1CreateDevice"); + } + } + + return hr; +} + +void Application::DestroyD2DDevice() +{ + _d2dDevice = nullptr; +} + +/*----Begin calling DirectComposition APIs----*/ +HRESULT Application::CreateDWriteFactory() +{ + HRESULT hr = (_dwriteFactory != nullptr) ? E_UNEXPECTED : S_OK; + + ShowMessageBoxIfFailed(hr, L"(_dwriteFactory != nullptr)"); + + if (SUCCEEDED(hr)) + { + hr = ::DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory) , reinterpret_cast(_dwriteFactory.GetAddressOf())); + + ShowMessageBoxIfFailed(hr, L"::DWriteCreateFactory"); + } + + return hr; +} + +void Application::DestroyDWriteFactory() +{ + _dwriteFactory = nullptr; +} + +// Initializing DirectComposition device using a D2D device object +// Pointing to a D2D device object is required for D2D batching +HRESULT Application::CreateDCompDevice() +{ + HRESULT hr = ((_d2dDevice == nullptr) || (_dcompDevice != nullptr)) ? E_UNEXPECTED : S_OK; + + ShowMessageBoxIfFailed(hr, L"((_d2dDevice == nullptr) || (_dcompDevice != nullptr))"); + + if (SUCCEEDED(hr)) + { + hr = ::DCompositionCreateDevice2(_d2dDevice.Get(), __uuidof(IDCompositionDesktopDevice) , reinterpret_cast(_dcompDevice.GetAddressOf())); + + ShowMessageBoxIfFailed(hr, L"::DCompositionCreateDevice2"); + } + + return hr; +} + +void Application::DestroyDCompDevice() +{ + _dcompDevice = nullptr; +} + +// Calling functions to build DirectComposition visual tree, creating surfaces and setting visual properties +HRESULT Application::CreateDCompVisualTree() +{ + HRESULT hr = ((_hWnd == NULL) || (_dcompDevice == nullptr)) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + hr = CreateDCompTarget(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompRootVisual(); + } + + if (SUCCEEDED(hr)) + { + hr = BindDCompRootVisualToTarget(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompTextVisual(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompTextSurface(); + } + + if (SUCCEEDED(hr)) + { + hr = DrawDCompTextSurface(); + } + + if (SUCCEEDED(hr)) + { + hr = BindDCompTextSurfaceToVisual(); + } + + if (SUCCEEDED(hr)) + { + hr = SetOffsetOnDCompTextVisual(); + } + + if (SUCCEEDED(hr)) + { + hr = AddDCompTextVisualToRootVisual(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompTileVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompTileSurfaces(); + } + + if (SUCCEEDED(hr)) + { + hr = DrawDCompTileSurfaces(); + } + + if (SUCCEEDED(hr)) + { + hr = BindDCompTileSurfacesToVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = SetOffsetOnDCompTileVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = SetBackfaceVisibilityOnDCompTileVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = AddDCompTileVisualsToRootVisual(); + } + + if (SUCCEEDED(hr)) + { + hr = CommitDCompDevice(); + } + + return hr; +} + +void Application::DestroyDCompVisualTree() +{ + DestroyDCompTileSurfaces(); + + DestroyDCompTileVisuals(); + + DestroyDCompTextSurface(); + + DestroyDCompTextVisual(); + + DestroyDCompRootVisual(); + + DestroyDCompTarget(); +} + +// Creating DirectComposition Target which is associated to an HWND +HRESULT Application::CreateDCompTarget() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->CreateTargetForHwnd(_hWnd, TRUE, &_dcompTarget); + + ShowMessageBoxIfFailed(hr, L"_dcompDevice->CreateTargetForHwnd"); + } + + return hr; +} + +void Application::DestroyDCompTarget() +{ + _dcompTarget = nullptr; +} + +/*----Creating visuals----*/ +HRESULT Application::CreateDCompRootVisual() +{ + HRESULT hr = ((_dcompDevice == nullptr) || (_dcompRootVisual != nullptr)) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->CreateVisual(&_dcompRootVisual); + + ShowMessageBoxIfFailed(hr, L"_dcompDevice->CreateVisual"); + } + + return hr; +} + +void Application::DestroyDCompRootVisual() +{ + _dcompRootVisual = nullptr; +} + +// Creating visual which contains sample description +HRESULT Application::CreateDCompTextVisual() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->CreateVisual(&_dcompTextVisual); + + ShowMessageBoxIfFailed(hr, L"_dcompDevice->CreateVisual"); + } + + return hr; +} + +void Application::DestroyDCompTextVisual() +{ + _dcompTextVisual = nullptr; +} + +// Creating surface for DCompTextVisual +HRESULT Application::CreateDCompTextSurface() +{ + HRESULT hr = S_OK; + + UINT dcompTextSurfaceWidth = 7 * _hWndClientWidth / 8; + UINT dcompTextSurfaceHeight = 2 * _hWndClientHeight / 8; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->CreateSurface(dcompTextSurfaceWidth, dcompTextSurfaceHeight, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ALPHA_MODE_IGNORE, &_dcompTextSurface); + + ShowMessageBoxIfFailed(hr, L"_dcompDevice->CreateSurface"); + } + + return hr; +} + +void Application::DestroyDCompTextSurface() +{ + _dcompTextSurface = nullptr; +} + +// Creating tile visuals +HRESULT Application::CreateDCompTileVisuals() +{ + HRESULT hr = S_OK; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompDevice->CreateVisual(&_dcompTileVisuals[i]); + + ShowMessageBoxIfFailed(hr, L"_dcompDevice->CreateVisual"); + } + + return hr; +} + +void Application::DestroyDCompTileVisuals() +{ + for (int i = 0; i < 4; ++i) + { + _dcompTileVisuals[i] = nullptr; + } +} + +// Creating surfaces for the DComp tile visuals +HRESULT Application::CreateDCompTileSurfaces() +{ + HRESULT hr = S_OK; + + UINT dcompTileSurfaceWidth = 2 * _hWndClientWidth / 8; + UINT dcompTileSurfaceHeight = 2 * _hWndClientHeight / 8; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompDevice->CreateSurface(dcompTileSurfaceWidth, dcompTileSurfaceHeight, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ALPHA_MODE_IGNORE, &_dcompTileSurfaces[i]); + + ShowMessageBoxIfFailed(hr, L"dcompTileSurfaceFactory->CreateSurface"); + } + + return hr; +} + +void Application::DestroyDCompTileSurfaces() +{ + for (int i = 0; i < 4; ++i) + { + _dcompTileSurfaces[i] = nullptr; + } +} +/*----End of creating visuals----*/ + +/*----Creating surfaces----*/ +// Defining text properties and drawing text into the DComp text surface +HRESULT Application::DrawDCompTextSurface() +{ + HRESULT hr = S_OK; + + UINT dcompTextSurfaceWidth = 7 * _hWndClientWidth / 8; + UINT dcompTextSurfaceHeight = 2 * _hWndClientHeight / 8; + + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr d2dDeviceContext; + POINT updateOffset = { 0 }; + + hr = _dcompTextSurface->BeginDraw(nullptr, __uuidof(ID2D1DeviceContext) , reinterpret_cast(d2dDeviceContext.GetAddressOf()), &updateOffset); + + ShowMessageBoxIfFailed(hr, L"_dcompTextSurface->BeginDraw"); + + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr d2dBackgroundBrush; + + if (SUCCEEDED(hr)) + { + hr = d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &d2dBackgroundBrush); + + ShowMessageBoxIfFailed(hr, L"d2dDeviceContext->CreateSolidColorBrush"); + } + + Microsoft::WRL::ComPtr d2dForegroundBrush; + + if (SUCCEEDED(hr)) + { + hr = d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &d2dForegroundBrush); + + ShowMessageBoxIfFailed(hr, L"d2dDeviceContext->CreateSolidColorBrush"); + } + + Microsoft::WRL::ComPtr dwriteTextFormat; + + if (SUCCEEDED(hr)) + { + hr = _dwriteFactory->CreateTextFormat(L"Verdana", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-us", &dwriteTextFormat); + + ShowMessageBoxIfFailed(hr, L"dwriteFactory->CreateTextFormat"); + } + + if (SUCCEEDED(hr)) + { + hr = dwriteTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_JUSTIFIED); + + ShowMessageBoxIfFailed(hr, L"dwriteTextFormat->SetTextAlignment"); + } + + if (SUCCEEDED(hr)) + { + hr = dwriteTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR); + + ShowMessageBoxIfFailed(hr, L"dwriteTextFormat->SetParagraphAlignment"); + } + + if (SUCCEEDED(hr)) + { + const wchar_t dcompTileSurfaceText [] = L"This sample demonstrates how to use DirectComposition to apply backface visibility and utilize performance optmization feature known as D2D Batching. Tiles 2 & 3 show backface visible while 1 & 4 show the backface hidden. \n\n" + L"Step 1. Tap or click any tile below \n" + L"Step 2. Reset by selecting background \n"; + + D2D1_RECT_F dcompTextSurfaceRect = D2D1::RectF( + updateOffset.x + 0.0f * dcompTextSurfaceWidth, + updateOffset.y + 0.0f * dcompTextSurfaceHeight, + updateOffset.x + 1.0f * dcompTextSurfaceWidth, + updateOffset.y + 1.0f * dcompTextSurfaceHeight + ); + + d2dDeviceContext->FillRectangle( + dcompTextSurfaceRect, + d2dBackgroundBrush.Get()); + + d2dDeviceContext->DrawText( + dcompTileSurfaceText, + wcslen(dcompTileSurfaceText), + dwriteTextFormat.Get(), + &dcompTextSurfaceRect, + d2dForegroundBrush.Get()); + + ShowMessageBoxIfFailed(hr, L"d2dDeviceContext->EndDraw"); + } + } + + if (SUCCEEDED(hr)) + { + hr = _dcompTextSurface->EndDraw(); + + ShowMessageBoxIfFailed(hr, L"_dcompTextSurface->EndDraw"); + } + } + + return hr; +} + +// Drawing tile content into tile surfaces using D2D batching +HRESULT Application::DrawDCompTileSurfaces() +{ + HRESULT hr = S_OK; + + // Defining tile colors + D2D1_COLOR_F dcompTileSurfaceBackgroundColors [] = + { + D2D1::ColorF(D2D1::ColorF::LightBlue), + D2D1::ColorF(D2D1::ColorF::BlueViolet), + D2D1::ColorF(D2D1::ColorF::Blue), + D2D1::ColorF(D2D1::ColorF::Cyan) + }; + + D2D1_COLOR_F dcompTileSurfaceForegroundColors [] = + { + D2D1::ColorF(D2D1::ColorF::Black), + D2D1::ColorF(D2D1::ColorF::Black), + D2D1::ColorF(D2D1::ColorF::Black), + D2D1::ColorF(D2D1::ColorF::Black), + }; + + // Defining tile content + const wchar_t *dcompTileSurfaceTexts [] = + { + L"1", + L"2", + L"3", + L"4" + }; + + UINT dcompTileSurfaceWidth = 2 * _hWndClientWidth / 8; + UINT dcompTileSurfaceHeight = 2 * _hWndClientHeight / 8; + + // Drawing content for all tile surfaces + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + Microsoft::WRL::ComPtr d2dDeviceContext; + POINT updateOffset = { 0 }; + + // Begin draw is using a D2D device context for D2D batching + hr = _dcompTileSurfaces[i]->BeginDraw(nullptr, __uuidof(ID2D1DeviceContext) , reinterpret_cast(d2dDeviceContext.GetAddressOf()), &updateOffset); + + ShowMessageBoxIfFailed(hr, L"pDCompSurface->BeginDraw"); + + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr d2dBackgroundBrush; + + if (SUCCEEDED(hr)) + { + hr = d2dDeviceContext->CreateSolidColorBrush(dcompTileSurfaceBackgroundColors[i], &d2dBackgroundBrush); + + ShowMessageBoxIfFailed(hr, L"d2dDeviceContext->CreateSolidColorBrush"); + } + + Microsoft::WRL::ComPtr d2dForegroundBrush; + + if (SUCCEEDED(hr)) + { + hr = d2dDeviceContext->CreateSolidColorBrush(dcompTileSurfaceForegroundColors[i], &d2dForegroundBrush); + + ShowMessageBoxIfFailed(hr, L"d2dDeviceContext->CreateSolidColorBrush"); + } + + Microsoft::WRL::ComPtr dwriteTextFormat; + + if (SUCCEEDED(hr)) + { + hr = _dwriteFactory->CreateTextFormat(L"Verdana", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, 72.0f, L"en-us", &dwriteTextFormat); + + ShowMessageBoxIfFailed(hr, L"dwriteFactory->CreateTextFormat"); + } + + if (SUCCEEDED(hr)) + { + hr = dwriteTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); + + ShowMessageBoxIfFailed(hr, L"dwriteTextFormat->SetTextAlignment"); + } + + if (SUCCEEDED(hr)) + { + hr = dwriteTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); + + ShowMessageBoxIfFailed(hr, L"dwriteTextFormat->SetParagraphAlignment"); + } + + if (SUCCEEDED(hr)) + { + D2D1_RECT_F dcompTileSurfaceRect = D2D1::RectF( + updateOffset.x + 0.0f * dcompTileSurfaceWidth, + updateOffset.y + 0.0f * dcompTileSurfaceHeight, + updateOffset.x + 1.0f * dcompTileSurfaceWidth, + updateOffset.y + 1.0f * dcompTileSurfaceHeight + ); + + d2dDeviceContext->FillRectangle( + dcompTileSurfaceRect, + d2dBackgroundBrush.Get()); + + d2dDeviceContext->DrawText( + dcompTileSurfaceTexts[i], + wcslen(dcompTileSurfaceTexts[i]), + dwriteTextFormat.Get(), + &dcompTileSurfaceRect, + d2dForegroundBrush.Get()); + + ShowMessageBoxIfFailed(hr, L"d2dDeviceContext->EndDraw"); + } + } + + if (SUCCEEDED(hr)) + { + hr = _dcompTileSurfaces[i]->EndDraw(); + + ShowMessageBoxIfFailed(hr, L"pDCompSurface->EndDraw"); + } + } + + return hr; +} +/*---- End of creating surfaces ----*/ + +/*---- Binding surfaces to visuals and root visual to target ----*/ +HRESULT Application::BindDCompRootVisualToTarget() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompTarget->SetRoot(_dcompRootVisual.Get()); + + ShowMessageBoxIfFailed(hr, L"_dcompTarget->SetRoot"); + } + + return hr; +} + +HRESULT Application::BindDCompTextSurfaceToVisual() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompTextVisual->SetContent(_dcompTextSurface.Get()); + + ShowMessageBoxIfFailed(hr, L"_dcompTextVisual->SetContent"); + } + + return hr; +} + +HRESULT Application::BindDCompTileSurfacesToVisuals() +{ + HRESULT hr = S_OK; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompTileVisuals[i]->SetContent(_dcompTileSurfaces[i].Get()); + + ShowMessageBoxIfFailed(hr, L"_dcompTileVisuals[i]->SetContent"); + } + + return hr; +} +/*---- End of binding visuals ----*/ + +/*---- Setting offsets to visuals ----*/ +HRESULT Application::SetOffsetOnDCompTextVisual() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompTextVisual->SetOffsetX(0.5f * _hWndClientWidth / 8.0f); + + ShowMessageBoxIfFailed(hr, L"_dcompTextVisual->SetOffsetX"); + } + + if (SUCCEEDED(hr)) + { + hr = _dcompTextVisual->SetOffsetY(0.25f * _hWndClientHeight / 8.0f); + + ShowMessageBoxIfFailed(hr, L"_dcompTextVisual->SetOffsetY"); + } + + return hr; +} + +HRESULT Application::SetOffsetOnDCompTileVisuals() +{ + HRESULT hr = S_OK; + + float dcompVisualOffsetX [] = + { + 1.0f * _hWndClientWidth / 8.0f, + 5.0f * _hWndClientWidth / 8.0f, + 1.0f * _hWndClientWidth / 8.0f, + 5.0f * _hWndClientWidth / 8.0f + }; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompTileVisuals[i]->SetOffsetX(dcompVisualOffsetX[i]); + + ShowMessageBoxIfFailed(hr, L"_dcompTileVisuals[i]->SetOffsetX"); + } + + float dcompVisualOffsetY [] = + { + 2.0f * _hWndClientWidth / 8.0f, + 2.0f * _hWndClientWidth / 8.0f, + 5.0f * _hWndClientWidth / 8.0f, + 5.0f * _hWndClientWidth / 8.0f + }; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompTileVisuals[i]->SetOffsetY(dcompVisualOffsetY[i]); + + ShowMessageBoxIfFailed(hr, L"_dcompTileVisuals[i]->SetOffsetY"); + } + + return hr; +} +/*---- End of setting offsets ----*/ + +// Setting backface visibility visible or hidden to visuals +HRESULT Application::SetBackfaceVisibilityOnDCompTileVisuals() +{ + HRESULT hr = S_OK; + + DCOMPOSITION_BACKFACE_VISIBILITY dcompVisualBackfaceVisibility [] = + { + DCOMPOSITION_BACKFACE_VISIBILITY_HIDDEN, + DCOMPOSITION_BACKFACE_VISIBILITY_VISIBLE, + DCOMPOSITION_BACKFACE_VISIBILITY_VISIBLE, + DCOMPOSITION_BACKFACE_VISIBILITY_HIDDEN + }; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompTileVisuals[i]->SetBackFaceVisibility(dcompVisualBackfaceVisibility[i]); + } + + return hr; +} + +/*---- Begin binding visuals to root visual to create visual tree ----*/ +HRESULT Application::AddDCompTextVisualToRootVisual() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompRootVisual->AddVisual(_dcompTextVisual.Get(), TRUE, nullptr); + + ShowMessageBoxIfFailed(hr, L"_dcompRootVisual->AddVisual"); + } + + return hr; +} + +HRESULT Application::AddDCompTileVisualsToRootVisual() +{ + HRESULT hr = S_OK; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompRootVisual->AddVisual(_dcompTileVisuals[i].Get(), TRUE, (i == 0) ? _dcompTextVisual.Get() : _dcompTileVisuals[i - 1].Get()); + + ShowMessageBoxIfFailed(hr, L"_dcompRootVisual->AddVisual"); + } + + return hr; +} +/*---- End of binding viusals ----*/ + +// Commiting the DComp device +HRESULT Application::CommitDCompDevice() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->Commit(); + + ShowMessageBoxIfFailed(hr, L"_dcompDevice->Commit"); + } + + return hr; +} + +// Hit-testing visual +LRESULT Application::OnPointerUp(LPARAM lparam) +{ + POINT p = { GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) }; + + ::ScreenToClient(_hWnd, &p); + + int visualIndex = -1; + + if (HasAnyVisualBeenHit(p.x, p.y, &visualIndex)) + { + ShowMessageBoxIfFailed(FlipVisual(visualIndex), L"FlipVisual(visualIndex)"); + } + else + { + ShowMessageBoxIfFailed(ResetVisuals(), L"ResetVisual"); + } + + return 0; +} + +// Identify which tile visual has been hit-tested +bool Application::HasAnyVisualBeenHit(int x, int y, int *pVisualIndex) +{ + bool br = (pVisualIndex != nullptr); + + int visualIndex = -1; + + if (br) + { + int x0[4] = + { + 1 * _hWndClientWidth / 8, + 5 * _hWndClientWidth / 8, + 1 * _hWndClientWidth / 8, + 5 * _hWndClientWidth / 8, + }; + + int x1[4] = + { + 3 * _hWndClientWidth / 8, + 7 * _hWndClientWidth / 8, + 3 * _hWndClientWidth / 8, + 7 * _hWndClientWidth / 8, + }; + + int y0[4] = + { + 2 * _hWndClientWidth / 8, + 2 * _hWndClientWidth / 8, + 5 * _hWndClientWidth / 8, + 5 * _hWndClientWidth / 8, + }; + + int y1[4] = + { + 4 * _hWndClientWidth / 8, + 4 * _hWndClientWidth / 8, + 7 * _hWndClientWidth / 8, + 7 * _hWndClientWidth / 8, + }; + + for (int i = 0; i < 4; ++i) + { + if ((x0[i] <= x) && (x <= x1[i]) && (y0[i] <= y) && (y <= y1[i])) + { + visualIndex = i; + break; + } + } + + br = (visualIndex != -1); + *pVisualIndex = visualIndex; + } + + + + return br; +} + +// Apply a 3D flip for hit-tested tile visual +HRESULT Application::FlipVisual(int visualIndex) +{ + HRESULT hr = S_OK; + + Microsoft::WRL::ComPtr dcompAngleAnimation; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->CreateAnimation(&dcompAngleAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = dcompAngleAnimation->AddCubic(0.0, 0.0f, 180.0f, 0.0f, 0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompAngleAnimation->End(1.0, 180.0f); + } + + Microsoft::WRL::ComPtr dcompFlipTransform; + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->CreateRotateTransform3D(&dcompFlipTransform); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetCenterX(1.0f * _hWndClientWidth / 8.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetCenterY(1.0f * _hWndClientHeight / 8.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetCenterZ(0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetAxisX(0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetAxisY(1.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetAxisZ(0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = dcompFlipTransform->SetAngle(dcompAngleAnimation.Get()); + } + + if (SUCCEEDED(hr)) + { + hr = _dcompTileVisuals[visualIndex]->SetEffect(dcompFlipTransform.Get()); + } + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->Commit(); + } + + return hr; +} + +// Reset all visuals when a hit-test is detected outside of tile visuals +HRESULT Application::ResetVisuals() +{ + HRESULT hr = S_OK; + + for (int i = 0; SUCCEEDED(hr) && i < 4; ++i) + { + hr = _dcompTileVisuals[i]->SetEffect(nullptr); + } + + if (SUCCEEDED(hr)) + { + hr = _dcompDevice->Commit(); + } + + return hr; +} + +LRESULT Application::OnClose() +{ + if (_hWnd != NULL) + { + DestroyWindow(_hWnd); + _hWnd = NULL; + } + + return 0; +} + +LRESULT Application::OnDestroy() +{ + PostQuitMessage(0); + + return 0; +} + +void Application::ShowMessageBoxIfFailed(HRESULT hr, const wchar_t *pMessage) +{ + if (FAILED(hr)) + { + ::MessageBox(NULL, pMessage, L"Failed", MB_OK); + } +} \ No newline at end of file diff --git a/Samples/DCompV2BackfaceandD2DBatching/cpp/Application.h b/Samples/DCompV2BackfaceandD2DBatching/cpp/Application.h new file mode 100644 index 00000000..1db7d707 --- /dev/null +++ b/Samples/DCompV2BackfaceandD2DBatching/cpp/Application.h @@ -0,0 +1,127 @@ +// 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 + +class Application +{ +public: + Application(HINSTANCE hInstance); + ~Application(); + + int Run(); + +private: + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam); + +private: + Application(const Application &); // not implemented + Application &operator=(const Application &); // not implemented + +private: + HRESULT BeforeEnteringMessageLoop(); + int EnterMessageLoop(); + void AfterLeavingMessageLoop(); + + HRESULT CreateMainWindow(); + HRESULT ShowMainWindow(); + void DestroyMainWindow(); + + HRESULT EnableMouseAsPointerDevice(); + + HRESULT CreateD3DDevice(); + void DestroyD3DDevice(); + + HRESULT CreateD2DDevice(); + void DestroyD2DDevice(); + + HRESULT CreateDWriteFactory(); + void DestroyDWriteFactory(); + + HRESULT CreateDCompDevice(); + void DestroyDCompDevice(); + + HRESULT CreateDCompVisualTree(); + void DestroyDCompVisualTree(); + + HRESULT CreateDCompTarget(); + void DestroyDCompTarget(); + + HRESULT CreateDCompRootVisual(); + void DestroyDCompRootVisual(); + + HRESULT CreateDCompTextVisual(); + void DestroyDCompTextVisual(); + + HRESULT CreateDCompTextSurface(); + void DestroyDCompTextSurface(); + + HRESULT CreateDCompTileVisuals(); + void DestroyDCompTileVisuals(); + + HRESULT CreateDCompTileSurfaces(); + void DestroyDCompTileSurfaces(); + + HRESULT DrawDCompTextSurface(); + HRESULT DrawDCompTileSurfaces(); + + HRESULT BindDCompRootVisualToTarget(); + HRESULT BindDCompTextSurfaceToVisual(); + HRESULT BindDCompTileSurfacesToVisuals(); + + HRESULT SetOffsetOnDCompTextVisual(); + HRESULT SetOffsetOnDCompTileVisuals(); + + HRESULT SetBackfaceVisibilityOnDCompTileVisuals(); + + HRESULT AddDCompTextVisualToRootVisual(); + HRESULT AddDCompTileVisualsToRootVisual(); + + HRESULT CommitDCompDevice(); + + LRESULT OnPointerUp(LPARAM lparam); + LRESULT OnClose(); + LRESULT OnDestroy(); + + bool HasAnyVisualBeenHit(int x, int y, int *pVisualIndex); + HRESULT FlipVisual(int visualIndex); + HRESULT ResetVisuals(); + + void ShowMessageBoxIfFailed(HRESULT hr, const wchar_t *pMessage); + +private: + static Application *_application; + +private: + HINSTANCE _hInstance; + + HWND _hWnd; + UINT _hWndClientWidth; + UINT _hWndClientHeight; + + Microsoft::WRL::ComPtr _d3dDevice; + + Microsoft::WRL::ComPtr _d2dDevice; + + Microsoft::WRL::ComPtr _dwriteFactory; + + Microsoft::WRL::ComPtr _dcompDevice; + Microsoft::WRL::ComPtr _dcompTarget; + Microsoft::WRL::ComPtr _dcompRootVisual; + Microsoft::WRL::ComPtr _dcompTextVisual; + Microsoft::WRL::ComPtr _dcompTextSurface; + Microsoft::WRL::ComPtr _dcompTileVisuals[4]; + Microsoft::WRL::ComPtr _dcompTileSurfaces[4]; + +}; \ No newline at end of file diff --git a/Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.sln b/Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.sln new file mode 100644 index 00000000..47a8d127 --- /dev/null +++ b/Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.20513.1 PREVIEW +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DCompV2BackfaceandD2Dbatching", "DCompV2BackfaceandD2Dbatching.vcxproj", "{EA51AAE8-0D3B-4033-BA94-9FEFD67295AF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA51AAE8-0D3B-4033-BA94-9FEFD67295AF}.Debug|Win32.ActiveCfg = Debug|Win32 + {EA51AAE8-0D3B-4033-BA94-9FEFD67295AF}.Debug|Win32.Build.0 = Debug|Win32 + {EA51AAE8-0D3B-4033-BA94-9FEFD67295AF}.Release|Win32.ActiveCfg = Release|Win32 + {EA51AAE8-0D3B-4033-BA94-9FEFD67295AF}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.vcxproj b/Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.vcxproj new file mode 100644 index 00000000..27748797 --- /dev/null +++ b/Samples/DCompV2BackfaceandD2DBatching/cpp/DCompV2BackfaceandD2DBatching.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {EA51AAE8-0D3B-4033-BA94-9FEFD67295AF} + Win32Proj + DCompV2BackfaceandD2Dbatching + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + d3d11.lib;d2d1.lib;dwrite.lib;dcomp.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;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + d3d11.lib;d2d1.lib;dwrite.lib;dcomp.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) + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/DCompV2BackfaceandD2DBatching/cpp/Main.cpp b/Samples/DCompV2BackfaceandD2DBatching/cpp/Main.cpp new file mode 100644 index 00000000..7842eed4 --- /dev/null +++ b/Samples/DCompV2BackfaceandD2DBatching/cpp/Main.cpp @@ -0,0 +1,20 @@ +// 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 "Application.h" + +//Provides the entry point to the application +int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR cmdLine, _In_ int cmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(cmdLine); + UNREFERENCED_PARAMETER(cmdShow); + + Application application(hInstance); + + return application.Run(); +} diff --git a/Samples/DHCP/AddPolicyRange/README.md b/Samples/DHCP/AddPolicyRange/README.md new file mode 100644 index 00000000..7608a750 --- /dev/null +++ b/Samples/DHCP/AddPolicyRange/README.md @@ -0,0 +1,42 @@ +DhcpV4AddPolicyRange API sample +=============================== + +This sample explains how to use the DhcpV4AddPolicyRange API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4AddPolicyRange**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404291) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample is built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.cpp b/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.cpp new file mode 100644 index 00000000..e63f76f0 --- /dev/null +++ b/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.cpp @@ -0,0 +1,48 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "testPolicy" on subnet address 10.0.0.0 +*/ + + +#include +#include +#include + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + +int __cdecl main(void) +{ + DHCP_IP_RANGE range = {0}; // Variable to hold the range value to be added to the policy. + DWORD dwError = ERROR_SUCCESS; // Variable to store the error code + LPWSTR pwszPolicyName = L"testPolicy"; // Name of the policy + LPWSTR pwszServer = NULL; // Server IP Address, Null signifies the current server (where the program is run) + DWORD dwScope = 0xa000000; //(10.0.0.0) Subnet address + DWORD dwStartAddress = 0xa00000a; //(10.0.0.10) Start Address for the range + DWORD dwEndAddress = 0xa000032; //(10.0.0.50) End Address for the range + + range.StartAddress = dwStartAddress; + range.EndAddress = dwEndAddress; + + // Adds a policy range for the policy "testPolicy" on subnet address 10.0.0.0 + dwError = DhcpV4AddPolicyRange( + pwszServer, //ServerIpAddress, if this is NULL, it means the current server on which the program is run + dwScope, // SubnetAddress + pwszPolicyName,// Name of the policy + &range // Range to be added + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4AddPolicyRange failed with Error = %d\n",dwError); + } + return 0; +} diff --git a/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.sln b/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.sln new file mode 100644 index 00000000..530fc737 --- /dev/null +++ b/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "addpolicyrange", "addpolicyrange.vcxproj", "{7C04C03A-A5DB-45D6-A9B9-340440267BCC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7C04C03A-A5DB-45D6-A9B9-340440267BCC}.Debug|x64.ActiveCfg = Debug|x64 + {7C04C03A-A5DB-45D6-A9B9-340440267BCC}.Debug|x64.Build.0 = Debug|x64 + {7C04C03A-A5DB-45D6-A9B9-340440267BCC}.Release|x64.ActiveCfg = Release|x64 + {7C04C03A-A5DB-45D6-A9B9-340440267BCC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.vcxproj b/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.vcxproj new file mode 100644 index 00000000..39ec51f5 --- /dev/null +++ b/Samples/DHCP/AddPolicyRange/cpp/addpolicyrange.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {7C04C03A-A5DB-45D6-A9B9-340440267BCC} + Win32Proj + addpolicyrange + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + addpolicyrange + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/AddScopeToRelationship/README.md b/Samples/DHCP/AddScopeToRelationship/README.md new file mode 100644 index 00000000..92dc36f6 --- /dev/null +++ b/Samples/DHCP/AddScopeToRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverAddScopeToRelationship API sample +=============================================== + +This sample explains how to use the DhcpV4FailoverAddScopeToRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverAddScopeToRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404300) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.cpp b/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.cpp new file mode 100644 index 00000000..13485616 --- /dev/null +++ b/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.cpp @@ -0,0 +1,206 @@ +// 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 + +/* +Assumptions: + 1) There exists a relationship with the name "Test". + 2) Identical scope 172.0.0.0 should be present on primary as well as partner server, which should not be part of relationship. +*/ + +#include +#include +#include + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + // Frees relationship name + if (NULL != pFailRel->RelationshipName) + DhcpRpcFreeMemory(pFailRel->RelationshipName); + + // Frees shared secret + if( NULL != pFailRel->SharedSecret) + DhcpRpcFreeMemory(pFailRel->SharedSecret); + + //Frees Primary server's name + if (NULL != pFailRel->PrimaryServerName) + DhcpRpcFreeMemory(pFailRel->PrimaryServerName); + + // Frees Secondary server's name + if (NULL != pFailRel->SecondaryServerName) + DhcpRpcFreeMemory(pFailRel->SecondaryServerName); + + //Frees the relationship + DhcpRpcFreeMemory(pFailRel); + pFailRel=NULL; + } +} + + +//This routine frees LPDHCP_SUBNET_INFO_VQ +void FreeSubnetInfoVQ(LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ) +{ + // Frees NetBios Name + if(pSubnetInfoVQ->PrimaryHost.NetBiosName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.NetBiosName); + + //Frees host name + if(pSubnetInfoVQ->PrimaryHost.HostName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.HostName); + + // Frees Subnet Name + if(pSubnetInfoVQ->SubnetName) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetName); + + // Frees subnet comment + if(pSubnetInfoVQ->SubnetComment) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetComment); + + DhcpRpcFreeMemory(pSubnetInfoVQ); +} + +// This function changes the states of the scope. +DWORD ChangeScopeStates(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray, DHCP_SUBNET_STATE dwState) +{ + DWORD dwError = ERROR_SUCCESS; + DWORD dwIndex = 0; + LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ = NULL; + for(dwIndex = 0 ; dwIndex < pArray->NumElements ; dwIndex++) + { + dwError = DhcpGetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],&pSubnetInfoVQ); + if(ERROR_SUCCESS != dwError) + return dwError; + + // set the scope state to dwState + pSubnetInfoVQ->SubnetState= dwState; + dwError = DhcpSetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],pSubnetInfoVQ); + if(dwError != ERROR_SUCCESS) + { + return dwError; + } + // Free memory for pSubnetInfoVQ + FreeSubnetInfoVQ(pSubnetInfoVQ); + pSubnetInfoVQ = NULL; + } + return dwError; +} + +// This function changes the scope state to "disabled" +DWORD DeactivateScopes(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray) +{ + return ChangeScopeStates(pServer,pArray,DhcpSubnetDisabled); +} + +// This function changes the scope state to "enabled" +DWORD ActivateScopes(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray) +{ + return ChangeScopeStates(pServer,pArray,DhcpSubnetEnabled); +} + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; // Server IP Address + LPWSTR pwszRelationshipName = L"test"; // Relationship name + LPDHCP_FAILOVER_RELATIONSHIP pRelationship = NULL; // Relationship structure + LPDHCP_IP_ARRAY pIpAddressArray = NULL; // Array of IP Addresses + DWORD dwError = ERROR_SUCCESS;// Variable to hold error codes + + // Gets a relationship with the name stored in the variable "pwszRelationshipName" + dwError = DhcpV4FailoverGetRelationship( + pwszServer, // Server IP Address + pwszRelationshipName, // Relationship name + &pRelationship // Failover relationship + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetRelationship failed with Error = %d\n", dwError); + goto cleanup; + } + // Create an array of IP address which will have the scopes to be added to the relationship + pIpAddressArray = (LPDHCP_IP_ARRAY)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DHCP_IP_ARRAY)); + if(pIpAddressArray == NULL) + { + wprintf(L"HeapAlloc failed !! Not enough memory\n"); + goto cleanup; + } + // Number of scopes to be added is 1 + pIpAddressArray->NumElements = 1; + pIpAddressArray->Elements=(LPDHCP_IP_ADDRESS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(DHCP_IP_ADDRESS)); + if(pIpAddressArray->Elements == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + // Fill the elements in the array + pIpAddressArray->Elements[0]=0xac100000; //172.16.0.0 + if (NULL != pRelationship->pScopes) + { + if(NULL != pRelationship->pScopes->Elements) + { + DhcpRpcFreeMemory(pRelationship->pScopes->Elements); + } + DhcpRpcFreeMemory(pRelationship->pScopes); + } + pRelationship->pScopes = pIpAddressArray; + + // Deactivate scopes on partner server + dwError = DeactivateScopes(pRelationship->SecondaryServerName, pRelationship->pScopes); + if( ERROR_SUCCESS != dwError) + { wprintf(L"Failed to deactivate scopes on partner server\n"); + goto cleanup; + } + // Deactivate scopes on current server + dwError = DeactivateScopes(pRelationship->PrimaryServerName, pRelationship->pScopes); + if( ERROR_SUCCESS != dwError) + { wprintf(L"Failed to deactivate scopes on primary server\n"); + goto ActivateSecAndCleanup; + } + + //Adds the scope to the relationship on the secondary server + dwError = DhcpV4FailoverAddScopeToRelationship( + pRelationship->SecondaryServerName, + pRelationship); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverAddScopeToRelationship failed with Error = %d for partner server\n",dwError); + goto ActivatePriAndCleanup; + } + + //Adds the scope to the relationship on the primary server + dwError = DhcpV4FailoverAddScopeToRelationship( + pwszServer, + pRelationship); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverAddScopeToRelationship failed with Error = %d for primary server\n",dwError); + } + +ActivatePriAndCleanup: + //Activate scopes on primary server + ActivateScopes(pRelationship->PrimaryServerName,pRelationship->pScopes); + +ActivateSecAndCleanup: + //Activate scopes on secondary server + ActivateScopes(pRelationship->SecondaryServerName,pRelationship->pScopes); + +cleanup: + + if( NULL != pIpAddressArray ) + { + if( NULL != pIpAddressArray->Elements) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pIpAddressArray->Elements); + pIpAddressArray->Elements = NULL; + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pIpAddressArray); + pIpAddressArray = NULL; + } + FreeRelationshipMemory(pRelationship); + return 0; +} diff --git a/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.sln b/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.sln new file mode 100644 index 00000000..f101663d --- /dev/null +++ b/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AddScopeToRelationship", "AddScopeToRelationship.vcxproj", "{CED1A580-52DC-448D-9A05-565ADFDC3767}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CED1A580-52DC-448D-9A05-565ADFDC3767}.Debug|x64.ActiveCfg = Debug|x64 + {CED1A580-52DC-448D-9A05-565ADFDC3767}.Debug|x64.Build.0 = Debug|x64 + {CED1A580-52DC-448D-9A05-565ADFDC3767}.Release|x64.ActiveCfg = Release|x64 + {CED1A580-52DC-448D-9A05-565ADFDC3767}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.vcxproj b/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.vcxproj new file mode 100644 index 00000000..e88bfb8c --- /dev/null +++ b/Samples/DHCP/AddScopeToRelationship/cpp/AddScopeToRelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {CED1A580-52DC-448D-9A05-565ADFDC3767} + Win32Proj + AddScopeToRelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + AddScopeToRelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/CreatePolicy/README.md b/Samples/DHCP/CreatePolicy/README.md new file mode 100644 index 00000000..4173e018 --- /dev/null +++ b/Samples/DHCP/CreatePolicy/README.md @@ -0,0 +1,42 @@ +DhcpV4CreatePolicy API sample +============================= + +This sample shows how to use the DhcpV4CreatePolicy API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4CreatePolicy**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404293) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/CreatePolicy/cpp/createpolicy.cpp b/Samples/DHCP/CreatePolicy/cpp/createpolicy.cpp new file mode 100644 index 00000000..37ec5fc4 --- /dev/null +++ b/Samples/DHCP/CreatePolicy/cpp/createpolicy.cpp @@ -0,0 +1,109 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope address 10.0.0.0 +*/ + +#include +#include +#include + + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength = 0; // Number of bytes of user data in pUserClassCondValueInBytes + LPBYTE pUserClassCondValueInBytes = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0xa000000; // Subnet Address (10.0.0.0) + LPWSTR pwszServer = NULL; // Server IP Address, NULL signifies the current server (on which the program is running). + LPWSTR pwszName = L"testPolicy"; //Name of the policy to be created + LPWSTR pwszDescription = L"PolicyDescription"; // Description of the policy to be created + char* szUserClassConditionValue = {"BOOTP.Microsoft"}; // Default BOOTP Class + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + + //Helper routine is invoked to create/fill the policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + dwBytesLength = (DWORD)strlen(szUserClassConditionValue); + pUserClassCondValueInBytes = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength); + if(NULL == pUserClassCondValueInBytes) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + // Fill in bytes for szUserClassConditionValue + memcpy(pUserClassCondValueInBytes, szUserClassConditionValue, dwBytesLength); + + // DhcpHlprAddV4PolicyCondition is invoked to add conditions for the policy. + // The condition in this case is "user class" equals "Default BOOTP Class" + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes, // Condition values in bytes + dwBytesLength, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + + // This is the actual RPC call to create policy on the server. + // pPolicy is formed and filled by helper APIs and is fed to the RPC api for the policy to be created. + dwError=DhcpV4CreatePolicy(pwszServer, pPolicy); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4CreatePolicy failed with Error = %d\n", dwError); + } +cleanup: + + // Frees the variable that holds the bytes for condition values + if(NULL != pUserClassCondValueInBytes) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes); + pUserClassCondValueInBytes = NULL; + } + + //Frees the variable that holds the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + return 0; +} diff --git a/Samples/DHCP/CreatePolicy/cpp/createpolicy.sln b/Samples/DHCP/CreatePolicy/cpp/createpolicy.sln new file mode 100644 index 00000000..7e7d4ec0 --- /dev/null +++ b/Samples/DHCP/CreatePolicy/cpp/createpolicy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "createpolicy", "createpolicy.vcxproj", "{57EE5696-EE7B-4896-A2E1-82BBF359457B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {57EE5696-EE7B-4896-A2E1-82BBF359457B}.Debug|x64.ActiveCfg = Debug|x64 + {57EE5696-EE7B-4896-A2E1-82BBF359457B}.Debug|x64.Build.0 = Debug|x64 + {57EE5696-EE7B-4896-A2E1-82BBF359457B}.Release|x64.ActiveCfg = Release|x64 + {57EE5696-EE7B-4896-A2E1-82BBF359457B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/CreatePolicy/cpp/createpolicy.vcxproj b/Samples/DHCP/CreatePolicy/cpp/createpolicy.vcxproj new file mode 100644 index 00000000..35143b6d --- /dev/null +++ b/Samples/DHCP/CreatePolicy/cpp/createpolicy.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {57EE5696-EE7B-4896-A2E1-82BBF359457B} + Win32Proj + createpolicy + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + createpolicy + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/CreateRelationship/README.md b/Samples/DHCP/CreateRelationship/README.md new file mode 100644 index 00000000..c43b4962 --- /dev/null +++ b/Samples/DHCP/CreateRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverCreateRelationship API sample +=========================================== + +This sample shows how to use the DhcpV4FailoverCreateRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverCreateRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404302) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/CreateRelationship/cpp/createrelationship.cpp b/Samples/DHCP/CreateRelationship/cpp/createrelationship.cpp new file mode 100644 index 00000000..608b48a4 --- /dev/null +++ b/Samples/DHCP/CreateRelationship/cpp/createrelationship.cpp @@ -0,0 +1,228 @@ +// 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 +#include +#include + +/* +Assumptions: + 1) Primary Server IP: 10.0.0.1 + 2) Name of the primary server: failover-test1 + 3) Partner Server IP: 10.0.0.2 + 4) Name of the partner server: failover-test2 + 5) Identical scope should be present on both the server: (10.0.0.0) +*/ + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + //Frees pScopes + if (NULL != pFailRel->pScopes) + { + //Frees individual elements of pScopes + if(NULL != pFailRel->pScopes->Elements) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pFailRel->pScopes->Elements); + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pFailRel->pScopes); + } + //Frees the relationship + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pFailRel); + pFailRel=NULL; + } +} + +//This routine frees LPDHCP_SUBNET_INFO_VQ +void FreeSubnetInfoVQ(LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ) +{ + // Frees NetBios Name + if(pSubnetInfoVQ->PrimaryHost.NetBiosName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.NetBiosName); + + //Frees host name + if(pSubnetInfoVQ->PrimaryHost.HostName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.HostName); + + // Frees Subnet Name + if(pSubnetInfoVQ->SubnetName) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetName); + + // Frees subnet comment + if(pSubnetInfoVQ->SubnetComment) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetComment); + + DhcpRpcFreeMemory(pSubnetInfoVQ); +} + +// This function changes the states of the scope. +DWORD ChangeScopeStates(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray, DHCP_SUBNET_STATE dwState) +{ + DWORD dwError = ERROR_SUCCESS; + DWORD dwIndex = 0; + LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ = NULL; + for(dwIndex = 0 ; dwIndex < pArray->NumElements ; dwIndex++) + { + dwError = DhcpGetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],&pSubnetInfoVQ); + if(ERROR_SUCCESS != dwError) + return dwError; + + // set the scope state to dwState + pSubnetInfoVQ->SubnetState= dwState; + dwError = DhcpSetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],pSubnetInfoVQ); + if(dwError != ERROR_SUCCESS) + { + return dwError; + } + // Free memory for pSubnetInfoVQ + FreeSubnetInfoVQ(pSubnetInfoVQ); + pSubnetInfoVQ = NULL; + } + return dwError; +} + +// This function changes the scope state to "disabled" +DWORD DeactivateScopes(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray) +{ + return ChangeScopeStates(pServer,pArray,DhcpSubnetDisabled); +} + +// This function changes the scope state to "enabled" +DWORD ActivateScopes(_In_ LPWSTR pServer,_Inout_ LPDHCP_IP_ARRAY pArray) +{ + return ChangeScopeStates(pServer,pArray,DhcpSubnetEnabled); +} + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; // Server IP Address + LPDHCP_FAILOVER_RELATIONSHIP pRelationship = NULL; // Relationship structure on the server + LPDHCP_FAILOVER_RELATIONSHIP pPartnerRelationship = NULL; // Relationship structure on partner + DWORD dwError = ERROR_SUCCESS; // Variable to hold error codes + + pRelationship = (LPDHCP_FAILOVER_RELATIONSHIP)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DHCP_FAILOVER_RELATIONSHIP)); + if(pRelationship == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + return 0; + } + pRelationship->PrimaryServer = 0xa000001; // Primary server IP Address (10.0.0.1) + pRelationship->SecondaryServer = 0xa000002; // Secondary server IP Address (10.0.0.2) + pRelationship->Mode=LoadBalance; //Mode of the relationship. Other values can be HotStandby + pRelationship->ServerType = PrimaryServer; // Type of the server in the relationship (Primary or secondary) + pRelationship->State= NO_STATE; // State of the relationship + pRelationship->PrevState= NO_STATE; // Previous state + pRelationship->Mclt=0xe10; // Maximum Client lead time => 1 hours (0xe10 sec) + pRelationship->SafePeriod=0x258; // Safe period 10 min (0x258 sec) + pRelationship->SharedSecret=L"secretpassword"; // Shared secret + pRelationship->Percentage=0x32; // Percentage (50 %) + pRelationship->PrimaryServerName=L"failover-test1"; // Primary server name + pRelationship->SecondaryServerName=L"failover-test2"; //Secondary server name + pRelationship->RelationshipName=L"test"; // Relationship name + + //Creates IP Array for storing scopes + pRelationship->pScopes = (LPDHCP_IP_ARRAY)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DHCP_IP_ARRAY)); + if(pRelationship->pScopes == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + + // Number of scopes in the relationship = 1 + pRelationship->pScopes->NumElements = 1; + pRelationship->pScopes->Elements=(LPDHCP_IP_ADDRESS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(DHCP_IP_ADDRESS)); + if(pRelationship->pScopes->Elements == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + //Scope is 10.0.0.0 + pRelationship->pScopes->Elements[0]=0xa000000; // 10.0.0.0 + + pPartnerRelationship = (LPDHCP_FAILOVER_RELATIONSHIP)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DHCP_FAILOVER_RELATIONSHIP)); + if(pPartnerRelationship == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + pPartnerRelationship->PrimaryServer = 0xa000001; // Primary server IP Address (10.0.0.1) + pPartnerRelationship->SecondaryServer = 0xa000002; // Secondary server IP Address (10.0.0.2) + pPartnerRelationship->Mode=LoadBalance; //Mode of the relationship. Other values can be HotStandby + pPartnerRelationship->ServerType = SecondaryServer; // Type of the server in the relationship (Primary or secondary) + pPartnerRelationship->State= NO_STATE; // State of the relationship + pPartnerRelationship->PrevState= NO_STATE; // Previous state + pPartnerRelationship->Mclt=0xe10; // Maximum Client lead time => 1 hours (0xe10 sec) + pPartnerRelationship->SafePeriod=0x258; // Safe period 10 min (0x258 sec) + pPartnerRelationship->SharedSecret=L"secretpassword"; // Shared secret + pPartnerRelationship->Percentage=0x32; // Percentage (50 %) + pPartnerRelationship->PrimaryServerName=L"failover-test1"; // Primary server name + pPartnerRelationship->SecondaryServerName=L"failover-test2"; //Secondary server name + pPartnerRelationship->RelationshipName=L"test"; // Relationship name + + //Creates IP Array for storing scopes + pPartnerRelationship->pScopes = (LPDHCP_IP_ARRAY)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DHCP_IP_ARRAY)); + if(pPartnerRelationship->pScopes == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + // Number of scopes in the relationship = 1 + pPartnerRelationship->pScopes->NumElements = 1; + pPartnerRelationship->pScopes->Elements=(LPDHCP_IP_ADDRESS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(DHCP_IP_ADDRESS)); + if(pPartnerRelationship->pScopes->Elements == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + //Scope is 10.0.0.0 + pPartnerRelationship->pScopes->Elements[0]=0xa000000; //10.0.0.0 + + // Deactivate scopes on partner server + dwError = DeactivateScopes(pRelationship->SecondaryServerName, pRelationship->pScopes); + if( ERROR_SUCCESS != dwError) + { wprintf(L"Failed to deactivate scopes on partner server\n"); + goto cleanup; + } + // Deactivate scopes on current server + dwError = DeactivateScopes(pRelationship->PrimaryServerName, pRelationship->pScopes); + if( ERROR_SUCCESS != dwError) + { wprintf(L"Failed to deactivate scopes on primary server\n"); + goto ActivateSecAndCleanup; + } + //Creates the relationship + dwError = DhcpV4FailoverCreateRelationship( + pPartnerRelationship->SecondaryServerName, + pPartnerRelationship); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverCreateRelationship failed with Error = %d\n",dwError); + goto ActivatePriAndCleanup; + } + dwError = DhcpV4FailoverCreateRelationship( + pwszServer, + pRelationship); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverCreateRelationship failed with Error = %d\n",dwError); + DhcpV4FailoverDeleteRelationship(pPartnerRelationship->SecondaryServerName, pPartnerRelationship->RelationshipName); + } +ActivatePriAndCleanup: + //Activate scopes on primary server + ActivateScopes(pRelationship->PrimaryServerName,pRelationship->pScopes); + +ActivateSecAndCleanup: + //Activate scopes on secondary server + ActivateScopes(pRelationship->SecondaryServerName,pRelationship->pScopes); + +cleanup: + FreeRelationshipMemory(pRelationship); + FreeRelationshipMemory(pPartnerRelationship); + return 0; +} diff --git a/Samples/DHCP/CreateRelationship/cpp/createrelationship.sln b/Samples/DHCP/CreateRelationship/cpp/createrelationship.sln new file mode 100644 index 00000000..fa374321 --- /dev/null +++ b/Samples/DHCP/CreateRelationship/cpp/createrelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "createrelationship", "createrelationship.vcxproj", "{3ECDC601-36B2-47F4-82CE-1CE0F1E5D4B5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3ECDC601-36B2-47F4-82CE-1CE0F1E5D4B5}.Debug|x64.ActiveCfg = Debug|x64 + {3ECDC601-36B2-47F4-82CE-1CE0F1E5D4B5}.Debug|x64.Build.0 = Debug|x64 + {3ECDC601-36B2-47F4-82CE-1CE0F1E5D4B5}.Release|x64.ActiveCfg = Release|x64 + {3ECDC601-36B2-47F4-82CE-1CE0F1E5D4B5}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/CreateRelationship/cpp/createrelationship.vcxproj b/Samples/DHCP/CreateRelationship/cpp/createrelationship.vcxproj new file mode 100644 index 00000000..1110ad29 --- /dev/null +++ b/Samples/DHCP/CreateRelationship/cpp/createrelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {3ECDC601-36B2-47F4-82CE-1CE0F1E5D4B5} + Win32Proj + createrelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + createrelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/DeletePolicy/README.md b/Samples/DHCP/DeletePolicy/README.md new file mode 100644 index 00000000..35abfec5 --- /dev/null +++ b/Samples/DHCP/DeletePolicy/README.md @@ -0,0 +1,42 @@ +DhcpV4DeletePolicy API sample +============================= + +This sample explains the usage of the DhcpV4DeletePolicy API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4DeletePolicy**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404294) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/DeletePolicy/cpp/deletepolicy.cpp b/Samples/DHCP/DeletePolicy/cpp/deletepolicy.cpp new file mode 100644 index 00000000..9981dd71 --- /dev/null +++ b/Samples/DHCP/DeletePolicy/cpp/deletepolicy.cpp @@ -0,0 +1,37 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "PolicyNewName" on scope 10.0.0.0 +*/ + +#include +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //NULL signifies current server + DWORD dwScope = 0xa000000; // (10.0.0.0) Subnet Address + LPWSTR pwszName = L"PolicyNewName"; // Name of the policy to be deleted + DWORD dwError = ERROR_SUCCESS; // Variable to hold the error code. + + dwError = DhcpV4DeletePolicy( + pwszServer, // ServerIpAddress, from where the policy needs to be deleted + (dwScope == 0), // fGloabalPolicy, true in case it is a global policy, for global policyies subnetAddress is zero. + dwScope, // SubnetAddress + pwszName // Name of the policy to be deleted. + ); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4DeletePolicy returned error. + wprintf(L"DhcpV4DeletePolicy failed with error %d\n",dwError); + } + return 0; +} diff --git a/Samples/DHCP/DeletePolicy/cpp/deletepolicy.sln b/Samples/DHCP/DeletePolicy/cpp/deletepolicy.sln new file mode 100644 index 00000000..d210196b --- /dev/null +++ b/Samples/DHCP/DeletePolicy/cpp/deletepolicy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deletepolicy", "deletepolicy.vcxproj", "{9320DEA6-5E94-4FE6-A146-0FED613ADD74}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9320DEA6-5E94-4FE6-A146-0FED613ADD74}.Debug|x64.ActiveCfg = Debug|x64 + {9320DEA6-5E94-4FE6-A146-0FED613ADD74}.Debug|x64.Build.0 = Debug|x64 + {9320DEA6-5E94-4FE6-A146-0FED613ADD74}.Release|x64.ActiveCfg = Release|x64 + {9320DEA6-5E94-4FE6-A146-0FED613ADD74}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/DeletePolicy/cpp/deletepolicy.vcxproj b/Samples/DHCP/DeletePolicy/cpp/deletepolicy.vcxproj new file mode 100644 index 00000000..08d73ed4 --- /dev/null +++ b/Samples/DHCP/DeletePolicy/cpp/deletepolicy.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {9320DEA6-5E94-4FE6-A146-0FED613ADD74} + Win32Proj + deletepolicy + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + deletepolicy + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/DeleteRelationship/README.md b/Samples/DHCP/DeleteRelationship/README.md new file mode 100644 index 00000000..38bebcd7 --- /dev/null +++ b/Samples/DHCP/DeleteRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverDeleteRelationship API sample +=========================================== + +This sample explains the usage of the DhcpV4FailoverDeleteRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverDeleteRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404304) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.cpp b/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.cpp new file mode 100644 index 00000000..9c10ff54 --- /dev/null +++ b/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.cpp @@ -0,0 +1,152 @@ +// 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 +#include +#include + + +//This routine frees LPDHCP_SUBNET_INFO_VQ +void FreeSubnetInfoVQ(LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ) +{ + // Frees NetBios Name + if(pSubnetInfoVQ->PrimaryHost.NetBiosName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.NetBiosName); + + //Frees host name + if(pSubnetInfoVQ->PrimaryHost.HostName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.HostName); + + // Frees Subnet Name + if(pSubnetInfoVQ->SubnetName) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetName); + + // Frees subnet comment + if(pSubnetInfoVQ->SubnetComment) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetComment); + + DhcpRpcFreeMemory(pSubnetInfoVQ); +} + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + // Frees relationship name + if (NULL != pFailRel->RelationshipName) + DhcpRpcFreeMemory(pFailRel->RelationshipName); + + // Frees shared secret + if( NULL != pFailRel->SharedSecret) + DhcpRpcFreeMemory(pFailRel->SharedSecret); + + //Frees Primary server's name + if (NULL != pFailRel->PrimaryServerName) + DhcpRpcFreeMemory(pFailRel->PrimaryServerName); + + // Frees Secondary server's name + if (NULL != pFailRel->SecondaryServerName) + DhcpRpcFreeMemory(pFailRel->SecondaryServerName); + + //Frees pScopes + if (NULL != pFailRel->pScopes) + { + //Frees individual elements of pScopes + if(NULL != pFailRel->pScopes->Elements) + { + DhcpRpcFreeMemory(pFailRel->pScopes->Elements); + } + DhcpRpcFreeMemory(pFailRel->pScopes); + } + //Frees the relationship + DhcpRpcFreeMemory(pFailRel); + pFailRel=NULL; + } +} + +DWORD DeactivateScopes(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray) +{ + DWORD dwError = ERROR_SUCCESS; + DWORD dwIndex = 0; + LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ = NULL; + for(dwIndex = 0 ; dwIndex < pArray->NumElements ; dwIndex++) + { + dwError = DhcpGetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],&pSubnetInfoVQ); + if(ERROR_SUCCESS != dwError) + return dwError; + + // set the scope to deactivated + pSubnetInfoVQ->SubnetState= DhcpSubnetDisabled; + dwError = DhcpSetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],pSubnetInfoVQ); + if(dwError != ERROR_SUCCESS) + { + return dwError; + } + // Free memory for pSubnetInfoVQ + FreeSubnetInfoVQ(pSubnetInfoVQ); + pSubnetInfoVQ = NULL; + } + return dwError; +} + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; + LPWSTR pwszRelationshipName = L"test"; + LPDHCP_FAILOVER_RELATIONSHIP pRelationShip = NULL; + DWORD dwError = ERROR_SUCCESS; + + dwError = DhcpV4FailoverGetRelationship( + pwszServer, + pwszRelationshipName, + &pRelationShip); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetRelationship failed with Error = %d\n",dwError); + goto cleanup; + } + // Deactivate scopes on partner server + dwError = DeactivateScopes(pRelationShip->SecondaryServerName, pRelationShip->pScopes); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"Failed to deactivate scopes on partner server\n"); + goto cleanup; + } + // Deactivate scopes on current server + dwError = DeactivateScopes(pRelationShip->PrimaryServerName, pRelationShip->pScopes); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"Failed to deactivate scopes on primary server\n"); + goto cleanup; + } + + //Delete relationship from partner server + dwError = DhcpV4FailoverDeleteRelationship( + pRelationShip->SecondaryServerName, + pwszRelationshipName); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverDeleteRelationship failed with Error = %d\n",dwError); + //Even if relationship on partner server is not getting deleted, we shouldnt stop deleting relationship on the current server + // It might have happened that the tcp connection is down and partner server is not reachable. + // That shouldnt restrict us from deleting the relationship on the current server. + } + + //Delete relationship from primary server + dwError = DhcpV4FailoverDeleteRelationship( + pwszServer, + pwszRelationshipName); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverDeleteRelationship failed with Error = %d\n",dwError); + } +cleanup: + FreeRelationshipMemory(pRelationShip); + return 0; +} diff --git a/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.sln b/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.sln new file mode 100644 index 00000000..941e9320 --- /dev/null +++ b/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeleteRelationship", "DeleteRelationship.vcxproj", "{1703A2F3-9335-48AE-A356-68C663E211E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1703A2F3-9335-48AE-A356-68C663E211E9}.Debug|x64.ActiveCfg = Debug|x64 + {1703A2F3-9335-48AE-A356-68C663E211E9}.Debug|x64.Build.0 = Debug|x64 + {1703A2F3-9335-48AE-A356-68C663E211E9}.Release|x64.ActiveCfg = Release|x64 + {1703A2F3-9335-48AE-A356-68C663E211E9}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.vcxproj b/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.vcxproj new file mode 100644 index 00000000..1bd0e2c5 --- /dev/null +++ b/Samples/DHCP/DeleteRelationship/cpp/DeleteRelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {1703A2F3-9335-48AE-A356-68C663E211E9} + Win32Proj + DeleteRelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + DeleteRelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/DeleteScopeFromRelationship/README.md b/Samples/DHCP/DeleteScopeFromRelationship/README.md new file mode 100644 index 00000000..66af3593 --- /dev/null +++ b/Samples/DHCP/DeleteScopeFromRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverDeleteScopeFromRelationship API sample +==================================================== + +This sample explains the usage of the DhcpV4FailoverDeleteScopeFromRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverDeleteScopeFromRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404307) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.cpp b/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.cpp new file mode 100644 index 00000000..43daf6b6 --- /dev/null +++ b/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.cpp @@ -0,0 +1,168 @@ +// 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 +#include +#include + +//This routine frees LPDHCP_SUBNET_INFO_VQ +void FreeSubnetInfoVQ(LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ) +{ + // Frees NetBios Name + if(pSubnetInfoVQ->PrimaryHost.NetBiosName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.NetBiosName); + + //Frees host name + if(pSubnetInfoVQ->PrimaryHost.HostName) + DhcpRpcFreeMemory(pSubnetInfoVQ->PrimaryHost.HostName); + + // Frees Subnet Name + if(pSubnetInfoVQ->SubnetName) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetName); + + // Frees subnet comment + if(pSubnetInfoVQ->SubnetComment) + DhcpRpcFreeMemory(pSubnetInfoVQ->SubnetComment); + + DhcpRpcFreeMemory(pSubnetInfoVQ); +} + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + // Frees relationship name + if (NULL != pFailRel->RelationshipName) + DhcpRpcFreeMemory(pFailRel->RelationshipName); + + // Frees shared secret + if( NULL != pFailRel->SharedSecret) + DhcpRpcFreeMemory(pFailRel->SharedSecret); + + //Frees Primary server's name + if (NULL != pFailRel->PrimaryServerName) + DhcpRpcFreeMemory(pFailRel->PrimaryServerName); + + // Frees Secondary server's name + if (NULL != pFailRel->SecondaryServerName) + DhcpRpcFreeMemory(pFailRel->SecondaryServerName); + + //Frees the relationship + DhcpRpcFreeMemory(pFailRel); + pFailRel=NULL; + } +} + +DWORD DeactivateScopes(_In_ LPWSTR pServer, _Inout_ LPDHCP_IP_ARRAY pArray) +{ + DWORD dwError = ERROR_SUCCESS; + DWORD dwIndex = 0; + LPDHCP_SUBNET_INFO_VQ pSubnetInfoVQ = NULL; + for(dwIndex = 0 ; dwIndex < pArray->NumElements ; dwIndex++) + { + dwError = DhcpGetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],&pSubnetInfoVQ); + if(ERROR_SUCCESS != dwError) + return dwError; + + // set the scope to deactivated + pSubnetInfoVQ->SubnetState= DhcpSubnetDisabled; + dwError = DhcpSetSubnetInfoVQ(pServer,pArray->Elements[dwIndex],pSubnetInfoVQ); + if(dwError != ERROR_SUCCESS) + { + return dwError; + } + // Free memory for pSubnetInfoVQ + FreeSubnetInfoVQ(pSubnetInfoVQ); + pSubnetInfoVQ = NULL; + } + return dwError; +} + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //Server IP Address + LPWSTR pwszRelationshipName = L"test"; // Name of the relationship + LPDHCP_FAILOVER_RELATIONSHIP pRelationship = NULL; // Failover relationship + LPDHCP_IP_ARRAY pIpAddressArray = NULL; // IP Address array having the scopes + DWORD dwError = ERROR_SUCCESS; // Variable to hold the error code + dwError = DhcpV4FailoverGetRelationship(pwszServer,pwszRelationshipName,&pRelationship); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetRelationship failed with Error = %d\n", dwError); + goto cleanup; + } + + pIpAddressArray = (LPDHCP_IP_ARRAY)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DHCP_IP_ARRAY)); + if(pIpAddressArray == NULL) + { + wprintf(L"HeapAlloc failed !! Not enough memory\n"); + goto cleanup; + } + pIpAddressArray->NumElements = 1; + pIpAddressArray->Elements=(LPDHCP_IP_ADDRESS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(DHCP_IP_ADDRESS)); + if(pIpAddressArray->Elements == NULL) + { + wprintf(L"HeapAlloc failed. Not enough memory\n"); + goto cleanup; + } + pIpAddressArray->Elements[0]=0xac100000; + + if (NULL != pRelationship->pScopes) + { + if(NULL != pRelationship->pScopes->Elements) + { + DhcpRpcFreeMemory(pRelationship->pScopes->Elements); + } + DhcpRpcFreeMemory(pRelationship->pScopes); + } + pRelationship->pScopes = pIpAddressArray; + + // Deactivate scopes on partner server + dwError = DeactivateScopes(pRelationship->SecondaryServerName, pRelationship->pScopes); + if( ERROR_SUCCESS != dwError) + { wprintf(L"Failed to deactivate scopes on partner server\n"); + goto cleanup; + } + // Deactivate scopes on current server + dwError = DeactivateScopes(pRelationship->PrimaryServerName, pRelationship->pScopes); + if( ERROR_SUCCESS != dwError) + { wprintf(L"Failed to deactivate scopes on primary server\n"); + goto cleanup; + } + + dwError = DhcpV4FailoverDeleteScopeFromRelationship( + pRelationship->SecondaryServerName, + pRelationship); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverDeleteScopeFromRelationship failed with Error = %d\n for partner server",dwError); + goto cleanup; + } + + dwError = DhcpV4FailoverDeleteScopeFromRelationship( + pwszServer, + pRelationship); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverDeleteScopeFromRelationship failed with Error = %d for primary server\n",dwError); + } +cleanup: + if( NULL != pIpAddressArray ) + { + if( NULL != pIpAddressArray->Elements) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pIpAddressArray->Elements); + pIpAddressArray->Elements = NULL; + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pIpAddressArray); + pIpAddressArray = NULL; + } + FreeRelationshipMemory(pRelationship); + return 0; +} diff --git a/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.sln b/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.sln new file mode 100644 index 00000000..0b419559 --- /dev/null +++ b/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeleteScopeFromRelationship", "DeleteScopeFromRelationship.vcxproj", "{9CDF71A9-BE9B-490F-BDB9-0327AE5D5BAB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9CDF71A9-BE9B-490F-BDB9-0327AE5D5BAB}.Debug|x64.ActiveCfg = Debug|x64 + {9CDF71A9-BE9B-490F-BDB9-0327AE5D5BAB}.Debug|x64.Build.0 = Debug|x64 + {9CDF71A9-BE9B-490F-BDB9-0327AE5D5BAB}.Release|x64.ActiveCfg = Release|x64 + {9CDF71A9-BE9B-490F-BDB9-0327AE5D5BAB}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.vcxproj b/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.vcxproj new file mode 100644 index 00000000..2d8a981c --- /dev/null +++ b/Samples/DHCP/DeleteScopeFromRelationship/cpp/DeleteScopeFromRelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {9CDF71A9-BE9B-490F-BDB9-0327AE5D5BAB} + Win32Proj + DeleteScopeFromRelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + DeleteScopeFromRelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/EnumPolicy/README.md b/Samples/DHCP/EnumPolicy/README.md new file mode 100644 index 00000000..0a1a3c3d --- /dev/null +++ b/Samples/DHCP/EnumPolicy/README.md @@ -0,0 +1,42 @@ +DhcpV4EnumPolicies API sample +============================= + +This sample explains the usage of the DhcpV4EnumPolicies API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4EnumPolicies**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404295) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/EnumPolicy/cpp/enumpolicy.cpp b/Samples/DHCP/EnumPolicy/cpp/enumpolicy.cpp new file mode 100644 index 00000000..dd3e2c6b --- /dev/null +++ b/Samples/DHCP/EnumPolicy/cpp/enumpolicy.cpp @@ -0,0 +1,125 @@ +// 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 +#include +#include +#include + + +// This routine frees LPDHCP_POLICY and its internal elements. +VOID FreeDhcpPolicyMemory(DHCP_POLICY pDhcpPolicy) +{ + // Frees the policy name + if (NULL != pDhcpPolicy.PolicyName) + DhcpRpcFreeMemory(pDhcpPolicy.PolicyName); + + // Frees the policy description + if( NULL != pDhcpPolicy.Description) + DhcpRpcFreeMemory(pDhcpPolicy.Description); + + // Frees the policy condition + if(NULL != pDhcpPolicy.Conditions) + { + for(DWORD dwIndex = 0; dwIndexNumElements; dwIndex++) + { + // Frees the vendorName holder in condition's elements, if it exists + if( NULL != pDhcpPolicy.Conditions->Elements[dwIndex].VendorName) + DhcpRpcFreeMemory(pDhcpPolicy.Conditions->Elements[dwIndex].VendorName); + + // Frees the "bytes" used for storing condition values + if (NULL != pDhcpPolicy.Conditions->Elements[dwIndex].Value) + DhcpRpcFreeMemory(pDhcpPolicy.Conditions->Elements[dwIndex].Value); + } + DhcpRpcFreeMemory(pDhcpPolicy.Conditions); + } + + // Frees the policy expression + if(NULL != pDhcpPolicy.Expressions) + { + // Frees the expression elements, if they exist + if(pDhcpPolicy.Expressions->NumElements && pDhcpPolicy.Expressions->Elements) + DhcpRpcFreeMemory(pDhcpPolicy.Expressions->Elements); + DhcpRpcFreeMemory(pDhcpPolicy.Expressions); + } + + // Frees the policy ranges + if(NULL != pDhcpPolicy.Ranges) + { + // Frees the individual range elements + if(pDhcpPolicy.Ranges->Elements) + DhcpRpcFreeMemory(pDhcpPolicy.Ranges->Elements); + DhcpRpcFreeMemory(pDhcpPolicy.Ranges); + } +} + +// This routine frees LPDHCP_POLICY_ARRAY and its internal elements. +VOID FreeDhcpPolicyInfoMemory(LPDHCP_POLICY_ARRAY pEnumPoliciesInfo) +{ + if(NULL != pEnumPoliciesInfo) + { + for(DWORD dwIndex=0; dwIndex < pEnumPoliciesInfo->NumElements; dwIndex++) + { + FreeDhcpPolicyMemory(pEnumPoliciesInfo->Elements[dwIndex]); + } + DhcpRpcFreeMemory(pEnumPoliciesInfo); + pEnumPoliciesInfo = NULL; + } +} + +int __cdecl main(void) +{ + DWORD dwError = ERROR_MORE_DATA; + DWORD dwElementsRead = 0; + DWORD dwScopeId = 0xa000000; + DWORD dwElementsTotal = 0; + DWORD preferredMax = DWORD_MAX; + LPWSTR pwszServer = NULL; + LPDHCP_POLICY_ARRAY enumPoliciesInfo = NULL; + DWORD resumeHandle = 0; + DWORD dwIdx = 0; + for(;;) + { + dwError = DhcpV4EnumPolicies( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed) + &resumeHandle, // Resume Handle + preferredMax, // Preferred maximum + (dwScopeId==0), // fGlobalPolicy, global policy or scope level policy + dwScopeId, // Subnet Address + &enumPoliciesInfo, // DHCP_POLICY_ARRAY containing policies + &dwElementsRead, // Total number of elements read + &dwElementsTotal // Total number of elements + ); + if ((NO_ERROR != dwError) && + (ERROR_MORE_DATA != dwError) && + (ERROR_NO_MORE_ITEMS != dwError )) + { + wprintf(L"Error in enumerating policies. Error = %d\n",dwError); + break; + } + if (dwElementsRead && enumPoliciesInfo) + { + //operate on enumPoliciesInfo, for example in the below snippet, we are printing the names of the + // enumerated policies. + for ( dwIdx = 0; dwIdx < enumPoliciesInfo->NumElements; dwIdx++ ) + { + wprintf(L"policies name = %s \n",enumPoliciesInfo->Elements[dwIdx].PolicyName); + } + //one needs to free the enumPoliciesInfo once used + FreeDhcpPolicyInfoMemory(enumPoliciesInfo); + enumPoliciesInfo = NULL; + } + if (ERROR_NO_MORE_ITEMS == dwError || (dwError == ERROR_SUCCESS && dwElementsTotal == 0)) + { + dwError=ERROR_SUCCESS; + break; + } + dwElementsRead = 0; + dwElementsTotal = 0; + } + return 0; +} diff --git a/Samples/DHCP/EnumPolicy/cpp/enumpolicy.sln b/Samples/DHCP/EnumPolicy/cpp/enumpolicy.sln new file mode 100644 index 00000000..de26b369 --- /dev/null +++ b/Samples/DHCP/EnumPolicy/cpp/enumpolicy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "enumpolicy", "enumpolicy.vcxproj", "{7F08F34C-FF6A-4135-AEAA-A4D3C9359B6C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7F08F34C-FF6A-4135-AEAA-A4D3C9359B6C}.Debug|x64.ActiveCfg = Debug|x64 + {7F08F34C-FF6A-4135-AEAA-A4D3C9359B6C}.Debug|x64.Build.0 = Debug|x64 + {7F08F34C-FF6A-4135-AEAA-A4D3C9359B6C}.Release|x64.ActiveCfg = Release|x64 + {7F08F34C-FF6A-4135-AEAA-A4D3C9359B6C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/EnumPolicy/cpp/enumpolicy.vcxproj b/Samples/DHCP/EnumPolicy/cpp/enumpolicy.vcxproj new file mode 100644 index 00000000..040eacbd --- /dev/null +++ b/Samples/DHCP/EnumPolicy/cpp/enumpolicy.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {7F08F34C-FF6A-4135-AEAA-A4D3C9359B6C} + Win32Proj + enumpolicy + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + enumpolicy + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/EnumRelationship/README.md b/Samples/DHCP/EnumRelationship/README.md new file mode 100644 index 00000000..19415d47 --- /dev/null +++ b/Samples/DHCP/EnumRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverEnumRelationship API sample +========================================= + +This sample explains the usage of the DhcpV4FailoverEnumRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverEnumRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404309) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.cpp b/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.cpp new file mode 100644 index 00000000..a9e416c3 --- /dev/null +++ b/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.cpp @@ -0,0 +1,116 @@ +// 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 +#include +#include +#include + +void FreeIPArray(LPDHCP_IP_ARRAY Array) +{ + if(Array) + { + DhcpRpcFreeMemory(Array->Elements); + + } + DhcpRpcFreeMemory(Array); + Array = NULL; + +} + +void +FreeDhcpFailoverRelationship( + DHCP_FAILOVER_RELATIONSHIP FailoverRelationship) +{ + DhcpRpcFreeMemory(FailoverRelationship.RelationshipName); + DhcpRpcFreeMemory(FailoverRelationship.PrimaryServerName); + DhcpRpcFreeMemory(FailoverRelationship.SecondaryServerName); + FreeIPArray(FailoverRelationship.pScopes); + DhcpRpcFreeMemory(FailoverRelationship.SharedSecret); +} + +void +FreeDhcpFailoverRelationship( + LPDHCP_FAILOVER_RELATIONSHIP pFailoverInfo) +{ + if (NULL == pFailoverInfo) + return; + + FreeDhcpFailoverRelationship(*pFailoverInfo); + + DhcpRpcFreeMemory(pFailoverInfo); + pFailoverInfo = NULL; +} + + +void +FreeDhcpFailoverRelationshipArray( + LPDHCP_FAILOVER_RELATIONSHIP_ARRAY FailoverEnumInfo) +{ + if (NULL == FailoverEnumInfo) + return; + + for (DWORD i = 0; i < FailoverEnumInfo->NumElements; i++) + { + FreeDhcpFailoverRelationship(FailoverEnumInfo->pRelationships[i]); + } + + DhcpRpcFreeMemory(FailoverEnumInfo->pRelationships); + DhcpRpcFreeMemory(FailoverEnumInfo); + FailoverEnumInfo = NULL; +} + +int __cdecl main(void) +{ + DWORD dwError = ERROR_MORE_DATA; + DWORD dwElementsRead = 0; + DWORD dwElementsTotal = 0; + DWORD preferredMax = DWORD_MAX; + LPWSTR pwszServer = NULL; + LPDHCP_FAILOVER_RELATIONSHIP_ARRAY enumRelationInfo = NULL; + DWORD resumeHandle = 0; + DWORD dwIdx = 0; + for(;;) + { + dwError = DhcpV4FailoverEnumRelationship( + pwszServer, + &resumeHandle, + preferredMax, + &enumRelationInfo, + &dwElementsRead, + &dwElementsTotal); + + if ((NO_ERROR != dwError) && + (ERROR_MORE_DATA != dwError) && + (ERROR_NO_MORE_ITEMS != dwError )) + { + wprintf(L"Error in enumerating relationships. Error = %d\n",dwError); + break; + } + if (dwElementsRead && enumRelationInfo) + { + //operate on enumPoliciesInfo, for example in the below snippet, we are printing the names of the + // enumerated relationships. + for ( dwIdx = 0; dwIdx < enumRelationInfo->NumElements; dwIdx++ ) + { + wprintf(L"Relationship name = %s\n",enumRelationInfo->pRelationships[dwIdx].RelationshipName); + } + FreeDhcpFailoverRelationshipArray(enumRelationInfo); + enumRelationInfo = NULL; + } + if (ERROR_NO_MORE_ITEMS == dwError || (dwError == ERROR_SUCCESS && dwElementsTotal == 0)) + { + dwError=ERROR_SUCCESS; + break; + } + dwElementsRead = 0; + dwElementsTotal = 0; + } + + return 0; +} diff --git a/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.sln b/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.sln new file mode 100644 index 00000000..61dfcf70 --- /dev/null +++ b/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EnumRelationship", "EnumRelationship.vcxproj", "{B518D28F-51CA-4CF9-AEDA-BB9978855A8B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B518D28F-51CA-4CF9-AEDA-BB9978855A8B}.Debug|x64.ActiveCfg = Debug|x64 + {B518D28F-51CA-4CF9-AEDA-BB9978855A8B}.Debug|x64.Build.0 = Debug|x64 + {B518D28F-51CA-4CF9-AEDA-BB9978855A8B}.Release|x64.ActiveCfg = Release|x64 + {B518D28F-51CA-4CF9-AEDA-BB9978855A8B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.vcxproj b/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.vcxproj new file mode 100644 index 00000000..2c681a02 --- /dev/null +++ b/Samples/DHCP/EnumRelationship/cpp/EnumRelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {B518D28F-51CA-4CF9-AEDA-BB9978855A8B} + Win32Proj + EnumRelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + EnumRelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/EnumSubnetClients/README.md b/Samples/DHCP/EnumSubnetClients/README.md new file mode 100644 index 00000000..5e65d78f --- /dev/null +++ b/Samples/DHCP/EnumSubnetClients/README.md @@ -0,0 +1,42 @@ +DhcpV4EnumSubnetClients API sample +================================== + +This sample explains the usage of the DhcpV4EnumSubnetClients API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4EnumSubnetClients**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404297) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-\>Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.cpp b/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.cpp new file mode 100644 index 00000000..f28690c5 --- /dev/null +++ b/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.cpp @@ -0,0 +1,120 @@ +// 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 +#include +#include +#include + + +// This routine frees LPDHCP_CLIENT_INFO_PB and its internal elements. +VOID FreeDhcpEnumSubnetClientMemory(LPDHCP_CLIENT_INFO_PB pEnumClientInfo) +{ + if( NULL != pEnumClientInfo) + { + + if(pEnumClientInfo->ClientHardwareAddress.Data) + { + DhcpRpcFreeMemory(pEnumClientInfo->ClientHardwareAddress.Data); + pEnumClientInfo->ClientHardwareAddress.Data = NULL; + } + if(pEnumClientInfo->ClientName) + { + DhcpRpcFreeMemory(pEnumClientInfo->ClientName); + pEnumClientInfo->ClientName = NULL; + } + if(pEnumClientInfo->ClientComment) + { + DhcpRpcFreeMemory(pEnumClientInfo->ClientComment); + pEnumClientInfo->ClientComment = NULL; + } + if(pEnumClientInfo->OwnerHost.HostName) + { + DhcpRpcFreeMemory(pEnumClientInfo->OwnerHost.HostName); + pEnumClientInfo->OwnerHost.HostName = NULL; + } + if(pEnumClientInfo->OwnerHost.NetBiosName) + { + DhcpRpcFreeMemory(pEnumClientInfo->OwnerHost.NetBiosName); + pEnumClientInfo->OwnerHost.NetBiosName = NULL; + } + if(pEnumClientInfo->PolicyName) + { + DhcpRpcFreeMemory(pEnumClientInfo->PolicyName); + pEnumClientInfo->PolicyName = NULL; + } + DhcpRpcFreeMemory(pEnumClientInfo); + } + pEnumClientInfo = NULL; +} + +// This routine frees LPDHCP_CLIENT_INFO_PB_ARRAY and its internal elements. +VOID FreeDhcpEnumSubnetClientInfo(LPDHCP_CLIENT_INFO_PB_ARRAY pEnumClientArray) +{ + if(NULL != pEnumClientArray) + { + for(DWORD dwIndex=0; dwIndex < pEnumClientArray->NumElements; dwIndex++) + { + FreeDhcpEnumSubnetClientMemory(pEnumClientArray->Clients[dwIndex]); + } + DhcpRpcFreeMemory(pEnumClientArray); + pEnumClientArray = NULL; + } +} + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to hold error code + DWORD dwElementsRead = 0; // Variable to hold number of elements read + DWORD dwSubnetAddress = 0xa000000; // Variable to hold subnet address + DWORD dwElementsTotal = 0; // Variable to hold total number of elements + DWORD preferredMax = DWORD_MAX; // Variable to hold Preferred maximum value to be fetched in one call of DhcpV4EnumSubnetClients + LPWSTR pwszServer = NULL; // Variable to hold Server IP Address + LPDHCP_CLIENT_INFO_PB_ARRAY pEnumClientInfo = NULL; // Variable to hold subnet clients fetched using DhcpV4EnumSubnetClients + DWORD resumeHandle = 0; // variable to hold resume handle + DWORD dwIdx = 0; + + for(;;) + { + dwError = DhcpV4EnumSubnetClients( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed) + dwSubnetAddress, // Subnet Address + &resumeHandle, // Resume Handle + preferredMax, // Preferred maximum + &pEnumClientInfo, // Pointer to a DHCP_CLIENT_INFO_PB_ARRAY, contains the DHCP client lease records set available for the specified subnet. + &dwElementsRead, // Total number of elements read + &dwElementsTotal // Total number of elements + ); + if ((ERROR_SUCCESS != dwError) && + (ERROR_MORE_DATA != dwError) && + (ERROR_NO_MORE_ITEMS != dwError )) + { + wprintf(L"Error in enumerating policies. Error = %d\n",dwError); + break; + } + if (dwElementsRead && pEnumClientInfo) + { + //operate on pEnumClientInfo + for ( dwIdx = 0; dwIdx < pEnumClientInfo->NumElements; dwIdx++ ) + { + wprintf(L"ClientIpAddress = %u \n",pEnumClientInfo->Clients[dwIdx]->ClientIpAddress); + wprintf(L"PolicyName = %s \n",pEnumClientInfo->Clients[dwIdx]->PolicyName); + } + //one needs to free the pEnumClientInfo once used + FreeDhcpEnumSubnetClientInfo(pEnumClientInfo); + pEnumClientInfo = NULL; + } + if (dwError == ERROR_SUCCESS || dwError == ERROR_NO_MORE_ITEMS) + { + break; + } + dwElementsRead = 0; + dwElementsTotal = 0; + } + return 0; +} diff --git a/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.sln b/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.sln new file mode 100644 index 00000000..ee861354 --- /dev/null +++ b/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EnumSubnetClients", "EnumSubnetClients.vcxproj", "{6B4D1C35-F1FF-4FDC-AB6F-EEB1324B2FB3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6B4D1C35-F1FF-4FDC-AB6F-EEB1324B2FB3}.Debug|x64.ActiveCfg = Debug|x64 + {6B4D1C35-F1FF-4FDC-AB6F-EEB1324B2FB3}.Debug|x64.Build.0 = Debug|x64 + {6B4D1C35-F1FF-4FDC-AB6F-EEB1324B2FB3}.Release|x64.ActiveCfg = Release|x64 + {6B4D1C35-F1FF-4FDC-AB6F-EEB1324B2FB3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.vcxproj b/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.vcxproj new file mode 100644 index 00000000..a36febcb --- /dev/null +++ b/Samples/DHCP/EnumSubnetClients/cpp/EnumSubnetClients.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {6B4D1C35-F1FF-4FDC-AB6F-EEB1324B2FB3} + Win32Proj + EnumSubnetClients + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + EnumSubnetClients + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/EnumSubnetReservations/README.md b/Samples/DHCP/EnumSubnetReservations/README.md new file mode 100644 index 00000000..de4d100a --- /dev/null +++ b/Samples/DHCP/EnumSubnetReservations/README.md @@ -0,0 +1,42 @@ +DhcpV4EnumSubnetReservations API sample +======================================= + +This sample explains the usage of the DhcpV4EnumSubnetReservations API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4EnumSubnetReservations**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404299) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.cpp b/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.cpp new file mode 100644 index 00000000..005cc73c --- /dev/null +++ b/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.cpp @@ -0,0 +1,105 @@ +// 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 +#include +#include +#include + + +// This routine frees LPDHCP_IP_RESERVATION_INFO and its internal elements. +VOID FreeDhcpEnumSubnetReservationsMemory(LPDHCP_IP_RESERVATION_INFO pEnumReservationInfo) +{ + if( NULL != pEnumReservationInfo) + { + if(pEnumReservationInfo->ReservedForClient.Data) + { + DhcpRpcFreeMemory(pEnumReservationInfo->ReservedForClient.Data); + pEnumReservationInfo->ReservedForClient.Data = NULL; + } + if(pEnumReservationInfo->ReservedClientName) + { + DhcpRpcFreeMemory(pEnumReservationInfo->ReservedClientName); + pEnumReservationInfo->ReservedClientName= NULL; + } + if(pEnumReservationInfo->ReservedClientDesc) + { + DhcpRpcFreeMemory(pEnumReservationInfo->ReservedClientDesc); + pEnumReservationInfo->ReservedClientDesc= NULL; + } + DhcpRpcFreeMemory(pEnumReservationInfo); + } + pEnumReservationInfo = NULL; +} + +// This routine frees LPDHCP_RESERVATION_INFO_ARRAY and its internal elements. +VOID FreeDhcpEnumSubnetReservationsInfo(LPDHCP_RESERVATION_INFO_ARRAY pEnumReservationInfoArray) +{ + if(NULL != pEnumReservationInfoArray) + { + for(DWORD dwIndex=0; dwIndex < pEnumReservationInfoArray->NumElements; dwIndex++) + { + FreeDhcpEnumSubnetReservationsMemory(pEnumReservationInfoArray->Elements[dwIndex]); + } + DhcpRpcFreeMemory(pEnumReservationInfoArray); + pEnumReservationInfoArray = NULL; + } +} + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to hold error code + DWORD dwElementsRead = 0; // Number of elements read + DWORD dwSubnetAddress = 0xa000000; // Subnet Address 10.0.0.0 + DWORD dwElementsTotal = 0; // Variable to hold total number of elements + DWORD preferredMax = DWORD_MAX; // Preferred maximum value to be used in DhcpV4EnumSubnetReservations + LPWSTR pwszServer = NULL; // Server IP Address + LPDHCP_RESERVATION_INFO_ARRAY pEnumReservationInfo = NULL; // Variable to hold the reservations + DWORD resumeHandle = 0; // Variable to hold resume handle + DWORD dwIdx = 0; + for(;;) + { + dwError = DhcpV4EnumSubnetReservations( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed) + dwSubnetAddress, // Subnet Address + &resumeHandle, // Resume Handle + preferredMax, // Preferred maximum + &pEnumReservationInfo, // Pointer to a DHCP_RESERVATION_INFO_ARRAY, contains the reservations elements available for the specified subnet. + &dwElementsRead, // Total number of elements read + &dwElementsTotal // Total number of elements + ); + if ((NO_ERROR != dwError) && + (ERROR_MORE_DATA != dwError) && + (ERROR_NO_MORE_ITEMS != dwError )) + { + wprintf(L"Error in enumerating policies. Error = %d\n",dwError); + break; + } + if (dwElementsRead && pEnumReservationInfo) + { + //operate on pEnumReservationInfo + for ( dwIdx = 0; dwIdx < pEnumReservationInfo->NumElements; dwIdx++ ) + { + wprintf(L"ReservedClientName = %s \n",pEnumReservationInfo->Elements[dwIdx]->ReservedClientName); + wprintf(L"ReservedIpAddress = %u\n",pEnumReservationInfo->Elements[dwIdx]->ReservedIpAddress); + } + //one needs to free the pEnumReservationInfo once used + FreeDhcpEnumSubnetReservationsInfo(pEnumReservationInfo); + pEnumReservationInfo= NULL; + } + if (ERROR_NO_MORE_ITEMS == dwError || (dwError == ERROR_SUCCESS && dwElementsTotal == 0)) + { + dwError=ERROR_SUCCESS; + break; + } + dwElementsRead = 0; + dwElementsTotal = 0; + } + return 0; +} diff --git a/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.sln b/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.sln new file mode 100644 index 00000000..188e696f --- /dev/null +++ b/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EnumSubnetReservations", "EnumSubnetReservations.vcxproj", "{AF39F376-632E-4F99-B2F5-53BB3A2DF243}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AF39F376-632E-4F99-B2F5-53BB3A2DF243}.Debug|x64.ActiveCfg = Debug|x64 + {AF39F376-632E-4F99-B2F5-53BB3A2DF243}.Debug|x64.Build.0 = Debug|x64 + {AF39F376-632E-4F99-B2F5-53BB3A2DF243}.Release|x64.ActiveCfg = Release|x64 + {AF39F376-632E-4F99-B2F5-53BB3A2DF243}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.vcxproj b/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.vcxproj new file mode 100644 index 00000000..06b0e05a --- /dev/null +++ b/Samples/DHCP/EnumSubnetReservations/cpp/EnumSubnetReservations.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {AF39F376-632E-4F99-B2F5-53BB3A2DF243} + Win32Proj + EnumSubnetReservations + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + EnumSubnetReservations + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetAddressStatus/README.md b/Samples/DHCP/GetAddressStatus/README.md new file mode 100644 index 00000000..fe699902 --- /dev/null +++ b/Samples/DHCP/GetAddressStatus/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverGetAddressStatus API sample +========================================= + +This sample explains the usage of the DhcpV4FailoverGetAddressStatus API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverGetAddressStatus**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404311) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.cpp b/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.cpp new file mode 100644 index 00000000..5c15a4f9 --- /dev/null +++ b/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.cpp @@ -0,0 +1,47 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + + +#include +#include +#include + +int __cdecl main(void) +{ + DWORD dwStatus = 0; // Status of the address + DWORD dwSubnet = 0xa000033; //(10.0.0.51) + DWORD dwError = ERROR_SUCCESS; // Variable to hold error code + LPWSTR pwszServer = NULL; // Server IP Address + + dwError = DhcpV4FailoverGetAddressStatus( + pwszServer, + dwSubnet, + &dwStatus); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetAddressStatus failed with Error = %d\n",dwError); + return 0; + } + switch(dwStatus) + { + case 0: + wprintf(L"The address is with primary server\n"); + break; + case 1: + wprintf(L"The address is with secondary (partner) server\n"); + break; + case 2: + wprintf(L"The address is neither with primary nor with secondary\n"); + break; + case 3: + wprintf(L"The address corresponds to Reservation\n"); + break; + default: + wprintf(L"Unknown status\n"); + } + return 0; +} diff --git a/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.sln b/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.sln new file mode 100644 index 00000000..df0cb2fd --- /dev/null +++ b/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetAddressStatus", "GetAddressStatus.vcxproj", "{66E947BF-943C-4E1A-B0A8-C78AAE078FCD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {66E947BF-943C-4E1A-B0A8-C78AAE078FCD}.Debug|x64.ActiveCfg = Debug|x64 + {66E947BF-943C-4E1A-B0A8-C78AAE078FCD}.Debug|x64.Build.0 = Debug|x64 + {66E947BF-943C-4E1A-B0A8-C78AAE078FCD}.Release|x64.ActiveCfg = Release|x64 + {66E947BF-943C-4E1A-B0A8-C78AAE078FCD}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.vcxproj b/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.vcxproj new file mode 100644 index 00000000..de349c19 --- /dev/null +++ b/Samples/DHCP/GetAddressStatus/cpp/GetAddressStatus.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {66E947BF-943C-4E1A-B0A8-C78AAE078FCD} + Win32Proj + GetAddressStatus + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetAddressStatus + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetClientInfo/README.md b/Samples/DHCP/GetClientInfo/README.md new file mode 100644 index 00000000..5c971d17 --- /dev/null +++ b/Samples/DHCP/GetClientInfo/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverGetClientInfo API sample +====================================== + +This sample explains the usage of the DhcpV4FailoverGetClientInfo API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverGetClientInfo**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404313) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.cpp b/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.cpp new file mode 100644 index 00000000..280f50e8 --- /dev/null +++ b/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.cpp @@ -0,0 +1,78 @@ +// 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 +#include +#include + +// This routine frees LPDHCPV4_FAILOVER_CLIENT_INFO and its internal elements. +VOID FreeClientInfoMemory(LPDHCPV4_FAILOVER_CLIENT_INFO pClientInfo) +{ + if (NULL != pClientInfo) + { + // Frees client name + if( NULL != pClientInfo->ClientName) + DhcpRpcFreeMemory(pClientInfo->ClientName); + + //Frees policy name + if (NULL != pClientInfo->PolicyName) + DhcpRpcFreeMemory(pClientInfo->PolicyName); + + //Frees client comments + if (NULL != pClientInfo->ClientComment) + DhcpRpcFreeMemory(pClientInfo->ClientComment); + + //Frees the ClientHardwareAddress + if(NULL != pClientInfo->ClientHardwareAddress.Data && pClientInfo->ClientHardwareAddress.DataLength > 0) + DhcpRpcFreeMemory(pClientInfo->ClientHardwareAddress.Data); + + //Frees the HostName + if(NULL != pClientInfo->OwnerHost.HostName) + DhcpRpcFreeMemory(pClientInfo->OwnerHost.HostName); + + //Frees the NetBiosName + if(NULL != pClientInfo->OwnerHost.NetBiosName) + DhcpRpcFreeMemory(pClientInfo->OwnerHost.NetBiosName); + + // Frees the clientInfo + DhcpRpcFreeMemory(pClientInfo); + pClientInfo=NULL; + } +} + +int __cdecl main(void) +{ + DHCP_SEARCH_INFO *pSearchInfo = NULL; //SearchInfo + LPDHCPV4_FAILOVER_CLIENT_INFO pClientInfo = NULL; // ClientInfo + DWORD dwError = ERROR_SUCCESS; // Variable that holds the error code + LPWSTR pwszServer = NULL; //Server IP Address + + pSearchInfo = (DHCP_SEARCH_INFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(DHCP_SEARCH_INFO)); + if(pSearchInfo == NULL) + { + wprintf(L"HeapAlloc failed. Not Enough memory\n"); + goto cleanup; + } + pSearchInfo->SearchType = DhcpClientIpAddress; + pSearchInfo->SearchInfo.ClientIpAddress=0xa000033; // Client with IP Address 10.0.0.51 + dwError = DhcpV4FailoverGetClientInfo( + pwszServer, // Server IP Address + pSearchInfo, // Search Info on the basis of which clients will be fetched + &pClientInfo // ClientInfo obtained from the server + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetClientInfo failed with Error = %d\n", dwError); + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pSearchInfo); + pSearchInfo = NULL; + FreeClientInfoMemory(pClientInfo); + pClientInfo = NULL; +cleanup: + return 0; +} diff --git a/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.sln b/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.sln new file mode 100644 index 00000000..04caa06d --- /dev/null +++ b/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetClientInfo", "GetClientInfo.vcxproj", "{A656004C-4B1B-4A1A-A122-673C944918F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A656004C-4B1B-4A1A-A122-673C944918F2}.Debug|x64.ActiveCfg = Debug|x64 + {A656004C-4B1B-4A1A-A122-673C944918F2}.Debug|x64.Build.0 = Debug|x64 + {A656004C-4B1B-4A1A-A122-673C944918F2}.Release|x64.ActiveCfg = Release|x64 + {A656004C-4B1B-4A1A-A122-673C944918F2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.vcxproj b/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.vcxproj new file mode 100644 index 00000000..14a6f183 --- /dev/null +++ b/Samples/DHCP/GetClientInfo/cpp/GetClientInfo.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {A656004C-4B1B-4A1A-A122-673C944918F2} + Win32Proj + GetClientInfo + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetClientInfo + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetPolicy/README.md b/Samples/DHCP/GetPolicy/README.md new file mode 100644 index 00000000..82be1997 --- /dev/null +++ b/Samples/DHCP/GetPolicy/README.md @@ -0,0 +1,42 @@ +DhcpV4GetPolicy API sample +========================== + +This sample explains the usage of the DhcpV4GetPolicy API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4GetPolicy**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404336) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetPolicy/cpp/getpolicy.cpp b/Samples/DHCP/GetPolicy/cpp/getpolicy.cpp new file mode 100644 index 00000000..0b984c55 --- /dev/null +++ b/Samples/DHCP/GetPolicy/cpp/getpolicy.cpp @@ -0,0 +1,95 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "testPolicy" on scope 10.0.0.0 +*/ + +#include +#include +#include + +// This routine frees LPDHCP_POLICY and its internal elements. +VOID FreeDhcpPolicyMemory(LPDHCP_POLICY pDhcpPolicy) +{ + if (NULL != pDhcpPolicy) + { + // Frees the policy name + if (NULL != pDhcpPolicy->PolicyName) + DhcpRpcFreeMemory(pDhcpPolicy->PolicyName); + + // Frees the policy description + if( NULL != pDhcpPolicy->Description) + DhcpRpcFreeMemory(pDhcpPolicy->Description); + + // Frees the policy condition + if(NULL != pDhcpPolicy->Conditions) + { + for(DWORD dwIndex = 0; dwIndexConditions->NumElements; dwIndex++) + { + // Frees the vendorName holder in condition's elements, if it exists + if( NULL != pDhcpPolicy->Conditions->Elements[dwIndex].VendorName) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].VendorName); + + // Frees the "bytes" used for storing condition values + if (NULL != pDhcpPolicy->Conditions->Elements[dwIndex].Value) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].Value); + } + DhcpRpcFreeMemory(pDhcpPolicy->Conditions); + } + + // Frees the policy expression + if(NULL != pDhcpPolicy->Expressions) + { + // Frees the expression elements, if they exist + if(pDhcpPolicy->Expressions->NumElements && pDhcpPolicy->Expressions->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Expressions->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Expressions); + } + + // Frees the policy ranges + if(NULL != pDhcpPolicy->Ranges) + { + // Frees the individual range elements + if(pDhcpPolicy->Ranges->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Ranges->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Ranges); + } + + // Finally frees the policy structure + DhcpRpcFreeMemory(pDhcpPolicy); + pDhcpPolicy=NULL; + } +} + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure, this will hold the policies obtained from DhcpV4GetPolicy + LPWSTR pwszServer = NULL; // NULL signifies current server + DWORD dwScope = 0xa000000; // (10.0.0.0) Subnet address + DWORD dwError = ERROR_SUCCESS; // Variable to hold the error code + LPWSTR pwszName = L"testPolicy"; // Name of the policy + + dwError = DhcpV4GetPolicy( + pwszServer, // Server IP Address, NULL signifies the current server (where the program is executed) + (dwScope == 0), // fGlobalPolicy, TRUE means a global policy, for a global policy SubnetAddress is 0. + dwScope, // Subnet address, if it is a global policy, its value is 0 + pwszName, // Name of the policy + &pPolicy // Policy structure obtained from the server + ); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4GetPolicy returned error. + wprintf(L"DhcpV4GetPolicy failed with error %d\n",dwError); + goto cleanup; + } + FreeDhcpPolicyMemory(pPolicy); +cleanup: + return 0; +} diff --git a/Samples/DHCP/GetPolicy/cpp/getpolicy.sln b/Samples/DHCP/GetPolicy/cpp/getpolicy.sln new file mode 100644 index 00000000..06911f3b --- /dev/null +++ b/Samples/DHCP/GetPolicy/cpp/getpolicy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getpolicy", "getpolicy.vcxproj", "{2B4279D7-80C2-48F1-AA4A-55D0FF4A7E56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B4279D7-80C2-48F1-AA4A-55D0FF4A7E56}.Debug|x64.ActiveCfg = Debug|x64 + {2B4279D7-80C2-48F1-AA4A-55D0FF4A7E56}.Debug|x64.Build.0 = Debug|x64 + {2B4279D7-80C2-48F1-AA4A-55D0FF4A7E56}.Release|x64.ActiveCfg = Release|x64 + {2B4279D7-80C2-48F1-AA4A-55D0FF4A7E56}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetPolicy/cpp/getpolicy.vcxproj b/Samples/DHCP/GetPolicy/cpp/getpolicy.vcxproj new file mode 100644 index 00000000..bfb24f42 --- /dev/null +++ b/Samples/DHCP/GetPolicy/cpp/getpolicy.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {2B4279D7-80C2-48F1-AA4A-55D0FF4A7E56} + Win32Proj + getpolicy + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + getpolicy + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetRelationship/README.md b/Samples/DHCP/GetRelationship/README.md new file mode 100644 index 00000000..9392bbc4 --- /dev/null +++ b/Samples/DHCP/GetRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverGetRelationship API sample +======================================== + +This sample explains the usage of the DhcpV4FailoverGetRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverGetRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404315) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetRelationship/cpp/GetRelationship.cpp b/Samples/DHCP/GetRelationship/cpp/GetRelationship.cpp new file mode 100644 index 00000000..b8adbdf3 --- /dev/null +++ b/Samples/DHCP/GetRelationship/cpp/GetRelationship.cpp @@ -0,0 +1,72 @@ +// 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 + +/* +Assumptions: + 1) There exists a relationship with the name "test" +*/ + +#include +#include +#include + + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + // Frees relationship name + if (NULL != pFailRel->RelationshipName) + DhcpRpcFreeMemory(pFailRel->RelationshipName); + + // Frees shared secret + if( NULL != pFailRel->SharedSecret) + DhcpRpcFreeMemory(pFailRel->SharedSecret); + + //Frees Primary server's name + if (NULL != pFailRel->PrimaryServerName) + DhcpRpcFreeMemory(pFailRel->PrimaryServerName); + + // Frees Secondary server's name + if (NULL != pFailRel->SecondaryServerName) + DhcpRpcFreeMemory(pFailRel->SecondaryServerName); + + //Frees pScopes + if (NULL != pFailRel->pScopes) + { + //Frees individual elements of pScopes + if(NULL != pFailRel->pScopes->Elements) + { + DhcpRpcFreeMemory(pFailRel->pScopes->Elements); + } + DhcpRpcFreeMemory(pFailRel->pScopes); + } + //Frees the relationship + DhcpRpcFreeMemory(pFailRel); + pFailRel=NULL; + } +} + +int __cdecl main(void) +{ + LPDHCP_FAILOVER_RELATIONSHIP pRelationShip = NULL; // Failover relationship + LPWSTR pwszServer = NULL; // Server IP Address + LPWSTR pwszRelationshipName = L"test"; // Relationship name to be fetched + DWORD dwError = ERROR_SUCCESS; // Variable to hold error code + dwError = DhcpV4FailoverGetRelationship( + pwszServer, // Server IP Address, if NULL, reflects the current server (where the program is executed) + pwszRelationshipName, // Relationship name + &pRelationShip // Failover relationship + ); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetRelationship failed with Error = %d\n",dwError); + } + FreeRelationshipMemory(pRelationShip); + return 0; +} diff --git a/Samples/DHCP/GetRelationship/cpp/GetRelationship.sln b/Samples/DHCP/GetRelationship/cpp/GetRelationship.sln new file mode 100644 index 00000000..d87ebd7b --- /dev/null +++ b/Samples/DHCP/GetRelationship/cpp/GetRelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetRelationship", "GetRelationship.vcxproj", "{707BBAD3-8FA4-4277-B082-69C45173272E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {707BBAD3-8FA4-4277-B082-69C45173272E}.Debug|x64.ActiveCfg = Debug|x64 + {707BBAD3-8FA4-4277-B082-69C45173272E}.Debug|x64.Build.0 = Debug|x64 + {707BBAD3-8FA4-4277-B082-69C45173272E}.Release|x64.ActiveCfg = Release|x64 + {707BBAD3-8FA4-4277-B082-69C45173272E}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetRelationship/cpp/GetRelationship.vcxproj b/Samples/DHCP/GetRelationship/cpp/GetRelationship.vcxproj new file mode 100644 index 00000000..2637074a --- /dev/null +++ b/Samples/DHCP/GetRelationship/cpp/GetRelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {707BBAD3-8FA4-4277-B082-69C45173272E} + Win32Proj + GetRelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetRelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetScopeRelationship/README.md b/Samples/DHCP/GetScopeRelationship/README.md new file mode 100644 index 00000000..fe6112b0 --- /dev/null +++ b/Samples/DHCP/GetScopeRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverGetScopeRelationship API sample +============================================= + +This sample explains the usage of the DhcpV4FailoverGetScopeRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverGetScopeRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404317) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.cpp b/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.cpp new file mode 100644 index 00000000..dda0f22d --- /dev/null +++ b/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.cpp @@ -0,0 +1,77 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) The scope 10.0.0.0 is part of some relationship +*/ + +#include +#include +#include + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + // Frees relationship name + if (NULL != pFailRel->RelationshipName) + DhcpRpcFreeMemory(pFailRel->RelationshipName); + + // Frees shared secret + if( NULL != pFailRel->SharedSecret) + DhcpRpcFreeMemory(pFailRel->SharedSecret); + + //Frees Primary server's name + if (NULL != pFailRel->PrimaryServerName) + DhcpRpcFreeMemory(pFailRel->PrimaryServerName); + + // Frees Secondary server's name + if (NULL != pFailRel->SecondaryServerName) + DhcpRpcFreeMemory(pFailRel->SecondaryServerName); + + //Frees pScopes + if (NULL != pFailRel->pScopes) + { + //Frees individual elements of pScopes + if(NULL != pFailRel->pScopes->Elements) + { + DhcpRpcFreeMemory(pFailRel->pScopes->Elements); + } + DhcpRpcFreeMemory(pFailRel->pScopes); + } + //Frees the relationship + DhcpRpcFreeMemory(pFailRel); + pFailRel=NULL; + } +} + +int __cdecl main(void) +{ + LPDHCP_FAILOVER_RELATIONSHIP pRelationShip = NULL; // Failover relationship + LPWSTR pwszServer = NULL; // Server IP Address + DWORD dwError = ERROR_SUCCESS; // Variable to hold error code + DWORD dwScope = 0xa000000; // Subnet Address + + // This API fetches the information about the relationship of a specific scope + dwError = DhcpV4FailoverGetScopeRelationship( + pwszServer, // Server IP Address, a value of NULL reflects current server (where program is executed) + dwScope, // Subnet Address + &pRelationShip // Failover relationship + ); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetRelationship failed with Error = %d\n",dwError); + goto cleanup; + } + wprintf(L"Relationship name = %s\n",pRelationShip->RelationshipName); + FreeRelationshipMemory(pRelationShip); +cleanup: + return 0; +} diff --git a/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.sln b/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.sln new file mode 100644 index 00000000..3550b617 --- /dev/null +++ b/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetScopeRelationship", "GetScopeRelationship.vcxproj", "{028D4D77-E729-43D8-B7AB-52068E8C0E30}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {028D4D77-E729-43D8-B7AB-52068E8C0E30}.Debug|x64.ActiveCfg = Debug|x64 + {028D4D77-E729-43D8-B7AB-52068E8C0E30}.Debug|x64.Build.0 = Debug|x64 + {028D4D77-E729-43D8-B7AB-52068E8C0E30}.Release|x64.ActiveCfg = Release|x64 + {028D4D77-E729-43D8-B7AB-52068E8C0E30}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.vcxproj b/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.vcxproj new file mode 100644 index 00000000..605c50f1 --- /dev/null +++ b/Samples/DHCP/GetScopeRelationship/cpp/GetScopeRelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {028D4D77-E729-43D8-B7AB-52068E8C0E30} + Win32Proj + GetScopeRelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetScopeRelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetScopeStatistics/README.md b/Samples/DHCP/GetScopeStatistics/README.md new file mode 100644 index 00000000..66bf3256 --- /dev/null +++ b/Samples/DHCP/GetScopeStatistics/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverGetScopeStatistics API sample +=========================================== + +This sample explains the usage of the DhcpV4FailoverGetScopeStatistics API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverGetScopeStatistics**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404319) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.cpp b/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.cpp new file mode 100644 index 00000000..a850bd22 --- /dev/null +++ b/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.cpp @@ -0,0 +1,48 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 +*/ + +#include +#include +#include + +int __cdecl main(void) +{ + LPDHCP_FAILOVER_STATISTICS pStats = NULL; // Variable to hold Failover statistics for a scope + DHCP_IP_ADDRESS dwScope = 0xa000000; //(10.0.0.0) Subnet Address + LPWSTR pwszServer = NULL; // Server IP Address + DWORD dwError = ERROR_SUCCESS; // Variable to hold error values + + // This API returns the statistics w.r.t a specific scope. + dwError = DhcpV4FailoverGetScopeStatistics( + pwszServer, // Server IP Address + dwScope, // Subnet address + &pStats // Failover statistics for the scope + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetScopeStatistics failed with Error = %d\n", dwError); + goto cleanup; + } + wprintf(L"Statistics:\n"); + wprintf(L"Number of addresses: %d\n",pStats->NumAddr); + wprintf(L"Number of free addresses: %d\n",pStats->AddrFree); + wprintf(L"Number of addresses in use : %d\n",pStats->AddrInUse); + wprintf(L"Number of free partner addresses: %d\n",pStats->PartnerAddrFree); + wprintf(L"Number of partner addresses in use: %d\n",pStats->PartnerAddrInUse); +cleanup: + if(NULL != pStats) + { + DhcpRpcFreeMemory(pStats); + pStats = NULL; + } + return 0; +} diff --git a/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.sln b/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.sln new file mode 100644 index 00000000..d75b5b3f --- /dev/null +++ b/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetScopeStatistics", "GetScopeStatistics.vcxproj", "{A4F1F966-81A1-4955-924E-5F3B4A4E09A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A4F1F966-81A1-4955-924E-5F3B4A4E09A8}.Debug|x64.ActiveCfg = Debug|x64 + {A4F1F966-81A1-4955-924E-5F3B4A4E09A8}.Debug|x64.Build.0 = Debug|x64 + {A4F1F966-81A1-4955-924E-5F3B4A4E09A8}.Release|x64.ActiveCfg = Release|x64 + {A4F1F966-81A1-4955-924E-5F3B4A4E09A8}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.vcxproj b/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.vcxproj new file mode 100644 index 00000000..f6b7fd33 --- /dev/null +++ b/Samples/DHCP/GetScopeStatistics/cpp/GetScopeStatistics.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {A4F1F966-81A1-4955-924E-5F3B4A4E09A8} + Win32Proj + GetScopeStatistics + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetScopeStatistics + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetStatelessStatistics/README.md b/Samples/DHCP/GetStatelessStatistics/README.md new file mode 100644 index 00000000..ed6f320c --- /dev/null +++ b/Samples/DHCP/GetStatelessStatistics/README.md @@ -0,0 +1,42 @@ +DhcpV6GetStatelessStatistics API sample +======================================= + +This sample explains the usage of the DhcpV6GetStatelessStatistics API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV6GetStatelessStatistics**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404356) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build-**\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.cpp b/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.cpp new file mode 100644 index 00000000..a721e08e --- /dev/null +++ b/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.cpp @@ -0,0 +1,68 @@ +// 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 +#include +#include +#include + + +// This routine frees LPDHCPV6_STATELESS_STATS +VOID FreeDhcpv6StatelessStats(LPDHCPV6_STATELESS_STATS pStatelessStats) +{ + if(NULL != pStatelessStats) + { + if(NULL != pStatelessStats->ScopeStats) + { + DhcpRpcFreeMemory(pStatelessStats->ScopeStats); + } + DhcpRpcFreeMemory(pStatelessStats); + pStatelessStats = NULL; + + } +} + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to hold Error Codes + LPWSTR pwszServer = NULL; // Variable to hold Server IP Address + LPDHCPV6_STATELESS_STATS pStatelessStats = NULL; // Variable to hold stateless statistics + DWORD dwIdx = 0; + + dwError = DhcpV6GetStatelessStatistics( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed) + &pStatelessStats //Pointer to a DHCPV6_STATELESS_STATS structure that contain DHCPv6 stateless server IPv6 subnet statistics + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV6GetStatelessStatistics failed with Error = %d\n", dwError); + goto cleanup; + } + if(pStatelessStats->NumScopes == 0 || pStatelessStats->ScopeStats == NULL) + { + wprintf(L"No scopes are found\n"); + goto cleanup; + } + + wprintf(L"Statistics:\n"); + for(dwIdx = 0; dwIdx < pStatelessStats->NumScopes; dwIdx++) + { + wprintf(L"Scope High Ordered bits: %llu Low Ordered bits: %llu \n",pStatelessStats->ScopeStats[dwIdx].SubnetAddress.HighOrderBits, pStatelessStats->ScopeStats[dwIdx].SubnetAddress.LowOrderBits); + wprintf(L"NumStatelessClientsAdded : %llu\n",pStatelessStats->ScopeStats[dwIdx].NumStatelessClientsAdded); + wprintf(L"NumStatelessClientsRemoved : %llu\n",pStatelessStats->ScopeStats[dwIdx].NumStatelessClientsRemoved); + } + +cleanup: + if(NULL != pStatelessStats) + { + FreeDhcpv6StatelessStats(pStatelessStats); + pStatelessStats = NULL; + } + return 0; +} diff --git a/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.sln b/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.sln new file mode 100644 index 00000000..d1ec2733 --- /dev/null +++ b/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetStatelessStatistics", "GetStatelessStatistics.vcxproj", "{D91C9B93-6EB8-42C3-8C69-55C391C69884}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D91C9B93-6EB8-42C3-8C69-55C391C69884}.Debug|x64.ActiveCfg = Debug|x64 + {D91C9B93-6EB8-42C3-8C69-55C391C69884}.Debug|x64.Build.0 = Debug|x64 + {D91C9B93-6EB8-42C3-8C69-55C391C69884}.Release|x64.ActiveCfg = Release|x64 + {D91C9B93-6EB8-42C3-8C69-55C391C69884}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.vcxproj b/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.vcxproj new file mode 100644 index 00000000..7bfb1f74 --- /dev/null +++ b/Samples/DHCP/GetStatelessStatistics/cpp/GetStatelessStatistics.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {D91C9B93-6EB8-42C3-8C69-55C391C69884} + Win32Proj + GetStatelessStatistics + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetStatelessStatistics + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetStatelessStoreParams/README.md b/Samples/DHCP/GetStatelessStoreParams/README.md new file mode 100644 index 00000000..f2f568f3 --- /dev/null +++ b/Samples/DHCP/GetStatelessStoreParams/README.md @@ -0,0 +1,42 @@ +DhcpV6GetStatelessStoreParams API sample +======================================== + +This sample explains the usage of the DhcpV6GetStatelessStoreParams API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV6GetStatelessStoreParams**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404358) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.cpp b/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.cpp new file mode 100644 index 00000000..c38eb56f --- /dev/null +++ b/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.cpp @@ -0,0 +1,44 @@ +// 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 +#include +#include +#include + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to hold Error Codes + LPWSTR pwszServer = NULL; // Variable to hold Server IP Address + DHCP_IPV6_ADDRESS subnetAddress = {0}; // Subnet + BOOL bServerLevel = TRUE; // Variable to signify scope or server level + LPDHCPV6_STATELESS_PARAMS pStoreParams = NULL; // Variable to hold stateless store params. + + + dwError = DhcpV6GetStatelessStoreParams( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed), + bServerLevel, // Server level or Scope level + subnetAddress, // Contains the IPv6 subnet address of the stateless client + &pStoreParams //Pointer to a DHCPV6_STATELESS_PARAMS structure that contains the stateless client inventory configuration settings + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV6GetStatelessStoreParams failed with Error = %d\n", dwError); + goto cleanup; + } + wprintf(L"Status = %d PurgeInterval: %u\n",pStoreParams->Status,pStoreParams->PurgeInterval); + +cleanup: + if(NULL != pStoreParams) + { + DhcpRpcFreeMemory(pStoreParams); + pStoreParams = NULL; + } + return 0; +} diff --git a/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.sln b/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.sln new file mode 100644 index 00000000..c3661cbd --- /dev/null +++ b/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetStatelessStoreParams", "GetStatelessStoreParams.vcxproj", "{1D794D16-8AA8-4EC6-B733-9338CD17D879}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1D794D16-8AA8-4EC6-B733-9338CD17D879}.Debug|x64.ActiveCfg = Debug|x64 + {1D794D16-8AA8-4EC6-B733-9338CD17D879}.Debug|x64.Build.0 = Debug|x64 + {1D794D16-8AA8-4EC6-B733-9338CD17D879}.Release|x64.ActiveCfg = Release|x64 + {1D794D16-8AA8-4EC6-B733-9338CD17D879}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.vcxproj b/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.vcxproj new file mode 100644 index 00000000..5131b992 --- /dev/null +++ b/Samples/DHCP/GetStatelessStoreParams/cpp/GetStatelessStoreParams.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {1D794D16-8AA8-4EC6-B733-9338CD17D879} + Win32Proj + GetStatelessStoreParams + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetStatelessStoreParams + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/GetSystemTime/README.md b/Samples/DHCP/GetSystemTime/README.md new file mode 100644 index 00000000..1434bda9 --- /dev/null +++ b/Samples/DHCP/GetSystemTime/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverGetSystemTime API sample +====================================== + +This sample explains the usage of the DhcpV4FailoverGetSystemTime API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverGetSystemTime**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404321) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.cpp b/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.cpp new file mode 100644 index 00000000..2108ee7b --- /dev/null +++ b/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.cpp @@ -0,0 +1,29 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to hold returned error code + DWORD dwTime = 0; // Variable to hold system time of the server + DWORD dwAllowedDelay = 0; // Variable to hold the max allowed delta in time. + LPWSTR pwszServer = NULL; // Server IP Address + dwError = DhcpV4FailoverGetSystemTime( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed) + &dwTime, // System time of the server + &dwAllowedDelay // Max time difference allowed + ); + if( ERROR_SUCCESS != dwError ) + { + wprintf(L"DhcpV4FailoverGetSystemTime failed with Error = %d\n",dwError); + } + return 0; +} diff --git a/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.sln b/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.sln new file mode 100644 index 00000000..d4df86e0 --- /dev/null +++ b/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetSystemTime", "GetSystemTime.vcxproj", "{1C02E57F-8996-4C95-8885-9A30112C7080}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1C02E57F-8996-4C95-8885-9A30112C7080}.Debug|x64.ActiveCfg = Debug|x64 + {1C02E57F-8996-4C95-8885-9A30112C7080}.Debug|x64.Build.0 = Debug|x64 + {1C02E57F-8996-4C95-8885-9A30112C7080}.Release|x64.ActiveCfg = Release|x64 + {1C02E57F-8996-4C95-8885-9A30112C7080}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.vcxproj b/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.vcxproj new file mode 100644 index 00000000..2780e8e4 --- /dev/null +++ b/Samples/DHCP/GetSystemTime/cpp/GetSystemTime.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {1C02E57F-8996-4C95-8885-9A30112C7080} + Win32Proj + GetSystemTime + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + GetSystemTime + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprAddPolicyCondition/README.md b/Samples/DHCP/HlprAddPolicyCondition/README.md new file mode 100644 index 00000000..cb111825 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyCondition/README.md @@ -0,0 +1,42 @@ +DhcpHlprAddV4PolicyCondition API sample +======================================= + +This sample explains the usage of the DhcpHlprAddV4PolicyCondition API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprAddV4PolicyCondition**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404269) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.cpp b/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.cpp new file mode 100644 index 00000000..c830f699 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.cpp @@ -0,0 +1,105 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 +*/ + +#include +#include +#include + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength = 0; // Number of bytes of user data in pUserClassCondValueInBytes + LPBYTE pUserClassCondValueInBytes = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0xa000000; // Subnet Address (10.0.0.0) + LPWSTR pwszName = L"testPolicy"; //Name of the policy to be created + LPWSTR pwszDescription = L"PolicyDescription"; // Description of the policy to be created + char* szUserClassConditionValue = {"RRAS.Microsoft"}; // Default Routing and Remote Access Class + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + + + // Invokes helper API to create/fill policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + dwBytesLength = (DWORD)strlen(szUserClassConditionValue); + + // Allocates memory for variable that will hold the values for condition values. + pUserClassCondValueInBytes = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength); + if(NULL == pUserClassCondValueInBytes) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + + // Copies the bytes for condition values from pUserClassCondValueInBytes + memcpy(pUserClassCondValueInBytes, szUserClassConditionValue, dwBytesLength); + + // Invokes helper API to create/fill the structure for adding conditions for the policy. + // The condition in this case is "user class" equals "Default Routing and Remote Access Class" + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes, // Condition values in bytes + dwBytesLength, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + +cleanup: + + // Frees the variable that holds the bytes for condition values + if(NULL != pUserClassCondValueInBytes) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes); + pUserClassCondValueInBytes = NULL; + } + + //Frees the variable that holds the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + return 0; +} + diff --git a/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.sln b/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.sln new file mode 100644 index 00000000..8607c2b1 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlpraddpolicycond", "hlpraddpolicycond.vcxproj", "{E50683D7-9761-45F8-8C0A-881D9E23F3B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E50683D7-9761-45F8-8C0A-881D9E23F3B1}.Debug|x64.ActiveCfg = Debug|x64 + {E50683D7-9761-45F8-8C0A-881D9E23F3B1}.Debug|x64.Build.0 = Debug|x64 + {E50683D7-9761-45F8-8C0A-881D9E23F3B1}.Release|x64.ActiveCfg = Release|x64 + {E50683D7-9761-45F8-8C0A-881D9E23F3B1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.vcxproj b/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.vcxproj new file mode 100644 index 00000000..6afba2ec --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyCondition/cpp/hlpraddpolicycond.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {E50683D7-9761-45F8-8C0A-881D9E23F3B1} + Win32Proj + hlpraddpolicycond + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlpraddpolicycond + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprAddPolicyExpr/README.md b/Samples/DHCP/HlprAddPolicyExpr/README.md new file mode 100644 index 00000000..53dda8fb --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyExpr/README.md @@ -0,0 +1,42 @@ +DhcpHlprAddV4PolicyExpr API sample +================================== + +This sample explains the usage of the DhcpHlprAddV4PolicyExpr API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprAddV4PolicyExpr**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404270) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.cpp b/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.cpp new file mode 100644 index 00000000..490379ac --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.cpp @@ -0,0 +1,153 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 +*/ + +#include +#include +#include +#include + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength1 = 0; // Number of bytes of user data in pUserClassCondValueInBytes1 + DWORD dwBytesLength2 = 0; // Number of bytes of user data in pUserClassCondValueInBytes2 + DWORD dwParentExpr = 0; // Parent expression index + LPBYTE pUserClassCondValueInBytes1 = NULL; // Bytes containing condition value (user class based in the current example) + LPBYTE pUserClassCondValueInBytes2 = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0; // Subnet Address + LPWSTR pwszName = L"testPolicy"; // Name of the policy + LPWSTR pwszDescription = L"PolicyDescription"; // Policy description + char* szUserClassConditionValue1 = {"BOOTP.Microsoft"}; // Default BOOT class + char* szUserClassConditionValue2 = {"MSFT Quarantine"}; // Default Network Access Protection cclass + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_LOGIC_OPER exprLogicalOperator = DhcpLogicalAnd; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + + //Helper routine is invoked to create/fill the policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + // Fill in bytes and dwBytesLength + dwBytesLength1 = (DWORD)strlen(szUserClassConditionValue1); + pUserClassCondValueInBytes1= (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength1); + if(NULL == pUserClassCondValueInBytes1) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + memcpy(pUserClassCondValueInBytes1, szUserClassConditionValue1, dwBytesLength1); + dwError=DhcpHlprAddV4PolicyExpr( + pPolicy, // DHCP Policy + dwParentExpr, // Parent expression Index + exprLogicalOperator, // Root operator for the expression + &dwExprIdx // expression index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyExpr failed with Error = %d\n", dwError); + goto cleanup; + } + + // DhcpHlprAddV4PolicyCondition is invoked to add/fill the conditions for the policy + // This adds condition "UserClass equals "Default BOOTP Class"" to the policy. + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes1, // Condition values in bytes + dwBytesLength1, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + dwBytesLength2 = (DWORD)strlen(szUserClassConditionValue2); + pUserClassCondValueInBytes2= (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength2); + if(NULL == pUserClassCondValueInBytes2) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + memcpy(pUserClassCondValueInBytes2, szUserClassConditionValue2, dwBytesLength2); + + // DhcpHlprAddV4PolicyCondition is invoked to add/fill the conditions for the policy + // This will add another condition {UserClass equals "Default Network Access Protection Class"} to the expression. + // The final expression will be {"UserClass equals "Default BOOTP Class", "Default Network Access Protection Class"} + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes2, // Condition values in bytes + dwBytesLength2, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + } + +cleanup: + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes1) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes1); + pUserClassCondValueInBytes1 = NULL; + } + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes2) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes2); + pUserClassCondValueInBytes2 = NULL; + } + + // Frees the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + return 0; +} diff --git a/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.sln b/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.sln new file mode 100644 index 00000000..3a7a6257 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlpraddpolicyexpr", "hlpraddpolicyexpr.vcxproj", "{E9DCD77B-4436-494B-AB86-DE3F9EBFA9A0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E9DCD77B-4436-494B-AB86-DE3F9EBFA9A0}.Debug|x64.ActiveCfg = Debug|x64 + {E9DCD77B-4436-494B-AB86-DE3F9EBFA9A0}.Debug|x64.Build.0 = Debug|x64 + {E9DCD77B-4436-494B-AB86-DE3F9EBFA9A0}.Release|x64.ActiveCfg = Release|x64 + {E9DCD77B-4436-494B-AB86-DE3F9EBFA9A0}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.vcxproj b/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.vcxproj new file mode 100644 index 00000000..992f1100 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyExpr/cpp/hlpraddpolicyexpr.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {E9DCD77B-4436-494B-AB86-DE3F9EBFA9A0} + Win32Proj + hlpraddpolicyexpr + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlpraddpolicyexpr + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprAddPolicyRange/README.md b/Samples/DHCP/HlprAddPolicyRange/README.md new file mode 100644 index 00000000..7430fa10 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyRange/README.md @@ -0,0 +1,42 @@ +DhcpHlprAddV4PolicyRange API sample +=================================== + +This sample explains the usage of the DhcpHlprAddV4PolicyRange API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprAddV4PolicyRange**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404282) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.cpp b/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.cpp new file mode 100644 index 00000000..13c9f832 --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.cpp @@ -0,0 +1,112 @@ +// 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 +#include +#include + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength = 0; // Number of bytes of user data in pUserClassCondValueInBytes + LPBYTE pUserClassCondValueInBytes = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0xa000000; // Subnet Address (10.0.0.0) + LPWSTR pwszName = L"testPolicy"; //Name of the policy to be created + LPWSTR pwszDescription = L"PolicyDescription"; // Description of the policy to be created + char* szUserClassConditionValue = {"RRAS.Microsoft"}; // Default Routing and Remote Access Class + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + DHCP_IP_RANGE range = {0}; // Variable to hold range values + DWORD dwStartAddress = 0xa00000a; //(10.0.0.10) Start Address of the range + DWORD dwEndAddress = 0xa000032; //(10.0.0.50) End Address of the range + + range.StartAddress = dwStartAddress; + range.EndAddress = dwEndAddress; + + + // Invokes helper API to create/fill policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + + // Fill in pUserClassCondValueInBytes and dwBytesLength + dwBytesLength = (DWORD)strlen(szUserClassConditionValue); + pUserClassCondValueInBytes = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength); + if(NULL == pUserClassCondValueInBytes) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + // Copies the bytes for condition values from pUserClassCondValueInBytes + memcpy(pUserClassCondValueInBytes, szUserClassConditionValue, dwBytesLength); + + // Invokes helper API to create/fill the structure for adding conditions for the policy. + // The condition in this case is "user class" equals "Default Routing and Remote Access Class" + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes, // Condition values in bytes + dwBytesLength, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + // Helper class for adding policy ip range is invoked from below. + dwError = DhcpHlprAddV4PolicyRange(pPolicy,&range); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyRange failed with Error = %d\n",dwError); + } +cleanup: + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes); + pUserClassCondValueInBytes = NULL; + } + + // Frees the variable holding the policy. + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + + return 0; +} diff --git a/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.sln b/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.sln new file mode 100644 index 00000000..93a12f7f --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlpraddpolicyrange", "hlpraddpolicyrange.vcxproj", "{D94576BC-0A6A-49C7-A836-84D62756C0E1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D94576BC-0A6A-49C7-A836-84D62756C0E1}.Debug|x64.ActiveCfg = Debug|x64 + {D94576BC-0A6A-49C7-A836-84D62756C0E1}.Debug|x64.Build.0 = Debug|x64 + {D94576BC-0A6A-49C7-A836-84D62756C0E1}.Release|x64.ActiveCfg = Release|x64 + {D94576BC-0A6A-49C7-A836-84D62756C0E1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.vcxproj b/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.vcxproj new file mode 100644 index 00000000..707d6d5b --- /dev/null +++ b/Samples/DHCP/HlprAddPolicyRange/cpp/hlpraddpolicyrange.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {D94576BC-0A6A-49C7-A836-84D62756C0E1} + Win32Proj + hlpraddpolicyrange + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlpraddpolicyrange + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprCreatePolicy/README.md b/Samples/DHCP/HlprCreatePolicy/README.md new file mode 100644 index 00000000..46b3fdb1 --- /dev/null +++ b/Samples/DHCP/HlprCreatePolicy/README.md @@ -0,0 +1,42 @@ +DhcpHlprCreateV4Policy API sample +================================= + +This sample explains the usage of the DhcpHlprCreateV4Policy API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprCreateV4Policy**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404283) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.cpp b/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.cpp new file mode 100644 index 00000000..19482075 --- /dev/null +++ b/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.cpp @@ -0,0 +1,45 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Variable to hold the policy structure + DWORD dwError = ERROR_SUCCESS; // Variable to hold the error code + DHCP_IP_ADDRESS dwSubnet = 0; // Subnet Address, a value of 0 means server level policy + LPWSTR pwszName = L"testPolicy"; // Name of the policy that needs to be created + LPWSTR pwszDescription = L"PolicyDescription"; // Description of the policy + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator + + //Helper routine is invoked to create/fill the policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + // Frees the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } +cleanup: + return 0; +} diff --git a/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.sln b/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.sln new file mode 100644 index 00000000..03f804b2 --- /dev/null +++ b/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlprcreatepolicy", "hlprcreatepolicy.vcxproj", "{ACF9B30C-50B3-49C6-819B-792CB1162014}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ACF9B30C-50B3-49C6-819B-792CB1162014}.Debug|x64.ActiveCfg = Debug|x64 + {ACF9B30C-50B3-49C6-819B-792CB1162014}.Debug|x64.Build.0 = Debug|x64 + {ACF9B30C-50B3-49C6-819B-792CB1162014}.Release|x64.ActiveCfg = Release|x64 + {ACF9B30C-50B3-49C6-819B-792CB1162014}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.vcxproj b/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.vcxproj new file mode 100644 index 00000000..e659f07a --- /dev/null +++ b/Samples/DHCP/HlprCreatePolicy/cpp/hlprcreatepolicy.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {ACF9B30C-50B3-49C6-819B-792CB1162014} + Win32Proj + hlprcreatepolicy + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlprcreatepolicy + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprIsPolicySingleUC/README.md b/Samples/DHCP/HlprIsPolicySingleUC/README.md new file mode 100644 index 00000000..604d4af5 --- /dev/null +++ b/Samples/DHCP/HlprIsPolicySingleUC/README.md @@ -0,0 +1,42 @@ +DhcpHlprIsV4PolicySingleUC API sample +===================================== + +This sample explains the usage of the DhcpHlprIsV4PolicySingleUC API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprIsV4PolicySingleUC**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404285) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.cpp b/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.cpp new file mode 100644 index 00000000..0f01c14e --- /dev/null +++ b/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.cpp @@ -0,0 +1,103 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "testPolicy" on scope 10.0.0.0 +*/ + +#include +#include +#include + +// This routine frees LPDHCP_POLICY and its internal elements. +VOID FreeDhcpPolicyMemory(LPDHCP_POLICY pDhcpPolicy) +{ + if (NULL != pDhcpPolicy) + { + // Frees the policy name + if (NULL != pDhcpPolicy->PolicyName) + DhcpRpcFreeMemory(pDhcpPolicy->PolicyName); + + // Frees the policy description + if( NULL != pDhcpPolicy->Description) + DhcpRpcFreeMemory(pDhcpPolicy->Description); + + // Frees the policy condition + if(NULL != pDhcpPolicy->Conditions) + { + for(DWORD dwIndex = 0; dwIndexConditions->NumElements; dwIndex++) + { + // Frees the vendorName holder in condition's elements, if it exists + if( NULL != pDhcpPolicy->Conditions->Elements[dwIndex].VendorName) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].VendorName); + + // Frees the "bytes" used for storing condition values + if (NULL != pDhcpPolicy->Conditions->Elements[dwIndex].Value) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].Value); + } + DhcpRpcFreeMemory(pDhcpPolicy->Conditions); + } + + // Frees the policy expression + if(NULL != pDhcpPolicy->Expressions) + { + // Frees the expression elements, if they exist + if(pDhcpPolicy->Expressions->NumElements && pDhcpPolicy->Expressions->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Expressions->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Expressions); + } + + // Frees the policy ranges + if(NULL != pDhcpPolicy->Ranges) + { + // Frees the individual range elements + if(pDhcpPolicy->Ranges->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Ranges->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Ranges); + } + + // Finally frees the policy structure + DhcpRpcFreeMemory(pDhcpPolicy); + pDhcpPolicy=NULL; + } +} + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Variable to hold the DHCP Policy structure + LPWSTR pwszServer = NULL; //Server IP Address, NULL signifies current server (where the program is executed) + DWORD dwScope = 0xa000000; // Subnet Address (10.0.0.0) + DWORD dwError = ERROR_SUCCESS; // Variable to hold error code + LPWSTR pwszName = L"testPolicy"; // Policy Name + BOOL bIsUCBased = FALSE; + dwError = DhcpV4GetPolicy( + pwszServer, // Server IP Address, NULL signifies the current server (where the program is executed) + (dwScope == 0), // fGlobalPolicy, TRUE means a global policy, for a global policy SubnetAddress is 0. + dwScope, // Subnet address, if it is a global policy, its value is 0 + pwszName, // Name of the policy + &pPolicy // Policy structure obtained from the server + ); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4GetPolicy returned error. + wprintf(L"DhcpV4GetPolicy failed with error %d\n",dwError); + goto cleanup; + } + // DhcpHlprIsV4PolicySingleUC returns true or false. + // True means the policy contains single user class based conditions. + // False means the policy in question doesnt contain just one user class based condition + bIsUCBased = DhcpHlprIsV4PolicySingleUC(pPolicy); + if(bIsUCBased) + wprintf(L"Policy contains single user class based condition\n"); + else + wprintf(L"Policy does not contain just one user class based condition\n"); + FreeDhcpPolicyMemory(pPolicy); +cleanup: + return 0; +} diff --git a/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.sln b/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.sln new file mode 100644 index 00000000..48b70898 --- /dev/null +++ b/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlprispolicysingleuc", "hlprispolicysingleuc.vcxproj", "{83B8CBB0-EDD3-462A-AF2D-C048089F94ED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {83B8CBB0-EDD3-462A-AF2D-C048089F94ED}.Debug|x64.ActiveCfg = Debug|x64 + {83B8CBB0-EDD3-462A-AF2D-C048089F94ED}.Debug|x64.Build.0 = Debug|x64 + {83B8CBB0-EDD3-462A-AF2D-C048089F94ED}.Release|x64.ActiveCfg = Release|x64 + {83B8CBB0-EDD3-462A-AF2D-C048089F94ED}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.vcxproj b/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.vcxproj new file mode 100644 index 00000000..6c11809b --- /dev/null +++ b/Samples/DHCP/HlprIsPolicySingleUC/cpp/hlprispolicysingleuc.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {83B8CBB0-EDD3-462A-AF2D-C048089F94ED} + Win32Proj + hlprispolicysingleuc + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlprispolicysingleuc + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprIsPolicyWellFormed/README.md b/Samples/DHCP/HlprIsPolicyWellFormed/README.md new file mode 100644 index 00000000..a0893a04 --- /dev/null +++ b/Samples/DHCP/HlprIsPolicyWellFormed/README.md @@ -0,0 +1,42 @@ +DhcpHlprIsV4PolicyWellFormed API sample +======================================= + +This sample explains the usage of the DhcpHlprIsV4PolicyWellFormed API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprIsV4PolicyWellFormed**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404288) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.cpp b/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.cpp new file mode 100644 index 00000000..45fd1d72 --- /dev/null +++ b/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.cpp @@ -0,0 +1,155 @@ +// 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 +#include +#include +#include + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + + +int __cdecl main(void) +{ + BOOL bIsWellFormed = FALSE; + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength1 = 0; // Number of bytes of user data in pUserClassCondValueInBytes1 + DWORD dwBytesLength2 = 0; // Number of bytes of user data in pUserClassCondValueInBytes2 + DWORD dwParentExpr = 0; // Parent expression index + LPBYTE pUserClassCondValueInBytes1 = NULL; // Bytes containing condition value (user class based in the current example) + LPBYTE pUserClassCondValueInBytes2 = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0; // Subnet Address + LPWSTR pwszName = L"testPolicy"; // Name of the policy + LPWSTR pwszDescription = L"PolicyDescription"; // Policy description + char* szUserClassConditionValue1 = {"BOOTP.Microsoft"}; // Default BOOT class + char* szUserClassConditionValue2 = {"MSFT Quarantine"}; // Default Network Access Protection cclass + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_LOGIC_OPER exprLogicalOperator = DhcpLogicalAnd; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + + //Helper routine is invoked to create/fill the policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + // Fill in bytes and dwBytesLength + dwBytesLength1 = (DWORD)strlen(szUserClassConditionValue1); + pUserClassCondValueInBytes1= (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength1); + if(NULL == pUserClassCondValueInBytes1) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + memcpy(pUserClassCondValueInBytes1, szUserClassConditionValue1, dwBytesLength1); + dwError=DhcpHlprAddV4PolicyExpr( + pPolicy, // DHCP Policy + dwParentExpr, // Parent expression Index + exprLogicalOperator, // Root operator for the expression + &dwExprIdx // expression index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyExpr failed with Error = %d\n", dwError); + goto cleanup; + } + + // DhcpHlprAddV4PolicyCondition is invoked to add/fill the conditions for the policy + // This adds condition "UserClass equals "Default BOOTP Class"" to the policy. + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes1, // Condition values in bytes + dwBytesLength1, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + dwBytesLength2 = (DWORD)strlen(szUserClassConditionValue2); + pUserClassCondValueInBytes2= (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength2); + if(NULL == pUserClassCondValueInBytes2) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + memcpy(pUserClassCondValueInBytes2, szUserClassConditionValue2, dwBytesLength2); + + // DhcpHlprAddV4PolicyCondition is invoked to add/fill the conditions for the policy + // This will add another condition {UserClass equals "Default Network Access Protection Class"} to the expression. + // The final expression will be {"UserClass equals "Default BOOTP Class", "Default Network Access Protection Class"} + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes2, // Condition values in bytes + dwBytesLength2, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + } + // Checks if the policy structure which is created has all expressions/conditions in correct manner or not. + bIsWellFormed = DhcpHlprIsV4PolicyWellFormed(pPolicy); + if(TRUE == bIsWellFormed) + wprintf(L"Valid conditions and expressions\n"); + else + wprintf(L"Invalid conditions or expressions"); +cleanup: + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes1) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes1); + pUserClassCondValueInBytes1 = NULL; + } + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes2) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes2); + pUserClassCondValueInBytes2 = NULL; + } + + // Frees the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + return 0; +} diff --git a/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.sln b/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.sln new file mode 100644 index 00000000..67082e07 --- /dev/null +++ b/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlprispolicywellformed", "hlprispolicywellformed.vcxproj", "{E25214E7-F517-4313-85F7-28376A894683}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E25214E7-F517-4313-85F7-28376A894683}.Debug|x64.ActiveCfg = Debug|x64 + {E25214E7-F517-4313-85F7-28376A894683}.Debug|x64.Build.0 = Debug|x64 + {E25214E7-F517-4313-85F7-28376A894683}.Release|x64.ActiveCfg = Release|x64 + {E25214E7-F517-4313-85F7-28376A894683}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.vcxproj b/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.vcxproj new file mode 100644 index 00000000..76faa0bc --- /dev/null +++ b/Samples/DHCP/HlprIsPolicyWellFormed/cpp/hlprispolicywellformed.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {E25214E7-F517-4313-85F7-28376A894683} + Win32Proj + hlprispolicywellformed + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlprispolicywellformed + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprModifyPolicyExpr/README.md b/Samples/DHCP/HlprModifyPolicyExpr/README.md new file mode 100644 index 00000000..11b6b27e --- /dev/null +++ b/Samples/DHCP/HlprModifyPolicyExpr/README.md @@ -0,0 +1,42 @@ +DhcpHlprModifyV4PolicyExpr API sample +===================================== + +This sample explains the usage of the DhcpHlprModifyV4PolicyExpr API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprModifyV4PolicyExpr**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404289) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.cpp b/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.cpp new file mode 100644 index 00000000..f790e4a1 --- /dev/null +++ b/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.cpp @@ -0,0 +1,108 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "testPolicy" on scope 10.0.0.0 +*/ + +#include +#include +#include + +// This routine frees LPDHCP_POLICY and its internal elements. +VOID FreeDhcpPolicyMemory(LPDHCP_POLICY pDhcpPolicy) +{ + if (NULL != pDhcpPolicy) + { + // Frees the policy name + if (NULL != pDhcpPolicy->PolicyName) + DhcpRpcFreeMemory(pDhcpPolicy->PolicyName); + + // Frees the policy description + if( NULL != pDhcpPolicy->Description) + DhcpRpcFreeMemory(pDhcpPolicy->Description); + + // Frees the policy condition + if(NULL != pDhcpPolicy->Conditions) + { + for(DWORD dwIndex = 0; dwIndexConditions->NumElements; dwIndex++) + { + // Frees the vendorName holder in condition's elements, if it exists + if( NULL != pDhcpPolicy->Conditions->Elements[dwIndex].VendorName) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].VendorName); + + // Frees the "bytes" used for storing condition values + if (NULL != pDhcpPolicy->Conditions->Elements[dwIndex].Value) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].Value); + } + DhcpRpcFreeMemory(pDhcpPolicy->Conditions); + } + + // Frees the policy expression + if(NULL != pDhcpPolicy->Expressions) + { + // Frees the expression elements, if they exist + if(pDhcpPolicy->Expressions->NumElements && pDhcpPolicy->Expressions->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Expressions->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Expressions); + } + + // Frees the policy ranges + if(NULL != pDhcpPolicy->Ranges) + { + // Frees the individual range elements + if(pDhcpPolicy->Ranges->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Ranges->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Ranges); + } + + // Finally frees the policy structure + DhcpRpcFreeMemory(pDhcpPolicy); + pDhcpPolicy=NULL; + } +} + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure, this will hold the policies obtained from DhcpV4GetPolicy + LPWSTR pwszServer = NULL; // NULL signifies current server + DWORD dwScope = 0xa000000; // (10.0.0.0) Subnet address + DWORD dwError = ERROR_SUCCESS; // Variable to hold the error code + LPWSTR pwszName = L"testPolicy"; // Name of the policy + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the policy + + dwError = DhcpV4GetPolicy( + pwszServer, // Server IP Address, NULL signifies the current server (where the program is executed) + (dwScope == 0), // fGlobalPolicy, TRUE means a global policy, for a global policy SubnetAddress is 0. + dwScope, // Subnet address, if it is a global policy, its value is 0 + pwszName, // Name of the policy + &pPolicy // Policy structure obtained from the server + ); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4GetPolicy returned error. + wprintf(L"DhcpV4GetPolicy failed with error %d\n",dwError); + goto cleanup; + } + wprintf(L"Policy expression Operator (before calling DhcpHlprModifyV4PolicyExpr) = %d\n",pPolicy->Expressions->Elements[0].Operator); + + policyOperator = pPolicy->Expressions->Elements[0].Operator; + + // Modifies the root operator for the policy expression + dwError = DhcpHlprModifyV4PolicyExpr(pPolicy, ((policyOperator == DhcpLogicalOr)?DhcpLogicalAnd:DhcpLogicalOr)); + if(ERROR_SUCCESS != dwError){ + wprintf(L"DhcpHlprModifyV4PolicyExpr failed with Error = %d\n", dwError); + } + else{ + wprintf(L"Policy expression Operator (after calling DhcpHlprModifyV4PolicyExpr) = %d\n",pPolicy->Expressions->Elements[0].Operator); + } + FreeDhcpPolicyMemory(pPolicy); +cleanup: + return 0; +} diff --git a/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.sln b/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.sln new file mode 100644 index 00000000..414bc0da --- /dev/null +++ b/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlprmodifypolicyexpr", "hlprmodifypolicyexpr.vcxproj", "{4793F448-FB53-40F4-A629-B8CB3B129D20}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4793F448-FB53-40F4-A629-B8CB3B129D20}.Debug|x64.ActiveCfg = Debug|x64 + {4793F448-FB53-40F4-A629-B8CB3B129D20}.Debug|x64.Build.0 = Debug|x64 + {4793F448-FB53-40F4-A629-B8CB3B129D20}.Release|x64.ActiveCfg = Release|x64 + {4793F448-FB53-40F4-A629-B8CB3B129D20}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.vcxproj b/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.vcxproj new file mode 100644 index 00000000..d8488d81 --- /dev/null +++ b/Samples/DHCP/HlprModifyPolicyExpr/cpp/hlprmodifypolicyexpr.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {4793F448-FB53-40F4-A629-B8CB3B129D20} + Win32Proj + hlprmodifypolicyexpr + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlprmodifypolicyexpr + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprResetPolicyExpr/README.md b/Samples/DHCP/HlprResetPolicyExpr/README.md new file mode 100644 index 00000000..f18b9cd9 --- /dev/null +++ b/Samples/DHCP/HlprResetPolicyExpr/README.md @@ -0,0 +1,42 @@ +DhcpHlprResetV4PolicyExpr API sample +==================================== + +This sample explains the usage of the DhcpHlprResetV4PolicyExpr API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprResetV4PolicyExpr**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404290) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.cpp b/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.cpp new file mode 100644 index 00000000..7464041c --- /dev/null +++ b/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.cpp @@ -0,0 +1,163 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 +*/ + +#include +#include +#include + + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength1 = 0; // Number of bytes of user data in pUserClassCondValueInBytes1 + DWORD dwBytesLength2 = 0; // Number of bytes of user data in pUserClassCondValueInBytes2 + DWORD dwParentExpr = 0; // Parent expression index + LPBYTE pUserClassCondValueInBytes1 = NULL; // Bytes containing condition value (user class based in the current example) + LPBYTE pUserClassCondValueInBytes2 = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0; // Subnet Address + LPWSTR pwszName = L"testPolicy"; // Name of the policy + LPWSTR pwszDescription = L"PolicyDescription"; // Policy description + char* szUserClassConditionValue1 = {"BOOTP.Microsoft"}; // Default BOOT class + char* szUserClassConditionValue2 = {"MSFT Quarantine"}; // Default Network Access Protection cclass + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_LOGIC_OPER exprLogicalOperator = DhcpLogicalAnd; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + + //Helper routine is invoked to create/fill the policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + // Fill in bytes and dwBytesLength + dwBytesLength1 = (DWORD)strlen(szUserClassConditionValue1); + pUserClassCondValueInBytes1= (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength1); + if(NULL == pUserClassCondValueInBytes1) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + memcpy(pUserClassCondValueInBytes1, szUserClassConditionValue1, dwBytesLength1); + dwError=DhcpHlprAddV4PolicyExpr( + pPolicy, // DHCP Policy + dwParentExpr, // Parent expression Index + exprLogicalOperator, // Root operator for the expression + &dwExprIdx // expression index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyExpr failed with Error = %d\n", dwError); + goto cleanup; + } + + // DhcpHlprAddV4PolicyCondition is invoked to add/fill the conditions for the policy + // This adds condition "UserClass equals "Default BOOTP Class"" to the policy. + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes1, // Condition values in bytes + dwBytesLength1, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + dwBytesLength2 = (DWORD)strlen(szUserClassConditionValue2); + pUserClassCondValueInBytes2= (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength2); + if(NULL == pUserClassCondValueInBytes2) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + memcpy(pUserClassCondValueInBytes2, szUserClassConditionValue2, dwBytesLength2); + + // DhcpHlprAddV4PolicyCondition is invoked to add/fill the conditions for the policy + // This will add another condition {UserClass equals "Default Network Access Protection Class"} to the expression. + // The final expression will be {"UserClass equals "Default BOOTP Class", "Default Network Access Protection Class"} + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes2, // Condition values in bytes + dwBytesLength2, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + } + + wprintf(L"Number of elements in policy expression (before reset) = %d\n",pPolicy->Expressions->NumElements); + + // Resets the policy expression + dwError = DhcpHlprResetV4PolicyExpr(pPolicy); + if(ERROR_SUCCESS != dwError){ + wprintf(L"DhcpHlprResetV4PolicyExpr failed with Error = %d\n",dwError); + }else{ + wprintf(L"Number of elements in policy expression (after reset) = %d\n",pPolicy->Expressions->NumElements); + } +cleanup: + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes1) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes1); + pUserClassCondValueInBytes1 = NULL; + } + + // Frees the variable holding the condition values in bytes + if(NULL != pUserClassCondValueInBytes2) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes2); + pUserClassCondValueInBytes2 = NULL; + } + + // Frees the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + return 0; +} + diff --git a/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.sln b/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.sln new file mode 100644 index 00000000..899d9092 --- /dev/null +++ b/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlprresetpolicyexpr", "hlprresetpolicyexpr.vcxproj", "{4C193251-5F8B-44C5-B445-E19E428714C5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4C193251-5F8B-44C5-B445-E19E428714C5}.Debug|x64.ActiveCfg = Debug|x64 + {4C193251-5F8B-44C5-B445-E19E428714C5}.Debug|x64.Build.0 = Debug|x64 + {4C193251-5F8B-44C5-B445-E19E428714C5}.Release|x64.ActiveCfg = Release|x64 + {4C193251-5F8B-44C5-B445-E19E428714C5}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.vcxproj b/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.vcxproj new file mode 100644 index 00000000..9b6ba668 --- /dev/null +++ b/Samples/DHCP/HlprResetPolicyExpr/cpp/hlprresetpolicyexpr.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {4C193251-5F8B-44C5-B445-E19E428714C5} + Win32Proj + hlprresetpolicyexpr + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlprresetpolicyexpr + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/HlprisPolicyValid/README.md b/Samples/DHCP/HlprisPolicyValid/README.md new file mode 100644 index 00000000..4a5d148a --- /dev/null +++ b/Samples/DHCP/HlprisPolicyValid/README.md @@ -0,0 +1,42 @@ +DhcpHlprIsV4PolicyValid API sample +================================== + +This sample explains the usage of the DhcpHlprIsV4PolicyValid API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpHlprIsV4PolicyValid**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404287) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to **Build**-\>**Build Solution** from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the **Debug** menu.) + diff --git a/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.cpp b/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.cpp new file mode 100644 index 00000000..3d5473ca --- /dev/null +++ b/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.cpp @@ -0,0 +1,115 @@ +// 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 +#include +#include + + +#ifndef OPTION_USER_CLASS +#define OPTION_USER_CLASS 77 +#endif + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Policy structure + DWORD dwError = ERROR_SUCCESS; // It stores the error code + DWORD dwExprIdx = 0; // Expression Index + DWORD dwOptionId = OPTION_USER_CLASS; // Option ID for UserClass + DWORD dwSubOptionId = 0; // Sub Option ID for UserClass + DWORD dwConditionIdx = 0; // Condition index which will be returned from DhcpHlprAddV4PolicyCondition + DWORD dwBytesLength = 0; // Number of bytes of user data in pUserClassCondValueInBytes + LPBYTE pUserClassCondValueInBytes = NULL; // Bytes containing condition value (user class based in the current example) + DHCP_IP_ADDRESS dwSubnet = 0xa000000; // Subnet Address (10.0.0.0) + LPWSTR pwszName = L"testPolicy"; //Name of the policy to be created + LPWSTR pwszDescription = L"PolicyDescription"; // Description of the policy to be created + char* szUserClassConditionValue = {"RRAS.Microsoft"}; // Default Routing and Remote Access Class + DHCP_POL_LOGIC_OPER policyOperator = DhcpLogicalOr; // Root operator for the conditions and expressions + DHCP_POL_ATTR_TYPE policyAttrType = DhcpAttrOption; // Policy attribute type + DHCP_POL_COMPARATOR conditionOper = DhcpCompEqual; // Condition operator + + + // Invokes helper API to create/fill policy structure. + dwError=DhcpHlprCreateV4Policy( + pwszName, // Policy Name + (dwSubnet == 0), // fGloabalPolicy, if scope is zero, this means it is a global policy else it is for a specific scope + dwSubnet, // Scope + 0, // Processing order + policyOperator, // Logical operator, possible values are: DhcpLogicalOr, DhcpLogicalAnd + pwszDescription, // Policy description + TRUE, // Policy active or not + &pPolicy // This is the actual structure that holds the policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprCreateV4Policy failed with Error = %d\n", dwError); + goto cleanup; + } + + // Checks if the policy structure created is valid or not + dwError = DhcpHlprIsV4PolicyValid(pPolicy); + if(ERROR_SUCCESS == dwError) + wprintf(L"Valid Policy\n"); + else + wprintf(L"Invalid Policy\n"); + + dwBytesLength = (DWORD)strlen(szUserClassConditionValue); + + // Allocates memory for variable that will hold the values for condition values. + pUserClassCondValueInBytes = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesLength); + if(NULL == pUserClassCondValueInBytes) + { + wprintf(L"Not Enough memory, HeapAllocFailed !!\n"); + goto cleanup; + } + + // Copies the bytes for condition values from pUserClassCondValueInBytes + memcpy(pUserClassCondValueInBytes, szUserClassConditionValue, dwBytesLength); + + // Invokes helper API to create/fill the structure for adding conditions for the policy. + // The condition in this case is "user class" equals "Default Routing and Remote Access Class" + dwError = DhcpHlprAddV4PolicyCondition( + pPolicy, // Policy where conditions need to be added + dwExprIdx, // Parent expression index + policyAttrType, // Policy attribute type, possible values can be: DhcpAttrHWAddr, DhcpAttrOption and DhcpAttrSubOption + dwOptionId, // Option ID + dwSubOptionId, // Sub Option ID + NULL, // Vendor Name + conditionOper, // Policy comparator operator + pUserClassCondValueInBytes, // Condition values in bytes + dwBytesLength, // Number of bytes in the condition value + &dwConditionIdx // Condition index + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpHlprAddV4PolicyCondition failed with Error = %d\n", dwError); + goto cleanup; + } + + // Checks if the policy structure created is valid or not + dwError = DhcpHlprIsV4PolicyValid(pPolicy); + if(ERROR_SUCCESS == dwError) + wprintf(L"Valid Policy\n"); + else + wprintf(L"Invalid Policy\n"); + +cleanup: + // Frees the variable that holds the bytes for condition values + if(NULL != pUserClassCondValueInBytes) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pUserClassCondValueInBytes); + pUserClassCondValueInBytes = NULL; + } + + //Frees the variable that holds the policy structure + if(NULL != pPolicy) + { + DhcpHlprFreeV4Policy(pPolicy); + } + return 0; +} diff --git a/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.sln b/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.sln new file mode 100644 index 00000000..ff922b9d --- /dev/null +++ b/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hlprispolicyvalid", "hlprispolicyvalid.vcxproj", "{90C5617A-D14C-4524-9BBA-8E3C7B33243A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {90C5617A-D14C-4524-9BBA-8E3C7B33243A}.Debug|x64.ActiveCfg = Debug|x64 + {90C5617A-D14C-4524-9BBA-8E3C7B33243A}.Debug|x64.Build.0 = Debug|x64 + {90C5617A-D14C-4524-9BBA-8E3C7B33243A}.Release|x64.ActiveCfg = Release|x64 + {90C5617A-D14C-4524-9BBA-8E3C7B33243A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.vcxproj b/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.vcxproj new file mode 100644 index 00000000..cfe31f0e --- /dev/null +++ b/Samples/DHCP/HlprisPolicyValid/cpp/hlprispolicyvalid.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {90C5617A-D14C-4524-9BBA-8E3C7B33243A} + Win32Proj + hlprispolicyvalid + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + hlprispolicyvalid + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/QueryPolicyEnforcement/README.md b/Samples/DHCP/QueryPolicyEnforcement/README.md new file mode 100644 index 00000000..9bc08f82 --- /dev/null +++ b/Samples/DHCP/QueryPolicyEnforcement/README.md @@ -0,0 +1,42 @@ +DhcpV4QueryPolicyEnforcement API sample +======================================= + +This sample explains the usage of the DhcpV4QueryPolicyEnforcement API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4QueryPolicyEnforcement**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404338) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.cpp b/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.cpp new file mode 100644 index 00000000..db8f5ee9 --- /dev/null +++ b/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.cpp @@ -0,0 +1,41 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 +*/ + +#include +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; // Server IP Address, a value of NULL signifies the current server (where program is executed) + DWORD dwSubnet = 0xa000000; //(10.0.0.0) Subnet address + DWORD dwError = ERROR_SUCCESS;// Variable that holds the error code + BOOL bIsPolicyActivated = TRUE; + + // DhcpV4QueryPolicyEnforcement sets bPolicyActivated to TRUE if policies are enabled for the scope "dwSubnet" on the server, otherwise + // bPolicyActivated is set to FALSE. + dwError = DhcpV4QueryPolicyEnforcement( + pwszServer, // Server IP Address, a value of NULL means the current server (where the program is executed) + (dwSubnet == 0), // fGlobalPolicy, signifies whether the policy enforcement is queried for server or a specific scope + dwSubnet, // Subnet Address + &bIsPolicyActivated //PBOOL to hold the results of whether the policies are enabled or not + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4QueryPolicyEnforcement failed with Error = %d\n", dwError); + } + if(bIsPolicyActivated) + wprintf(L"Policy is enabled for scope %d\n",dwSubnet); + else + wprintf(L"Policy is disabled for scope %d\n", dwSubnet); + return 0; +} diff --git a/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.sln b/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.sln new file mode 100644 index 00000000..ffcb735e --- /dev/null +++ b/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "querypolicyenforcement", "querypolicyenforcement.vcxproj", "{84359DA2-09C2-498C-BAD2-D63BB454978F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {84359DA2-09C2-498C-BAD2-D63BB454978F}.Debug|x64.ActiveCfg = Debug|x64 + {84359DA2-09C2-498C-BAD2-D63BB454978F}.Debug|x64.Build.0 = Debug|x64 + {84359DA2-09C2-498C-BAD2-D63BB454978F}.Release|x64.ActiveCfg = Release|x64 + {84359DA2-09C2-498C-BAD2-D63BB454978F}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.vcxproj b/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.vcxproj new file mode 100644 index 00000000..4d0a59ee --- /dev/null +++ b/Samples/DHCP/QueryPolicyEnforcement/cpp/querypolicyenforcement.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {84359DA2-09C2-498C-BAD2-D63BB454978F} + Win32Proj + querypolicyenforcement + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + querypolicyenforcement + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/RemovePolicyRange/README.md b/Samples/DHCP/RemovePolicyRange/README.md new file mode 100644 index 00000000..e5233cc0 --- /dev/null +++ b/Samples/DHCP/RemovePolicyRange/README.md @@ -0,0 +1,42 @@ +DhcpV4RemovePolicyRange API sample +================================== + +This sample explains the usage of the DhcpV4RemovePolicyRange API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4RemovePolicyRange**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404340) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.cpp b/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.cpp new file mode 100644 index 00000000..07094ec4 --- /dev/null +++ b/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.cpp @@ -0,0 +1,44 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "testPolicy" on scope 10.0.0.0 + 3) There exists a policy range in the "testPolicy" with start address 10.0.0.10 and end address 10.0.0.50 +*/ + +#include +#include +#include + +int __cdecl main(void) +{ + DHCP_IP_RANGE range = {0}; // Variable to hold the range + DWORD dwError = ERROR_SUCCESS; // Variable to hold the error code + LPWSTR pwszPolicyName = L"testPolicy"; // Name of the policy + LPWSTR pwszServer = NULL; //Server IP Address, NULL signifies the current server (where the program is executed) + DWORD dwScope = 0xa000000; //(10.0.0.0) subnet address + DWORD dwStartAddress = 0xa00000a; //(10.0.0.10) start address of the range + DWORD dwEndAddress = 0xa000032; //(10.0.0.50) end address of the range + + range.StartAddress = dwStartAddress; + range.EndAddress = dwEndAddress; + + // Removes the range from the policy + dwError = DhcpV4RemovePolicyRange( + pwszServer, //Server IP Address, NULL signifies the current server (where the program is executed) + dwScope, // Subnet Address + pwszPolicyName, // Name of the policy + &range // Range that needs to be removed + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4RemovePolicyRange failed with Error = %d\n",dwError); + } + return 0; +} diff --git a/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.sln b/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.sln new file mode 100644 index 00000000..2f189761 --- /dev/null +++ b/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "removepolicyrange", "removepolicyrange.vcxproj", "{8DA81527-854B-4F9A-A7D6-A362BE95D2FE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8DA81527-854B-4F9A-A7D6-A362BE95D2FE}.Debug|x64.ActiveCfg = Debug|x64 + {8DA81527-854B-4F9A-A7D6-A362BE95D2FE}.Debug|x64.Build.0 = Debug|x64 + {8DA81527-854B-4F9A-A7D6-A362BE95D2FE}.Release|x64.ActiveCfg = Release|x64 + {8DA81527-854B-4F9A-A7D6-A362BE95D2FE}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.vcxproj b/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.vcxproj new file mode 100644 index 00000000..15f374e9 --- /dev/null +++ b/Samples/DHCP/RemovePolicyRange/cpp/removepolicyrange.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {8DA81527-854B-4F9A-A7D6-A362BE95D2FE} + Win32Proj + removepolicyrange + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + removepolicyrange + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/SetPolicy/README.md b/Samples/DHCP/SetPolicy/README.md new file mode 100644 index 00000000..7cf04936 --- /dev/null +++ b/Samples/DHCP/SetPolicy/README.md @@ -0,0 +1,42 @@ +DhcpV4SetPolicy API sample +========================== + +This sample explains the usage of the DhcpV4SetPolicy API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4SetPolicy**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404343) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/SetPolicy/cpp/setpolicy.cpp b/Samples/DHCP/SetPolicy/cpp/setpolicy.cpp new file mode 100644 index 00000000..9d35cab1 --- /dev/null +++ b/Samples/DHCP/SetPolicy/cpp/setpolicy.cpp @@ -0,0 +1,116 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 + 2) There exists a policy with the name "testPolicy" on scope 10.0.0.0 +*/ + +#include +#include +#include + + +// This routine frees LPDHCP_POLICY and its internal elements. +VOID FreeDhcpPolicyMemory(LPDHCP_POLICY pDhcpPolicy) +{ + if (NULL != pDhcpPolicy) + { + // Frees the policy description + if( NULL != pDhcpPolicy->Description) + DhcpRpcFreeMemory(pDhcpPolicy->Description); + + // Frees the policy condition + if(NULL != pDhcpPolicy->Conditions) + { + for(DWORD dwIndex = 0; dwIndexConditions->NumElements; dwIndex++) + { + // Frees the vendorName holder in condition's elements, if it exists + if( NULL != pDhcpPolicy->Conditions->Elements[dwIndex].VendorName) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].VendorName); + + // Frees the "bytes" used for storing condition values + if (NULL != pDhcpPolicy->Conditions->Elements[dwIndex].Value) + DhcpRpcFreeMemory(pDhcpPolicy->Conditions->Elements[dwIndex].Value); + } + DhcpRpcFreeMemory(pDhcpPolicy->Conditions); + } + + // Frees the policy expression + if(NULL != pDhcpPolicy->Expressions) + { + // Frees the expression elements, if they exist + if(pDhcpPolicy->Expressions->NumElements && pDhcpPolicy->Expressions->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Expressions->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Expressions); + } + + // Frees the policy ranges + if(NULL != pDhcpPolicy->Ranges) + { + // Frees the individual range elements + if(pDhcpPolicy->Ranges->Elements) + DhcpRpcFreeMemory(pDhcpPolicy->Ranges->Elements); + DhcpRpcFreeMemory(pDhcpPolicy->Ranges); + } + + // Finally frees the policy structure + DhcpRpcFreeMemory(pDhcpPolicy); + pDhcpPolicy=NULL; + } +} + +int __cdecl main(void) +{ + LPDHCP_POLICY pPolicy = NULL; // Variable that holds the DHCP_POLICY structure + DWORD dwError = ERROR_SUCCESS; // Variable that holds the error code + DWORD dwFieldsModified = 0; // Flag to reflect which all fields from DHCP_POLICY are modified + DHCP_IP_ADDRESS dwSubnet = 0xa000000; // SubnetAddress + LPWSTR pwszName = L"testPolicy"; // Name of the policy + LPWSTR pwszNewName = L"PolicyNewName"; // New name of the policy + LPWSTR pwszServer = NULL; //Server IP Address, NULL signifies the current server (where the program is executed) + + dwError = DhcpV4GetPolicy( + pwszServer, // Server IP Address, NULL signifies the current server (where the program is executed) + (dwSubnet == 0), // fGlobalPolicy, TRUE means a global policy, for a global policy SubnetAddress is 0. + dwSubnet, // Subnet address, if it is a global policy, its value is 0 + pwszName, // Name of the policy + &pPolicy // Policy structure obtained from the server + ); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4GetPolicy returned error. + wprintf(L"DhcpV4GetPolicy failed with error %d\n",dwError); + return 0; + } + // Frees the policy name + DhcpRpcFreeMemory(pPolicy->PolicyName); + + pPolicy->PolicyName = pwszNewName; + dwFieldsModified |= DhcpUpdatePolicyName; + + // DhcpV4SetPolicy reads the value for "dwFieldsModified" and whichever fields from DHCP_POLICY are getting modified, + // are taken from "pPolicy" and the necessary modification is performed. + // For example, "dwFieldsModified" has values "DhcpUpdatePolicyName". This means the "Name" field of DHCP_POLICY + // need to be modified. In that case, during modification, "Name" field is queried from "pPolicy" and necessary modification + // is performed. + dwError=DhcpV4SetPolicy( + pwszServer, // Server IP Address, NULL signifies the current server (where the program is executed) + dwFieldsModified, // Fields modified, flag to reflect which all parameters of DHCP_POLICY needs to be modified + (dwSubnet == 0), // fGloabalPolicy, whether the policy is for a specific scope or at server level. if subnetAddress is 0, it means it is at server level + dwSubnet, // Subnet Address + pwszName, // Name of the policy + pPolicy // policy structure whose values will form the modified policy + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4SetPolicy failed with Error = %d\n", dwError); + } + FreeDhcpPolicyMemory(pPolicy); + return 0; +} diff --git a/Samples/DHCP/SetPolicy/cpp/setpolicy.sln b/Samples/DHCP/SetPolicy/cpp/setpolicy.sln new file mode 100644 index 00000000..959a1af8 --- /dev/null +++ b/Samples/DHCP/SetPolicy/cpp/setpolicy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "setpolicy", "setpolicy.vcxproj", "{DB752058-3500-482D-8DFD-09A690A27027}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DB752058-3500-482D-8DFD-09A690A27027}.Debug|x64.ActiveCfg = Debug|x64 + {DB752058-3500-482D-8DFD-09A690A27027}.Debug|x64.Build.0 = Debug|x64 + {DB752058-3500-482D-8DFD-09A690A27027}.Release|x64.ActiveCfg = Release|x64 + {DB752058-3500-482D-8DFD-09A690A27027}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/SetPolicy/cpp/setpolicy.vcxproj b/Samples/DHCP/SetPolicy/cpp/setpolicy.vcxproj new file mode 100644 index 00000000..c1995034 --- /dev/null +++ b/Samples/DHCP/SetPolicy/cpp/setpolicy.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {DB752058-3500-482D-8DFD-09A690A27027} + Win32Proj + setpolicy + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + setpolicy + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/SetPolicyEnforcement/README.md b/Samples/DHCP/SetPolicyEnforcement/README.md new file mode 100644 index 00000000..83cf6f15 --- /dev/null +++ b/Samples/DHCP/SetPolicyEnforcement/README.md @@ -0,0 +1,42 @@ +DhcpV4SetPolicyEnforcement API sample +===================================== + +This sample explains the usage of the DhcpV4SetPolicyEnforcement API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4SetPolicyEnforcement**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404344) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.cpp b/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.cpp new file mode 100644 index 00000000..a1f327e5 --- /dev/null +++ b/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.cpp @@ -0,0 +1,50 @@ +// 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 + +/* +Assumptions: + 1) There exists a scope 10.0.0.0 +*/ + +#include +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; // Server IP Address, a value of NULL signifies the current server (where program is executed) + DWORD dwSubnet = 0xa000000; //(10.0.0.0) Subnet address + DWORD dwError = ERROR_SUCCESS;// Variable that holds the error code + BOOL bPolicyActivated = TRUE; + + // DhcpV4QueryPolicyEnforcement sets bPolicyActivated to TRUE if policies are enabled for the scope "dwSubnet" on the server, otherwise + // bPolicyActivated is set to FALSE. + dwError = DhcpV4QueryPolicyEnforcement( + pwszServer, // Server IP Address, a value of NULL means the current server (where the program is executed) + (dwSubnet == 0), // fGlobalPolicy, signifies whether the policy enforcement is queried for server or a specific scope + dwSubnet, // Subnet Address + &bPolicyActivated //PBOOL to hold the results of whether the policies are enabled or not + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4QueryPolicyEnforcement failed with Error = %d\n", dwError); + return 0; + } + //DhcpV4SetPolicyEnforcement sets the policy enforcement for the scope "dwSubnet" on the server. + dwError = DhcpV4SetPolicyEnforcement( + pwszServer, // Server IP Address, a value of NULL means the current server (where the program is executed) + (dwSubnet == 0), // fGlobalPolicy, signifies whether the policy enforcement is getting set for server or a specific scope + dwSubnet, // Subnet Address + ((bPolicyActivated==TRUE)?FALSE:TRUE)// Policy is to be enabled or disabled. + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4SetPolicyEnforcement failed with Error = %d\n", dwError); + return 0; + } + return 0; +} diff --git a/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.sln b/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.sln new file mode 100644 index 00000000..c1e40458 --- /dev/null +++ b/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "setpolicyenforcement", "setpolicyenforcement.vcxproj", "{16985943-B2CE-4ED7-A5A4-C67E1D97FEC2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {16985943-B2CE-4ED7-A5A4-C67E1D97FEC2}.Debug|x64.ActiveCfg = Debug|x64 + {16985943-B2CE-4ED7-A5A4-C67E1D97FEC2}.Debug|x64.Build.0 = Debug|x64 + {16985943-B2CE-4ED7-A5A4-C67E1D97FEC2}.Release|x64.ActiveCfg = Release|x64 + {16985943-B2CE-4ED7-A5A4-C67E1D97FEC2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.vcxproj b/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.vcxproj new file mode 100644 index 00000000..bc5ca298 --- /dev/null +++ b/Samples/DHCP/SetPolicyEnforcement/cpp/setpolicyenforcement.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {16985943-B2CE-4ED7-A5A4-C67E1D97FEC2} + Win32Proj + setpolicyenforcement + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + setpolicyenforcement + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/SetRelationship/README.md b/Samples/DHCP/SetRelationship/README.md new file mode 100644 index 00000000..33fde278 --- /dev/null +++ b/Samples/DHCP/SetRelationship/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverSetRelationship API sample +======================================== + +This sample explains the usage of the DhcpV4FailoverSetRelationship API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverSetRelationship**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404323) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/SetRelationship/cpp/setrelationship.cpp b/Samples/DHCP/SetRelationship/cpp/setrelationship.cpp new file mode 100644 index 00000000..6254f03f --- /dev/null +++ b/Samples/DHCP/SetRelationship/cpp/setrelationship.cpp @@ -0,0 +1,91 @@ +// 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 + +/* +Assumptions: + 1) There exists a relationship with the name "test" +*/ + +#include +#include +#include + +// This routine frees LPDHCP_FAILOVER_RELATIONSHIP and its internal elements. +VOID FreeRelationshipMemory(LPDHCP_FAILOVER_RELATIONSHIP pFailRel) +{ + if (NULL != pFailRel) + { + // Frees relationship name + if (NULL != pFailRel->RelationshipName) + DhcpRpcFreeMemory(pFailRel->RelationshipName); + + // Frees shared secret + if( NULL != pFailRel->SharedSecret) + DhcpRpcFreeMemory(pFailRel->SharedSecret); + + //Frees Primary server's name + if (NULL != pFailRel->PrimaryServerName) + DhcpRpcFreeMemory(pFailRel->PrimaryServerName); + + // Frees Secondary server's name + if (NULL != pFailRel->SecondaryServerName) + DhcpRpcFreeMemory(pFailRel->SecondaryServerName); + + //Frees pScopes + if (NULL != pFailRel->pScopes) + { + //Frees individual elements of pScopes + if(NULL != pFailRel->pScopes->Elements) + { + DhcpRpcFreeMemory(pFailRel->pScopes->Elements); + } + DhcpRpcFreeMemory(pFailRel->pScopes); + } + //Frees the relationship + DhcpRpcFreeMemory(pFailRel); + pFailRel=NULL; + } +} + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; // Server IP Address, a value of NULL signifies the current server (where program is executed) + LPWSTR pwszRelationshipName = L"test"; // Relationship name + LPDHCP_FAILOVER_RELATIONSHIP pRelationship = NULL; // Relationship structure + DWORD dwError = ERROR_SUCCESS;// Variable to hold error code + DWORD dwFlags = 0; // Flags to reflect which all fields are getting modified + + dwError = DhcpV4FailoverGetRelationship( + pwszServer, // Server IP Address + pwszRelationshipName, // Relationship name + &pRelationship // Relationship structure (LPDHCP_FAILOVER_RELATIONSHIP) + ); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverGetRelationship failed with Error = %d\n",dwError); + goto cleanup; + } + + pRelationship->Mode=HotStandby; // Failover mode + pRelationship->Mclt=0xe20; // 3616 seconds + pRelationship->SafePeriod=0x300; // 768 seconds + pRelationship->Percentage=0x46; //70 % + + dwFlags |= MODE | SAFEPERIOD | MCLT | PERCENTAGE; // mode, safeperiod, mclt and percentage field needs to be modified + dwError = DhcpV4FailoverSetRelationship( + pwszServer, // Server IP Address + dwFlags, // Flags to reflect which all fields are getting modified + pRelationship // Relationship structure from which values to be modified will be picked + ); + if( ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverSetRelationship failed with Error = %d\n",dwError); + } + FreeRelationshipMemory(pRelationship); +cleanup: + return 0; +} diff --git a/Samples/DHCP/SetRelationship/cpp/setrelationship.sln b/Samples/DHCP/SetRelationship/cpp/setrelationship.sln new file mode 100644 index 00000000..3dcdc4a6 --- /dev/null +++ b/Samples/DHCP/SetRelationship/cpp/setrelationship.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "setrelationship", "setrelationship.vcxproj", "{6E27E46C-73C2-4497-9868-79601C149262}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6E27E46C-73C2-4497-9868-79601C149262}.Debug|x64.ActiveCfg = Debug|x64 + {6E27E46C-73C2-4497-9868-79601C149262}.Debug|x64.Build.0 = Debug|x64 + {6E27E46C-73C2-4497-9868-79601C149262}.Release|x64.ActiveCfg = Release|x64 + {6E27E46C-73C2-4497-9868-79601C149262}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/SetRelationship/cpp/setrelationship.vcxproj b/Samples/DHCP/SetRelationship/cpp/setrelationship.vcxproj new file mode 100644 index 00000000..12fe32fd --- /dev/null +++ b/Samples/DHCP/SetRelationship/cpp/setrelationship.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {6E27E46C-73C2-4497-9868-79601C149262} + Win32Proj + setrelationship + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + setrelationship + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/SetStatelessStoreParams/README.md b/Samples/DHCP/SetStatelessStoreParams/README.md new file mode 100644 index 00000000..0977f003 --- /dev/null +++ b/Samples/DHCP/SetStatelessStoreParams/README.md @@ -0,0 +1,42 @@ +DhcpV6SetStatelessStoreParams API sample +======================================== + +This sample explains the usage of the DhcpV6SetStatelessStoreParams API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV6SetStatelessStoreParams**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404360) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.cpp b/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.cpp new file mode 100644 index 00000000..0738570b --- /dev/null +++ b/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.cpp @@ -0,0 +1,39 @@ +// 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 +#include +#include +#include + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; + LPWSTR pwszServer = NULL; + DHCP_IPV6_ADDRESS subnetAddress = {0}; + DWORD dwFieldModified = 0; + BOOL bServerLevel = TRUE; + DHCPV6_STATELESS_PARAMS storeParams = {0}; + + dwFieldModified |= DhcpStatelessPurgeInterval; // The parameters that need to be modified + storeParams.PurgeInterval = 1; // 1 hour + + dwError = DhcpV6SetStatelessStoreParams( + pwszServer, // Server IP Address, a value of NULL reflects the current server (where the program is executed), + bServerLevel, // Server level or Scope level + subnetAddress, // Contains the IPv6 subnet address of the stateless client + dwFieldModified, // Flag to reflect the fields which are getting modified in storeParams + &storeParams //Pointer to a DHCPV6_STATELESS_PARAMS structure that contains the stateless client inventory configuration settings + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV6SetStatelessStoreParams failed with Error = %d\n", dwError); + } + return 0; +} diff --git a/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.sln b/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.sln new file mode 100644 index 00000000..a55fc72f --- /dev/null +++ b/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetStatelessStoreParams", "SetStatelessStoreParams.vcxproj", "{436C3AF1-02D3-415D-8B27-B5FE781DAE42}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {436C3AF1-02D3-415D-8B27-B5FE781DAE42}.Debug|x64.ActiveCfg = Debug|x64 + {436C3AF1-02D3-415D-8B27-B5FE781DAE42}.Debug|x64.Build.0 = Debug|x64 + {436C3AF1-02D3-415D-8B27-B5FE781DAE42}.Release|x64.ActiveCfg = Release|x64 + {436C3AF1-02D3-415D-8B27-B5FE781DAE42}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.vcxproj b/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.vcxproj new file mode 100644 index 00000000..3745ffdf --- /dev/null +++ b/Samples/DHCP/SetStatelessStoreParams/cpp/SetStatelessStoreParams.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {436C3AF1-02D3-415D-8B27-B5FE781DAE42} + Win32Proj + SetStatelessStoreParams + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + SetStatelessStoreParams + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/TriggerAddrAllocation/README.md b/Samples/DHCP/TriggerAddrAllocation/README.md new file mode 100644 index 00000000..867d3e2f --- /dev/null +++ b/Samples/DHCP/TriggerAddrAllocation/README.md @@ -0,0 +1,42 @@ +DhcpV4FailoverTriggerAddrAllocation API sample +============================================== + +This sample explains the usage of the DhcpV4FailoverTriggerAddrAllocation API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4FailoverTriggerAddrAllocation**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404325) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.cpp b/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.cpp new file mode 100644 index 00000000..3797fee1 --- /dev/null +++ b/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.cpp @@ -0,0 +1,33 @@ +// 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 + +/* +Assumptions: + 1) There exists a relationship with the name "test" +*/ + +#include +#include +#include + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; + LPWSTR pwszServerName = NULL; + LPWSTR pwszRelationshipName = L"test"; + + // This triggers the address allocation + dwError = DhcpV4FailoverTriggerAddrAllocation( + pwszServerName, // Server IP Address, a value of NULL signifies the current server (where program is executed) + pwszRelationshipName // Relationship name + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4FailoverTriggerAddrAllocation failed with Error = %d\n",dwError); + } + return 0; +} diff --git a/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.sln b/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.sln new file mode 100644 index 00000000..92e8b935 --- /dev/null +++ b/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TriggerAddrAllocation", "TriggerAddrAllocation.vcxproj", "{B26EF730-3436-4FAC-B4CA-E9B35CCD83A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B26EF730-3436-4FAC-B4CA-E9B35CCD83A1}.Debug|x64.ActiveCfg = Debug|x64 + {B26EF730-3436-4FAC-B4CA-E9B35CCD83A1}.Debug|x64.Build.0 = Debug|x64 + {B26EF730-3436-4FAC-B4CA-E9B35CCD83A1}.Release|x64.ActiveCfg = Release|x64 + {B26EF730-3436-4FAC-B4CA-E9B35CCD83A1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.vcxproj b/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.vcxproj new file mode 100644 index 00000000..09901f72 --- /dev/null +++ b/Samples/DHCP/TriggerAddrAllocation/cpp/TriggerAddrAllocation.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {B26EF730-3436-4FAC-B4CA-E9B35CCD83A1} + Win32Proj + TriggerAddrAllocation + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + TriggerAddrAllocation + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/V4CreateClientInfo/README.md b/Samples/DHCP/V4CreateClientInfo/README.md new file mode 100644 index 00000000..7348628f --- /dev/null +++ b/Samples/DHCP/V4CreateClientInfo/README.md @@ -0,0 +1,42 @@ +DhcpV4CreateClientInfo API sample +================================= + +This sample explains the usage of the DhcpV4CreateClientInfo API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4CreateClientInfo**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404292) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.cpp b/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.cpp new file mode 100644 index 00000000..d087323d --- /dev/null +++ b/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.cpp @@ -0,0 +1,80 @@ +// 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 +#include +#include + +#define DHCP_DATE_TIME_INFINIT_HIGH 0x7FFFFFFF +#define DHCP_DATE_TIME_INFINIT_LOW 0xFFFFFFFF +#define ADDRESS_STATE_ACTIVE 1 +#define SAMPLE_HOST_NAME L"TEST-HOSTNAME" +#define SAMPLE_COMMENT L"TEST-COMMENT" + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to store the error code + DWORD dwIpAddress = 0xa00000a; // 10.0.0.10 + DWORD dwSubnetMask = 0xa000000; // 10.0.0.0 + LPWSTR pwszServer = NULL; // Server IP Address, Null signifies the current server (where the program is run) + DHCP_CLIENT_INFO_PB clientInfo = {0}; // Client Info to be created + LPWSTR pwszComment = SAMPLE_COMMENT; // Client comment + LPWSTR pwszPolicyName = NULL ; // Policy Name + DATE_TIME probEndTime = {0}; // Probation end time + DATE_TIME leaseExpTime = {0}; // Lease expiry time + BYTE clientType = CLIENT_TYPE_NONE; // Client Type + BYTE addressState = ADDRESS_STATE_ACTIVE; // ADDRESS_STATE_ACTIVE == 1 + BOOL bNAPCapable = FALSE; // NAP Capable or not + QuarantineStatus bNAPStatus = NOQUARANTINE; // Quarantine status + char* hwAddress = "121212"; + size_t dwHwAddrLen = strlen(hwAddress); + + // Create LeaseTime + // The assigned value mean that lease wont expire (Reservation) + leaseExpTime.dwHighDateTime = DHCP_DATE_TIME_INFINIT_HIGH; + leaseExpTime.dwLowDateTime = DHCP_DATE_TIME_INFINIT_LOW; + + // Fill clientInfo + clientInfo.ClientIpAddress = dwIpAddress; + clientInfo.SubnetMask = dwSubnetMask; + clientInfo.ClientName = SAMPLE_HOST_NAME; + clientInfo.ClientComment = pwszComment; + clientInfo.ClientLeaseExpires = leaseExpTime; + clientInfo.bClientType = clientType; + clientInfo.Status = bNAPStatus; + clientInfo.ProbationEnds = probEndTime; + clientInfo.QuarantineCapable = bNAPCapable; + clientInfo.FilterStatus = 0; + clientInfo.PolicyName = pwszPolicyName; + clientInfo.AddressState = addressState; + clientInfo.OwnerHost.HostName = SAMPLE_HOST_NAME; + clientInfo.OwnerHost.NetBiosName = SAMPLE_HOST_NAME; + clientInfo.OwnerHost.IpAddress = dwIpAddress; + + clientInfo.ClientHardwareAddress.DataLength = (DWORD)dwHwAddrLen; + clientInfo.ClientHardwareAddress.Data=(BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwHwAddrLen); + if(clientInfo.ClientHardwareAddress.Data == NULL) + goto Cleanup; + memcpy_s(clientInfo.ClientHardwareAddress.Data,dwHwAddrLen, hwAddress, dwHwAddrLen); + + //Creates a DHCPv4 client lease record in the DHCP server database + dwError = DhcpV4CreateClientInfo( + pwszServer, //ServerIpAddress, if this is NULL, it means the current server on which the program is run + &clientInfo + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4CreateClientInfo failed with Error = %d\n",dwError); + }else + { + wprintf(L"DhcpV4CreateClientInfo returned success\n"); + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, clientInfo.ClientHardwareAddress.Data); +Cleanup: + return 0; +} diff --git a/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.sln b/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.sln new file mode 100644 index 00000000..e03b084c --- /dev/null +++ b/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V4CreateClientInfo", "V4CreateClientInfo.vcxproj", "{A302AC14-A370-4A63-A000-BA98EADC0137}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A302AC14-A370-4A63-A000-BA98EADC0137}.Debug|x64.ActiveCfg = Debug|x64 + {A302AC14-A370-4A63-A000-BA98EADC0137}.Debug|x64.Build.0 = Debug|x64 + {A302AC14-A370-4A63-A000-BA98EADC0137}.Release|x64.ActiveCfg = Release|x64 + {A302AC14-A370-4A63-A000-BA98EADC0137}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.vcxproj b/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.vcxproj new file mode 100644 index 00000000..228f83a0 --- /dev/null +++ b/Samples/DHCP/V4CreateClientInfo/cpp/V4CreateClientInfo.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {A302AC14-A370-4A63-A000-BA98EADC0137} + Win32Proj + V4CreateClientInfo + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + V4CreateClientInfo + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/V4GetAllOptionValue/README.md b/Samples/DHCP/V4GetAllOptionValue/README.md new file mode 100644 index 00000000..389d1feb --- /dev/null +++ b/Samples/DHCP/V4GetAllOptionValue/README.md @@ -0,0 +1,42 @@ +DhcpV4GetAllOptionValues API sample +=================================== + +This sample explains the usage of the DhcpV4GetAllOptionValues API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4GetAllOptionValues**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404327) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.cpp b/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.cpp new file mode 100644 index 00000000..bc15635f --- /dev/null +++ b/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.cpp @@ -0,0 +1,39 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //NULL signifies current server + DWORD dwScope = 0xa000000; + DWORD dwError = ERROR_SUCCESS; + DHCP_OPTION_SCOPE_INFO scopeInfo; + LPDHCP_ALL_OPTION_VALUES_PB pOptionValues = NULL; + + ZeroMemory( &scopeInfo, sizeof(scopeInfo) ); + scopeInfo.ScopeType = DhcpSubnetOptions; + scopeInfo.ScopeInfo.SubnetScopeInfo =dwScope; + + dwError = DhcpV4GetAllOptionValues( + pwszServer, + 0, + &scopeInfo, + &pOptionValues); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4GetAllOptionValues returned error. + wprintf(L"DhcpV4GetAllOptionValues failed with error %d\n",dwError); + } + if(pOptionValues != NULL) + { + DhcpRpcFreeMemory(pOptionValues); + } + return 0; +} diff --git a/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.sln b/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.sln new file mode 100644 index 00000000..9729aac1 --- /dev/null +++ b/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v4getalloptionvalue", "v4getalloptionvalue.vcxproj", "{801E252E-10D5-4A3B-80C1-18D28DEE2F12}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {801E252E-10D5-4A3B-80C1-18D28DEE2F12}.Debug|x64.ActiveCfg = Debug|x64 + {801E252E-10D5-4A3B-80C1-18D28DEE2F12}.Debug|x64.Build.0 = Debug|x64 + {801E252E-10D5-4A3B-80C1-18D28DEE2F12}.Release|x64.ActiveCfg = Release|x64 + {801E252E-10D5-4A3B-80C1-18D28DEE2F12}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.vcxproj b/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.vcxproj new file mode 100644 index 00000000..5fe46337 --- /dev/null +++ b/Samples/DHCP/V4GetAllOptionValue/cpp/v4getalloptionvalue.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {801E252E-10D5-4A3B-80C1-18D28DEE2F12} + Win32Proj + v4getalloptionvalue + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + v4getalloptionvalue + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/V4GetClientInfo/README.md b/Samples/DHCP/V4GetClientInfo/README.md new file mode 100644 index 00000000..94e20d64 --- /dev/null +++ b/Samples/DHCP/V4GetClientInfo/README.md @@ -0,0 +1,42 @@ +DhcpV4GetClientInfo API sample +============================== + +This sample explains the usage of the DhcpV4GetClientInfo API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4GetClientInfo**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404329) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.cpp b/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.cpp new file mode 100644 index 00000000..4c37caa6 --- /dev/null +++ b/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.cpp @@ -0,0 +1,74 @@ +// 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 +#include +#include + +VOID FreeClientInfoMemory(LPDHCP_CLIENT_INFO_PB pClientInfo) +{ + if (NULL != pClientInfo) + { + // Frees client name + if( NULL != pClientInfo->ClientName) + DhcpRpcFreeMemory(pClientInfo->ClientName); + + //Frees policy name + if (NULL != pClientInfo->PolicyName) + DhcpRpcFreeMemory(pClientInfo->PolicyName); + + //Frees client comments + if (NULL != pClientInfo->ClientComment) + DhcpRpcFreeMemory(pClientInfo->ClientComment); + + //Frees the ClientHardwareAddress + if(NULL != pClientInfo->ClientHardwareAddress.Data && pClientInfo->ClientHardwareAddress.DataLength > 0) + DhcpRpcFreeMemory(pClientInfo->ClientHardwareAddress.Data); + + //Frees the HostName + if(NULL != pClientInfo->OwnerHost.HostName) + DhcpRpcFreeMemory(pClientInfo->OwnerHost.HostName); + + //Frees the NetBiosName + if(NULL != pClientInfo->OwnerHost.NetBiosName) + DhcpRpcFreeMemory(pClientInfo->OwnerHost.NetBiosName); + + // Frees the clientInfo + DhcpRpcFreeMemory(pClientInfo); + pClientInfo=NULL; + } +} + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to store the error code + DWORD dwIpAddress = 0xa00000a; // 10.0.0.10 + LPWSTR pwszServer = NULL; // Server IP Address, Null signifies the current server (where the program is run) + LPDHCP_CLIENT_INFO_PB pClientInfo = NULL; // Client Info to be created + DHCP_SEARCH_INFO searchInfo; + + searchInfo.SearchType = DhcpClientIpAddress; + searchInfo.SearchInfo.ClientIpAddress = dwIpAddress; + + //Creates a DHCPv4 client lease record in the DHCP server database + dwError = DhcpV4GetClientInfo( + pwszServer, //ServerIpAddress, if this is NULL, it means the current server on which the program is run + &searchInfo, + &pClientInfo + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4GetClientInfo failed with Error = %d\n",dwError); + }else + { + wprintf(L"Client Name = %s\n",pClientInfo->ClientName); + wprintf(L"Client Comment = %s\n",pClientInfo->ClientComment); + FreeClientInfoMemory(pClientInfo); + } + return 0; +} diff --git a/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.sln b/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.sln new file mode 100644 index 00000000..09e2f64c --- /dev/null +++ b/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V4GetClientInfo", "V4GetClientInfo.vcxproj", "{35CCA7F1-46DE-4F1A-AFBC-A6759AA40DB3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35CCA7F1-46DE-4F1A-AFBC-A6759AA40DB3}.Debug|x64.ActiveCfg = Debug|x64 + {35CCA7F1-46DE-4F1A-AFBC-A6759AA40DB3}.Debug|x64.Build.0 = Debug|x64 + {35CCA7F1-46DE-4F1A-AFBC-A6759AA40DB3}.Release|x64.ActiveCfg = Release|x64 + {35CCA7F1-46DE-4F1A-AFBC-A6759AA40DB3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.vcxproj b/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.vcxproj new file mode 100644 index 00000000..3dfad68a --- /dev/null +++ b/Samples/DHCP/V4GetClientInfo/cpp/V4GetClientInfo.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {35CCA7F1-46DE-4F1A-AFBC-A6759AA40DB3} + Win32Proj + V4GetClientInfo + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + V4GetClientInfo + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/V4GetFreeIPAddress/README.md b/Samples/DHCP/V4GetFreeIPAddress/README.md new file mode 100644 index 00000000..f080f94e --- /dev/null +++ b/Samples/DHCP/V4GetFreeIPAddress/README.md @@ -0,0 +1,42 @@ +DhcpV4GetFreeIPAddress API sample +================================= + +This sample explains the usage of the DhcpV4GetFreeIPAddress API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4GetFreeIPAddress**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404331) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.cpp b/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.cpp new file mode 100644 index 00000000..7f2f7ffc --- /dev/null +++ b/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.cpp @@ -0,0 +1,51 @@ +// 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 +#include +#include + + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to store the error code + DWORD dwNumAddr = 2; // specifies the number of IPv4 addresses retrieved from the specified scope in IPAddrList. + DWORD dwIndex = 0; + LPWSTR pwszServer = NULL; // Server IP Address, Null signifies the current server (where the program is run) + DHCP_IP_ADDRESS dwScope = 0xa000000; // Subnet address (10.0.0.0) + DHCP_IP_ADDRESS dwStartIp = 0; // 0 signifies scope's default start IP + DHCP_IP_ADDRESS dwEndIp = 0; // 0 signifies scope's default End IP + LPDHCP_IP_ARRAY pIpAddrList = NULL; + + // Retrieves the list of available IPv4 addresses that can be leased to clients + dwError = DhcpV4GetFreeIPAddress( + pwszServer, //ServerIpAddress, if this is NULL, it means the current server on which the program is run + dwScope, // Subnet address (10.0.0.0) + dwStartIp, // Start IP Address after which free IP address needs to be retrieved + dwEndIp, // End IP Address before which free IP address needs to be retrieved + dwNumAddr, // Total number of free IP address requested + &pIpAddrList // List of retrieved IP Addresses + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV4GetFreeIPAddress failed with Error = %d\n",dwError); + }else + { + if(pIpAddrList) + { + for(dwIndex = 0; dwIndex < pIpAddrList->NumElements; dwIndex++) + { + wprintf(L"Free IpAddress = %u\n",pIpAddrList->Elements[dwIndex]); + } + DhcpRpcFreeMemory(pIpAddrList->Elements); + DhcpRpcFreeMemory(pIpAddrList); + pIpAddrList = NULL; + } + } + return 0; +} diff --git a/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.sln b/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.sln new file mode 100644 index 00000000..f73cd7fe --- /dev/null +++ b/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V4GetFreeIPAddress", "V4GetFreeIPAddress.vcxproj", "{00B5BCDA-B02B-4CBE-847C-0D1E796402E3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {00B5BCDA-B02B-4CBE-847C-0D1E796402E3}.Debug|x64.ActiveCfg = Debug|x64 + {00B5BCDA-B02B-4CBE-847C-0D1E796402E3}.Debug|x64.Build.0 = Debug|x64 + {00B5BCDA-B02B-4CBE-847C-0D1E796402E3}.Release|x64.ActiveCfg = Release|x64 + {00B5BCDA-B02B-4CBE-847C-0D1E796402E3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.vcxproj b/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.vcxproj new file mode 100644 index 00000000..202a9cee --- /dev/null +++ b/Samples/DHCP/V4GetFreeIPAddress/cpp/V4GetFreeIPAddress.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {00B5BCDA-B02B-4CBE-847C-0D1E796402E3} + Win32Proj + V4GetFreeIPAddress + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + V4GetFreeIPAddress + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/V6CreateClientInfo/README.md b/Samples/DHCP/V6CreateClientInfo/README.md new file mode 100644 index 00000000..7bfbf7aa --- /dev/null +++ b/Samples/DHCP/V6CreateClientInfo/README.md @@ -0,0 +1,42 @@ +DhcpV6CreateClientInfo API sample +================================= + +This sample explains the usage of the DhcpV6CreateClientInfo API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV6CreateClientInfo**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404352) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.cpp b/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.cpp new file mode 100644 index 00000000..6251f821 --- /dev/null +++ b/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.cpp @@ -0,0 +1,72 @@ +// 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 +#include +#include + +#define DHCP_DATE_TIME_RANDOM_HIGH_VALUE 0x1ccba28 +#define DHCP_DATE_TIME_RANDOM_LOW_VALUE 0x3f4115f0 +#define DHCP_SAMPLE_IAID 0x1400155d +#define SAMPLE_HOST_NAME L"TEST-HOSTNAME" +#define SAMPLE_COMMENT L"TEST-COMMENT" + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to store the error code + DHCP_IPV6_ADDRESS dwIpAddress = {0}; + LPWSTR pwszServer = NULL; // Server IP Address, Null signifies the current server (where the program is run) + DHCP_CLIENT_INFO_V6 clientInfo = {0}; // Client Info to be created + LPWSTR pwszComment = SAMPLE_COMMENT; // Client comment + DATE_TIME leaseExpTime = {0}; // Lease expiry time + char* hwAddress = "12121212"; + size_t dwHwAddrLen = strlen(hwAddress); + + // Create LeaseTime + // The assigned value mean that lease wont expire (Reservation) + leaseExpTime.dwHighDateTime = DHCP_DATE_TIME_RANDOM_HIGH_VALUE; + leaseExpTime.dwLowDateTime = DHCP_DATE_TIME_RANDOM_LOW_VALUE; + + dwIpAddress.HighOrderBits = 0xfc00000000000000; + dwIpAddress.LowOrderBits = 0xa; + + // Fill clientInfo + clientInfo.ClientIpAddress = dwIpAddress; + clientInfo.ClientName = SAMPLE_HOST_NAME; + clientInfo.ClientComment = pwszComment; + clientInfo.ClientValidLeaseExpires = leaseExpTime; + clientInfo.ClientPrefLeaseExpires = leaseExpTime; + clientInfo.AddressType = 0; // IANA + clientInfo.IAID = DHCP_SAMPLE_IAID; + clientInfo.OwnerHost.HostName = SAMPLE_HOST_NAME; + clientInfo.OwnerHost.NetBiosName = SAMPLE_HOST_NAME; + clientInfo.OwnerHost.IpAddress = dwIpAddress; + + clientInfo.ClientDUID.DataLength = (DWORD)dwHwAddrLen; + clientInfo.ClientDUID.Data=(BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwHwAddrLen); + if(clientInfo.ClientDUID.Data == NULL) + goto Cleanup; + memcpy_s(clientInfo.ClientDUID.Data, dwHwAddrLen, hwAddress, dwHwAddrLen); + + //Creates a DHCPv4 client lease record in the DHCP server database + dwError = DhcpV6CreateClientInfo( + pwszServer, //ServerIpAddress, if this is NULL, it means the current server on which the program is run + &clientInfo + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV6CreateClientInfo failed with Error = %d\n",dwError); + }else + { + wprintf(L"DhcpV6CreateClientInfo returned success\n"); + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, clientInfo.ClientDUID.Data); +Cleanup: + return 0; +} + diff --git a/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.sln b/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.sln new file mode 100644 index 00000000..43c7f44c --- /dev/null +++ b/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V6CreateClientInfo", "V6CreateClientInfo.vcxproj", "{CB579724-1A00-4661-92AC-E12BF047CC09}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB579724-1A00-4661-92AC-E12BF047CC09}.Debug|x64.ActiveCfg = Debug|x64 + {CB579724-1A00-4661-92AC-E12BF047CC09}.Debug|x64.Build.0 = Debug|x64 + {CB579724-1A00-4661-92AC-E12BF047CC09}.Release|x64.ActiveCfg = Release|x64 + {CB579724-1A00-4661-92AC-E12BF047CC09}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.vcxproj b/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.vcxproj new file mode 100644 index 00000000..44edd121 --- /dev/null +++ b/Samples/DHCP/V6CreateClientInfo/cpp/V6CreateClientInfo.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {CB579724-1A00-4661-92AC-E12BF047CC09} + Win32Proj + V6CreateClientInfo + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + V6CreateClientInfo + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/V6GetFreeIPAddress/README.md b/Samples/DHCP/V6GetFreeIPAddress/README.md new file mode 100644 index 00000000..d92a8b0f --- /dev/null +++ b/Samples/DHCP/V6GetFreeIPAddress/README.md @@ -0,0 +1,42 @@ +DhcpV6GetFreeIPAddress API sample +================================= + +This sample explains the usage of the DhcpV6GetFreeIPAddress API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV6GetFreeIPAddress**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404354) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.cpp b/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.cpp new file mode 100644 index 00000000..838049b0 --- /dev/null +++ b/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.cpp @@ -0,0 +1,57 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + DWORD dwError = ERROR_SUCCESS; // Variable to store the error code + DWORD dwNumAddr = 4; // specifies the number of IPv6 addresses retrieved from the specified scope in IPAddrList. + DWORD dwIndex = 0; + LPWSTR pwszServer = NULL; // Server IP Address, Null signifies the current server (where the program is run) + DHCP_IPV6_ADDRESS dwScope = {0}; // Subnet address + DHCP_IPV6_ADDRESS dwStartIp = {0}; // 0 signifies scope's default start IP + DHCP_IPV6_ADDRESS dwEndIp = {0}; // 0 signifies scope's default End IP + LPDHCPV6_IP_ARRAY pIpAddrList = NULL; + + //Scope with prefix 2001:db8:: + dwScope.HighOrderBits = 0xfc00000000000000; + dwScope.LowOrderBits = 0; + + // Retrieves the list of available IPv6 addresses that can be leased to clients + dwError = DhcpV6GetFreeIPAddress( + pwszServer, //ServerIpAddress, if this is NULL, it means the current server on which the program is run + dwScope, // Subnet address + dwStartIp, // Start IP Address after which free IP address needs to be retrieved + dwEndIp, // End IP Address before which free IP address needs to be retrieved + dwNumAddr, // Total number of free IP address requested + &pIpAddrList // List of retrieved IP Addresses + ); + if(ERROR_SUCCESS != dwError) + { + wprintf(L"DhcpV6GetFreeIPAddress failed with Error = %d\n",dwError); + }else + { + for(dwIndex = 0; dwIndex < dwNumAddr; dwIndex++) + { + wprintf(L"Free IpAddress HighOrderBits = %llu LowOrderBits = %llu\n",pIpAddrList->Elements[dwIndex].HighOrderBits, pIpAddrList->Elements[dwIndex].LowOrderBits); + } + if(pIpAddrList) + { + if( NULL != pIpAddrList->Elements) + { + DhcpRpcFreeMemory(pIpAddrList->Elements); + } + DhcpRpcFreeMemory(pIpAddrList); + } + pIpAddrList = NULL; + } + return 0; +} diff --git a/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.sln b/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.sln new file mode 100644 index 00000000..fe1ce24e --- /dev/null +++ b/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V6GetFreeIPAddress", "V6GetFreeIPAddress.vcxproj", "{9277DD9F-2E76-494D-91D0-46B73FE1E620}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9277DD9F-2E76-494D-91D0-46B73FE1E620}.Debug|x64.ActiveCfg = Debug|x64 + {9277DD9F-2E76-494D-91D0-46B73FE1E620}.Debug|x64.Build.0 = Debug|x64 + {9277DD9F-2E76-494D-91D0-46B73FE1E620}.Release|x64.ActiveCfg = Release|x64 + {9277DD9F-2E76-494D-91D0-46B73FE1E620}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.vcxproj b/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.vcxproj new file mode 100644 index 00000000..7b85510b --- /dev/null +++ b/Samples/DHCP/V6GetFreeIPAddress/cpp/V6GetFreeIPAddress.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {9277DD9F-2E76-494D-91D0-46B73FE1E620} + Win32Proj + V6GetFreeIPAddress + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + V6GetFreeIPAddress + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/v4GetOptionValue/README.md b/Samples/DHCP/v4GetOptionValue/README.md new file mode 100644 index 00000000..7de4ca63 --- /dev/null +++ b/Samples/DHCP/v4GetOptionValue/README.md @@ -0,0 +1,42 @@ +DhcpV4GetOptionValue API sample +=============================== + +This sample explains the usage of the DhcpV4GetOptionValue API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4GetOptionValue**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404334) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.cpp b/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.cpp new file mode 100644 index 00000000..d00552e7 --- /dev/null +++ b/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.cpp @@ -0,0 +1,45 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //NULL signifies current server + DWORD dwScope = 0xa000000; + DWORD dwError = ERROR_SUCCESS; + LPWSTR pwszName = L"testPolicy"; + LPWSTR pwszVendorName = NULL; + DWORD dwOptionId =2; + DHCP_OPTION_SCOPE_INFO scopeInfo; + LPDHCP_OPTION_VALUE pOptionValue = NULL; + + ZeroMemory( &scopeInfo, sizeof(scopeInfo) ); + scopeInfo.ScopeType = DhcpSubnetOptions; + scopeInfo.ScopeInfo.SubnetScopeInfo =dwScope; + + dwError = DhcpV4GetOptionValue( + pwszServer, + 0, + dwOptionId, + pwszName, + pwszVendorName, + &scopeInfo, + &pOptionValue); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4GetOptionValue returned error. + wprintf(L"DhcpV4GetOptionValue failed with error %d\n",dwError); + } + if(pOptionValue != NULL) + { + DhcpRpcFreeMemory(pOptionValue); + } + return 0; +} diff --git a/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.sln b/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.sln new file mode 100644 index 00000000..f74c521a --- /dev/null +++ b/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v4getoptionvalue", "v4getoptionvalue.vcxproj", "{C0B6B24B-1C11-4F76-ADA2-B83417C1B75F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C0B6B24B-1C11-4F76-ADA2-B83417C1B75F}.Debug|x64.ActiveCfg = Debug|x64 + {C0B6B24B-1C11-4F76-ADA2-B83417C1B75F}.Debug|x64.Build.0 = Debug|x64 + {C0B6B24B-1C11-4F76-ADA2-B83417C1B75F}.Release|x64.ActiveCfg = Release|x64 + {C0B6B24B-1C11-4F76-ADA2-B83417C1B75F}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.vcxproj b/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.vcxproj new file mode 100644 index 00000000..4e42d765 --- /dev/null +++ b/Samples/DHCP/v4GetOptionValue/cpp/v4getoptionvalue.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {C0B6B24B-1C11-4F76-ADA2-B83417C1B75F} + Win32Proj + v4getoptionvalue + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + v4getoptionvalue + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/v4RemoveOptionValue/README.md b/Samples/DHCP/v4RemoveOptionValue/README.md new file mode 100644 index 00000000..b5843033 --- /dev/null +++ b/Samples/DHCP/v4RemoveOptionValue/README.md @@ -0,0 +1,42 @@ +DhcpV4RemoveOptionValue API sample +================================== + +This sample explains the usage of the DhcpV4RemoveOptionValue API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4RemoveOptionValue**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404339) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.cpp b/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.cpp new file mode 100644 index 00000000..388e22b9 --- /dev/null +++ b/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.cpp @@ -0,0 +1,39 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //NULL signifies current server + DWORD dwScope = 0xa000000; + DWORD dwError = ERROR_SUCCESS; + LPWSTR pwszName = L"testPolicy"; + LPWSTR pwszVendorName = NULL; + DWORD dwOptionId =2; + DHCP_OPTION_SCOPE_INFO scopeInfo; + + ZeroMemory( &scopeInfo, sizeof(scopeInfo) ); + scopeInfo.ScopeType = DhcpSubnetOptions; + scopeInfo.ScopeInfo.SubnetScopeInfo =dwScope; + + dwError = DhcpV4RemoveOptionValue( + pwszServer, + 0, + dwOptionId, + pwszName, + pwszVendorName, + &scopeInfo); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4RemoveOptionValue returned error. + wprintf(L"DhcpV4RemoveOptionValue failed with error %d\n",dwError); + } + return 0; +} diff --git a/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.sln b/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.sln new file mode 100644 index 00000000..454f5538 --- /dev/null +++ b/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v4removeoptionvalue", "v4removeoptionvalue.vcxproj", "{33FD6937-4A34-4C67-8EEC-944410DA7C30}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {33FD6937-4A34-4C67-8EEC-944410DA7C30}.Debug|x64.ActiveCfg = Debug|x64 + {33FD6937-4A34-4C67-8EEC-944410DA7C30}.Debug|x64.Build.0 = Debug|x64 + {33FD6937-4A34-4C67-8EEC-944410DA7C30}.Release|x64.ActiveCfg = Release|x64 + {33FD6937-4A34-4C67-8EEC-944410DA7C30}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.vcxproj b/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.vcxproj new file mode 100644 index 00000000..8d370104 --- /dev/null +++ b/Samples/DHCP/v4RemoveOptionValue/cpp/v4removeoptionvalue.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {33FD6937-4A34-4C67-8EEC-944410DA7C30} + Win32Proj + v4removeoptionvalue + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + v4removeoptionvalue + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/v4SetOptionValue/README.md b/Samples/DHCP/v4SetOptionValue/README.md new file mode 100644 index 00000000..6c4bb6f0 --- /dev/null +++ b/Samples/DHCP/v4SetOptionValue/README.md @@ -0,0 +1,42 @@ +DhcpV4SetOptionValue API sample +=============================== + +This sample explains the usage of the DhcpV4SetOptionValue API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4SetOptionValue**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404341) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.cpp b/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.cpp new file mode 100644 index 00000000..43aff6c8 --- /dev/null +++ b/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.cpp @@ -0,0 +1,55 @@ +// 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 +#include +#include + +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //NULL signifies current server + DWORD dwScope = 0xa000000; + DWORD dwError = ERROR_SUCCESS; + LPWSTR pwszName = L"testPolicy"; + LPWSTR pwszVendorName = NULL; + DWORD dwOptionId =2; + DHCP_OPTION_SCOPE_INFO scopeInfo; + DHCP_OPTION_DATA optionData = {0}; + + ZeroMemory( &scopeInfo, sizeof(scopeInfo) ); + scopeInfo.ScopeType = DhcpSubnetOptions; + scopeInfo.ScopeInfo.SubnetScopeInfo =dwScope; + + optionData.NumElements = 1; + optionData.Elements = (LPDHCP_OPTION_DATA_ELEMENT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DHCP_OPTION_DATA_ELEMENT)); + if(optionData.Elements == NULL) + { + wprintf(L"Not Enough memory\n"); + goto cleanup; + } + optionData.Elements->OptionType=DhcpDWordOption; + optionData.Elements->Element.DWordOption = 0x5; + dwError = DhcpV4SetOptionValue( + pwszServer, + 0, + dwOptionId, + pwszName, + pwszVendorName, + &scopeInfo, + &optionData); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4SetOptionValue returned error. + wprintf(L"DhcpV4SetOptionValue failed with error %d\n",dwError); + } + if(optionData.Elements != NULL) + { + HeapFree(GetProcessHeap(),0, optionData.Elements); + } +cleanup: + return 0; +} diff --git a/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.sln b/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.sln new file mode 100644 index 00000000..bfbc1fb8 --- /dev/null +++ b/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v4setoptionvalue", "v4setoptionvalue.vcxproj", "{827E2F43-B47C-47C0-AD37-48EF583029A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {827E2F43-B47C-47C0-AD37-48EF583029A7}.Debug|x64.ActiveCfg = Debug|x64 + {827E2F43-B47C-47C0-AD37-48EF583029A7}.Debug|x64.Build.0 = Debug|x64 + {827E2F43-B47C-47C0-AD37-48EF583029A7}.Release|x64.ActiveCfg = Release|x64 + {827E2F43-B47C-47C0-AD37-48EF583029A7}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.vcxproj b/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.vcxproj new file mode 100644 index 00000000..d792604b --- /dev/null +++ b/Samples/DHCP/v4SetOptionValue/cpp/v4setoptionvalue.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {827E2F43-B47C-47C0-AD37-48EF583029A7} + Win32Proj + v4setoptionvalue + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + v4setoptionvalue + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DHCP/v4SetOptionValues/README.md b/Samples/DHCP/v4SetOptionValues/README.md new file mode 100644 index 00000000..11632ece --- /dev/null +++ b/Samples/DHCP/v4SetOptionValues/README.md @@ -0,0 +1,42 @@ +DhcpV4SetOptionValues API sample +================================ + +This sample explains the usage of the DhcpV4SetOptionValues API.DHCP is a standardized protocol that enables clients to be dynamically assigned with various configuration parameters, such as an IP address, subnet mask, default gateway, and other critical network configuration information. DHCP servers centrally manage such configuration data, and are configured by network administrators with settings that are appropriate for a given network environment. DHCP servers, in turn, communicate with DHCP clients through the use of DHCP messages. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DhcpV4SetOptionValues**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404342) + +Related technologies +-------------------- + +[DHCP Server Management API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363376) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio Express 2013 for Windows 8.1 or later versions of Visual Studio and Windows (any SKU). (Or select the corresponding options from the Debug menu.) + diff --git a/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.cpp b/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.cpp new file mode 100644 index 00000000..7320f754 --- /dev/null +++ b/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.cpp @@ -0,0 +1,82 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +#include +#include +#include + +#define NUM_OPTION_VALUES 2 +int __cdecl main(void) +{ + LPWSTR pwszServer = NULL; //NULL signifies current server + DWORD dwScope = 0xa000000; + DWORD dwIndex = 0; + DWORD dwError = ERROR_SUCCESS; + LPWSTR pwszName = L"testPolicy"; + LPWSTR pwszVendorName = NULL; + DHCP_OPTION_SCOPE_INFO scopeInfo; + DHCP_OPTION_VALUE_ARRAY optionValueArray = {0}; + + ZeroMemory( &scopeInfo, sizeof(scopeInfo) ); + scopeInfo.ScopeType = DhcpSubnetOptions; + scopeInfo.ScopeInfo.SubnetScopeInfo =dwScope; + + optionValueArray.NumElements = 2; + optionValueArray.Values = (LPDHCP_OPTION_VALUE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (NUM_OPTION_VALUES*sizeof(DHCP_OPTION_VALUE))); + if(optionValueArray.Values == NULL) + { + wprintf(L"Not Enough memory\n"); + goto cleanup; + } + optionValueArray.Values[0].OptionID = 0xd; + optionValueArray.Values[0].Value.NumElements = 1; + optionValueArray.Values[0].Value.Elements=(LPDHCP_OPTION_DATA_ELEMENT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DHCP_OPTION_DATA_ELEMENT)); + if(optionValueArray.Values[0].Value.Elements == NULL) + { + wprintf(L"Not Enough Memory\n"); + goto cleanup; + } + optionValueArray.Values[0].Value.Elements->OptionType = DhcpDWordOption; + optionValueArray.Values[0].Value.Elements->Element.DWordOption = 0xa; + + optionValueArray.Values[1].OptionID = 0x3; + optionValueArray.Values[1].Value.NumElements = 1; + optionValueArray.Values[1].Value.Elements=(LPDHCP_OPTION_DATA_ELEMENT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DHCP_OPTION_DATA_ELEMENT)); + if(optionValueArray.Values[1].Value.Elements == NULL) + { + wprintf(L"Not Enough Memory\n"); + goto cleanup; + } + optionValueArray.Values[1].Value.Elements->OptionType = DhcpIpAddressOption; + optionValueArray.Values[1].Value.Elements->Element.IpAddressOption = 0xa000004; + + dwError = DhcpV4SetOptionValues( + pwszServer, + 0, + pwszName, + pwszVendorName, + &scopeInfo, + &optionValueArray); + if(ERROR_SUCCESS != dwError) + { + //DhcpV4SetOptionValue returned error. + wprintf(L"DhcpV4SetOptionValue failed with error %d\n",dwError); + } +cleanup: + if(optionValueArray.Values != NULL) + { + for(dwIndex = 0; dwIndex < optionValueArray.NumElements; dwIndex++) + { + if((optionValueArray.Values[dwIndex].Value.Elements != NULL)) + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, optionValueArray.Values[dwIndex].Value.Elements); + } + } + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, optionValueArray.Values); + } + return 0; +} diff --git a/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.sln b/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.sln new file mode 100644 index 00000000..2a2f2614 --- /dev/null +++ b/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v4setoptionvalues", "v4setoptionvalues.vcxproj", "{DEFAAE82-67ED-4C7A-898C-F00C83025574}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DEFAAE82-67ED-4C7A-898C-F00C83025574}.Debug|x64.ActiveCfg = Debug|x64 + {DEFAAE82-67ED-4C7A-898C-F00C83025574}.Debug|x64.Build.0 = Debug|x64 + {DEFAAE82-67ED-4C7A-898C-F00C83025574}.Release|x64.ActiveCfg = Release|x64 + {DEFAAE82-67ED-4C7A-898C-F00C83025574}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.vcxproj b/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.vcxproj new file mode 100644 index 00000000..1aa4e3f5 --- /dev/null +++ b/Samples/DHCP/v4SetOptionValues/cpp/v4setoptionvalues.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + $(VCTargetsPath11) + + + {DEFAAE82-67ED-4C7A-898C-F00C83025574} + Win32Proj + v4setoptionvalues + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + v4setoptionvalues + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + %(AdditionalDependencies) + dhcpsapi.lib + + + + + + diff --git a/Samples/DNSAsyncNetworkNameResolution/README.md b/Samples/DNSAsyncNetworkNameResolution/README.md new file mode 100644 index 00000000..c87f73cf --- /dev/null +++ b/Samples/DNSAsyncNetworkNameResolution/README.md @@ -0,0 +1,37 @@ +Asynchronous Winsock network name resolution sample +=================================================== + +This sample demonstrates how to Winsock to use asynchronously resolve network names using the [**GetAddrInfoEx**](http://msdn.microsoft.com/en-us/library/windows/desktop/ms738518) 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! + +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 +-------------- + +[**GetAddrInfoEx**](http://msdn.microsoft.com/en-us/library/windows/desktop/ms738518) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the CPP project solution (.sln) file within Visual Studio 2013 for Windows 8.1 (any SKU) or later versions of Visual Studio and Windows. Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. The sample will be built in the default \\Debug or Release directory. + +Run the sample +-------------- + +To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled) from Visual Studio. (Or select the corresponding options from the **Debug** menu.) When the app is running, switch to the Start screen and back to the desktop. + diff --git a/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.cpp b/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.cpp new file mode 100644 index 00000000..dfd2df6b --- /dev/null +++ b/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.cpp @@ -0,0 +1,236 @@ +// +// 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 +// +// Abstract: +// +// The sample demonstrates how to use asynchronous GetAddrInfoEx to +// resolve name to IP address. +// +// ResolveName +// +// + +#include +#include +#include +#include + +#define MAX_ADDRESS_STRING_LENGTH 64 + +// +// Asynchronous query context structure. +// + +typedef struct _QueryContext +{ + OVERLAPPED QueryOverlapped; + PADDRINFOEX QueryResults; + HANDLE CompleteEvent; +}QUERY_CONTEXT, *PQUERY_CONTEXT; + +VOID +WINAPI +QueryCompleteCallback( + _In_ DWORD Error, + _In_ DWORD Bytes, + _In_ LPOVERLAPPED Overlapped + ); + +int +__cdecl +wmain( + _In_ int Argc, + _In_reads_(Argc) PWCHAR Argv[] + ) +{ + INT Error = ERROR_SUCCESS; + WSADATA wsaData; + BOOL IsWSAStartupCalled = FALSE; + ADDRINFOEX Hints; + QUERY_CONTEXT QueryContext; + HANDLE CancelHandle = NULL; + DWORD QueryTimeout = 5 * 1000; // 5 seconds + + ZeroMemory(&QueryContext, sizeof(QueryContext)); + + // + // Validate the parameters + // + + if (Argc != 2) + { + wprintf(L"Usage: ResolveName \n"); + goto exit; + } + + // + // All Winsock functions require WSAStartup() to be called first + // + + Error = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (Error != 0) + { + wprintf(L"WSAStartup failed with %d\n", Error); + goto exit; + } + + IsWSAStartupCalled = TRUE; + + ZeroMemory(&Hints, sizeof(Hints)); + Hints.ai_family = AF_UNSPEC; + + // + // Note that this is a simple sample that waits/cancels a single + // asynchronous query. The reader may extend this to support + // multiple asynchronous queries. + // + + QueryContext.CompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (QueryContext.CompleteEvent == NULL) + { + Error = GetLastError(); + wprintf(L"Failed to create completion event: Error %d\n", Error); + goto exit; + } + + // + // Initiate asynchronous GetAddrInfoExW. + // + // Note GetAddrInfoEx can also be invoked asynchronously using an event + // in the overlapped object (Just set hEvent in the Overlapped object + // and set NULL as completion callback.) + // + // This sample uses the completion callback method. + // + + Error = GetAddrInfoExW(Argv[1], + NULL, + NS_DNS, + NULL, + &Hints, + &QueryContext.QueryResults, + NULL, + &QueryContext.QueryOverlapped, + QueryCompleteCallback, + &CancelHandle); + + // + // If GetAddrInfoExW() returns WSA_IO_PENDING, GetAddrInfoExW will invoke + // the completion routine. If GetAddrInfoExW returned anything else we must + // invoke the completion directly. + // + + if (Error != WSA_IO_PENDING) + { + QueryCompleteCallback(Error, 0, &QueryContext.QueryOverlapped); + goto exit; + } + + // + // Wait for query completion for 5 seconds and cancel the query if it has + // not yet completed. + // + + if (WaitForSingleObject(QueryContext.CompleteEvent, + QueryTimeout) == WAIT_TIMEOUT ) + { + + // + // Cancel the query: Note that the GetAddrInfoExCancelcancel call does + // not block, so we must wait for the completion routine to be invoked. + // If we fail to wait, WSACleanup() could be called while an + // asynchronous query is still in progress, possibly causing a crash. + // + + wprintf(L"The query took longer than %d seconds to complete; " + L"cancelling the query...\n", QueryTimeout/1000); + + GetAddrInfoExCancel(&CancelHandle); + + WaitForSingleObject(QueryContext.CompleteEvent, + INFINITE); + } + +exit: + + if (IsWSAStartupCalled) + { + WSACleanup(); + } + + if (QueryContext.CompleteEvent) + { + CloseHandle(QueryContext.CompleteEvent); + } + + return Error; +} + +// +// Callback function called by Winsock as part of asynchronous query complete +// + +VOID +WINAPI +QueryCompleteCallback( + _In_ DWORD Error, + _In_ DWORD Bytes, + _In_ LPOVERLAPPED Overlapped + ) +{ + PQUERY_CONTEXT QueryContext = NULL; + PADDRINFOEX QueryResults = NULL; + WCHAR AddrString[MAX_ADDRESS_STRING_LENGTH]; + DWORD AddressStringLength; + + UNREFERENCED_PARAMETER(Bytes); + + QueryContext = CONTAINING_RECORD(Overlapped, + QUERY_CONTEXT, + QueryOverlapped); + + if (Error != ERROR_SUCCESS) + { + wprintf(L"ResolveName failed with %d\n", Error); + goto exit; + } + + wprintf(L"ResolveName succeeded. Query Results:\n"); + + QueryResults = QueryContext->QueryResults; + + while(QueryResults) + { + AddressStringLength = MAX_ADDRESS_STRING_LENGTH; + + WSAAddressToString(QueryResults->ai_addr, + (DWORD)QueryResults->ai_addrlen, + NULL, + AddrString, + &AddressStringLength); + + wprintf(L"Ip Address: %s\n", AddrString); + QueryResults = QueryResults->ai_next; + } + +exit: + + if (QueryContext->QueryResults) + { + FreeAddrInfoEx(QueryContext->QueryResults); + } + + // + // Notify caller that the query completed + // + + SetEvent(QueryContext->CompleteEvent); + return; +} + diff --git a/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.sln b/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.sln new file mode 100644 index 00000000..db33c747 --- /dev/null +++ b/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ResolveName", "ResolveName.vcxproj", "{188D870B-80D9-4332-BC41-292CA6E8FF76}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {188D870B-80D9-4332-BC41-292CA6E8FF76}.Debug|Win32.ActiveCfg = Debug|Win32 + {188D870B-80D9-4332-BC41-292CA6E8FF76}.Debug|Win32.Build.0 = Debug|Win32 + {188D870B-80D9-4332-BC41-292CA6E8FF76}.Release|Win32.ActiveCfg = Release|Win32 + {188D870B-80D9-4332-BC41-292CA6E8FF76}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.vcxproj b/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.vcxproj new file mode 100644 index 00000000..730c3c78 --- /dev/null +++ b/Samples/DNSAsyncNetworkNameResolution/cpp/ResolveName.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + $(VCTargetsPath11) + + + {188D870B-80D9-4332-BC41-292CA6E8FF76} + Win32Proj + ResolveName + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + ResolveName + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Ws2_32.lib;%(AdditionalDependencies) + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Ws2_32.lib;%(AdditionalDependencies) + + + + + + diff --git a/Samples/DNSAsyncQuery/README.md b/Samples/DNSAsyncQuery/README.md new file mode 100644 index 00000000..76b4a8b5 --- /dev/null +++ b/Samples/DNSAsyncQuery/README.md @@ -0,0 +1,45 @@ +Asynchronous DNS query API sample +================================= + +This sample demonstrates how to asynchronously query DNS records and parse the results. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. + +This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[**DnsQuery**](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682016) + +[**DnsQueryEx**](http://msdn.microsoft.com/en-us/library/windows/desktop/hh447188) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the 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 titled DnsQueryEx.sln. + +3. Press F7 (or F6 for Visual Studio 2013) or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/DNSAsyncQuery/cpp/DnsQueryEx.cpp b/Samples/DNSAsyncQuery/cpp/DnsQueryEx.cpp new file mode 100644 index 00000000..d841886e --- /dev/null +++ b/Samples/DNSAsyncQuery/cpp/DnsQueryEx.cpp @@ -0,0 +1,364 @@ +// +// 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 +// +// Abstract: +// +// The sample demonstrates how to use asynchronous DnsQueryEx to +// resolve DNS records as well as using various types of DNS records. +// +// DnsQuery -q [-t QueryType] [-o QueryOptions] [-s server] +// + +#include +#include +#include +#include +#include +#include + +// +// Asynchronous query context structure. +// + +typedef struct _QueryContextStruct +{ + ULONG RefCount; + WCHAR QueryName[DNS_MAX_NAME_BUFFER_LENGTH]; + WORD QueryType; + ULONG QueryOptions; + DNS_QUERY_RESULT QueryResults; + DNS_QUERY_CANCEL QueryCancelContext; + HANDLE QueryCompletedEvent; +}QUERY_CONTEXT, *PQUERY_CONTEXT; + +DWORD +ParseArguments( + _In_ int Argc, + _In_reads_(Argc) PWCHAR Argv[], + _Out_writes_(DNS_MAX_NAME_BUFFER_LENGTH) PWSTR QueryName, + _Out_ WORD *QueryType, + _Out_ ULONG *QueryOptions, + _Out_writes_(MAX_PATH) PWSTR ServerIp + ); + +VOID +PrintDnsRecordList( + _Inout_ PDNS_RECORD DnsRecord + ); + +VOID +AddReferenceQueryContext( + _Inout_ PQUERY_CONTEXT QueryContext + ); + +VOID +DeReferenceQueryContext( + _Inout_ PQUERY_CONTEXT *QueryContext + ); + +DWORD +AllocateQueryContext( + _Out_ PQUERY_CONTEXT *QueryContext + ); + +DWORD +CreateDnsServerList( + _In_ PWSTR ServerIp, + _Out_ PDNS_ADDR_ARRAY DnsServerList + ); + +VOID +WINAPI +QueryCompleteCallback( + _In_ PVOID Context, + _Inout_ PDNS_QUERY_RESULT QueryResults + ); + +int +__cdecl +wmain( + _In_ int Argc, + _In_reads_(Argc) PWCHAR Argv[] + ) +{ + DWORD Error = ERROR_SUCCESS; + PQUERY_CONTEXT QueryContext = NULL; + DNS_QUERY_REQUEST DnsQueryRequest; + DWORD QueryTimeout = 5 * 1000; // 5 seconds + WCHAR ServerIp[MAX_PATH]; + DNS_ADDR_ARRAY DnsServerList; + + // + // Allocate QueryContext + // + + Error = AllocateQueryContext(&QueryContext); + + if (Error != ERROR_SUCCESS) + { + wprintf(L"AllocateQueryContext failed with error %d", Error); + goto exit; + } + + // + // Parse input arguments + // + + Error = ParseArguments(Argc, + Argv, + QueryContext->QueryName, + &QueryContext->QueryType, + &QueryContext->QueryOptions, + ServerIp); + + if (Error != ERROR_SUCCESS) + { + goto exit; + } + + // + // Initiate asynchronous DnsQuery: Note that QueryResults and + // QueryCancelContext should be valid till query completes. + // + + ZeroMemory(&DnsQueryRequest, sizeof(DnsQueryRequest)); + + DnsQueryRequest.Version = DNS_QUERY_REQUEST_VERSION1; + DnsQueryRequest.QueryName = QueryContext->QueryName; + DnsQueryRequest.QueryType = QueryContext->QueryType; + DnsQueryRequest.QueryOptions = (ULONG64)QueryContext->QueryOptions; + DnsQueryRequest.pQueryContext = QueryContext; + DnsQueryRequest.pQueryCompletionCallback = QueryCompleteCallback; + + // + // If user specifies server, construct DNS_ADDR_ARRAY + // + + if (ServerIp[0] != L'\0') + { + Error = CreateDnsServerList(ServerIp, &DnsServerList); + + if (Error != ERROR_SUCCESS) + { + wprintf(L"CreateDnsServerList failed with error %d", Error); + goto exit; + } + + DnsQueryRequest.pDnsServerList = &DnsServerList; + } + + // + // Add a reference before initiating asynchronous query. + // + + AddReferenceQueryContext(QueryContext); + + Error = DnsQueryEx(&DnsQueryRequest, + &QueryContext->QueryResults, + &QueryContext->QueryCancelContext); + + // + // If DnsQueryEx() returns DNS_REQUEST_PENDING, Completion routine + // will be invoked. If not (when completed inline) completion routine + // will not be invoked. + // + + if (Error != DNS_REQUEST_PENDING) + { + QueryCompleteCallback(QueryContext, &QueryContext->QueryResults); + goto exit; + } + + // + // Wait for query completion for 5 seconds and initiate cancel if + // completion has not happened. + // + + if (WaitForSingleObject(QueryContext->QueryCompletedEvent, + QueryTimeout) == WAIT_TIMEOUT) + { + + // + // Initiate Cancel: Note that Cancel is just a request which will + // speed the process. It should still wait for the completion callback. + // + + wprintf(L"The query took longer than %d seconds to complete; " + L"cancelling the query...\n", QueryTimeout/1000); + + DnsCancelQuery(&QueryContext->QueryCancelContext); + + WaitForSingleObject(QueryContext->QueryCompletedEvent, + INFINITE); + } + +exit: + + if (QueryContext) + { + DeReferenceQueryContext(&QueryContext); + } + + return Error; +} + +VOID +AddReferenceQueryContext( + _Inout_ PQUERY_CONTEXT QueryContext + ) +{ + InterlockedIncrement(&QueryContext->RefCount); +} + +VOID +DeReferenceQueryContext( + _Inout_ PQUERY_CONTEXT *QueryContext + ) +{ + PQUERY_CONTEXT QC = *QueryContext; + + if (InterlockedDecrement(&QC->RefCount) == 0) + { + if (QC->QueryCompletedEvent) + { + CloseHandle(QC->QueryCompletedEvent); + } + + HeapFree(GetProcessHeap(), + 0, + QC); + *QueryContext = NULL; + } +} + +DWORD +AllocateQueryContext( + _Out_ PQUERY_CONTEXT *QueryContext + ) +{ + DWORD Error = ERROR_SUCCESS; + + *QueryContext = (PQUERY_CONTEXT) HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(QUERY_CONTEXT)); + if (*QueryContext == NULL) + { + Error = GetLastError(); + goto exit; + } + + AddReferenceQueryContext(*QueryContext); + + (*QueryContext)->QueryResults.Version = DNS_QUERY_RESULTS_VERSION1; + + (*QueryContext)->QueryCompletedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if ((*QueryContext)->QueryCompletedEvent == NULL) + { + Error = GetLastError(); + DeReferenceQueryContext(QueryContext); + *QueryContext = NULL; + goto exit; + } + +exit: + return Error; +} + +// +// Wrapper function that creates DNS_ADDR_ARRAY from IP address string. +// + +DWORD +CreateDnsServerList( + _In_ PWSTR ServerIp, + _Out_ PDNS_ADDR_ARRAY DnsServerList + ) +{ + DWORD Error = ERROR_SUCCESS; + SOCKADDR_STORAGE SockAddr; + INT AddressLength; + WSADATA wsaData; + + ZeroMemory(DnsServerList, sizeof(*DnsServerList)); + + Error = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (Error != 0) + { + wprintf(L"WSAStartup failed with %d\n", Error); + return Error; + } + + AddressLength = sizeof(SockAddr); + Error = WSAStringToAddress(ServerIp, + AF_INET, + NULL, + (LPSOCKADDR)&SockAddr, + &AddressLength); + if (Error != ERROR_SUCCESS) + { + + AddressLength = sizeof(SockAddr); + Error = WSAStringToAddress(ServerIp, + AF_INET6, + NULL, + (LPSOCKADDR)&SockAddr, + &AddressLength); + } + + if (Error != ERROR_SUCCESS) + { + wprintf(L"WSAStringToAddress for %s failed with error %d\n", + ServerIp, + Error); + goto exit; + } + + DnsServerList->MaxCount = 1; + DnsServerList->AddrCount = 1; + CopyMemory(DnsServerList->AddrArray[0].MaxSa, &SockAddr, DNS_ADDR_MAX_SOCKADDR_LENGTH); + +exit: + + WSACleanup(); + return Error; +} + + +// +// Callback function called by DNS as part of asynchronous query complete +// + +VOID +WINAPI +QueryCompleteCallback( + _In_ PVOID Context, + _Inout_ PDNS_QUERY_RESULT QueryResults + ) +{ + PQUERY_CONTEXT QueryContext = (PQUERY_CONTEXT)Context; + + if (QueryResults->QueryStatus == ERROR_SUCCESS) + { + wprintf(L"DnsQuery() succeeded.\n Query response records:\n"); + PrintDnsRecordList(QueryResults->pQueryRecords); + } + else + { + wprintf(L"DnsQuery() failed, %d\n", QueryResults->QueryStatus); + } + + if (QueryResults->pQueryRecords) + { + DnsRecordListFree(QueryResults->pQueryRecords, DnsFreeRecordList); + } + + SetEvent(QueryContext->QueryCompletedEvent); + DeReferenceQueryContext(&QueryContext); +} + diff --git a/Samples/DNSAsyncQuery/cpp/DnsQueryEx.sln b/Samples/DNSAsyncQuery/cpp/DnsQueryEx.sln new file mode 100644 index 00000000..662efdf6 --- /dev/null +++ b/Samples/DNSAsyncQuery/cpp/DnsQueryEx.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DnsQuery", "DnsQueryEx.vcxproj", "{D8ED101B-C401-4E7F-9EA0-17B5412124BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D8ED101B-C401-4E7F-9EA0-17B5412124BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {D8ED101B-C401-4E7F-9EA0-17B5412124BD}.Debug|Win32.Build.0 = Debug|Win32 + {D8ED101B-C401-4E7F-9EA0-17B5412124BD}.Release|Win32.ActiveCfg = Release|Win32 + {D8ED101B-C401-4E7F-9EA0-17B5412124BD}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DNSAsyncQuery/cpp/DnsQueryEx.vcxproj b/Samples/DNSAsyncQuery/cpp/DnsQueryEx.vcxproj new file mode 100644 index 00000000..7a1c9c9f --- /dev/null +++ b/Samples/DNSAsyncQuery/cpp/DnsQueryEx.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + $(VCTargetsPath11) + + + {D8ED101B-C401-4E7F-9EA0-17B5412124BD} + Win32Proj + DnsQuery + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + DnsQuery + + + false + + + + + + Level4 + Disabled + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dnsapi.lib;ntdll.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + Level4 + + + MaxSpeed + true + true + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dnsapi.lib;ntdll.lib;ws2_32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/Samples/DNSAsyncQuery/cpp/ParseArgs.cpp b/Samples/DNSAsyncQuery/cpp/ParseArgs.cpp new file mode 100644 index 00000000..88748b42 --- /dev/null +++ b/Samples/DNSAsyncQuery/cpp/ParseArgs.cpp @@ -0,0 +1,301 @@ +// +// 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 +// +// Abstract: +// +// This file abstracts parsing input arguments for DnsQuery Sample +// +// DnsQuery -q [-t QueryType] [-o QueryOptions] [-s server] +// + +#include +#include +#include +#include +#include + +VOID +PrintHelp() +{ + wprintf(L"Usage: DnsQuery -q [-t QueryType] [-s DnsServerIP] [-o QueryOptions]\n"); + wprintf(L"\t\tInput query Name\n"); + wprintf(L"\t\tInput query type: A, PTR, NS, AAAA, TXT....\n"); + wprintf(L"\t\tDNS Server IP address\n"); + wprintf(L"\t\tInput query flags (use combination of following numerics or one of the below option string):\n"); + wprintf(L"\t\t\t\t0x0 DNS_QUERY_STANDARD\n"); + wprintf(L"\t\t\t\t0x1 DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE\n"); + wprintf(L"\t\t\t\t0x2 DNS_QUERY_USE_TCP_ONLY\n"); + wprintf(L"\t\t\t\t0x4 DNS_QUERY_NO_RECURSION\n"); + wprintf(L"\t\t\t\t0x8 DNS_QUERY_BYPASS_CACHE\n"); + wprintf(L"\t\t\t\t0x10 DNS_QUERY_NO_WIRE_QUERY\n"); + wprintf(L"\t\t\t\t0x20 DNS_QUERY_NO_LOCAL_NAME\n"); + wprintf(L"\t\t\t\t0x40 DNS_QUERY_NO_HOSTS_FILE\n"); + wprintf(L"\t\t\t\t0x100 DNS_QUERY_WIRE_ONLY\n"); + wprintf(L"\t\t\t\t0x400 DNS_QUERY_MULTICAST_ONLY\n"); + wprintf(L"\t\t\t\t0x800 DNS_QUERY_NO_MULTICAST\n"); + wprintf(L"\t\t\t\t0x1000 DNS_QUERY_TREAT_AS_FQDN\n"); + wprintf(L"\t\t\t\t0x200000 DNS_QUERY_DISABLE_IDN_ENCODING\n"); + wprintf(L"\n"); + return; +} + +typedef struct _USER_FRIENDLY_QUERY_TYPE +{ + PWSTR String; + WORD Value; +}USER_FRIENDLY_QUERY_TYPE; + +USER_FRIENDLY_QUERY_TYPE TypeTable[] = +{ + L"ZERO" , 0 , + L"A" , DNS_TYPE_A , + L"NS" , DNS_TYPE_NS , + L"MD" , DNS_TYPE_MD , + L"MF" , DNS_TYPE_MF , + L"CNAME" , DNS_TYPE_CNAME , + L"SOA" , DNS_TYPE_SOA , + L"MB" , DNS_TYPE_MB , + L"MG" , DNS_TYPE_MG , + L"MR" , DNS_TYPE_MR , + L"NULL" , DNS_TYPE_NULL , + L"WKS" , DNS_TYPE_WKS , + L"PTR" , DNS_TYPE_PTR , + L"HINFO" , DNS_TYPE_HINFO , + L"MINFO" , DNS_TYPE_MINFO , + L"MX" , DNS_TYPE_MX , + L"TXT" , DNS_TYPE_TEXT , + L"RP" , DNS_TYPE_RP , + L"AFSDB" , DNS_TYPE_AFSDB , + L"X25" , DNS_TYPE_X25 , + L"ISDN" , DNS_TYPE_ISDN , + L"RT" , DNS_TYPE_RT , + L"NSAP" , DNS_TYPE_NSAP , + L"NSAPPTR" , DNS_TYPE_NSAPPTR , + L"SIG" , DNS_TYPE_SIG , + L"KEY" , DNS_TYPE_KEY , + L"PX" , DNS_TYPE_PX , + L"GPOS" , DNS_TYPE_GPOS , + L"AAAA" , DNS_TYPE_AAAA , + L"LOC" , DNS_TYPE_LOC , + L"NXT" , DNS_TYPE_NXT , + L"EID" , DNS_TYPE_EID , + L"NIMLOC" , DNS_TYPE_NIMLOC , + L"SRV" , DNS_TYPE_SRV , + L"ATMA" , DNS_TYPE_ATMA , + L"NAPTR" , DNS_TYPE_NAPTR , + L"KX" , DNS_TYPE_KX , + L"CERT" , DNS_TYPE_CERT , + L"A6" , DNS_TYPE_A6 , + L"DNAME" , DNS_TYPE_DNAME , + L"SINK" , DNS_TYPE_SINK , + L"OPT" , DNS_TYPE_OPT , + L"DS" , DNS_TYPE_DS , + L"RRSIG" , DNS_TYPE_RRSIG , + L"NSEC" , DNS_TYPE_NSEC , + L"DNSKEY" , DNS_TYPE_DNSKEY , + L"DHCID" , DNS_TYPE_DHCID , + L"NSEC3" , DNS_TYPE_NSEC3 , + L"NSEC3PARAM", DNS_TYPE_NSEC3PARAM , + L"ALL" , DNS_TYPE_ALL , + NULL, 0, +}; + +WORD +ExtractUserFriendlyQueryType( + _In_ PWSTR QueryType + ) +{ + INT Index = 0; + WORD ReturnValue = 0; + PWSTR EndPtr = NULL; + + while(TypeTable[Index].String != NULL) + { + if (_wcsicmp(QueryType, TypeTable[Index].String) == 0) + { + ReturnValue = TypeTable[Index].Value; + goto exit; + } + Index++; + } + + ReturnValue = (WORD)wcstoul(QueryType, &EndPtr, 0); + +exit: + return ReturnValue; +} + +typedef struct _USER_FRIENDLY_QUERY_OPTIONS +{ + PWSTR String; + ULONG Value; +}USER_FRIENDLY_QUERY_OPTIONS; + +USER_FRIENDLY_QUERY_OPTIONS TableOption[] = +{ + L"DNS_QUERY_STANDARD", DNS_QUERY_STANDARD, + L"DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE", DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE, + L"DNS_QUERY_USE_TCP_ONLY", DNS_QUERY_USE_TCP_ONLY, + L"DNS_QUERY_NO_RECURSION", DNS_QUERY_NO_RECURSION, + L"DNS_QUERY_BYPASS_CACHE", DNS_QUERY_BYPASS_CACHE, + L"DNS_QUERY_NO_WIRE_QUERY", DNS_QUERY_NO_WIRE_QUERY, + L"DNS_QUERY_NO_LOCAL_NAME", DNS_QUERY_NO_LOCAL_NAME, + L"DNS_QUERY_NO_HOSTS_FILE", DNS_QUERY_NO_HOSTS_FILE, + L"DNS_QUERY_WIRE_ONLY", DNS_QUERY_WIRE_ONLY, + L"DNS_QUERY_MULTICAST_ONLY", DNS_QUERY_MULTICAST_ONLY, + L"DNS_QUERY_NO_MULTICAST", DNS_QUERY_NO_MULTICAST, + L"DNS_QUERY_TREAT_AS_FQDN", DNS_QUERY_TREAT_AS_FQDN, + L"DNS_QUERY_DISABLE_IDN_ENCODING", DNS_QUERY_DISABLE_IDN_ENCODING, + NULL, 0, +}; + +ULONG +ExtractUserFriendlyQueryOptions( + _In_ PWSTR QueryOptions + ) +{ + INT Index = 0; + ULONG ReturnValue = 0; + PWSTR EndPtr = NULL; + + while(TableOption[Index].String != NULL) + { + if (_wcsicmp(QueryOptions, TableOption[Index].String) == 0) + { + ReturnValue = TableOption[Index].Value; + goto exit; + } + Index++; + } + + ReturnValue = (ULONG)wcstoul(QueryOptions, &EndPtr, 0); + +exit: + return ReturnValue; +} + +DWORD +ParseArguments( + _In_ int Argc, + _In_reads_(Argc) PWCHAR Argv[], + _Out_writes_(DNS_MAX_NAME_BUFFER_LENGTH) PWSTR QueryName, + _Out_ WORD *QueryType, + _Out_ ULONG *QueryOptions, + _Out_writes_(MAX_PATH) PWSTR ServerIp + ) +{ + int CurrentIndex = 1; + BOOL ArgContainsQueryName = FALSE; + BOOL Error = ERROR_INVALID_PARAMETER; + + *QueryType = DNS_TYPE_A; // default type + *QueryOptions = 0; // default query options + *QueryName = L'\0'; + *ServerIp = L'\0'; + + while (CurrentIndex < Argc) + { + // + // Query Name: + // + + #pragma prefast(suppress:6385, "CurrentIndex is guaranteed less than Argc") + if (_wcsicmp(Argv[CurrentIndex], L"-q") == 0) + { + CurrentIndex++; + if (CurrentIndex < Argc) + { + StringCchCopy(QueryName, DNS_MAX_NAME_BUFFER_LENGTH, Argv[CurrentIndex]); + ArgContainsQueryName = TRUE; + } + else + { + goto exit; + } + } + + // + // Query Type + // + + else if (_wcsicmp(Argv[CurrentIndex], L"-t") == 0) + { + + CurrentIndex++; + if (CurrentIndex < Argc) + { + *QueryType = ExtractUserFriendlyQueryType(Argv[CurrentIndex]); + if (*QueryType == 0) + { + goto exit; + } + } + else + { + goto exit; + } + } + + // + // Query Options + // + + else if (_wcsicmp(Argv[CurrentIndex], L"-o") == 0) + { + + CurrentIndex++; + if (CurrentIndex < Argc) + { + *QueryOptions = ExtractUserFriendlyQueryOptions(Argv[CurrentIndex]); + } + else + { + goto exit; + } + } + + // + // Server List + // + + else if (_wcsicmp(Argv[CurrentIndex], L"-s") == 0) + { + CurrentIndex++; + if (CurrentIndex < Argc) + { + StringCchCopy(ServerIp, MAX_PATH, Argv[CurrentIndex]); + } + else + { + goto exit; + } + } + + #pragma prefast(suppress:6385, "CurrentIndex is guaranteed less than Argc") + else + { + goto exit; + } + CurrentIndex++; + } + + if (ArgContainsQueryName) + { + Error = ERROR_SUCCESS; + } + +exit: + if (Error != ERROR_SUCCESS) + { + PrintHelp(); + } + + return Error; + +} + diff --git a/Samples/DNSAsyncQuery/cpp/PrintDnsRecord.cpp b/Samples/DNSAsyncQuery/cpp/PrintDnsRecord.cpp new file mode 100644 index 00000000..d0087ff0 --- /dev/null +++ b/Samples/DNSAsyncQuery/cpp/PrintDnsRecord.cpp @@ -0,0 +1,327 @@ +// +// 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 +// +// Abstract: +// +// This file abstracts printing various types of DNS records. +// + +#include +#include +#include +#include +#include +#include + +#define MAX_ADDRESS_STRING_LENGTH 64 + +VOID +ARecordPrint( + PDNS_RECORD DnsRecord + ) +{ + struct in_addr Ipv4address; + WCHAR Ipv4String[MAX_ADDRESS_STRING_LENGTH] = L"\0"; + + Ipv4address.S_un.S_addr = DnsRecord->Data.A.IpAddress; + RtlIpv4AddressToString(&Ipv4address, Ipv4String); + + wprintf(L"\tIP address = %s\n",Ipv4String); +} + +VOID +PtrRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tHostName = %s\n", DnsRecord->Data.PTR.pNameHost); +} + +VOID +SoaRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + + wprintf(L"n\tPrimary = %s\n" + L"\tAdmin = %s\n" + L"\tSerial = %d\n" + L"\tRefresh = %d\n" + L"\tRetry = %d\n" + L"\tExpire = %d\n" + L"\tDefault TTL = %d\n", + DnsRecord->Data.SOA.pNamePrimaryServer, + DnsRecord->Data.SOA.pNameAdministrator, + DnsRecord->Data.SOA.dwSerialNo, + DnsRecord->Data.SOA.dwRefresh, + DnsRecord->Data.SOA.dwRetry, + DnsRecord->Data.SOA.dwExpire, + DnsRecord->Data.SOA.dwDefaultTtl); + +} +VOID +TxtRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + INT Index = 0; + INT Count = 0; + LPTSTR *StringArray; + + + Count = DnsRecord->Data.TXT.dwStringCount; + StringArray = DnsRecord->Data.TXT.pStringArray; + + for( Index = 1; Index <= Count; Index++ ) + { + wprintf(L"\tString[%d] = %s\n", Index,*StringArray); + StringArray++; + } + +} +VOID +MxRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tPreference = %d\n" + L"\tExchange = %s\n", + DnsRecord->Data.MX.wPreference, + DnsRecord->Data.MX.pNameExchange); +} + +VOID +AaaaRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + IN6_ADDR Ipv6address; + WCHAR Ipv6String[MAX_ADDRESS_STRING_LENGTH] = L"\0"; + + CopyMemory(&Ipv6address, + &DnsRecord->Data.AAAA.Ip6Address, + sizeof(Ipv6address)); + + RtlIpv6AddressToString(&Ipv6address, Ipv6String); + wprintf(L"\tIP address = %s\n",Ipv6String); +} + +VOID +SrvRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tPriority = %d\n" + L"\tWeight = %d\n" + L"\tPort = %d\n" + L"\tTarget Host = %s\n", + DnsRecord->Data.SRV.wPriority, + DnsRecord->Data.SRV.wWeight, + DnsRecord->Data.SRV.wPort, + DnsRecord->Data.SRV.pNameTarget); +} + +VOID +SigRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + + wprintf(L"\tType Covered = %d\n" + L"\tAlgorithm = %d\n" + L"\tLabels = %d\n" + L"\tOriginal TTL = %d\n" + L"\tSignature Expiration = %d\n" + L"\tSignature Inception = %d\n" + L"\tKey Tag = %d\n" + L"\tSigner's Name = %s\n", + DnsRecord->Data.SIG.wTypeCovered, + DnsRecord->Data.SIG.chAlgorithm, + DnsRecord->Data.SIG.chLabelCount, + DnsRecord->Data.SIG.dwOriginalTtl, + DnsRecord->Data.SIG.dwExpiration, + DnsRecord->Data.SIG.dwTimeSigned, + DnsRecord->Data.SIG.wKeyTag, + DnsRecord->Data.SIG.pNameSigner); +} + + +VOID +KeyRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tFlags = 0x%04x\n" + L"\tProtocol = %d\n" + L"\tAlgorithm = %d\n", + DnsRecord->Data.KEY.wFlags, + DnsRecord->Data.KEY.chProtocol, + DnsRecord->Data.KEY.chAlgorithm); + +} + +VOID +DsRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tKey Tag = %d\n" + L"\tAlgorithm = %d\n" + L"\tDigest Type = %d\n", + DnsRecord->Data.DS.wKeyTag, + DnsRecord->Data.DS.chAlgorithm, + DnsRecord->Data.DS.chDigestType); +} + +VOID +NsecRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tNext Domain Name = %s\n", + DnsRecord->Data.NSEC.pNextDomainName); + +} + +VOID +Nsec3RecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tHashAlgorithm = %d\n" + L"\tFlags = 0x%02x\n" + L"\tIterations = %d\n", + DnsRecord->Data.NSEC3.chAlgorithm, + DnsRecord->Data.NSEC3.bFlags, + DnsRecord->Data.NSEC3.wIterations); +} + +VOID +Nsec3ParamRecordPrint( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L"\tHashAlgorithm = %d\n" + L"\tFlags = 0x%02x\n" + L"\tIterations = %d\n", + DnsRecord->Data.NSEC3PARAM.chAlgorithm, + DnsRecord->Data.NSEC3PARAM.bFlags, + DnsRecord->Data.NSEC3PARAM.wIterations); +} + +typedef VOID (* PRINT_DNS_RECORD_DATA_FUNCTION)( + PDNS_RECORD DnsRecord + ); + +// +// This sample prints record data for most commonly used DNS TYPES. +// + +PRINT_DNS_RECORD_DATA_FUNCTION PrintDataTable[] = +{ + NULL, // ZERO + ARecordPrint, // A + PtrRecordPrint, // NS + PtrRecordPrint, // MD + PtrRecordPrint, // MF + PtrRecordPrint, // CNAME + SoaRecordPrint, // SOA + PtrRecordPrint, // MB + PtrRecordPrint, // MG + PtrRecordPrint, // MR + NULL, // NULL + NULL, // WKS + PtrRecordPrint, // PTR + TxtRecordPrint, // HINFO + NULL, // MINFO + MxRecordPrint, // MX + TxtRecordPrint, // TXT + NULL, // RP + MxRecordPrint, // AFSDB + TxtRecordPrint, // X25 + TxtRecordPrint, // ISDN + MxRecordPrint, // RT + NULL, // NSAP + NULL, // NSAPPTR + SigRecordPrint, // SIG + KeyRecordPrint, // KEY + NULL, // PX + NULL, // GPOS + AaaaRecordPrint, // AAAA + NULL, // LOC + NULL, // NXT + NULL, // EID + NULL, // NIMLOC + SrvRecordPrint, // SRV + NULL, // ATMA + NULL, // NAPTR + NULL, // KX + NULL, // CERT + NULL, // A6 + NULL, // DNAME + NULL, // SINK + NULL, // OPT + NULL, // 42 + DsRecordPrint, // DS + NULL, // 44 + NULL, // 45 + SigRecordPrint, // RRSIG + NsecRecordPrint, // NSEC + KeyRecordPrint, // DNSKEY + NULL, // DHCID + Nsec3RecordPrint, // NSEC3 + Nsec3ParamRecordPrint // NSEC3PARAM +}; + +VOID +PrintRecord( + PDNS_RECORD DnsRecord + ) +{ + wprintf(L" Record:\n" + L"\tPtr = %p, pNext = %p\n" + L"\tOwner = %s\n" + L"\tType = %d\n" + L"\tFlags = %08x\n" + L"\t\tSection = %d\n" + L"\t\tDelete = %d\n" + L"\t\tCharSet = %d\n" + L"\tTTL = %d\n" + L"\tReserved = %d\n" + L"\tDataLength = %d\n", + DnsRecord, + DnsRecord->pNext, + DnsRecord->pName, + DnsRecord->wType, + DnsRecord->Flags.DW, + DnsRecord->Flags.S.Section, + DnsRecord->Flags.S.Delete, + DnsRecord->Flags.S.CharSet, + DnsRecord->dwTtl, + DnsRecord->dwReserved, + DnsRecord->wDataLength ); + + if (DnsRecord->wType < ARRAYSIZE(PrintDataTable) && + PrintDataTable[DnsRecord->wType] != NULL) + { + PrintDataTable[DnsRecord->wType](DnsRecord); + } +} + +VOID +PrintDnsRecordList( + PDNS_RECORD DnsRecord + ) +{ + while(DnsRecord) + { + PrintRecord(DnsRecord); + DnsRecord = DnsRecord->pNext; + } +} + diff --git a/Samples/DPIAwarenessPerMonitor/README.md b/Samples/DPIAwarenessPerMonitor/README.md new file mode 100644 index 00000000..5bca7b36 --- /dev/null +++ b/Samples/DPIAwarenessPerMonitor/README.md @@ -0,0 +1,30 @@ +DPI Tutorial sample +=================== + +This sample uses DPI Awareness APIs to show how to implement basic application functionality for a per-monitor DPI aware application. This includes operations like scaling a window, selecting new fonts, and re-rendering the window's content when the window moves to a monitor with a different DPI. + +**Warning** This sample requires Microsoft Visual Studio Ultimate 2013 and doesn't compile in Microsoft Visual Studio Express 2013 for Windows. + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**. +2. Go to the directory named for the sample, and double-click the Visual Studio Solution (.sln) file. +3. Press F7 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To debug the app and then run it, press F5 or use **Debug** \> **Start Debugging**. To run the app without debugging, press Ctrl+F5 or use **Debug** \> **Start Without Debugging**. + diff --git a/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.cpp b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.cpp new file mode 100644 index 00000000..5294ed85 --- /dev/null +++ b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.cpp @@ -0,0 +1,471 @@ +// 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. + +// DPITutorial.cpp : Defines the entry point for the application. + +#include "stdafx.h" +#include "DPITutorial.h" + +// Global Variables +CDPI g_Dpi; // Helper class for scaling +TCHAR g_szTitle[MAX_LOADSTRING]; +TCHAR g_szWindowClass[MAX_LOADSTRING]; +wchar_t g_pszString[MAX_LOADSTRING]; +bool g_bRescaleOnDpiChanged = true; +UINT g_nFontHeight = BUTTON_FONT_HEIGHT; +HBITMAP g_hBmp[4]; +HFONT g_hButtonFont, g_hTextFont; + +// +// WinMain - Checks for S or P in command line, and sets the DPI awareness as specified +// +extern int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + MSG msg; + HACCEL hAccelTable; + + // Read command line and set awareness level if specified: + // default = DPI unaware (0) + // cmd line + S = System DPI aware (1) + // cmd line + P = Per-monitor DPI aware (2) + // + // To provide a command-line parameter from within Visual Studio, press Alt+F7 to open the project Property Pages dialog + // then select the Debugging option in the left pane and add the argument to the Command Arguments field. + + if (FindStringOrdinal(FIND_FROMSTART, lpCmdLine, -1, (LPCTSTR) L"p", -1, TRUE) >= 0) + { + g_Dpi.SetAwareness(PROCESS_PER_MONITOR_DPI_AWARE); + } + else if (FindStringOrdinal(FIND_FROMSTART, lpCmdLine, -1, (LPCTSTR) L"s", -1, TRUE) >= 0) + { + g_Dpi.SetAwareness(PROCESS_SYSTEM_DPI_AWARE); + } + + // Initialize global strings + wsprintf(g_szTitle, L"DPI Awareness Tutorial"); + wsprintf(g_szWindowClass, L"DPITUTORIAL"); + + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance(hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DPITUTORIAL)); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int) msg.wParam; +} + +// +// MyRegisterClass - registers the window class +// +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DPITUTORIAL)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH) GetStockObject(COLOR_WINDOW + 1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DPITUTORIAL); + wcex.lpszClassName = g_szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassEx(&wcex); +} + +// +// InitInstance: +// Initializes the DPI +// Creates the main window +// Loads the bitmap resources +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd, hWndButton; + HMONITOR hMonitor; + POINT pt; + UINT dpix = 0, dpiy = 0; + HRESULT hr = E_FAIL; + + // Get the DPI for the main monitor, and set the scaling factor + pt.x = 1; + pt.y = 1; + hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + hr = GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + + if (hr != S_OK) + { + MessageBox(NULL, (LPCWSTR) L"GetDpiForMonitor failed", (LPCWSTR) L"Notification", MB_OK); + return FALSE; + } + g_Dpi.SetScale(dpix); + + // Create main window and pushbutton window + hWnd = CreateWindow(g_szWindowClass, g_szTitle, WS_OVERLAPPEDWINDOW, g_Dpi.Scale(100), g_Dpi.Scale(100), + g_Dpi.Scale(WINDOW_WIDTH), g_Dpi.Scale(WINDOW_HEIGHT), NULL, NULL, hInstance, NULL); + + if (!hWnd) + { + return FALSE; + } + + hWndButton = CreateWindow(L"BUTTON", L"&Rescale", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 0, 0, 0, hWnd, (HMENU) IDM_RESCALE_NOW, hInstance, NULL); + + // Load bitmaps for each scaling factor + g_hBmp[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP100)); + g_hBmp[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP125)); + g_hBmp[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP150)); + g_hBmp[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP200)); + + // Create fonts for button and window text output + CreateFonts(hWnd); + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + return TRUE; +} + +// +// CreateScaledFont - Create a font close to the specified height +// +HFONT CreateScaledFont(int g_nFontHeight) +{ + LOGFONT lf; + HFONT hFont; + + memset(&lf, 0, sizeof(lf)); + lf.lfQuality = CLEARTYPE_QUALITY; + lf.lfHeight = -g_nFontHeight; + hFont = CreateFontIndirect(&lf); + return (hFont); +} + +// +// CreateFonts creates fonts for button and window text output, appropriate for the DPI +// +void CreateFonts(HWND hWnd) +{ + if (g_hButtonFont != NULL) + { + DeleteObject(g_hButtonFont); + g_hButtonFont = NULL; + } + + g_hButtonFont = CreateScaledFont(g_Dpi.Scale(BUTTON_FONT_HEIGHT)); + if (g_hButtonFont == NULL) + { + MessageBox(hWnd, (LPCWSTR) L"Failed to create scaled font for button", (LPCWSTR) L"Notification", MB_OK); + } + + if (g_hTextFont != NULL) + { + DeleteObject(g_hTextFont); + g_hTextFont = NULL; + } + + g_hTextFont = CreateScaledFont(g_Dpi.Scale(g_nFontHeight)); + if (g_hTextFont == NULL) + { + MessageBox(hWnd, (LPCWSTR) L"Failed to create scaled font for text", (LPCWSTR) L"Notification", MB_OK); + } + + return; +} + +// +// RenderWindow - Draw the elements of the window: background color, rectangle (frame for bitmap), +// bitmap (selected from resources based on DPI), and text (using a font based on the DPI) +// The GetAwareness return value is used as an index into the string & color arrays +// +void RenderWindow(HWND hWnd) +{ + HDC hdc, hdcMem; + HBRUSH hBrush; + PAINTSTRUCT ps; + RECT rcText, rcWin, rcClient; + POINT ptOffset; + LPCWSTR awareText[3] = { L"DPI Unaware", L"System DPI Aware", L"Per-Monitor DPI Aware" }; + COLORREF colors[3] = { RGB(220, 120, 120), RGB(250, 250, 210), RGB(150, 250, 150) }; + BITMAP bmp; + HBITMAP hbmpTemp, hbmpScaled; + HWND hWndButton; + UINT nPad; + + GetWindowRect(hWnd, &rcWin); + GetClientRect(hWnd, &rcClient); + nPad = g_Dpi.Scale(PADDING); + + hdc = BeginPaint(hWnd, &ps); + SetBkMode(hdc, TRANSPARENT); + + // Render client area background + hBrush = CreateSolidBrush(colors[g_Dpi.GetAwareness()]); + FillRect(hdc, &rcClient, hBrush); + + // Select the appropriate bitmap for the scaling factor and load it into memory + if (g_Dpi.GetAwareness() == PROCESS_DPI_UNAWARE) + { + hbmpScaled = g_hBmp[0]; + } + else + { + switch (g_Dpi.GetScale()) + { + case 125: + hbmpScaled = g_hBmp[1]; + break; + + case 150: + hbmpScaled = g_hBmp[2]; + break; + + case 200: + hbmpScaled = g_hBmp[3]; + break; + + default: + hbmpScaled = g_hBmp[0]; + break; + } + } + hdcMem = CreateCompatibleDC(NULL); + hbmpTemp = SelectBitmap(hdcMem, hbmpScaled); + GetObject(hbmpScaled, sizeof(bmp), &bmp); + + // Render a rectangle to frame the bitmap in the lower-right of the window + ptOffset.x = rcClient.right - bmp.bmWidth - nPad; + ptOffset.y = rcClient.bottom - bmp.bmHeight - nPad; + Rectangle(hdc, ptOffset.x - nPad / 2, ptOffset.y - nPad / 2, rcClient.right - nPad / 2, rcClient.bottom - nPad / 2); + + // Render bitmap + BitBlt(hdc, ptOffset.x, ptOffset.y, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY); + SelectBitmap(hdcMem, hbmpTemp); + DeleteDC(hdcMem); + + // Render button + SelectObject(hdc, g_hButtonFont); + hWndButton = GetWindow(hWnd, GW_CHILD); + SetWindowPos(hWndButton, HWND_TOP, rcClient.left + nPad, rcClient.bottom - g_Dpi.Scale(BUTTON_HEIGHT) - nPad, + g_Dpi.Scale(BUTTON_WIDTH), g_Dpi.Scale(BUTTON_HEIGHT), SWP_SHOWWINDOW); + SendMessage(hWndButton, WM_SETFONT, (WPARAM) g_hButtonFont, TRUE); + UpdateWindow(hWndButton); + EnableWindow(hWndButton, ((g_Dpi.GetAwareness() == PROCESS_PER_MONITOR_DPI_AWARE) && (g_bRescaleOnDpiChanged == false)) ? TRUE : FALSE); + + // Render Text + SelectObject(hdc, g_hTextFont); + + rcText.left = rcClient.left + nPad; + rcText.top = rcClient.top + nPad; + wsprintf(g_pszString, L"%s Window", awareText[g_Dpi.GetAwareness()]); + DrawText(hdc, g_pszString, -1, &rcText, DT_CALCRECT | DT_LEFT | DT_TOP); + DrawText(hdc, g_pszString, -1, &rcText, DT_LEFT | DT_TOP); + + rcText.top = rcText.bottom + nPad; + wsprintf(g_pszString, L"Scaling: %i%%", g_Dpi.GetScale()); + DrawText(hdc, g_pszString, -1, &rcText, DT_CALCRECT | DT_LEFT | DT_TOP); + DrawText(hdc, g_pszString, -1, &rcText, DT_LEFT | DT_TOP); + + rcText.top = rcText.bottom + nPad; + wsprintf(g_pszString, L"Position: (%i, %i) to (%i, %i)", rcWin.left, rcWin.top, rcWin.right, rcWin.bottom); + DrawText(hdc, g_pszString, -1, &rcText, DT_CALCRECT | DT_LEFT | DT_TOP); + DrawText(hdc, g_pszString, -1, &rcText, DT_LEFT | DT_TOP); + + rcText.top = rcText.bottom + nPad; + wsprintf(g_pszString, L"Size: %i x %i", RectWidth(rcWin), RectHeight(rcWin)); + DrawText(hdc, g_pszString, -1, &rcText, DT_CALCRECT | DT_LEFT | DT_TOP); + DrawText(hdc, g_pszString, -1, &rcText, DT_LEFT | DT_TOP); + + rcText.top = rcText.bottom + nPad; + wsprintf(g_pszString, L"Font height: %i (%i unscaled)", g_Dpi.Scale(g_nFontHeight), g_nFontHeight); + DrawText(hdc, g_pszString, -1, &rcText, DT_CALCRECT | DT_LEFT | DT_TOP); + DrawText(hdc, g_pszString, -1, &rcText, DT_LEFT | DT_TOP); + + // Cleanup + EndPaint(hWnd, &ps); + DeleteObject(hBrush); + DeleteDC(hdc); + return; +} + +// +// WndProc: Message handler +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT lRet = 0; + HWND hWndButton; + HMENU hMenu; + MENUITEMINFO mii; + LPRECT lprcNewScale; + static RECT rcNewScale; + + switch (message) + { + case WM_CREATE: + // Initialize window rect + GetWindowRect(hWnd, &rcNewScale); + + // Initialize menu bar + hMenu = GetMenu(hWnd); + + // Set the default (selected) state of the menu item + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + mii.fState = (g_bRescaleOnDpiChanged == true) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(hMenu, IDM_RESCALE_ON_DPICHANGED, FALSE, &mii); + + // Disable the "Rescale on DPICHANGED" menu item unless the app is DPI Aware + if (g_Dpi.GetAwareness() == PROCESS_PER_MONITOR_DPI_AWARE) + { + break; + } + + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + mii.fState = MFS_DISABLED; + SetMenuItemInfo(hMenu, IDM_RESCALE_ON_DPICHANGED, FALSE, &mii); + break; + + case WM_DPICHANGED: + // This message tells the program that most of its window is on a monitor with a new DPI. + // The wParam contains the new DPI, and the lParam contains a rect which defines the window + // rectangle scaled to the new DPI. + + g_Dpi.SetScale(LOWORD(wParam)); // Set the new DPI, retrieved from the wParam + + if (g_Dpi.GetAwareness() != PROCESS_PER_MONITOR_DPI_AWARE) + { + break; + } + + lprcNewScale = (LPRECT) lParam; // Get the window rectangle scaled for the new DPI, retrieved from the lParam + CopyRect(&rcNewScale, lprcNewScale); // Save the rectangle for the on-demand rescale option (IDM_RESCALE_NOW) + + if (g_bRescaleOnDpiChanged) + { + // For the new DPI: resize the window, select new fonts, and re-render window content + SetWindowPos(hWnd, + HWND_TOP, + lprcNewScale->left, + lprcNewScale->top, + RectWidth(*lprcNewScale), + RectHeight(*lprcNewScale), + SWP_NOZORDER | SWP_NOACTIVATE); + CreateFonts(hWnd); + RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + } + break; + + case WM_PAINT: + RenderWindow(hWnd); + break; + + case WM_EXITSIZEMOVE: + if (g_bRescaleOnDpiChanged) + { + // Refresh the window to display its new position + RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + } + break; + + case WM_COMMAND: + // Respond to user input from the keyboard or menu options + + switch (LOWORD(wParam)) + { + case IDM_RESCALE_NOW: // The "Rescale" pushbutton was clicked + if (!g_bRescaleOnDpiChanged) + { + // For the new DPI: resize the window, select new fonts, and re-render window content + SetWindowPos(hWnd, + HWND_TOP, + 0, // Position origin ignored (per SWP_NOMOVE) + 0, // Position origin ignored (per SWP_NOMOVE) + RectWidth(rcNewScale), + RectHeight(rcNewScale), + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + CreateFonts(hWnd); + RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + SetFocus(hWnd); // Return focus from pushbutton to main window + } + break; + + case IDM_RESCALE_ON_DPICHANGED: // The "Rescale on DPICHANGED" menu item was selected + g_bRescaleOnDpiChanged = !g_bRescaleOnDpiChanged; + + hMenu = GetMenu(hWnd); // Toggle the selected/unselected state of the menu item + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + mii.fState = (g_bRescaleOnDpiChanged) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(hMenu, IDM_RESCALE_ON_DPICHANGED, FALSE, &mii); + + hWndButton = GetWindow(hWnd, GW_CHILD); // Toggle the enabled/disabled state of the pushbutton + EnableWindow(hWndButton, (g_bRescaleOnDpiChanged == false) ? TRUE : FALSE); + RenderWindow(hWnd); + break; + + case IDM_FONT_INCREASE: + g_nFontHeight += 5; + if (g_nFontHeight > WINDOW_HEIGHT / 5) + { + g_nFontHeight = WINDOW_HEIGHT / 5; + } + CreateFonts(hWnd); + RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + break; + + case IDM_FONT_DECREASE: + g_nFontHeight -= 5; + if (g_nFontHeight < 10) + { + g_nFontHeight = 10; + } + CreateFonts(hWnd); + RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + break; + + case IDM_EXIT: + DestroyWindow(hWnd); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + + case WM_DESTROY: + DeleteObject(g_hButtonFont); + DeleteObject(g_hTextFont); + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return lRet; +} \ No newline at end of file diff --git a/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.h b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.h new file mode 100644 index 00000000..a1521792 --- /dev/null +++ b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.h @@ -0,0 +1,145 @@ +// 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 "resource.h" + +// DPI Helper Class - functions to manage the state of DPI awareness, and scale values used for window size and rendering. +// +// Scale, GetScale, SetScale +// GetAwareness, SetAwareness +// SetDPIChanged, GetDPIChanged + +// Constants for UI size +#define MAX_LOADSTRING 100 +#define PADDING 10 +#define WINDOW_HEIGHT 400 // Default size of window for a standard display (96 DPI, 100% scaling) +#define WINDOW_WIDTH 600 +#define BUTTON_HEIGHT (WINDOW_HEIGHT / 8) +#define BUTTON_WIDTH (WINDOW_WIDTH / 5) +#define BUTTON_FONT_HEIGHT (BUTTON_HEIGHT / 2) + +// Forward declarations +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +HFONT CreateScaledFont(int g_nFontHeight); +void CreateFonts(HWND hWnd); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); + +// Rectangle helper functions +int RectHeight(RECT Rect) +{ + return Rect.bottom - Rect.top; +} + +int RectWidth(RECT Rect) +{ + return Rect.right - Rect.left; +} + +class CDPI +{ +public: + CDPI() + { + m_nScaleFactor = 0; + m_nScaleFactorSDA = 0; + m_Awareness = PROCESS_DPI_UNAWARE; + } + + int Scale(int x) + { + // DPI Unaware: Return the input value with no scaling. + // These apps are always virtualized to 96 DPI and scaled by the system for the DPI of the monitor where shown. + if (m_Awareness == PROCESS_DPI_UNAWARE) + { + return x; + } + + // System DPI Aware: Return the input value scaled by the factor determined by the system DPI when the app was launched. + // These apps render themselves according to the DPI of the display where they are launched, and they expect that scaling + // to remain constant for all displays on the system. + // These apps are scaled up or down when moved to a display with a different DPI from the system DPI. + if (m_Awareness == PROCESS_SYSTEM_DPI_AWARE) + { + return MulDiv(x, m_nScaleFactorSDA, 100); + } + + // Per-Monitor DPI Aware: Return the input value scaled by the factor for the display which contains most of the window. + // These apps render themselves for any DPI, and re-render when the DPI changes (as indicated by the WM_DPICHANGED window message). + return MulDiv(x, m_nScaleFactor, 100); + } + + UINT GetScale() + { + if (m_Awareness == PROCESS_DPI_UNAWARE) + { + return 100; + } + + if (m_Awareness == PROCESS_SYSTEM_DPI_AWARE) + { + return m_nScaleFactorSDA; + } + + return m_nScaleFactor; + } + + void SetScale(__in UINT iDPI) + { + m_nScaleFactor = MulDiv(iDPI, 100, 96); + if (m_nScaleFactorSDA == 0) + { + m_nScaleFactorSDA = m_nScaleFactor; // Save the first scale factor, which is all that SDA apps know about + } + return; + } + + PROCESS_DPI_AWARENESS GetAwareness() + { + HANDLE hProcess; + hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId()); + GetProcessDpiAwareness(hProcess, &m_Awareness); + return m_Awareness; + } + + void SetAwareness(PROCESS_DPI_AWARENESS awareness) + { + HRESULT hr = E_FAIL; + hr = SetProcessDpiAwareness(awareness); + if (hr == S_OK) + { + m_Awareness = awareness; + } + else + { + MessageBox(NULL, (LPCWSTR) L"SetProcessDpiAwareness Error", (LPCWSTR) L"Error", MB_OK); + } + return; + } + + // Scale rectangle from raw pixels to relative pixels. + void ScaleRect(__inout RECT *pRect) + { + pRect->left = Scale(pRect->left); + pRect->right = Scale(pRect->right); + pRect->top = Scale(pRect->top); + pRect->bottom = Scale(pRect->bottom); + } + + // Scale Point from raw pixels to relative pixels. + void ScalePoint(__inout POINT *pPoint) + { + pPoint->x = Scale(pPoint->x); + pPoint->y = Scale(pPoint->y); + } + +private: + UINT m_nScaleFactor; + UINT m_nScaleFactorSDA; + PROCESS_DPI_AWARENESS m_Awareness; +}; \ No newline at end of file diff --git a/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.ico b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.ico new file mode 100644 index 0000000000000000000000000000000000000000..449296f495af26f2b41bb1626a28de7432145472 GIT binary patch literal 2998 zcmeHJIc@?$5G;1VEan=&z(kgxVUhCya&kft2^&G^5AXoz*K%ZEh6^mKRC)SN;9Ie2I^4EsEuJm3ak4(0(K0-)vtx2mz-v5Du5+`|?E{2~nF zj-DY~i1~a@z`8H2Rm8@RN^*7j%+?3;*Is5r;m32z^?Gs%|GV@5y&h|~@doa#jn6yX zPm+(*yf56oD($=C(DJ(6=%K6Llfe5Uo;dPV7%T5PITm!!YhANqXLaS`0ufOBi8crP zkWX22ZGmf>3$1+|+x>UW$1lsro%1<*HCnUTM61<8yWK{o(?Pe}#b7YNXf(oPGQo5@ z#cVdiVzIz-xkMC2Sglrgd0u0)*q_P14fKAcHBIgSup6(l)H0Rx6BS&0GPpi7+=`R!@G zv#W6^k(8yV1_**&a=ANmcIV9O?Ed$4$9C+GHZTr;Ld2iaG{Yg!S=aE&ZIpp2-3q$!XN9Sc? z2h7X-91obK8@posV`fM5&}Gygcs3Yyjd5x|_Nm|Hp0`NW1_Lx`{s*+q&ZuO*WA@%6 zv0iAmF&r2MMvU!mWDT*kTW%wap^w!D)BaJLterJ!0|bmhp!uN7hN~ml+T1+Y=b^8g50;>cE3ze5?i+PO;A+*A~6L za3zI3yU1w6Aw|Na7b;F+GEOtz}8pxD^i|^zwQA()^e4O&dUV8_F&$1z%H!% zll_~(&5Pi*2~kf>RkT!u72gv)M-g@syyBL(vk*fSR~7Sy)3#%JCc&o^ljYwDEpNFl zY1QL>Oer);_)g=B@!*O!^1cx*BJL62LZWCRJh8XXDB_RopXuK#${0a3I-za^CbTFO zhr2MO&HEnANVpnsMX^}#6uNu%v zUJHKx#wA(lT77FQ9q@{+b)HppD~bxaRxxSODi{%|ynfZo2!_W`|{ zp||t9g~zn;rB-0xCSS^(qDPOWeDk*X68x|0lW*>WI&!%IcI9N}FnYu@A;Qbw<@X)* z{2S_?kmGHkEy~i!ju_eN;LTm$Vy+R_mk!c3CfDm_zWzG$m(l-hp?+mJH9S@M-YWXl zwiSGQZyK$ZN8Sec_ekJTa+A4HT&vj|rsqRMHQN3EgRp3CA{XC(W! zX`iw6_#UU*thjUzDAyFD(m1uU$L#R?oBq2Gm9KPkUMlzPah-=KANMpjc!~d4srw-x z--8Frk7VUGGUJLEcOLoPTA^JfpuU_l4oOzc7KDFcC6)#K8`3IT~t@Jmru8QzOYqMjLDt@e6ka=xtMj&&alo6^3N26 zqew%v%kpOlCq$I3oL}bD$vwb5r(C6@^HQ1g7+#78AH(dPv0v2w z(Oan0t@BImn3Xr`q$KV-^(W8I9?Cw7ciCw#lavl?v*x`;sguL*{ccyb@x8iY{9W+8 zcn&!t|5a?5Fgj&N7hzYN7emt4_A!^sW{$=!v1 + + + + Debug + Win32 + + + Release + Win32 + + + + {CCC90AC6-B0BE-4A9D-BCEB-AD15DBA1FB23} + Win32Proj + DPITutorial + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + shcore.lib;%(AdditionalDependencies) + "type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'" + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + shcore.lib;%(AdditionalDependencies) + true + true + "type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'" + + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.vcxproj.filters b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.vcxproj.filters new file mode 100644 index 00000000..272e64c5 --- /dev/null +++ b/Samples/DPIAwarenessPerMonitor/cpp/DPITutorial.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;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 + + + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/Samples/DPIAwarenessPerMonitor/cpp/Resource.h b/Samples/DPIAwarenessPerMonitor/cpp/Resource.h new file mode 100644 index 00000000..56cc0a4e --- /dev/null +++ b/Samples/DPIAwarenessPerMonitor/cpp/Resource.h @@ -0,0 +1,41 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DPITUTORIAL.rc +// + +#define IDR_MAINFRAME 100 +#define IDS_APP_TITLE 101 +#define IDD_DPITUTORIAL_DIALOG 102 + +#define IDI_DPITUTORIAL 104 +#define IDI_SMALL 105 +#define IDC_DPITUTORIAL 106 + +#define IDM_RESCALE_NOW 111 +#define IDM_RESCALE_ON_DPICHANGED 112 +#define IDM_FONT_INCREASE 113 +#define IDM_FONT_DECREASE 114 +#define IDM_EXIT 115 + +#define IDB_BITMAP100 121 +#define IDB_BITMAP125 122 +#define IDB_BITMAP150 123 +#define IDB_BITMAP200 124 + +#define IDC_MYICON 2 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/Samples/DPIAwarenessPerMonitor/cpp/scaled100.bmp b/Samples/DPIAwarenessPerMonitor/cpp/scaled100.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f3c3c6e4579e9e0b3f850f15289a11be66861b9d GIT binary patch literal 90054 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 literal 0 HcmV?d00001 diff --git a/Samples/DPIAwarenessPerMonitor/cpp/scaled125.bmp b/Samples/DPIAwarenessPerMonitor/cpp/scaled125.bmp new file mode 100644 index 0000000000000000000000000000000000000000..edda2830573b00453eb51389343526a5c3fc2490 GIT binary patch literal 141430 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 zutkjHhcg(6+uc!MbC^Y+p6%-vT}aovW_hO& zy?QpoXxMZ7zrt_%p;yo06>Y-Tk#`F9e$QD9?Ok6(uVDBr1}S$wwxl`Ite(F!?+LX& zwx>;J{@*cposU<1f=^%o24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS z00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS z00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS L00v-S9|QjnrQ#B3 literal 0 HcmV?d00001 diff --git a/Samples/DPIAwarenessPerMonitor/cpp/small.ico b/Samples/DPIAwarenessPerMonitor/cpp/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..449296f495af26f2b41bb1626a28de7432145472 GIT binary patch literal 2998 zcmeHJIc@?$5G;1VEan=&z(kgxVUhCya&kft2^&G^5AXoz*K%ZEh6^mKRC)SN;9Ie2I^4EsEuJm3ak4(0(K0-)vtx2mz-v5Du5+`|?E{2~nF zj-DY~i1~a@z`8H2Rm8@RN^*7j%+?3;*Is5r;m32z^?Gs%|GV@5y&h|~@doa#jn6yX zPm+(*yf56oD($=C(DJ(6=%K6Llfe5Uo;dPV7%T5PITm!!YhANqXLaS`0ufOBi8crP zkWX22ZGmf>3$1+|+x>UW$1lsro%1<*HCnUTM61<8yWK{o(?Pe}#b7YNXf(oPGQo5@ z#cVdiVzIz-xkMC2Sglrgd0u0)* +#include + +// C RunTime Header Files +#include +#include +#include +#include + +// Specific header required by the program +#include diff --git a/Samples/DPIAwarenessPerMonitor/cpp/targetver.h b/Samples/DPIAwarenessPerMonitor/cpp/targetver.h new file mode 100644 index 00000000..87c0086d --- /dev/null +++ b/Samples/DPIAwarenessPerMonitor/cpp/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/Samples/DX11VideoRenderer/README.md b/Samples/DX11VideoRenderer/README.md new file mode 100644 index 00000000..7aa1b472 --- /dev/null +++ b/Samples/DX11VideoRenderer/README.md @@ -0,0 +1,56 @@ +DirectX video rendering sample +============================== + +This sample shows how to create a media sink that renders video output to a window using DirectX 11. + +Specifically, this sample shows how to: + +- Decode the video using the Media Foundation APIs +- Render the decoded video using the DirectX 11 APIs +- Output the video stream to multi-monitor displays + +For more info about the concepts and APIs demonstrated in this sample, see the following topics: + +- [Direct3D 11 graphics APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/ff476080) +- [Media Foundation media APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197) +- [DirectX Graphics Interface (DXGI) APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/bb205169) + +**Note** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU) and will not build in Microsoft Visual Studio Express 2013 for Windows . + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related technologies +-------------------- + +[Media Foundation](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample: + +1. Open the solutions (.sln) file titled DX11VideoRenderer.sln from Visual Studio. You'll find the solutions file in \<*install\_root*\>\\DX11VideoRenderer\\C++. +2. After the sample has loaded, press the F7 (or F6 for Visual Studio 2013) key or select **Build Solution** from the **Build** menu. + +Run the sample +-------------- + +To run this sample after building it, go to the installation folder for this sample with Windows Explorer and run DX11VideoRenderer.exe from the *\*\\DX11VideoRenderer\\C++\\Debug folder. + +To run this sample from Microsoft Visual Studio, press the F5 key to run with debugging enabled, or Ctrl+F5 to run without debugging enabled. Alternatively, select **Start Debugging** or **Start Without Debugging** from the **Debug** menu. + diff --git a/Samples/DX11VideoRenderer/cpp/Activate.cpp b/Samples/DX11VideoRenderer/cpp/Activate.cpp new file mode 100644 index 00000000..ac706327 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Activate.cpp @@ -0,0 +1,213 @@ +#include "Activate.h" + +HRESULT DX11VideoRenderer::CActivate::CreateInstance(HWND hwnd, IMFActivate** ppActivate) +{ + if (ppActivate == NULL) + { + return E_POINTER; + } + + CActivate* pActivate = new CActivate(); + if (pActivate == NULL) + { + return E_OUTOFMEMORY; + } + + pActivate->AddRef(); + + HRESULT hr = S_OK; + + do + { + hr = pActivate->Initialize(); + if (FAILED(hr)) + { + break; + } + + hr = pActivate->QueryInterface(IID_PPV_ARGS(ppActivate)); + if (FAILED(hr)) + { + break; + } + + pActivate->m_hwnd = hwnd; + } + while (FALSE); + + SafeRelease(pActivate); + + return hr; +} + +// IUnknown +ULONG DX11VideoRenderer::CActivate::AddRef(void) +{ + return InterlockedIncrement(&m_lRefCount); +} + +// IUnknown +HRESULT DX11VideoRenderer::CActivate::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(static_cast(this)); + } + else if (iid == __uuidof(IMFActivate)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IPersistStream)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IPersist)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFAttributes)) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +// IUnknown +ULONG DX11VideoRenderer::CActivate::Release(void) +{ + ULONG lRefCount = InterlockedDecrement(&m_lRefCount); + if (lRefCount == 0) + { + delete this; + } + return lRefCount; +} + +// IMFActivate +HRESULT DX11VideoRenderer::CActivate::ActivateObject(__RPC__in REFIID riid, __RPC__deref_out_opt void** ppvObject) +{ + HRESULT hr = S_OK; + IMFGetService* pSinkGetService = NULL; + IMFVideoDisplayControl* pSinkVideoDisplayControl = NULL; + + do + { + if (m_pMediaSink == NULL) + { + hr = CMediaSink::CreateInstance(IID_PPV_ARGS(&m_pMediaSink)); + if (FAILED(hr)) + { + break; + } + + hr = m_pMediaSink->QueryInterface(IID_PPV_ARGS(&pSinkGetService)); + if (FAILED(hr)) + { + break; + } + + hr = pSinkGetService->GetService(MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pSinkVideoDisplayControl)); + if (FAILED(hr)) + { + break; + } + + hr = pSinkVideoDisplayControl->SetVideoWindow(m_hwnd); + if (FAILED(hr)) + { + break; + } + } + + hr = m_pMediaSink->QueryInterface(riid, ppvObject); + if (FAILED(hr)) + { + break; + } + } + while (FALSE); + + SafeRelease(pSinkGetService); + SafeRelease(pSinkVideoDisplayControl); + + return hr; +} + +// IMFActivate +HRESULT DX11VideoRenderer::CActivate::DetachObject(void) +{ + SafeRelease(m_pMediaSink); + + return S_OK; +} + +// IMFActivate +HRESULT DX11VideoRenderer::CActivate::ShutdownObject(void) +{ + if (m_pMediaSink != NULL) + { + m_pMediaSink->Shutdown(); + SafeRelease(m_pMediaSink); + } + + return S_OK; +} + +// IPersistStream +HRESULT DX11VideoRenderer::CActivate::GetSizeMax(__RPC__out ULARGE_INTEGER* pcbSize) +{ + return E_NOTIMPL; +} + +// IPersistStream +HRESULT DX11VideoRenderer::CActivate::IsDirty(void) +{ + return E_NOTIMPL; +} + +// IPersistStream +HRESULT DX11VideoRenderer::CActivate::Load(__RPC__in_opt IStream* pStream) +{ + return E_NOTIMPL; +} + +// IPersistStream +HRESULT DX11VideoRenderer::CActivate::Save(__RPC__in_opt IStream* pStream, BOOL bClearDirty) +{ + return E_NOTIMPL; +} + +// IPersist +HRESULT DX11VideoRenderer::CActivate::GetClassID(__RPC__out CLSID* pClassID) +{ + if (pClassID == NULL) + { + return E_POINTER; + } + *pClassID = CLSID_DX11VideoRendererActivate; + return S_OK; +} + +// ctor +DX11VideoRenderer::CActivate::CActivate(void) : + m_lRefCount(0), + m_pMediaSink(NULL), + m_hwnd(NULL) +{ +} + +// dtor +DX11VideoRenderer::CActivate::~CActivate(void) +{ + SafeRelease(m_pMediaSink); +} diff --git a/Samples/DX11VideoRenderer/cpp/Activate.h b/Samples/DX11VideoRenderer/cpp/Activate.h new file mode 100644 index 00000000..badc1197 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Activate.h @@ -0,0 +1,43 @@ +#pragma once + +#include "Common.h" +#include "MFAttributesImpl.h" +#include "MediaSink.h" + +namespace DX11VideoRenderer +{ + class CActivate : public CMFAttributesImpl, public IPersistStream, private CBase + { + public: + + static HRESULT CreateInstance(HWND hwnd, IMFActivate** ppActivate); + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP QueryInterface(REFIID riid, __RPC__deref_out _Result_nullonfailure_ void** ppvObject); + STDMETHODIMP_(ULONG) Release(void); + + // IMFActivate + STDMETHODIMP ActivateObject(__RPC__in REFIID riid, __RPC__deref_out_opt void** ppvObject); + STDMETHODIMP DetachObject(void); + STDMETHODIMP ShutdownObject(void); + + // IPersistStream + STDMETHODIMP GetSizeMax(__RPC__out ULARGE_INTEGER* pcbSize); + STDMETHODIMP IsDirty(void); + STDMETHODIMP Load(__RPC__in_opt IStream* pStream); + STDMETHODIMP Save(__RPC__in_opt IStream* pStream, BOOL bClearDirty); + + // IPersist (from IPersistStream) + STDMETHODIMP GetClassID(__RPC__out CLSID* pClassID); + + private: + + CActivate(void); + ~CActivate(void); + + long m_lRefCount; + IMFMediaSink* m_pMediaSink; + HWND m_hwnd; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/ClassFactory.cpp b/Samples/DX11VideoRenderer/cpp/ClassFactory.cpp new file mode 100644 index 00000000..64ff278f --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/ClassFactory.cpp @@ -0,0 +1,88 @@ +#include "ClassFactory.h" + +BOOL DX11VideoRenderer::CClassFactory::IsLocked(void) +{ + return (s_lLockCount == 0) ? FALSE : TRUE; +} + +DX11VideoRenderer::CClassFactory::CClassFactory(void) : + m_lRefCount(0) +{ +} + +DX11VideoRenderer::CClassFactory::~CClassFactory(void) +{ +} + +// IUnknown +ULONG DX11VideoRenderer::CClassFactory::AddRef(void) +{ + return InterlockedIncrement(&m_lRefCount); +} + +// IUnknown +HRESULT DX11VideoRenderer::CClassFactory::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(static_cast(this)); + } + else if (iid == __uuidof(IClassFactory)) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +// IUnknown +ULONG DX11VideoRenderer::CClassFactory::Release(void) +{ + ULONG lRefCount = InterlockedDecrement(&m_lRefCount); + if (lRefCount == 0) + { + delete this; + } + return lRefCount; +} + +// IClassFactory +HRESULT DX11VideoRenderer::CClassFactory::CreateInstance(_In_opt_ IUnknown* pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void** ppvObject) +{ + if (ppvObject == NULL) + { + return E_POINTER; + } + + *ppvObject = NULL; + + if (pUnkOuter != NULL) + { + return CLASS_E_NOAGGREGATION; + } + + return CMediaSink::CreateInstance(riid, ppvObject); +} + +// IClassFactory +HRESULT DX11VideoRenderer::CClassFactory::LockServer(BOOL bLock) +{ + if (bLock == FALSE) + { + InterlockedDecrement(&s_lLockCount); + } + else + { + InterlockedIncrement(&s_lLockCount); + } + return S_OK; +} diff --git a/Samples/DX11VideoRenderer/cpp/ClassFactory.h b/Samples/DX11VideoRenderer/cpp/ClassFactory.h new file mode 100644 index 00000000..2b300960 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/ClassFactory.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Common.h" +#include "MediaSink.h" + +namespace DX11VideoRenderer +{ + class CClassFactory : public IClassFactory, private CBase + { + public: + + static BOOL IsLocked(void); + + CClassFactory(void); + ~CClassFactory(void); + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP QueryInterface(REFIID riid, __RPC__deref_out _Result_nullonfailure_ void** ppvObject); + STDMETHODIMP_(ULONG) Release(void); + + // IClassFactory + STDMETHODIMP CreateInstance(_In_opt_ IUnknown* pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void** ppvObject); + STDMETHODIMP LockServer(BOOL bLock); + + private: + + static volatile long s_lLockCount; + + long m_lRefCount; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/Common.h b/Samples/DX11VideoRenderer/cpp/Common.h new file mode 100644 index 00000000..e8f25286 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Common.h @@ -0,0 +1,384 @@ +#pragma once + +#include +#include // for FLT_MAX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for MEDIASUBTYPE_V216 +#include "DX11VideoRenderer.h" +#include "linklist.h" +#include "staticasynccallback.h" + +DEFINE_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82); + +// MF_XVP_PLAYBACK_MODE +// Data type: UINT32 (treat as BOOL) +// If this attribute is TRUE, the XVP will run in playback mode where it will: +// 1) Allow caller to allocate D3D output samples +// 2) Not perform FRC +// 3) Allow last frame regeneration (repaint) +// This attribute should be set on the transform's attrbiute store prior to setting the input type. +DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); + +namespace DX11VideoRenderer +{ + inline void SafeCloseHandle(HANDLE& h) + { + if (h != NULL) + { + CloseHandle(h); + h = NULL; + } + } + + template inline void SafeDelete(T*& pT) + { + delete pT; + pT = NULL; + } + + template inline void SafeDeleteArray(T*& pT) + { + delete[] pT; + pT = NULL; + } + + template inline void SafeRelease(T*& pT) + { + if (pT != NULL) + { + pT->Release(); + pT = NULL; + } + } + + template inline double TicksToMilliseconds(const T& t) + { + return t / 10000.0; + } + + template inline T MillisecondsToTicks(const T& t) + { + return t * 10000; + } + + // returns the greatest common divisor of A and B + inline int gcd(int A, int B) + { + int Temp; + + if (A < B) + { + Temp = A; + A = B; + B = Temp; + } + + while (B != 0) + { + Temp = A % B; + A = B; + B = Temp; + } + + return A; + } + + // Convert a fixed-point to a float. + inline float MFOffsetToFloat(const MFOffset& offset) + { + return (float)offset.value + ((float)offset.value / 65536.0f); + } + + inline RECT MFVideoAreaToRect(const MFVideoArea area) + { + float left = MFOffsetToFloat(area.OffsetX); + float top = MFOffsetToFloat(area.OffsetY); + + RECT rc = + { + int( left + 0.5f ), + int( top + 0.5f ), + int( left + area.Area.cx + 0.5f ), + int( top + area.Area.cy + 0.5f ) + }; + + return rc; + } + + inline MFOffset MakeOffset(float v) + { + MFOffset offset; + offset.value = short(v); + offset.fract = WORD(65536 * (v-offset.value)); + return offset; + } + + inline MFVideoArea MakeArea(float x, float y, DWORD width, DWORD height) + { + MFVideoArea area; + area.OffsetX = MakeOffset(x); + area.OffsetY = MakeOffset(y); + area.Area.cx = width; + area.Area.cy = height; + return area; + } + + class CBase + { + public: + + static long GetObjectCount(void) + { + return s_lObjectCount; + } + + protected: + + CBase(void) + { + InterlockedIncrement(&s_lObjectCount); + } + + ~CBase(void) + { + InterlockedDecrement(&s_lObjectCount); + } + + private: + + static volatile long s_lObjectCount; + }; + + ////////////////////////////////////////////////////////////////////////// + // CAsyncCallback [template] + // + // Description: + // Helper class that routes IMFAsyncCallback::Invoke calls to a class + // method on the parent class. + // + // Usage: + // Add this class as a member variable. In the parent class constructor, + // initialize the CAsyncCallback class like this: + // m_cb(this, &CYourClass::OnInvoke) + // where + // m_cb = CAsyncCallback object + // CYourClass = parent class + // OnInvoke = Method in the parent class to receive Invoke calls. + // + // The parent's OnInvoke method (you can name it anything you like) must + // have a signature that matches the InvokeFn typedef below. + ////////////////////////////////////////////////////////////////////////// + + // T: Type of the parent object + template + class CAsyncCallback : public IMFAsyncCallback + { + public: + + typedef HRESULT (T::*InvokeFn)(IMFAsyncResult* pAsyncResult); + + CAsyncCallback(T* pParent, InvokeFn fn) : + m_pParent(pParent), + m_pInvokeFn(fn) + { + } + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(void) + { + // Delegate to parent class. + return m_pParent->AddRef(); + } + + STDMETHODIMP_(ULONG) Release(void) + { + // Delegate to parent class. + return m_pParent->Release(); + } + + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) + { + if (!ppv) + { + return E_POINTER; + } + if (iid == __uuidof(IUnknown)) + { + *ppv = static_cast(static_cast(this)); + } + else if (iid == __uuidof(IMFAsyncCallback)) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; + } + + // IMFAsyncCallback methods + STDMETHODIMP GetParameters(__RPC__out DWORD* pdwFlags, __RPC__out DWORD* pdwQueue) + { + // Implementation of this method is optional. + return E_NOTIMPL; + } + + STDMETHODIMP Invoke(__RPC__in_opt IMFAsyncResult* pAsyncResult) + { + return (m_pParent->*m_pInvokeFn)(pAsyncResult); + } + + private: + + T* m_pParent; + InvokeFn m_pInvokeFn; + }; + + //----------------------------------------------------------------------------- + // ThreadSafeQueue template + // Thread-safe queue of COM interface pointers. + // + // T: COM interface type. + // + // This class is used by the scheduler. + // + // Note: This class uses a critical section to protect the state of the queue. + // With a little work, the scheduler could probably use a lock-free queue. + //----------------------------------------------------------------------------- + + template + class ThreadSafeQueue + { + public: + + ThreadSafeQueue(void) + { + InitializeCriticalSection(&m_lock); + } + + virtual ~ThreadSafeQueue(void) + { + DeleteCriticalSection(&m_lock); + } + + HRESULT Queue(T* p) + { + EnterCriticalSection(&m_lock); + HRESULT hr = m_list.InsertBack(p); + LeaveCriticalSection(&m_lock); + return hr; + } + + HRESULT Dequeue(T** pp) + { + EnterCriticalSection(&m_lock); + HRESULT hr = S_OK; + if (m_list.IsEmpty()) + { + *pp = NULL; + hr = S_FALSE; + } + else + { + hr = m_list.RemoveFront(pp); + } + LeaveCriticalSection(&m_lock); + return hr; + } + + HRESULT PutBack(T* p) + { + EnterCriticalSection(&m_lock); + HRESULT hr = m_list.InsertFront(p); + LeaveCriticalSection(&m_lock); + return hr; + } + + DWORD GetCount(void) + { + EnterCriticalSection(&m_lock); + DWORD nCount = m_list.GetCount(); + LeaveCriticalSection(&m_lock); + return nCount; + } + + void Clear(void) + { + EnterCriticalSection(&m_lock); + m_list.Clear(); + LeaveCriticalSection(&m_lock); + } + + private: + + CRITICAL_SECTION m_lock; + ComPtrListEx m_list; + }; + + class CCritSec + { + public: + + CCritSec(void) : + m_cs() + { + InitializeCriticalSection(&m_cs); + } + + ~CCritSec(void) + { + DeleteCriticalSection(&m_cs); + } + + _Acquires_lock_(this->m_cs) + void Lock(void) + { + EnterCriticalSection(&m_cs); + } + + _Releases_lock_(this->m_cs) + void Unlock(void) + { + LeaveCriticalSection(&m_cs); + } + + private: + + CRITICAL_SECTION m_cs; + }; + + class CAutoLock + { + public: + + _Acquires_lock_(this->m_pLock->m_cs) + CAutoLock(CCritSec* pLock) : + m_pLock(pLock) + { + m_pLock->Lock(); + } + + _Releases_lock_(this->m_pLock->m_cs) + ~CAutoLock(void) + { + m_pLock->Unlock(); + } + + private: + + CCritSec* m_pLock; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/DLLMain.cpp b/Samples/DX11VideoRenderer/cpp/DLLMain.cpp new file mode 100644 index 00000000..65835969 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/DLLMain.cpp @@ -0,0 +1,261 @@ +#include +#include "Common.h" +#include "Activate.h" +#include "ClassFactory.h" +#include "MediaSink.h" + +HMODULE g_hModule = NULL; +volatile long DX11VideoRenderer::CBase::s_lObjectCount = 0; +volatile long DX11VideoRenderer::CClassFactory::s_lLockCount = 0; + +// helper functions + +/////////////////////////////////////////////////////////////////////// +// Name: CreateObjectKeyName +// Desc: Converts a CLSID into a string with the form "CLSID\{clsid}" +/////////////////////////////////////////////////////////////////////// + +HRESULT CreateObjectKeyName(const GUID& guid, _Out_writes_(cchMax) TCHAR* pszName, DWORD cchMax) +{ + pszName[0] = _T('\0'); + + // convert CLSID to string + OLECHAR pszCLSID[CHARS_IN_GUID]; + HRESULT hr = StringFromGUID2(guid, pszCLSID, CHARS_IN_GUID); + if (SUCCEEDED(hr)) + { + // create a string of the form "CLSID\{clsid}" + hr = StringCchPrintf(pszName, cchMax - 1, TEXT("CLSID\\%ls"), pszCLSID); + } + return hr; +} + +/////////////////////////////////////////////////////////////////////// +// Name: SetKeyValue +// Desc: Sets a string value (REG_SZ) for a registry key +// +// hKey: Handle to the registry key. +// sName: Name of the value. Use NULL for the default value. +// sValue: The string value. +/////////////////////////////////////////////////////////////////////// + +HRESULT SetKeyValue(HKEY hKey, const TCHAR* pszName, const TCHAR* pszValue) +{ + size_t cch = 0; + DWORD cbData = 0; + HRESULT hr = StringCchLength(pszValue, MAXLONG, &cch); + if (SUCCEEDED(hr)) + { + cbData = (DWORD) (sizeof(TCHAR) * (cch + 1)); // add 1 for the NULL character + hr = __HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszName, 0, REG_SZ, reinterpret_cast(pszValue), cbData)); + } + return hr; +} + +/////////////////////////////////////////////////////////////////////// +// Name: RegisterObject +// Desc: Creates the registry entries for a COM object. +// +// guid: The object's CLSID +// sDescription: Description of the object +// sThreadingMode: Threading model. e.g., "Both" +/////////////////////////////////////////////////////////////////////// + +HRESULT RegisterObject(GUID guid, const TCHAR* pszDescription, const TCHAR* pszThreadingModel) +{ + HRESULT hr = S_OK; + TCHAR pszTemp[MAX_PATH]; + HKEY hKey = NULL; + HKEY hSubkey = NULL; + DWORD dwRet = 0; + + do + { + hr = CreateObjectKeyName(guid, pszTemp, MAX_PATH); + if (FAILED(hr)) + { + break; + } + + hr = __HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_CLASSES_ROOT, pszTemp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)); + if (FAILED(hr)) + { + break; + } + + hr = SetKeyValue(hKey, NULL, pszDescription); + if (FAILED(hr)) + { + break; + } + + hr = __HRESULT_FROM_WIN32(RegCreateKeyEx(hKey, L"InprocServer32", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubkey, NULL)); + if (FAILED(hr)) + { + break; + } + + dwRet = GetModuleFileName(g_hModule, pszTemp, MAX_PATH); + if (dwRet == 0) + { + hr = __HRESULT_FROM_WIN32(GetLastError()); + break; + } + if (dwRet == MAX_PATH) + { + hr = E_FAIL; // buffer too small + break; + } + + hr = SetKeyValue(hSubkey, NULL, pszTemp); + if (FAILED(hr)) + { + break; + } + + hr = SetKeyValue(hSubkey, L"ThreadingModel", pszThreadingModel); + } + while (FALSE); + + if (hSubkey != NULL) + { + RegCloseKey(hSubkey); + } + + if (hKey != NULL) + { + RegCloseKey(hKey); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////// +// Name: UnregisterObject +// Desc: Deletes the registry entries for a COM object. +// +// guid: The object's CLSID +/////////////////////////////////////////////////////////////////////// + +HRESULT UnregisterObject(GUID guid) +{ + HRESULT hr = S_OK; + TCHAR pszTemp[MAX_PATH]; + + do + { + hr = CreateObjectKeyName(guid, pszTemp, MAX_PATH); + if (FAILED(hr)) + { + break; + } + + hr = __HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, pszTemp)); + } + while (FALSE); + + return hr; +} + +// DLL Exports + +STDAPI CreateDX11VideoRenderer(REFIID riid, void** ppvObject) +{ + return DX11VideoRenderer::CMediaSink::CreateInstance(riid, ppvObject); +} + +STDAPI CreateDX11VideoRendererActivate(HWND hwnd, IMFActivate** ppActivate) +{ + return DX11VideoRenderer::CActivate::CreateInstance(hwnd, ppActivate); +} + +STDAPI DllCanUnloadNow(void) +{ + return (DX11VideoRenderer::CBase::GetObjectCount() == 0 && DX11VideoRenderer::CClassFactory::IsLocked() == FALSE) ? S_OK : S_FALSE; +} + +STDAPI DllGetClassObject(_In_ REFCLSID clsid, _In_ REFIID riid, _Outptr_ void** ppvObject) +{ + if (clsid != CLSID_DX11VideoRenderer) + { + return CLASS_E_CLASSNOTAVAILABLE; + } + + DX11VideoRenderer::CClassFactory* pFactory = new DX11VideoRenderer::CClassFactory(); + if (pFactory == NULL) + { + return E_OUTOFMEMORY; + } + + pFactory->AddRef(); + + HRESULT hr = pFactory->QueryInterface(riid, ppvObject); + + SafeRelease(pFactory); + + return hr; +} + +BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = static_cast(hModule); + break; + } + default: + { + break; + } + } + + return TRUE; +} + +STDAPI DllRegisterServer(void) +{ + HRESULT hr = S_OK; + + do + { + hr = RegisterObject(CLSID_DX11VideoRenderer, L"DX11 Video Renderer", L"Both"); + if (FAILED(hr)) + { + break; + } + + hr = RegisterObject(CLSID_DX11VideoRendererActivate, L"DX11 Video Renderer Activate", L"Both"); + if (FAILED(hr)) + { + break; + } + + hr = MFTRegister( + CLSID_DX11VideoRenderer, // CLSID + MFT_CATEGORY_OTHER, // Category + L"DX11 Video Renderer", // Friendly name + 0, // Reserved, must be zero. + 0, + NULL, + 0, + NULL, + NULL + ); + } + while (FALSE); + + return hr; +} + +STDAPI DllUnregisterServer(void) +{ + HRESULT hr = UnregisterObject(CLSID_DX11VideoRenderer); + HRESULT hrTemp = MFTUnregister(CLSID_DX11VideoRenderer); + if (SUCCEEDED(hr)) + { + hr = hrTemp; + } + return hr; +} diff --git a/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.def b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.def new file mode 100644 index 00000000..2de1efec --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.def @@ -0,0 +1,9 @@ +LIBRARY "DX11VideoRenderer" +EXPORTS + CreateDX11VideoRenderer + CreateDX11VideoRendererActivate + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllMain PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE \ No newline at end of file diff --git a/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.h b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.h new file mode 100644 index 00000000..892af982 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.h @@ -0,0 +1,11 @@ +#pragma once + +// {83A1FDBC-AB3A-4376-A529-80E18C206534} +DEFINE_GUID(CLSID_DX11VideoRenderer, 0x83a1fdbc, 0xab3a, 0x4376, 0xa5, 0x29, 0x80, 0xe1, 0x8c, 0x20, 0x65, 0x34); + +// {0743FA5C-DA9E-4760-8187-CCAC3DC15D77} +DEFINE_GUID(CLSID_DX11VideoRendererActivate, 0x743fa5c, 0xda9e, 0x4760, 0x81, 0x87, 0xcc, 0xac, 0x3d, 0xc1, 0x5d, 0x77); + +// creation methods exposed by the lib +STDAPI CreateDX11VideoRenderer(REFIID riid, void** ppvObject); +STDAPI CreateDX11VideoRendererActivate(HWND hwnd, IMFActivate** ppActivate); diff --git a/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.sln b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.sln new file mode 100644 index 00000000..be67423c --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DX11VideoRenderer", "DX11VideoRenderer.vcxproj", "{ED9D0263-0454-4C86-967B-BEEB81B8330B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ED9D0263-0454-4C86-967B-BEEB81B8330B}.Debug|Win32.ActiveCfg = Debug|Win32 + {ED9D0263-0454-4C86-967B-BEEB81B8330B}.Debug|Win32.Build.0 = Debug|Win32 + {ED9D0263-0454-4C86-967B-BEEB81B8330B}.Release|Win32.ActiveCfg = Release|Win32 + {ED9D0263-0454-4C86-967B-BEEB81B8330B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.vcxproj b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.vcxproj new file mode 100644 index 00000000..75d25968 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/DX11VideoRenderer.vcxproj @@ -0,0 +1,117 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {ED9D0263-0454-4C86-967B-BEEB81B8330B} + Win32Proj + DX11VideoRenderer + native + + + + DynamicLibrary + true + Unicode + v110 + + + DynamicLibrary + false + true + Unicode + v110 + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + + Windows + true + DX11VideoRenderer.def + winmm.lib;dcomp.lib;d3d11.lib;mfuuid.lib;mfplat.lib;evr.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;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + + Windows + true + true + true + DX11VideoRenderer.def + winmm.lib;dcomp.lib;d3d11.lib;mfuuid.lib;mfplat.lib;evr.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) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/DX11VideoRenderer/cpp/MFAttributesImpl.h b/Samples/DX11VideoRenderer/cpp/MFAttributesImpl.h new file mode 100644 index 00000000..9402a4af --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/MFAttributesImpl.h @@ -0,0 +1,352 @@ +#pragma once + +template +class CMFAttributesImpl : public TBase +{ +protected: + + // This version of the constructor does not initialize the + // attribute store. The derived class must call Initialize() in + // its own constructor. + CMFAttributesImpl(void) : + _pAttributes(NULL) + { + } + + // This version of the constructor initializes the attribute + // store, but the derived class must pass an HRESULT parameter + // to the constructor. + + CMFAttributesImpl(HRESULT& hr, UINT32 cInitialSize = 0) : + _pAttributes(NULL) + { + hr = Initialize(cInitialSize); + } + + // The next version of the constructor uses a caller-provided + // implementation of IMFAttributes. + + // (Sometimes you want to delegate IMFAttributes calls to some + // other object that implements IMFAttributes, rather than using + // MFCreateAttributes.) + + CMFAttributesImpl(HRESULT& hr, IUnknown* pUnk) : + _pAttributes(NULL) + { + hr = Initialize(pUnk); + } + + virtual ~CMFAttributesImpl(void) + { + if (_pAttributes) + { + _pAttributes->Release(); + } + } + + // Initializes the object by creating the standard Media Foundation attribute store. + HRESULT Initialize(UINT32 cInitialSize = 0) + { + if (_pAttributes == NULL) + { + return MFCreateAttributes(&_pAttributes, cInitialSize); + } + else + { + return S_OK; + } + } + + // Initializes this object from a caller-provided attribute store. + // pUnk: Pointer to an object that exposes IMFAttributes. + HRESULT Initialize(IUnknown* pUnk) + { + if (_pAttributes) + { + _pAttributes->Release(); + _pAttributes = NULL; + } + + return pUnk->QueryInterface(IID_PPV_ARGS(&_pAttributes)); + } + +public: + + // IMFAttributes methods + + STDMETHODIMP GetItem(__RPC__in REFGUID guidKey, __RPC__inout_opt PROPVARIANT* pValue) + { + assert(_pAttributes); + return _pAttributes->GetItem(guidKey, pValue); + } + + STDMETHODIMP GetItemType(__RPC__in REFGUID guidKey, __RPC__out MF_ATTRIBUTE_TYPE* pType) + { + assert(_pAttributes); + return _pAttributes->GetItemType(guidKey, pType); + } + + STDMETHODIMP CompareItem(__RPC__in REFGUID guidKey, __RPC__in REFPROPVARIANT Value, __RPC__out BOOL* pbResult) + { + assert(_pAttributes); + return _pAttributes->CompareItem(guidKey, Value, pbResult); + } + + STDMETHODIMP Compare(__RPC__in_opt IMFAttributes* pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, __RPC__out BOOL* pbResult) + { + assert(_pAttributes); + return _pAttributes->Compare(pTheirs, MatchType, pbResult); + } + + STDMETHODIMP GetUINT32(__RPC__in REFGUID guidKey, __RPC__out UINT32* punValue) + { + assert(_pAttributes); + return _pAttributes->GetUINT32(guidKey, punValue); + } + + STDMETHODIMP GetUINT64(__RPC__in REFGUID guidKey, __RPC__out UINT64* punValue) + { + assert(_pAttributes); + return _pAttributes->GetUINT64(guidKey, punValue); + } + + STDMETHODIMP GetDouble(__RPC__in REFGUID guidKey, __RPC__out double* pfValue) + { + assert(_pAttributes); + return _pAttributes->GetDouble(guidKey, pfValue); + } + + STDMETHODIMP GetGUID(__RPC__in REFGUID guidKey, __RPC__out GUID* pguidValue) + { + assert(_pAttributes); + return _pAttributes->GetGUID(guidKey, pguidValue); + } + + STDMETHODIMP GetStringLength(__RPC__in REFGUID guidKey, __RPC__out UINT32* pcchLength) + { + assert(_pAttributes); + return _pAttributes->GetStringLength(guidKey, pcchLength); + } + + STDMETHODIMP GetString(__RPC__in REFGUID guidKey, __RPC__out_ecount_full(cchBufSize) LPWSTR pwszValue, UINT32 cchBufSize, __RPC__inout_opt UINT32* pcchLength) + { + assert(_pAttributes); + return _pAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength); + } + + STDMETHODIMP GetAllocatedString(__RPC__in REFGUID guidKey, __RPC__deref_out_ecount_full_opt(( *pcchLength + 1 ) ) LPWSTR* ppwszValue, __RPC__out UINT32* pcchLength) + { + assert(_pAttributes); + return _pAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength); + } + + STDMETHODIMP GetBlobSize(__RPC__in REFGUID guidKey, __RPC__out UINT32* pcbBlobSize) + { + assert(_pAttributes); + return _pAttributes->GetBlobSize(guidKey, pcbBlobSize); + } + + STDMETHODIMP GetBlob(__RPC__in REFGUID guidKey, __RPC__out_ecount_full(cbBufSize) UINT8* pBuf, UINT32 cbBufSize, __RPC__inout_opt UINT32* pcbBlobSize) + { + assert(_pAttributes); + return _pAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize); + } + + STDMETHODIMP GetAllocatedBlob(__RPC__in REFGUID guidKey, __RPC__deref_out_ecount_full_opt(*pcbSize) UINT8** ppBuf, __RPC__out UINT32* pcbSize) + { + assert(_pAttributes); + return _pAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize); + } + + STDMETHODIMP GetUnknown(__RPC__in REFGUID guidKey, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppv) + { + assert(_pAttributes); + return _pAttributes->GetUnknown(guidKey, riid, ppv); + } + + STDMETHODIMP SetItem(__RPC__in REFGUID guidKey, __RPC__in REFPROPVARIANT Value) + { + assert(_pAttributes); + return _pAttributes->SetItem(guidKey, Value); + } + + STDMETHODIMP DeleteItem(__RPC__in REFGUID guidKey) + { + assert(_pAttributes); + return _pAttributes->DeleteItem(guidKey); + } + + STDMETHODIMP DeleteAllItems(void) + { + assert(_pAttributes); + return _pAttributes->DeleteAllItems(); + } + + STDMETHODIMP SetUINT32(__RPC__in REFGUID guidKey, UINT32 unValue) + { + assert(_pAttributes); + return _pAttributes->SetUINT32(guidKey, unValue); + } + + STDMETHODIMP SetUINT64(__RPC__in REFGUID guidKey, UINT64 unValue) + { + assert(_pAttributes); + return _pAttributes->SetUINT64(guidKey, unValue); + } + + STDMETHODIMP SetDouble(__RPC__in REFGUID guidKey, double fValue) + { + assert(_pAttributes); + return _pAttributes->SetDouble(guidKey, fValue); + } + + STDMETHODIMP SetGUID(__RPC__in REFGUID guidKey, __RPC__in REFGUID guidValue) + { + assert(_pAttributes); + return _pAttributes->SetGUID(guidKey, guidValue); + } + + STDMETHODIMP SetString(__RPC__in REFGUID guidKey, __RPC__in_string LPCWSTR wszValue) + { + assert(_pAttributes); + return _pAttributes->SetString(guidKey, wszValue); + } + + STDMETHODIMP SetBlob(__RPC__in REFGUID guidKey, __RPC__in_ecount_full(cbBufSize) const UINT8* pBuf, UINT32 cbBufSize) + { + assert(_pAttributes); + return _pAttributes->SetBlob(guidKey, pBuf, cbBufSize); + } + + STDMETHODIMP SetUnknown(__RPC__in REFGUID guidKey, __RPC__in_opt IUnknown* pUnknown) + { + assert(_pAttributes); + return _pAttributes->SetUnknown(guidKey, pUnknown); + } + + STDMETHODIMP LockStore(void) + { + assert(_pAttributes); + return _pAttributes->LockStore(); + } + + STDMETHODIMP UnlockStore(void) + { + assert(_pAttributes); + return _pAttributes->UnlockStore(); + } + + STDMETHODIMP GetCount(__RPC__out UINT32* pcItems) + { + assert(_pAttributes); + return _pAttributes->GetCount(pcItems); + } + + STDMETHODIMP GetItemByIndex(UINT32 unIndex, __RPC__out GUID* pguidKey, __RPC__inout_opt PROPVARIANT* pValue) + { + assert(_pAttributes); + return _pAttributes->GetItemByIndex(unIndex, pguidKey, pValue); + } + + STDMETHODIMP CopyAllItems(__RPC__in_opt IMFAttributes* pDest) + { + assert(_pAttributes); + return _pAttributes->CopyAllItems(pDest); + } + + // Helper functions + + HRESULT SerializeToStream(DWORD dwOptions, IStream* pStm) + // dwOptions: Flags from MF_ATTRIBUTE_SERIALIZE_OPTIONS + { + assert(_pAttributes); + return MFSerializeAttributesToStream(_pAttributes, dwOptions, pStm); + } + + HRESULT DeserializeFromStream(DWORD dwOptions, IStream* pStm) + { + assert(_pAttributes); + return MFDeserializeAttributesFromStream(_pAttributes, dwOptions, pStm); + } + + // SerializeToBlob: Stores the attributes in a byte array. + // + // ppBuf: Receives a pointer to the byte array. + // pcbSize: Receives the size of the byte array. + // + // The caller must free the array using CoTaskMemFree. + HRESULT SerializeToBlob(UINT8** ppBuffer, UINT* pcbSize) + { + assert(_pAttributes); + + if (ppBuffer == NULL) + { + return E_POINTER; + } + if (pcbSize == NULL) + { + return E_POINTER; + } + + HRESULT hr = S_OK; + UINT32 cbSize = 0; + BYTE* pBuffer = NULL; + + CHECK_HR(hr = MFGetAttributesAsBlobSize(_pAttributes, &cbSize)); + + pBuffer = (BYTE*)CoTaskMemAlloc(cbSize); + if (pBuffer == NULL) + { + CHECK_HR(hr = E_OUTOFMEMORY); + } + + CHECK_HR(hr = MFGetAttributesAsBlob(_pAttributes, pBuffer, cbSize)); + + *ppBuffer = pBuffer; + *pcbSize = cbSize; + + if (FAILED(hr)) + { + *ppBuffer = NULL; + *pcbSize = 0; + CoTaskMemFree(pBuffer); + } + return hr; + } + + HRESULT DeserializeFromBlob(const UINT8* pBuffer, UINT cbSize) + { + assert(_pAttributes); + return MFInitAttributesFromBlob(_pAttributes, pBuffer, cbSize); + } + + HRESULT GetRatio(REFGUID guidKey, UINT32* pnNumerator, UINT32* punDenominator) + { + assert(_pAttributes); + return MFGetAttributeRatio(_pAttributes, guidKey, pnNumerator, punDenominator); + } + + HRESULT SetRatio(REFGUID guidKey, UINT32 unNumerator, UINT32 unDenominator) + { + assert(_pAttributes); + return MFSetAttributeRatio(_pAttributes, guidKey, unNumerator, unDenominator); + } + + // Gets an attribute whose value represents the size of something (eg a video frame). + HRESULT GetSize(REFGUID guidKey, UINT32* punWidth, UINT32* punHeight) + { + assert(_pAttributes); + return MFGetAttributeSize(_pAttributes, guidKey, punWidth, punHeight); + } + + // Sets an attribute whose value represents the size of something (eg a video frame). + HRESULT SetSize(REFGUID guidKey, UINT32 unWidth, UINT32 unHeight) + { + assert(_pAttributes); + return MFSetAttributeSize (_pAttributes, guidKey, unWidth, unHeight); + } + +protected: + + IMFAttributes* _pAttributes; +}; \ No newline at end of file diff --git a/Samples/DX11VideoRenderer/cpp/Marker.cpp b/Samples/DX11VideoRenderer/cpp/Marker.cpp new file mode 100644 index 00000000..75fe7af3 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Marker.cpp @@ -0,0 +1,142 @@ +#include "Marker.h" + +////////////////////// +// CMarker class +// Holds information from IMFStreamSink::PlaceMarker +// + +DX11VideoRenderer::CMarker::CMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType) : + m_nRefCount(1), + m_eMarkerType(eMarkerType) +{ + PropVariantInit(&m_varMarkerValue); + PropVariantInit(&m_varContextValue); +} + +DX11VideoRenderer::CMarker::~CMarker(void) +{ + assert(m_nRefCount == 0); + + PropVariantClear(&m_varMarkerValue); + PropVariantClear(&m_varContextValue); +} + +/* static */ +HRESULT DX11VideoRenderer::CMarker::Create( + MFSTREAMSINK_MARKER_TYPE eMarkerType, + const PROPVARIANT* pvarMarkerValue, // Can be NULL. + const PROPVARIANT* pvarContextValue, // Can be NULL. + IMarker** ppMarker + ) +{ + if (ppMarker == NULL) + { + return E_POINTER; + } + + HRESULT hr = S_OK; + CMarker* pMarker = new CMarker(eMarkerType); + + if (pMarker == NULL) + { + hr = E_OUTOFMEMORY; + } + + // Copy the marker data. + if (SUCCEEDED(hr)) + { + if (pvarMarkerValue) + { + hr = PropVariantCopy(&pMarker->m_varMarkerValue, pvarMarkerValue); + } + } + + if (SUCCEEDED(hr)) + { + if (pvarContextValue) + { + hr = PropVariantCopy(&pMarker->m_varContextValue, pvarContextValue); + } + } + + if (SUCCEEDED(hr)) + { + *ppMarker = pMarker; + (*ppMarker)->AddRef(); + } + + SafeRelease(pMarker); + + return hr; +} + +// IUnknown methods. + +ULONG DX11VideoRenderer::CMarker::AddRef(void) +{ + return InterlockedIncrement(&m_nRefCount); +} + +ULONG DX11VideoRenderer::CMarker::Release(void) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + // For thread safety, return a temporary variable. + return uCount; +} + +HRESULT DX11VideoRenderer::CMarker::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMarker)) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +// IMarker methods +HRESULT DX11VideoRenderer::CMarker::GetMarkerType(MFSTREAMSINK_MARKER_TYPE* pType) +{ + if (pType == NULL) + { + return E_POINTER; + } + + *pType = m_eMarkerType; + return S_OK; +} + +HRESULT DX11VideoRenderer::CMarker::GetMarkerValue(PROPVARIANT* pvar) +{ + if (pvar == NULL) + { + return E_POINTER; + } + return PropVariantCopy(pvar, &m_varMarkerValue); + +} +HRESULT DX11VideoRenderer::CMarker::GetContext(PROPVARIANT* pvar) +{ + if (pvar == NULL) + { + return E_POINTER; + } + return PropVariantCopy(pvar, &m_varContextValue); +} diff --git a/Samples/DX11VideoRenderer/cpp/Marker.h b/Samples/DX11VideoRenderer/cpp/Marker.h new file mode 100644 index 00000000..7761f4ff --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Marker.h @@ -0,0 +1,62 @@ +#pragma once + +#include "Common.h" +#include "Scheduler.h" +#include "display.h" + +namespace DX11VideoRenderer +{ + // IMarker: + // Custom interface for handling IMFStreamSink::PlaceMarker calls asynchronously. + + // A marker consists of a marker type, marker data, and context data. + // By defining this interface, we can store the marker data inside an IUnknown object + // and keep that object on the same queue that holds the media samples. This is + // useful because samples and markers must be serialized. That is, we cannot respond + // to a marker until we have processed all of the samples that came before it. + + // Note that IMarker is not a standard Media Foundation interface. + MIDL_INTERFACE("3AC82233-933C-43a9-AF3D-ADC94EABF406") + IMarker : public IUnknown + { + virtual STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE* pType) = 0; + virtual STDMETHODIMP GetMarkerValue(PROPVARIANT* pvar) = 0; + virtual STDMETHODIMP GetContext(PROPVARIANT* pvar) = 0; + }; + + // Holds marker information for IMFStreamSink::PlaceMarker + + class CMarker : public IMarker, private CBase + { + public: + + static HRESULT Create( + MFSTREAMSINK_MARKER_TYPE eMarkerType, + const PROPVARIANT* pvarMarkerValue, + const PROPVARIANT* pvarContextValue, + IMarker** ppMarker + ); + + // IUnknown methods. + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP_(ULONG) Release(void); + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv); + + STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE* pType); + STDMETHODIMP GetMarkerValue(PROPVARIANT* pvar); + STDMETHODIMP GetContext(PROPVARIANT* pvar); + + protected: + + MFSTREAMSINK_MARKER_TYPE m_eMarkerType; + PROPVARIANT m_varMarkerValue; + PROPVARIANT m_varContextValue; + + private: + + CMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType); + virtual ~CMarker(void); + + long m_nRefCount; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/MediaSink.cpp b/Samples/DX11VideoRenderer/cpp/MediaSink.cpp new file mode 100644 index 00000000..2c249d40 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/MediaSink.cpp @@ -0,0 +1,791 @@ +#include "MediaSink.h" + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// CMediaSink class. - Implements the media sink. +// +// Notes: +// - Most public methods calls CheckShutdown. This method fails if the sink was shut down. +// +///////////////////////////////////////////////////////////////////////////////////////////// + +DX11VideoRenderer::CCritSec DX11VideoRenderer::CMediaSink::s_csStreamSinkAndScheduler; + +//------------------------------------------------------------------- +// Name: CreateInstance +// Description: Creates an instance of the DX11 Video Renderer sink object. +//------------------------------------------------------------------- + +/* static */ HRESULT DX11VideoRenderer::CMediaSink::CreateInstance(_In_ REFIID iid, _COM_Outptr_ void** ppSink) +{ + if (ppSink == NULL) + { + return E_POINTER; + } + + *ppSink = NULL; + + HRESULT hr = S_OK; + CMediaSink* pSink = new CMediaSink(); // Created with ref count = 1. + + if (pSink == NULL) + { + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + hr = pSink->Initialize(); + } + + if (SUCCEEDED(hr)) + { + hr = pSink->QueryInterface(iid, ppSink); + } + + SafeRelease(pSink); + + return hr; +} + +// IUnknown methods + +ULONG DX11VideoRenderer::CMediaSink::AddRef(void) +{ + return InterlockedIncrement(&m_nRefCount); +} + +HRESULT DX11VideoRenderer::CMediaSink::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(static_cast(this)); + } + else if (iid == __uuidof(IMFMediaSink)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFClockStateSink)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFGetService)) + { + *ppv = static_cast(this); + } + else if (iid == IID_IMFRateSupport) + { + *ppv = static_cast(this); + } + else if (iid == IID_IMFMediaSinkPreroll) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +ULONG DX11VideoRenderer::CMediaSink::Release(void) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + // For thread safety, return a temporary variable. + return uCount; +} + +/// IMFMediaSink methods. + +//------------------------------------------------------------------- +// Name: AddStreamSink +// Description: Adds a new stream to the sink. +// +// Note: This sink has a fixed number of streams, so this method +// always returns MF_E_STREAMSINKS_FIXED. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::AddStreamSink(DWORD dwStreamSinkIdentifier, __RPC__in_opt IMFMediaType* pMediaType, __RPC__deref_out_opt IMFStreamSink** ppStreamSink) +{ + return MF_E_STREAMSINKS_FIXED; +} + +//------------------------------------------------------------------- +// Name: GetCharacteristics +// Description: Returns the characteristics flags. +// +// Note: This sink has a fixed number of streams. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::GetCharacteristics(__RPC__out DWORD* pdwCharacteristics) +{ + CAutoLock lock(&m_csMediaSink); + + if (pdwCharacteristics == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + *pdwCharacteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL; + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetPresentationClock +// Description: Returns a pointer to the presentation clock. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::GetPresentationClock(__RPC__deref_out_opt IMFPresentationClock** ppPresentationClock) +{ + CAutoLock lock(&m_csMediaSink); + + if (ppPresentationClock == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + if (m_pClock == NULL) + { + hr = MF_E_NO_CLOCK; // There is no presentation clock. + } + else + { + // Return the pointer to the caller. + *ppPresentationClock = m_pClock; + (*ppPresentationClock)->AddRef(); + } + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetStreamSinkById +// Description: Retrieves a stream by ID. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::GetStreamSinkById(DWORD dwStreamSinkIdentifier, __RPC__deref_out_opt IMFStreamSink** ppStreamSink) +{ + CAutoLock lock(&m_csMediaSink); + + if (ppStreamSink == NULL) + { + return E_POINTER; + } + + // Fixed stream ID. + if (dwStreamSinkIdentifier != STREAM_ID) + { + return MF_E_INVALIDSTREAMNUMBER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + *ppStreamSink = m_pStream; + (*ppStreamSink)->AddRef(); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetStreamSinkByIndex +// Description: Retrieves a stream by index. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::GetStreamSinkByIndex(DWORD dwIndex, __RPC__deref_out_opt IMFStreamSink** ppStreamSink) +{ + CAutoLock lock(&m_csMediaSink); + + if (ppStreamSink == NULL) + { + return E_POINTER; + } + + // Fixed stream: Index 0. + if (dwIndex > 0) + { + return MF_E_INVALIDINDEX; + } + + HRESULT hr = CheckShutdown(); + if (SUCCEEDED(hr)) + { + *ppStreamSink = m_pStream; + (*ppStreamSink)->AddRef(); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetStreamSinkCount +// Description: Returns the number of streams. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::GetStreamSinkCount(__RPC__out DWORD* pcStreamSinkCount) +{ + CAutoLock lock(&m_csMediaSink); + + if (pcStreamSinkCount == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + *pcStreamSinkCount = 1; // Fixed number of streams. + } + + return hr; + +} + +//------------------------------------------------------------------- +// Name: RemoveStreamSink +// Description: Removes a stream from the sink. +// +// Note: This sink has a fixed number of streams, so this method +// always returns MF_E_STREAMSINKS_FIXED. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::RemoveStreamSink(DWORD dwStreamSinkIdentifier) +{ + return MF_E_STREAMSINKS_FIXED; +} + +//------------------------------------------------------------------- +// Name: SetPresentationClock +// Description: Sets the presentation clock. +// +// pPresentationClock: Pointer to the clock. Can be NULL. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::SetPresentationClock(__RPC__in_opt IMFPresentationClock* pPresentationClock) +{ + CAutoLock lock(&m_csMediaSink); + + HRESULT hr = CheckShutdown(); + + // If we already have a clock, remove ourselves from that clock's + // state notifications. + if (SUCCEEDED(hr)) + { + if (m_pClock) + { + hr = m_pClock->RemoveClockStateSink(this); + } + } + + // Register ourselves to get state notifications from the new clock. + if (SUCCEEDED(hr)) + { + if (pPresentationClock) + { + hr = pPresentationClock->AddClockStateSink(this); + } + } + + if (SUCCEEDED(hr)) + { + // Release the pointer to the old clock. + // Store the pointer to the new clock. + + SafeRelease(m_pClock); + m_pClock = pPresentationClock; + if (m_pClock) + { + m_pClock->AddRef(); + } + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: Shutdown +// Description: Releases resources held by the media sink. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::Shutdown(void) +{ + CAutoLock lock(&m_csMediaSink); + + HRESULT hr = MF_E_SHUTDOWN; + + m_IsShutdown = TRUE; + + if (m_pStream != NULL) + { + m_pStream->Shutdown(); + } + + if (m_pPresenter != NULL) + { + m_pPresenter->Shutdown(); + } + + SafeRelease(m_pClock); + SafeRelease(m_pStream); + SafeRelease(m_pPresenter); + + if (m_pScheduler != NULL) + { + hr = m_pScheduler->StopScheduler(); + } + + SafeRelease(m_pScheduler); + + return hr; +} + +//------------------------------------------------------------------- +// Name: OnClockPause +// Description: Called when the presentation clock paused. +// +// Note: For an archive sink, the paused state is equivalent to the +// running (started) state. We still accept data and archive it. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::OnClockPause( + /* [in] */ MFTIME hnsSystemTime) +{ + CAutoLock lock(&m_csMediaSink); + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pStream->Pause(); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: OnClockRestart +// Description: Called when the presentation clock restarts. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::OnClockRestart( + /* [in] */ MFTIME hnsSystemTime) +{ + CAutoLock lock(&m_csMediaSink); + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pStream->Restart(); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: OnClockSetRate +// Description: Called when the presentation clock's rate changes. +// +// Note: For a rateless sink, the clock rate is not important. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::OnClockSetRate( + /* [in] */ MFTIME hnsSystemTime, + /* [in] */ float flRate) +{ + if (m_pScheduler != NULL) + { + // Tell the scheduler about the new rate. + m_pScheduler->SetClockRate(flRate); + } + + return S_OK; +} + +//------------------------------------------------------------------- +// Name: OnClockStart +// Description: Called when the presentation clock starts. +// +// hnsSystemTime: System time when the clock started. +// llClockStartOffset: Starting presentatation time. +// +// Note: For an archive sink, we don't care about the system time. +// But we need to cache the value of llClockStartOffset. This +// gives us the earliest time stamp that we archive. If any +// input samples have an earlier time stamp, we discard them. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::OnClockStart( + /* [in] */ MFTIME hnsSystemTime, + /* [in] */ LONGLONG llClockStartOffset) +{ + CAutoLock lock(&m_csMediaSink); + + HRESULT hr = CheckShutdown(); + if (FAILED(hr)) + { + return hr; + } + + // Check if the clock is already active (not stopped). + // And if the clock position changes while the clock is active, it + // is a seek request. We need to flush all pending samples. + if (m_pStream->IsActive() && llClockStartOffset != PRESENTATION_CURRENT_POSITION) + { + // This call blocks until the scheduler threads discards all scheduled samples. + hr = m_pStream->Flush(); + } + else + { + if (m_pScheduler != NULL) + { + // Start the scheduler thread. + hr = m_pScheduler->StartScheduler(m_pClock); + } + } + + if (SUCCEEDED(hr)) + { + hr = m_pStream->Start(llClockStartOffset); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: OnClockStop +// Description: Called when the presentation clock stops. +// +// Note: After this method is called, we stop accepting new data. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::OnClockStop( + /* [in] */ MFTIME hnsSystemTime) +{ + CAutoLock lock(&m_csMediaSink); + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pStream->Stop(); + } + + if (SUCCEEDED(hr)) + { + if (m_pScheduler != NULL) + { + // Stop the scheduler thread. + hr = m_pScheduler->StopScheduler(); + } + } + + return hr; +} + +//------------------------------------------------------------------------- +// Name: GetService +// Description: IMFGetService +//------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject) +{ + HRESULT hr = S_OK; + + if (guidService == MF_RATE_CONTROL_SERVICE) + { + hr = QueryInterface(riid, ppvObject); + } + else if (guidService == MR_VIDEO_RENDER_SERVICE) + { + hr = m_pPresenter->QueryInterface(riid, ppvObject); + } + else if (guidService == MR_VIDEO_ACCELERATION_SERVICE) + { + hr = m_pPresenter->GetService(guidService, riid, ppvObject); + } + else + { + hr = MF_E_UNSUPPORTED_SERVICE; + } + + return hr; +} + +STDMETHODIMP DX11VideoRenderer::CMediaSink::GetFastestRate( + MFRATE_DIRECTION eDirection, + BOOL fThin, + _Out_ float *pflRate + ) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_csMediaSink); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (NULL == pflRate) + { + hr = E_POINTER; + break; + } + + float rate; + + hr = m_pStream->GetMaxRate(fThin, &rate); + if (FAILED(hr)) + { + break; + } + + if (MFRATE_FORWARD == eDirection) + { + *pflRate = rate; + } + else + { + *pflRate = -rate; + } + } + while (FALSE); + + return hr; +} + +//------------------------------------------------------------------------- +// Name: GetSlowestRate +// Description: IMFRateSupport +//------------------------------------------------------------------------- + +STDMETHODIMP DX11VideoRenderer::CMediaSink::GetSlowestRate( + MFRATE_DIRECTION eDirection, + BOOL fThin, + _Out_ float* pflRate + ) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_csMediaSink); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (NULL == pflRate) + { + hr = E_POINTER; + break; + } + + if (SUCCEEDED(hr)) + { + // + // We go as slow as you want! + // + *pflRate = 0; + } + } + while (FALSE); + + return hr; +} + +STDMETHODIMP DX11VideoRenderer::CMediaSink::IsRateSupported(BOOL fThin, float flRate, __RPC__inout_opt float* pflNearestSupportedRate) +{ + HRESULT hr = S_OK; + float flNearestSupportedRate = flRate; + + CAutoLock lock(&m_csMediaSink); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + // + // Only support rates up to the refresh rate of the monitor. + // This check makes sense only if we're going to be receiving + // all frames + // + if ( !fThin ) + { + float rate; + + hr = m_pStream->GetMaxRate(fThin, &rate); + if (FAILED(hr)) + { + break; + } + + if ( (flRate > 0 && flRate > (float)rate) || + (flRate < 0 && flRate < -(float)rate) ) + { + hr = MF_E_UNSUPPORTED_RATE; + flNearestSupportedRate = ( flRate >= 0.0f ) ? rate : -rate; + + break; + } + } + } + while (FALSE); + + if ( NULL != pflNearestSupportedRate ) + { + *pflNearestSupportedRate = flNearestSupportedRate; + } + + return hr; +} + +STDMETHODIMP DX11VideoRenderer::CMediaSink::NotifyPreroll(MFTIME hnsUpcomingStartTime) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_csMediaSink); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pStream->Preroll(); + } + + return hr; +} + +/// Private methods + +//------------------------------------------------------------------- +// CMediaSink constructor. +//------------------------------------------------------------------- + +DX11VideoRenderer::CMediaSink::CMediaSink(void) : + STREAM_ID(1), + m_nRefCount(1), + m_csMediaSink(), // default ctor + m_IsShutdown(FALSE), + m_pStream(NULL), + m_pClock(NULL), + m_pScheduler(NULL), + m_pPresenter(NULL) +{ +} + +//------------------------------------------------------------------- +// CMediaSink destructor. +//------------------------------------------------------------------- + +DX11VideoRenderer::CMediaSink::~CMediaSink(void) +{ +} + +HRESULT DX11VideoRenderer::CMediaSink::CheckShutdown(void) const +{ + if (m_IsShutdown) + { + return MF_E_SHUTDOWN; + } + else + { + return S_OK; + } +} + +//------------------------------------------------------------------- +// Name: Initialize +// Description: Initializes the media sink. +// +// Note: This method is called once when the media sink is first +// initialized. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CMediaSink::Initialize(void) +{ + HRESULT hr = S_OK; + IMFMediaSink* pSink = NULL; + + do + { + m_pScheduler = new CScheduler(s_csStreamSinkAndScheduler); + if (m_pScheduler == NULL) + { + hr = E_OUTOFMEMORY; + break; + } + + m_pStream = new CStreamSink(STREAM_ID, s_csStreamSinkAndScheduler, m_pScheduler); + if (m_pStream == NULL) + { + hr = E_OUTOFMEMORY; + break; + } + + m_pPresenter = new CPresenter(); // Created with ref count = 1. + if (m_pPresenter == NULL) + { + hr = E_OUTOFMEMORY; + break; + } + + hr = QueryInterface(IID_PPV_ARGS(&pSink)); + if (FAILED(hr)) + { + break; + } + + hr = m_pStream->Initialize(pSink, m_pPresenter); + if (FAILED(hr)) + { + break; + } + + m_pScheduler->SetCallback(static_cast(m_pStream)); + } + while (FALSE); + + if (FAILED(hr)) + { + Shutdown(); + } + + SafeRelease(pSink); + + return hr; +} diff --git a/Samples/DX11VideoRenderer/cpp/MediaSink.h b/Samples/DX11VideoRenderer/cpp/MediaSink.h new file mode 100644 index 00000000..a18a0b98 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/MediaSink.h @@ -0,0 +1,76 @@ +#pragma once + +#include "Common.h" +#include "Presenter.h" +#include "Scheduler.h" +#include "StreamSink.h" + +namespace DX11VideoRenderer +{ + class CMediaSink : + public IMFMediaSink, + public IMFClockStateSink, + public IMFGetService, + public IMFRateSupport, + public IMFMediaSinkPreroll, + private CBase + { + public: + + // Static method to create the object. + static HRESULT CreateInstance(_In_ REFIID iid, _COM_Outptr_ void** ppSink); + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv); + STDMETHODIMP_(ULONG) Release(void); + + // IMFMediaSink methods + STDMETHODIMP AddStreamSink(DWORD dwStreamSinkIdentifier, __RPC__in_opt IMFMediaType* pMediaType, __RPC__deref_out_opt IMFStreamSink** ppStreamSink); + STDMETHODIMP GetCharacteristics(__RPC__out DWORD* pdwCharacteristics); + STDMETHODIMP GetPresentationClock(__RPC__deref_out_opt IMFPresentationClock** ppPresentationClock); + STDMETHODIMP GetStreamSinkById(DWORD dwIdentifier, __RPC__deref_out_opt IMFStreamSink** ppStreamSink); + STDMETHODIMP GetStreamSinkByIndex(DWORD dwIndex, __RPC__deref_out_opt IMFStreamSink** ppStreamSink); + STDMETHODIMP GetStreamSinkCount(__RPC__out DWORD* pcStreamSinkCount); + STDMETHODIMP RemoveStreamSink(DWORD dwStreamSinkIdentifier); + STDMETHODIMP SetPresentationClock(__RPC__in_opt IMFPresentationClock* pPresentationClock); + STDMETHODIMP Shutdown(void); + + // IMFClockStateSink methods + STDMETHODIMP OnClockPause(MFTIME hnsSystemTime); + STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime); + STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate); + STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset); + STDMETHODIMP OnClockStop(MFTIME hnsSystemTime); + + // IMFGetService + STDMETHODIMP GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject); + + // IMFRateSupport + STDMETHODIMP GetFastestRate(MFRATE_DIRECTION eDirection, BOOL fThin, _Out_ float* pflRate); + STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION eDirection, BOOL fThin, _Out_ float* pflRate); + STDMETHODIMP IsRateSupported(BOOL fThin, float flRate, __RPC__inout_opt float* pflNearestSupportedRate); + + // IMFMediaSinkPreroll + STDMETHODIMP NotifyPreroll(MFTIME hnsUpcomingStartTime); + + private: + + static CCritSec s_csStreamSinkAndScheduler; // critical section for thread safety, used for CStreamSink and CScheduler + + CMediaSink(void); + virtual ~CMediaSink(void); + + HRESULT CheckShutdown(void) const; + HRESULT Initialize(void); + + const DWORD STREAM_ID; // The stream ID of the one stream on the sink. + long m_nRefCount; // reference count + CCritSec m_csMediaSink; // critical section for thread safety, used for CMediaSink + BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called. + CStreamSink* m_pStream; // Byte stream + IMFPresentationClock* m_pClock; // Presentation clock. + CScheduler* m_pScheduler; // Manages scheduling of samples. + CPresenter* m_pPresenter; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/Presenter.cpp b/Samples/DX11VideoRenderer/cpp/Presenter.cpp new file mode 100644 index 00000000..5f228f79 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Presenter.cpp @@ -0,0 +1,2307 @@ +#include "Presenter.h" + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// CPresenter class. - Presents samples using DX11. +// +// Notes: +// - Most public methods calls CheckShutdown. This method fails if the presenter was shut down. +// +///////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------------------------------------------------- +// CPresenter constructor. +//------------------------------------------------------------------- + +DX11VideoRenderer::CPresenter::CPresenter(void) : + m_nRefCount(1), + m_critSec(), // default ctor + m_IsShutdown(FALSE), + m_pDXGIFactory2(NULL), + m_pD3D11Device(NULL), + m_pD3DImmediateContext(NULL), + m_pDXGIManager(NULL), + m_pDXGIOutput1(NULL), + m_pSampleAllocatorEx(NULL), + m_pDCompDevice(NULL), + m_pHwndTarget(NULL), + m_pRootVisual(NULL), + m_bSoftwareDXVADeviceInUse(FALSE), + m_hwndVideo(NULL), + m_pMonitors(NULL), + m_lpCurrMon(NULL), + m_DeviceResetToken(0), + m_DXSWSwitch(0), + m_useXVP(1), + m_useDCompVisual(0), + m_useDebugLayer(D3D11_CREATE_DEVICE_VIDEO_SUPPORT), + m_pDX11VideoDevice(NULL), + m_pVideoProcessorEnum(NULL), + m_pVideoProcessor(NULL), + m_pSwapChain1(NULL), + m_bDeviceChanged(FALSE), + m_bResize(TRUE), + m_b3DVideo(FALSE), + m_bStereoEnabled(FALSE), + m_vp3DOutput(MFVideo3DSampleFormat_BaseView), + m_bFullScreenState(FALSE), + m_bCanProcessNextSample(TRUE), + m_displayRect(), // default ctor + m_imageWidthInPixels(0), + m_imageHeightInPixels(0), + m_uiRealDisplayWidth(0), + m_uiRealDisplayHeight(0), + m_rcSrcApp(), // default ctor + m_rcDstApp(), // default ctor + m_pXVP(NULL), + m_pXVPControl(NULL) +{ + ZeroMemory(&m_rcSrcApp, sizeof(m_rcSrcApp)); + ZeroMemory(&m_rcDstApp, sizeof(m_rcDstApp)); +} + +//------------------------------------------------------------------- +// CPresenter destructor. +//------------------------------------------------------------------- + +DX11VideoRenderer::CPresenter::~CPresenter(void) +{ + SafeDelete(m_pMonitors); +} + +// IUnknown +ULONG DX11VideoRenderer::CPresenter::AddRef(void) +{ + return InterlockedIncrement(&m_nRefCount); +} + +// IUnknown +HRESULT DX11VideoRenderer::CPresenter::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(static_cast(this)); + } + else if (iid == __uuidof(IMFVideoDisplayControl)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFGetService)) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +// IUnknown +ULONG DX11VideoRenderer::CPresenter::Release(void) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + // For thread safety, return a temporary variable. + return uCount; +} + +// IMFVideoDisplayControl +HRESULT DX11VideoRenderer::CPresenter::GetFullscreen(__RPC__out BOOL* pfFullscreen) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = CheckShutdown(); + if (FAILED(hr)) + { + return hr; + } + + if (pfFullscreen == NULL) + { + return E_POINTER; + } + + *pfFullscreen = m_bFullScreenState; + + return S_OK; +} + +// IMFVideoDisplayControl +HRESULT DX11VideoRenderer::CPresenter::SetFullscreen(BOOL fFullscreen) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + m_bFullScreenState = fFullscreen; + + SafeRelease(m_pDX11VideoDevice); + SafeRelease(m_pVideoProcessorEnum); + SafeRelease(m_pVideoProcessor); + } + + return hr; +} + +// IMFVideoDisplayControl +HRESULT DX11VideoRenderer::CPresenter::SetVideoWindow(__RPC__in HWND hwndVideo) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (!IsWindow(hwndVideo)) + { + hr = E_INVALIDARG; + break; + } + + m_pMonitors = new CMonitorArray(); + if (!m_pMonitors) + { + hr = E_OUTOFMEMORY; + break; + } + + hr = SetVideoMonitor(hwndVideo); + if (FAILED(hr)) + { + break; + } + + CheckDecodeSwitchRegKey(); + + m_hwndVideo = hwndVideo; + + hr = CreateDXGIManagerAndDevice(); + if (FAILED(hr)) + { + break; + } + + if (m_useXVP) + { + hr = CreateXVP(); + if (FAILED(hr)) + { + break; + } + } + } + while(FALSE); + + return hr; +} + +//------------------------------------------------------------------------- +// Name: GetService +// Description: IMFGetService +//------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject) +{ + HRESULT hr = S_OK; + + if (guidService == MR_VIDEO_ACCELERATION_SERVICE) + { + if (riid == __uuidof(IMFDXGIDeviceManager)) + { + if (NULL != m_pDXGIManager) + { + *ppvObject = (void*) static_cast(m_pDXGIManager); + ((IUnknown*) *ppvObject)->AddRef(); + } + else + { + hr = E_NOINTERFACE; + } + } + else if (riid == __uuidof(IMFVideoSampleAllocatorEx)) + { + if (NULL == m_pSampleAllocatorEx) + { + hr = MFCreateVideoSampleAllocatorEx(IID_IMFVideoSampleAllocatorEx, (LPVOID*)&m_pSampleAllocatorEx); + if (SUCCEEDED(hr) && NULL != m_pDXGIManager) + { + hr = m_pSampleAllocatorEx->SetDirectXManager(m_pDXGIManager); + } + } + if (SUCCEEDED(hr)) + { + hr = m_pSampleAllocatorEx->QueryInterface(riid, ppvObject); + } + } + else + { + hr = E_NOINTERFACE; + } + } + else if (guidService == MR_VIDEO_RENDER_SERVICE) + { + hr = QueryInterface(riid, ppvObject); + } + else + { + hr = MF_E_UNSUPPORTED_SERVICE; + } + + return hr; +} + +BOOL DX11VideoRenderer::CPresenter::CanProcessNextSample(void) +{ + return m_bCanProcessNextSample; +} + +HRESULT DX11VideoRenderer::CPresenter::Flush(void) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr) && m_useXVP) + { + hr = m_pXVP->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); + } + + m_bCanProcessNextSample = TRUE; + + return hr; +} + +HRESULT DX11VideoRenderer::CPresenter::GetMonitorRefreshRate(DWORD* pdwRefreshRate) +{ + if (pdwRefreshRate == NULL) + { + return E_POINTER; + } + + if (m_lpCurrMon == NULL) + { + return MF_E_INVALIDREQUEST; + } + + *pdwRefreshRate = m_lpCurrMon->dwRefreshRate; + + return S_OK; +} + +HRESULT DX11VideoRenderer::CPresenter::IsMediaTypeSupported(IMFMediaType* pMediaType, DXGI_FORMAT dxgiFormat) +{ + HRESULT hr = S_OK; + UINT32 uiNumerator = 30000, uiDenominator = 1001; + UINT32 uimageWidthInPixels, uimageHeightInPixels = 0; + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (pMediaType == NULL) + { + hr = E_POINTER; + break; + } + + if (!m_pDX11VideoDevice) + { + hr = m_pD3D11Device->QueryInterface(__uuidof(ID3D11VideoDevice), (void**)&m_pDX11VideoDevice); + if (FAILED(hr)) + { + break; + } + } + + hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &uimageWidthInPixels, &uimageHeightInPixels); + + if (FAILED(hr)) + { + break; + } + + MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &uiNumerator, &uiDenominator); + + //Check if the format is supported + + D3D11_VIDEO_PROCESSOR_CONTENT_DESC ContentDesc; + ZeroMemory( &ContentDesc, sizeof( ContentDesc ) ); + ContentDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST; + ContentDesc.InputWidth = (DWORD)uimageWidthInPixels; + ContentDesc.InputHeight = (DWORD)uimageHeightInPixels; + ContentDesc.OutputWidth = (DWORD)uimageWidthInPixels; + ContentDesc.OutputHeight = (DWORD)uimageHeightInPixels; + ContentDesc.InputFrameRate.Numerator = uiNumerator; + ContentDesc.InputFrameRate.Denominator = uiDenominator; + ContentDesc.OutputFrameRate.Numerator = uiNumerator; + ContentDesc.OutputFrameRate.Denominator = uiDenominator; + ContentDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; + + SafeRelease(m_pVideoProcessorEnum); + hr = m_pDX11VideoDevice->CreateVideoProcessorEnumerator(&ContentDesc, &m_pVideoProcessorEnum); + if (FAILED(hr)) + { + break; + } + + UINT uiFlags; + hr = m_pVideoProcessorEnum->CheckVideoProcessorFormat(dxgiFormat, &uiFlags); + if (FAILED(hr) || 0 == (uiFlags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT)) + { + hr = MF_E_UNSUPPORTED_D3D_TYPE; + break; + } + + if (m_useXVP) + { + hr = m_pXVP->SetInputType(0, pMediaType, MFT_SET_TYPE_TEST_ONLY); + if (FAILED(hr)) + { + break; + } + } + } + while (FALSE); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: PresentFrame +// +// Synopsis: Present the current outstanding frame in the DX queue +// +//-------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::PresentFrame(void) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (NULL == m_pSwapChain1) + { + break; + } + + RECT rcDest; + ZeroMemory(&rcDest, sizeof(rcDest)); + if (CheckEmptyRect(&rcDest)) + { + hr = S_OK; + break; + } + + hr = m_pSwapChain1->Present( 0, 0 ); + if (FAILED(hr)) + { + break; + } + + m_bCanProcessNextSample = TRUE; + } + while (FALSE); + + return hr; +} + +//------------------------------------------------------------------- +// Name: ProcessFrame +// Description: Present one media sample. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::ProcessFrame(IMFMediaType* pCurrentType, IMFSample* pSample, UINT32* punInterlaceMode, BOOL* pbDeviceChanged, BOOL* pbProcessAgain, IMFSample** ppOutputSample) +{ + HRESULT hr = S_OK; + BYTE* pData = NULL; + DWORD dwSampleSize = 0; + IMFMediaBuffer* pBuffer = NULL; + IMFMediaBuffer* pEVBuffer = NULL; + DWORD cBuffers = 0; + ID3D11Texture2D* pTexture2D = NULL; + IMFDXGIBuffer* pDXGIBuffer = NULL; + ID3D11Texture2D* pEVTexture2D = NULL; + IMFDXGIBuffer* pEVDXGIBuffer = NULL; + ID3D11Device* pDeviceInput = NULL; + UINT dwViewIndex = 0; + UINT dwEVViewIndex = 0; + + CAutoLock lock(&m_critSec); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (punInterlaceMode == NULL || pCurrentType == NULL || pSample == NULL || pbDeviceChanged == NULL || pbProcessAgain == NULL) + { + hr = E_POINTER; + break; + } + + *pbProcessAgain = FALSE; + *pbDeviceChanged = FALSE; + + hr = pSample->GetBufferCount( &cBuffers ); + if (FAILED(hr)) + { + break; + } + + if (1 == cBuffers) + { + hr = pSample->GetBufferByIndex(0, &pBuffer); + } + else if (2 == cBuffers && m_b3DVideo && 0 != m_vp3DOutput) + { + hr = pSample->GetBufferByIndex(0, &pBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pSample->GetBufferByIndex(1, &pEVBuffer); + } + else + { + hr = pSample->ConvertToContiguousBuffer(&pBuffer); + } + + if (FAILED(hr)) + { + break; + } + + hr = CheckDeviceState(pbDeviceChanged); + if (FAILED(hr)) + { + break; + } + + RECT rcDest; + ZeroMemory(&rcDest, sizeof(rcDest)); + if (CheckEmptyRect(&rcDest)) + { + hr = S_OK; + break; + } + + MFVideoInterlaceMode unInterlaceMode = (MFVideoInterlaceMode) MFGetAttributeUINT32( pCurrentType, MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive ); + + // + // Check the per-sample attributes + // + if (MFVideoInterlace_MixedInterlaceOrProgressive == unInterlaceMode) + { + BOOL fInterlaced = MFGetAttributeUINT32( pSample, MFSampleExtension_Interlaced, FALSE ); + if ( !fInterlaced ) + { + // Progressive sample + *punInterlaceMode = MFVideoInterlace_Progressive; + } + else + { + BOOL fBottomFirst = MFGetAttributeUINT32( pSample, MFSampleExtension_BottomFieldFirst, FALSE ); + if ( fBottomFirst ) + { + *punInterlaceMode = MFVideoInterlace_FieldInterleavedLowerFirst; + } + else + { + *punInterlaceMode = MFVideoInterlace_FieldInterleavedUpperFirst; + } + } + } + + hr = pBuffer->QueryInterface(__uuidof(IMFDXGIBuffer), (LPVOID*)&pDXGIBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pDXGIBuffer->GetResource(__uuidof(ID3D11Texture2D), (LPVOID*)&pTexture2D); + if (FAILED(hr)) + { + break; + } + + hr = pDXGIBuffer->GetSubresourceIndex(&dwViewIndex); + if (FAILED(hr)) + { + break; + } + + if (m_b3DVideo && 0 != m_vp3DOutput) + { + if (pEVBuffer && MFVideo3DSampleFormat_MultiView == m_vp3DOutput) + { + hr = pEVBuffer->QueryInterface(__uuidof(IMFDXGIBuffer), (LPVOID*)&pEVDXGIBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pEVDXGIBuffer->GetResource(__uuidof(ID3D11Texture2D), (LPVOID*)&pEVTexture2D); + if (FAILED(hr)) + { + break; + } + + hr = pEVDXGIBuffer->GetSubresourceIndex(&dwEVViewIndex); + if (FAILED(hr)) + { + break; + } + } + } + + pTexture2D->GetDevice(&pDeviceInput); + if ((NULL == pDeviceInput) || (pDeviceInput != m_pD3D11Device)) + { + break; + } + + if (m_useXVP) + { + BOOL bInputFrameUsed = FALSE; + + hr = ProcessFrameUsingXVP( pCurrentType, pSample, pTexture2D, rcDest, ppOutputSample, &bInputFrameUsed ); + + if (SUCCEEDED(hr) && !bInputFrameUsed) + { + *pbProcessAgain = TRUE; + } + } + else + { + hr = ProcessFrameUsingD3D11( pTexture2D, pEVTexture2D, dwViewIndex, dwEVViewIndex, rcDest, *punInterlaceMode, ppOutputSample ); + + LONGLONG hnsDuration = 0; + LONGLONG hnsTime = 0; + DWORD dwSampleFlags = 0; + + if (ppOutputSample != NULL && *ppOutputSample != NULL) + { + if (SUCCEEDED(pSample->GetSampleDuration(&hnsDuration))) + { + (*ppOutputSample)->SetSampleDuration(hnsDuration); + } + + if (SUCCEEDED(pSample->GetSampleTime(&hnsTime))) + { + (*ppOutputSample)->SetSampleTime(hnsTime); + } + + if (SUCCEEDED(pSample->GetSampleFlags(&dwSampleFlags))) + { + (*ppOutputSample)->SetSampleFlags(dwSampleFlags); + } + } + } + } + while (FALSE); + + SafeRelease(pTexture2D); + SafeRelease(pDXGIBuffer); + SafeRelease(pEVTexture2D); + SafeRelease(pEVDXGIBuffer); + SafeRelease(pDeviceInput); + SafeRelease(pBuffer); + SafeRelease(pEVBuffer); + + return hr; +} + +HRESULT DX11VideoRenderer::CPresenter::SetCurrentMediaType(IMFMediaType* pMediaType) +{ + HRESULT hr = S_OK; + IMFAttributes* pAttributes = NULL; + + CAutoLock lock(&m_critSec); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + hr = pMediaType->QueryInterface(IID_IMFAttributes, reinterpret_cast(&pAttributes)); + if (FAILED(hr)) + { + break; + } + + HRESULT hr1 = pAttributes->GetUINT32(MF_MT_VIDEO_3D, (UINT32*)&m_b3DVideo); + if (SUCCEEDED(hr1)) + { + hr = pAttributes->GetUINT32(MF_MT_VIDEO_3D_FORMAT, (UINT32*)&m_vp3DOutput); + if (FAILED(hr)) + { + break; + } + } + + //Now Determine Correct Display Resolution + if (SUCCEEDED(hr)) + { + UINT32 parX = 0, parY = 0; + int PARWidth = 0, PARHeight = 0; + MFVideoArea videoArea = {0}; + ZeroMemory(&m_displayRect, sizeof(RECT)); + + if (FAILED(MFGetAttributeSize(pMediaType, MF_MT_PIXEL_ASPECT_RATIO, &parX, &parY))) + { + parX = 1; + parY = 1; + } + + hr = GetVideoDisplayArea(pMediaType, &videoArea); + if (FAILED(hr)) + { + break; + } + + m_displayRect = MFVideoAreaToRect(videoArea); + + PixelAspectToPictureAspect( + videoArea.Area.cx, + videoArea.Area.cy, + parX, + parY, + &PARWidth, + &PARHeight); + + SIZE szVideo = videoArea.Area; + SIZE szPARVideo = {PARWidth, PARHeight}; + AspectRatioCorrectSize(&szVideo, szPARVideo, videoArea.Area, FALSE); + m_uiRealDisplayWidth = szVideo.cx; + m_uiRealDisplayHeight = szVideo.cy; + } + + if (SUCCEEDED(hr) && m_useXVP) + { + // set the input type on the XVP + hr = m_pXVP->SetInputType(0, pMediaType, 0); + if (FAILED(hr)) + { + break; + } + } + } + while (FALSE); + + SafeRelease(pAttributes); + + return hr; +} + +//------------------------------------------------------------------- +// Name: Shutdown +// Description: Releases resources held by the presenter. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::Shutdown(void) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = MF_E_SHUTDOWN; + + m_IsShutdown = TRUE; + + SafeRelease(m_pDXGIManager); + SafeRelease(m_pDXGIFactory2); + SafeRelease(m_pD3D11Device); + SafeRelease(m_pD3DImmediateContext); + SafeRelease(m_pDXGIOutput1); + SafeRelease(m_pSampleAllocatorEx); + SafeRelease(m_pDCompDevice); + SafeRelease(m_pHwndTarget); + SafeRelease(m_pRootVisual); + SafeRelease(m_pXVPControl); + SafeRelease(m_pXVP); + SafeRelease(m_pDX11VideoDevice); + SafeRelease(m_pVideoProcessor); + SafeRelease(m_pVideoProcessorEnum); + SafeRelease(m_pSwapChain1); + + return hr; +} + +/// Private methods + +//+------------------------------------------------------------------------- +// +// Function: AspectRatioCorrectSize +// +// Synopsis: Corrects the supplied size structure so that it becomes the same shape +// as the specified aspect ratio, the correction is always applied in the +// horizontal axis +// +//-------------------------------------------------------------------------- + +void DX11VideoRenderer::CPresenter::AspectRatioCorrectSize( + LPSIZE lpSizeImage, // size to be aspect ratio corrected + const SIZE& sizeAr, // aspect ratio of image + const SIZE& sizeOrig, // original image size + BOOL ScaleXorY // axis to correct in + ) +{ + int cxAR = sizeAr.cx; + int cyAR = sizeAr.cy; + int cxOr = sizeOrig.cx; + int cyOr = sizeOrig.cy; + int sx = lpSizeImage->cx; + int sy = lpSizeImage->cy; + + // MulDiv rounds correctly. + lpSizeImage->cx = MulDiv((sx * cyOr), cxAR, (cyAR * cxOr)); + + if (ScaleXorY && lpSizeImage->cx < cxOr) + { + lpSizeImage->cx = cxOr; + lpSizeImage->cy = MulDiv((sy * cxOr), cyAR, (cxAR * cyOr)); + } +} + +void DX11VideoRenderer::CPresenter::CheckDecodeSwitchRegKey(void) +{ + const TCHAR* lpcszDXSW = TEXT("DXSWSwitch"); + const TCHAR* lpcszInVP = TEXT("XVP"); + const TCHAR* lpcszDComp = TEXT("DComp"); + const TCHAR* lpcszDebugLayer = TEXT("Dbglayer"); + const TCHAR* lpcszREGKEY = TEXT("SOFTWARE\\Microsoft\\Scrunch\\CodecPack\\MSDVD"); + HKEY hk = NULL; + DWORD dwData; + DWORD cbData = sizeof(DWORD); + DWORD cbType; + + if(0 == RegOpenKeyEx(HKEY_CURRENT_USER, lpcszREGKEY, 0, KEY_READ, &hk)) + { + if (0 == RegQueryValueEx(hk, lpcszDXSW, 0, &cbType, (LPBYTE)&dwData, &cbData)) + { + m_DXSWSwitch = dwData; + } + + dwData = 0; + cbData = sizeof(DWORD); + if (0 == RegQueryValueEx(hk, lpcszInVP, 0, &cbType, (LPBYTE)&dwData, &cbData)) + { + m_useXVP = dwData; + } + + dwData = 0; + cbData = sizeof(DWORD); + if (0 == RegQueryValueEx(hk, lpcszDComp, 0, &cbType, (LPBYTE)&dwData, &cbData)) + { + m_useDCompVisual = dwData; + } + + dwData = 0; + cbData = sizeof(DWORD); + if (0 == RegQueryValueEx(hk, lpcszDebugLayer, 0, &cbType, (LPBYTE)&dwData, &cbData)) + { + m_useDebugLayer = dwData; + } + } + + if(NULL != hk) + { + RegCloseKey(hk); + } + + return; +} + +HRESULT DX11VideoRenderer::CPresenter::CheckDeviceState(BOOL* pbDeviceChanged) +{ + if (pbDeviceChanged == NULL) + { + return E_POINTER; + } + + static int deviceStateChecks = 0; + static D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; + + HRESULT hr = SetVideoMonitor(m_hwndVideo); + if (FAILED(hr)) + { + return hr; + } + + if (m_pD3D11Device != NULL) + { + // Lost/hung device. Destroy the device and create a new one. + if (S_FALSE == hr || (m_DXSWSwitch > 0 && deviceStateChecks == m_DXSWSwitch)) + { + if (m_DXSWSwitch > 0 && deviceStateChecks == m_DXSWSwitch) + { + (driverType == D3D_DRIVER_TYPE_HARDWARE) ? driverType = D3D_DRIVER_TYPE_WARP : driverType = D3D_DRIVER_TYPE_HARDWARE; + } + + hr = CreateDXGIManagerAndDevice(driverType); + if (FAILED(hr)) + { + return hr; + } + + *pbDeviceChanged = TRUE; + + SafeRelease(m_pDX11VideoDevice); + SafeRelease(m_pVideoProcessorEnum); + SafeRelease(m_pVideoProcessor); + SafeRelease(m_pSwapChain1); + + deviceStateChecks = 0; + } + deviceStateChecks++; + } + + return hr; +} + +BOOL DX11VideoRenderer::CPresenter::CheckEmptyRect(RECT* pDst) +{ + GetClientRect(m_hwndVideo, pDst); + + return IsRectEmpty(pDst); +} + +HRESULT DX11VideoRenderer::CPresenter::CheckShutdown(void) const +{ + if (m_IsShutdown) + { + return MF_E_SHUTDOWN; + } + else + { + return S_OK; + } +} + +HRESULT DX11VideoRenderer::CPresenter::CreateDCompDeviceAndVisual(void) +{ + HRESULT hr = S_OK; + IDXGIDevice* pDXGIDevice = NULL; + + do + { + hr = m_pD3D11Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&pDXGIDevice)); + if (FAILED(hr)) + { + break; + } + + hr = DCompositionCreateDevice(pDXGIDevice, __uuidof(IDCompositionDevice), reinterpret_cast(&m_pDCompDevice)); + if (FAILED(hr)) + { + break; + } + + hr = m_pDCompDevice->CreateTargetForHwnd(m_hwndVideo, TRUE, &m_pHwndTarget); + if (FAILED(hr)) + { + break; + } + + hr = m_pDCompDevice->CreateVisual(reinterpret_cast(&m_pRootVisual)); + if (FAILED(hr)) + { + break; + } + + hr = m_pHwndTarget->SetRoot(m_pRootVisual); + if (FAILED(hr)) + { + break; + } + } + while(FALSE); + + SafeRelease(pDXGIDevice); + + return hr; +} + +//------------------------------------------------------------------- +// Name: CreateDXGIManagerAndDevice +// Description: Creates D3D11 device and manager. +// +// Note: This method is called once when SetVideoWindow is called using +// IDX11VideoRenderer. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::CreateDXGIManagerAndDevice(D3D_DRIVER_TYPE DriverType) +{ + HRESULT hr = S_OK; + + IDXGIAdapter* pTempAdapter = NULL; + ID3D10Multithread* pMultiThread = NULL; + IDXGIDevice1* pDXGIDev = NULL; + IDXGIAdapter1* pAdapter = NULL; + IDXGIOutput* pDXGIOutput = NULL; + + D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; + D3D_FEATURE_LEVEL featureLevel; + UINT resetToken; + + do + { + SafeRelease(m_pD3D11Device); + if (D3D_DRIVER_TYPE_WARP == DriverType) + { + ID3D11Device* pD3D11Device = NULL; + + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, m_useDebugLayer, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, &pD3D11Device, &featureLevel, NULL); + + if (SUCCEEDED(hr)) + { + m_pD3D11Device = new CPrivate_ID3D11Device(pD3D11Device); + if (NULL == m_pD3D11Device) + { + E_OUTOFMEMORY; + } + } + // SafeRelease(pD3D11Device); + } + else + { + for (DWORD dwCount = 0; dwCount < ARRAYSIZE(featureLevels); dwCount++) + { + hr = D3D11CreateDevice(NULL, DriverType, NULL, m_useDebugLayer, &featureLevels[dwCount], 1, D3D11_SDK_VERSION, &m_pD3D11Device, &featureLevel, NULL); + if (SUCCEEDED(hr)) + { + ID3D11VideoDevice* pDX11VideoDevice = NULL; + hr = m_pD3D11Device->QueryInterface(__uuidof(ID3D11VideoDevice), (void**)&pDX11VideoDevice); + SafeRelease(pDX11VideoDevice); + + if (SUCCEEDED(hr)) + { + break; + } + SafeRelease(m_pD3D11Device); + } + } + } + + if (FAILED(hr)) + { + break; + } + + if (NULL == m_pDXGIManager) + { + hr = MFCreateDXGIDeviceManager(&resetToken, &m_pDXGIManager); + if (FAILED(hr)) + { + break; + } + m_DeviceResetToken = resetToken; + } + + hr = m_pDXGIManager->ResetDevice(m_pD3D11Device, m_DeviceResetToken); + if (FAILED(hr)) + { + break; + } + + SafeRelease(m_pD3DImmediateContext); + m_pD3D11Device->GetImmediateContext(&m_pD3DImmediateContext); + + // Need to explitly set the multithreaded mode for this device + hr = m_pD3DImmediateContext->QueryInterface(__uuidof(ID3D10Multithread), (void**)&pMultiThread); + if (FAILED(hr)) + { + break; + } + + pMultiThread->SetMultithreadProtected(TRUE); + + hr = m_pD3D11Device->QueryInterface( __uuidof( IDXGIDevice1 ), ( LPVOID* )&pDXGIDev ); + if (FAILED(hr)) + { + break; + } + + hr = pDXGIDev->GetAdapter(&pTempAdapter); + if (FAILED(hr)) + { + break; + } + + hr = pTempAdapter->QueryInterface( __uuidof( IDXGIAdapter1 ), (LPVOID*) &pAdapter ) ; + if (FAILED(hr)) + { + break; + } + + SafeRelease(m_pDXGIFactory2); + hr = pAdapter->GetParent( __uuidof( IDXGIFactory2 ), (LPVOID*) &m_pDXGIFactory2 ); + if (FAILED(hr)) + { + break; + } + + hr = pAdapter->EnumOutputs(0, &pDXGIOutput); + if (FAILED(hr)) + { + break; + } + + SafeRelease(m_pDXGIOutput1); + hr = pDXGIOutput->QueryInterface( __uuidof(IDXGIOutput1), (LPVOID*) &m_pDXGIOutput1 ); + if (FAILED(hr)) + { + break; + } + + if (m_useDCompVisual) + { + hr = CreateDCompDeviceAndVisual(); + if (FAILED(hr)) + { + break; + } + } + } + while(FALSE); + + SafeRelease(pTempAdapter); + SafeRelease(pMultiThread); + SafeRelease(pDXGIDev); + SafeRelease(pAdapter); + SafeRelease(pDXGIOutput); + + return hr; +} + +//------------------------------------------------------------------- +// Name: CreateXVP +// Description: Creates a new instance of the XVP MFT. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::CreateXVP(void) +{ + HRESULT hr = S_OK; + IMFAttributes* pAttributes = NULL; + + do + { + hr = CoCreateInstance(CLSID_VideoProcessorMFT, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (void**)&m_pXVP); + if (FAILED(hr)) + { + break; + } + + hr = m_pXVP->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, ULONG_PTR(m_pDXGIManager)); + if (FAILED(hr)) + { + break; + } + + // Tell the XVP that we are the swapchain allocator + hr = m_pXVP->GetAttributes(&pAttributes); + if (FAILED(hr)) + { + break; + } + + hr = pAttributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); + if (FAILED(hr)) + { + break; + } + + hr = m_pXVP->QueryInterface(IID_PPV_ARGS(&m_pXVPControl)); + if (FAILED(hr)) + { + break; + } + } + while (FALSE); + + SafeRelease(pAttributes); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: FindBOBProcessorIndex +// +// Synopsis: Find the BOB video processor. BOB does not require any +// reference frames and can be used with both Progressive +// and interlaced video +// +//-------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::FindBOBProcessorIndex(DWORD* pIndex) +{ + HRESULT hr = S_OK; + D3D11_VIDEO_PROCESSOR_CAPS caps = {}; + D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS convCaps = {}; + + *pIndex = 0; + hr = m_pVideoProcessorEnum->GetVideoProcessorCaps(&caps); + if (FAILED(hr)) + { + return hr; + } + for (DWORD i = 0; i < caps.RateConversionCapsCount; i++) + { + hr = m_pVideoProcessorEnum->GetVideoProcessorRateConversionCaps(i, &convCaps); + if (FAILED(hr)) + { + return hr; + } + + // Check the caps to see which deinterlacer is supported + if ((convCaps.ProcessorCaps & D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB) != 0) + { + *pIndex = i; + return hr; + } + } + + return E_FAIL; +} + +//------------------------------------------------------------------- +// Name: GetVideoDisplayArea +// Description: get the display area from the media type. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::GetVideoDisplayArea(IMFMediaType* pType, MFVideoArea* pArea) +{ + HRESULT hr = S_OK; + BOOL bPanScan = FALSE; + UINT32 uimageWidthInPixels = 0, uimageHeightInPixels = 0; + + hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &uimageWidthInPixels, &uimageHeightInPixels); + if (FAILED(hr)) + { + return hr; + } + + if (uimageWidthInPixels != m_imageWidthInPixels || uimageHeightInPixels != m_imageHeightInPixels) + { + SafeRelease(m_pVideoProcessorEnum); + SafeRelease(m_pVideoProcessor); + SafeRelease(m_pSwapChain1); + } + + m_imageWidthInPixels = uimageWidthInPixels; + m_imageHeightInPixels = uimageHeightInPixels; + + bPanScan = MFGetAttributeUINT32(pType, MF_MT_PAN_SCAN_ENABLED, FALSE); + + // In pan/scan mode, try to get the pan/scan region. + if (bPanScan) + { + hr = pType->GetBlob( + MF_MT_PAN_SCAN_APERTURE, + (UINT8*)pArea, + sizeof(MFVideoArea), + NULL + ); + } + + // If not in pan/scan mode, or the pan/scan region is not set, + // get the minimimum display aperture. + + if (!bPanScan || hr == MF_E_ATTRIBUTENOTFOUND) + { + hr = pType->GetBlob( + MF_MT_MINIMUM_DISPLAY_APERTURE, + (UINT8*)pArea, + sizeof(MFVideoArea), + NULL + ); + + if (hr == MF_E_ATTRIBUTENOTFOUND) + { + // Minimum display aperture is not set. + + // For backward compatibility with some components, + // check for a geometric aperture. + + hr = pType->GetBlob( + MF_MT_GEOMETRIC_APERTURE, + (UINT8*)pArea, + sizeof(MFVideoArea), + NULL + ); + } + + // Default: Use the entire video area. + + if (hr == MF_E_ATTRIBUTENOTFOUND) + { + *pArea = MakeArea(0.0, 0.0, m_imageWidthInPixels, m_imageHeightInPixels); + hr = S_OK; + } + } + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Function: LetterBoxDstRectPixelAspectToPictureAspect +// +// Synopsis: +// +// Takes a src rectangle and constructs the largest possible destination +// rectangle within the specifed destination rectangle such that +// the video maintains its current shape. +// +// This function assumes that pels are the same shape within both the src +// and dst rectangles. +// +//-------------------------------------------------------------------------- + +void DX11VideoRenderer::CPresenter::LetterBoxDstRect( + LPRECT lprcLBDst, // output letterboxed rectangle + const RECT& rcSrc, // input source rectangle + const RECT& rcDst // input destination rectangle + ) +{ + // figure out src/dest scale ratios + int iSrcWidth = rcSrc.right - rcSrc.left; + int iSrcHeight = rcSrc.bottom - rcSrc.top; + + int iDstWidth = rcDst.right - rcDst.left; + int iDstHeight = rcDst.bottom - rcDst.top; + + int iDstLBWidth = 0; + int iDstLBHeight = 0; + + // + // work out if we are Column or Row letter boxing + // + + if (MulDiv(iSrcWidth, iDstHeight, iSrcHeight) <= iDstWidth) + { + // + // column letter boxing - we add border color bars to the + // left and right of the video image to fill the destination + // rectangle. + // + iDstLBWidth = MulDiv(iDstHeight, iSrcWidth, iSrcHeight); + iDstLBHeight = iDstHeight; + } + else + { + // + // row letter boxing - we add border color bars to the top + // and bottom of the video image to fill the destination + // rectangle + // + iDstLBWidth = iDstWidth; + iDstLBHeight = MulDiv(iDstWidth, iSrcHeight, iSrcWidth); + } + + // + // now create a centered LB rectangle within the current destination rect + // + lprcLBDst->left = rcDst.left + ((iDstWidth - iDstLBWidth) / 2); + lprcLBDst->right = lprcLBDst->left + iDstLBWidth; + + lprcLBDst->top = rcDst.top + ((iDstHeight - iDstLBHeight) / 2); + lprcLBDst->bottom = lprcLBDst->top + iDstLBHeight; +} + +//+------------------------------------------------------------------------- +// +// Function: PixelAspectToPictureAspect +// +// Synopsis: Converts a pixel aspect ratio to a picture aspect ratio +// +//-------------------------------------------------------------------------- + +void DX11VideoRenderer::CPresenter::PixelAspectToPictureAspect( + int Width, + int Height, + int PixelAspectX, + int PixelAspectY, + int* pPictureAspectX, + int* pPictureAspectY + ) +{ + // + // sanity check - if any inputs are 0, return 0 + // + if (PixelAspectX == 0 || PixelAspectY == 0 || Width == 0 || Height == 0) + { + *pPictureAspectX = 0; + *pPictureAspectY = 0; + return; + } + + // + // start by reducing both ratios to lowest terms + // + ReduceToLowestTerms(Width, Height, &Width, &Height); + ReduceToLowestTerms(PixelAspectX, PixelAspectY, &PixelAspectX, &PixelAspectY); + + // + // Make sure that none of the values are larger than 2^16, so we don't + // overflow on the last operation. This reduces the accuracy somewhat, + // but it's a "hail mary" for incredibly strange aspect ratios that don't + // exist in practical usage. + // + while (Width > 0xFFFF || Height > 0xFFFF) + { + Width >>= 1; + Height >>= 1; + } + + while (PixelAspectX > 0xFFFF || PixelAspectY > 0xFFFF) + { + PixelAspectX >>= 1; + PixelAspectY >>= 1; + } + + ReduceToLowestTerms( + PixelAspectX * Width, + PixelAspectY * Height, + pPictureAspectX, + pPictureAspectY + ); +} + +HRESULT DX11VideoRenderer::CPresenter::ProcessFrameUsingD3D11( ID3D11Texture2D* pLeftTexture2D, ID3D11Texture2D* pRightTexture2D, UINT dwLeftViewIndex, UINT dwRightViewIndex, RECT rcDest, UINT32 unInterlaceMode, IMFSample** ppVideoOutFrame ) +{ + HRESULT hr = S_OK; + ID3D11VideoContext* pVideoContext = NULL; + ID3D11VideoProcessorInputView* pLeftInputView = NULL; + ID3D11VideoProcessorInputView* pRightInputView = NULL; + ID3D11VideoProcessorOutputView* pOutputView = NULL; + ID3D11Texture2D* pDXGIBackBuffer = NULL; + ID3D11RenderTargetView* pRTView = NULL; + IMFSample* pRTSample = NULL; + IMFMediaBuffer* pBuffer = NULL; + D3D11_VIDEO_PROCESSOR_CAPS vpCaps = {0}; + LARGE_INTEGER lpcStart,lpcEnd; + + do + { + if (!m_pDX11VideoDevice) + { + hr = m_pD3D11Device->QueryInterface(__uuidof(ID3D11VideoDevice), (void**)&m_pDX11VideoDevice); + if (FAILED(hr)) + { + break; + } + } + + hr = m_pD3DImmediateContext->QueryInterface(__uuidof( ID3D11VideoContext ), (void**)&pVideoContext); + if (FAILED(hr)) + { + break; + } + + // remember the original rectangles + RECT TRectOld = m_rcDstApp; + RECT SRectOld = m_rcSrcApp; + UpdateRectangles(&TRectOld, &SRectOld); + + //Update destination rect with current client rect + m_rcDstApp = rcDest; + + D3D11_TEXTURE2D_DESC surfaceDesc; + pLeftTexture2D->GetDesc(&surfaceDesc); + + if (!m_pVideoProcessorEnum || !m_pVideoProcessor || m_imageWidthInPixels != surfaceDesc.Width || m_imageHeightInPixels != surfaceDesc.Height) + { + SafeRelease(m_pVideoProcessorEnum); + SafeRelease(m_pVideoProcessor); + + m_imageWidthInPixels = surfaceDesc.Width; + m_imageHeightInPixels = surfaceDesc.Height; + + D3D11_VIDEO_PROCESSOR_CONTENT_DESC ContentDesc; + ZeroMemory( &ContentDesc, sizeof( ContentDesc ) ); + ContentDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST; + ContentDesc.InputWidth = surfaceDesc.Width; + ContentDesc.InputHeight = surfaceDesc.Height; + ContentDesc.OutputWidth = surfaceDesc.Width; + ContentDesc.OutputHeight = surfaceDesc.Height; + ContentDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; + + hr = m_pDX11VideoDevice->CreateVideoProcessorEnumerator(&ContentDesc, &m_pVideoProcessorEnum); + if (FAILED(hr)) + { + break; + } + + UINT uiFlags; + DXGI_FORMAT VP_Output_Format = DXGI_FORMAT_B8G8R8A8_UNORM; + + hr = m_pVideoProcessorEnum->CheckVideoProcessorFormat(VP_Output_Format, &uiFlags); + if (FAILED(hr) || 0 == (uiFlags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT)) + { + hr = MF_E_UNSUPPORTED_D3D_TYPE; + break; + } + + m_rcSrcApp.left = 0; + m_rcSrcApp.top = 0; + m_rcSrcApp.right = m_uiRealDisplayWidth; + m_rcSrcApp.bottom = m_uiRealDisplayHeight; + + DWORD index; + hr = FindBOBProcessorIndex(&index); + if (FAILED(hr)) + { + break; + } + + hr = m_pDX11VideoDevice->CreateVideoProcessor(m_pVideoProcessorEnum, index, &m_pVideoProcessor); + if (FAILED(hr)) + { + break; + } + + if (m_b3DVideo) + { + hr = m_pVideoProcessorEnum->GetVideoProcessorCaps(&vpCaps); + if (FAILED(hr)) + { + break; + } + + if (vpCaps.FeatureCaps & D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_STEREO) + { + m_bStereoEnabled = TRUE; + } + + DXGI_MODE_DESC1 modeFilter = { 0 }; + modeFilter.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + modeFilter.Width = surfaceDesc.Width; + modeFilter.Height = surfaceDesc.Height; + modeFilter.Stereo = m_bStereoEnabled; + + DXGI_MODE_DESC1 matchedMode; + if (m_bFullScreenState) + { + hr = m_pDXGIOutput1->FindClosestMatchingMode1(&modeFilter, &matchedMode, m_pD3D11Device); + if (FAILED(hr)) + { + break; + } + } + } + } + + // now create the input and output media types - these need to reflect + // the src and destination rectangles that we have been given. + RECT TRect = m_rcDstApp; + RECT SRect = m_rcSrcApp; + UpdateRectangles(&TRect, &SRect); + + const BOOL fDestRectChanged = !EqualRect(&TRect, &TRectOld); + + if (!m_pSwapChain1 || fDestRectChanged) + { + hr = UpdateDXGISwapChain(); + if (FAILED(hr)) + { + break; + } + } + + m_bCanProcessNextSample = FALSE; + + // Get Backbuffer + hr = m_pSwapChain1->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pDXGIBackBuffer); + if (FAILED(hr)) + { + break; + } + + // create the output media sample + hr = MFCreateSample(&pRTSample); + if (FAILED(hr)) + { + break; + } + + hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), pDXGIBackBuffer, 0, FALSE, &pBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pRTSample->AddBuffer(pBuffer); + if (FAILED(hr)) + { + break; + } + + if (m_b3DVideo && 0 != m_vp3DOutput) + { + SafeRelease(pBuffer); + + hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), pDXGIBackBuffer, 1, FALSE, &pBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pRTSample->AddBuffer(pBuffer); + if (FAILED(hr)) + { + break; + } + } + + QueryPerformanceCounter(&lpcStart); + + QueryPerformanceCounter(&lpcEnd); + + // + // Create Output View of Output Surfaces. + // + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc; + ZeroMemory( &OutputViewDesc, sizeof( OutputViewDesc ) ); + if (m_b3DVideo && m_bStereoEnabled) + { + OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2DARRAY; + } + else + { + OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; + } + OutputViewDesc.Texture2D.MipSlice = 0; + OutputViewDesc.Texture2DArray.MipSlice = 0; + OutputViewDesc.Texture2DArray.FirstArraySlice = 0; + if (m_b3DVideo && 0 != m_vp3DOutput) + { + OutputViewDesc.Texture2DArray.ArraySize = 2; // STEREO + } + + QueryPerformanceCounter(&lpcStart); + + hr = m_pDX11VideoDevice->CreateVideoProcessorOutputView(pDXGIBackBuffer, m_pVideoProcessorEnum, &OutputViewDesc, &pOutputView); + if (FAILED(hr)) + { + break; + } + + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC InputLeftViewDesc; + ZeroMemory( &InputLeftViewDesc, sizeof( InputLeftViewDesc ) ); + InputLeftViewDesc.FourCC = 0; + InputLeftViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; + InputLeftViewDesc.Texture2D.MipSlice = 0; + InputLeftViewDesc.Texture2D.ArraySlice = dwLeftViewIndex; + + hr = m_pDX11VideoDevice->CreateVideoProcessorInputView(pLeftTexture2D, m_pVideoProcessorEnum, &InputLeftViewDesc, &pLeftInputView); + if (FAILED(hr)) + { + break; + } + + if (m_b3DVideo && MFVideo3DSampleFormat_MultiView == m_vp3DOutput && pRightTexture2D) + { + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC InputRightViewDesc; + ZeroMemory( &InputRightViewDesc, sizeof( InputRightViewDesc ) ); + InputRightViewDesc.FourCC = 0; + InputRightViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; + InputRightViewDesc.Texture2D.MipSlice = 0; + InputRightViewDesc.Texture2D.ArraySlice = dwRightViewIndex; + + hr = m_pDX11VideoDevice->CreateVideoProcessorInputView(pRightTexture2D, m_pVideoProcessorEnum, &InputRightViewDesc, &pRightInputView); + if (FAILED(hr)) + { + break; + } + } + QueryPerformanceCounter(&lpcEnd); + + QueryPerformanceCounter(&lpcStart); + + SetVideoContextParameters(pVideoContext, &SRect, &TRect, unInterlaceMode); + + // Enable/Disable Stereo + if (m_b3DVideo) + { + pVideoContext->VideoProcessorSetOutputStereoMode(m_pVideoProcessor, m_bStereoEnabled); + + D3D11_VIDEO_PROCESSOR_STEREO_FORMAT vpStereoFormat = D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_SEPARATE; + if (MFVideo3DSampleFormat_Packed_LeftRight == m_vp3DOutput) + { + vpStereoFormat = D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_HORIZONTAL; + } + else if (MFVideo3DSampleFormat_Packed_TopBottom == m_vp3DOutput) + { + vpStereoFormat = D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_VERTICAL; + } + + pVideoContext->VideoProcessorSetStreamStereoFormat(m_pVideoProcessor, + 0, m_bStereoEnabled, vpStereoFormat, TRUE, TRUE, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_NONE, 0); + } + + QueryPerformanceCounter(&lpcEnd); + + QueryPerformanceCounter(&lpcStart); + + D3D11_VIDEO_PROCESSOR_STREAM StreamData; + ZeroMemory( &StreamData, sizeof( StreamData ) ); + StreamData.Enable = TRUE; + StreamData.OutputIndex = 0; + StreamData.InputFrameOrField = 0; + StreamData.PastFrames = 0; + StreamData.FutureFrames = 0; + StreamData.ppPastSurfaces = NULL; + StreamData.ppFutureSurfaces = NULL; + StreamData.pInputSurface = pLeftInputView; + StreamData.ppPastSurfacesRight = NULL; + StreamData.ppFutureSurfacesRight = NULL; + + if (m_b3DVideo && MFVideo3DSampleFormat_MultiView == m_vp3DOutput && pRightTexture2D) + { + StreamData.pInputSurfaceRight = pRightInputView; + } + + hr = pVideoContext->VideoProcessorBlt(m_pVideoProcessor, pOutputView, 0, 1, &StreamData ); + if (FAILED(hr)) + { + break; + } + QueryPerformanceCounter(&lpcEnd); + + if (ppVideoOutFrame != NULL) + { + *ppVideoOutFrame = pRTSample; + (*ppVideoOutFrame)->AddRef(); + } + } + while (FALSE); + + SafeRelease(pBuffer); + SafeRelease(pRTSample); + SafeRelease(pDXGIBackBuffer); + SafeRelease(pOutputView); + SafeRelease(pLeftInputView); + SafeRelease(pRightInputView); + SafeRelease(pVideoContext); + + return hr; +} + +HRESULT DX11VideoRenderer::CPresenter::ProcessFrameUsingXVP( IMFMediaType* pCurrentType, IMFSample* pVideoFrame, ID3D11Texture2D* pTexture2D, RECT rcDest, IMFSample** ppVideoOutFrame, BOOL* pbInputFrameUsed ) +{ + HRESULT hr = S_OK; + ID3D11VideoContext* pVideoContext = NULL; + ID3D11Texture2D* pDXGIBackBuffer = NULL; + IMFSample* pRTSample = NULL; + IMFMediaBuffer* pBuffer = NULL; + IMFAttributes* pAttributes = NULL; + D3D11_VIDEO_PROCESSOR_CAPS vpCaps = {0}; + + do + { + if (!m_pDX11VideoDevice) + { + hr = m_pD3D11Device->QueryInterface(__uuidof(ID3D11VideoDevice), (void**)&m_pDX11VideoDevice); + if (FAILED(hr)) + { + break; + } + } + + hr = m_pD3DImmediateContext->QueryInterface(__uuidof( ID3D11VideoContext ), (void**)&pVideoContext); + if (FAILED(hr)) + { + break; + } + + // remember the original rectangles + RECT TRectOld = m_rcDstApp; + RECT SRectOld = m_rcSrcApp; + UpdateRectangles(&TRectOld, &SRectOld); + + //Update destination rect with current client rect + m_rcDstApp = rcDest; + + D3D11_TEXTURE2D_DESC surfaceDesc; + pTexture2D->GetDesc(&surfaceDesc); + + BOOL fTypeChanged = FALSE; + if (!m_pVideoProcessorEnum || !m_pSwapChain1 || m_imageWidthInPixels != surfaceDesc.Width || m_imageHeightInPixels != surfaceDesc.Height) + { + SafeRelease(m_pVideoProcessorEnum); + SafeRelease(m_pSwapChain1); + + m_imageWidthInPixels = surfaceDesc.Width; + m_imageHeightInPixels = surfaceDesc.Height; + fTypeChanged = TRUE; + + D3D11_VIDEO_PROCESSOR_CONTENT_DESC ContentDesc; + ZeroMemory( &ContentDesc, sizeof( ContentDesc ) ); + ContentDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST; + ContentDesc.InputWidth = surfaceDesc.Width; + ContentDesc.InputHeight = surfaceDesc.Height; + ContentDesc.OutputWidth = surfaceDesc.Width; + ContentDesc.OutputHeight = surfaceDesc.Height; + ContentDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; + + hr = m_pDX11VideoDevice->CreateVideoProcessorEnumerator(&ContentDesc, &m_pVideoProcessorEnum); + if (FAILED(hr)) + { + break; + } + + m_rcSrcApp.left = 0; + m_rcSrcApp.top = 0; + m_rcSrcApp.right = m_uiRealDisplayWidth; + m_rcSrcApp.bottom = m_uiRealDisplayHeight; + + if (m_b3DVideo) + { + hr = m_pVideoProcessorEnum->GetVideoProcessorCaps(&vpCaps); + if (FAILED(hr)) + { + break; + } + + if (vpCaps.FeatureCaps & D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_STEREO) + { + m_bStereoEnabled = TRUE; + } + + DXGI_MODE_DESC1 modeFilter = { 0 }; + modeFilter.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + modeFilter.Width = surfaceDesc.Width; + modeFilter.Height = surfaceDesc.Height; + modeFilter.Stereo = m_bStereoEnabled; + + DXGI_MODE_DESC1 matchedMode; + if (m_bFullScreenState) + { + hr = m_pDXGIOutput1->FindClosestMatchingMode1(&modeFilter, &matchedMode, m_pD3D11Device); + if (FAILED(hr)) + { + break; + } + } + + hr = m_pXVP->GetAttributes(&pAttributes); + if (FAILED(hr)) + { + break; + } + + hr = pAttributes->SetUINT32(MF_ENABLE_3DVIDEO_OUTPUT, (0 != m_vp3DOutput) ? MF3DVideoOutputType_Stereo : MF3DVideoOutputType_BaseView); + if (FAILED(hr)) + { + break; + } + } + } + + // now create the input and output media types - these need to reflect + // the src and destination rectangles that we have been given. + RECT TRect = m_rcDstApp; + RECT SRect = m_rcSrcApp; + UpdateRectangles(&TRect, &SRect); + + const BOOL fDestRectChanged = !EqualRect(&TRect, &TRectOld); + const BOOL fSrcRectChanged = !EqualRect(&SRect, &SRectOld); + + if (!m_pSwapChain1 || fDestRectChanged) + { + hr = UpdateDXGISwapChain(); + if (FAILED(hr)) + { + break; + } + } + + if (fTypeChanged || fSrcRectChanged || fDestRectChanged) + { + // stop streaming to avoid multiple start\stop calls internally in XVP + hr = m_pXVP->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0); + if (FAILED(hr)) + { + break; + } + + if (fTypeChanged) + { + hr = SetXVPOutputMediaType(pCurrentType, DXGI_FORMAT_B8G8R8A8_UNORM); + if (FAILED(hr)) + { + break; + } + } + + if (fDestRectChanged) + { + hr = m_pXVPControl->SetDestinationRectangle(&m_rcDstApp); + if (FAILED(hr)) + { + break; + } + } + + if (fSrcRectChanged) + { + hr = m_pXVPControl->SetSourceRectangle(&SRect); + if (FAILED(hr)) + { + break; + } + } + + hr = m_pXVP->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); + if (FAILED(hr)) + { + break; + } + } + + m_bCanProcessNextSample = FALSE; + + // Get Backbuffer + hr = m_pSwapChain1->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pDXGIBackBuffer); + if (FAILED(hr)) + { + break; + } + + // create the output media sample + hr = MFCreateSample(&pRTSample); + if (FAILED(hr)) + { + break; + } + + hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), pDXGIBackBuffer, 0, FALSE, &pBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pRTSample->AddBuffer(pBuffer); + if (FAILED(hr)) + { + break; + } + + if (m_b3DVideo && 0 != m_vp3DOutput) + { + SafeRelease(pBuffer); + + hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), pDXGIBackBuffer, 1, FALSE, &pBuffer); + if (FAILED(hr)) + { + break; + } + + hr = pRTSample->AddBuffer(pBuffer); + if (FAILED(hr)) + { + break; + } + } + + DWORD dwStatus = 0; + MFT_OUTPUT_DATA_BUFFER outputDataBuffer = {}; + outputDataBuffer.pSample = pRTSample; + hr = m_pXVP->ProcessOutput(0, 1, &outputDataBuffer, &dwStatus); + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + { + //call process input on the MFT to deliver the YUV video sample + // and the call process output to extract of newly processed frame + hr = m_pXVP->ProcessInput(0, pVideoFrame, 0); + if (FAILED(hr)) + { + break; + } + + *pbInputFrameUsed = TRUE; + + hr = m_pXVP->ProcessOutput(0, 1, &outputDataBuffer, &dwStatus); + if (FAILED(hr)) + { + break; + } + } + else + { + *pbInputFrameUsed = FALSE; + } + + if (ppVideoOutFrame != NULL) + { + *ppVideoOutFrame = pRTSample; + (*ppVideoOutFrame)->AddRef(); + } + } + while (FALSE); + + SafeRelease(pAttributes); + SafeRelease(pBuffer); + SafeRelease(pRTSample); + SafeRelease(pDXGIBackBuffer); + SafeRelease(pVideoContext); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Function: ReduceToLowestTerms +// +// Synopsis: reduces a numerator and denominator pair to their lowest terms +// +//-------------------------------------------------------------------------- + +void DX11VideoRenderer::CPresenter::ReduceToLowestTerms( + int NumeratorIn, + int DenominatorIn, + int* pNumeratorOut, + int* pDenominatorOut + ) +{ + int GCD = gcd(NumeratorIn, DenominatorIn); + + *pNumeratorOut = NumeratorIn / GCD; + *pDenominatorOut = DenominatorIn / GCD; +} + +HRESULT DX11VideoRenderer::CPresenter::SetMonitor(UINT adapterID) +{ + HRESULT hr = S_OK; + DWORD dwMatchID = 0; + + CAutoLock lock(&m_critSec); + + do + { + hr = m_pMonitors->MatchGUID(adapterID, &dwMatchID); + if (FAILED(hr)) + { + break; + } + + if (hr == S_FALSE) + { + hr = E_INVALIDARG; + break; + } + + m_lpCurrMon = &(*m_pMonitors)[dwMatchID]; + m_ConnectionGUID = adapterID; + } + while (FALSE); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: SetVideoContextParameters +// +// Synopsis: Updates the various parameters used for VpBlt call +// +//-------------------------------------------------------------------------- + +void DX11VideoRenderer::CPresenter::SetVideoContextParameters(ID3D11VideoContext* pVideoContext, const RECT* pSRect, const RECT* pTRect, UINT32 unInterlaceMode) +{ + D3D11_VIDEO_FRAME_FORMAT FrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE; + if ( MFVideoInterlace_FieldInterleavedUpperFirst == unInterlaceMode || MFVideoInterlace_FieldSingleUpper == unInterlaceMode || MFVideoInterlace_MixedInterlaceOrProgressive == unInterlaceMode ) + { + FrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST; + } + else if ( MFVideoInterlace_FieldInterleavedLowerFirst == unInterlaceMode || MFVideoInterlace_FieldSingleLower == unInterlaceMode ) + { + FrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST; + } + + // input format + pVideoContext->VideoProcessorSetStreamFrameFormat(m_pVideoProcessor, 0, FrameFormat); + + // Output rate (repeat frames) + pVideoContext->VideoProcessorSetStreamOutputRate(m_pVideoProcessor, 0, D3D11_VIDEO_PROCESSOR_OUTPUT_RATE_NORMAL, TRUE, NULL); + + // Source rect + pVideoContext->VideoProcessorSetStreamSourceRect(m_pVideoProcessor, 0, TRUE, pSRect); + + // Stream dest rect + pVideoContext->VideoProcessorSetStreamDestRect(m_pVideoProcessor, 0, TRUE, pTRect); + + pVideoContext->VideoProcessorSetOutputTargetRect(m_pVideoProcessor, TRUE, &m_rcDstApp); + + // Stream color space + D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace = {}; + colorSpace.YCbCr_xvYCC = 1; + pVideoContext->VideoProcessorSetStreamColorSpace(m_pVideoProcessor, 0, &colorSpace); + + // Output color space + pVideoContext->VideoProcessorSetOutputColorSpace(m_pVideoProcessor, &colorSpace); + + // Output background color (black) + D3D11_VIDEO_COLOR backgroundColor = {}; + backgroundColor.RGBA.A = 1.0F; + backgroundColor.RGBA.R = 1.0F * static_cast(GetRValue(0)) / 255.0F; + backgroundColor.RGBA.G = 1.0F * static_cast(GetGValue(0)) / 255.0F; + backgroundColor.RGBA.B = 1.0F * static_cast(GetBValue(0)) / 255.0F; + + pVideoContext->VideoProcessorSetOutputBackgroundColor(m_pVideoProcessor, FALSE, &backgroundColor); +} + +HRESULT DX11VideoRenderer::CPresenter::SetVideoMonitor(HWND hwndVideo) +{ + HRESULT hr = S_OK; + CAMDDrawMonitorInfo* pMonInfo = NULL; + HMONITOR hMon = NULL; + + if (!m_pMonitors) + { + return E_UNEXPECTED; + } + + hMon = MonitorFromWindow(hwndVideo, MONITOR_DEFAULTTONULL); + + do + { + if (NULL != hMon) + { + m_pMonitors->TerminateDisplaySystem(); + m_lpCurrMon = NULL; + + hr = m_pMonitors->InitializeDisplaySystem(hwndVideo); + if (FAILED(hr)) + { + break; + } + + pMonInfo = m_pMonitors->FindMonitor(hMon); + if (NULL != pMonInfo && pMonInfo->uDevID != m_ConnectionGUID) + { + hr = SetMonitor(pMonInfo->uDevID); + if (FAILED(hr)) + { + break; + } + hr = S_FALSE; + } + } + else + { + hr = E_POINTER; + break; + } + } + while(FALSE); + + return hr; +} + +//------------------------------------------------------------------- +// Name: SetXVPOutputMediaType +// Description: Tells the XVP about the size of the destination surface +// and where within the surface we should be writing. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CPresenter::SetXVPOutputMediaType(IMFMediaType* pType, DXGI_FORMAT vpOutputFormat) +{ + HRESULT hr = S_OK; + IMFVideoMediaType* pMTOutput = NULL; + MFVIDEOFORMAT mfvf = {}; + + if (SUCCEEDED(hr)) + { + hr = MFInitVideoFormat_RGB( + &mfvf, + m_rcDstApp.right, + m_rcDstApp.bottom, + MFMapDXGIFormatToDX9Format(vpOutputFormat)); + } + + if (SUCCEEDED(hr)) + { + hr = MFCreateVideoMediaType(&mfvf, &pMTOutput); + } + + if (SUCCEEDED(hr)) + { + hr = m_pXVP->SetOutputType(0, pMTOutput, 0); + } + + SafeRelease(pMTOutput); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: UpdateDXGISwapChain +// +// Synopsis: Creates SwapChain for HWND or DComp or Resizes buffers in case of resolution change +// +//-------------------------------------------------------------------------- + +_Post_satisfies_(this->m_pSwapChain1 != NULL) +HRESULT DX11VideoRenderer::CPresenter::UpdateDXGISwapChain(void) +{ + HRESULT hr = S_OK; + + // Get the DXGISwapChain1 + DXGI_SWAP_CHAIN_DESC1 scd; + ZeroMemory(&scd, sizeof(scd)); + scd.SampleDesc.Count = 1; + scd.SampleDesc.Quality = 0; + scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + scd.Scaling = DXGI_SCALING_STRETCH; + scd.Width = m_rcDstApp.right; + scd.Height = m_rcDstApp.bottom; + scd.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + scd.Stereo = m_bStereoEnabled; + scd.BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT; + scd.Flags = m_bStereoEnabled ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0; //opt in to do direct flip; + scd.BufferCount = 4; + + do + { + if (m_pSwapChain1) + { + // Resize our back buffers for the desired format. + hr = m_pSwapChain1->ResizeBuffers + ( + 4, + m_rcDstApp.right, + m_rcDstApp.bottom, + scd.Format, + scd.Flags + ); + + break; + } + + if (!m_useDCompVisual) + { + hr = m_pDXGIFactory2->CreateSwapChainForHwnd(m_pD3D11Device, m_hwndVideo, &scd, NULL, NULL, &m_pSwapChain1); + if (FAILED(hr)) + { + break; + } + + if (m_bFullScreenState) + { + hr = m_pSwapChain1->SetFullscreenState(TRUE, NULL); + if (FAILED(hr)) + { + break; + } + } + else + { + hr = m_pSwapChain1->SetFullscreenState(FALSE, NULL); + if (FAILED(hr)) + { + break; + } + } + } + else + { + // Create a swap chain for composition + hr = m_pDXGIFactory2->CreateSwapChainForComposition(m_pD3D11Device, &scd, NULL, &m_pSwapChain1); + if (FAILED(hr)) + { + break; + } + + hr = m_pRootVisual->SetContent(m_pSwapChain1); + if (FAILED(hr)) + { + break; + } + + hr = m_pDCompDevice->Commit(); + if (FAILED(hr)) + { + break; + } + } + } + while (FALSE); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: UpodateRectangles +// +// Synopsis: Figures out the real source and destination rectangles +// to use when drawing the video frame into the clients +// destination location. Takes into account pixel aspect +// ration correction, letterboxing and source rectangles. +// +//-------------------------------------------------------------------------- + +void DX11VideoRenderer::CPresenter::UpdateRectangles(RECT* pDst, RECT* pSrc) +{ + // take the given src rect and reverse map it into the native video + // image rectange. For example, consider a video with a buffer size of + // 720x480 and an active area of 704x480 - 8,0 with a picture aspect + // ratio of 4:3. The user sees the native video size as 640x480. + // + // If the user gave us a src rectangle of (180, 135, 540, 405) + // then this gets reversed mapped to + // + // 8 + (180 * 704 / 640) = 206 + // 0 + (135 * 480 / 480) = 135 + // 8 + (540 * 704 / 640) = 602 + // 0 + (405 * 480 / 480) = 405 + + RECT Src = *pSrc; + + pSrc->left = m_displayRect.left + MulDiv(pSrc->left, (m_displayRect.right - m_displayRect.left), m_uiRealDisplayWidth); + pSrc->right = m_displayRect.left + MulDiv(pSrc->right, (m_displayRect.right - m_displayRect.left), m_uiRealDisplayWidth); + + pSrc->top = m_displayRect.top + MulDiv(pSrc->top, (m_displayRect.bottom - m_displayRect.top), m_uiRealDisplayHeight); + pSrc->bottom = m_displayRect.top + MulDiv(pSrc->bottom, (m_displayRect.bottom - m_displayRect.top), m_uiRealDisplayHeight); + + LetterBoxDstRect(pDst, Src, m_rcDstApp); +} diff --git a/Samples/DX11VideoRenderer/cpp/Presenter.h b/Samples/DX11VideoRenderer/cpp/Presenter.h new file mode 100644 index 00000000..1f379e70 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Presenter.h @@ -0,0 +1,704 @@ +#pragma once + +#include "Common.h" +#include "display.h" + +namespace DX11VideoRenderer +{ + class CPresenter : + public IMFVideoDisplayControl, + public IMFGetService, + private CBase + { + public: + CPresenter(void); + virtual ~CPresenter(void); + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv); + STDMETHODIMP_(ULONG) Release(void); + + // IMFVideoDisplayControl + STDMETHODIMP GetAspectRatioMode(__RPC__out DWORD* pdwAspectRatioMode) { return E_NOTIMPL; } + STDMETHODIMP GetBorderColor(__RPC__out COLORREF* pClr) { return E_NOTIMPL; } + STDMETHODIMP GetCurrentImage(__RPC__inout BITMAPINFOHEADER* pBih, __RPC__deref_out_ecount_full_opt(*pcbDib) BYTE** pDib, __RPC__out DWORD* pcbDib, __RPC__inout_opt LONGLONG* pTimestamp) { return E_NOTIMPL; } + STDMETHODIMP GetFullscreen(__RPC__out BOOL* pfFullscreen); + STDMETHODIMP GetIdealVideoSize(__RPC__inout_opt SIZE* pszMin, __RPC__inout_opt SIZE* pszMax) { return E_NOTIMPL; } + STDMETHODIMP GetNativeVideoSize(__RPC__inout_opt SIZE* pszVideo, __RPC__inout_opt SIZE* pszARVideo) { return E_NOTIMPL; } + STDMETHODIMP GetRenderingPrefs(__RPC__out DWORD* pdwRenderFlags) { return E_NOTIMPL; } + STDMETHODIMP GetVideoPosition(__RPC__out MFVideoNormalizedRect* pnrcSource, __RPC__out LPRECT prcDest) { return E_NOTIMPL; } + STDMETHODIMP GetVideoWindow(__RPC__deref_out_opt HWND* phwndVideo) { return E_NOTIMPL; } + STDMETHODIMP RepaintVideo(void) { return E_NOTIMPL; } + STDMETHODIMP SetAspectRatioMode(DWORD dwAspectRatioMode) { return E_NOTIMPL; } + STDMETHODIMP SetBorderColor(COLORREF Clr) { return E_NOTIMPL; } + STDMETHODIMP SetFullscreen(BOOL fFullscreen); + STDMETHODIMP SetRenderingPrefs(DWORD dwRenderingPrefs) { return E_NOTIMPL; } + STDMETHODIMP SetVideoPosition(__RPC__in_opt const MFVideoNormalizedRect* pnrcSource, __RPC__in_opt const LPRECT prcDest) { return E_NOTIMPL; } + STDMETHODIMP SetVideoWindow(__RPC__in HWND hwndVideo); + + // IMFGetService + STDMETHODIMP GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject); + + BOOL CanProcessNextSample(void); + HRESULT Flush(void); + HRESULT GetMonitorRefreshRate(DWORD* pdwMonitorRefreshRate); + HRESULT IsMediaTypeSupported(IMFMediaType* pMediaType, DXGI_FORMAT dxgiFormat); + HRESULT PresentFrame(void); + HRESULT ProcessFrame(IMFMediaType* pCurrentType, IMFSample* pSample, UINT32* punInterlaceMode, BOOL* pbDeviceChanged, BOOL* pbProcessAgain, IMFSample** ppOutputSample = NULL); + HRESULT SetCurrentMediaType(IMFMediaType* pMediaType); + HRESULT Shutdown(void); + + private: + + void AspectRatioCorrectSize( + LPSIZE lpSizeImage, // size to be aspect ratio corrected + const SIZE& sizeAr, // aspect ratio of image + const SIZE& sizeOrig, // original image size + BOOL ScaleXorY // axis to correct in + ); + void CheckDecodeSwitchRegKey(void); + HRESULT CheckDeviceState(BOOL* pbDeviceChanged); + BOOL CheckEmptyRect(RECT* pDst); + HRESULT CheckShutdown(void) const; + HRESULT CreateDCompDeviceAndVisual(void); + HRESULT CreateDXGIManagerAndDevice(D3D_DRIVER_TYPE DriverType=D3D_DRIVER_TYPE_HARDWARE); + HRESULT CreateXVP(void); + HRESULT FindBOBProcessorIndex(DWORD* pIndex); + HRESULT GetVideoDisplayArea(IMFMediaType* pType, MFVideoArea* pArea); + void LetterBoxDstRect( + LPRECT lprcLBDst, // output letterboxed rectangle + const RECT& rcSrc, // input source rectangle + const RECT& rcDst // input destination rectangle + ); + void PixelAspectToPictureAspect( + int Width, + int Height, + int PixelAspectX, + int PixelAspectY, + int* pPictureAspectX, + int* pPictureAspectY + ); + HRESULT ProcessFrameUsingD3D11( ID3D11Texture2D* pLeftTexture2D, ID3D11Texture2D* pRightTexture2D, UINT dwLeftViewIndex, UINT dwRightViewIndex, RECT rcDest, UINT32 unInterlaceMode, IMFSample** ppVideoOutFrame ); + HRESULT ProcessFrameUsingXVP( IMFMediaType* pCurrentType, IMFSample* pVideoFrame, ID3D11Texture2D* pTexture2D, RECT rcDest, IMFSample** ppVideoOutFrame, BOOL* pbInputFrameUsed ); + void ReduceToLowestTerms( + int NumeratorIn, + int DenominatorIn, + int* pNumeratorOut, + int* pDenominatorOut + ); + HRESULT SetMonitor(UINT adapterID); + void SetVideoContextParameters(ID3D11VideoContext* pVideoContext, const RECT* pSRect, const RECT* pTRect, UINT32 unInterlaceMode); + HRESULT SetVideoMonitor(HWND hwndVideo); + HRESULT SetXVPOutputMediaType(IMFMediaType* pType, DXGI_FORMAT vpOutputFormat); + _Post_satisfies_(this->m_pSwapChain1 != NULL) + HRESULT UpdateDXGISwapChain(void); + void UpdateRectangles(RECT* pDst, RECT* pSrc); + + long m_nRefCount; // reference count + CCritSec m_critSec; // critical section for thread safety + BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called. + IDXGIFactory2* m_pDXGIFactory2; + ID3D11Device* m_pD3D11Device; + ID3D11DeviceContext* m_pD3DImmediateContext; + IMFDXGIDeviceManager* m_pDXGIManager; + IDXGIOutput1* m_pDXGIOutput1; + IMFVideoSampleAllocatorEx* m_pSampleAllocatorEx; + IDCompositionDevice* m_pDCompDevice; + IDCompositionTarget* m_pHwndTarget; + IDCompositionVisual* m_pRootVisual; + BOOL m_bSoftwareDXVADeviceInUse; + HWND m_hwndVideo; + CMonitorArray* m_pMonitors; + CAMDDrawMonitorInfo* m_lpCurrMon; + UINT m_DeviceResetToken; + UINT m_ConnectionGUID; + UINT m_DXSWSwitch; + UINT m_useXVP; + UINT m_useDCompVisual; + UINT m_useDebugLayer; + ID3D11VideoDevice* m_pDX11VideoDevice; + ID3D11VideoProcessorEnumerator* m_pVideoProcessorEnum; + ID3D11VideoProcessor* m_pVideoProcessor; + IDXGISwapChain1* m_pSwapChain1; + BOOL m_bDeviceChanged; + BOOL m_bResize; + BOOL m_b3DVideo; + BOOL m_bStereoEnabled; + MFVideo3DFormat m_vp3DOutput; + BOOL m_bFullScreenState; + BOOL m_bCanProcessNextSample; + RECT m_displayRect; + UINT32 m_imageWidthInPixels; + UINT32 m_imageHeightInPixels; + UINT32 m_uiRealDisplayWidth; + UINT32 m_uiRealDisplayHeight; + RECT m_rcSrcApp; + RECT m_rcDstApp; + IMFTransform* m_pXVP; + IMFVideoProcessorControl* m_pXVPControl; + }; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // Wrapper class for D3D11 Device and D3D11 Video device used for DXVA to Software decode switch + class CPrivate_ID3D11VideoDevice : public ID3D11VideoDevice + { + private: + + ID3D11VideoDevice* m_pReal; + ULONG m_cRef; + + public: + + CPrivate_ID3D11VideoDevice(ID3D11VideoDevice* pReal) : + m_pReal(pReal), + m_cRef(0) + { + } + + virtual ~CPrivate_ID3D11VideoDevice(void) + { + } + + STDMETHODIMP QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject) + { + if (__uuidof(ID3D11VideoDevice) == riid) + { + this->AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + return m_pReal->QueryInterface(riid,ppvObject); + } + } + + STDMETHODIMP_(ULONG) AddRef(void) + { + InterlockedIncrement(&m_cRef); + return m_pReal->AddRef(); + } + + STDMETHODIMP_(ULONG) Release(void) + { + ULONG ulVal = m_pReal->Release(); + if (0 == InterlockedDecrement(&m_cRef)) + { + } + return ulVal; + } + + STDMETHODIMP CreateVideoDecoder( + _In_ const D3D11_VIDEO_DECODER_DESC* pVideoDesc, + _In_ const D3D11_VIDEO_DECODER_CONFIG* pConfig, + _Out_ ID3D11VideoDecoder** ppDecoder) + { + return E_FAIL; + } + + STDMETHODIMP CreateVideoProcessor( + _In_ ID3D11VideoProcessorEnumerator* pEnum, + _In_ UINT RateConversionIndex, + _Out_ ID3D11VideoProcessor** ppVideoProcessor) + { + return m_pReal->CreateVideoProcessor(pEnum,RateConversionIndex,ppVideoProcessor); + } + + STDMETHODIMP CreateAuthenticatedChannel( + _In_ D3D11_AUTHENTICATED_CHANNEL_TYPE ChannelType, + _Out_ ID3D11AuthenticatedChannel** ppAuthenticatedChannel) + { + return m_pReal->CreateAuthenticatedChannel(ChannelType,ppAuthenticatedChannel); + } + + STDMETHODIMP CreateCryptoSession( + _In_ const GUID* pCryptoType, + _In_opt_ const GUID* pDecoderProfile, + _In_ const GUID* pKeyExchangeType, + _Outptr_ ID3D11CryptoSession** ppCryptoSession) + { + return m_pReal->CreateCryptoSession(pCryptoType,pDecoderProfile,pKeyExchangeType,ppCryptoSession); + } + + STDMETHODIMP CreateVideoDecoderOutputView( + _In_ ID3D11Resource* pResource, + _In_ const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC* pDesc, + _Out_opt_ ID3D11VideoDecoderOutputView** ppVDOVView) + { + return m_pReal->CreateVideoDecoderOutputView(pResource,pDesc,ppVDOVView); + } + + STDMETHODIMP CreateVideoProcessorInputView( + _In_ ID3D11Resource* pResource, + _In_ ID3D11VideoProcessorEnumerator* pEnum, + _In_ const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc, + _Out_opt_ ID3D11VideoProcessorInputView** ppVPIView) + { + return m_pReal->CreateVideoProcessorInputView(pResource,pEnum,pDesc,ppVPIView); + } + + STDMETHODIMP CreateVideoProcessorOutputView( + _In_ ID3D11Resource* pResource, + _In_ ID3D11VideoProcessorEnumerator* pEnum, + _In_ const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc, + _Out_opt_ ID3D11VideoProcessorOutputView** ppVPOView) + { + return m_pReal->CreateVideoProcessorOutputView(pResource,pEnum,pDesc,ppVPOView); + } + + STDMETHODIMP CreateVideoProcessorEnumerator( + _In_ const D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pDesc, + _Out_ ID3D11VideoProcessorEnumerator** ppEnum) + { + return m_pReal->CreateVideoProcessorEnumerator(pDesc,ppEnum); + } + + STDMETHODIMP_(UINT) GetVideoDecoderProfileCount(void) + { + return m_pReal->GetVideoDecoderProfileCount(); + } + + STDMETHODIMP GetVideoDecoderProfile( + _In_ UINT Index, + _Out_ GUID* pDecoderProfile) + { + return m_pReal->GetVideoDecoderProfile(Index,pDecoderProfile); + } + + STDMETHODIMP CheckVideoDecoderFormat( + _In_ const GUID* pDecoderProfile, + _In_ DXGI_FORMAT Format, + _Out_ BOOL* pSupported) + { + return m_pReal->CheckVideoDecoderFormat(pDecoderProfile,Format,pSupported); + } + + STDMETHODIMP GetVideoDecoderConfigCount( + _In_ const D3D11_VIDEO_DECODER_DESC* pDesc, + _Out_ UINT* pCount) + { + return m_pReal->GetVideoDecoderConfigCount(pDesc,pCount); + } + + STDMETHODIMP GetVideoDecoderConfig( + _In_ const D3D11_VIDEO_DECODER_DESC* pDesc, + _In_ UINT Index, + _Out_ D3D11_VIDEO_DECODER_CONFIG* pConfig) + { + return m_pReal->GetVideoDecoderConfig(pDesc,Index,pConfig); + } + + STDMETHODIMP GetContentProtectionCaps( + _In_opt_ const GUID* pCryptoType, + _In_opt_ const GUID* pDecoderProfile, + _Out_ D3D11_VIDEO_CONTENT_PROTECTION_CAPS* pCaps) + { + return m_pReal->GetContentProtectionCaps(pCryptoType,pDecoderProfile,pCaps); + } + + STDMETHODIMP CheckCryptoKeyExchange( + _In_ const GUID* pCryptoType, + _In_opt_ const GUID* pDecoderProfile, + _In_ UINT Index, + _Out_ GUID* pKeyExchangeType) + { + return m_pReal->CheckCryptoKeyExchange(pCryptoType,pDecoderProfile,Index,pKeyExchangeType); + } + + STDMETHODIMP SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) + { + return m_pReal->SetPrivateData(guid,DataSize,pData); + } + + STDMETHODIMP SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) + { + return m_pReal->SetPrivateDataInterface(guid,pData); + } + }; + + class CPrivate_ID3D11Device : public ID3D11Device + { + private: + + ID3D11Device* m_pReal; + ULONG m_cRef; + CPrivate_ID3D11VideoDevice* m_pVideoDevice; + + public: + + CPrivate_ID3D11Device(ID3D11Device* pReal) : + m_pReal(pReal), + m_cRef(1), + m_pVideoDevice(NULL) + { + ID3D11VideoDevice* pDevice; + m_pReal->QueryInterface(__uuidof(ID3D11VideoDevice),(void**)&pDevice); + m_pVideoDevice = new CPrivate_ID3D11VideoDevice(pDevice); + if (pDevice != NULL) + { + pDevice->Release(); + } + } + + virtual ~CPrivate_ID3D11Device(void) + { + SafeDelete(m_pVideoDevice); + } + + STDMETHODIMP QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject) + { + if (__uuidof(ID3D11VideoDevice) == riid) + { + m_pVideoDevice->AddRef(); + *ppvObject = m_pVideoDevice; + return S_OK; + } + else if (__uuidof(ID3D11Device) == riid) + { + this->AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + return m_pReal->QueryInterface(riid,ppvObject); + } + } + + STDMETHODIMP_(ULONG) AddRef(void) + { + InterlockedIncrement(&m_cRef); + return m_pReal->AddRef(); + } + + STDMETHODIMP_(ULONG) Release(void) + { + ULONG ulVal = m_pReal->Release(); + if (0 == InterlockedDecrement(&m_cRef)) + { + delete this; + } + return ulVal; + } + + STDMETHODIMP CreateBuffer( + _In_ const D3D11_BUFFER_DESC* pDesc, + _In_opt_ const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Buffer** ppBuffer) + { + return m_pReal->CreateBuffer(pDesc,pInitialData,ppBuffer); + } + + STDMETHODIMP CreateTexture1D( + _In_ const D3D11_TEXTURE1D_DESC* pDesc, + _In_reads_opt_(pDesc->MipLevels * pDesc->ArraySize) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture1D** ppTexture1D) + { + return m_pReal->CreateTexture1D(pDesc,pInitialData,ppTexture1D); + } + + STDMETHODIMP CreateTexture2D( + _In_ const D3D11_TEXTURE2D_DESC* pDesc, + _In_reads_opt_(pDesc->MipLevels * pDesc->ArraySize) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture2D** ppTexture2D) + { + return m_pReal->CreateTexture2D(pDesc,pInitialData,ppTexture2D); + } + + STDMETHODIMP CreateTexture3D( + _In_ const D3D11_TEXTURE3D_DESC* pDesc, + _In_reads_opt_(pDesc->MipLevels) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture3D** ppTexture3D) + { + return m_pReal->CreateTexture3D(pDesc,pInitialData,ppTexture3D); + } + + STDMETHODIMP CreateShaderResourceView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + _Out_opt_ ID3D11ShaderResourceView** ppSRView) + { + return m_pReal->CreateShaderResourceView(pResource,pDesc,ppSRView); + } + + STDMETHODIMP CreateUnorderedAccessView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + _Out_opt_ ID3D11UnorderedAccessView** ppUAView) + { + return m_pReal->CreateUnorderedAccessView(pResource,pDesc,ppUAView); + } + + STDMETHODIMP CreateRenderTargetView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + _Out_opt_ ID3D11RenderTargetView** ppRTView) + { + return m_pReal->CreateRenderTargetView(pResource,pDesc,ppRTView); + } + + STDMETHODIMP CreateDepthStencilView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, + _Out_opt_ ID3D11DepthStencilView** ppDepthStencilView) + { + return m_pReal->CreateDepthStencilView(pResource,pDesc,ppDepthStencilView); + } + + STDMETHODIMP CreateInputLayout( + _In_reads_(NumElements) const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, + _In_range_( 0, D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT ) UINT NumElements, + _In_ const void* pShaderBytecodeWithInputSignature, + _In_ SIZE_T BytecodeLength, + _Out_opt_ ID3D11InputLayout** ppInputLayout) + { + return m_pReal->CreateInputLayout(pInputElementDescs,NumElements,pShaderBytecodeWithInputSignature,BytecodeLength,ppInputLayout); + } + + STDMETHODIMP CreateVertexShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11VertexShader** ppVertexShader) + { + return m_pReal->CreateVertexShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppVertexShader); + } + + STDMETHODIMP CreateGeometryShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11GeometryShader** ppGeometryShader) + { + return m_pReal->CreateGeometryShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppGeometryShader); + } + + STDMETHODIMP CreateGeometryShaderWithStreamOutput( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_reads_opt_(NumEntries) const D3D11_SO_DECLARATION_ENTRY* pSODeclaration, + _In_range_( 0, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT ) UINT NumEntries, + _In_reads_opt_(NumStrides) const UINT* pBufferStrides, + _In_range_( 0, D3D11_SO_BUFFER_SLOT_COUNT ) UINT NumStrides, + _In_ UINT RasterizedStream, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11GeometryShader** ppGeometryShader) + { + return m_pReal->CreateGeometryShaderWithStreamOutput(pShaderBytecode,BytecodeLength,pSODeclaration,NumEntries,pBufferStrides,NumStrides,RasterizedStream,pClassLinkage,ppGeometryShader); + } + + STDMETHODIMP CreatePixelShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11PixelShader** ppPixelShader) + { + return m_pReal->CreatePixelShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppPixelShader); + } + + STDMETHODIMP CreateHullShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11HullShader** ppHullShader) + { + return m_pReal->CreateHullShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppHullShader); + } + + STDMETHODIMP CreateDomainShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11DomainShader** ppDomainShader) + { + return m_pReal->CreateDomainShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppDomainShader); + } + + STDMETHODIMP CreateComputeShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11ComputeShader** ppComputeShader) + { + return m_pReal->CreateComputeShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppComputeShader); + } + + STDMETHODIMP CreateClassLinkage( + _Out_ ID3D11ClassLinkage** ppLinkage) + { + return m_pReal->CreateClassLinkage(ppLinkage); + } + + STDMETHODIMP CreateBlendState( + _In_ const D3D11_BLEND_DESC* pBlendStateDesc, + _Out_opt_ ID3D11BlendState** ppBlendState) + { + return m_pReal->CreateBlendState(pBlendStateDesc,ppBlendState); + } + + STDMETHODIMP CreateDepthStencilState( + _In_ const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, + _Out_opt_ ID3D11DepthStencilState** ppDepthStencilState) + { + return m_pReal->CreateDepthStencilState(pDepthStencilDesc,ppDepthStencilState); + } + + STDMETHODIMP CreateRasterizerState( + _In_ const D3D11_RASTERIZER_DESC* pRasterizerDesc, + _Out_opt_ ID3D11RasterizerState** ppRasterizerState) + { + return m_pReal->CreateRasterizerState(pRasterizerDesc,ppRasterizerState); + } + + STDMETHODIMP CreateSamplerState( + _In_ const D3D11_SAMPLER_DESC* pSamplerDesc, + _Out_opt_ ID3D11SamplerState** ppSamplerState) + { + return m_pReal->CreateSamplerState(pSamplerDesc,ppSamplerState); + } + + STDMETHODIMP CreateQuery( + _In_ const D3D11_QUERY_DESC* pQueryDesc, + _Out_opt_ ID3D11Query** ppQuery) + { + return m_pReal->CreateQuery(pQueryDesc,ppQuery); + } + + STDMETHODIMP CreatePredicate( + _In_ const D3D11_QUERY_DESC* pPredicateDesc, + _Out_opt_ ID3D11Predicate** ppPredicate) + { + return m_pReal->CreatePredicate(pPredicateDesc,ppPredicate); + } + + STDMETHODIMP CreateCounter( + _In_ const D3D11_COUNTER_DESC* pCounterDesc, + _Out_opt_ ID3D11Counter** ppCounter) + { + return m_pReal->CreateCounter(pCounterDesc,ppCounter); + } + + STDMETHODIMP CreateDeferredContext( + UINT ContextFlags, + _Out_opt_ ID3D11DeviceContext** ppDeferredContext) + { + return m_pReal->CreateDeferredContext(ContextFlags,ppDeferredContext); + } + + STDMETHODIMP OpenSharedResource( + _In_ HANDLE hResource, + _In_ REFIID ReturnedInterface, + _Out_opt_ void** ppResource) + { + return m_pReal->OpenSharedResource(hResource,ReturnedInterface,ppResource); + } + + STDMETHODIMP CheckFormatSupport( + _In_ DXGI_FORMAT Format, + _Out_ UINT* pFormatSupport) + { + return m_pReal->CheckFormatSupport(Format,pFormatSupport); + } + + STDMETHODIMP CheckMultisampleQualityLevels( + _In_ DXGI_FORMAT Format, + _In_ UINT SampleCount, + _Out_ UINT* pNumQualityLevels) + { + return m_pReal->CheckMultisampleQualityLevels(Format,SampleCount,pNumQualityLevels); + } + + STDMETHODIMP_(void) CheckCounterInfo( + _Out_ D3D11_COUNTER_INFO* pCounterInfo) + { + return m_pReal->CheckCounterInfo(pCounterInfo); + } + + STDMETHODIMP CheckCounter( + _In_ const D3D11_COUNTER_DESC* pDesc, + _Out_ D3D11_COUNTER_TYPE* pType, + _Out_ UINT* pActiveCounters, + _Out_writes_opt_(*pNameLength) LPSTR szName, + _Inout_opt_ UINT* pNameLength, + _Out_writes_opt_(*pUnitsLength) LPSTR szUnits, + _Inout_opt_ UINT* pUnitsLength, + _Out_writes_opt_(*pDescriptionLength) LPSTR szDescription, + _Inout_opt_ UINT* pDescriptionLength) + { + return m_pReal->CheckCounter(pDesc,pType,pActiveCounters,szName,pNameLength,szUnits,pUnitsLength,szDescription,pDescriptionLength); + } + + STDMETHODIMP CheckFeatureSupport( + D3D11_FEATURE Feature, + _Out_writes_bytes_(FeatureSupportDataSize) void* pFeatureSupportData, + UINT FeatureSupportDataSize) + { + return m_pReal->CheckFeatureSupport(Feature,pFeatureSupportData,FeatureSupportDataSize); + } + + STDMETHODIMP GetPrivateData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) + { + return m_pReal->GetPrivateData(guid,pDataSize,pData); + } + + STDMETHODIMP SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) + { + return m_pReal->SetPrivateData(guid,DataSize,pData); + } + + STDMETHODIMP SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) + { + return m_pReal->SetPrivateDataInterface(guid,pData); + } + + STDMETHODIMP_(D3D_FEATURE_LEVEL) GetFeatureLevel(void) + { + return m_pReal->GetFeatureLevel(); + } + + STDMETHODIMP_(UINT) GetCreationFlags(void) + { + return m_pReal->GetCreationFlags(); + } + + STDMETHODIMP GetDeviceRemovedReason(void) + { + return m_pReal->GetDeviceRemovedReason(); + } + + STDMETHODIMP_(void) GetImmediateContext( + _Out_ ID3D11DeviceContext** ppImmediateContext) + { + return m_pReal->GetImmediateContext(ppImmediateContext); + } + + STDMETHODIMP SetExceptionMode( + UINT RaiseFlags) + { + return m_pReal->SetExceptionMode(RaiseFlags); + } + + STDMETHODIMP_(UINT) GetExceptionMode(void) + { + return m_pReal->GetExceptionMode(); + } + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/Scheduler.cpp b/Samples/DX11VideoRenderer/cpp/Scheduler.cpp new file mode 100644 index 00000000..7ba67cf2 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Scheduler.cpp @@ -0,0 +1,416 @@ +#include "Scheduler.h" + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +DX11VideoRenderer::CScheduler::CScheduler(CCritSec& critSec) : + m_nRefCount(1), + m_critSec(critSec), + m_pCB(NULL), + m_ScheduledSamples(), // default ctor + m_pClock(NULL), + m_fRate(1.0f), + m_hWaitTimer(NULL), + m_LastSampleTime(0), + m_PerFrameInterval(0), + m_PerFrame_1_4th(0), + m_keyTimer(0) +{ +} + + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +DX11VideoRenderer::CScheduler::~CScheduler(void) +{ + if (m_hWaitTimer != NULL) + { + CloseHandle(m_hWaitTimer); + m_hWaitTimer = NULL; + } + + // Discard samples. + m_ScheduledSamples.Clear(); + + SafeRelease(m_pClock); +} + +// IUnknown methods + +ULONG DX11VideoRenderer::CScheduler::AddRef() +{ + return InterlockedIncrement(&m_nRefCount); +} + +ULONG DX11VideoRenderer::CScheduler::Release() +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + // For thread safety, return a temporary variable. + return uCount; +} + +HRESULT DX11VideoRenderer::CScheduler::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +//----------------------------------------------------------------------------- +// SetFrameRate +// Specifies the frame rate of the video, in frames per second. +//----------------------------------------------------------------------------- + +void DX11VideoRenderer::CScheduler::SetFrameRate(const MFRatio& fps) +{ + UINT64 AvgTimePerFrame = 0; + + // Convert to a duration. + MFFrameRateToAverageTimePerFrame(fps.Numerator, fps.Denominator, &AvgTimePerFrame); + + m_PerFrameInterval = (MFTIME)AvgTimePerFrame; + + // Calculate 1/4th of this value, because we use it frequently. + m_PerFrame_1_4th = m_PerFrameInterval / 4; +} + + + +//----------------------------------------------------------------------------- +// StartScheduler +// Starts the scheduler's worker thread. +// +// IMFClock: Pointer to the DX11VideoRenderer's presentation clock. Can be NULL. +//----------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CScheduler::StartScheduler(IMFClock* pClock) +{ + HRESULT hr = S_OK; + + SafeRelease(m_pClock); + m_pClock = pClock; + if (m_pClock != NULL) + { + m_pClock->AddRef(); + } + + // Set a high the timer resolution (ie, short timer period). + timeBeginPeriod(1); + + // create the waitable timer + m_hWaitTimer = CreateWaitableTimer(NULL, FALSE, NULL); + if (m_hWaitTimer == NULL) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + return hr; +} + + +//----------------------------------------------------------------------------- +// StopScheduler +// +// Stops the scheduler's worker thread. +//----------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CScheduler::StopScheduler(void) +{ + if (m_hWaitTimer != NULL) + { + CloseHandle(m_hWaitTimer); + m_hWaitTimer = NULL; + } + + // Discard samples. + m_ScheduledSamples.Clear(); + + // Restore the timer resolution. + timeEndPeriod(1); + + SafeRelease(m_pClock); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Flush +// +// Flushes all samples that are queued for presentation. +// +// Note: This method is synchronous; ie., it waits for the flush operation to +// complete on the worker thread. +//----------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CScheduler::Flush(void) +{ + CAutoLock lock(&m_critSec); + + // Flushing: Clear the sample queue and set the event. + m_ScheduledSamples.Clear(); + + // Cancel timer callback + if (m_keyTimer != 0) + { + (void)MFCancelWorkItem(m_keyTimer); + m_keyTimer = 0; + } + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// ScheduleSample +// +// Schedules a new sample for presentation. +// +// pSample: Pointer to the sample. +// bPresentNow: If TRUE, the sample is presented immediately. Otherwise, the +// sample's time stamp is used to schedule the sample. +//----------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CScheduler::ScheduleSample(IMFSample* pSample, BOOL bPresentNow) +{ + if (m_pCB == NULL) + { + return MF_E_NOT_INITIALIZED; + } + + HRESULT hr = S_OK; + + if (bPresentNow || (m_pClock == NULL)) + { + // Present the sample immediately. + hr = m_pCB->PresentFrame(); + } + else + { + // Queue the sample and ask the scheduler thread to wake up. + hr = m_ScheduledSamples.Queue(pSample); + + if (SUCCEEDED(hr)) + { + // process the frame asynchronously + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &m_xOnTimer, nullptr); + } + } + + return hr; +} + +//----------------------------------------------------------------------------- +// ProcessSamplesInQueue +// +// Processes all the samples in the queue. +// +// plNextSleep: Receives the length of time the scheduler thread should sleep +// before it calls ProcessSamplesInQueue again. +//----------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CScheduler::ProcessSamplesInQueue(LONG* plNextSleep) +{ + HRESULT hr = S_OK; + LONG lWait = 0; + IMFSample* pSample = NULL; + + // Process samples until the queue is empty or until the wait time > 0. + + // Note: Dequeue returns S_FALSE when the queue is empty. + + while (m_ScheduledSamples.Dequeue(&pSample) == S_OK) + { + // Process the next sample in the queue. If the sample is not ready + // for presentation. the value returned in lWait is > 0, which + // means the scheduler should sleep for that amount of time. + + hr = ProcessSample(pSample, &lWait); + SafeRelease(pSample); + + if (FAILED(hr) || lWait > 0) + { + break; + } + } + + // If the wait time is zero, it means we stopped because the queue is + // empty (or an error occurred). Set the wait time to infinite; this will + // make the scheduler thread sleep until it gets another thread message. + if (lWait == 0) + { + lWait = INFINITE; + } + + *plNextSleep = lWait; + return hr; +} + + +//----------------------------------------------------------------------------- +// ProcessSample +// +// Processes a sample. +// +// plNextSleep: Receives the length of time the scheduler thread should sleep. +//----------------------------------------------------------------------------- + + +HRESULT DX11VideoRenderer::CScheduler::ProcessSample(IMFSample* pSample, LONG* plNextSleep) +{ + HRESULT hr = S_OK; + + LONGLONG hnsPresentationTime = 0; + LONGLONG hnsTimeNow = 0; + MFTIME hnsSystemTime = 0; + LONGLONG hnsDelta = 0; + + BOOL bPresentNow = TRUE; + LONG lNextSleep = 0; + + if (m_pClock) + { + // Get the sample's time stamp. It is valid for a sample to + // have no time stamp. + hr = pSample->GetSampleTime(&hnsPresentationTime); + + // Get the clock time. (But if the sample does not have a time stamp, + // we don't need the clock time.) + if (SUCCEEDED(hr)) + { + hr = m_pClock->GetCorrelatedTime(0, &hnsTimeNow, &hnsSystemTime); + } + + if (SUCCEEDED(hr)) + { + // Calculate the time until the sample's presentation time. + // A negative value means the sample is late. + hnsDelta = hnsPresentationTime - hnsTimeNow; + if (m_fRate < 0) + { + // For reverse playback, the clock runs backward. Therefore, the + // delta is reversed. + hnsDelta = - hnsDelta; + } + + if (hnsDelta < - m_PerFrame_1_4th) + { + // This sample is late. + bPresentNow = TRUE; + } + else if (hnsDelta > (3 * m_PerFrame_1_4th)) + { + // This sample is still too early. Go to sleep. + lNextSleep = static_cast(TicksToMilliseconds(hnsDelta - (3 * m_PerFrame_1_4th))); + + // Adjust the sleep time for the clock rate. (The presentation clock runs + // at m_fRate, but sleeping uses the system clock.) + lNextSleep = static_cast(lNextSleep / fabsf(m_fRate)); + + // Don't present yet. + bPresentNow = FALSE; + } + } + } + + if (bPresentNow) + { + hr = m_pCB->PresentFrame(); + } + else + { + // The sample is not ready yet. Return it to the queue. + hr = m_ScheduledSamples.PutBack(pSample); + } + + *plNextSleep = lNextSleep; + + return hr; +} + +//----------------------------------------------------------------------------- +// StartProcessSample +// +// Synopsis: Main entrypoint for the frame processing +//----------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CScheduler::StartProcessSample() +{ + HRESULT hr = S_OK; + + LONG lWait = INFINITE; + BOOL bExitThread = FALSE; + IMFAsyncResult *pAsyncResult = NULL; + + hr = ProcessSamplesInQueue(&lWait); + + if(SUCCEEDED(hr)) + { + if(INFINITE != lWait && 0 < lWait) + { + // not time to process the frame yet, wait until the right time + LARGE_INTEGER llDueTime; + llDueTime.QuadPart = -1 * MillisecondsToTicks(lWait); + if (SetWaitableTimer(m_hWaitTimer, &llDueTime, 0, NULL, NULL, FALSE) == 0) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if(SUCCEEDED(hr)) + { + // queue a waititem to wait for timer completion + hr = MFCreateAsyncResult(nullptr, &m_xOnTimer, nullptr, &pAsyncResult); + if(SUCCEEDED(hr)) + { + hr = MFPutWaitingWorkItem(m_hWaitTimer, 0, pAsyncResult, &m_keyTimer); + } + } + } + } + + SafeRelease(pAsyncResult); + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Function: OnTimer +// +// Synopsis: Callback fired when the timer expires. Used as entrypoint to +// check whether a frame should now be presented +// +//-------------------------------------------------------------------------- +HRESULT DX11VideoRenderer::CScheduler::OnTimer(__RPC__in_opt IMFAsyncResult *pResult) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + + m_keyTimer = 0; + + // if we have a pending frame, process it + // it's possible that we don't have a frame at this point if the pending frame was cancelled + hr = StartProcessSample(); + + return hr; +} \ No newline at end of file diff --git a/Samples/DX11VideoRenderer/cpp/Scheduler.h b/Samples/DX11VideoRenderer/cpp/Scheduler.h new file mode 100644 index 00000000..9cf53419 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/Scheduler.h @@ -0,0 +1,89 @@ +#pragma once + +#include "Common.h" + +namespace DX11VideoRenderer +{ + //----------------------------------------------------------------------------- + // SchedulerCallback + // + // Defines the callback method to present samples. + //----------------------------------------------------------------------------- + + struct SchedulerCallback + { + virtual HRESULT PresentFrame(void) = 0; + }; + + //----------------------------------------------------------------------------- + // Scheduler class + // + // Schedules when a sample should be displayed. + // + // Note: Presentation of each sample is performed by another object which + // must implement SchedulerCallback::PresentSample. + // + // General design: + // The scheduler generally receives samples before their presentation time. It + // puts the samples on a queue and presents them in FIFO order on a worker + // thread. The scheduler communicates with the worker thread by posting thread + // messages. + // + // The caller has the option of presenting samples immediately (for example, + // for repaints). + //----------------------------------------------------------------------------- + + class CScheduler: + public IUnknown, + private CBase + { + public: + + CScheduler(CCritSec& critSec); + virtual ~CScheduler(void); + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv); + + void SetCallback(SchedulerCallback* pCB) + { + m_pCB = pCB; + } + + void SetFrameRate(const MFRatio& fps); + void SetClockRate(float fRate) { m_fRate = fRate; } + + const LONGLONG& LastSampleTime(void) const { return m_LastSampleTime; } + const LONGLONG& FrameDuration(void) const { return m_PerFrameInterval; } + + HRESULT StartScheduler(IMFClock* pClock); + HRESULT StopScheduler(void); + + HRESULT ScheduleSample(IMFSample* pSample, BOOL bPresentNow); + HRESULT ProcessSamplesInQueue(LONG* plNextSleep); + HRESULT ProcessSample(IMFSample* pSample, LONG* plNextSleep); + HRESULT Flush(void); + + DWORD GetCount(void){ return m_ScheduledSamples.GetCount(); } + + private: + + HRESULT StartProcessSample(); + HRESULT OnTimer(__RPC__in_opt IMFAsyncResult* pResult); + METHODASYNCCALLBACKEX(OnTimer, CScheduler, 0, MFASYNC_CALLBACK_QUEUE_MULTITHREADED); + + long m_nRefCount; + CCritSec& m_critSec; // critical section for thread safety + SchedulerCallback* m_pCB; // Weak reference; do not delete. + ThreadSafeQueue m_ScheduledSamples; // Samples waiting to be presented. + IMFClock* m_pClock; // Presentation clock. Can be NULL. + float m_fRate; // Playback rate. + HANDLE m_hWaitTimer; // Wait Timer after which frame is presented. + MFTIME m_LastSampleTime; // Most recent sample time. + MFTIME m_PerFrameInterval; // Duration of each frame. + LONGLONG m_PerFrame_1_4th; // 1/4th of the frame duration. + MFWORKITEM_KEY m_keyTimer; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/StaticAsyncCallback.h b/Samples/DX11VideoRenderer/cpp/StaticAsyncCallback.h new file mode 100644 index 00000000..c979f907 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/StaticAsyncCallback.h @@ -0,0 +1,116 @@ +#ifndef __STATICASYNCCALLBACK__ +#define __STATICASYNCCALLBACK__ + +//////////////////////////////////////////////////////// +// +#define STATICASYNCCALLBACK(Callback, Parent) \ +class Callback##AsyncCallback; \ +friend class Callback##AsyncCallback; \ +class Callback##AsyncCallback : public IMFAsyncCallback \ +{ \ +public: \ + STDMETHOD_( ULONG, AddRef )() \ + { \ + Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \ + return pThis->AddRef(); \ + } \ + STDMETHOD_( ULONG, Release )() \ + { \ + Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \ + return pThis->Release(); \ + } \ + STDMETHOD( QueryInterface )( REFIID riid, __RPC__deref_out _Result_nullonfailure_ void **ppvObject ) \ + { \ + return E_NOINTERFACE; \ + } \ + STDMETHOD( GetParameters )( \ + __RPC__out DWORD *pdwFlags, \ + __RPC__out DWORD *pdwQueue) \ + { \ + return S_OK; \ + } \ + STDMETHOD( Invoke )( __RPC__in_opt IMFAsyncResult * pResult ) \ + { \ + Callback( pResult ); \ + return S_OK; \ + } \ +} m_x##Callback; + + +//////////////////////////////////////////////////////// +// +// +// We need to support QI interface so that DCOM is happy when it tries to marshal the interface pointer +// + +#define METHODASYNCCALLBACKEX(Callback, Parent, Flag, Queue) \ +class Callback##AsyncCallback; \ +friend class Callback##AsyncCallback; \ +class Callback##AsyncCallback : public IMFAsyncCallback \ +{ \ +public: \ + STDMETHOD_( ULONG, AddRef )() \ + { \ + return GetParent()->AddRef(); \ + } \ + STDMETHOD_( ULONG, Release )() \ + { \ + return GetParent()->Release(); \ + } \ + STDMETHOD( QueryInterface )( REFIID riid, __RPC__deref_out _Result_nullonfailure_ void **ppvObject ) \ + { \ + if(riid == IID_IMFAsyncCallback || riid == IID_IUnknown) \ + { \ + (*ppvObject) = this; \ + AddRef(); \ + return S_OK; \ + } \ + (*ppvObject) = NULL; \ + return E_NOINTERFACE; \ + } \ + STDMETHOD( GetParameters )( \ + __RPC__out DWORD *pdwFlags, \ + __RPC__out DWORD *pdwQueue) \ + { \ + *pdwFlags = Flag; \ + *pdwQueue = Queue; \ + return S_OK; \ + } \ + STDMETHOD( Invoke )( __RPC__in_opt IMFAsyncResult * pResult ) \ + { \ + GetParent()->Callback( pResult ); \ + return S_OK; \ + } \ +protected: \ + Parent* GetParent() \ + { \ + return ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \ + } \ +} m_x##Callback; + +//////////////////////////////////////////////////////// +// +#define METHODFASTCALLBACK(Callback, Parent) \ + METHODASYNCCALLBACKEX(Callback, Parent, MFASYNC_FAST_IO_PROCESSING_CALLBACK, MFASYNC_CALLBACK_QUEUE_STANDARD) + +#define METHODASYNCCALLBACK(Callback, Parent) \ + METHODASYNCCALLBACKEX(Callback, Parent, 0, MFASYNC_CALLBACK_QUEUE_STANDARD) + +#define METHODASYNCRTCALLBACK(Callback, Parent) \ + METHODASYNCCALLBACKEX(Callback, Parent, 0, MFASYNC_CALLBACK_QUEUE_RT) + +#define METHODASYNCIOCALLBACK(Callback, Parent) \ + METHODASYNCCALLBACKEX(Callback, Parent, MFASYNC_FAST_IO_PROCESSING_CALLBACK, MFASYNC_CALLBACK_QUEUE_IO) + +//////////////////////////////////////////////////////// +// +#define METHODASYNCCALLBACKEX2(Callback, Parent, GetQueue ) \ + METHODASYNCCALLBACKEX(Callback, Parent, \ + 0, \ + GetParent()->GetQueue() ) + +#define METHODASYNCCALLBACKEX3(Callback, Parent, GetFlags, GetQueue ) \ + METHODASYNCCALLBACKEX(Callback, Parent, \ + GetParent()->GetFlags(), GetParent()->GetQueue() ) + +#endif diff --git a/Samples/DX11VideoRenderer/cpp/StreamSink.cpp b/Samples/DX11VideoRenderer/cpp/StreamSink.cpp new file mode 100644 index 00000000..66272336 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/StreamSink.cpp @@ -0,0 +1,1648 @@ +#include "StreamSink.h" + +GUID const* const DX11VideoRenderer::CStreamSink::s_pVideoFormats[] = +{ + &MFVideoFormat_NV12, + &MFVideoFormat_IYUV, + &MFVideoFormat_YUY2, + &MFVideoFormat_YV12, + &MFVideoFormat_RGB32, + &MFVideoFormat_RGB32, + &MFVideoFormat_RGB24, + &MFVideoFormat_RGB555, + &MFVideoFormat_RGB565, + &MFVideoFormat_RGB8, + &MFVideoFormat_AYUV, + &MFVideoFormat_UYVY, + &MFVideoFormat_YVYU, + &MFVideoFormat_YVU9, + &MEDIASUBTYPE_V216, + &MFVideoFormat_v410, + &MFVideoFormat_I420, + &MFVideoFormat_NV11, + &MFVideoFormat_420O +}; + +const DWORD DX11VideoRenderer::CStreamSink::s_dwNumVideoFormats = sizeof(DX11VideoRenderer::CStreamSink::s_pVideoFormats) / sizeof(DX11VideoRenderer::CStreamSink::s_pVideoFormats[0]); + +const MFRatio DX11VideoRenderer::CStreamSink::s_DefaultFrameRate = { 30, 1 }; + +const DX11VideoRenderer::CStreamSink::FormatEntry DX11VideoRenderer::CStreamSink::s_DXGIFormatMapping[] = +{ + { MFVideoFormat_RGB32, DXGI_FORMAT_B8G8R8X8_UNORM }, + { MFVideoFormat_ARGB32, DXGI_FORMAT_R8G8B8A8_UNORM }, + { MFVideoFormat_AYUV, DXGI_FORMAT_AYUV }, + { MFVideoFormat_YUY2, DXGI_FORMAT_YUY2 }, + { MFVideoFormat_NV12, DXGI_FORMAT_NV12 }, + { MFVideoFormat_NV11, DXGI_FORMAT_NV11 }, + { MFVideoFormat_AI44, DXGI_FORMAT_AI44 }, + { MFVideoFormat_P010, DXGI_FORMAT_P010 }, + { MFVideoFormat_P016, DXGI_FORMAT_P016 }, + { MFVideoFormat_Y210, DXGI_FORMAT_Y210 }, + { MFVideoFormat_Y216, DXGI_FORMAT_Y216 }, + { MFVideoFormat_Y410, DXGI_FORMAT_Y410 }, + { MFVideoFormat_Y416, DXGI_FORMAT_Y416 }, + { MFVideoFormat_420O, DXGI_FORMAT_420_OPAQUE } +}; + +// Control how we batch work from the decoder. +// On receiving a sample we request another one if the number on the queue is +// less than the hi water threshold. +// When displaying samples (removing them from the sample queue) we request +// another one if the number of falls below the lo water threshold +// +#define SAMPLE_QUEUE_HIWATER_THRESHOLD 3 +// maximum # of past reference frames required for deinterlacing +#define MAX_PAST_FRAMES 3 + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// CStreamSink class. - Implements the stream sink. +// +// Notes: +// - Most of the real work gets done in this class. +// - The sink has one stream. If it had multiple streams, it would need to coordinate them. +// - Most operations are done asynchronously on a work queue. +// - Async methods are handled like this: +// 1. Call ValidateOperation to check if the operation is permitted at this time +// 2. Create an CAsyncOperation object for the operation. +// 3. Call QueueAsyncOperation. This puts the operation on the work queue. +// 4. The workqueue calls OnDispatchWorkItem. +// - Locking: +// To avoid deadlocks, do not hold the CStreamSink lock followed by the CMediaSink lock. +// The other order is OK (CMediaSink, then CStreamSink). +// +///////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------------------------------------------------- +// Name: ValidStateMatrix +// Description: Class-static matrix of operations vs states. +// +// If an entry is TRUE, the operation is valid from that state. +//------------------------------------------------------------------- + +BOOL DX11VideoRenderer::CStreamSink::ValidStateMatrix[DX11VideoRenderer::CStreamSink::State_Count][DX11VideoRenderer::CStreamSink::Op_Count] = +{ + // States: Operations: + // SetType Start Restart Pause Stop Sample Marker + /* NotSet */ TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + + /* Ready */ TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, + + /* Start */ TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, + + /* Pause */ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + + /* Stop */ TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE + + // Note about states: + // 1. OnClockRestart should only be called from paused state. + // 2. While paused, the sink accepts samples but does not process them. + +}; + +//------------------------------------------------------------------- +// CStreamSink constructor +//------------------------------------------------------------------- + +#pragma warning( push ) +#pragma warning( disable : 4355 ) // 'this' used in base member initializer list + +DX11VideoRenderer::CStreamSink::CStreamSink(DWORD dwStreamId, CCritSec& critSec, CScheduler* pScheduler) : + STREAM_ID(dwStreamId), + m_nRefCount(1), + m_critSec(critSec), + m_state(State_TypeNotSet), + m_IsShutdown(FALSE), + m_WorkQueueId(0), + m_WorkQueueCB(this, &CStreamSink::OnDispatchWorkItem), + m_ConsumeData(ProcessFrames), + m_StartTime(0), + m_cbDataWritten(0), + m_cOutstandingSampleRequests(0), + m_pSink(NULL), + m_pEventQueue(NULL), + m_pByteStream(NULL), + m_pPresenter(NULL), + m_pScheduler(pScheduler), + m_pCurrentType(NULL), + m_fPrerolling(FALSE), + m_fWaitingForOnClockStart(FALSE), + m_SamplesToProcess(), // default ctor + m_unInterlaceMode(MFVideoInterlace_Progressive), + m_imageBytesPP(), // default ctor + m_dxgiFormat(DXGI_FORMAT_UNKNOWN) +{ + m_imageBytesPP.Numerator = 1; + m_imageBytesPP.Denominator = 1; +} + +#pragma warning( pop ) + +//------------------------------------------------------------------- +// CStreamSink destructor +//------------------------------------------------------------------- + +DX11VideoRenderer::CStreamSink::~CStreamSink(void) +{ +} + +// IUnknown methods + +ULONG DX11VideoRenderer::CStreamSink::AddRef(void) +{ + return InterlockedIncrement(&m_nRefCount); +} + +HRESULT DX11VideoRenderer::CStreamSink::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(static_cast(this)); + } + else if (iid == __uuidof(IMFStreamSink )) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFMediaEventGenerator)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFMediaTypeHandler)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFGetService)) + { + *ppv = static_cast(this); + } + else if (iid == __uuidof(IMFAttributes)) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +ULONG DX11VideoRenderer::CStreamSink::Release(void) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + // For thread safety, return a temporary variable. + return uCount; +} + +/// IMFStreamSink methods + +//------------------------------------------------------------------- +// Name: Flush +// Description: Discards all samples that were not processed yet. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Flush(void) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + m_ConsumeData = DropFrames; + // Note: Even though we are flushing data, we still need to send + // any marker events that were queued. + hr = ProcessSamplesFromQueue(m_ConsumeData); + } + + if (SUCCEEDED(hr)) + { + // This call blocks until the scheduler threads discards all scheduled samples. + m_pScheduler->Flush(); + + hr = m_pPresenter->Flush(); + } + + m_ConsumeData = ProcessFrames; + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetIdentifier +// Description: Returns the stream identifier. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetIdentifier(__RPC__out DWORD* pdwIdentifier) +{ + CAutoLock lock(&m_critSec); + + if (pdwIdentifier == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + *pdwIdentifier = STREAM_ID; + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetMediaSink +// Description: Returns the parent media sink. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetMediaSink(__RPC__deref_out_opt IMFMediaSink** ppMediaSink) +{ + CAutoLock lock(&m_critSec); + + if (ppMediaSink == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + *ppMediaSink = m_pSink; + (*ppMediaSink)->AddRef(); + } + + return hr; + +} + +//------------------------------------------------------------------- +// Name: GetMediaTypeHandler +// Description: Returns a media type handler for this stream. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetMediaTypeHandler(__RPC__deref_out_opt IMFMediaTypeHandler** ppHandler) +{ + CAutoLock lock(&m_critSec); + + if (ppHandler == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + // This stream object acts as its own type handler, so we QI ourselves. + if (SUCCEEDED(hr)) + { + hr = this->QueryInterface(IID_IMFMediaTypeHandler, (void**)ppHandler); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: PlaceMarker +// Description: Receives a marker. [Asynchronous] +// +// Note: The client can call PlaceMarker at any time. In response, +// we need to queue an MEStreamSinkMarker event, but not until +// *after* we have processed all samples that we have received +// up to this point. +// +// Also, in general you might need to handle specific marker +// types, although this sink does not. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::PlaceMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType, __RPC__in const PROPVARIANT* pvarMarkerValue, __RPC__in const PROPVARIANT* pvarContextValue) +{ + + CAutoLock lock(&m_critSec); + + HRESULT hr = S_OK; + + IMarker* pMarker = NULL; + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = ValidateOperation(OpPlaceMarker); + } + + // Create a marker object and put it on the sample queue. + if (SUCCEEDED(hr)) + { + hr = CMarker::Create( + eMarkerType, + pvarMarkerValue, + pvarContextValue, + &pMarker); + } + + if (SUCCEEDED(hr)) + { + hr = m_SamplesToProcess.Queue(pMarker); + } + + // Unless we are paused, start an async operation to dispatch the next sample/marker. + if (SUCCEEDED(hr)) + { + if (m_state != State_Paused) + { + // Queue the operation. + hr = QueueAsyncOperation(OpPlaceMarker); // Increments ref count on pOp. + } + } + SafeRelease(pMarker); + + return hr; +} + +//------------------------------------------------------------------- +// Name: ProcessSample +// Description: Receives an input sample. [Asynchronous] +// +// Note: The client should only give us a sample after we send an +// MEStreamSinkRequestSample event. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::ProcessSample(__RPC__in_opt IMFSample* pSample) +{ + CAutoLock lock(&m_critSec); + + if (pSample == NULL) + { + return E_POINTER; + } + + if (0 == m_cOutstandingSampleRequests) + { + return MF_E_INVALIDREQUEST; + } + + HRESULT hr = S_OK; + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + m_cOutstandingSampleRequests--; + + if (!m_fPrerolling && !m_fWaitingForOnClockStart) + { + // Validate the operation. + hr = ValidateOperation(OpProcessSample); + if (FAILED(hr)) + { + break; + } + } + + // Add the sample to the sample queue. + hr = m_SamplesToProcess.Queue(pSample); + if (FAILED(hr)) + { + break; + } + + if (m_fPrerolling) + { + m_fPrerolling = FALSE; + return QueueEvent(MEStreamSinkPrerolled, GUID_NULL, S_OK, NULL); + } + + // Unless we are paused/stopped, start an async operation to dispatch the next sample. + if (m_state != State_Paused && m_state != State_Stopped) + { + // Queue the operation. + hr = QueueAsyncOperation(OpProcessSample); + } + } + while (FALSE); + + return hr; +} + +// IMFMediaEventGenerator methods. +// Note: These methods call through to the event queue helper object. + +HRESULT DX11VideoRenderer::CStreamSink::BeginGetEvent(IMFAsyncCallback* pCallback, IUnknown* punkState) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pEventQueue->BeginGetEvent(pCallback, punkState); + } + + return hr; +} + +HRESULT DX11VideoRenderer::CStreamSink::EndGetEvent(IMFAsyncResult* pResult, _Out_ IMFMediaEvent** ppEvent) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pEventQueue->EndGetEvent(pResult, ppEvent); + } + + return hr; +} + +HRESULT DX11VideoRenderer::CStreamSink::GetEvent(DWORD dwFlags, __RPC__deref_out_opt IMFMediaEvent** ppEvent) +{ + // NOTE: + // GetEvent can block indefinitely, so we don't hold the lock. + // This requires some juggling with the event queue pointer. + + HRESULT hr = S_OK; + + IMFMediaEventQueue* pQueue = NULL; + + { // scope for lock + + CAutoLock lock(&m_critSec); + + // Check shutdown + hr = CheckShutdown(); + + // Get the pointer to the event queue. + if (SUCCEEDED(hr)) + { + pQueue = m_pEventQueue; + pQueue->AddRef(); + } + + } // release lock + + // Now get the event. + if (SUCCEEDED(hr)) + { + hr = pQueue->GetEvent(dwFlags, ppEvent); + } + + SafeRelease(pQueue); + + return hr; +} + +HRESULT DX11VideoRenderer::CStreamSink::QueueEvent(MediaEventType met, __RPC__in REFGUID guidExtendedType, HRESULT hrStatus, __RPC__in_opt const PROPVARIANT* pvValue) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); + } + + return hr; +} + +/// IMFMediaTypeHandler methods + +//------------------------------------------------------------------- +// Name: GetCurrentMediaType +// Description: Return the current media type, if any. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetCurrentMediaType(_Outptr_ IMFMediaType** ppMediaType) +{ + CAutoLock lock(&m_critSec); + + if (ppMediaType == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + if (m_pCurrentType == NULL) + { + hr = MF_E_NOT_INITIALIZED; + } + } + + if (SUCCEEDED(hr)) + { + *ppMediaType = m_pCurrentType; + (*ppMediaType)->AddRef(); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetMajorType +// Description: Return the major type GUID. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetMajorType(__RPC__out GUID* pguidMajorType) +{ + if (pguidMajorType == NULL) + { + return E_POINTER; + } + + HRESULT hr = CheckShutdown(); + if (FAILED(hr)) + { + return hr; + } + + if (m_pCurrentType == NULL) + { + return MF_E_NOT_INITIALIZED; + } + + return m_pCurrentType->GetGUID(MF_MT_MAJOR_TYPE, pguidMajorType); +} + +//------------------------------------------------------------------- +// Name: GetMediaTypeByIndex +// Description: Return a preferred media type by index. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetMediaTypeByIndex(DWORD dwIndex, _Outptr_ IMFMediaType** ppType) +{ + HRESULT hr = S_OK; + + do + { + if (ppType == NULL) + { + hr = E_POINTER; + break; + } + + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (dwIndex >= s_dwNumVideoFormats) + { + hr = MF_E_NO_MORE_TYPES; + break; + } + + IMFMediaType* pVideoMediaType = NULL; + + do + { + hr = MFCreateMediaType(&pVideoMediaType); + if (FAILED(hr)) + { + break; + } + + hr = pVideoMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); + if (FAILED(hr)) + { + break; + } + + hr = pVideoMediaType->SetGUID(MF_MT_SUBTYPE, *(s_pVideoFormats[dwIndex])); + if (FAILED(hr)) + { + break; + } + + pVideoMediaType->AddRef(); + *ppType = pVideoMediaType; + } + while (FALSE); + + SafeRelease(pVideoMediaType); + + if (FAILED(hr)) + { + break; + } + } + while (FALSE); + + return hr; +} + +//------------------------------------------------------------------- +// Name: GetMediaTypeCount +// Description: Return the number of preferred media types. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetMediaTypeCount(__RPC__out DWORD* pdwTypeCount) +{ + HRESULT hr = S_OK; + + do + { + if (pdwTypeCount == NULL) + { + hr = E_POINTER; + break; + } + + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + *pdwTypeCount = s_dwNumVideoFormats; + } + while (FALSE); + + return hr; +} + +//------------------------------------------------------------------- +// Name: IsMediaTypeSupported +// Description: Check if a media type is supported. +// +// pMediaType: The media type to check. +// ppMediaType: Optionally, receives a "close match" media type. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::IsMediaTypeSupported(IMFMediaType* pMediaType, _Outptr_opt_result_maybenull_ IMFMediaType** ppMediaType) +{ + HRESULT hr = S_OK; + GUID subType = GUID_NULL; + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + if (pMediaType == NULL) + { + hr = E_POINTER; + break; + } + + hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType); + if (FAILED(hr)) + { + break; + } + + hr = MF_E_INVALIDMEDIATYPE; // This will be set to OK if we find the subtype is accepted + + for(DWORD i = 0; i < s_dwNumVideoFormats; i++) + { + if (subType == (*s_pVideoFormats[i])) + { + hr = S_OK; + break; + } + } + + if (FAILED(hr)) + { + break; + } + + for( DWORD i = 0; i < ARRAYSIZE( s_DXGIFormatMapping ); i++ ) + { + const FormatEntry& e = s_DXGIFormatMapping[i]; + if ( e.Subtype == subType ) + { + m_dxgiFormat = e.DXGIFormat; + break; + } + } + + hr = m_pPresenter->IsMediaTypeSupported(pMediaType, m_dxgiFormat); + if (FAILED(hr)) + { + break; + } + } + while (FALSE); + + // We don't return any "close match" types. + if (ppMediaType) + { + *ppMediaType = NULL; + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: SetCurrentMediaType +// Description: Set the current media type. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::SetCurrentMediaType(IMFMediaType* pMediaType) +{ + if (pMediaType == NULL) + { + return E_POINTER; + } + + HRESULT hr = S_OK; + MFRatio fps = { 0, 0 }; + GUID guidSubtype = GUID_NULL; + + CAutoLock lock(&m_critSec); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + hr = ValidateOperation(OpSetMediaType); + if (FAILED(hr)) + { + break; + } + + hr = IsMediaTypeSupported(pMediaType, NULL); + if (FAILED(hr)) + { + break; + } + + SafeRelease(m_pCurrentType); + m_pCurrentType = pMediaType; + m_pCurrentType->AddRef(); + + pMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype); + + if ((guidSubtype == MFVideoFormat_NV12) || + (guidSubtype == MFVideoFormat_YV12) || + (guidSubtype == MFVideoFormat_IYUV) || + (guidSubtype == MFVideoFormat_YVU9) || + (guidSubtype == MFVideoFormat_I420)) + { + m_imageBytesPP.Numerator = 3; + m_imageBytesPP.Denominator = 2; + } + else if ((guidSubtype == MFVideoFormat_YUY2)|| + (guidSubtype == MFVideoFormat_RGB555) || + (guidSubtype == MFVideoFormat_RGB565) || + (guidSubtype == MFVideoFormat_UYVY) || + (guidSubtype == MFVideoFormat_YVYU) || + (guidSubtype == MEDIASUBTYPE_V216)) + { + m_imageBytesPP.Numerator = 2; + m_imageBytesPP.Denominator = 1; + } + else if (guidSubtype == MFVideoFormat_RGB24) + { + m_imageBytesPP.Numerator = 3; + m_imageBytesPP.Denominator = 1; + } + else if (guidSubtype == MFVideoFormat_RGB32) + { + m_imageBytesPP.Numerator = 4; + m_imageBytesPP.Denominator = 1; + } + else if (guidSubtype == MFVideoFormat_v410) + { + m_imageBytesPP.Numerator = 5; + m_imageBytesPP.Denominator = 4; + } + else // includes: + // MFVideoFormat_RGB8 + // MFVideoFormat_AYUV + // MFVideoFormat_NV11 + { + // This is just a fail-safe + m_imageBytesPP.Numerator = 1; + m_imageBytesPP.Denominator = 1; + } + + pMediaType->GetUINT32(MF_MT_INTERLACE_MODE, &m_unInterlaceMode); + + // Set the frame rate on the scheduler. + if (SUCCEEDED(GetFrameRate(pMediaType, &fps)) && (fps.Numerator != 0) && (fps.Denominator != 0)) + { + if (MFVideoInterlace_FieldInterleavedUpperFirst == m_unInterlaceMode || + MFVideoInterlace_FieldInterleavedLowerFirst == m_unInterlaceMode || + MFVideoInterlace_FieldSingleUpper == m_unInterlaceMode || + MFVideoInterlace_FieldSingleLower == m_unInterlaceMode || + MFVideoInterlace_MixedInterlaceOrProgressive == m_unInterlaceMode) + { + fps.Numerator*=2; + } + + m_pScheduler->SetFrameRate(fps); + } + else + { + // NOTE: The mixer's proposed type might not have a frame rate, in which case + // we'll use an arbitary default. (Although it's unlikely the video source + // does not have a frame rate.) + m_pScheduler->SetFrameRate(s_DefaultFrameRate); + } + + // Update the required sample count based on the media type (progressive vs. interlaced) + if (m_unInterlaceMode == MFVideoInterlace_Progressive) + { + // XVP will hold on to 1 sample but that's the same sample we will internally hold on to + hr = SetUINT32(MF_SA_REQUIRED_SAMPLE_COUNT, SAMPLE_QUEUE_HIWATER_THRESHOLD); + } + else + { + // Assume we will need a maximum of 3 backward reference frames for deinterlacing + // However, one of the frames is "shared" with SVR + hr = SetUINT32(MF_SA_REQUIRED_SAMPLE_COUNT, SAMPLE_QUEUE_HIWATER_THRESHOLD + MAX_PAST_FRAMES - 1); + } + + if (SUCCEEDED(hr)) + { + hr = m_pPresenter->SetCurrentMediaType(pMediaType); + if (FAILED(hr)) + { + break; + } + } + + if ( State_Started != m_state && State_Paused != m_state ) + { + m_state = State_Ready; + } + else + { + //Flush all current samples in the Queue as this is a format change + hr = Flush(); + } + } + while (FALSE); + + return hr; +} + +//------------------------------------------------------------------------- +// Name: GetService +// Description: IMFGetService +//------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject) +{ + IMFGetService* pGetService = NULL; + HRESULT hr = m_pSink->QueryInterface(IID_PPV_ARGS(&pGetService)); + if (SUCCEEDED(hr)) + { + hr = pGetService->GetService(guidService, riid, ppvObject); + } + SafeRelease(pGetService); + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: PresentFrame +// +// Synopsis: Present the current outstanding frame in the DX queue +// +//-------------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::PresentFrame(void) +{ + HRESULT hr = S_OK; + + if (DropFrames == m_ConsumeData) + { + return hr; + } + + CAutoLock lock(&m_critSec); + + do + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + hr = m_pPresenter->PresentFrame(); + if (FAILED(hr)) + { + break; + } + } + while (FALSE); + + if (SUCCEEDED(hr)) + { + // Unless we are paused/stopped, start an async operation to dispatch the next sample. + if (m_state != State_Paused && m_state != State_Stopped) + { + // Queue the operation. + hr = QueueAsyncOperation(OpProcessSample); + } + } + else + { + // We are in the middle of an asynchronous operation, so if something failed, send an error. + hr = QueueEvent(MEError, GUID_NULL, hr, NULL); + } + + return hr; +} + +HRESULT DX11VideoRenderer::CStreamSink::GetMaxRate(BOOL fThin, float* pflRate) +{ + HRESULT hr = S_OK; + DWORD dwMonitorRefreshRate = 0; + UINT32 unNumerator = 0; + UINT32 unDenominator = 0; + + do + { + hr = m_pPresenter->GetMonitorRefreshRate(&dwMonitorRefreshRate); + if (FAILED(hr)) + { + break; + } + + if (m_pCurrentType == NULL) + { + hr = MF_E_INVALIDREQUEST; + break; + } + + if (fThin == TRUE) + { + *pflRate = FLT_MAX; + break; + } + + MFGetAttributeRatio(m_pCurrentType, MF_MT_FRAME_RATE, &unNumerator, &unDenominator); + + if (unNumerator == 0 || unDenominator == 0) + { + // We support anything. + *pflRate = FLT_MAX; + } + else + { + if (MFVideoInterlace_FieldInterleavedUpperFirst == m_unInterlaceMode || + MFVideoInterlace_FieldInterleavedLowerFirst == m_unInterlaceMode || + MFVideoInterlace_FieldSingleUpper == m_unInterlaceMode || + MFVideoInterlace_FieldSingleLower == m_unInterlaceMode || + MFVideoInterlace_MixedInterlaceOrProgressive == m_unInterlaceMode) + { + unNumerator*=2; + } + + // + // Only support rates up to the refresh rate of the monitor. + // + *pflRate = (float)MulDiv(dwMonitorRefreshRate, unDenominator, unNumerator); + } + } + while (FALSE); + + return hr; +} + +//------------------------------------------------------------------- +// Name: Initialize +// Description: Initializes the stream sink. +// +// Note: This method is called once when the media sink is first +// initialized. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Initialize(IMFMediaSink* pParent, CPresenter* pPresenter) +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = CMFAttributesImpl::Initialize(); + } + + // Create the event queue helper. + if (SUCCEEDED(hr)) + { + hr = MFCreateEventQueue(&m_pEventQueue); + } + + // Allocate a new work queue for async operations. + if (SUCCEEDED(hr)) + { + hr = MFAllocateWorkQueue(&m_WorkQueueId); + } + + if (SUCCEEDED(hr)) + { + m_pPresenter = pPresenter; + m_pPresenter->AddRef(); + } + + if (SUCCEEDED(hr)) + { + m_pSink = pParent; + m_pSink->AddRef(); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: Pause +// Description: Called when the presentation clock pauses. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Pause(void) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = ValidateOperation(OpPause); + + if (SUCCEEDED(hr)) + { + m_state = State_Paused; + hr = QueueAsyncOperation(OpPause); + } + + return hr; +} + +HRESULT DX11VideoRenderer::CStreamSink::Preroll(void) +{ + HRESULT hr = S_OK; + + CAutoLock lock(&m_critSec); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + m_fPrerolling = TRUE; + m_fWaitingForOnClockStart = TRUE; + + // Kick things off by requesting a sample... + m_cOutstandingSampleRequests++; + + hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: Restart +// Description: Called when the presentation clock restarts. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Restart(void) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = ValidateOperation(OpRestart); + + if (SUCCEEDED(hr)) + { + m_state = State_Started; + hr = QueueAsyncOperation(OpRestart); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: Shutdown +// Description: Shuts down the stream sink. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Shutdown(void) +{ + CAutoLock lock(&m_critSec); + + m_IsShutdown = TRUE; + + if (m_pEventQueue) + { + m_pEventQueue->Shutdown(); + } + + MFUnlockWorkQueue(m_WorkQueueId); + + m_SamplesToProcess.Clear(); + + SafeRelease(m_pSink); + SafeRelease(m_pEventQueue); + SafeRelease(m_pByteStream); + SafeRelease(m_pPresenter); + SafeRelease(m_pCurrentType); + + return MF_E_SHUTDOWN; +} + +//------------------------------------------------------------------- +// Name: Start +// Description: Called when the presentation clock starts. +// Note: Start time can be PRESENTATION_CURRENT_POSITION meaning +// resume from the last current position. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Start(MFTIME start) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = S_OK; + + do + { + hr = ValidateOperation(OpStart); + if (FAILED(hr)) + { + break; + } + + if (start != PRESENTATION_CURRENT_POSITION) + { + // We're starting from a "new" position + m_StartTime = start; // Cache the start time. + } + + m_state = State_Started; + hr = QueueAsyncOperation(OpStart); + } + while (FALSE); + + m_fWaitingForOnClockStart = FALSE; + + return hr; +} + +//------------------------------------------------------------------- +// Name: Stop +// Description: Called when the presentation clock stops. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::Stop(void) +{ + CAutoLock lock(&m_critSec); + + HRESULT hr = ValidateOperation(OpStop); + + if (SUCCEEDED(hr)) + { + m_state = State_Stopped; + hr = QueueAsyncOperation(OpStop); + } + + return hr; +} + +// private methods + +//------------------------------------------------------------------- +// Name: DispatchProcessSample +// Description: Complete a ProcessSample or PlaceMarker request. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::DispatchProcessSample(CAsyncOperation* pOp) +{ + HRESULT hr = S_OK; + assert(pOp != NULL); + + hr = CheckShutdown(); + if (FAILED(hr)) + { + return hr; + } + + if (m_pPresenter->CanProcessNextSample()) + { + hr = ProcessSamplesFromQueue(ProcessFrames); + + // Ask for another sample + if (SUCCEEDED(hr)) + { + if (pOp->m_op == OpProcessSample) + { + hr = RequestSamples(); + } + } + + // We are in the middle of an asynchronous operation, so if something failed, send an error. + if (FAILED(hr)) + { + hr = QueueEvent(MEError, GUID_NULL, hr, NULL); + } + } + + return hr; +} + +HRESULT DX11VideoRenderer::CStreamSink::CheckShutdown(void) const +{ + if (m_IsShutdown) + { + return MF_E_SHUTDOWN; + } + else + { + return S_OK; + } +} + +inline HRESULT DX11VideoRenderer::CStreamSink::GetFrameRate(IMFMediaType* pType, MFRatio* pRatio) +{ + return MFGetAttributeRatio(pType, MF_MT_FRAME_RATE, (UINT32*)&pRatio->Numerator, (UINT32*)&pRatio->Denominator); +} + +//+------------------------------------------------------------------------- +// +// Member: NeedMoreSamples +// +// Synopsis: Returns true if the number of samples in flight +// (queued + requested) is less than the max allowed +// +//-------------------------------------------------------------------------- +BOOL DX11VideoRenderer::CStreamSink::NeedMoreSamples(void) +{ + const DWORD cSamplesInFlight = m_SamplesToProcess.GetCount() + m_cOutstandingSampleRequests; + + return cSamplesInFlight < SAMPLE_QUEUE_HIWATER_THRESHOLD; +} + +//------------------------------------------------------------------- +// Name: OnDispatchWorkItem +// Description: Callback for MFPutWorkItem. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::OnDispatchWorkItem(IMFAsyncResult* pAsyncResult) +{ + // Called by work queue thread. Need to hold the critical section. + CAutoLock lock(&m_critSec); + + HRESULT hr = CheckShutdown(); + if (FAILED(hr)) + { + return hr; + } + + IUnknown* pState = NULL; + + hr = pAsyncResult->GetState(&pState); + + if (SUCCEEDED(hr)) + { + // The state object is a CAsncOperation object. + CAsyncOperation* pOp = (CAsyncOperation*)pState; + + StreamOperation op = pOp->m_op; + + switch (op) + { + case OpStart: + case OpRestart: + // Send MEStreamSinkStarted. + hr = QueueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL); + + // Kick things off by requesting two samples... + if (SUCCEEDED(hr)) + { + m_cOutstandingSampleRequests++; + hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL); + } + + // There might be samples queue from earlier (ie, while paused). + if (SUCCEEDED(hr)) + { + hr = ProcessSamplesFromQueue(m_ConsumeData); + } + + break; + + case OpStop: + + m_pPresenter->SetFullscreen(FALSE); + + // Drop samples from queue. + Flush(); + + m_cOutstandingSampleRequests = 0; + + // Send the event even if the previous call failed. + hr = QueueEvent(MEStreamSinkStopped, GUID_NULL, hr, NULL); + + break; + + case OpPause: + hr = QueueEvent(MEStreamSinkPaused, GUID_NULL, hr, NULL); + break; + + case OpProcessSample: + case OpPlaceMarker: + if (!(m_fWaitingForOnClockStart)) + { + hr = DispatchProcessSample(pOp); + } + break; + } + } + + SafeRelease(pState); + + return hr; +} + +//------------------------------------------------------------------- +// Name: ProcessSamplesFromQueue +// Description: +// +// Removes all of the samples and markers that are currently in the +// queue and processes them. +// +// If bConsumeData = DropFrames +// For each marker, send an MEStreamSinkMarker event, with hr = E_ABORT. +// For each sample, drop the sample. +// +// If bConsumeData = ProcessFrames +// For each marker, send an MEStreamSinkMarker event, with hr = S_OK. +// For each sample, write the sample to the file. +// +// This method is called when we flush, stop, restart, receive a new +// sample, or receive a marker. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::ProcessSamplesFromQueue(ConsumeState bConsumeData) +{ + HRESULT hr = S_OK; + IUnknown* pUnk = NULL; + BOOL bProcessMoreSamples = TRUE; + BOOL bDeviceChanged = FALSE; + BOOL bProcessAgain = FALSE; + + // Enumerate all of the samples/markers in the queue. + + // Note: Dequeue returns S_FALSE when the queue is empty. + while (m_SamplesToProcess.Dequeue(&pUnk) == S_OK) + { + bProcessMoreSamples = TRUE; + IMarker* pMarker = NULL; + IMFSample* pSample = NULL; + IMFSample* pOutSample = NULL; + + // Figure out if this is a marker or a sample. + + hr = pUnk->QueryInterface(__uuidof(IMarker), (void**)&pMarker); + if (hr == E_NOINTERFACE) + { + // If this is a sample, write it to the file. + hr = pUnk->QueryInterface(IID_IMFSample, (void**)&pSample); + } + + // Now handle the sample/marker appropriately. + if (SUCCEEDED(hr)) + { + if (pMarker) + { + hr = SendMarkerEvent(pMarker, bConsumeData); + } + else + { + assert(pSample != NULL); // Not a marker, must be a sample + if (bConsumeData == ProcessFrames) + { + hr = m_pPresenter->ProcessFrame(m_pCurrentType, pSample, &m_unInterlaceMode, &bDeviceChanged, &bProcessAgain, &pOutSample); + + if (SUCCEEDED(hr)) + { + if (bDeviceChanged) + { + QueueEvent(MEStreamSinkDeviceChanged, GUID_NULL, S_OK, NULL); + } + + if (bProcessAgain) + { + // The input sample is not used. Return it to the queue. + hr = m_SamplesToProcess.PutBack(pSample); + } + } + + // If we are not actively playing, OR we are scrubbing (rate = 0) OR this is a + // repaint request, then we need to present the sample immediately. Otherwise, + // schedule it normally. + if (SUCCEEDED(hr)) + { + if (pOutSample) + { + hr = m_pScheduler->ScheduleSample(pOutSample, (State_Started != m_state)); + bProcessMoreSamples = FALSE; + } + } + } + } + } + + SafeRelease(pUnk); + SafeRelease(pMarker); + SafeRelease(pSample); + SafeRelease(pOutSample); + + if (!bProcessMoreSamples) + { + break; + } + } // while loop + + SafeRelease(pUnk); + + return hr; +} + +//------------------------------------------------------------------- +// Name: QueueAsyncOperation +// Description: Puts an async operation on the work queue. +//------------------------------------------------------------------- +HRESULT DX11VideoRenderer::CStreamSink::QueueAsyncOperation(StreamOperation op) +{ + HRESULT hr = S_OK; + CAsyncOperation* pOp = new CAsyncOperation(op); // Created with ref count = 1 + if (pOp == NULL) + { + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + hr = MFPutWorkItem(m_WorkQueueId, &m_WorkQueueCB, pOp); + } + + SafeRelease(pOp); // Releases ref count + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Member: RequestSamples +// +// Synopsis: Issue more sample requests if necessary. +// +//-------------------------------------------------------------------------- +HRESULT DX11VideoRenderer::CStreamSink::RequestSamples(void) +{ + HRESULT hr = S_OK; + + while (NeedMoreSamples()) + { + hr = CheckShutdown(); + if (FAILED(hr)) + { + break; + } + + m_cOutstandingSampleRequests++; + + hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); + } + + return hr; +} + +//------------------------------------------------------------------- +// Name: SendMarkerEvent +// Description: Saned a marker event. +// +// pMarker: Pointer to our custom IMarker interface, which holds +// the marker information. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::SendMarkerEvent(IMarker* pMarker, ConsumeState ConsumeState) +{ + HRESULT hr = S_OK; + HRESULT hrStatus = S_OK; // Status code for marker event. + + PROPVARIANT var; + PropVariantInit(&var); + + do + { + if (ConsumeState == DropFrames) + { + hrStatus = E_ABORT; + } + + // Get the context data. + hr = pMarker->GetContext(&var); + + if (SUCCEEDED(hr)) + { + hr = QueueEvent(MEStreamSinkMarker, GUID_NULL, hrStatus, &var); + } + } + while (FALSE); + + PropVariantClear(&var); + + return hr; +} + +//------------------------------------------------------------------- +// Name: ValidateOperation +// Description: Checks if an operation is valid in the current state. +//------------------------------------------------------------------- + +HRESULT DX11VideoRenderer::CStreamSink::ValidateOperation(StreamOperation op) +{ + HRESULT hr = S_OK; + + BOOL bTransitionAllowed = ValidStateMatrix[m_state][op]; + + if (bTransitionAllowed) + { + return S_OK; + } + else + { + return MF_E_INVALIDREQUEST; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// CAsyncOperation class. - Private class used by CStreamSink class. +// +///////////////////////////////////////////////////////////////////////////////////////////// + +DX11VideoRenderer::CStreamSink::CAsyncOperation::CAsyncOperation(StreamOperation op) : + m_nRefCount(1), + m_op(op) +{ +} + +ULONG DX11VideoRenderer::CStreamSink::CAsyncOperation::AddRef(void) +{ + return InterlockedIncrement(&m_nRefCount); +} + +HRESULT DX11VideoRenderer::CStreamSink::CAsyncOperation::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv) +{ + if (!ppv) + { + return E_POINTER; + } + if (iid == IID_IUnknown) + { + *ppv = static_cast(this); + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +ULONG DX11VideoRenderer::CStreamSink::CAsyncOperation::Release(void) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + // For thread safety, return a temporary variable. + return uCount; +} + +DX11VideoRenderer::CStreamSink::CAsyncOperation::~CAsyncOperation(void) +{ +} \ No newline at end of file diff --git a/Samples/DX11VideoRenderer/cpp/StreamSink.h b/Samples/DX11VideoRenderer/cpp/StreamSink.h new file mode 100644 index 00000000..c0c73a7d --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/StreamSink.h @@ -0,0 +1,186 @@ +#pragma once + +#include "Common.h" +#include "display.h" +#include "MFAttributesImpl.h" +#include "Marker.h" +#include "Presenter.h" +#include "Scheduler.h" + +namespace DX11VideoRenderer +{ + class CStreamSink : + public IMFStreamSink, + public IMFMediaTypeHandler, + public IMFGetService, + public SchedulerCallback, + public CMFAttributesImpl, + private CBase + { + public: + + CStreamSink(DWORD dwStreamId, CCritSec& critSec, CScheduler* pScheduler); + virtual ~CStreamSink(void); + + // IUnknown + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv); + STDMETHODIMP_(ULONG) Release(void); + + // IMFStreamSink + STDMETHODIMP Flush(void); + STDMETHODIMP GetIdentifier(__RPC__out DWORD* pdwIdentifier); + STDMETHODIMP GetMediaSink(__RPC__deref_out_opt IMFMediaSink** ppMediaSink); + STDMETHODIMP GetMediaTypeHandler(__RPC__deref_out_opt IMFMediaTypeHandler** ppHandler); + STDMETHODIMP PlaceMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType, __RPC__in const PROPVARIANT* pvarMarkerValue, __RPC__in const PROPVARIANT* pvarContextValue); + STDMETHODIMP ProcessSample(__RPC__in_opt IMFSample* pSample); + + // IMFMediaEventGenerator (from IMFStreamSink) + STDMETHODIMP BeginGetEvent(IMFAsyncCallback* pCallback,IUnknown* punkState); + STDMETHODIMP EndGetEvent(IMFAsyncResult* pResult, _Out_ IMFMediaEvent** ppEvent); + STDMETHODIMP GetEvent(DWORD dwFlags, __RPC__deref_out_opt IMFMediaEvent** ppEvent); + STDMETHODIMP QueueEvent(MediaEventType met, __RPC__in REFGUID guidExtendedType, HRESULT hrStatus, __RPC__in_opt const PROPVARIANT* pvValue); + + // IMFMediaTypeHandler + STDMETHODIMP GetCurrentMediaType(_Outptr_ IMFMediaType** ppMediaType); + STDMETHODIMP GetMajorType(__RPC__out GUID* pguidMajorType); + STDMETHODIMP GetMediaTypeByIndex(DWORD dwIndex, _Outptr_ IMFMediaType** ppType); + STDMETHODIMP GetMediaTypeCount(__RPC__out DWORD* pdwTypeCount); + STDMETHODIMP IsMediaTypeSupported(IMFMediaType* pMediaType, _Outptr_opt_result_maybenull_ IMFMediaType** ppMediaType); + STDMETHODIMP SetCurrentMediaType(IMFMediaType* pMediaType); + + // IMFGetService + STDMETHODIMP GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject); + + // SchedulerCallback + HRESULT PresentFrame(void); + + HRESULT GetMaxRate(BOOL fThin, float* pflRate); + HRESULT Initialize(IMFMediaSink* pParent, CPresenter* pPresenter); + inline BOOL IsActive(void) const // IsActive: The "active" state is started or paused. + { + return ((m_state == State_Started) || (m_state == State_Paused)); + } + HRESULT Pause(void); + HRESULT Preroll(void); + HRESULT Restart(void); + HRESULT Shutdown(void); + HRESULT Start(MFTIME start); + HRESULT Stop(void); + + private: + + // State enum: Defines the current state of the stream. + enum State + { + State_TypeNotSet = 0, // No media type is set + State_Ready, // Media type is set, Start has never been called. + State_Started, + State_Paused, + State_Stopped, + + State_Count // Number of states + }; + + // StreamOperation: Defines various operations that can be performed on the stream. + enum StreamOperation + { + OpSetMediaType = 0, + OpStart, + OpRestart, + OpPause, + OpStop, + OpProcessSample, + OpPlaceMarker, + + Op_Count // Number of operations + }; + + enum ConsumeState + { + DropFrames = 0, + ProcessFrames + }; + + // CAsyncOperation: + // Used to queue asynchronous operations. When we call MFPutWorkItem, we use this + // object for the callback state (pState). Then, when the callback is invoked, + // we can use the object to determine which asynchronous operation to perform. + + // Optional data can include a sample (IMFSample) or a marker. + // When ProcessSample is called, we use it to queue a sample. When ProcessMarker is + // called, we use it to queue a marker. This way, samples and markers can live in + // the same queue. We need this because the sink has to serialize marker events + // with sample processing. + class CAsyncOperation : public IUnknown + { + public: + + CAsyncOperation(StreamOperation op); + + // IUnknown methods. + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv); + STDMETHODIMP_(ULONG) Release(void); + + // Structure data. + StreamOperation m_op; // The operation to perform. + PROPVARIANT m_varDataWM; // Optional data, only used for water mark + + private: + + virtual ~CAsyncOperation(void); + + long m_nRefCount; + }; + + static GUID const* const s_pVideoFormats[]; + static const DWORD s_dwNumVideoFormats; + static const MFRatio s_DefaultFrameRate; + static const struct FormatEntry + { + GUID Subtype; + DXGI_FORMAT DXGIFormat; + } s_DXGIFormatMapping[]; + static BOOL ValidStateMatrix[State_Count][Op_Count]; // Defines a look-up table that says which operations are valid from which states. + + HRESULT DispatchProcessSample(CAsyncOperation* pOp); + HRESULT CheckShutdown(void) const; + HRESULT GetFrameRate(IMFMediaType* pType, MFRatio* pRatio); + BOOL NeedMoreSamples(void); + HRESULT OnDispatchWorkItem(IMFAsyncResult* pAsyncResult); + HRESULT ProcessSamplesFromQueue(ConsumeState bConsumeData); + HRESULT QueueAsyncOperation(StreamOperation op); + HRESULT RequestSamples(void); + HRESULT SendMarkerEvent(IMarker* pMarker, ConsumeState bConsumeData); + HRESULT ValidateOperation(StreamOperation op); + + const DWORD STREAM_ID; + long m_nRefCount; // reference count + CCritSec& m_critSec; // critical section for thread safety + State m_state; + BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called. + DWORD m_WorkQueueId; // ID of the work queue for asynchronous operations. + CAsyncCallback m_WorkQueueCB; // Callback for the work queue. + ConsumeState m_ConsumeData; // Flag to indicate process or drop frames + MFTIME m_StartTime; // Presentation time when the clock started. + DWORD m_cbDataWritten; // How many bytes we have written so far. + DWORD m_cOutstandingSampleRequests; // Outstanding reuqests for samples. + IMFMediaSink* m_pSink; // Parent media sink + IMFMediaEventQueue* m_pEventQueue; // Event queue + IMFByteStream* m_pByteStream; // Bytestream where we write the data. + CPresenter* m_pPresenter; + CScheduler* m_pScheduler; + IMFMediaType* m_pCurrentType; + BOOL m_fPrerolling; + BOOL m_fWaitingForOnClockStart; + ThreadSafeQueue m_SamplesToProcess; // Queue to hold samples and markers. Applies to: ProcessSample, PlaceMarker + UINT32 m_unInterlaceMode; + struct sFraction + { + DWORD Numerator; + DWORD Denominator; + } m_imageBytesPP; + DXGI_FORMAT m_dxgiFormat; + }; +} diff --git a/Samples/DX11VideoRenderer/cpp/display.cpp b/Samples/DX11VideoRenderer/cpp/display.cpp new file mode 100644 index 00000000..131e8270 --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/display.cpp @@ -0,0 +1,313 @@ +/******************************Module*Header*******************************\ +* Module Name: display.cpp +* +* Support for DDraw device on Multiple Monitors. +* +* +* Created: Mon 01/24/2000 +* Author: Stephen Estrop [StEstrop] +* Mod: KirtD - First integration into MF renderer model +* +* Copyright (c) Microsoft Corporation +\**************************************************************************/ +#include +#include +#include "display.h" +#include + + +#ifndef DEFAULT_DENSITY_LIMIT +#define DEFAULT_DENSITY_LIMIT 60 +#endif +#ifndef WIDTH +#define WIDTH(x) ((x)->right - (x)->left) +#endif +#ifndef HEIGHT +#define HEIGHT(x) ((x)->bottom - (x)->top) +#endif + + +/* ------------------------------------------------------------------------- +** Structure use to pass info to the DDrawEnumEx callback +** ------------------------------------------------------------------------- +*/ + +struct DDRAWINFO +{ + DWORD dwCount; + DWORD dwPmiSize; + HRESULT hrCallback; + const GUID* pGUID; + CAMDDrawMonitorInfo* pmi; + HWND hwnd; +}; + +/******************************Public*Routine******************************\ +* TermDDrawMonitorInfo +* +* +* +* History: +* 01-17-2000 - StEstrop - Created +* +\**************************************************************************/ +void CMonitorArray::TermDDrawMonitorInfo( + _Inout_ CAMDDrawMonitorInfo* pmi + ) +{ + + + ZeroMemory(pmi, sizeof(CAMDDrawMonitorInfo)); +} + +/*****************************Private*Routine******************************\ +* GetAMDDrawMonitorInfo +* +* +* +* History: +* Tue 08/17/1999 - StEstrop - Created +* +\**************************************************************************/ +BOOL CMonitorArray::GetAMDDrawMonitorInfo( + UINT uDevID, + _Out_ CAMDDrawMonitorInfo* lpmi, + _In_ HMONITOR hm + ) +{ + MONITORINFOEX miInfoEx; + miInfoEx.cbSize = sizeof(miInfoEx); + + lpmi->hMon = NULL; + lpmi->uDevID = 0; + lpmi->physMonDim.cx = 0; + lpmi->physMonDim.cy = 0; + lpmi->dwRefreshRate = DEFAULT_DENSITY_LIMIT; + + if (GetMonitorInfo(hm, &miInfoEx)) + { + HRESULT hr = StringCchCopy(lpmi->szDevice, sizeof(lpmi->szDevice)/sizeof(lpmi->szDevice[0]), miInfoEx.szDevice); + + if ( FAILED( hr ) ) + { + return FALSE; + } + + lpmi->hMon = hm; + lpmi->uDevID = uDevID; + lpmi->physMonDim.cx = WIDTH(&miInfoEx.rcMonitor); + lpmi->physMonDim.cy = HEIGHT(&miInfoEx.rcMonitor); + + int j = 0; + DISPLAY_DEVICE ddMonitor; + + ddMonitor.cb = sizeof(ddMonitor); + while (EnumDisplayDevices(lpmi->szDevice, j, &ddMonitor, 0)) + { + if (ddMonitor.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) + { + DEVMODE dm; + + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + if (EnumDisplaySettings(lpmi->szDevice, ENUM_CURRENT_SETTINGS, &dm)) + { + lpmi->dwRefreshRate = dm.dmDisplayFrequency == 0 ? lpmi->dwRefreshRate : dm.dmDisplayFrequency; + } + + // Remove registry snooping for monitor dimensions, as this is not supported by LDDM. + // if (!FindMonitorDimensions(ddMonitor.DeviceID, &lpmi->physMonDim.cx, &lpmi->physMonDim.cy)) + { + lpmi->physMonDim.cx = WIDTH(&miInfoEx.rcMonitor); + lpmi->physMonDim.cy = HEIGHT(&miInfoEx.rcMonitor); + } + } + j++; + } + + return TRUE; + } + + return FALSE; +} + + +BOOL CMonitorArray::InitMonitor( + _In_ HMONITOR hMon, + BOOL fXclMode + ) +{ + + + if (GetAMDDrawMonitorInfo(m_dwNumMonitors, &m_DDMon[m_dwNumMonitors], hMon)) + { + m_DDMon[m_dwNumMonitors].pDD = (IUnknown*)1; // make checks for pDD succeed. + m_dwNumMonitors++; + } + + if (EVR_MAX_MONITORS >= m_dwNumMonitors) + { + // don't exceed array bounds + return TRUE; + } + + return FALSE; +} + + +BOOL CALLBACK CMonitorArray::MonitorEnumProc( + _In_ HMONITOR hMon, + _In_opt_ HDC hDC, + _In_ LPRECT pRect, + LPARAM dwData + ) +{ + MonitorEnumProcInfo* info = (MonitorEnumProcInfo*)dwData; + + if (!info) + { + return TRUE; + } + + return info->pMonArray->InitMonitor(hMon, FALSE); +} + +/*****************************Private*Routine******************************\ +* InitializeDisplaySystem +* +* +* +* History: +* Mon 01/24/2000 - StEstrop - Created +* +\**************************************************************************/ +HRESULT CMonitorArray::InitializeDisplaySystem( + _In_ HWND hwnd + ) +{ + HRESULT hr = S_OK; + + MonitorEnumProcInfo info; + + info.hwnd = hwnd; + info.pMonArray = this; + + EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, (LPARAM)&info); + + if (m_dwNumMonitors == 0) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + return(hr); + } + + return(hr); +} + +/*****************************Private*Routine******************************\ +* FindMonitor +* +* find the current monitor +* +* History: +* Fri 04/25/2000 - GlennE - Created +* +\**************************************************************************/ +CAMDDrawMonitorInfo* CMonitorArray::FindMonitor( + _In_ HMONITOR hMon + ) +{ + + + for (DWORD i = 0; i < m_dwNumMonitors; i++) + { + if (hMon == m_DDMon[i].hMon) + { + return &m_DDMon[i]; + } + } + + return NULL; +} + +/*****************************Private*Routine******************************\ +* MatchGUID +* +* +* +* History: +* Fri 04/25/2000 - GlennE - Created +* +\**************************************************************************/ +HRESULT CMonitorArray::MatchGUID( + UINT uDevID, + _Out_ DWORD* pdwMatchID + ) +{ + HRESULT hr = S_OK; + + *pdwMatchID = 0; + + for (DWORD i = 0; i < m_dwNumMonitors; i++) + { + + UINT uMonDevID = m_DDMon[i].uDevID; + + if (uDevID == uMonDevID) + { + + *pdwMatchID = i; + hr = S_OK; + return( hr ); + } + } + + hr = S_FALSE; + return( hr ); +} + + +/*****************************Private*Routine******************************\ +* TerminateDisplaySystem +* +* +* +* History: +* Mon 01/24/2000 - StEstrop - Created +* +\**************************************************************************/ +void CMonitorArray::TerminateDisplaySystem() +{ + + + for (DWORD i = 0; i < m_dwNumMonitors; i++) + { + TermDDrawMonitorInfo(&m_DDMon[i]); + } + m_dwNumMonitors = 0; +} + + +/******************************Public*Routine******************************\ +* Constructor and destructor +* +* +* +* History: +* Fri 11/17/2001 - StEstrop - Created +* +\**************************************************************************/ +CMonitorArray::CMonitorArray() + : m_dwNumMonitors(0) +{ + + + ZeroMemory(m_DDMon, sizeof(m_DDMon)); +} + + +CMonitorArray::~CMonitorArray() +{ + + TerminateDisplaySystem(); +} + diff --git a/Samples/DX11VideoRenderer/cpp/display.h b/Samples/DX11VideoRenderer/cpp/display.h new file mode 100644 index 00000000..529d35dc --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/display.h @@ -0,0 +1,73 @@ +/******************************Module*Header*******************************\ +* Module Name: display.h +* +* +* +* +* Created: Mon 01/24/2000 +* Author: Stephen Estrop [StEstrop] +* +* Copyright (c) Microsoft Corporation +\**************************************************************************/ + +#if !defined(__DISPLAY_H__) +#define __DISPLAY_H__ + +#define AMDDRAWMONITORINFO_PRIMARY_MONITOR 0x0001 + +struct CAMDDrawMonitorInfo +{ + UINT uDevID; + HMONITOR hMon; + TCHAR szDevice[ 32 ]; + LARGE_INTEGER liDriverVersion; + DWORD dwVendorId; + DWORD dwDeviceId; + DWORD dwSubSysId; + DWORD dwRevision; + SIZE physMonDim; + DWORD dwRefreshRate; + IUnknown *pDD; +}; + +#define EVR_MAX_MONITORS 16 + +class CMonitorArray +{ +public: + CMonitorArray(); + virtual ~CMonitorArray(); + + virtual HRESULT InitializeDisplaySystem(_In_ HWND hwnd); + + virtual HRESULT InitializeXclModeDisplaySystem(_In_ IUnknown* lpDD, _Out_ UINT* pAdapterID) { return E_NOTIMPL; } + + virtual void TerminateDisplaySystem(); + CAMDDrawMonitorInfo* FindMonitor(_In_ HMONITOR hMon); + HRESULT MatchGUID(UINT uDevID, _Out_ DWORD* pdwMatchID ); + + + CAMDDrawMonitorInfo& operator[](int i) + { return m_DDMon[i]; } + DWORD Count() const + { return m_dwNumMonitors; } + + static BOOL CALLBACK MonitorEnumProc(_In_ HMONITOR hMon, _In_opt_ HDC hDC, _In_ LPRECT pRect, LPARAM dwData); + + virtual BOOL InitMonitor(_In_ HMONITOR hMon, BOOL fXclMode); +protected: + BOOL GetAMDDrawMonitorInfo(UINT uDevID, _Out_ CAMDDrawMonitorInfo* lpmi, _In_ HMONITOR hm); + + virtual void TermDDrawMonitorInfo(_Inout_ CAMDDrawMonitorInfo* pmi); + + DWORD m_dwNumMonitors; + CAMDDrawMonitorInfo m_DDMon[EVR_MAX_MONITORS]; +}; + +typedef struct { + HWND hwnd; + CMonitorArray* pMonArray; +} MonitorEnumProcInfo; + +#endif // !defined(__DISPLAY_H__) + diff --git a/Samples/DX11VideoRenderer/cpp/linklist.h b/Samples/DX11VideoRenderer/cpp/linklist.h new file mode 100644 index 00000000..8d176e8f --- /dev/null +++ b/Samples/DX11VideoRenderer/cpp/linklist.h @@ -0,0 +1,735 @@ +//----------------------------------------------------------------------------- +// File: Linklist.h +// Desc: Linked list class. +// Copyright (C) Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + + +// Notes: +// +// This class template implements a simple double-linked list. +// Objects are held as pointers. (Does not use STL's copy semantics.) +// The Clear() method takes a functor object that releases the objects. + +#pragma once + +#include +#include +#include + +template +class List +{ +protected: + + // Nodes in the linked list + struct Node + { + Node *prev; + Node *next; + T *item; + + Node() : prev(NULL), next(NULL), item(NULL) + { + } + + Node(T* item) : prev(NULL), next(NULL) + { + this->item = item; + } + + T* Item() const { return item; } + }; + + + +protected: + Node m_anchor; // Anchor node for the linked list. + DWORD m_count; // Number of items in the list + + Node *m_pEnum; // Enumeration node + + void InvalidateEnumerator() + { + m_pEnum = NULL; + } + + Node* Front() const + { + return m_anchor.next; + } + + Node* Back() const + { + return m_anchor.prev; + } + + virtual HRESULT InsertAfter(T* item, Node *pBefore) + { + if (item == NULL || pBefore == NULL) + { + return E_POINTER; + } + + Node *pNode = new Node(item); + if (pNode == NULL) + { + return E_OUTOFMEMORY; + } + + Node *pAfter = pBefore->next; + + pBefore->next = pNode; + pAfter->prev = pNode; + + pNode->prev = pBefore; + pNode->next = pAfter; + + m_count++; + + InvalidateEnumerator(); + + return S_OK; + } + + virtual HRESULT GetItem(Node *pNode, T** ppItem) + { + if (pNode == NULL || ppItem == NULL) + { + return E_POINTER; + } + + if (pNode->item) + { + *ppItem = pNode->item; + return S_OK; + } + else + { + return E_INVALIDARG; + } + } + + + // RemoveItem: + // Removes a node and optionally returns the item. + // ppItem can be NULL. + virtual HRESULT RemoveItem(Node *pNode, T **ppItem) + { + if (pNode == NULL) + { + return E_POINTER; + } + + if (pNode == &m_anchor) + { + return E_INVALIDARG; + } + + + T* item = NULL; + + // anchor points back to the previous thing + m_anchor.prev = pNode->prev; + + // the previous thing points to the anchor + pNode->prev->next = &m_anchor; + + item = pNode->item; + delete pNode; + + m_count--; + + if (ppItem) + { + *ppItem = item; + } + + InvalidateEnumerator(); + + return S_OK; + } + +public: + + List() + { + m_anchor.next = &m_anchor; + m_anchor.prev = &m_anchor; + + m_count = 0; + + m_pEnum = NULL; + } + + virtual ~List() + { + + } + + // Insertion functions + HRESULT InsertBack(T* item) + { + return InsertAfter(item, m_anchor.prev); + } + + HRESULT InsertFront(T* item) + { + return InsertAfter(item, &m_anchor); + } + + // RemoveBack: Removes the tail of the list and returns the value. + HRESULT RemoveBack(T **ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return RemoveItem(Back(), ppItem); + } + } + + // RemoveFront: Removes the head of the list and returns the value. + HRESULT RemoveFront(T **ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return RemoveItem(Front(), ppItem); + } + } + + HRESULT PopFront() + { + return RemoveFront(NULL); + } + + HRESULT PopBack() + { + return RemoveBack(NULL); + } + + HRESULT GetBack(T **ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return GetItem(Back(), ppItem); + } + } + + HRESULT GetFront(T **ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return GetItem(Front(), ppItem); + } + } + + // GetCount: Returns the number of items in the list. + DWORD GetCount() const { return m_count; } + + bool IsEmpty() const + { + return (GetCount() == 0); + } + + // Clear: Takes a functor object whose operator() + // frees the object on the list. + template + void Clear(FN& clear_fn) + { + Node *n = m_anchor.next; + + // Delete the nodes + while (n != &m_anchor) + { + clear_fn(n->item); + + Node *tmp = n->next; + delete n; + n = tmp; + } + + // Reset the anchor to point at itself + m_anchor.next = &m_anchor; + m_anchor.prev = &m_anchor; + + m_count = 0; + } + + // Enumerator functions + void ResetEnumerator() + { + m_pEnum = Front(); + } + + HRESULT Next(T **ppItem) + { + if (ppItem == NULL) + { + return E_POINTER; + } + + if (m_pEnum == NULL) + { + return E_FAIL; // Needs reset + } + + if (m_pEnum == &m_anchor) + { + return __HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); + } + + HRESULT hr = GetItem(m_pEnum, ppItem); + + if (SUCCEEDED(hr)) + { + m_pEnum = m_pEnum->next; + } + return hr; + } + +}; + + + +// Typical functors for Clear method. + +// ComAutoRelease: Releases COM pointers. +// MemDelete: Deletes pointers to new'd memory. + +class ComAutoRelease +{ +public: + void operator()(IUnknown *p) + { + if (p) + { + p->Release(); + } + } +}; + +class MemDelete +{ +public: + void operator()(void *p) + { + if (p) + { + delete p; + } + } +}; + + + //ComPtrList class + //Derived class that makes it safer to store COM pointers in the List<> class. + //It automatically AddRef's the pointers that are inserted onto the list + //(unless the insertion method fails). + + //T must be a COM interface type. + +template +class ComPtrList : public List +{ +public: + void Clear() + { + List::Clear(ComAutoRelease()); + } + +protected: + HRESULT InsertAfter(T* item, Node *pBefore) + { + item->AddRef(); + + HRESULT hr = List::InsertAfter(item, pBefore); + if (FAILED(hr)) + { + item->Release(); + } + return hr; + } + + HRESULT GetItem(Node *pNode, T** ppItem) + { + HRESULT hr = List::GetItem(pNode, ppItem); + if (SUCCEEDED(hr)) + { + (*ppItem)->AddRef(); + } + return hr; + } + + HRESULT RemoveItem(Node *pNode, T **ppItem) + { + // ppItem can be NULL, but we need to get the + // item so that we can release it. + + // If ppItem is not NULL, we will AddRef it on the way out/ + + T* item = NULL; + + HRESULT hr = List::RemoveItem(pNode, &item); + + if (SUCCEEDED(hr)) + { + if (ppItem) + { + *ppItem = item; + (*ppItem)->AddRef(); + } + + item->Release(); + } + + return hr; + } + +}; + +template +class ComPtrListEx +{ +protected: + + typedef T* Ptr; + + // Nodes in the linked list + struct Node + { + Node *prev; + Node *next; + Ptr item; + + Node() : prev(NULL), next(NULL), item(NULL) + { + } + + Node(Ptr item) : prev(NULL), next(NULL) + { + this->item = item; + if (item) + { + item->AddRef(); + } + } + ~Node() + { + if (item) + { + item->Release(); + } + } + + Ptr Item() const { return item; } + }; + +public: + + // Object for enumerating the list. + class POSITION + { + friend class ComPtrListEx; + + public: + POSITION() : pNode(NULL) + { + } + + bool operator==(const POSITION &p) const + { + return pNode == p.pNode; + } + + bool operator!=(const POSITION &p) const + { + return pNode != p.pNode; + } + + private: + const Node *pNode; + + POSITION(Node *p) : pNode(p) + { + } + }; + +protected: + Node m_anchor; // Anchor node for the linked list. + DWORD m_count; // Number of items in the list. + + Node* Front() const + { + return m_anchor.next; + } + + Node* Back() const + { + return m_anchor.prev; + } + + virtual HRESULT InsertAfter(Ptr item, Node *pBefore) + { + if (pBefore == NULL) + { + return E_POINTER; + } + + // Do not allow NULL item pointers unless NULLABLE is true. + if (!item && !NULLABLE) + { + return E_POINTER; + } + + Node *pNode = new Node(item); + if (pNode == NULL) + { + return E_OUTOFMEMORY; + } + + Node *pAfter = pBefore->next; + + pBefore->next = pNode; + pAfter->prev = pNode; + + pNode->prev = pBefore; + pNode->next = pAfter; + + m_count++; + + return S_OK; + } + + virtual HRESULT GetItem(const Node *pNode, Ptr* ppItem) + { + if (pNode == NULL || ppItem == NULL) + { + return E_POINTER; + } + + *ppItem = pNode->item; + + if (*ppItem) + { + (*ppItem)->AddRef(); + } + + return S_OK; + } + + // RemoveItem: + // Removes a node and optionally returns the item. + // ppItem can be NULL. + virtual HRESULT RemoveItem(Node *pNode, Ptr *ppItem) + { + if (pNode == NULL) + { + return E_POINTER; + } + + assert(pNode != &m_anchor); // We should never try to remove the anchor node. + if (pNode == &m_anchor) + { + return E_INVALIDARG; + } + + + Ptr item; + + // The next node's previous is this node's previous. + pNode->next->prev = pNode->prev; + + // The previous node's next is this node's next. + pNode->prev->next = pNode->next; + + item = pNode->item; + + if (ppItem) + { + *ppItem = item; + + if (*ppItem) + { + (*ppItem)->AddRef(); + } + } + + delete pNode; + m_count--; + + return S_OK; + } + +public: + + ComPtrListEx() + { + m_anchor.next = &m_anchor; + m_anchor.prev = &m_anchor; + + m_count = 0; + } + + virtual ~ComPtrListEx() + { + Clear(); + } + + void Clear() + { + Node *n = m_anchor.next; + + // Delete the nodes + while (n != &m_anchor) + { + if (n->item) + { + n->item->Release(); + n->item = NULL; + } + + Node *tmp = n->next; + delete n; + n = tmp; + } + + // Reset the anchor to point at itself + m_anchor.next = &m_anchor; + m_anchor.prev = &m_anchor; + + m_count = 0; + } + + // Insertion functions + HRESULT InsertBack(Ptr item) + { + return InsertAfter(item, m_anchor.prev); + } + + + HRESULT InsertFront(Ptr item) + { + return InsertAfter(item, &m_anchor); + } + + // RemoveBack: Removes the tail of the list and returns the value. + // ppItem can be NULL if you don't want the item back. + HRESULT RemoveBack(Ptr *ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return RemoveItem(Back(), ppItem); + } + } + + // RemoveFront: Removes the head of the list and returns the value. + // ppItem can be NULL if you don't want the item back. + HRESULT RemoveFront(Ptr *ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return RemoveItem(Front(), ppItem); + } + } + + // GetBack: Gets the tail item. + HRESULT GetBack(Ptr *ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return GetItem(Back(), ppItem); + } + } + + // GetFront: Gets the front item. + HRESULT GetFront(Ptr *ppItem) + { + if (IsEmpty()) + { + return E_FAIL; + } + else + { + return GetItem(Front(), ppItem); + } + } + + + // GetCount: Returns the number of items in the list. + DWORD GetCount() const { return m_count; } + + bool IsEmpty() const + { + return (GetCount() == 0); + } + + // Enumerator functions + + POSITION FrontPosition() + { + if (IsEmpty()) + { + return POSITION(NULL); + } + else + { + return POSITION(Front()); + } + } + + POSITION EndPosition() const + { + return POSITION(); + } + + HRESULT GetItemByPosition(POSITION pos, Ptr *ppItem) + { + if (pos.pNode) + { + return GetItem(pos.pNode, ppItem); + } + else + { + return E_FAIL; + } + } + + POSITION Next(const POSITION pos) + { + if (pos.pNode && (pos.pNode->next != &m_anchor)) + { + return POSITION(pos.pNode->next); + } + else + { + return POSITION(NULL); + } + } +}; \ No newline at end of file diff --git a/Samples/DXGIDesktopDuplication/README.md b/Samples/DXGIDesktopDuplication/README.md new file mode 100644 index 00000000..f1211f23 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/README.md @@ -0,0 +1,44 @@ +DXGI desktop duplication sample +=============================== + +This sample demonstrates how to use the desktop duplication behaviors exposed by DXGI in DirectX. + +This sample is written in C++. You also need some experience with DirectX. + +**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. + +For info about how to use the desktop duplication API, see [Desktop Duplication API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh404487). + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample, open the solution (.sln) file titled DesktopDuplication.sln from Visual Studio 2013 for Windows 8.1 (any SKU) or later versions of Visual Studio and Windows. Press F7 (or F6 for Visual Studio 2013) or go to Build-\>Build Solution from the top menu after the sample has loaded. + +Run the sample +-------------- + +To run this sample after building it, perform the following: + +1. Navigate to the directory that contains the new executable, using the command prompt. +2. Type one of the following commands to run the executable. + 1. From the command-line, run **desktopduplication.exe parameter \\bitmap [interval in seconds]** to produce a bitmap every [interval in seconds] seconds + 2. From the command-line, run **desktopduplication.exe \\output [all, \#]** where "all" duplicates the desktop to all outputs, and [\#] specifies the number of outputs. + + diff --git a/Samples/DXGIDesktopDuplication/cpp/CommonTypes.h b/Samples/DXGIDesktopDuplication/cpp/CommonTypes.h new file mode 100644 index 00000000..c46050e6 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/CommonTypes.h @@ -0,0 +1,115 @@ +// 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 + +#ifndef _COMMONTYPES_H_ +#define _COMMONTYPES_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "PixelShader.h" +#include "VertexShader.h" + +#define NUMVERTICES 6 +#define BPP 4 + +#define OCCLUSION_STATUS_MSG WM_USER + +extern HRESULT SystemTransitionsExpectedErrors[]; +extern HRESULT CreateDuplicationExpectedErrors[]; +extern HRESULT FrameInfoExpectedErrors[]; +extern HRESULT AcquireFrameExpectedError[]; +extern HRESULT EnumOutputsExpectedErrors[]; + +typedef _Return_type_success_(return == DUPL_RETURN_SUCCESS) enum +{ + DUPL_RETURN_SUCCESS = 0, + DUPL_RETURN_ERROR_EXPECTED = 1, + DUPL_RETURN_ERROR_UNEXPECTED = 2 +}DUPL_RETURN; + +_Post_satisfies_(return != DUPL_RETURN_SUCCESS) +DUPL_RETURN ProcessFailure(_In_opt_ ID3D11Device* Device, _In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr, _In_opt_z_ HRESULT* ExpectedErrors = nullptr); + +void DisplayMsg(_In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr); + +// +// Holds info about the pointer/cursor +// +typedef struct _PTR_INFO +{ + _Field_size_bytes_(BufferSize) BYTE* PtrShapeBuffer; + DXGI_OUTDUPL_POINTER_SHAPE_INFO ShapeInfo; + POINT Position; + bool Visible; + UINT BufferSize; + UINT WhoUpdatedPositionLast; + LARGE_INTEGER LastTimeStamp; +} PTR_INFO; + +// +// Structure that holds D3D resources not directly tied to any one thread +// +typedef struct _DX_RESOURCES +{ + ID3D11Device* Device; + ID3D11DeviceContext* Context; + ID3D11VertexShader* VertexShader; + ID3D11PixelShader* PixelShader; + ID3D11InputLayout* InputLayout; + ID3D11SamplerState* SamplerLinear; +} DX_RESOURCES; + +// +// Structure to pass to a new thread +// +typedef struct _THREAD_DATA +{ + // Used to indicate abnormal error condition + HANDLE UnexpectedErrorEvent; + + // Used to indicate a transition event occurred e.g. PnpStop, PnpStart, mode change, TDR, desktop switch and the application needs to recreate the duplication interface + HANDLE ExpectedErrorEvent; + + // Used by WinProc to signal to threads to exit + HANDLE TerminateThreadsEvent; + + HANDLE TexSharedHandle; + UINT Output; + INT OffsetX; + INT OffsetY; + PTR_INFO* PtrInfo; + DX_RESOURCES DxRes; +} THREAD_DATA; + +// +// FRAME_DATA holds information about an acquired frame +// +typedef struct _FRAME_DATA +{ + ID3D11Texture2D* Frame; + DXGI_OUTDUPL_FRAME_INFO FrameInfo; + _Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData; + UINT DirtyCount; + UINT MoveCount; +} FRAME_DATA; + +// +// A vertex with a position and texture coordinate +// +typedef struct _VERTEX +{ + DirectX::XMFLOAT3 Pos; + DirectX::XMFLOAT2 TexCoord; +} VERTEX; + +#endif diff --git a/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.cpp b/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.cpp new file mode 100644 index 00000000..bf2c48f1 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.cpp @@ -0,0 +1,697 @@ +// 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 + +#include "DisplayManager.h" +#include "DuplicationManager.h" +#include "OutputManager.h" +#include "ThreadManager.h" + +// +// Globals +// +OUTPUTMANAGER OutMgr; + +// Below are lists of errors expect from Dxgi API calls when a transition event like mode change, PnpStop, PnpStart +// desktop switch, TDR or session disconnect/reconnect. In all these cases we want the application to clean up the threads that process +// the desktop updates and attempt to recreate them. +// If we get an error that is not on the appropriate list then we exit the application + +// These are the errors we expect from general Dxgi API due to a transition +HRESULT SystemTransitionsExpectedErrors[] = { + DXGI_ERROR_DEVICE_REMOVED, + DXGI_ERROR_ACCESS_LOST, + static_cast(WAIT_ABANDONED), + S_OK // Terminate list with zero valued HRESULT + }; + +// These are the errors we expect from IDXGIOutput1::DuplicateOutput due to a transition +HRESULT CreateDuplicationExpectedErrors[] = { + DXGI_ERROR_DEVICE_REMOVED, + static_cast(E_ACCESSDENIED), + DXGI_ERROR_UNSUPPORTED, + DXGI_ERROR_SESSION_DISCONNECTED, + S_OK // Terminate list with zero valued HRESULT + }; + +// These are the errors we expect from IDXGIOutputDuplication methods due to a transition +HRESULT FrameInfoExpectedErrors[] = { + DXGI_ERROR_DEVICE_REMOVED, + DXGI_ERROR_ACCESS_LOST, + S_OK // Terminate list with zero valued HRESULT + }; + +// These are the errors we expect from IDXGIAdapter::EnumOutputs methods due to outputs becoming stale during a transition +HRESULT EnumOutputsExpectedErrors[] = { + DXGI_ERROR_NOT_FOUND, + S_OK // Terminate list with zero valued HRESULT + }; + + +// +// Forward Declarations +// +DWORD WINAPI DDProc(_In_ void* Param); +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +bool ProcessCmdline(_Out_ INT* Output); +void ShowHelp(); + +// +// Class for progressive waits +// +typedef struct +{ + UINT WaitTime; + UINT WaitCount; +}WAIT_BAND; + +#define WAIT_BAND_COUNT 3 +#define WAIT_BAND_STOP 0 + +class DYNAMIC_WAIT +{ + public : + DYNAMIC_WAIT(); + ~DYNAMIC_WAIT(); + + void Wait(); + + private : + + static const WAIT_BAND m_WaitBands[WAIT_BAND_COUNT]; + + // Period in seconds that a new wait call is considered part of the same wait sequence + static const UINT m_WaitSequenceTimeInSeconds = 2; + + UINT m_CurrentWaitBandIdx; + UINT m_WaitCountInCurrentBand; + LARGE_INTEGER m_QPCFrequency; + LARGE_INTEGER m_LastWakeUpTime; + BOOL m_QPCValid; +}; +const WAIT_BAND DYNAMIC_WAIT::m_WaitBands[WAIT_BAND_COUNT] = { + {250, 20}, + {2000, 60}, + {5000, WAIT_BAND_STOP} // Never move past this band + }; + +DYNAMIC_WAIT::DYNAMIC_WAIT() : m_CurrentWaitBandIdx(0), m_WaitCountInCurrentBand(0) +{ + m_QPCValid = QueryPerformanceFrequency(&m_QPCFrequency); + m_LastWakeUpTime.QuadPart = 0L; +} + +DYNAMIC_WAIT::~DYNAMIC_WAIT() +{ +} + +void DYNAMIC_WAIT::Wait() +{ + LARGE_INTEGER CurrentQPC = {0}; + + // Is this wait being called with the period that we consider it to be part of the same wait sequence + QueryPerformanceCounter(&CurrentQPC); + if (m_QPCValid && (CurrentQPC.QuadPart <= (m_LastWakeUpTime.QuadPart + (m_QPCFrequency.QuadPart * m_WaitSequenceTimeInSeconds)))) + { + // We are still in the same wait sequence, lets check if we should move to the next band + if ((m_WaitBands[m_CurrentWaitBandIdx].WaitCount != WAIT_BAND_STOP) && (m_WaitCountInCurrentBand > m_WaitBands[m_CurrentWaitBandIdx].WaitCount)) + { + m_CurrentWaitBandIdx++; + m_WaitCountInCurrentBand = 0; + } + } + else + { + // Either we could not get the current time or we are starting a new wait sequence + m_WaitCountInCurrentBand = 0; + m_CurrentWaitBandIdx = 0; + } + + // Sleep for the required period of time + Sleep(m_WaitBands[m_CurrentWaitBandIdx].WaitTime); + + // Record the time we woke up so we can detect wait sequences + QueryPerformanceCounter(&m_LastWakeUpTime); + m_WaitCountInCurrentBand++; +} + + +// +// Program entry point +// +int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ INT nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + INT SingleOutput; + + // Synchronization + HANDLE UnexpectedErrorEvent = nullptr; + HANDLE ExpectedErrorEvent = nullptr; + HANDLE TerminateThreadsEvent = nullptr; + + // Window + HWND WindowHandle = nullptr; + + bool CmdResult = ProcessCmdline(&SingleOutput); + if (!CmdResult) + { + ShowHelp(); + return 0; + } + + // Event used by the threads to signal an unexpected error and we want to quit the app + UnexpectedErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (!UnexpectedErrorEvent) + { + ProcessFailure(nullptr, L"UnexpectedErrorEvent creation failed", L"Error", E_UNEXPECTED); + return 0; + } + + // Event for when a thread encounters an expected error + ExpectedErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (!ExpectedErrorEvent) + { + ProcessFailure(nullptr, L"ExpectedErrorEvent creation failed", L"Error", E_UNEXPECTED); + return 0; + } + + // Event to tell spawned threads to quit + TerminateThreadsEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (!TerminateThreadsEvent) + { + ProcessFailure(nullptr, L"TerminateThreadsEvent creation failed", L"Error", E_UNEXPECTED); + return 0; + } + + // Load simple cursor + HCURSOR Cursor = nullptr; + Cursor = LoadCursor(nullptr, IDC_ARROW); + if (!Cursor) + { + ProcessFailure(nullptr, L"Cursor load failed", L"Error", E_UNEXPECTED); + return 0; + } + + // Register class + WNDCLASSEXW Wc; + Wc.cbSize = sizeof(WNDCLASSEXW); + Wc.style = CS_HREDRAW | CS_VREDRAW; + Wc.lpfnWndProc = WndProc; + Wc.cbClsExtra = 0; + Wc.cbWndExtra = 0; + Wc.hInstance = hInstance; + Wc.hIcon = nullptr; + Wc.hCursor = Cursor; + Wc.hbrBackground = nullptr; + Wc.lpszMenuName = nullptr; + Wc.lpszClassName = L"ddasample"; + Wc.hIconSm = nullptr; + if (!RegisterClassExW(&Wc)) + { + ProcessFailure(nullptr, L"Window class registration failed", L"Error", E_UNEXPECTED); + return 0; + } + + // Create window + RECT WindowRect = {0, 0, 800, 600}; + AdjustWindowRect(&WindowRect, WS_OVERLAPPEDWINDOW, FALSE); + WindowHandle = CreateWindowW(L"ddasample", L"DXGI desktop duplication sample", + WS_OVERLAPPEDWINDOW, + 0, 0, + WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, + nullptr, nullptr, hInstance, nullptr); + if (!WindowHandle) + { + ProcessFailure(nullptr, L"Window creation failed", L"Error", E_FAIL); + return 0; + } + + DestroyCursor(Cursor); + + ShowWindow(WindowHandle, nCmdShow); + UpdateWindow(WindowHandle); + + THREADMANAGER ThreadMgr; + RECT DeskBounds; + UINT OutputCount; + + // Message loop (attempts to update screen when no other messages to process) + MSG msg = {0}; + bool FirstTime = true; + bool Occluded = true; + DYNAMIC_WAIT DynamicWait; + + while (WM_QUIT != msg.message) + { + DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + if (msg.message == OCCLUSION_STATUS_MSG) + { + // Present may not be occluded now so try again + Occluded = false; + } + else + { + // Process window messages + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else if (WaitForSingleObjectEx(UnexpectedErrorEvent, 0, FALSE) == WAIT_OBJECT_0) + { + // Unexpected error occurred so exit the application + break; + } + else if (FirstTime || WaitForSingleObjectEx(ExpectedErrorEvent, 0, FALSE) == WAIT_OBJECT_0) + { + if (!FirstTime) + { + // Terminate other threads + SetEvent(TerminateThreadsEvent); + ThreadMgr.WaitForThreadTermination(); + ResetEvent(TerminateThreadsEvent); + ResetEvent(ExpectedErrorEvent); + + // Clean up + ThreadMgr.Clean(); + OutMgr.CleanRefs(); + + // As we have encountered an error due to a system transition we wait before trying again, using this dynamic wait + // the wait periods will get progressively long to avoid wasting too much system resource if this state lasts a long time + DynamicWait.Wait(); + } + else + { + // First time through the loop so nothing to clean up + FirstTime = false; + } + + // Re-initialize + Ret = OutMgr.InitOutput(WindowHandle, SingleOutput, &OutputCount, &DeskBounds); + if (Ret == DUPL_RETURN_SUCCESS) + { + HANDLE SharedHandle = OutMgr.GetSharedHandle(); + if (SharedHandle) + { + Ret = ThreadMgr.Initialize(SingleOutput, OutputCount, UnexpectedErrorEvent, ExpectedErrorEvent, TerminateThreadsEvent, SharedHandle, &DeskBounds); + } + else + { + DisplayMsg(L"Failed to get handle of shared surface", L"Error", S_OK); + Ret = DUPL_RETURN_ERROR_UNEXPECTED; + } + } + + // We start off in occluded state and we should immediate get a occlusion status window message + Occluded = true; + } + else + { + // Nothing else to do, so try to present to write out to window if not occluded + if (!Occluded) + { + Ret = OutMgr.UpdateApplicationWindow(ThreadMgr.GetPointerInfo(), &Occluded); + } + } + + // Check if for errors + if (Ret != DUPL_RETURN_SUCCESS) + { + if (Ret == DUPL_RETURN_ERROR_EXPECTED) + { + // Some type of system transition is occurring so retry + SetEvent(ExpectedErrorEvent); + } + else + { + // Unexpected error so exit + break; + } + } + } + + // Make sure all other threads have exited + if (SetEvent(TerminateThreadsEvent)) + { + ThreadMgr.WaitForThreadTermination(); + } + + // Clean up + CloseHandle(UnexpectedErrorEvent); + CloseHandle(ExpectedErrorEvent); + CloseHandle(TerminateThreadsEvent); + + if (msg.message == WM_QUIT) + { + // For a WM_QUIT message we should return the wParam value + return static_cast(msg.wParam); + } + + return 0; +} + +// +// Shows help +// +void ShowHelp() +{ + DisplayMsg(L"The following optional parameters can be used -\n /output [all | n]\t\tto duplicate all outputs or the nth output\n /?\t\t\tto display this help section", + L"Proper usage", S_OK); +} + +// +// Process command line parameters +// +bool ProcessCmdline(_Out_ INT* Output) +{ + *Output = -1; + + // __argv and __argc are global vars set by system + for (UINT i = 1; i < static_cast(__argc); ++i) + { + if ((strcmp(__argv[i], "-output") == 0) || + (strcmp(__argv[i], "/output") == 0)) + { + if (++i >= static_cast(__argc)) + { + return false; + } + + if (strcmp(__argv[i], "all") == 0) + { + *Output = -1; + } + else + { + *Output = atoi(__argv[i]); + } + continue; + } + else + { + return false; + } + } + return true; +} + +// +// Window message processor +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_DESTROY: + { + PostQuitMessage(0); + break; + } + case WM_SIZE: + { + // Tell output manager that window size has changed + OutMgr.WindowResize(); + break; + } + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; +} + +// +// Entry point for new duplication threads +// +DWORD WINAPI DDProc(_In_ void* Param) +{ + // Classes + DISPLAYMANAGER DispMgr; + DUPLICATIONMANAGER DuplMgr; + + // D3D objects + ID3D11Texture2D* SharedSurf = nullptr; + IDXGIKeyedMutex* KeyMutex = nullptr; + + // Data passed in from thread creation + THREAD_DATA* TData = reinterpret_cast(Param); + + // Get desktop + DUPL_RETURN Ret; + HDESK CurrentDesktop = nullptr; + CurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL); + if (!CurrentDesktop) + { + // We do not have access to the desktop so request a retry + SetEvent(TData->ExpectedErrorEvent); + Ret = DUPL_RETURN_ERROR_EXPECTED; + goto Exit; + } + + // Attach desktop to this thread + bool DesktopAttached = SetThreadDesktop(CurrentDesktop) != 0; + CloseDesktop(CurrentDesktop); + CurrentDesktop = nullptr; + if (!DesktopAttached) + { + // We do not have access to the desktop so request a retry + Ret = DUPL_RETURN_ERROR_EXPECTED; + goto Exit; + } + + // New display manager + DispMgr.InitD3D(&TData->DxRes); + + // Obtain handle to sync shared Surface + HRESULT hr = TData->DxRes.Device->OpenSharedResource(TData->TexSharedHandle, __uuidof(ID3D11Texture2D), reinterpret_cast(&SharedSurf)); + if (FAILED (hr)) + { + Ret = ProcessFailure(TData->DxRes.Device, L"Opening shared texture failed", L"Error", hr, SystemTransitionsExpectedErrors); + goto Exit; + } + + hr = SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast(&KeyMutex)); + if (FAILED(hr)) + { + Ret = ProcessFailure(nullptr, L"Failed to get keyed mutex interface in spawned thread", L"Error", hr); + goto Exit; + } + + // Make duplication manager + Ret = DuplMgr.InitDupl(TData->DxRes.Device, TData->Output); + if (Ret != DUPL_RETURN_SUCCESS) + { + goto Exit; + } + + // Get output description + DXGI_OUTPUT_DESC DesktopDesc; + RtlZeroMemory(&DesktopDesc, sizeof(DXGI_OUTPUT_DESC)); + DuplMgr.GetOutputDesc(&DesktopDesc); + + // Main duplication loop + bool WaitToProcessCurrentFrame = false; + FRAME_DATA CurrentData; + + while ((WaitForSingleObjectEx(TData->TerminateThreadsEvent, 0, FALSE) == WAIT_TIMEOUT)) + { + if (!WaitToProcessCurrentFrame) + { + // Get new frame from desktop duplication + bool TimeOut; + Ret = DuplMgr.GetFrame(&CurrentData, &TimeOut); + if (Ret != DUPL_RETURN_SUCCESS) + { + // An error occurred getting the next frame drop out of loop which + // will check if it was expected or not + break; + } + + // Check for timeout + if (TimeOut) + { + // No new frame at the moment + continue; + } + } + + // We have a new frame so try and process it + // Try to acquire keyed mutex in order to access shared surface + hr = KeyMutex->AcquireSync(0, 1000); + if (hr == static_cast(WAIT_TIMEOUT)) + { + // Can't use shared surface right now, try again later + WaitToProcessCurrentFrame = true; + continue; + } + else if (FAILED(hr)) + { + // Generic unknown failure + Ret = ProcessFailure(TData->DxRes.Device, L"Unexpected error acquiring KeyMutex", L"Error", hr, SystemTransitionsExpectedErrors); + DuplMgr.DoneWithFrame(); + break; + } + + // We can now process the current frame + WaitToProcessCurrentFrame = false; + + // Get mouse info + Ret = DuplMgr.GetMouse(TData->PtrInfo, &(CurrentData.FrameInfo), TData->OffsetX, TData->OffsetY); + if (Ret != DUPL_RETURN_SUCCESS) + { + DuplMgr.DoneWithFrame(); + KeyMutex->ReleaseSync(1); + break; + } + + // Process new frame + Ret = DispMgr.ProcessFrame(&CurrentData, SharedSurf, TData->OffsetX, TData->OffsetY, &DesktopDesc); + if (Ret != DUPL_RETURN_SUCCESS) + { + DuplMgr.DoneWithFrame(); + KeyMutex->ReleaseSync(1); + break; + } + + // Release acquired keyed mutex + hr = KeyMutex->ReleaseSync(1); + if (FAILED(hr)) + { + Ret = ProcessFailure(TData->DxRes.Device, L"Unexpected error releasing the keyed mutex", L"Error", hr, SystemTransitionsExpectedErrors); + DuplMgr.DoneWithFrame(); + break; + } + + // Release frame back to desktop duplication + Ret = DuplMgr.DoneWithFrame(); + if (Ret != DUPL_RETURN_SUCCESS) + { + break; + } + } + +Exit: + if (Ret != DUPL_RETURN_SUCCESS) + { + if (Ret == DUPL_RETURN_ERROR_EXPECTED) + { + // The system is in a transition state so request the duplication be restarted + SetEvent(TData->ExpectedErrorEvent); + } + else + { + // Unexpected error so exit the application + SetEvent(TData->UnexpectedErrorEvent); + } + } + + if (SharedSurf) + { + SharedSurf->Release(); + SharedSurf = nullptr; + } + + if (KeyMutex) + { + KeyMutex->Release(); + KeyMutex = nullptr; + } + + return 0; +} + +_Post_satisfies_(return != DUPL_RETURN_SUCCESS) +DUPL_RETURN ProcessFailure(_In_opt_ ID3D11Device* Device, _In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr, _In_opt_z_ HRESULT* ExpectedErrors) +{ + HRESULT TranslatedHr; + + // On an error check if the DX device is lost + if (Device) + { + HRESULT DeviceRemovedReason = Device->GetDeviceRemovedReason(); + + switch (DeviceRemovedReason) + { + case DXGI_ERROR_DEVICE_REMOVED : + case DXGI_ERROR_DEVICE_RESET : + case static_cast(E_OUTOFMEMORY) : + { + // Our device has been stopped due to an external event on the GPU so map them all to + // device removed and continue processing the condition + TranslatedHr = DXGI_ERROR_DEVICE_REMOVED; + break; + } + + case S_OK : + { + // Device is not removed so use original error + TranslatedHr = hr; + break; + } + + default : + { + // Device is removed but not a error we want to remap + TranslatedHr = DeviceRemovedReason; + } + } + } + else + { + TranslatedHr = hr; + } + + // Check if this error was expected or not + if (ExpectedErrors) + { + HRESULT* CurrentResult = ExpectedErrors; + + while (*CurrentResult != S_OK) + { + if (*(CurrentResult++) == TranslatedHr) + { + return DUPL_RETURN_ERROR_EXPECTED; + } + } + } + + // Error was not expected so display the message box + DisplayMsg(Str, Title, TranslatedHr); + + return DUPL_RETURN_ERROR_UNEXPECTED; +} + +// +// Displays a message +// +void DisplayMsg(_In_ LPCWSTR Str, _In_ LPCWSTR Title, HRESULT hr) +{ + if (SUCCEEDED(hr)) + { + MessageBoxW(nullptr, Str, Title, MB_OK); + return; + } + + const UINT StringLen = (UINT)(wcslen(Str) + sizeof(" with HRESULT 0x########.")); + wchar_t* OutStr = new wchar_t[StringLen]; + if (!OutStr) + { + return; + } + + INT LenWritten = swprintf_s(OutStr, StringLen, L"%s with 0x%X.", Str, hr); + if (LenWritten != -1) + { + MessageBoxW(nullptr, OutStr, Title, MB_OK); + } + + delete [] OutStr; +} diff --git a/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.sln b/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.sln new file mode 100644 index 00000000..048168a7 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DesktopDuplication", "DesktopDuplication.vcxproj", "{05050918-71E9-AF87-0B3C-6F34D471A55A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Debug|Win32.ActiveCfg = Debug|Win32 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Debug|Win32.Build.0 = Debug|Win32 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Debug|x64.ActiveCfg = Debug|x64 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Debug|x64.Build.0 = Debug|x64 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Release|Win32.ActiveCfg = Release|Win32 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Release|Win32.Build.0 = Release|Win32 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Release|x64.ActiveCfg = Release|x64 + {05050918-71E9-AF87-0B3C-6F34D471A55A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.vcxproj b/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.vcxproj new file mode 100644 index 00000000..5a0ca859 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DesktopDuplication.vcxproj @@ -0,0 +1,229 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Win32Proj + v4.5 + {05050918-71E9-AF87-0B3C-6F34D471A55A} + + + + Application + true + Unicode + v120 + + + Application + true + Unicode + v120 + + + Application + false + Unicode + v120 + + + Application + false + Unicode + v120 + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + ProgramDatabase + Disabled + $(OutDir) + + + MachineX86 + true + Windows + d3d11.lib;dxgi.lib;%(AdditionalDependencies) + + + true + + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + ProgramDatabase + Disabled + $(OutDir) + + + true + Windows + d3d11.lib;dxgi.lib;%(AdditionalDependencies) + + + true + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + ProgramDatabase + MaxSpeed + $(OutDir) + + + MachineX86 + true + Windows + true + true + dxgi.lib;d3d11.lib;%(AdditionalDependencies) + + + true + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + ProgramDatabase + MaxSpeed + $(OutDir) + + + true + Windows + true + true + dxgi.lib;d3d11.lib;%(AdditionalDependencies) + + + true + + + + + $(OutDir);%(AdditionalIncludeDirectories) + $(OutDir);%(AdditionalIncludeDirectories) + $(OutDir);%(AdditionalIncludeDirectories) + $(OutDir);%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + PS + PS + Pixel + Pixel + 4.0_level_9_1 + 4.0_level_9_1 + PS + PS + 4.0_level_9_1 + 4.0_level_9_1 + Pixel + Pixel + $(OutDir)%(Filename).h + $(OutDir)%(Filename).h + $(OutDir)%(Filename).h + + + + + + + $(OutDir)%(Filename).h + + + + + VS + VS + 4.0_level_9_1 + 4.0_level_9_1 + VS + VS + 4.0_level_9_1 + 4.0_level_9_1 + Vertex + Vertex + $(OutDir)%(Filename).h + $(OutDir)%(Filename).h + $(OutDir)%(Filename).h + $(OutDir)%(Filename).h + + + + + + + + + Vertex + Vertex + + + + + + \ No newline at end of file diff --git a/Samples/DXGIDesktopDuplication/cpp/DisplayManager.cpp b/Samples/DXGIDesktopDuplication/cpp/DisplayManager.cpp new file mode 100644 index 00000000..98209a0d --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DisplayManager.cpp @@ -0,0 +1,478 @@ +// 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 "DisplayManager.h" +using namespace DirectX; + +// +// Constructor NULLs out vars +// +DISPLAYMANAGER::DISPLAYMANAGER() : m_Device(nullptr), + m_DeviceContext(nullptr), + m_MoveSurf(nullptr), + m_VertexShader(nullptr), + m_PixelShader(nullptr), + m_InputLayout(nullptr), + m_RTV(nullptr), + m_SamplerLinear(nullptr), + m_DirtyVertexBufferAlloc(nullptr), + m_DirtyVertexBufferAllocSize(0) +{ +} + +// +// Destructor calls CleanRefs to destroy everything +// +DISPLAYMANAGER::~DISPLAYMANAGER() +{ + CleanRefs(); + + if (m_DirtyVertexBufferAlloc) + { + delete [] m_DirtyVertexBufferAlloc; + m_DirtyVertexBufferAlloc = nullptr; + } +} + +// +// Initialize D3D variables +// +void DISPLAYMANAGER::InitD3D(DX_RESOURCES* Data) +{ + m_Device = Data->Device; + m_DeviceContext = Data->Context; + m_VertexShader = Data->VertexShader; + m_PixelShader = Data->PixelShader; + m_InputLayout = Data->InputLayout; + m_SamplerLinear = Data->SamplerLinear; + + m_Device->AddRef(); + m_DeviceContext->AddRef(); + m_VertexShader->AddRef(); + m_PixelShader->AddRef(); + m_InputLayout->AddRef(); + m_SamplerLinear->AddRef(); +} + +// +// Process a given frame and its metadata +// +DUPL_RETURN DISPLAYMANAGER::ProcessFrame(_In_ FRAME_DATA* Data, _Inout_ ID3D11Texture2D* SharedSurf, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc) +{ + DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; + + // Process dirties and moves + if (Data->FrameInfo.TotalMetadataBufferSize) + { + D3D11_TEXTURE2D_DESC Desc; + Data->Frame->GetDesc(&Desc); + + if (Data->MoveCount) + { + Ret = CopyMove(SharedSurf, reinterpret_cast(Data->MetaData), Data->MoveCount, OffsetX, OffsetY, DeskDesc, Desc.Width, Desc.Height); + if (Ret != DUPL_RETURN_SUCCESS) + { + return Ret; + } + } + + if (Data->DirtyCount) + { + Ret = CopyDirty(Data->Frame, SharedSurf, reinterpret_cast(Data->MetaData + (Data->MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT))), Data->DirtyCount, OffsetX, OffsetY, DeskDesc); + } + } + + return Ret; +} + +// +// Returns D3D device being used +// +ID3D11Device* DISPLAYMANAGER::GetDevice() +{ + return m_Device; +} + +// +// Set appropriate source and destination rects for move rects +// +void DISPLAYMANAGER::SetMoveRect(_Out_ RECT* SrcRect, _Out_ RECT* DestRect, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ DXGI_OUTDUPL_MOVE_RECT* MoveRect, INT TexWidth, INT TexHeight) +{ + switch (DeskDesc->Rotation) + { + case DXGI_MODE_ROTATION_UNSPECIFIED: + case DXGI_MODE_ROTATION_IDENTITY: + { + SrcRect->left = MoveRect->SourcePoint.x; + SrcRect->top = MoveRect->SourcePoint.y; + SrcRect->right = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left; + SrcRect->bottom = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top; + + *DestRect = MoveRect->DestinationRect; + break; + } + case DXGI_MODE_ROTATION_ROTATE90: + { + SrcRect->left = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top); + SrcRect->top = MoveRect->SourcePoint.x; + SrcRect->right = TexHeight - MoveRect->SourcePoint.y; + SrcRect->bottom = MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left; + + DestRect->left = TexHeight - MoveRect->DestinationRect.bottom; + DestRect->top = MoveRect->DestinationRect.left; + DestRect->right = TexHeight - MoveRect->DestinationRect.top; + DestRect->bottom = MoveRect->DestinationRect.right; + break; + } + case DXGI_MODE_ROTATION_ROTATE180: + { + SrcRect->left = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left); + SrcRect->top = TexHeight - (MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top); + SrcRect->right = TexWidth - MoveRect->SourcePoint.x; + SrcRect->bottom = TexHeight - MoveRect->SourcePoint.y; + + DestRect->left = TexWidth - MoveRect->DestinationRect.right; + DestRect->top = TexHeight - MoveRect->DestinationRect.bottom; + DestRect->right = TexWidth - MoveRect->DestinationRect.left; + DestRect->bottom = TexHeight - MoveRect->DestinationRect.top; + break; + } + case DXGI_MODE_ROTATION_ROTATE270: + { + SrcRect->left = MoveRect->SourcePoint.x; + SrcRect->top = TexWidth - (MoveRect->SourcePoint.x + MoveRect->DestinationRect.right - MoveRect->DestinationRect.left); + SrcRect->right = MoveRect->SourcePoint.y + MoveRect->DestinationRect.bottom - MoveRect->DestinationRect.top; + SrcRect->bottom = TexWidth - MoveRect->SourcePoint.x; + + DestRect->left = MoveRect->DestinationRect.top; + DestRect->top = TexWidth - MoveRect->DestinationRect.right; + DestRect->right = MoveRect->DestinationRect.bottom; + DestRect->bottom = TexWidth - MoveRect->DestinationRect.left; + break; + } + default: + { + RtlZeroMemory(DestRect, sizeof(RECT)); + RtlZeroMemory(SrcRect, sizeof(RECT)); + break; + } + } +} + +// +// Copy move rectangles +// +DUPL_RETURN DISPLAYMANAGER::CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(MoveCount) DXGI_OUTDUPL_MOVE_RECT* MoveBuffer, UINT MoveCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, INT TexWidth, INT TexHeight) +{ + D3D11_TEXTURE2D_DESC FullDesc; + SharedSurf->GetDesc(&FullDesc); + + // Make new intermediate surface to copy into for moving + if (!m_MoveSurf) + { + D3D11_TEXTURE2D_DESC MoveDesc; + MoveDesc = FullDesc; + MoveDesc.Width = DeskDesc->DesktopCoordinates.right - DeskDesc->DesktopCoordinates.left; + MoveDesc.Height = DeskDesc->DesktopCoordinates.bottom - DeskDesc->DesktopCoordinates.top; + MoveDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + MoveDesc.MiscFlags = 0; + HRESULT hr = m_Device->CreateTexture2D(&MoveDesc, nullptr, &m_MoveSurf); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create staging texture for move rects", L"Error", hr, SystemTransitionsExpectedErrors); + } + } + + for (UINT i = 0; i < MoveCount; ++i) + { + RECT SrcRect; + RECT DestRect; + + SetMoveRect(&SrcRect, &DestRect, DeskDesc, &(MoveBuffer[i]), TexWidth, TexHeight); + + // Copy rect out of shared surface + D3D11_BOX Box; + Box.left = SrcRect.left + DeskDesc->DesktopCoordinates.left - OffsetX; + Box.top = SrcRect.top + DeskDesc->DesktopCoordinates.top - OffsetY; + Box.front = 0; + Box.right = SrcRect.right + DeskDesc->DesktopCoordinates.left - OffsetX; + Box.bottom = SrcRect.bottom + DeskDesc->DesktopCoordinates.top - OffsetY; + Box.back = 1; + m_DeviceContext->CopySubresourceRegion(m_MoveSurf, 0, SrcRect.left, SrcRect.top, 0, SharedSurf, 0, &Box); + + // Copy back to shared surface + Box.left = SrcRect.left; + Box.top = SrcRect.top; + Box.front = 0; + Box.right = SrcRect.right; + Box.bottom = SrcRect.bottom; + Box.back = 1; + m_DeviceContext->CopySubresourceRegion(SharedSurf, 0, DestRect.left + DeskDesc->DesktopCoordinates.left - OffsetX, DestRect.top + DeskDesc->DesktopCoordinates.top - OffsetY, 0, m_MoveSurf, 0, &Box); + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Sets up vertices for dirty rects for rotated desktops +// +#pragma warning(push) +#pragma warning(disable:__WARNING_USING_UNINIT_VAR) // false positives in SetDirtyVert due to tool bug + +void DISPLAYMANAGER::SetDirtyVert(_Out_writes_(NUMVERTICES) VERTEX* Vertices, _In_ RECT* Dirty, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ D3D11_TEXTURE2D_DESC* FullDesc, _In_ D3D11_TEXTURE2D_DESC* ThisDesc) +{ + INT CenterX = FullDesc->Width / 2; + INT CenterY = FullDesc->Height / 2; + + INT Width = DeskDesc->DesktopCoordinates.right - DeskDesc->DesktopCoordinates.left; + INT Height = DeskDesc->DesktopCoordinates.bottom - DeskDesc->DesktopCoordinates.top; + + // Rotation compensated destination rect + RECT DestDirty = *Dirty; + + // Set appropriate coordinates compensated for rotation + switch (DeskDesc->Rotation) + { + case DXGI_MODE_ROTATION_ROTATE90: + { + DestDirty.left = Width - Dirty->bottom; + DestDirty.top = Dirty->left; + DestDirty.right = Width - Dirty->top; + DestDirty.bottom = Dirty->right; + + Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + break; + } + case DXGI_MODE_ROTATION_ROTATE180: + { + DestDirty.left = Width - Dirty->right; + DestDirty.top = Height - Dirty->bottom; + DestDirty.right = Width - Dirty->left; + DestDirty.bottom = Height - Dirty->top; + + Vertices[0].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + break; + } + case DXGI_MODE_ROTATION_ROTATE270: + { + DestDirty.left = Dirty->top; + DestDirty.top = Height - Dirty->right; + DestDirty.right = Dirty->bottom; + DestDirty.bottom = Height - Dirty->left; + + Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + break; + } + default: + assert(false); // drop through + case DXGI_MODE_ROTATION_UNSPECIFIED: + case DXGI_MODE_ROTATION_IDENTITY: + { + Vertices[0].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + Vertices[1].TexCoord = XMFLOAT2(Dirty->left / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + Vertices[2].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->bottom / static_cast(ThisDesc->Height)); + Vertices[5].TexCoord = XMFLOAT2(Dirty->right / static_cast(ThisDesc->Width), Dirty->top / static_cast(ThisDesc->Height)); + break; + } + } + + // Set positions + Vertices[0].Pos = XMFLOAT3((DestDirty.left + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast(CenterX), + -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast(CenterY), + 0.0f); + Vertices[1].Pos = XMFLOAT3((DestDirty.left + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast(CenterX), + -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast(CenterY), + 0.0f); + Vertices[2].Pos = XMFLOAT3((DestDirty.right + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast(CenterX), + -1 * (DestDirty.bottom + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast(CenterY), + 0.0f); + Vertices[3].Pos = Vertices[2].Pos; + Vertices[4].Pos = Vertices[1].Pos; + Vertices[5].Pos = XMFLOAT3((DestDirty.right + DeskDesc->DesktopCoordinates.left - OffsetX - CenterX) / static_cast(CenterX), + -1 * (DestDirty.top + DeskDesc->DesktopCoordinates.top - OffsetY - CenterY) / static_cast(CenterY), + 0.0f); + + Vertices[3].TexCoord = Vertices[2].TexCoord; + Vertices[4].TexCoord = Vertices[1].TexCoord; +} + +#pragma warning(pop) // re-enable __WARNING_USING_UNINIT_VAR + +// +// Copies dirty rectangles +// +DUPL_RETURN DISPLAYMANAGER::CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(DirtyCount) RECT* DirtyBuffer, UINT DirtyCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc) +{ + HRESULT hr; + + D3D11_TEXTURE2D_DESC FullDesc; + SharedSurf->GetDesc(&FullDesc); + + D3D11_TEXTURE2D_DESC ThisDesc; + SrcSurface->GetDesc(&ThisDesc); + + if (!m_RTV) + { + hr = m_Device->CreateRenderTargetView(SharedSurf, nullptr, &m_RTV); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create render target view for dirty rects", L"Error", hr, SystemTransitionsExpectedErrors); + } + } + + D3D11_SHADER_RESOURCE_VIEW_DESC ShaderDesc; + ShaderDesc.Format = ThisDesc.Format; + ShaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + ShaderDesc.Texture2D.MostDetailedMip = ThisDesc.MipLevels - 1; + ShaderDesc.Texture2D.MipLevels = ThisDesc.MipLevels; + + // Create new shader resource view + ID3D11ShaderResourceView* ShaderResource = nullptr; + hr = m_Device->CreateShaderResourceView(SrcSurface, &ShaderDesc, &ShaderResource); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create shader resource view for dirty rects", L"Error", hr, SystemTransitionsExpectedErrors); + } + + FLOAT BlendFactor[4] = {0.f, 0.f, 0.f, 0.f}; + m_DeviceContext->OMSetBlendState(nullptr, BlendFactor, 0xFFFFFFFF); + m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr); + m_DeviceContext->VSSetShader(m_VertexShader, nullptr, 0); + m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0); + m_DeviceContext->PSSetShaderResources(0, 1, &ShaderResource); + m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerLinear); + m_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // Create space for vertices for the dirty rects if the current space isn't large enough + UINT BytesNeeded = sizeof(VERTEX) * NUMVERTICES * DirtyCount; + if (BytesNeeded > m_DirtyVertexBufferAllocSize) + { + if (m_DirtyVertexBufferAlloc) + { + delete [] m_DirtyVertexBufferAlloc; + } + + m_DirtyVertexBufferAlloc = new (std::nothrow) BYTE[BytesNeeded]; + if (!m_DirtyVertexBufferAlloc) + { + m_DirtyVertexBufferAllocSize = 0; + return ProcessFailure(nullptr, L"Failed to allocate memory for dirty vertex buffer.", L"Error", E_OUTOFMEMORY); + } + + m_DirtyVertexBufferAllocSize = BytesNeeded; + } + + // Fill them in + VERTEX* DirtyVertex = reinterpret_cast(m_DirtyVertexBufferAlloc); + for (UINT i = 0; i < DirtyCount; ++i, DirtyVertex += NUMVERTICES) + { + SetDirtyVert(DirtyVertex, &(DirtyBuffer[i]), OffsetX, OffsetY, DeskDesc, &FullDesc, &ThisDesc); + } + + // Create vertex buffer + D3D11_BUFFER_DESC BufferDesc; + RtlZeroMemory(&BufferDesc, sizeof(BufferDesc)); + BufferDesc.Usage = D3D11_USAGE_DEFAULT; + BufferDesc.ByteWidth = BytesNeeded; + BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + BufferDesc.CPUAccessFlags = 0; + D3D11_SUBRESOURCE_DATA InitData; + RtlZeroMemory(&InitData, sizeof(InitData)); + InitData.pSysMem = m_DirtyVertexBufferAlloc; + + ID3D11Buffer* VertBuf = nullptr; + hr = m_Device->CreateBuffer(&BufferDesc, &InitData, &VertBuf); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create vertex buffer in dirty rect processing", L"Error", hr, SystemTransitionsExpectedErrors); + } + UINT Stride = sizeof(VERTEX); + UINT Offset = 0; + m_DeviceContext->IASetVertexBuffers(0, 1, &VertBuf, &Stride, &Offset); + + D3D11_VIEWPORT VP; + VP.Width = static_cast(FullDesc.Width); + VP.Height = static_cast(FullDesc.Height); + VP.MinDepth = 0.0f; + VP.MaxDepth = 1.0f; + VP.TopLeftX = 0.0f; + VP.TopLeftY = 0.0f; + m_DeviceContext->RSSetViewports(1, &VP); + + m_DeviceContext->Draw(NUMVERTICES * DirtyCount, 0); + + VertBuf->Release(); + VertBuf = nullptr; + + ShaderResource->Release(); + ShaderResource = nullptr; + + return DUPL_RETURN_SUCCESS; +} + +// +// Clean all references +// +void DISPLAYMANAGER::CleanRefs() +{ + if (m_DeviceContext) + { + m_DeviceContext->Release(); + m_DeviceContext = nullptr; + } + + if (m_Device) + { + m_Device->Release(); + m_Device = nullptr; + } + + if (m_MoveSurf) + { + m_MoveSurf->Release(); + m_MoveSurf = nullptr; + } + + if (m_VertexShader) + { + m_VertexShader->Release(); + m_VertexShader = nullptr; + } + + if (m_PixelShader) + { + m_PixelShader->Release(); + m_PixelShader = nullptr; + } + + if (m_InputLayout) + { + m_InputLayout->Release(); + m_InputLayout = nullptr; + } + + if (m_SamplerLinear) + { + m_SamplerLinear->Release(); + m_SamplerLinear = nullptr; + } + + if (m_RTV) + { + m_RTV->Release(); + m_RTV = nullptr; + } +} diff --git a/Samples/DXGIDesktopDuplication/cpp/DisplayManager.h b/Samples/DXGIDesktopDuplication/cpp/DisplayManager.h new file mode 100644 index 00000000..f9bf69c7 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DisplayManager.h @@ -0,0 +1,46 @@ +// 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 + +#ifndef _DISPLAYMANAGER_H_ +#define _DISPLAYMANAGER_H_ + +#include "CommonTypes.h" + +// +// Handles the task of processing frames +// +class DISPLAYMANAGER +{ + public: + DISPLAYMANAGER(); + ~DISPLAYMANAGER(); + void InitD3D(DX_RESOURCES* Data); + ID3D11Device* GetDevice(); + DUPL_RETURN ProcessFrame(_In_ FRAME_DATA* Data, _Inout_ ID3D11Texture2D* SharedSurf, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc); + void CleanRefs(); + + private: + // methods + DUPL_RETURN CopyDirty(_In_ ID3D11Texture2D* SrcSurface, _Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(DirtyCount) RECT* DirtyBuffer, UINT DirtyCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc); + DUPL_RETURN CopyMove(_Inout_ ID3D11Texture2D* SharedSurf, _In_reads_(MoveCount) DXGI_OUTDUPL_MOVE_RECT* MoveBuffer, UINT MoveCount, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, INT TexWidth, INT TexHeight); + void SetDirtyVert(_Out_writes_(NUMVERTICES) VERTEX* Vertices, _In_ RECT* Dirty, INT OffsetX, INT OffsetY, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ D3D11_TEXTURE2D_DESC* FullDesc, _In_ D3D11_TEXTURE2D_DESC* ThisDesc); + void SetMoveRect(_Out_ RECT* SrcRect, _Out_ RECT* DestRect, _In_ DXGI_OUTPUT_DESC* DeskDesc, _In_ DXGI_OUTDUPL_MOVE_RECT* MoveRect, INT TexWidth, INT TexHeight); + + // variables + ID3D11Device* m_Device; + ID3D11DeviceContext* m_DeviceContext; + ID3D11Texture2D* m_MoveSurf; + ID3D11VertexShader* m_VertexShader; + ID3D11PixelShader* m_PixelShader; + ID3D11InputLayout* m_InputLayout; + ID3D11RenderTargetView* m_RTV; + ID3D11SamplerState* m_SamplerLinear; + BYTE* m_DirtyVertexBufferAlloc; + UINT m_DirtyVertexBufferAllocSize; +}; + +#endif diff --git a/Samples/DXGIDesktopDuplication/cpp/DuplicationManager.cpp b/Samples/DXGIDesktopDuplication/cpp/DuplicationManager.cpp new file mode 100644 index 00000000..a0110f2f --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DuplicationManager.cpp @@ -0,0 +1,319 @@ +// 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 "DuplicationManager.h" + +// +// Constructor sets up references / variables +// +DUPLICATIONMANAGER::DUPLICATIONMANAGER() : m_DeskDupl(nullptr), + m_AcquiredDesktopImage(nullptr), + m_MetaDataBuffer(nullptr), + m_MetaDataSize(0), + m_OutputNumber(0), + m_Device(nullptr) +{ + RtlZeroMemory(&m_OutputDesc, sizeof(m_OutputDesc)); +} + +// +// Destructor simply calls CleanRefs to destroy everything +// +DUPLICATIONMANAGER::~DUPLICATIONMANAGER() +{ + if (m_DeskDupl) + { + m_DeskDupl->Release(); + m_DeskDupl = nullptr; + } + + if (m_AcquiredDesktopImage) + { + m_AcquiredDesktopImage->Release(); + m_AcquiredDesktopImage = nullptr; + } + + if (m_MetaDataBuffer) + { + delete [] m_MetaDataBuffer; + m_MetaDataBuffer = nullptr; + } + + if (m_Device) + { + m_Device->Release(); + m_Device = nullptr; + } +} + +// +// Initialize duplication interfaces +// +DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, UINT Output) +{ + m_OutputNumber = Output; + + // Take a reference on the device + m_Device = Device; + m_Device->AddRef(); + + // Get DXGI device + IDXGIDevice* DxgiDevice = nullptr; + HRESULT hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&DxgiDevice)); + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr); + } + + // Get DXGI adapter + IDXGIAdapter* DxgiAdapter = nullptr; + hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast(&DxgiAdapter)); + DxgiDevice->Release(); + DxgiDevice = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Get output + IDXGIOutput* DxgiOutput = nullptr; + hr = DxgiAdapter->EnumOutputs(Output, &DxgiOutput); + DxgiAdapter->Release(); + DxgiAdapter = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to get specified output in DUPLICATIONMANAGER", L"Error", hr, EnumOutputsExpectedErrors); + } + + DxgiOutput->GetDesc(&m_OutputDesc); + + // QI for Output 1 + IDXGIOutput1* DxgiOutput1 = nullptr; + hr = DxgiOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast(&DxgiOutput1)); + DxgiOutput->Release(); + DxgiOutput = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to QI for DxgiOutput1 in DUPLICATIONMANAGER", L"Error", hr); + } + + // Create desktop duplication + hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl); + DxgiOutput1->Release(); + DxgiOutput1 = nullptr; + if (FAILED(hr)) + { + if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) + { + MessageBoxW(nullptr, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again.", L"Error", MB_OK); + return DUPL_RETURN_ERROR_UNEXPECTED; + } + return ProcessFailure(m_Device, L"Failed to get duplicate output in DUPLICATIONMANAGER", L"Error", hr, CreateDuplicationExpectedErrors); + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Retrieves mouse info and write it into PtrInfo +// +DUPL_RETURN DUPLICATIONMANAGER::GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OUTDUPL_FRAME_INFO* FrameInfo, INT OffsetX, INT OffsetY) +{ + // A non-zero mouse update timestamp indicates that there is a mouse position update and optionally a shape change + if (FrameInfo->LastMouseUpdateTime.QuadPart == 0) + { + return DUPL_RETURN_SUCCESS; + } + + bool UpdatePosition = true; + + // Make sure we don't update pointer position wrongly + // If pointer is invisible, make sure we did not get an update from another output that the last time that said pointer + // was visible, if so, don't set it to invisible or update. + if (!FrameInfo->PointerPosition.Visible && (PtrInfo->WhoUpdatedPositionLast != m_OutputNumber)) + { + UpdatePosition = false; + } + + // If two outputs both say they have a visible, only update if new update has newer timestamp + if (FrameInfo->PointerPosition.Visible && PtrInfo->Visible && (PtrInfo->WhoUpdatedPositionLast != m_OutputNumber) && (PtrInfo->LastTimeStamp.QuadPart > FrameInfo->LastMouseUpdateTime.QuadPart)) + { + UpdatePosition = false; + } + + // Update position + if (UpdatePosition) + { + PtrInfo->Position.x = FrameInfo->PointerPosition.Position.x + m_OutputDesc.DesktopCoordinates.left - OffsetX; + PtrInfo->Position.y = FrameInfo->PointerPosition.Position.y + m_OutputDesc.DesktopCoordinates.top - OffsetY; + PtrInfo->WhoUpdatedPositionLast = m_OutputNumber; + PtrInfo->LastTimeStamp = FrameInfo->LastMouseUpdateTime; + PtrInfo->Visible = FrameInfo->PointerPosition.Visible != 0; + } + + // No new shape + if (FrameInfo->PointerShapeBufferSize == 0) + { + return DUPL_RETURN_SUCCESS; + } + + // Old buffer too small + if (FrameInfo->PointerShapeBufferSize > PtrInfo->BufferSize) + { + if (PtrInfo->PtrShapeBuffer) + { + delete [] PtrInfo->PtrShapeBuffer; + PtrInfo->PtrShapeBuffer = nullptr; + } + PtrInfo->PtrShapeBuffer = new (std::nothrow) BYTE[FrameInfo->PointerShapeBufferSize]; + if (!PtrInfo->PtrShapeBuffer) + { + PtrInfo->BufferSize = 0; + return ProcessFailure(nullptr, L"Failed to allocate memory for pointer shape in DUPLICATIONMANAGER", L"Error", E_OUTOFMEMORY); + } + + // Update buffer size + PtrInfo->BufferSize = FrameInfo->PointerShapeBufferSize; + } + + // Get shape + UINT BufferSizeRequired; + HRESULT hr = m_DeskDupl->GetFramePointerShape(FrameInfo->PointerShapeBufferSize, reinterpret_cast(PtrInfo->PtrShapeBuffer), &BufferSizeRequired, &(PtrInfo->ShapeInfo)); + if (FAILED(hr)) + { + delete [] PtrInfo->PtrShapeBuffer; + PtrInfo->PtrShapeBuffer = nullptr; + PtrInfo->BufferSize = 0; + return ProcessFailure(m_Device, L"Failed to get frame pointer shape in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); + } + + return DUPL_RETURN_SUCCESS; +} + + +// +// Get next frame and write it into Data +// +_Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS) +DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout) +{ + IDXGIResource* DesktopResource = nullptr; + DXGI_OUTDUPL_FRAME_INFO FrameInfo; + + // Get new frame + HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); + if (hr == DXGI_ERROR_WAIT_TIMEOUT) + { + *Timeout = true; + return DUPL_RETURN_SUCCESS; + } + *Timeout = false; + + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to acquire next frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); + } + + // If still holding old frame, destroy it + if (m_AcquiredDesktopImage) + { + m_AcquiredDesktopImage->Release(); + m_AcquiredDesktopImage = nullptr; + } + + // QI for IDXGIResource + hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast(&m_AcquiredDesktopImage)); + DesktopResource->Release(); + DesktopResource = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to QI for ID3D11Texture2D from acquired IDXGIResource in DUPLICATIONMANAGER", L"Error", hr); + } + + // Get metadata + if (FrameInfo.TotalMetadataBufferSize) + { + // Old buffer too small + if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize) + { + if (m_MetaDataBuffer) + { + delete [] m_MetaDataBuffer; + m_MetaDataBuffer = nullptr; + } + m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize]; + if (!m_MetaDataBuffer) + { + m_MetaDataSize = 0; + Data->MoveCount = 0; + Data->DirtyCount = 0; + return ProcessFailure(nullptr, L"Failed to allocate memory for metadata in DUPLICATIONMANAGER", L"Error", E_OUTOFMEMORY); + } + m_MetaDataSize = FrameInfo.TotalMetadataBufferSize; + } + + UINT BufSize = FrameInfo.TotalMetadataBufferSize; + + // Get move rectangles + hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast(m_MetaDataBuffer), &BufSize); + if (FAILED(hr)) + { + Data->MoveCount = 0; + Data->DirtyCount = 0; + return ProcessFailure(nullptr, L"Failed to get frame move rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); + } + Data->MoveCount = BufSize / sizeof(DXGI_OUTDUPL_MOVE_RECT); + + BYTE* DirtyRects = m_MetaDataBuffer + BufSize; + BufSize = FrameInfo.TotalMetadataBufferSize - BufSize; + + // Get dirty rectangles + hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast(DirtyRects), &BufSize); + if (FAILED(hr)) + { + Data->MoveCount = 0; + Data->DirtyCount = 0; + return ProcessFailure(nullptr, L"Failed to get frame dirty rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); + } + Data->DirtyCount = BufSize / sizeof(RECT); + + Data->MetaData = m_MetaDataBuffer; + } + + Data->Frame = m_AcquiredDesktopImage; + Data->FrameInfo = FrameInfo; + + return DUPL_RETURN_SUCCESS; +} + +// +// Release frame +// +DUPL_RETURN DUPLICATIONMANAGER::DoneWithFrame() +{ + HRESULT hr = m_DeskDupl->ReleaseFrame(); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to release frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); + } + + if (m_AcquiredDesktopImage) + { + m_AcquiredDesktopImage->Release(); + m_AcquiredDesktopImage = nullptr; + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Gets output desc into DescPtr +// +void DUPLICATIONMANAGER::GetOutputDesc(_Out_ DXGI_OUTPUT_DESC* DescPtr) +{ + *DescPtr = m_OutputDesc; +} diff --git a/Samples/DXGIDesktopDuplication/cpp/DuplicationManager.h b/Samples/DXGIDesktopDuplication/cpp/DuplicationManager.h new file mode 100644 index 00000000..80eea6db --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/DuplicationManager.h @@ -0,0 +1,39 @@ +// 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 + +#ifndef _DUPLICATIONMANAGER_H_ +#define _DUPLICATIONMANAGER_H_ + +#include "CommonTypes.h" + +// +// Handles the task of duplicating an output. +// +class DUPLICATIONMANAGER +{ + public: + DUPLICATIONMANAGER(); + ~DUPLICATIONMANAGER(); + _Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS) DUPL_RETURN GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout); + DUPL_RETURN DoneWithFrame(); + DUPL_RETURN InitDupl(_In_ ID3D11Device* Device, UINT Output); + DUPL_RETURN GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OUTDUPL_FRAME_INFO* FrameInfo, INT OffsetX, INT OffsetY); + void GetOutputDesc(_Out_ DXGI_OUTPUT_DESC* DescPtr); + + private: + + // vars + IDXGIOutputDuplication* m_DeskDupl; + ID3D11Texture2D* m_AcquiredDesktopImage; + _Field_size_bytes_(m_MetaDataSize) BYTE* m_MetaDataBuffer; + UINT m_MetaDataSize; + UINT m_OutputNumber; + DXGI_OUTPUT_DESC m_OutputDesc; + ID3D11Device* m_Device; +}; + +#endif diff --git a/Samples/DXGIDesktopDuplication/cpp/OutputManager.cpp b/Samples/DXGIDesktopDuplication/cpp/OutputManager.cpp new file mode 100644 index 00000000..fd2e781d --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/OutputManager.cpp @@ -0,0 +1,1103 @@ +// 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 "OutputManager.h" +using namespace DirectX; + +// +// Constructor NULLs out all pointers & sets appropriate var vals +// +OUTPUTMANAGER::OUTPUTMANAGER() : m_SwapChain(nullptr), + m_Device(nullptr), + m_Factory(nullptr), + m_DeviceContext(nullptr), + m_RTV(nullptr), + m_SamplerLinear(nullptr), + m_BlendState(nullptr), + m_VertexShader(nullptr), + m_PixelShader(nullptr), + m_InputLayout(nullptr), + m_SharedSurf(nullptr), + m_KeyMutex(nullptr), + m_WindowHandle(nullptr), + m_NeedsResize(false), + m_OcclusionCookie(0) +{ +} + +// +// Destructor which calls CleanRefs to release all references and memory. +// +OUTPUTMANAGER::~OUTPUTMANAGER() +{ + CleanRefs(); +} + +// +// Indicates that window has been resized. +// +void OUTPUTMANAGER::WindowResize() +{ + m_NeedsResize = true; +} + +// +// Initialize all state +// +DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds) +{ + HRESULT hr; + + // Store window handle + m_WindowHandle = Window; + + // Driver types supported + D3D_DRIVER_TYPE DriverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + UINT NumDriverTypes = ARRAYSIZE(DriverTypes); + + // Feature levels supported + D3D_FEATURE_LEVEL FeatureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_1 + }; + UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels); + D3D_FEATURE_LEVEL FeatureLevel; + + // Create device + for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) + { + hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr, 0, FeatureLevels, NumFeatureLevels, + D3D11_SDK_VERSION, &m_Device, &FeatureLevel, &m_DeviceContext); + if (SUCCEEDED(hr)) + { + // Device creation succeeded, no need to loop anymore + break; + } + } + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Device creation in OUTPUTMANAGER failed", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Get DXGI factory + IDXGIDevice* DxgiDevice = nullptr; + hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&DxgiDevice)); + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr, nullptr); + } + + IDXGIAdapter* DxgiAdapter = nullptr; + hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast(&DxgiAdapter)); + DxgiDevice->Release(); + DxgiDevice = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); + } + + hr = DxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast(&m_Factory)); + DxgiAdapter->Release(); + DxgiAdapter = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to get parent DXGI Factory", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Register for occlusion status windows message + hr = m_Factory->RegisterOcclusionStatusWindow(Window, OCCLUSION_STATUS_MSG, &m_OcclusionCookie); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to register for occlusion message", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Get window size + RECT WindowRect; + GetClientRect(m_WindowHandle, &WindowRect); + UINT Width = WindowRect.right - WindowRect.left; + UINT Height = WindowRect.bottom - WindowRect.top; + + // Create swapchain for window + DXGI_SWAP_CHAIN_DESC1 SwapChainDesc; + RtlZeroMemory(&SwapChainDesc, sizeof(SwapChainDesc)); + + SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + SwapChainDesc.BufferCount = 2; + SwapChainDesc.Width = Width; + SwapChainDesc.Height = Height; + SwapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + SwapChainDesc.SampleDesc.Count = 1; + SwapChainDesc.SampleDesc.Quality = 0; + hr = m_Factory->CreateSwapChainForHwnd(m_Device, Window, &SwapChainDesc, nullptr, nullptr, &m_SwapChain); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create window swapchain", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Disable the ALT-ENTER shortcut for entering full-screen mode + hr = m_Factory->MakeWindowAssociation(Window, DXGI_MWA_NO_ALT_ENTER); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to make window association", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Create shared texture + DUPL_RETURN Return = CreateSharedSurf(SingleOutput, OutCount, DeskBounds); + if (Return != DUPL_RETURN_SUCCESS) + { + return Return; + } + + // Make new render target view + Return = MakeRTV(); + if (Return != DUPL_RETURN_SUCCESS) + { + return Return; + } + + // Set view port + SetViewPort(Width, Height); + + // Create the sample state + D3D11_SAMPLER_DESC SampDesc; + RtlZeroMemory(&SampDesc, sizeof(SampDesc)); + SampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + SampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + SampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + SampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + SampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + SampDesc.MinLOD = 0; + SampDesc.MaxLOD = D3D11_FLOAT32_MAX; + hr = m_Device->CreateSamplerState(&SampDesc, &m_SamplerLinear); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create sampler state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Create the blend state + D3D11_BLEND_DESC BlendStateDesc; + BlendStateDesc.AlphaToCoverageEnable = FALSE; + BlendStateDesc.IndependentBlendEnable = FALSE; + BlendStateDesc.RenderTarget[0].BlendEnable = TRUE; + BlendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + BlendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + BlendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + BlendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + BlendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + BlendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + BlendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + hr = m_Device->CreateBlendState(&BlendStateDesc, &m_BlendState); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create blend state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Initialize shaders + Return = InitShaders(); + if (Return != DUPL_RETURN_SUCCESS) + { + return Return; + } + + GetWindowRect(m_WindowHandle, &WindowRect); + MoveWindow(m_WindowHandle, WindowRect.left, WindowRect.top, (DeskBounds->right - DeskBounds->left) / 2, (DeskBounds->bottom - DeskBounds->top) / 2, TRUE); + + return Return; +} + +// +// Recreate shared texture +// +DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds) +{ + HRESULT hr; + + // Get DXGI resources + IDXGIDevice* DxgiDevice = nullptr; + hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&DxgiDevice)); + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr); + } + + IDXGIAdapter* DxgiAdapter = nullptr; + hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast(&DxgiAdapter)); + DxgiDevice->Release(); + DxgiDevice = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Set initial values so that we always catch the right coordinates + DeskBounds->left = INT_MAX; + DeskBounds->right = INT_MIN; + DeskBounds->top = INT_MAX; + DeskBounds->bottom = INT_MIN; + + IDXGIOutput* DxgiOutput = nullptr; + + // Figure out right dimensions for full size desktop texture and # of outputs to duplicate + UINT OutputCount; + if (SingleOutput < 0) + { + hr = S_OK; + for (OutputCount = 0; SUCCEEDED(hr); ++OutputCount) + { + if (DxgiOutput) + { + DxgiOutput->Release(); + DxgiOutput = nullptr; + } + hr = DxgiAdapter->EnumOutputs(OutputCount, &DxgiOutput); + if (DxgiOutput && (hr != DXGI_ERROR_NOT_FOUND)) + { + DXGI_OUTPUT_DESC DesktopDesc; + DxgiOutput->GetDesc(&DesktopDesc); + + DeskBounds->left = min(DesktopDesc.DesktopCoordinates.left, DeskBounds->left); + DeskBounds->top = min(DesktopDesc.DesktopCoordinates.top, DeskBounds->top); + DeskBounds->right = max(DesktopDesc.DesktopCoordinates.right, DeskBounds->right); + DeskBounds->bottom = max(DesktopDesc.DesktopCoordinates.bottom, DeskBounds->bottom); + } + } + + --OutputCount; + } + else + { + hr = DxgiAdapter->EnumOutputs(SingleOutput, &DxgiOutput); + if (FAILED(hr)) + { + DxgiAdapter->Release(); + DxgiAdapter = nullptr; + return ProcessFailure(m_Device, L"Output specified to be duplicated does not exist", L"Error", hr); + } + DXGI_OUTPUT_DESC DesktopDesc; + DxgiOutput->GetDesc(&DesktopDesc); + *DeskBounds = DesktopDesc.DesktopCoordinates; + + DxgiOutput->Release(); + DxgiOutput = nullptr; + + OutputCount = 1; + } + + DxgiAdapter->Release(); + DxgiAdapter = nullptr; + + // Set passed in output count variable + *OutCount = OutputCount; + + if (OutputCount == 0) + { + // We could not find any outputs, the system must be in a transition so return expected error + // so we will attempt to recreate + return DUPL_RETURN_ERROR_EXPECTED; + } + + // Create shared texture for all duplication threads to draw into + D3D11_TEXTURE2D_DESC DeskTexD; + RtlZeroMemory(&DeskTexD, sizeof(D3D11_TEXTURE2D_DESC)); + DeskTexD.Width = DeskBounds->right - DeskBounds->left; + DeskTexD.Height = DeskBounds->bottom - DeskBounds->top; + DeskTexD.MipLevels = 1; + DeskTexD.ArraySize = 1; + DeskTexD.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + DeskTexD.SampleDesc.Count = 1; + DeskTexD.Usage = D3D11_USAGE_DEFAULT; + DeskTexD.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + DeskTexD.CPUAccessFlags = 0; + DeskTexD.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + + hr = m_Device->CreateTexture2D(&DeskTexD, nullptr, &m_SharedSurf); + if (FAILED(hr)) + { + if (OutputCount != 1) + { + // If we are duplicating the complete desktop we try to create a single texture to hold the + // complete desktop image and blit updates from the per output DDA interface. The GPU can + // always support a texture size of the maximum resolution of any single output but there is no + // guarantee that it can support a texture size of the desktop. + // The sample only use this large texture to display the desktop image in a single window using DX + // we could revert back to using GDI to update the window in this failure case. + return ProcessFailure(m_Device, L"Failed to create DirectX shared texture - we are attempting to create a texture the size of the complete desktop and this may be larger than the maximum texture size of your GPU. Please try again using the -output command line parameter to duplicate only 1 monitor or configure your computer to a single monitor configuration", L"Error", hr, SystemTransitionsExpectedErrors); + } + else + { + return ProcessFailure(m_Device, L"Failed to create shared texture", L"Error", hr, SystemTransitionsExpectedErrors); + } + } + + // Get keyed mutex + hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast(&m_KeyMutex)); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to query for keyed mutex in OUTPUTMANAGER", L"Error", hr); + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Present to the application window +// +DUPL_RETURN OUTPUTMANAGER::UpdateApplicationWindow(_In_ PTR_INFO* PointerInfo, _Inout_ bool* Occluded) +{ + // In a typical desktop duplication application there would be an application running on one system collecting the desktop images + // and another application running on a different system that receives the desktop images via a network and display the image. This + // sample contains both these aspects into a single application. + // This routine is the part of the sample that displays the desktop image onto the display + + // Try and acquire sync on common display buffer + HRESULT hr = m_KeyMutex->AcquireSync(1, 100); + if (hr == static_cast(WAIT_TIMEOUT)) + { + // Another thread has the keyed mutex so try again later + return DUPL_RETURN_SUCCESS; + } + else if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to acquire Keyed mutex in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Got mutex, so draw + DUPL_RETURN Ret = DrawFrame(); + if (Ret == DUPL_RETURN_SUCCESS) + { + // We have keyed mutex so we can access the mouse info + if (PointerInfo->Visible) + { + // Draw mouse into texture + Ret = DrawMouse(PointerInfo); + } + } + + // Release keyed mutex + hr = m_KeyMutex->ReleaseSync(0); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to Release Keyed mutex in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Present to window if all worked + if (Ret == DUPL_RETURN_SUCCESS) + { + // Present to window + hr = m_SwapChain->Present(1, 0); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to present", L"Error", hr, SystemTransitionsExpectedErrors); + } + else if (hr == DXGI_STATUS_OCCLUDED) + { + *Occluded = true; + } + } + + return Ret; +} + +// +// Returns shared handle +// +HANDLE OUTPUTMANAGER::GetSharedHandle() +{ + HANDLE Hnd = nullptr; + + // QI IDXGIResource interface to synchronized shared surface. + IDXGIResource* DXGIResource = nullptr; + HRESULT hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIResource), reinterpret_cast(&DXGIResource)); + if (SUCCEEDED(hr)) + { + // Obtain handle to IDXGIResource object. + DXGIResource->GetSharedHandle(&Hnd); + DXGIResource->Release(); + DXGIResource = nullptr; + } + + return Hnd; +} + +// +// Draw frame into backbuffer +// +DUPL_RETURN OUTPUTMANAGER::DrawFrame() +{ + HRESULT hr; + + // If window was resized, resize swapchain + if (m_NeedsResize) + { + DUPL_RETURN Ret = ResizeSwapChain(); + if (Ret != DUPL_RETURN_SUCCESS) + { + return Ret; + } + m_NeedsResize = false; + } + + // Vertices for drawing whole texture + VERTEX Vertices[NUMVERTICES] = + { + {XMFLOAT3(-1.0f, -1.0f, 0), XMFLOAT2(0.0f, 1.0f)}, + {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)}, + {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)}, + {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)}, + {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)}, + {XMFLOAT3(1.0f, 1.0f, 0), XMFLOAT2(1.0f, 0.0f)}, + }; + + D3D11_TEXTURE2D_DESC FrameDesc; + m_SharedSurf->GetDesc(&FrameDesc); + + D3D11_SHADER_RESOURCE_VIEW_DESC ShaderDesc; + ShaderDesc.Format = FrameDesc.Format; + ShaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + ShaderDesc.Texture2D.MostDetailedMip = FrameDesc.MipLevels - 1; + ShaderDesc.Texture2D.MipLevels = FrameDesc.MipLevels; + + // Create new shader resource view + ID3D11ShaderResourceView* ShaderResource = nullptr; + hr = m_Device->CreateShaderResourceView(m_SharedSurf, &ShaderDesc, &ShaderResource); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create shader resource when drawing a frame", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Set resources + UINT Stride = sizeof(VERTEX); + UINT Offset = 0; + FLOAT blendFactor[4] = {0.f, 0.f, 0.f, 0.f}; + m_DeviceContext->OMSetBlendState(nullptr, blendFactor, 0xffffffff); + m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr); + m_DeviceContext->VSSetShader(m_VertexShader, nullptr, 0); + m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0); + m_DeviceContext->PSSetShaderResources(0, 1, &ShaderResource); + m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerLinear); + m_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + D3D11_BUFFER_DESC BufferDesc; + RtlZeroMemory(&BufferDesc, sizeof(BufferDesc)); + BufferDesc.Usage = D3D11_USAGE_DEFAULT; + BufferDesc.ByteWidth = sizeof(VERTEX) * NUMVERTICES; + BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + BufferDesc.CPUAccessFlags = 0; + D3D11_SUBRESOURCE_DATA InitData; + RtlZeroMemory(&InitData, sizeof(InitData)); + InitData.pSysMem = Vertices; + + ID3D11Buffer* VertexBuffer = nullptr; + + // Create vertex buffer + hr = m_Device->CreateBuffer(&BufferDesc, &InitData, &VertexBuffer); + if (FAILED(hr)) + { + ShaderResource->Release(); + ShaderResource = nullptr; + return ProcessFailure(m_Device, L"Failed to create vertex buffer when drawing a frame", L"Error", hr, SystemTransitionsExpectedErrors); + } + m_DeviceContext->IASetVertexBuffers(0, 1, &VertexBuffer, &Stride, &Offset); + + // Draw textured quad onto render target + m_DeviceContext->Draw(NUMVERTICES, 0); + + VertexBuffer->Release(); + VertexBuffer = nullptr; + + // Release shader resource + ShaderResource->Release(); + ShaderResource = nullptr; + + return DUPL_RETURN_SUCCESS; +} + +// +// Process both masked and monochrome pointers +// +DUPL_RETURN OUTPUTMANAGER::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInfo, _Out_ INT* PtrWidth, _Out_ INT* PtrHeight, _Out_ INT* PtrLeft, _Out_ INT* PtrTop, _Outptr_result_bytebuffer_(*PtrHeight * *PtrWidth * BPP) BYTE** InitBuffer, _Out_ D3D11_BOX* Box) +{ + // Desktop dimensions + D3D11_TEXTURE2D_DESC FullDesc; + m_SharedSurf->GetDesc(&FullDesc); + INT DesktopWidth = FullDesc.Width; + INT DesktopHeight = FullDesc.Height; + + // Pointer position + INT GivenLeft = PtrInfo->Position.x; + INT GivenTop = PtrInfo->Position.y; + + // Figure out if any adjustment is needed for out of bound positions + if (GivenLeft < 0) + { + *PtrWidth = GivenLeft + static_cast(PtrInfo->ShapeInfo.Width); + } + else if ((GivenLeft + static_cast(PtrInfo->ShapeInfo.Width)) > DesktopWidth) + { + *PtrWidth = DesktopWidth - GivenLeft; + } + else + { + *PtrWidth = static_cast(PtrInfo->ShapeInfo.Width); + } + + if (IsMono) + { + PtrInfo->ShapeInfo.Height = PtrInfo->ShapeInfo.Height / 2; + } + + if (GivenTop < 0) + { + *PtrHeight = GivenTop + static_cast(PtrInfo->ShapeInfo.Height); + } + else if ((GivenTop + static_cast(PtrInfo->ShapeInfo.Height)) > DesktopHeight) + { + *PtrHeight = DesktopHeight - GivenTop; + } + else + { + *PtrHeight = static_cast(PtrInfo->ShapeInfo.Height); + } + + if (IsMono) + { + PtrInfo->ShapeInfo.Height = PtrInfo->ShapeInfo.Height * 2; + } + + *PtrLeft = (GivenLeft < 0) ? 0 : GivenLeft; + *PtrTop = (GivenTop < 0) ? 0 : GivenTop; + + // Staging buffer/texture + D3D11_TEXTURE2D_DESC CopyBufferDesc; + CopyBufferDesc.Width = *PtrWidth; + CopyBufferDesc.Height = *PtrHeight; + CopyBufferDesc.MipLevels = 1; + CopyBufferDesc.ArraySize = 1; + CopyBufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + CopyBufferDesc.SampleDesc.Count = 1; + CopyBufferDesc.SampleDesc.Quality = 0; + CopyBufferDesc.Usage = D3D11_USAGE_STAGING; + CopyBufferDesc.BindFlags = 0; + CopyBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + CopyBufferDesc.MiscFlags = 0; + + ID3D11Texture2D* CopyBuffer = nullptr; + HRESULT hr = m_Device->CreateTexture2D(&CopyBufferDesc, nullptr, &CopyBuffer); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed creating staging texture for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Copy needed part of desktop image + Box->left = *PtrLeft; + Box->top = *PtrTop; + Box->right = *PtrLeft + *PtrWidth; + Box->bottom = *PtrTop + *PtrHeight; + m_DeviceContext->CopySubresourceRegion(CopyBuffer, 0, 0, 0, 0, m_SharedSurf, 0, Box); + + // QI for IDXGISurface + IDXGISurface* CopySurface = nullptr; + hr = CopyBuffer->QueryInterface(__uuidof(IDXGISurface), (void **)&CopySurface); + CopyBuffer->Release(); + CopyBuffer = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to QI staging texture into IDXGISurface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Map pixels + DXGI_MAPPED_RECT MappedSurface; + hr = CopySurface->Map(&MappedSurface, DXGI_MAP_READ); + if (FAILED(hr)) + { + CopySurface->Release(); + CopySurface = nullptr; + return ProcessFailure(m_Device, L"Failed to map surface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // New mouseshape buffer + *InitBuffer = new (std::nothrow) BYTE[*PtrWidth * *PtrHeight * BPP]; + if (!(*InitBuffer)) + { + return ProcessFailure(nullptr, L"Failed to allocate memory for new mouse shape buffer.", L"Error", E_OUTOFMEMORY); + } + + UINT* InitBuffer32 = reinterpret_cast(*InitBuffer); + UINT* Desktop32 = reinterpret_cast(MappedSurface.pBits); + UINT DesktopPitchInPixels = MappedSurface.Pitch / sizeof(UINT); + + // What to skip (pixel offset) + UINT SkipX = (GivenLeft < 0) ? (-1 * GivenLeft) : (0); + UINT SkipY = (GivenTop < 0) ? (-1 * GivenTop) : (0); + + if (IsMono) + { + for (INT Row = 0; Row < *PtrHeight; ++Row) + { + // Set mask + BYTE Mask = 0x80; + Mask = Mask >> (SkipX % 8); + for (INT Col = 0; Col < *PtrWidth; ++Col) + { + // Get masks using appropriate offsets + BYTE AndMask = PtrInfo->PtrShapeBuffer[((Col + SkipX) / 8) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch))] & Mask; + BYTE XorMask = PtrInfo->PtrShapeBuffer[((Col + SkipX) / 8) + ((Row + SkipY + (PtrInfo->ShapeInfo.Height / 2)) * (PtrInfo->ShapeInfo.Pitch))] & Mask; + UINT AndMask32 = (AndMask) ? 0xFFFFFFFF : 0xFF000000; + UINT XorMask32 = (XorMask) ? 0x00FFFFFF : 0x00000000; + + // Set new pixel + InitBuffer32[(Row * *PtrWidth) + Col] = (Desktop32[(Row * DesktopPitchInPixels) + Col] & AndMask32) ^ XorMask32; + + // Adjust mask + if (Mask == 0x01) + { + Mask = 0x80; + } + else + { + Mask = Mask >> 1; + } + } + } + } + else + { + UINT* Buffer32 = reinterpret_cast(PtrInfo->PtrShapeBuffer); + + // Iterate through pixels + for (INT Row = 0; Row < *PtrHeight; ++Row) + { + for (INT Col = 0; Col < *PtrWidth; ++Col) + { + // Set up mask + UINT MaskVal = 0xFF000000 & Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))]; + if (MaskVal) + { + // Mask was 0xFF + InitBuffer32[(Row * *PtrWidth) + Col] = (Desktop32[(Row * DesktopPitchInPixels) + Col] ^ Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))]) | 0xFF000000; + } + else + { + // Mask was 0x00 + InitBuffer32[(Row * *PtrWidth) + Col] = Buffer32[(Col + SkipX) + ((Row + SkipY) * (PtrInfo->ShapeInfo.Pitch / sizeof(UINT)))] | 0xFF000000; + } + } + } + } + + // Done with resource + hr = CopySurface->Unmap(); + CopySurface->Release(); + CopySurface = nullptr; + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to unmap surface for pointer", L"Error", hr, SystemTransitionsExpectedErrors); + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Draw mouse provided in buffer to backbuffer +// +DUPL_RETURN OUTPUTMANAGER::DrawMouse(_In_ PTR_INFO* PtrInfo) +{ + // Vars to be used + ID3D11Texture2D* MouseTex = nullptr; + ID3D11ShaderResourceView* ShaderRes = nullptr; + ID3D11Buffer* VertexBufferMouse = nullptr; + D3D11_SUBRESOURCE_DATA InitData; + D3D11_TEXTURE2D_DESC Desc; + D3D11_SHADER_RESOURCE_VIEW_DESC SDesc; + + // Position will be changed based on mouse position + VERTEX Vertices[NUMVERTICES] = + { + {XMFLOAT3(-1.0f, -1.0f, 0), XMFLOAT2(0.0f, 1.0f)}, + {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)}, + {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)}, + {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)}, + {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)}, + {XMFLOAT3(1.0f, 1.0f, 0), XMFLOAT2(1.0f, 0.0f)}, + }; + + D3D11_TEXTURE2D_DESC FullDesc; + m_SharedSurf->GetDesc(&FullDesc); + INT DesktopWidth = FullDesc.Width; + INT DesktopHeight = FullDesc.Height; + + // Center of desktop dimensions + INT CenterX = (DesktopWidth / 2); + INT CenterY = (DesktopHeight / 2); + + // Clipping adjusted coordinates / dimensions + INT PtrWidth = 0; + INT PtrHeight = 0; + INT PtrLeft = 0; + INT PtrTop = 0; + + // Buffer used if necessary (in case of monochrome or masked pointer) + BYTE* InitBuffer = nullptr; + + // Used for copying pixels + D3D11_BOX Box; + Box.front = 0; + Box.back = 1; + + Desc.MipLevels = 1; + Desc.ArraySize = 1; + Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + Desc.SampleDesc.Count = 1; + Desc.SampleDesc.Quality = 0; + Desc.Usage = D3D11_USAGE_DEFAULT; + Desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + Desc.CPUAccessFlags = 0; + Desc.MiscFlags = 0; + + // Set shader resource properties + SDesc.Format = Desc.Format; + SDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SDesc.Texture2D.MostDetailedMip = Desc.MipLevels - 1; + SDesc.Texture2D.MipLevels = Desc.MipLevels; + + switch (PtrInfo->ShapeInfo.Type) + { + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR: + { + PtrLeft = PtrInfo->Position.x; + PtrTop = PtrInfo->Position.y; + + PtrWidth = static_cast(PtrInfo->ShapeInfo.Width); + PtrHeight = static_cast(PtrInfo->ShapeInfo.Height); + + break; + } + + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME: + { + ProcessMonoMask(true, PtrInfo, &PtrWidth, &PtrHeight, &PtrLeft, &PtrTop, &InitBuffer, &Box); + break; + } + + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: + { + ProcessMonoMask(false, PtrInfo, &PtrWidth, &PtrHeight, &PtrLeft, &PtrTop, &InitBuffer, &Box); + break; + } + + default: + break; + } + + // VERTEX creation + Vertices[0].Pos.x = (PtrLeft - CenterX) / (FLOAT)CenterX; + Vertices[0].Pos.y = -1 * ((PtrTop + PtrHeight) - CenterY) / (FLOAT)CenterY; + Vertices[1].Pos.x = (PtrLeft - CenterX) / (FLOAT)CenterX; + Vertices[1].Pos.y = -1 * (PtrTop - CenterY) / (FLOAT)CenterY; + Vertices[2].Pos.x = ((PtrLeft + PtrWidth) - CenterX) / (FLOAT)CenterX; + Vertices[2].Pos.y = -1 * ((PtrTop + PtrHeight) - CenterY) / (FLOAT)CenterY; + Vertices[3].Pos.x = Vertices[2].Pos.x; + Vertices[3].Pos.y = Vertices[2].Pos.y; + Vertices[4].Pos.x = Vertices[1].Pos.x; + Vertices[4].Pos.y = Vertices[1].Pos.y; + Vertices[5].Pos.x = ((PtrLeft + PtrWidth) - CenterX) / (FLOAT)CenterX; + Vertices[5].Pos.y = -1 * (PtrTop - CenterY) / (FLOAT)CenterY; + + // Set texture properties + Desc.Width = PtrWidth; + Desc.Height = PtrHeight; + + // Set up init data + InitData.pSysMem = (PtrInfo->ShapeInfo.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR) ? PtrInfo->PtrShapeBuffer : InitBuffer; + InitData.SysMemPitch = (PtrInfo->ShapeInfo.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR) ? PtrInfo->ShapeInfo.Pitch : PtrWidth * BPP; + InitData.SysMemSlicePitch = 0; + + // Create mouseshape as texture + HRESULT hr = m_Device->CreateTexture2D(&Desc, &InitData, &MouseTex); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create mouse pointer texture", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Create shader resource from texture + hr = m_Device->CreateShaderResourceView(MouseTex, &SDesc, &ShaderRes); + if (FAILED(hr)) + { + MouseTex->Release(); + MouseTex = nullptr; + return ProcessFailure(m_Device, L"Failed to create shader resource from mouse pointer texture", L"Error", hr, SystemTransitionsExpectedErrors); + } + + D3D11_BUFFER_DESC BDesc; + ZeroMemory(&BDesc, sizeof(D3D11_BUFFER_DESC)); + BDesc.Usage = D3D11_USAGE_DEFAULT; + BDesc.ByteWidth = sizeof(VERTEX) * NUMVERTICES; + BDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + BDesc.CPUAccessFlags = 0; + + ZeroMemory(&InitData, sizeof(D3D11_SUBRESOURCE_DATA)); + InitData.pSysMem = Vertices; + + // Create vertex buffer + hr = m_Device->CreateBuffer(&BDesc, &InitData, &VertexBufferMouse); + if (FAILED(hr)) + { + ShaderRes->Release(); + ShaderRes = nullptr; + MouseTex->Release(); + MouseTex = nullptr; + return ProcessFailure(m_Device, L"Failed to create mouse pointer vertex buffer in OutputManager", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Set resources + FLOAT BlendFactor[4] = {0.f, 0.f, 0.f, 0.f}; + UINT Stride = sizeof(VERTEX); + UINT Offset = 0; + m_DeviceContext->IASetVertexBuffers(0, 1, &VertexBufferMouse, &Stride, &Offset); + m_DeviceContext->OMSetBlendState(m_BlendState, BlendFactor, 0xFFFFFFFF); + m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr); + m_DeviceContext->VSSetShader(m_VertexShader, nullptr, 0); + m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0); + m_DeviceContext->PSSetShaderResources(0, 1, &ShaderRes); + m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerLinear); + + // Draw + m_DeviceContext->Draw(NUMVERTICES, 0); + + // Clean + if (VertexBufferMouse) + { + VertexBufferMouse->Release(); + VertexBufferMouse = nullptr; + } + if (ShaderRes) + { + ShaderRes->Release(); + ShaderRes = nullptr; + } + if (MouseTex) + { + MouseTex->Release(); + MouseTex = nullptr; + } + if (InitBuffer) + { + delete [] InitBuffer; + InitBuffer = nullptr; + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Initialize shaders for drawing to screen +// +DUPL_RETURN OUTPUTMANAGER::InitShaders() +{ + HRESULT hr; + + UINT Size = ARRAYSIZE(g_VS); + hr = m_Device->CreateVertexShader(g_VS, Size, nullptr, &m_VertexShader); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create vertex shader in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + D3D11_INPUT_ELEMENT_DESC Layout[] = + { + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0} + }; + UINT NumElements = ARRAYSIZE(Layout); + hr = m_Device->CreateInputLayout(Layout, NumElements, g_VS, Size, &m_InputLayout); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create input layout in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + m_DeviceContext->IASetInputLayout(m_InputLayout); + + Size = ARRAYSIZE(g_PS); + hr = m_Device->CreatePixelShader(g_PS, Size, nullptr, &m_PixelShader); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create pixel shader in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Reset render target view +// +DUPL_RETURN OUTPUTMANAGER::MakeRTV() +{ + // Get backbuffer + ID3D11Texture2D* BackBuffer = nullptr; + HRESULT hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(&BackBuffer)); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to get backbuffer for making render target view in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Create a render target view + hr = m_Device->CreateRenderTargetView(BackBuffer, nullptr, &m_RTV); + BackBuffer->Release(); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to create render target view in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Set new render target + m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr); + + return DUPL_RETURN_SUCCESS; +} + +// +// Set new viewport +// +void OUTPUTMANAGER::SetViewPort(UINT Width, UINT Height) +{ + D3D11_VIEWPORT VP; + VP.Width = static_cast(Width); + VP.Height = static_cast(Height); + VP.MinDepth = 0.0f; + VP.MaxDepth = 1.0f; + VP.TopLeftX = 0; + VP.TopLeftY = 0; + m_DeviceContext->RSSetViewports(1, &VP); +} + +// +// Resize swapchain +// +DUPL_RETURN OUTPUTMANAGER::ResizeSwapChain() +{ + if (m_RTV) + { + m_RTV->Release(); + m_RTV = nullptr; + } + + RECT WindowRect; + GetClientRect(m_WindowHandle, &WindowRect); + UINT Width = WindowRect.right - WindowRect.left; + UINT Height = WindowRect.bottom - WindowRect.top; + + // Resize swapchain + DXGI_SWAP_CHAIN_DESC SwapChainDesc; + m_SwapChain->GetDesc(&SwapChainDesc); + HRESULT hr = m_SwapChain->ResizeBuffers(SwapChainDesc.BufferCount, Width, Height, SwapChainDesc.BufferDesc.Format, SwapChainDesc.Flags); + if (FAILED(hr)) + { + return ProcessFailure(m_Device, L"Failed to resize swapchain buffers in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Make new render target view + DUPL_RETURN Ret = MakeRTV(); + if (Ret != DUPL_RETURN_SUCCESS) + { + return Ret; + } + + // Set new viewport + SetViewPort(Width, Height); + + return Ret; +} + +// +// Releases all references +// +void OUTPUTMANAGER::CleanRefs() +{ + if (m_VertexShader) + { + m_VertexShader->Release(); + m_VertexShader = nullptr; + } + + if (m_PixelShader) + { + m_PixelShader->Release(); + m_PixelShader = nullptr; + } + + if (m_InputLayout) + { + m_InputLayout->Release(); + m_InputLayout = nullptr; + } + + if (m_RTV) + { + m_RTV->Release(); + m_RTV = nullptr; + } + + if (m_SamplerLinear) + { + m_SamplerLinear->Release(); + m_SamplerLinear = nullptr; + } + + if (m_BlendState) + { + m_BlendState->Release(); + m_BlendState = nullptr; + } + + if (m_DeviceContext) + { + m_DeviceContext->Release(); + m_DeviceContext = nullptr; + } + + if (m_Device) + { + m_Device->Release(); + m_Device = nullptr; + } + + if (m_SwapChain) + { + m_SwapChain->Release(); + m_SwapChain = nullptr; + } + + if (m_SharedSurf) + { + m_SharedSurf->Release(); + m_SharedSurf = nullptr; + } + + if (m_KeyMutex) + { + m_KeyMutex->Release(); + m_KeyMutex = nullptr; + } + + if (m_Factory) + { + if (m_OcclusionCookie) + { + m_Factory->UnregisterOcclusionStatus(m_OcclusionCookie); + m_OcclusionCookie = 0; + } + m_Factory->Release(); + m_Factory = nullptr; + } +} diff --git a/Samples/DXGIDesktopDuplication/cpp/OutputManager.h b/Samples/DXGIDesktopDuplication/cpp/OutputManager.h new file mode 100644 index 00000000..cd16e5f0 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/OutputManager.h @@ -0,0 +1,61 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved + +#ifndef _OUTPUTMANAGER_H_ +#define _OUTPUTMANAGER_H_ + +#include + +#include "CommonTypes.h" +#include "warning.h" + +// +// Handles the task of drawing into a window. +// Has the functionality to draw the mouse given a mouse shape buffer and position +// +class OUTPUTMANAGER +{ + public: + OUTPUTMANAGER(); + ~OUTPUTMANAGER(); + DUPL_RETURN InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds); + DUPL_RETURN UpdateApplicationWindow(_In_ PTR_INFO* PointerInfo, _Inout_ bool* Occluded); + void CleanRefs(); + HANDLE GetSharedHandle(); + void WindowResize(); + + private: + // Methods + DUPL_RETURN ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInfo, _Out_ INT* PtrWidth, _Out_ INT* PtrHeight, _Out_ INT* PtrLeft, _Out_ INT* PtrTop, _Outptr_result_bytebuffer_(*PtrHeight * *PtrWidth * BPP) BYTE** InitBuffer, _Out_ D3D11_BOX* Box); + DUPL_RETURN MakeRTV(); + void SetViewPort(UINT Width, UINT Height); + DUPL_RETURN InitShaders(); + DUPL_RETURN InitGeometry(); + DUPL_RETURN CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds); + DUPL_RETURN DrawFrame(); + DUPL_RETURN DrawMouse(_In_ PTR_INFO* PtrInfo); + DUPL_RETURN ResizeSwapChain(); + + // Vars + IDXGISwapChain1* m_SwapChain; + ID3D11Device* m_Device; + IDXGIFactory2* m_Factory; + ID3D11DeviceContext* m_DeviceContext; + ID3D11RenderTargetView* m_RTV; + ID3D11SamplerState* m_SamplerLinear; + ID3D11BlendState* m_BlendState; + ID3D11VertexShader* m_VertexShader; + ID3D11PixelShader* m_PixelShader; + ID3D11InputLayout* m_InputLayout; + ID3D11Texture2D* m_SharedSurf; + IDXGIKeyedMutex* m_KeyMutex; + HWND m_WindowHandle; + bool m_NeedsResize; + DWORD m_OcclusionCookie; +}; + +#endif diff --git a/Samples/DXGIDesktopDuplication/cpp/PixelShader.hlsl b/Samples/DXGIDesktopDuplication/cpp/PixelShader.hlsl new file mode 100644 index 00000000..db0067da --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/PixelShader.hlsl @@ -0,0 +1,24 @@ +// 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 +//---------------------------------------------------------------------- + +Texture2D tx : register( t0 ); +SamplerState samLinear : register( s0 ); + +struct PS_INPUT +{ + float4 Pos : SV_POSITION; + float2 Tex : TEXCOORD; +}; + +//-------------------------------------------------------------------------------------- +// Pixel Shader +//-------------------------------------------------------------------------------------- +float4 PS(PS_INPUT input) : SV_Target +{ + return tx.Sample( samLinear, input.Tex ); +} \ No newline at end of file diff --git a/Samples/DXGIDesktopDuplication/cpp/ThreadManager.cpp b/Samples/DXGIDesktopDuplication/cpp/ThreadManager.cpp new file mode 100644 index 00000000..0656cb15 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/ThreadManager.cpp @@ -0,0 +1,258 @@ +// 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 "ThreadManager.h" + +DWORD WINAPI DDProc(_In_ void* Param); + +THREADMANAGER::THREADMANAGER() : m_ThreadCount(0), + m_ThreadHandles(nullptr), + m_ThreadData(nullptr) +{ + RtlZeroMemory(&m_PtrInfo, sizeof(m_PtrInfo)); +} + +THREADMANAGER::~THREADMANAGER() +{ + Clean(); +} + +// +// Clean up resources +// +void THREADMANAGER::Clean() +{ + if (m_PtrInfo.PtrShapeBuffer) + { + delete [] m_PtrInfo.PtrShapeBuffer; + m_PtrInfo.PtrShapeBuffer = nullptr; + } + RtlZeroMemory(&m_PtrInfo, sizeof(m_PtrInfo)); + + if (m_ThreadHandles) + { + for (UINT i = 0; i < m_ThreadCount; ++i) + { + if (m_ThreadHandles[i]) + { + CloseHandle(m_ThreadHandles[i]); + } + } + delete [] m_ThreadHandles; + m_ThreadHandles = nullptr; + } + + if (m_ThreadData) + { + for (UINT i = 0; i < m_ThreadCount; ++i) + { + CleanDx(&m_ThreadData[i].DxRes); + } + delete [] m_ThreadData; + m_ThreadData = nullptr; + } + + m_ThreadCount = 0; +} + +// +// Clean up DX_RESOURCES +// +void THREADMANAGER::CleanDx(_Inout_ DX_RESOURCES* Data) +{ + if (Data->Device) + { + Data->Device->Release(); + Data->Device = nullptr; + } + + if (Data->Context) + { + Data->Context->Release(); + Data->Context = nullptr; + } + + if (Data->VertexShader) + { + Data->VertexShader->Release(); + Data->VertexShader = nullptr; + } + + if (Data->PixelShader) + { + Data->PixelShader->Release(); + Data->PixelShader = nullptr; + } + + if (Data->InputLayout) + { + Data->InputLayout->Release(); + Data->InputLayout = nullptr; + } + + if (Data->SamplerLinear) + { + Data->SamplerLinear->Release(); + Data->SamplerLinear = nullptr; + } +} + +// +// Start up threads for DDA +// +DUPL_RETURN THREADMANAGER::Initialize(INT SingleOutput, UINT OutputCount, HANDLE UnexpectedErrorEvent, HANDLE ExpectedErrorEvent, HANDLE TerminateThreadsEvent, HANDLE SharedHandle, _In_ RECT* DesktopDim) +{ + m_ThreadCount = OutputCount; + m_ThreadHandles = new (std::nothrow) HANDLE[m_ThreadCount]; + m_ThreadData = new (std::nothrow) THREAD_DATA[m_ThreadCount]; + if (!m_ThreadHandles || !m_ThreadData) + { + return ProcessFailure(nullptr, L"Failed to allocate array for threads", L"Error", E_OUTOFMEMORY); + } + + // Create appropriate # of threads for duplication + DUPL_RETURN Ret = DUPL_RETURN_SUCCESS; + for (UINT i = 0; i < m_ThreadCount; ++i) + { + m_ThreadData[i].UnexpectedErrorEvent = UnexpectedErrorEvent; + m_ThreadData[i].ExpectedErrorEvent = ExpectedErrorEvent; + m_ThreadData[i].TerminateThreadsEvent = TerminateThreadsEvent; + m_ThreadData[i].Output = (SingleOutput < 0) ? i : SingleOutput; + m_ThreadData[i].TexSharedHandle = SharedHandle; + m_ThreadData[i].OffsetX = DesktopDim->left; + m_ThreadData[i].OffsetY = DesktopDim->top; + m_ThreadData[i].PtrInfo = &m_PtrInfo; + + RtlZeroMemory(&m_ThreadData[i].DxRes, sizeof(DX_RESOURCES)); + Ret = InitializeDx(&m_ThreadData[i].DxRes); + if (Ret != DUPL_RETURN_SUCCESS) + { + return Ret; + } + + DWORD ThreadId; + m_ThreadHandles[i] = CreateThread(nullptr, 0, DDProc, &m_ThreadData[i], 0, &ThreadId); + if (m_ThreadHandles[i] == nullptr) + { + return ProcessFailure(nullptr, L"Failed to create thread", L"Error", E_FAIL); + } + } + + return Ret; +} + +// +// Get DX_RESOURCES +// +DUPL_RETURN THREADMANAGER::InitializeDx(_Out_ DX_RESOURCES* Data) +{ + HRESULT hr = S_OK; + + // Driver types supported + D3D_DRIVER_TYPE DriverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + UINT NumDriverTypes = ARRAYSIZE(DriverTypes); + + // Feature levels supported + D3D_FEATURE_LEVEL FeatureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_1 + }; + UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels); + + D3D_FEATURE_LEVEL FeatureLevel; + + // Create device + for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) + { + hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr, 0, FeatureLevels, NumFeatureLevels, + D3D11_SDK_VERSION, &Data->Device, &FeatureLevel, &Data->Context); + if (SUCCEEDED(hr)) + { + // Device creation success, no need to loop anymore + break; + } + } + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to create device in InitializeDx", L"Error", hr); + } + + // VERTEX shader + UINT Size = ARRAYSIZE(g_VS); + hr = Data->Device->CreateVertexShader(g_VS, Size, nullptr, &Data->VertexShader); + if (FAILED(hr)) + { + return ProcessFailure(Data->Device, L"Failed to create vertex shader in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Input layout + D3D11_INPUT_ELEMENT_DESC Layout[] = + { + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0} + }; + UINT NumElements = ARRAYSIZE(Layout); + hr = Data->Device->CreateInputLayout(Layout, NumElements, g_VS, Size, &Data->InputLayout); + if (FAILED(hr)) + { + return ProcessFailure(Data->Device, L"Failed to create input layout in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); + } + Data->Context->IASetInputLayout(Data->InputLayout); + + // Pixel shader + Size = ARRAYSIZE(g_PS); + hr = Data->Device->CreatePixelShader(g_PS, Size, nullptr, &Data->PixelShader); + if (FAILED(hr)) + { + return ProcessFailure(Data->Device, L"Failed to create pixel shader in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); + } + + // Set up sampler + D3D11_SAMPLER_DESC SampDesc; + RtlZeroMemory(&SampDesc, sizeof(SampDesc)); + SampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + SampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + SampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + SampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + SampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + SampDesc.MinLOD = 0; + SampDesc.MaxLOD = D3D11_FLOAT32_MAX; + hr = Data->Device->CreateSamplerState(&SampDesc, &Data->SamplerLinear); + if (FAILED(hr)) + { + return ProcessFailure(Data->Device, L"Failed to create sampler state in InitializeDx", L"Error", hr, SystemTransitionsExpectedErrors); + } + + return DUPL_RETURN_SUCCESS; +} + +// +// Getter for the PTR_INFO structure +// +PTR_INFO* THREADMANAGER::GetPointerInfo() +{ + return &m_PtrInfo; +} + +// +// Waits infinitely for all spawned threads to terminate +// +void THREADMANAGER::WaitForThreadTermination() +{ + if (m_ThreadCount != 0) + { + WaitForMultipleObjectsEx(m_ThreadCount, m_ThreadHandles, TRUE, INFINITE, FALSE); + } +} diff --git a/Samples/DXGIDesktopDuplication/cpp/ThreadManager.h b/Samples/DXGIDesktopDuplication/cpp/ThreadManager.h new file mode 100644 index 00000000..9e4681a9 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/ThreadManager.h @@ -0,0 +1,33 @@ +// 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 + +#ifndef _THREADMANAGER_H_ +#define _THREADMANAGER_H_ + +#include "CommonTypes.h" + +class THREADMANAGER +{ + public: + THREADMANAGER(); + ~THREADMANAGER(); + void Clean(); + DUPL_RETURN Initialize(INT SingleOutput, UINT OutputCount, HANDLE UnexpectedErrorEvent, HANDLE ExpectedErrorEvent, HANDLE TerminateThreadsEvent, HANDLE SharedHandle, _In_ RECT* DesktopDim); + PTR_INFO* GetPointerInfo(); + void WaitForThreadTermination(); + + private: + DUPL_RETURN InitializeDx(_Out_ DX_RESOURCES* Data); + void CleanDx(_Inout_ DX_RESOURCES* Data); + + PTR_INFO m_PtrInfo; + UINT m_ThreadCount; + _Field_size_(m_ThreadCount) HANDLE* m_ThreadHandles; + _Field_size_(m_ThreadCount) THREAD_DATA* m_ThreadData; +}; + +#endif diff --git a/Samples/DXGIDesktopDuplication/cpp/VertexShader.hlsl b/Samples/DXGIDesktopDuplication/cpp/VertexShader.hlsl new file mode 100644 index 00000000..95f94355 --- /dev/null +++ b/Samples/DXGIDesktopDuplication/cpp/VertexShader.hlsl @@ -0,0 +1,28 @@ +// 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 +//---------------------------------------------------------------------- + +struct VS_INPUT +{ + float4 Pos : POSITION; + float2 Tex : TEXCOORD; +}; + +struct VS_OUTPUT +{ + float4 Pos : SV_POSITION; + float2 Tex : TEXCOORD; +}; + + +//-------------------------------------------------------------------------------------- +// Vertex Shader +//-------------------------------------------------------------------------------------- +VS_OUTPUT VS(VS_INPUT input) +{ + return input; +} \ No newline at end of file diff --git a/Samples/DataDedupBackupRestore/README.md b/Samples/DataDedupBackupRestore/README.md new file mode 100644 index 00000000..40aca619 --- /dev/null +++ b/Samples/DataDedupBackupRestore/README.md @@ -0,0 +1,68 @@ +Data deduplication backup and restore sample +============================================ + +This sample demonstrates the use of the [Data Deduplication Backup/Restore API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh449211) to perform optimized backup and optimized restore that is not optimized. + +For more information about this scenario, see [Selective File Restore Using Data Deduplication](http://msdn.microsoft.com/en-us/library/windows/desktop/hh769317). + +This sample is written in C++ and requires some experience with COM. + +This sample contains the following files: + +- DedupBackupRestore.cpp +- DedupBackupRestore.sln +- DedupBackupRestore.vcxproj + +**Warning** This sample requires Windows Server 2012 R2 and Microsoft Visual Studio 2013. It will not compile in Microsoft Visual Studio Express 2013 for Windows. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related technologies +-------------------- + +[Data Deduplication API](http://msdn.microsoft.com/en-us/library/windows/desktop/hh449204) + +Operating system requirements +----------------------------- + +Client + +None supported + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build the sample using the command line: + +- Open the **Command Prompt** window and navigate to the directory. +- Type **msbuild DedupBackupRestore.sln**. + +To build the sample using Visual Studio (preferred method): + +- Open File Explorer and navigate to the directory. +- 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 +-------------- + +To run the sample: + +1. Install the Data Deduplication component. +2. Set up a Data Deduplication-enabled volume with some test files, and run a Deduplication Optimization job to optimize the files first. + **Note** The following sequence of PowerShell cmdlets assumes that your test volume is T:. + 1. **Enable-DedupVolume  -volume T:** + 2. **Set-DedupVolume  -volume T: -MinimumFileAgeDays 0** + 3. **Start-DedupJob  -volume T: -type Optimization -wait** + + For more information, see the [Enable-DedupVolume](http://technet.microsoft.com/library/4a752894-524d-4a64-8483-f06a73ab0ed0) PowerShell cmdlet documentation. +3. Navigate to the directory that contains the new executable file, using the **Command Prompt** or **File Explorer**. + **Note** If you use the Command Prompt, you must run as administrator. +4. Type the name of the executable file (DedupBackupRestore.exe by default) at the command prompt. + diff --git a/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.cpp b/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.cpp new file mode 100644 index 00000000..5f607a71 --- /dev/null +++ b/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.cpp @@ -0,0 +1,2690 @@ +// 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. + +///////////////////////////////////////////////////////////////////// +// +// The following backup/restore scenarios are addressed in the code +// 1. Optimized backup +// 2. Selective restore from optimized backup +// 3. Full volume restore from optimized backup +// +///////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +#include "ddpbackup.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Backup/restore constants +const PCWSTR SYSTEM_VOLUME_INFORMATION = L"\\System Volume Information"; +const PCWSTR DEDUP_FOLDER = L"\\Dedup"; +const PCWSTR BACKUP_METADATA_FILE_NAME = L"dedupBackupMetadata.{741309a8-a42a-4830-b530-fad823933e6d}"; +const PCWSTR BACKUP_METADATA_FORMAT = L"%s\r\n%s\r\n"; +const PCWSTR LONG_PATH_PREFIX = L"\\\\?\\"; +const PCWSTR DIRECTORY_BACKUP_FILE = + L"directoryBackup.{741309a8-a42a-4830-b530-fad823933e6d}"; +const ULONG DEDUP_STORE_FOLDERS_COUNT = 3; +const PCWSTR DEDUP_STORE_FOLDERS[DEDUP_STORE_FOLDERS_COUNT] = + { + L"\\ChunkStore", + L"\\Settings", + L"\\State" + }; + +// WMI constants from Data Deduplication MOF schema +const PCWSTR CIM_V2_NAMESPACE = L"root\\cimv2"; +const PCWSTR CIM_DEDUP_NAMESPACE = L"root\\Microsoft\\Windows\\Deduplication"; +const PCWSTR CIM_DEDUP_CLASS_VOLUME = L"MSFT_DedupVolume"; +const PCWSTR CIM_DEDUP_CLASS_VOLUME_METADATA = L"MSFT_DedupVolumeMetadata"; +const PCWSTR CIM_DEDUP_CLASS_JOB = L"MSFT_DedupJob"; +const PCWSTR CIM_DEDUP_METHOD_ENABLE = L"Enable"; +const PCWSTR CIM_DEDUP_METHOD_DISABLE = L"Disable"; +const PCWSTR CIM_DEDUP_METHOD_STOP = L"Stop"; +const PCWSTR CIM_DEDUP_METHOD_START = L"Start"; +const PCWSTR CIM_DEDUP_PROP_STOREID = L"StoreId"; +const PCWSTR CIM_DEDUP_PROP_DATAACCESS = L"DataAccess"; +const PCWSTR CIM_DEDUP_PROP_VOLUME = L"Volume"; +const PCWSTR CIM_DEDUP_PROP_VOLUMEID = L"VolumeId"; +const PCWSTR CIM_DEDUP_PROP_RETURNVALUE = L"ReturnValue"; +const PCWSTR CIM_DEDUP_PROP_TYPE = L"Type"; +const PCWSTR CIM_DEDUP_PROP_TIMESTAMP = L"Timestamp"; +const PCWSTR CIM_DEDUP_PROP_WAIT = L"Wait"; +const PCWSTR CIM_DEDUP_PROP_JOB = L"DedupJob"; +const PCWSTR CIM_DEDUP_PROP_ID = L"Id"; +const PCWSTR CIM_DEDUP_PROP_ERRORCODE = L"error_Code"; +const PCWSTR CIM_DEDUP_PROP_ERRORMESSAGE = L"Message"; +const PCWSTR CIM_DEDUP_PROP_PATH = L"__PATH"; +const ULONG CIM_DEDUP_JOB_TYPE_UNOPT = 4; +const ULONG CIM_DEDUP_JOB_TYPE_GC = 2; + +const PCWSTR DEDUP_OPERATIONAL_EVENT_CHANNEL_NAME = + L"Microsoft-Windows-Deduplication/Operational"; + +#define DDP_E_NOT_FOUND ((HRESULT)0x80565301L) +#define DDP_E_PATH_NOT_FOUND ((HRESULT)0x80565304L) +#define DDP_E_VOLUME_DEDUP_DISABLED ((HRESULT)0x80565323L) + +#define ARRAY_LEN(A) (sizeof(A)/sizeof((A)[0])) + +// Global variables + +// Enums, classes +enum Action +{ + BackupAction, + RestoreStubAction, + RestoreDataAction, + RestoreFileAction, + RestoreVolumeAction, + RestoreFilesAction +}; + +HRESULT RestoreVolume(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT ToggleDedupJobs(_In_ const wstring& volumeGuidName, _In_ bool enableJobs); +HRESULT ToggleDedupDataAccess(_In_ const wstring& volumeGuidName, _In_ bool enableDataAccess); +HRESULT CancelDedupJobs(_In_ const wstring& volumeGuidName); +HRESULT GetJobInstanceId(_In_ IWbemClassObject* startJobOutParams, _Out_ wstring& jobId); +HRESULT DisplayUnoptimizationFileError(_In_ EVT_HANDLE event); +HRESULT CheckForUnoptimizationFileErrors(_In_ const wstring& jobId, _Out_ bool& foundErrors); +HRESULT UnoptimizeSinceTimestamp(_In_ const wstring& volumeGuidName, _In_ wstring& backupTime); +HRESULT RunGarbageCollection(_In_ const wstring& volumeGuidName); + +void DoBackup(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreStub(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreData(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreFilesData(_In_ const wstring& source, _In_ vector& restoredFiles); + +HRESULT BackupFile(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT BackupDirectory(_In_ const wstring& source, _In_ const wstring& destination); +void BackupDirectoryTree(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreFile(_In_ const wstring& source, _In_ const wstring& destination, _In_opt_ bool overWriteExisting = false); +HRESULT RestoreDirectory(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreDedupStoreDirectories(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreDedupStore(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT RestoreFiles(_In_ const wstring& source, _In_ const wstring& destination, _In_ const bool isVolumeRestore, _Out_opt_ vector* pRestoredFiles); +HRESULT RestoreDirectoryTree(_In_ const wstring& source, _In_ const wstring& destination, _In_ const vector& sourceExcludePaths, _Out_opt_ vector* pRestoredFiles); +HRESULT DeleteDirectoryTree(_In_ const wstring& directory); +HRESULT DeleteDedupStore(_In_ const wstring& volume); + +HRESULT GetDedupChunkStoreId(_In_ const wstring& volumeGuidName, _Out_ wstring& chunkStoreId); +HRESULT VolumeHasDedupMetadata(_In_ const wstring& volumeGuidName, _Out_ bool& hasDedupMetadata, _Out_ wstring& chunkStoreId); +void WriteBackupMetadata(_In_ const wstring& source, _In_ const wstring& destination); +HRESULT ReadBackupMetadata(_In_ const wstring& source, _Out_ wstring& chunkStoreId, _Out_ wstring& backupTime); +wstring BuildDedupStorePath(_In_ const wstring& volume); + +HRESULT WmiGetWbemServices(_In_ PCWSTR wmiNamespace, _Out_ CComPtr& spWmi); +HRESULT WmiGetMethodInputParams(_In_ IWbemServices* pWmi, _In_ PCWSTR className, _In_ PCWSTR methodName, _Out_ CComPtr& spInParams); +HRESULT WmiAddVolumeInputParameter(_Inout_ IWbemClassObject* pParams, _In_ PCWSTR className, _In_ PCWSTR methodName, _In_ const wstring& volume); +HRESULT WmiAddInputParameter(_Inout_ IWbemClassObject* pParams, _In_ PCWSTR className, _In_ PCWSTR methodName, _In_ PCWSTR propertyName, _In_ variant_t& var); +HRESULT WmiGetErrorInfo(_Out_ HRESULT& hrOperation, _Out_ wstring& errorMessageOperation); +HRESULT WmiExecuteMethod(_In_ IWbemServices* pWmi, _In_ PCWSTR className, _In_ PCWSTR methodName, _In_opt_ IWbemClassObject* pInParams, + _Out_ CComPtr& spOutParams, _In_opt_ PCWSTR context = L""); +HRESULT WmiGetDedupInstanceByVolumeId(PCWSTR className, _In_ const wstring& volumeGuidName, _Out_ CComPtr& instance); +HRESULT WmiQueryDedupInstancesByVolumeId(_In_ IWbemServices* pWmi, _In_ const wstring& className, _In_ const wstring& volumeGuidName, _Out_ CComPtr& instances); + +void StringReplace(_Inout_ wstring& stringValue, _In_ const wstring& matchValue, _In_ const wstring& replaceValue); +wstring TrimTrailingSeparator(_In_ const wstring& str, _In_ WCHAR separator); +bool IsRootPath(_In_ const wstring& path); +void PrintUsage(_In_ LPCWSTR programName); +bool ParseCommandLine(_In_ int argc, _In_reads_(argc) _TCHAR* argv[], _Out_ Action *action, _Out_ wstring* source, _Out_ wstring* destination); +HRESULT ModifyPrivilege(_In_ LPCTSTR szPrivilege, _In_ BOOL fEnable); +HRESULT GetVolumeGuidNameForPath(_In_ const wstring& path, _Out_ wstring& volumeGuidName); +HRESULT GetEventData(_In_ EVT_HANDLE event, _In_ PCWSTR dataName, _Out_ variant_t& varData); +HRESULT GetFileSize(_In_ const std::wstring& FilePath, _Out_ LARGE_INTEGER& FileSize); + + + +///////////////////////////////////////////////////////////////////// +// +// This class is for selective restore from optimized backup +// +///////////////////////////////////////////////////////////////////// +class CBackupStore: public IDedupReadFileCallback +{ +private: + ULONGLONG m_refCount; + std::wstring m_backupLocation; + std::map m_dataStreamMap; + +public: + CBackupStore(_In_ const wstring& backupLocation) + { + m_refCount = 1; + m_backupLocation = backupLocation; + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ __RPC__in REFIID riid, + /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) + { + if (IsEqualIID(riid, IID_IUnknown) || + IsEqualIID(riid, __uuidof(IDedupReadFileCallback))) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void) + { + return (ULONG) InterlockedIncrement(&m_refCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void) + { + ULONGLONG ref = InterlockedDecrement(&m_refCount); + if (ref == 0) delete this; + return (ULONG) ref; + } + + virtual HRESULT STDMETHODCALLTYPE ReadBackupFile( + /* [in] */ __RPC__in BSTR FileFullPath, + /* [in] */ hyper FileOffset, + /* [in] */ ULONG SizeToRead, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(SizeToRead, *ReturnedSize) BYTE *FileBuffer, + /* [out] */ __RPC__out ULONG *ReturnedSize, + /* [in] */ DWORD Flags) + { + // This method is called by the backup support COM object to read + // the backup database from the backup medium + + UNREFERENCED_PARAMETER(Flags); + HRESULT hr = S_OK; + wstring filePath = m_backupLocation; + filePath += FileFullPath; + *ReturnedSize = 0; + // FileBuffer contents can be uninitialized after byte *ReturnedSize + + HANDLE hFile = ::CreateFile( + filePath.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + wcout << L"Cannot open file " << filePath << + L". Did we back it up? Error: " << GetLastError() << endl; + } + else + { + // This file was saved with BackupRead, so its contents are actually a series of + // WIN32_STREAM_ID structures that describe the original file + // To read data as we would read from the original file, we first need to find + // the DATA stream. + // If the file was not backed up with BackupRead you would not need this + + LONGLONG dataStreamOffset = 0; + hr = FindDataStream(hFile, filePath, &dataStreamOffset); + if (SUCCEEDED(hr)) + { + LONGLONG actualFileOffset = FileOffset + dataStreamOffset; + OVERLAPPED overlapped = {}; + + overlapped.Offset = LODWORD(actualFileOffset); + overlapped.OffsetHigh = HIDWORD(actualFileOffset); + + if (!ReadFile(hFile, FileBuffer, SizeToRead, ReturnedSize, &overlapped)) + { + wcout << L"Cannot read from file " << filePath << + L". Did we back it up? gle= " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + CloseHandle(hFile); + } + + return hr; + } + + virtual HRESULT STDMETHODCALLTYPE OrderContainersRestore( + /* [in] */ ULONG NumberOfContainers, + /* [size_is][in] */ __RPC__in_ecount_full(NumberOfContainers) BSTR *ContainerPaths, + /* [out] */ __RPC__out ULONG *ReadPlanEntries, + /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*ReadPlanEntries) DEDUP_CONTAINER_EXTENT **ReadPlan) + { + UNREFERENCED_PARAMETER(ContainerPaths); + + // If you backed up to multiple tapes and parts of every file are split between the tapes + // you want avoid switching tapes back and forth as the restore engine the backup database files + // To implement this, you need to return the order in which the restore engine should read the files + // In this example, we tell the restore engine to read first 64k of every file first, then + // the remainder of the file. In a real tape backup application you would need to read the backup + // catalog, then return an array containing the file ranges on the first tape, + // then the files on the second tape, and so on + // If you are backing up on fixed disk you don't need to implement this, just uncomment the following 2 + // lines and delete the rest: + //*ReadPlanEntries = 0; + //*ReadPlan = NULL; + + if (ReadPlan == NULL) + { + *ReadPlanEntries = 0; + return S_OK; + } + + ULONG fileFragments = 2 * NumberOfContainers; + *ReadPlan = (DEDUP_CONTAINER_EXTENT*)MIDL_user_allocate(fileFragments * sizeof(DEDUP_CONTAINER_EXTENT)); + if (*ReadPlan != NULL) + { + *ReadPlanEntries = fileFragments; + + for (ULONG i = 0; i < 2 * NumberOfContainers; i++) + { + (*ReadPlan)[i].ContainerIndex = i % NumberOfContainers; + + wstring filePath = m_backupLocation; + wstring relativePath = ContainerPaths[i % NumberOfContainers]; + filePath += relativePath; + + // Chop the file at % of file size, to demonstrate extents + LARGE_INTEGER fileSize = {}; + GetFileSize(filePath, fileSize); + + ULONG extentBoundary = (fileSize.LowPart * 10) / 100; + + if (i < NumberOfContainers) + { + (*ReadPlan)[i].StartOffset = 0; + (*ReadPlan)[i].Length = extentBoundary; + } + else + { + (*ReadPlan)[i].StartOffset = extentBoundary; + (*ReadPlan)[i].Length = LONGLONG_MAX; // this just says "until the end of the file" + } + } + } + else + { + // If allocation fails, we will just not optimize + *ReadPlanEntries = 0; + } + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE PreviewContainerRead( + /* [in] */ __RPC__in BSTR FileFullPath, + /* [in] */ ULONG NumberOfReads, + /* [size_is][in] */ __RPC__in_ecount_full(NumberOfReads) DDP_FILE_EXTENT *ReadOffsets) + { + UNREFERENCED_PARAMETER(FileFullPath); + UNREFERENCED_PARAMETER(NumberOfReads); + UNREFERENCED_PARAMETER(ReadOffsets); + + // This will be called before the actual read, so you can optimize and do bigger reads instead + // of smaller ones. If you decide you want to do this, examine the ReadOffsets and do a bigger read + // into a big buffer, then satisfy the next reads from the buffer you allocated. + + return S_OK; + } + +private: + HRESULT FindDataStream(_In_ HANDLE hFile, _In_ const wstring& filePath, _Out_ LONGLONG* result) + { + // Cache the results per file path so we don't have to do this for every read + if (m_dataStreamMap.find(filePath) == m_dataStreamMap.end()) + { + WIN32_STREAM_ID streamId = {}; + DWORD bytesRead = 0; + while (streamId.dwStreamId != BACKUP_DATA) + { + ::SetFilePointerEx(hFile, streamId.Size, NULL, FILE_CURRENT); + // The Size field is the actual size starting from the cStreamName field, so we only want to read the header + if (!ReadFile(hFile, &streamId, FIELD_OFFSET(WIN32_STREAM_ID, cStreamName), &bytesRead, NULL) || + bytesRead != FIELD_OFFSET(WIN32_STREAM_ID, cStreamName)) + { + wcout << "Cannot find the data stream in file. Did you use something other than BackupRead? Error: " << + GetLastError() << endl; + return E_UNEXPECTED; + } + } + + // Get the current position + LARGE_INTEGER zero = {}; + LARGE_INTEGER currentPosition; + ::SetFilePointerEx(hFile, zero, ¤tPosition, FILE_CURRENT); + m_dataStreamMap[filePath] = currentPosition.QuadPart; + } + *result = m_dataStreamMap[filePath]; + return S_OK; + } +}; + +///////////////////////////////////////////////////////////////////// +// +// Selective restore +// +///////////////////////////////////////////////////////////////////// + + +HRESULT RestoreStub(_In_ const wstring& source, _In_ const wstring& destination) +{ + return RestoreFile(source, destination); +} + +HRESULT RestoreData(_In_ const wstring& source, _In_ const wstring& destination) +{ + // Source is a file name, but we need the directory name so we can read + // the backup database inside the backup store + size_t lastSeparator = source.rfind('\\'); + if (lastSeparator == wstring::npos) + { + wcout << L"source is not a file path" << endl; + return E_UNEXPECTED; + } + wstring backupLocation = source.substr(0, lastSeparator); + CBackupStore* pStore = new(nothrow) CBackupStore(backupLocation); + + if (pStore == NULL) + { + wcout << L"Not enough resources" << endl; + return E_OUTOFMEMORY; + } + + CComPtr backupSupport; + HRESULT hr = backupSupport.CoCreateInstance(__uuidof(DedupBackupSupport), NULL); + if (FAILED(hr)) + { + wcout << L"Cannot instantiate the restore engine, hr = 0x" << hex << hr << endl; + } + else + { + // NOTE: destination was already created by RestoreStub + BSTR bstrFile = SysAllocString(destination.c_str()); + if (bstrFile == NULL) + { + wcout << L"Not enough resources" << endl; + delete pStore; + return E_OUTOFMEMORY; + } + hr = backupSupport->RestoreFiles(1, &bstrFile, pStore, DEDUP_RECONSTRUCT_UNOPTIMIZED, NULL); + SysFreeString(bstrFile); + } + + if (FAILED(hr)) + { + wcout << L"Restore failed, hr = 0x" << hex << hr << endl; + // We need to clean up on failure + DeleteFile(destination.c_str()); + } + + if (hr == S_FALSE) + { + wcout << L"Destination file is not a Data Deduplication file" << endl; + } + delete pStore; + + return hr; +} + +HRESULT RestoreFilesData(_In_ const wstring& source, _In_ vector& restoredFiles) +{ + HRESULT hr = S_OK; + + size_t fileCount = restoredFiles.size(); + if (fileCount == 0) + { + wcout << L"No files to restore" << endl; + return S_OK; + } + + BSTR* bstrFiles = NULL; + CBackupStore* pStore = NULL; + HRESULT* hrRestoreResults = NULL; + CComPtr backupSupport; + + bstrFiles = new BSTR[fileCount]; + if (bstrFiles == NULL) + { + hr = E_OUTOFMEMORY; + goto Cleanup; + } + ZeroMemory(bstrFiles, sizeof(BSTR*) * fileCount); + + size_t index = 0; + for ( ; index < fileCount; ++index) + { + bstrFiles[index] = SysAllocString(restoredFiles[index].c_str()); + if (bstrFiles[index] == NULL) + { + hr = E_OUTOFMEMORY; + goto Cleanup; + } + } + + hrRestoreResults = new HRESULT[fileCount]; + if (hrRestoreResults == NULL) + { + hr = E_OUTOFMEMORY; + goto Cleanup; + } + + pStore = new(nothrow) CBackupStore(source); + if (pStore == NULL) + { + hr = E_OUTOFMEMORY; + goto Cleanup; + } + + hr = backupSupport.CoCreateInstance(__uuidof(DedupBackupSupport), NULL); + if (FAILED(hr)) + { + wcout << L"Cannot instantiate the restore engine, hr = 0x" << hex << hr << endl; + goto Cleanup; + } + + // NOTE: destination stubs were already created by RestoreFiles + hr = backupSupport->RestoreFiles((ULONG)fileCount, bstrFiles, pStore, DEDUP_RECONSTRUCT_UNOPTIMIZED, hrRestoreResults); + + if (FAILED(hr)) + { + wcout << L"Restore failed, hr = 0x" << hex << hr << endl; + + // Files not restored successfully will have deduplication reparse points + // Non-dedup files were completely restored when restoring stubs + // When error code is DDP_E_JOB_COMPLETED_PARTIAL_SUCCESS some deduplicated files were also fully restored + // Cleanup failed restores + for (index = 0; index < fileCount; ++index) + { + if (FAILED(hrRestoreResults[index])) + { + wcout << L"Failed to restore file " << bstrFiles[index] << L", hr = 0x" << hex << hr << endl; + DeleteFile(bstrFiles[index]); + } + } + } + +Cleanup: + + if (hr == E_OUTOFMEMORY) + { + wcout << L"Not enough resources" << endl; + } + + if (pStore != NULL) + { + delete pStore; + } + + if (hrRestoreResults != NULL) + { + delete [] hrRestoreResults; + } + + if (bstrFiles != NULL) + { + for (index = 0; index < fileCount; ++index) + { + if (bstrFiles[index] != NULL) + { + SysFreeString(bstrFiles[index]); + } + } + delete [] bstrFiles; + } + + return hr; +} + +///////////////////////////////////////////////////////////////////// +// +// Backup full or selective volume +// +///////////////////////////////////////////////////////////////////// + +void DoBackup(_In_ const wstring& source, _In_ const wstring& destination) +{ + // Recursivelly back up the specified directory + BackupDirectoryTree(source, destination); + + WCHAR volumePathName[MAX_PATH]; + GetVolumePathName(source.c_str(), volumePathName, MAX_PATH); + + if (source != volumePathName) + { + // Important: you must always ensure you back up the deduplication database, which is under + // System Volume Information\Dedup and contains the actual file data + // since we didn't back up the whole volume we need to back it up now + + wstring dedupDatabase; + dedupDatabase = volumePathName; + dedupDatabase = TrimTrailingSeparator(dedupDatabase, L'\\'); + dedupDatabase += SYSTEM_VOLUME_INFORMATION; + + wstring databaseDestination = destination; + databaseDestination += SYSTEM_VOLUME_INFORMATION; + + // Backup SVI folder + BackupDirectory(dedupDatabase, databaseDestination); + + databaseDestination += DEDUP_FOLDER; + dedupDatabase += DEDUP_FOLDER; + + // Backup the deduplication store + BackupDirectoryTree(dedupDatabase, databaseDestination); + } + + WriteBackupMetadata(source, destination); +} + + + +///////////////////////////////////////////////////////////////////// +// +// Full volume restore core +// +///////////////////////////////////////////////////////////////////// + +HRESULT RestoreVolume(_In_ const wstring& source, _In_ const wstring& destination) +{ + HRESULT hr = S_OK; + wstring destinationDedupStoreId; + wstring destinationVolumeGuidName; + wstring sourceDedupStoreId; + wstring backupTime; + bool destinationHasDedupMetadata = false; + + wcout << L"Restoring files from '" << source << L"' to volume '" << destination << L"'" << endl; + + hr = GetVolumeGuidNameForPath(destination, destinationVolumeGuidName); + + // Get the chunk store ID and backup timestamp from the backup metadata + if (SUCCEEDED(hr)) + { + hr = ReadBackupMetadata(source, sourceDedupStoreId, backupTime); + } + + // Check for deduplication metadata + if (SUCCEEDED(hr)) + { + hr = VolumeHasDedupMetadata(destinationVolumeGuidName, destinationHasDedupMetadata, destinationDedupStoreId); + } + + if (SUCCEEDED(hr) && destinationHasDedupMetadata) + { + if (_wcsicmp(sourceDedupStoreId.c_str(), destinationDedupStoreId.c_str()) != 0) + { + wcout << L"Restore is unsupported. Source deduplication store ID '" << sourceDedupStoreId << + L"' does not match destination ID '" << destinationDedupStoreId << L"'." << endl; + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (SUCCEEDED(hr)) + { + // Disable deduplication jobs on the volume to avoid disruption during restore + hr = ToggleDedupJobs(destinationVolumeGuidName, false); + } + + // Cancel deduplication jobs running/queued on the volume + if (SUCCEEDED(hr)) + { + hr = CancelDedupJobs(destinationVolumeGuidName); + } + + // Unoptimize files that changed since backup timestamp + if (SUCCEEDED(hr)) + { + hr = UnoptimizeSinceTimestamp(destinationVolumeGuidName, backupTime); + } + + // Disable deduplication data access on the volume during restore + // NOTE: this operation causes the destination volume to dismount/remount + if (SUCCEEDED(hr)) + { + hr = ToggleDedupDataAccess(destinationVolumeGuidName, false); + } + + // Delete the deduplication store + if (SUCCEEDED(hr)) + { + hr = DeleteDedupStore(destinationVolumeGuidName); + } + } + + // Restore deduplication store + if (SUCCEEDED(hr)) + { + hr = RestoreDedupStore(source, destination); + } + + if (SUCCEEDED(hr) && !destinationHasDedupMetadata) + { + // Deduplication store is restored to a fresh volume + // Jobs and data access need to be disabled to avoid disruption during restore + + // Disable deduplication jobs on the volume + hr = ToggleDedupJobs(destinationVolumeGuidName, false); + + // Disable deduplication data access on the volume + // NOTE: this operation causes the destination volume to dismount/remount + if (SUCCEEDED(hr)) + { + hr = ToggleDedupDataAccess(destinationVolumeGuidName, false); + } + + // Set state such that deduplication is reenabled after restore + destinationHasDedupMetadata = true; + } + + // Restore files on the volume + if (SUCCEEDED(hr)) + { + // This sample restores files with source priority in cases where a file/directory + // exists in both the backup store and the target volume + // A real backup application might offer the option of target volume priority semantics + hr = RestoreFiles(source, destination, true, NULL); + } + + // Reenable deduplication jobs and data access + if (SUCCEEDED(hr) && destinationHasDedupMetadata) + { + // Enable deduplication data access on the volume + // NOTE: this operation causes the destination volume to dismount/remount + hr = ToggleDedupDataAccess(destinationVolumeGuidName, true); + + if (SUCCEEDED(hr)) + { + // Enable deduplication jobs on the volume + hr = ToggleDedupJobs(destinationVolumeGuidName, true); + } + } + + // Run GC job + if (SUCCEEDED(hr)) + { + hr = RunGarbageCollection(destinationVolumeGuidName); + } + + if (SUCCEEDED(hr)) + { + wcout << L"Restore completed" << endl; + } + else + { + wcout << L"Restore completed with error 0x" << hex << hr << endl; + } + + return hr; +} + + + +HRESULT GetDedupChunkStoreId(_In_ const wstring& volumeGuidName, _Out_ wstring& chunkStoreId) +{ + + HRESULT hr = S_OK; + CComPtr spInstance; + + chunkStoreId.clear(); + + // Returns S_FALSE if not found + hr = WmiGetDedupInstanceByVolumeId(CIM_DEDUP_CLASS_VOLUME_METADATA, volumeGuidName, spInstance); + + if (hr == S_OK) + { + _variant_t var; + + // Get the value of the StoreId property + hr = spInstance->Get(CIM_DEDUP_PROP_STOREID, 0, &var, 0, 0); + if (FAILED(hr)) + { + wcout << L"IWbemClassObject::Get for property StoreId failed with error 0x" << hex << hr << endl; + } + else + { + chunkStoreId = var.bstrVal; + } + } + + return hr; +} + + +HRESULT ToggleDedupJobs(_In_ const wstring& volumeGuidName, _In_ bool enableJobs) +{ + wstring methodName = enableJobs ? CIM_DEDUP_METHOD_ENABLE : CIM_DEDUP_METHOD_DISABLE; + + // Setup for WMI method call - get WBEM services, input parameter object + + CComPtr spWmi; + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + CComPtr spInParams; + if (SUCCEEDED(hr)) + { + hr = WmiGetMethodInputParams(spWmi, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), spInParams); + } + + if (SUCCEEDED(hr)) + { + hr = WmiAddVolumeInputParameter(spInParams, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), volumeGuidName); + } + + if (SUCCEEDED(hr)) + { + CComPtr spOutParams; + hr = WmiExecuteMethod(spWmi, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), spInParams, spOutParams, L"Jobs"); + } + + return hr; +} + +HRESULT ToggleDedupDataAccess(_In_ const wstring& volumeGuidName, _In_ bool enableDataAccess) +{ + wstring methodName = enableDataAccess ? CIM_DEDUP_METHOD_ENABLE : CIM_DEDUP_METHOD_DISABLE; + + // Setup for WMI method call - get WBEM services, input parameter object + CComPtr spWmi; + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + CComPtr spInParams; + if (SUCCEEDED(hr)) + { + hr = WmiGetMethodInputParams(spWmi, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), spInParams); + } + + // Volume name parameter + if (SUCCEEDED(hr)) + { + hr = WmiAddVolumeInputParameter(spInParams, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), volumeGuidName); + } + + // DataAccess parameter + if (SUCCEEDED(hr)) + { + variant_t dataAccessTrigger = true;; + + hr = WmiAddInputParameter(spInParams, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), CIM_DEDUP_PROP_DATAACCESS, dataAccessTrigger); + } + + // Execute method + if (SUCCEEDED(hr)) + { + CComPtr spOutParams; + hr = WmiExecuteMethod(spWmi, CIM_DEDUP_CLASS_VOLUME, methodName.c_str(), spInParams, spOutParams, L"DataAccess"); + } + + return hr; +} + +HRESULT CancelDedupJobs(_In_ const wstring& volumeGuidName) +{ + CComPtr spWmi; + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + // Get the job instance queued/running for the specified volume + CComPtr spInstances; + if (SUCCEEDED(hr)) + { + hr = WmiQueryDedupInstancesByVolumeId(spWmi, CIM_DEDUP_CLASS_JOB, volumeGuidName.c_str(), spInstances); + } + + // Stop each job + while (SUCCEEDED(hr)) + { + + CComPtr spInstance; + ULONG uReturn = 0; + + // Get a job instance + hr = spInstances->Next(WBEM_INFINITE, 1, &spInstance, &uReturn); + if (FAILED(hr)) + { + wcout << L"IEnumWbemClassObject::Next failed with error 0x" << hex << hr << endl; + break; + } + + if (uReturn == 0) + { + // All done + break; + } + + // Get the __PATH property (used as input to ExecMethod) + variant_t varObjectPath; + hr = spInstance->Get(CIM_DEDUP_PROP_PATH, 0, &varObjectPath, 0, 0); + if (FAILED(hr)) + { + wcout << L"IWbemClassObject::Get for property " << CIM_DEDUP_PROP_PATH << L" failed with error 0x" << hex << hr << endl; + break; + } + + // Call the Stop method + if (SUCCEEDED(hr)) + { + // NOTE: the MSFT_DedupJob.Stop method takes no input parameters + CComPtr spOutParams; + hr = WmiExecuteMethod(spWmi, varObjectPath.bstrVal, CIM_DEDUP_METHOD_STOP, NULL, spOutParams); + if (FAILED(hr)) + { + break; + } + } + } + + return hr; +} + +HRESULT RestoreDedupStoreDirectories(_In_ const wstring& source, _In_ const wstring& destination) +{ + wstring sourcePath = source; + wstring destinationPath = destination; + + sourcePath += SYSTEM_VOLUME_INFORMATION; + destinationPath += SYSTEM_VOLUME_INFORMATION; + + HRESULT hr = RestoreDirectory(sourcePath, destinationPath); + + if (SUCCEEDED(hr) || hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)) + { + sourcePath += DEDUP_FOLDER; + destinationPath += DEDUP_FOLDER; + + hr = RestoreDirectory(sourcePath, destinationPath); + } + + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)) + { + hr = S_OK; + } + + return hr; +} + +HRESULT RestoreDedupStore(_In_ const wstring& source, _In_ const wstring& destination) +{ + HRESULT hr = RestoreDedupStoreDirectories(source, destination); + + if (SUCCEEDED(hr)) + { + wstring sourceDedupStorePath = BuildDedupStorePath(source); + wstring destinationDedupStore = BuildDedupStorePath(destination); + + for (int index = 0; SUCCEEDED(hr) && index < DEDUP_STORE_FOLDERS_COUNT; index++) + { + wstring sourceDedupPath = sourceDedupStorePath; + sourceDedupPath.append(DEDUP_STORE_FOLDERS[index]); + + wstring destinationDedupPath = destinationDedupStore; + destinationDedupPath.append(DEDUP_STORE_FOLDERS[index]); + + vector excludePaths; + hr = RestoreDirectoryTree(sourceDedupPath, destinationDedupPath, excludePaths, NULL); + } + } + + return hr; +} + +HRESULT RestoreFiles(_In_ const wstring& source, _In_ const wstring& destination, _In_ const bool isVolumeRestore, _Out_opt_ vector* pRestoredFiles) +{ + HRESULT hr = S_OK; + + // Restore files (exclude deduplication store) + + vector excludePaths; + excludePaths.push_back(BuildDedupStorePath(source)); + + if (SUCCEEDED(hr)) + { + hr = RestoreDirectoryTree(source, destination, excludePaths, pRestoredFiles); + } + + if (SUCCEEDED(hr) && !isVolumeRestore) + { + // NOTE: RestoreDirectoryTree also restores SVI folder + // If the backed up directory was a volume root there may be files to restore under SVI folder + // If the backed up directory was a folder then SVI should be cleaned up + // Directory deletion failures ignored intentionally + wstring dedupStorePath = TrimTrailingSeparator(destination, L'\\'); + dedupStorePath.append(SYSTEM_VOLUME_INFORMATION); + RemoveDirectory(dedupStorePath.c_str()); + } + + return hr; +} + +HRESULT GetJobInstanceId(_In_ IWbemClassObject* startJobOutParams, _Out_ wstring& jobId) +{ + UNREFERENCED_PARAMETER(jobId); + + _variant_t varArray; + + jobId.clear(); + + // Get the value of the StoreId property + HRESULT hr = startJobOutParams->Get(CIM_DEDUP_PROP_JOB, 0, &varArray, 0, 0); + if (FAILED(hr)) + { + wcout << L"IWbemClassObject::Get for property " << CIM_DEDUP_PROP_JOB << L" failed with error 0x" << hex << hr << endl; + } + + if (varArray.vt != (VT_ARRAY | VT_UNKNOWN)) + { + wcout << L"VT Type is unexpected for property " << CIM_DEDUP_PROP_JOB << endl; + hr = E_FAIL; + } + + if (varArray.ppunkVal == NULL || *(varArray.ppunkVal) == NULL) + { + wcout << L"Property " << CIM_DEDUP_PROP_JOB << L" has a NULL value" << endl; + hr = E_FAIL; + } + + IUnknown* unknown = NULL; + + if (SUCCEEDED(hr)) + { + long index = 0; + SAFEARRAY *sa = varArray.parray; + hr = SafeArrayGetElement(sa, &index, &unknown); + if (FAILED(hr)) + { + wcout << L"SafeArrayGetElement failed with error 0x" << hex << hr << endl; + } + + if (unknown == NULL) + { + wcout << L"Property " << CIM_DEDUP_PROP_JOB << L" has a NULL value" << endl; + hr = E_FAIL; + } + } + + if (SUCCEEDED(hr)) + { + CComPtr spJob; + + CComPtr spUnknown = unknown; + + hr = spUnknown->QueryInterface(&spJob); + if (FAILED(hr)) + { + wcout << L"IUnknown::QueryInterface for IWbemClassObject failed with error 0x" << hex << hr << endl; + } + + if (SUCCEEDED(hr)) + { + variant_t varJobId; + + HRESULT hr = spJob->Get(CIM_DEDUP_PROP_ID, 0, &varJobId, 0, 0); + if (FAILED(hr)) + { + wcout << L"IWbemClassObject::Get for property " << CIM_DEDUP_PROP_ID << L" failed with error 0x" << hex << hr << endl; + } + + if (varJobId.vt != VT_BSTR) + { + wcout << L"VT Type is unexpected for property " << CIM_DEDUP_PROP_JOB << endl; + hr = E_FAIL; + } + + if (SUCCEEDED(hr)) + { + jobId = varJobId.bstrVal; + } + } + + } + + return hr; +} + +HRESULT GetEventData(_In_ EVT_HANDLE event, _In_ PCWSTR dataName, _Out_ variant_t& varData) +{ + HRESULT hr = S_OK; + + wstring eventDataXPath(L"Event/EventData/Data[@Name='"); + eventDataXPath.append(dataName); + eventDataXPath.append(L"']"); + + PCWSTR values[] = { eventDataXPath.c_str() }; + + EVT_HANDLE renderContext = EvtCreateRenderContext( + ARRAYSIZE(values), + values, + EvtRenderContextValues); + + if (renderContext == NULL) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + wcout << L"EvtCreateRenderContext failed with error " << GetLastError() << endl; + } + + if (SUCCEEDED(hr)) + { + PEVT_VARIANT properties = NULL; + ULONG bufferUsed = 0; + ULONG propertyCount = 0; + + BOOL result = EvtRender( + renderContext, + event, + EvtRenderEventValues, + 0, + NULL, + &bufferUsed, + &propertyCount); + + if (!result) + { + DWORD status = ::GetLastError(); + + if (status == ERROR_INSUFFICIENT_BUFFER) + { + WCHAR eventDataBuffer[1024] = {}; // production code should use dynamic memory + + properties = (PEVT_VARIANT)eventDataBuffer; + + result = ::EvtRender( + renderContext, + event, + EvtRenderEventValues, + sizeof(eventDataBuffer), + properties, + &bufferUsed, + &propertyCount); + } + } + + if (!result) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + wcout << L"EvtRender failed with error " << GetLastError() << endl; + } + + if (SUCCEEDED(hr)) + { + if (properties[0].Type == EvtVarTypeString) + { + varData = properties[0].StringVal; + } + else if (properties[0].Type == EvtVarTypeUInt32) + { + varData.ulVal = properties[0].UInt32Val; + varData.vt = VT_UI4; + } + else + { + wcout << L"Conversion from " << properties[0].Type << L" not implemented" << endl; + hr = E_FAIL; + } + } + + if (renderContext != NULL) + { + EvtClose(renderContext); + } + + } + + return hr; +} + +HRESULT DisplayUnoptimizationFileError(_In_ EVT_HANDLE event) +{ + wstring parentPath = L""; + wstring fileName = L""; + wstring errorMessage = L""; + ULONG errorCode = 0; + + variant_t var; + HRESULT hr = GetEventData(event, L"ParentDirectoryPath", var); + + if (SUCCEEDED(hr)) + { + parentPath = var.bstrVal; + } + + var.Clear(); + hr = GetEventData(event, L"FileName", var); + + if (SUCCEEDED(hr)) + { + fileName = var.bstrVal; + } + + var.Clear(); + hr = GetEventData(event, L"ErrorMessage", var); + + if (SUCCEEDED(hr)) + { + errorMessage = var.bstrVal; + } + + var.Clear(); + hr = GetEventData(event, L"ErrorCode", var); + + if (SUCCEEDED(hr)) + { + errorCode = var.ulVal; + } + + wstring filePath = parentPath + fileName; + + wcout << L"Unoptimization file error" << endl + << L" File path: " << filePath << endl + << L" Error code: 0x" << hex << errorCode << endl + << L" Error message: " << errorMessage << endl; + + return hr; +} + +HRESULT CheckForUnoptimizationFileErrors(_In_ const wstring& jobId, _Out_ bool& foundErrors) +{ + HRESULT hr = S_OK; + foundErrors = false; + + // Query for errors from the specified job ID + + // Build the query string + const PCWSTR eventQueryPrefix = + L" " + L" "; + + wstring queryXml = eventQueryPrefix; + queryXml.append(jobId); + queryXml.append(eventQuerySuffix); + + // Execute the query + EVT_HANDLE queryResult = EvtQuery( + NULL, + DEDUP_OPERATIONAL_EVENT_CHANNEL_NAME, + queryXml.c_str(), + //L"Event/System[EventID=6144]", + EvtQueryChannelPath | EvtQueryReverseDirection); + + if (queryResult == NULL) + { + DWORD error = ::GetLastError(); + hr = HRESULT_FROM_WIN32(error); + wcout << L"EvtQuery for unoptimization file errors failed with error " << error << endl; + } + + // Process the returned events, if any + while (SUCCEEDED(hr)) + { + DWORD eventsReturned = 0; + EVT_HANDLE eventHandle = NULL; + + BOOL bStatus = EvtNext( + queryResult, + 1, + &eventHandle, + INFINITE, + 0, + &eventsReturned); + + if (!bStatus) + { + DWORD error = ::GetLastError(); + + if (error != ERROR_NO_MORE_ITEMS) + { + hr = HRESULT_FROM_WIN32(error); + wcout << L"EvtNext for unoptimization file error failed with error " << error << endl; + } + else + { + break; + } + } + else if (eventsReturned == 1) + { + DisplayUnoptimizationFileError(eventHandle); + EvtClose(eventHandle); + foundErrors = true; + } + } + + if (queryResult != NULL) + { + EvtClose(queryResult); + } + + return hr; +} + +HRESULT UnoptimizeSinceTimestamp(_In_ const wstring& volumeGuidName, _In_ wstring& backupTime) +{ + // Setup for WMI method call - get WBEM services, input parameter object + CComPtr spWmi; + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + CComPtr spInParams; + if (SUCCEEDED(hr)) + { + hr = WmiGetMethodInputParams(spWmi, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, spInParams); + } + + // Volume parameter + if (SUCCEEDED(hr)) + { + hr = WmiAddVolumeInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, volumeGuidName); + } + + // Job type parameter + if (SUCCEEDED(hr)) + { + // Unoptimization job is type=4 (from Data Deduplication MOF schema) + variant_t var; + var.lVal = CIM_DEDUP_JOB_TYPE_UNOPT; + var.vt = VT_I4; + hr = WmiAddInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, CIM_DEDUP_PROP_TYPE, var); + } + + // Timestamp parameter + if (SUCCEEDED(hr)) + { + variant_t var = backupTime.c_str(); + hr = WmiAddInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, CIM_DEDUP_PROP_TIMESTAMP, var); + } + + // Job wait parameter for synchronous job + // NOTE: real backup applications might run optimization job asynchronously, track progress, etc. + if (SUCCEEDED(hr)) + { + variant_t var = (bool) true; + hr = WmiAddInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, CIM_DEDUP_PROP_WAIT, var); + } + + // Execute the unoptimization job + wstring jobId; + if (SUCCEEDED(hr)) + { + CComPtr spOutParams; + hr = WmiExecuteMethod(spWmi, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, spInParams, spOutParams, L"Unoptimization"); + + // Get the job id for error tracking + if (SUCCEEDED(hr)) + { + hr = GetJobInstanceId(spOutParams, jobId); + } + } + + // Check for file errors + if (SUCCEEDED(hr)) + { + bool foundErrors = false; + hr = CheckForUnoptimizationFileErrors(jobId, foundErrors); + + if (foundErrors) + { + wcout << L"One or more files failed to unoptimize. Resolve the problems and retry the restore." << endl; + hr = E_FAIL; + } + } + + return hr; +} + +HRESULT RunGarbageCollection(_In_ const wstring& volumeGuidName) +{ + // Setup for WMI method call - get WBEM services, input parameter object + CComPtr spWmi; + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + CComPtr spInParams; + if (SUCCEEDED(hr)) + { + hr = WmiGetMethodInputParams(spWmi, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, spInParams); + } + + // Volume parameter + if (SUCCEEDED(hr)) + { + hr = WmiAddVolumeInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, volumeGuidName); + } + + // Job type parameter + if (SUCCEEDED(hr)) + { + // GC job is type=2 (from Data Deduplication MOF schema) + variant_t var; + var.lVal = CIM_DEDUP_JOB_TYPE_GC; + var.vt = VT_I4; + hr = WmiAddInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, CIM_DEDUP_PROP_TYPE, var); + } + + // Job wait parameter for synchronous job + // NOTE: Backup applications are not required to wait for GC completion + if (SUCCEEDED(hr)) + { + variant_t var = (bool) true; + hr = WmiAddInputParameter(spInParams, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, CIM_DEDUP_PROP_WAIT, var); + } + + + // Execute the method + // Job will be queued and execute asynchronously + if (SUCCEEDED(hr)) + { + CComPtr spOutParams; + hr = WmiExecuteMethod(spWmi, CIM_DEDUP_CLASS_JOB, CIM_DEDUP_METHOD_START, spInParams, spOutParams, L"GarbageCollection"); + } + return hr; +} + + +HRESULT DeleteDedupStore(_In_ const wstring& volume) +{ + HRESULT hr = S_OK; + + wstring dedupStorePath = BuildDedupStorePath(volume); + + hr = DeleteDirectoryTree(dedupStorePath); + + return hr; +} + +///////////////////////////////////////////////////////////////////// +// +// Program main +// +///////////////////////////////////////////////////////////////////// + +int __cdecl _tmain(_In_ int argc, _In_reads_(argc) _TCHAR* argv[]) +{ + wstring source, destination; + Action action; + + if (!ParseCommandLine(argc, argv, &action, &source, &destination)) + { + PrintUsage(argv[0]); + return 1; + } + + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (SUCCEEDED(hr)) + { + hr = CoInitializeSecurity( + NULL, + -1, // COM authentication + NULL, // Authentication services + NULL, // Reserved + RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication + RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation + NULL, // Authentication info + EOAC_NONE, // Additional capabilities + NULL // Reserved + ); + + if (SUCCEEDED(hr)) + { + hr = ModifyPrivilege(SE_BACKUP_NAME, TRUE); + } + + if (SUCCEEDED(hr)) + { + hr = ModifyPrivilege(SE_RESTORE_NAME, TRUE); + } + + // Permit paths longer than MAX_PATH + source = wstring(LONG_PATH_PREFIX) + source; + destination = wstring(LONG_PATH_PREFIX) + destination; + + if (SUCCEEDED(hr)) + { + switch (action) + { + case BackupAction: + DoBackup(source, destination); + break; + case RestoreStubAction: + hr = RestoreStub(source, destination); + break; + case RestoreDataAction: + hr = RestoreData(source, destination); + break; + case RestoreFileAction: + hr = RestoreStub(source, destination); + if (SUCCEEDED(hr)) + { + hr = RestoreData(source, destination); + } + break; + case RestoreVolumeAction: + hr = RestoreVolume(source, destination); + break; + case RestoreFilesAction: + vector restoredFiles; + hr = RestoreFiles(source, destination, false, &restoredFiles); + if (SUCCEEDED(hr)) + { + hr = RestoreFilesData(source, restoredFiles); + } + restoredFiles.clear(); + break; + } + } + + CoUninitialize(); + } + + if (FAILED(hr)) return 1; + return 0; +} + +///////////////////////////////////////////////////////////////////// +// +// Backup/restore utilities +// +///////////////////////////////////////////////////////////////////// + +wstring BuildDedupStorePath(_In_ const wstring& volume) +{ + wstring dedupStorePath = TrimTrailingSeparator(volume, L'\\'); + + dedupStorePath.append(SYSTEM_VOLUME_INFORMATION); + dedupStorePath.append(DEDUP_FOLDER); + + return dedupStorePath; +} + +///////////////////////////////////////////////////////////////////// +// +// Backup related methods +// +///////////////////////////////////////////////////////////////////// + +HRESULT BackupFile(_In_ const wstring& source, _In_ const wstring& destination) +{ + // Open the source file + HANDLE hSourceFile = ::CreateFile( + source.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (hSourceFile == INVALID_HANDLE_VALUE) + { + wcout << L"CreateFile(" << source << L" failed with error " << GetLastError() << endl; + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Open the backup medium + // in this example the medium is another file, but it could be tape, network server, etc... + HANDLE hDestinationFile = ::CreateFile( + destination.c_str(), + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (hDestinationFile == INVALID_HANDLE_VALUE) + { + wcout << L"CreateFile(" << destination << L") failed with error " << GetLastError() << endl; + return HRESULT_FROM_WIN32(GetLastError()); + } + + // 4k is the default NTFS cluster size, and small enough to fit into the stack + // we could also readk 8k if we can afford the extra stack cost or allocate a heap buffer + // and read 64k or more + const DWORD DEFAULT_BUFFER_SIZE = 4086; + DWORD bytesRead = 0, bytesWritten = 0; + BYTE buffer[DEFAULT_BUFFER_SIZE]; + LPVOID context = NULL; + HRESULT hr = S_OK; + + // Read 4k at a time. BackupRead will return attributes, security, and reparse point information + while (BackupRead(hSourceFile, buffer, DEFAULT_BUFFER_SIZE, &bytesRead, FALSE, TRUE, &context) && bytesRead > 0) + { + // Save the data describing the source file to the destination medium. + // we do a write file here, but if this would be a network server you could send on a socket + if (!WriteFile(hDestinationFile, buffer, bytesRead, &bytesWritten, NULL)) + { + wcout << L"WriteFile(" << destination << L") failed with error " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(GetLastError()); + break; + } + + if (bytesRead != bytesWritten) + { + wcout << L"WriteFile(" << destination << L") unexpectedly wrote less bytes than expected (expected:" << bytesRead << L" written:" << bytesWritten << L")" << endl; + hr = E_UNEXPECTED; + break; + } + } + + // Call BackupRead one more time to clean up the context + BackupRead(hSourceFile, NULL, 0, NULL, TRUE, TRUE, &context); + + // Close the source file + CloseHandle(hSourceFile); + + // Close the backup medium + CloseHandle(hDestinationFile); + + return hr; +} + +HRESULT BackupDirectory(_In_ const wstring& source, _In_ const wstring& destination) +{ + HRESULT hr = S_OK; + + // Create the corresponding directory in the destination + if (!::CreateDirectory(destination.c_str(), NULL)) + { + DWORD error = GetLastError(); + if (error != ERROR_ALREADY_EXISTS) + { + wcout << L"CreateDirectory(" << destination << L") failed with error " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(error); + } + } + + if (SUCCEEDED(hr)) + { + // Backup the directory + wstring directoryBackupPath = destination; + directoryBackupPath.append(L"\\"); + directoryBackupPath.append(DIRECTORY_BACKUP_FILE); + + hr = BackupFile(source, directoryBackupPath); + } + + return hr; +} + +void BackupDirectoryTree(_In_ const wstring& source, _In_ const wstring& destination) +{ + // Backup the directory + HRESULT hr = BackupDirectory(source, destination); + if (FAILED(hr)) + { + return; + } + + // Walk through all the files and subdirectories + WIN32_FIND_DATA findData; + wstring pattern = source; + pattern += L"\\*"; + HANDLE hFind = FindFirstFile(pattern.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + // If not . or .. + if (findData.cFileName[0] != '.') + { + wstring newSource = source; + newSource += '\\'; + newSource += findData.cFileName; + wstring newDestination = destination; + newDestination += '\\'; + newDestination += findData.cFileName; + // Backup the source file or directory + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + // NOTE: This code is using recursion for simplicity, however a real backup application + // should avoid recursion since it will overflow the stack for a deep directory tree + BackupDirectoryTree(newSource, newDestination); + } + else + { + // Do BackupRead and backup the file + hr = BackupFile(newSource, newDestination); + if (FAILED(hr)) + { + // NOTE: This code ignores BackupFile errors, + // but a backup app might handle it differently + wcout << L"BackupFile failed, hr = 0x" << hex << hr << endl; + } + } + } + } while (FindNextFile(hFind, &findData)); + + FindClose(hFind); + } +} + +HRESULT VolumeHasDedupMetadata(_In_ const wstring& volumeGuidName, _Out_ bool& hasDedupMetadata, _Out_ wstring& chunkStoreId) +{ + chunkStoreId.clear(); + hasDedupMetadata = false; + + HRESULT hr = GetDedupChunkStoreId(volumeGuidName, chunkStoreId); + + if (SUCCEEDED(hr) && !chunkStoreId.empty()) + { + hasDedupMetadata = true; + } + + return hr; +} + +void WriteBackupMetadata(_In_ const wstring& source, _In_ const wstring& destination) +{ + wstring volumeGuidName; + wstring chunkStoreId; + + HRESULT hr = GetVolumeGuidNameForPath(source, volumeGuidName); + + // Get the deduplication chunk store ID + if (SUCCEEDED(hr)) + { + hr = GetDedupChunkStoreId(volumeGuidName.c_str(), chunkStoreId); + } + + // Write the store ID and backup timestamp to the backup metadata file + if (SUCCEEDED(hr) && !chunkStoreId.empty()) + { + wstring filePath = destination; + filePath.append(L"\\"); + filePath.append(BACKUP_METADATA_FILE_NAME); + + FILE* metadataFile = NULL; + errno_t err = _wfopen_s(&metadataFile, filePath.c_str(), L"w"); + if (err != 0) + { + wcout << L"Unable to create backup metadata file: " << filePath << endl; + } + else + { + // A real backup application would use the VSS snapshot timestamp + FILETIME ftNow = {}; + GetSystemTimeAsFileTime(&ftNow); + + // Convert time to wbem time string + WBEMTime backupTime(ftNow); + bstr_t bstrTime = backupTime.GetDMTF(); + + _ftprintf(metadataFile, BACKUP_METADATA_FORMAT, chunkStoreId.c_str(), (WCHAR*)bstrTime); + fclose(metadataFile); + } + } +} + +HRESULT ReadBackupMetadata(_In_ const wstring& source, _Out_ wstring& chunkStoreId, _Out_ wstring& backupTime) +{ + HRESULT hr = S_OK; + wstring filePath = source; + + backupTime.clear(); + chunkStoreId.clear(); + + filePath.append(L"\\"); + filePath.append(BACKUP_METADATA_FILE_NAME); + + FILE* metadataFile = NULL; + errno_t err = _wfopen_s(&metadataFile, filePath.c_str(), L"r"); + if (err != 0) + { + wcout << L"Unable to open backup metadata file: " << filePath << endl; + hr = E_FAIL; + } + else + { + WCHAR storeId[] = L"{00000000-0000-0000-0000-000000000000}"; + WCHAR timestamp[] = L"yyyymmddhhmmss.nnnnnn-ggg"; + + int converted = fwscanf_s(metadataFile, BACKUP_METADATA_FORMAT, storeId, ARRAY_LEN(storeId), timestamp, ARRAY_LEN(timestamp)); + if (converted != 2) + { + wcout << L"Unable to read chunk store ID and backup time from backup metadata file: " << filePath << endl; + } + else + { + chunkStoreId = storeId; + backupTime = timestamp; + } + fclose(metadataFile); + } + + return hr; +} + +///////////////////////////////////////////////////////////////////// +// +// Restore related methods +// +///////////////////////////////////////////////////////////////////// + +HRESULT RestoreFile(_In_ const wstring& source, _In_ const wstring& destination, _In_opt_ bool overWriteExisting) +{ + // Create destination dir if it doesn't exist + size_t lastSeparator = destination.rfind('\\'); + if (lastSeparator == wstring::npos) + { + wcout << L"destination is not a file path" << endl; + return E_UNEXPECTED; + } + wstring destinationLocation = destination.substr(0, lastSeparator); + ::CreateDirectory(destinationLocation.c_str(), NULL); + + // Open the backup medium + // In this example the medium is another file, but it could be tape, network server, etc... + HANDLE hSourceFile = ::CreateFile( + source.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (hSourceFile == INVALID_HANDLE_VALUE) + { + wcout << L"CreateFile(" << source << L") failed with error " << GetLastError() << endl; + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Open the file to be restored + HANDLE hDestinationFile = ::CreateFile( + destination.c_str(), + GENERIC_WRITE | WRITE_OWNER | WRITE_DAC, + FILE_SHARE_READ, + NULL, + overWriteExisting ? OPEN_EXISTING : CREATE_ALWAYS, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (hDestinationFile == INVALID_HANDLE_VALUE) + { + wcout << L"CreateFile(" << destination << L") failed with error " << GetLastError() << endl; + return HRESULT_FROM_WIN32(GetLastError()); + } + + const DWORD DEFAULT_BUFFER_SIZE = 4086; + DWORD bytesRead, bytesWritten; + BYTE buffer[DEFAULT_BUFFER_SIZE]; + LPVOID context = NULL; + HRESULT hr = S_OK; + + // Read 4k at a time from the backup medium. BackupRead will return attributes, security, and reparse point information + while (ReadFile(hSourceFile, buffer, DEFAULT_BUFFER_SIZE, &bytesRead, NULL) && bytesRead > 0) + { + // Call BackupWrite to restore the file, including security, attributes and reparse point + if (!BackupWrite(hDestinationFile, buffer, bytesRead, &bytesWritten, FALSE, TRUE, &context)) + { + wcout << L"BackupWrite(" << destination << L") failed with error " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(GetLastError()); + break; + } + + if (bytesRead != bytesWritten) + { + wcout << L"BackupWrite(" << destination << L") unexpectedly wrote less bytes than expected (expected:" << bytesRead << L" written:" << bytesWritten << L")" << endl; + hr = E_UNEXPECTED; + break; + } + } + + // Call BackupWrite one more time to clean up the context + BackupWrite(hDestinationFile, NULL, 0, NULL, TRUE, TRUE, &context); + + // Close the backup medium + CloseHandle(hSourceFile); + + // Close the destination file + CloseHandle(hDestinationFile); + + return hr; +} + +HRESULT RestoreDirectory(_In_ const wstring& source, _In_ const wstring& destination) +{ + HRESULT hr = S_OK; + + wstring directorySourcePath = source; + directorySourcePath.append(L"\\"); + directorySourcePath.append(DIRECTORY_BACKUP_FILE); + + // Create the corresponding directory in the destination, if not already present + if (!::CreateDirectory(destination.c_str(), NULL)) + { + DWORD error = GetLastError(); + // Access denied error can occur for volume root directory + // The sample code also exempts access denied error for all other directories + // A real backup application may handle this condition differently + if (error != ERROR_ALREADY_EXISTS && error != ERROR_ACCESS_DENIED) + { + wcout << L"CreateDirectory(" << destination << L") failed with error " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(error); + } + } + + if (SUCCEEDED(hr)) + { + // Restore the directory + RestoreFile(directorySourcePath, destination, true); + } + + return hr; +} + + +HRESULT DeleteDirectoryTree(_In_ const wstring& directory) +{ + HRESULT hr = S_OK; + + // Walk through all the files and subdirectories + WIN32_FIND_DATA findData; + wstring pattern = directory; + pattern += L"\\*"; + HANDLE hFind = FindFirstFile(pattern.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + // If not . or .. + if (findData.cFileName[0] != '.') + { + wstring newPath = directory; + newPath += '\\'; + newPath += findData.cFileName; + + // Backup the source file or directory + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + // NOTE: This code is using recursion for simplicity, however a real backup application + // should avoid recursion since it will overflow the stack for a deep directory tree + hr = DeleteDirectoryTree(newPath); + if (FAILED(hr)) + { + break; + } + + // NOTE: This code is ignoring directory deletion failures since the same tree will be restored anyway. + // real backup applications migh choose to handle this differently. + RemoveDirectory(newPath.c_str()); + } + else + { + // Do BackupRead and backup the file + BOOL result = DeleteFile(newPath.c_str()); + if (!result) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + wcout << L"DeleteFile failed, hr = 0x" << hex << hr << endl; + break; + } + } + } + } while (FindNextFile(hFind, &findData)); + + FindClose(hFind); + } + + return hr; +} + +HRESULT RestoreDirectoryTree(_In_ const wstring& source, _In_ const wstring& destination, _In_ const vector& sourceExcludePaths, _Out_opt_ vector* pRestoredFiles) +{ + HRESULT hr = S_OK; + + if (pRestoredFiles != NULL) + { + pRestoredFiles->clear(); + } + + // Check for exclusion + for (size_t index = 0; index < sourceExcludePaths.size(); index++) + { + wstring excludePath = sourceExcludePaths[index]; + if (wcscmp(source.c_str(), excludePath.c_str()) == 0) + { + return hr = S_FALSE; + } + } + + // Restore the directory + hr = RestoreDirectory(source, destination); + if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) && hr != HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) + { + return hr; + } + hr = S_OK; + + wstring trimmedSource = TrimTrailingSeparator(source, L'\\'); + + // Walk through all the files and subdirectories + WIN32_FIND_DATA findData; + wstring pattern = trimmedSource; + pattern += L"\\*"; + HANDLE hFind = FindFirstFile(pattern.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + // If not . or .. + if (findData.cFileName[0] != '.') + { + wstring newSource = trimmedSource; + newSource += '\\'; + newSource += findData.cFileName; + wstring newDestination = destination; + newDestination += '\\'; + newDestination += findData.cFileName; + // Restore the file or directory + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + + // NOTE: This code is using recursion for simplicity, however a real backup application + // should avoid recursion since it will overflow the stack for a deep directory tree + hr = RestoreDirectoryTree(newSource, newDestination, sourceExcludePaths, pRestoredFiles); + if (FAILED(hr)) + { + break; + } + } + else if ((_wcsicmp(findData.cFileName, DIRECTORY_BACKUP_FILE) == 0) || + (_wcsicmp(findData.cFileName, BACKUP_METADATA_FILE_NAME) == 0)) + { + // This file is backup metadata, not original volume data + continue; + } + else + { + // Restore the file + hr = RestoreFile(newSource, newDestination); + if (FAILED(hr)) + { + if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION)) + { + // Some files may be in busy, protected by a filter, etc. + // An online restore may not be able to replace every file + wcout << L"Warning: continuing restore after RestoreFile failed, hr = 0x" << hex << hr << endl; + hr = S_OK; + } + else + { + wcout << L"RestoreFile failed, hr = 0x" << hex << hr << endl; + break; + } + } + if (pRestoredFiles) + { + pRestoredFiles->push_back(newDestination); + } + } + } + } while (FindNextFile(hFind, &findData)); + + FindClose(hFind); + } + + return hr; +} + +///////////////////////////////////////////////////////////////////// +// +// WMI utilities +// +///////////////////////////////////////////////////////////////////// + +HRESULT WmiGetWbemServices(_In_ PCWSTR wmiNamespace, _Out_ CComPtr& spWmi) +{ + CComPtr spLocator = NULL; + + bstr_t bstrNamespace = wmiNamespace; + + HRESULT hr = CoCreateInstance( + CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, + (void**) &spLocator + ); + if (FAILED(hr)) + { + wcout << L"CoCreateInstance(IWbemLocator) failed, hr = 0x" << hex << hr << endl; + } + + if (SUCCEEDED(hr)) + { + hr = spLocator->ConnectServer( + bstrNamespace, + NULL, + NULL, + NULL, + 0L, + NULL, + NULL, + &spWmi + ); + if (FAILED(hr)) + { + wcout << L"unable to connect to WMI; namespace " << CIM_DEDUP_NAMESPACE << L", hr = 0x" << hex << hr << endl; + } + } + + if (SUCCEEDED(hr)) + { + hr = CoSetProxyBlanket( + spWmi, + RPC_C_AUTHN_WINNT, + RPC_C_AUTHZ_NONE, + NULL, + RPC_C_AUTHN_LEVEL_PKT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, + EOAC_NONE + ); + + if (FAILED(hr)) + { + wcout << L"CoSetProxyBlanket failed, hr = 0x" << hex << hr << endl; + } + } + + return hr; +} + +HRESULT WmiGetMethodInputParams(_In_ IWbemServices* pWmi, _In_ PCWSTR className, _In_ PCWSTR methodName, _Out_ CComPtr& spInParams) +{ + CComPtr spClass; + + spInParams = NULL; + + HRESULT hr = pWmi->GetObject(bstr_t(className), 0, NULL, &spClass, NULL); + if (FAILED(hr)) + { + wcout << L"WMI query for class " << className << L" failed with error 0x" << hex << hr << endl; + } + + CComPtr spInParamsDefinition; + if (SUCCEEDED(hr)) + { + hr = spClass->GetMethod(methodName, 0, &spInParamsDefinition, NULL); + if (FAILED(hr)) + { + wcout << L"WMI query for method " << className << L"." << (PCWSTR)methodName << L" failed with error 0x" << hex << hr << endl; + } + + // GetMethod returns NULL for method that takes no input parameters. + } + + if (SUCCEEDED(hr) && (spInParamsDefinition != NULL)) + { + hr = spInParamsDefinition->SpawnInstance(0, &spInParams); + if (FAILED(hr)) + { + wcout << L"WMI input parameter creation for method " << className << L"." << (PCWSTR)methodName << L" failed with error 0x" << hex << hr << endl; + } + } + else if (spInParamsDefinition == NULL) + { + hr = S_FALSE; + } + + return hr; +} + +HRESULT WmiAddVolumeInputParameter(_Inout_ IWbemClassObject* pParams, _In_ PCWSTR className, _In_ PCWSTR methodName, _In_ const wstring& volume) +{ + HRESULT hr = S_OK; + SAFEARRAY* psa = NULL; + SAFEARRAYBOUND saBound = {}; + saBound.lLbound = 0; + saBound.cElements = 1; + + psa = SafeArrayCreate(VT_BSTR, 1, &saBound); + if (psa == NULL) + { + wcout << L"Out of memory creating safe-array" << endl; + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + + long index = 0; + hr = SafeArrayPutElement(psa, &index, (BSTR)bstr_t(volume.c_str())); + if (FAILED(hr)) + { + wcout << L"SafeArrayPutElement(0, " << volume << L") failed with error 0x" << hex << hr << endl; + } + } + + VARIANT volumeArray; + VariantInit(&volumeArray); + volumeArray.vt = VT_ARRAY | VT_BSTR; + volumeArray.parray = psa; + + if (SUCCEEDED(hr)) + { + hr = pParams->Put(bstr_t(CIM_DEDUP_PROP_VOLUME), 0, &volumeArray, 0); + if (FAILED(hr)) + { + wcout << L"Setting property " << className << L"." << methodName << L"." << CIM_DEDUP_PROP_VOLUME << L" failed with error 0x" << hex << hr << endl; + } + } + + if (psa != NULL) + { + SafeArrayDestroy(psa); + } + + return hr; +} + +HRESULT WmiAddInputParameter(_Inout_ IWbemClassObject* pParams, _In_ PCWSTR className, _In_ PCWSTR methodName, _In_ PCWSTR propertyName, _In_ variant_t& var) +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = pParams->Put(bstr_t(propertyName), 0, &var, 0); + if (FAILED(hr)) + { + wcout << L"Setting property " << className << L"." << methodName << L"." << propertyName << L" failed with error 0x" << hex << hr << endl; + } + } + + return hr; +} + +HRESULT WmiGetErrorInfo(_Out_ HRESULT& hrOperation, _Out_ wstring& errorMessageOperation) +{ + CComPtr spErrorInfo; + CComPtr spWmiError; + + HRESULT hr = GetErrorInfo(0, &spErrorInfo); + if (FAILED(hr)) + { + wcout << L"GetErrorInfo failed with error 0x" << hex << hr << endl; + } + + if (SUCCEEDED(hr)) + { + hr = spErrorInfo->QueryInterface(&spWmiError); + if (FAILED(hr)) + { + wcout << L"IErrorInfo::QueryInterface failed with error 0x" << hex << hr << endl; + } + } + + if (SUCCEEDED(hr)) + { + variant_t var; + + // Get the value of the ErrorCode property + hr = spWmiError->Get(CIM_DEDUP_PROP_ERRORCODE, 0, &var, 0, 0); + if (FAILED(hr)) + { + wcout << L"IWbemClassObject::Get for property " << CIM_DEDUP_PROP_ERRORCODE << L" failed with error 0x" << hex << hr << endl; + } + else + { + // This is the root cause error + hrOperation = var.ulVal; + + // Get the error message + hr = spWmiError->Get(CIM_DEDUP_PROP_ERRORMESSAGE, 0, &var, 0, 0); + if (FAILED(hr)) + { + wcout << L"IWbemClassObject::Get for property " << CIM_DEDUP_PROP_ERRORMESSAGE << L" failed with error 0x" << hex << hr << endl; + } + else + { + errorMessageOperation = var.bstrVal; + } + } + } + + return hr; +} + +HRESULT WmiExecuteMethod(_In_ IWbemServices* pWmi, _In_ PCWSTR className, _In_ PCWSTR methodName, _In_opt_ IWbemClassObject* pInParams, + _Out_ CComPtr& spOutParams, _In_opt_ PCWSTR context) +{ + // Make the method call + HRESULT hr = pWmi->ExecMethod(bstr_t(className), bstr_t(methodName), 0, NULL, pInParams, &spOutParams, NULL); + + // Evaluate the output parameter object + if (SUCCEEDED(hr)) + { + variant_t var; + hr = spOutParams->Get(bstr_t(CIM_DEDUP_PROP_RETURNVALUE), 0, &var, NULL, 0); + if (FAILED(hr)) + { + wcout << L"Get method return value for " << className << L"." << methodName << L"(" << context << L")" << L" failed with error 0x" << hex << hr << endl; + } + + if (SUCCEEDED(hr) && FAILED(var.ulVal)) + { + hr = var.ulVal; + wcout << L"WMI method " << className << L"." << methodName << L"(" << context << L")" << L" failed with error 0x" << hex << hr << endl; + } + } + else + { + // Get the root cause error + HRESULT hrLocal = S_OK; + HRESULT hrOperation = S_OK; + wstring errorMessage; + + hrLocal = WmiGetErrorInfo(hrOperation, errorMessage); + + if (SUCCEEDED(hrLocal) && FAILED(hrOperation)) + { + hr = hrOperation; + wcout << L"WMI method execution " << className << L"." << methodName << L"(" << context << L")" << L" failed with error 0x" << hex << hr << endl; + wcout << L" Error message: " << errorMessage << endl; + } + } + + return hr; +} + +HRESULT WmiGetDedupInstanceByVolumeId(PCWSTR className, _In_ const wstring& volumeGuidName, _Out_ CComPtr& instance) +{ + CComPtr spWmi; + CComPtr spInstance; + + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + if (SUCCEEDED(hr)) + { + wstring objectPath = className; + objectPath.append(L".VolumeId='"); + objectPath.append(volumeGuidName); + objectPath.append(L"'"); + + // Get the specified object + hr = spWmi->GetObject( + bstr_t(objectPath.c_str()), + WBEM_FLAG_RETURN_WBEM_COMPLETE, + NULL, // context + &spInstance, + NULL // synchronous call; not needed + ); + + if (FAILED(hr)) + { + // Get the root cause error + HRESULT hrLocal = S_OK; + HRESULT hrOperation = S_OK; + wstring errorMessage; + + hrLocal = WmiGetErrorInfo(hrOperation, errorMessage); + + if (SUCCEEDED(hrLocal) && FAILED(hrOperation)) + { + if (hrOperation == DDP_E_NOT_FOUND || hrOperation == DDP_E_PATH_NOT_FOUND || hrOperation == DDP_E_VOLUME_DEDUP_DISABLED) + { + // The object is not found + hr = S_FALSE; + } + else + { + hr = hrOperation; + wcout << L"WMI query for " << objectPath << L" failed with error 0x" << hex << hr << endl; + wcout << L" Error message: " << errorMessage << endl; + } + } + } + } + + if (SUCCEEDED(hr)) + { + instance = spInstance; + } + + return hr; +} + +HRESULT WmiQueryDedupInstancesByVolumeId(_In_ IWbemServices* pWmi, _In_ const wstring& className, _In_ const wstring& volumeGuidName, _Out_ CComPtr& instances) +{ + CComPtr spWmi; + + HRESULT hr = WmiGetWbemServices(CIM_DEDUP_NAMESPACE, spWmi); + + // Backslash chars need to be escaped in WMI queries + wstring quotedVolumeGuidName = volumeGuidName; + StringReplace(quotedVolumeGuidName, L"\\", L"\\\\"); + + wstring query = L"select * from "; + query.append(className); + query.append(L" where VolumeId='"); + query.append(quotedVolumeGuidName); + query.append(L"'"); + + hr = pWmi->ExecQuery( + bstr_t("WQL"), + bstr_t(query.c_str()), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, + &instances + ); + + if (FAILED(hr)) + { + wcout << L"WMI query failed with error 0x" << hex << hr << L", query: " << query << endl; + } + + return hr; +} + + +///////////////////////////////////////////////////////////////////// +// +// Common utilities +// +///////////////////////////////////////////////////////////////////// + + +void StringReplace(_Inout_ wstring& stringValue, _In_ const wstring& matchValue, _In_ const wstring& replaceValue) +{ + if (!stringValue.empty()) + { + if (matchValue.compare(replaceValue) != 0) + { + wstring::size_type pos = stringValue.find(matchValue, 0); + + while (pos != wstring::npos) + { + + stringValue.replace( + pos, + matchValue.length(), + replaceValue); + + pos = stringValue.find( + matchValue, + pos + replaceValue.length() + ); + } + } + else + { + // If the two values are the same, we don't need to replace anything + } + } +} + +wstring TrimTrailingSeparator(_In_ const wstring& str, _In_ WCHAR separator) +{ + wstring returnString = str; + + std::wstring::size_type pos = returnString.find_last_not_of(separator); + + if (pos != std::wstring::npos) + { + ++pos; + } + else + { + pos = 0; + } + + if (pos < returnString.length()) + { + returnString.erase(pos); + } + + return returnString; +} + +bool IsRootPath(_In_ const wstring& path) +{ + + WCHAR volumePath[MAX_PATH]; + bool isRootPath = false; + + if (GetVolumePathName(path.c_str(), volumePath, MAX_PATH)) + { + // For volume root, input length will equal output length (ignoring + // trailing backslash if any) + + size_t cchPath = wcslen(path.c_str()); + size_t cchRoot = wcslen(volumePath); + + if (volumePath[cchRoot - 1] == L'\\') + cchRoot--; + if (path.c_str()[cchPath - 1] == L'\\') + cchPath--; + + if (cchPath == cchRoot) + { + isRootPath = true; + } + } + + return isRootPath; +} + +void PrintUsage(_In_ LPCWSTR programName) +{ + wcout << L"BACKUP" << endl; + wcout << L"Backup a directory to a destination directory:" << endl << + L"\t" << programName << L" -backup -destination " << endl << endl; + wcout << L"EXAMPLE: " << programName << L" -backup d:\\mydirectory -destination f:\\mydirectorybackup" << endl; + wcout << L"EXAMPLE: " << programName << L" -backup d:\\ -destination f:\\mydirectorybackup" << endl; + + wcout << endl << L"RESTORE" << endl; + wcout << L"Restore a backed up directory to a destination directory:" << endl << + L"\t" << programName << L" -restore -destination " << endl << endl; + wcout << L"EXAMPLE: " << programName << L" -restore f:\\mydirectorybackup -destination d:\\mydirectory" << endl; + + wcout << endl << L"SINGLE FILE RESTORE" << endl; + wcout << L"Restore the reparse point to the destination:" << endl << + L"\t" << programName << L" -restorestub -destination " << endl << endl; + wcout << L"Restore the data for the reparse point restored with the -restorestub option above:" << endl << + L"\t" << programName << L" -restoredata -destination " << endl << endl; + wcout << L"Restore the reparse point and data in one operation (-restorestub + -restoredata):" << endl << + L"\t" << programName << L" -restorefile -destination " << endl << endl; + wcout << L"EXAMPLE: " << programName << L" -restorefile f:\\mydirectorybackup\\myfile -destination d:\\temp\\myfile" << endl; + + wcout << endl << L"VOLUME RESTORE" << endl; + wcout << L"Restore the entire volume to the destination:" << endl << + L"\t" << programName << L" -restorevolume -destination " << endl << endl; + wcout << L"EXAMPLE: " << programName << L" -restorevolume f:\\mydirectorybackup -destination d:\\" << endl; +} + +bool ParseCommandLine(_In_ int argc, _In_reads_(argc) _TCHAR* argv[], _Out_ Action *action, _Out_ wstring* source, _Out_ wstring* destination) +{ + + if (action == NULL || source == NULL || destination == NULL) + { + return false; + } + + *action = BackupAction; + *source = L""; + *destination = L""; + + if (argc < 5) return false; + // argv[0] is the program name, skip it + + // argv[1] is the command, must be one of the following + wstring actionString = argv[1]; + if (actionString == L"-backup") + { + *action = BackupAction; + } + else if (actionString == L"-restorestub") + { + *action = RestoreStubAction; + } + else if (actionString == L"-restoredata") + { + *action = RestoreDataAction; + } + else if (actionString == L"-restorefile") + { + *action = RestoreFileAction; + } + else if (actionString == L"-restorevolume") + { + *action = RestoreVolumeAction; + } + else if (actionString == L"-restore") + { + *action = RestoreFilesAction; + } + else + { + return false; + } + + // argv[2] is the source + *source = argv[2]; + // argv[4] is the destination + *destination = argv[4]; + + // argv[3] is always "-destination", check it for completeness + wstring arg3 = argv[3]; + if (arg3 != L"-destination") return false; + + return true; +} + +HRESULT ModifyPrivilege(_In_ LPCTSTR szPrivilege, _In_ BOOL fEnable) +{ + HRESULT hr = S_OK; + TOKEN_PRIVILEGES NewState = {}; + LUID luid = {}; + HANDLE hToken = NULL; + + // Open the process token for this process. + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken )) + { + wcout << L"Failed OpenProcessToken" << endl; + return ERROR_FUNCTION_FAILED; + } + + // Get the local unique ID for the privilege. + if ( !LookupPrivilegeValue( NULL, + szPrivilege, + &luid )) + { + CloseHandle( hToken ); + wcout << L"Failed LookupPrivilegeValue" << endl; + return ERROR_FUNCTION_FAILED; + } + + // Assign values to the TOKEN_PRIVILEGE structure. + NewState.PrivilegeCount = 1; + NewState.Privileges[0].Luid = luid; + NewState.Privileges[0].Attributes = + (fEnable ? SE_PRIVILEGE_ENABLED : 0); + + // Adjust the token privilege. + if (!AdjustTokenPrivileges(hToken, + FALSE, + &NewState, + 0, + NULL, + NULL)) + { + wcout << L"Failed AdjustTokenPrivileges" << endl; + hr = ERROR_FUNCTION_FAILED; + } + + // Close the handle. + CloseHandle(hToken); + + return hr; +} + +HRESULT GetVolumeGuidNameForPath(_In_ const wstring& path, _Out_ wstring& volumeGuidName) +{ + HRESULT hr = S_OK; + + WCHAR volumePathName[MAX_PATH]; + BOOL result = GetVolumePathName(path.c_str(), volumePathName, MAX_PATH); + if (!result) + { + wcout << L"GetVolumePathName(" << path << L") failed with error " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + WCHAR tempVolumeGuidName[MAX_PATH]; + result = GetVolumeNameForVolumeMountPoint(volumePathName, tempVolumeGuidName, MAX_PATH); + if (!result) + { + wcout << L"GetVolumeNameForVolumePathName(" << volumePathName << L") failed with error " << GetLastError() << endl; + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + volumeGuidName = tempVolumeGuidName; + } + + return hr; +} + +// Required by RPC +_Must_inspect_result_ +_Ret_maybenull_ _Post_writable_byte_size_(size) +void * __RPC_USER MIDL_user_allocate(size_t size) +{ + return LocalAlloc(0, size); +} + +HRESULT +GetFileSize( + __in const std::wstring& FilePath, + __out LARGE_INTEGER& FileSize + ) +{ + HRESULT hr = S_OK; + + HANDLE fileHandle = + ::CreateFile( + FilePath.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if (fileHandle == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_WIN32(::GetLastError()); + + wcout << L"CreateFile(%s" << FilePath << L") failed with error " << GetLastError() << endl; + } + else + { + if (!::GetFileSizeEx(fileHandle, &FileSize)) + { + hr = HRESULT_FROM_WIN32(::GetLastError()); + + wcout << L"GetFileSizeEx(%s" << FilePath << L") failed with error " << GetLastError() << endl; + } + } + + return hr; +} + + + diff --git a/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.sln b/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.sln new file mode 100644 index 00000000..93258ed7 --- /dev/null +++ b/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DedupBackupRestore", "DedupBackupRestore.vcxproj", "{C76A93CD-2D09-4776-9D43-8FE51D5F143B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|x64 = Release|x64 + Debug|x64 = Debug|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C76A93CD-2D09-4776-9D43-8FE51D5F143B}.Release|x64.ActiveCfg = Release|x64 + {C76A93CD-2D09-4776-9D43-8FE51D5F143B}.Release|x64.Build.0 = Release|x64 + {C76A93CD-2D09-4776-9D43-8FE51D5F143B}.Debug|x64.ActiveCfg = Debug|x64 + {C76A93CD-2D09-4776-9D43-8FE51D5F143B}.Debug|x64.Build.0 = Debug|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.vcxproj b/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.vcxproj new file mode 100644 index 00000000..5e894043 --- /dev/null +++ b/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.vcxproj @@ -0,0 +1,92 @@ + + + + + Release + x64 + + + Debug + x64 + + + + {C76A93CD-2D09-4776-9D43-8FE51D5F143B} + x64Proj + DedupBackupRestore + + + + Application + false + true + Unicode + V110 + + + Application + true + Unicode + V110 + + + + + + + + + + + + + false + + + true + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + false + + + Console + true + true + true + comsupp.lib;wbemuuid.lib;framedyn.lib;wevtapi.lib;ole32.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + false + + + Console + true + comsupp.lib;wbemuuid.lib;framedyn.lib;wevtapi.lib;ole32.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/Samples/DesktopAutomationDismiss/README.md b/Samples/DesktopAutomationDismiss/README.md new file mode 100644 index 00000000..67206ac6 --- /dev/null +++ b/Samples/DesktopAutomationDismiss/README.md @@ -0,0 +1,59 @@ +Desktop Automation sample +========================= + +Automating desktop applications may require programmatic dismissal of the Start menu. This sample shows how to create a program that can be used as part of automation to dismiss the Start menu and apps. This binary should be run only for automated testing, and should be run prior to starting an automation run. + +**Note** This sample requires Microsoft Visual Studio Ultimate 2013 or later to build. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[Using MakeCert](http://msdn.microsoft.com/en-us/library/windows/desktop/aa388165) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +These steps are meant only for test machines running UI automation. It will require the creation of a self-signed root certificate. + +1. Make sure that the UIAccess is requested in the application manifest. The sample already has this set, and can be changed under **Solution Explorer -\> Properties -\> Linker -\> Manifest Tool -\> UAC Bypass UI Protection**. +2. Create a self-signed root authority certificate and export the private key. Use the MakeCert tool to do this. For example, the following command creates a self-signed certificate with a subject name of "CN=TempCA": **makecert -n "CN=TempCA" -r -sv TempCA.pvk TempCA.cer** You will be prompted to provide a password to protect the private key. This password is required when creating a certificate signed by this root certificate. It's important to keep this PVK in a safe place! Binaries signed with this certificate can circumvent a number of security restrictions. +3. Add the self-signed certificate to the trusted root store on the machines running automation. CertUtil can be used to do this. For example, run this command with administrator privileges: **certutil -addstore root TempCA.cer** +4. Create a certificate signed by the self-signed root authority certificate. Again, use the MakeCert tool. For example, the following command creates a certificate signed by the TempCA root authority certificate with a subject name of "CN=SignedByCA" using the private key of the issuer: **makecert -sk SignedByCA -iv TempCA.pvk -n "CN=SignedByCA" -ic TempCA.cer SignedByCA.cer -sr currentuser -ss MyCertStore** +5. Sign the created binary(in this example, DesktopAutomation.exe). SignTool can do this. For example, the following command signs **DesktopAutomation.exe**: **signtool sign /f SignedByCA.cer DesktopAutomation.exe** +6. Install the binary to the Program Files or Windows directory. + +Run the sample +-------------- + +Troubleshooting +--------------- + +Q: The sample fails with error code 5 (**ERROR\_ACCESS\_DENIED**) + +A: The sample is failing to get UIAccess privileges. + +- Make sure the executable is placed in either the Program Files or Windows directory. +- Make sure that UIAccess=true is set in the application manifest (see step 1). +- If you have disabled UAC (LUA) via group policy, re-enable it. Set it to "Never Notify" mode if you must run your tests with UAC disabled. Set "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA = 1" to turn UAC on. Set "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ConsentPromptBehaviorAdmin = 0" to turn on "Never Notify" mode. + +Q: When running the sample, a dialog appears with "A referral was returned from the server". + +A: The executable is not signed with a certificate, or the certificate does not chain to a trusted root authority See steps 2-5 above under Building the Sample. + diff --git a/Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.sln b/Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.sln new file mode 100644 index 00000000..a327d6fe --- /dev/null +++ b/Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DesktopAutomation", "DesktopAutomation.vcxproj", "{0B8E6386-252A-4FAD-A84B-C72E68897C49}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = preSolution + {0B8E6386-252A-4FAD-A84B-C72E68897C49}.Debug|Win32.ActiveCfg = Debug|Win32 + {0B8E6386-252A-4FAD-A84B-C72E68897C49}.Debug|Win32.Build.0 = Debug|Win32 + {0B8E6386-252A-4FAD-A84B-C72E68897C49}.Release|Win32.ActiveCfg = Release|Win32 + {0B8E6386-252A-4FAD-A84B-C72E68897C49}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.vcxproj b/Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.vcxproj new file mode 100644 index 00000000..4b456a37 --- /dev/null +++ b/Samples/DesktopAutomationDismiss/cpp/DesktopAutomation.vcxproj @@ -0,0 +1,91 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + {0B8E6386-252A-4FAD-A84B-C72E68897C49} + Win32Proj + DesktopAutomation + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/DesktopAutomationDismiss/cpp/ShowDesktop.cpp b/Samples/DesktopAutomationDismiss/cpp/ShowDesktop.cpp new file mode 100644 index 00000000..e1197931 --- /dev/null +++ b/Samples/DesktopAutomationDismiss/cpp/ShowDesktop.cpp @@ -0,0 +1,373 @@ +// 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 + +//********************************************************************** +// +// IMPORTANT NOTE! +// For this program to have the privileges to dismiss the desktop, it +// must be signed and run from Program Files or Windows directory. +// +//********************************************************************** + +// Includes +#include +#include +#include +#include + +#include +#include + +// Defines +#define MAX_RETRIES 5 +#define VK_D 0x44 + +// Static variables +HANDLE g_hFile = nullptr; +BOOL g_fOutputToFile = FALSE; + +// Forward declarations and typedefs +typedef struct _ENUMDISPLAYDATA { + BOOL fAppVisible; + IAppVisibility *pAppVisible; +} ENUMDISPLAYDATA; + +void ShowDesktop(); +BOOL CALLBACK MonitorEnumProc (_In_ HMONITOR hMonitor, _In_ HDC, _In_ LPRECT, _In_ LPARAM dwData); +BOOL IsAppVisible(); +BOOL WaitForDesktop(); +BOOL HasUIAccess(); +BOOL OutputString(_In_z_ _Null_terminated_ WCHAR *pszFormatString, ...); + +//********************************************************************** +// +// Sends Win + D to toggle to the desktop +// +//********************************************************************** +void ShowDesktop() +{ + OutputString(L"Sending 'Win-D'\r\n"); + INPUT inputs[4]; + ZeroMemory(inputs, sizeof(inputs)); + + inputs[0].type = INPUT_KEYBOARD; + inputs[0].ki.wVk = VK_LWIN; + + inputs[1].type = INPUT_KEYBOARD; + inputs[1].ki.wVk = VK_D; + + inputs[2].type = INPUT_KEYBOARD; + inputs[2].ki.wVk = VK_D; + inputs[2].ki.dwFlags = KEYEVENTF_KEYUP; + + inputs[3].type = INPUT_KEYBOARD; + inputs[3].ki.wVk = VK_LWIN; + inputs[3].ki.dwFlags = KEYEVENTF_KEYUP; + + UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT)); + if (uSent != ARRAYSIZE(inputs)) + { + OutputString(L"SendInput failed: 0x%x\n", HRESULT_FROM_WIN32(GetLastError())); + } +} + +//********************************************************************** +// +// Callback for EnumWindows in IsAppVisible +// +//********************************************************************** + +BOOL CALLBACK MonitorEnumProc (_In_ HMONITOR hMonitor, _In_ HDC, _In_ LPRECT, _In_ LPARAM dwData) +{ + ENUMDISPLAYDATA *pData = reinterpret_cast(dwData); + MONITOR_APP_VISIBILITY monitorAppVisibility = MAV_UNKNOWN; + + HRESULT hr = pData->pAppVisible->GetAppVisibilityOnMonitor(hMonitor, &monitorAppVisibility); + if (SUCCEEDED(hr)) + { + OutputString(L"\tMonitor app visibility:\t\t"); + switch (monitorAppVisibility) + { + case MAV_UNKNOWN: + OutputString(L"UNKNOWN\r\n"); + break; + case MAV_NO_APP_VISIBLE: + OutputString(L"NO APP VISIBLE\r\n"); + break; + case MAV_APP_VISIBLE: + OutputString(L"APP VISIBLE\r\n"); + pData->fAppVisible = TRUE; + break; + default: + OutputString(L"UNDEFINED\r\n"); + break; + } + } + + return TRUE; +} + +//********************************************************************** +// +// Checks to see if any apps or the Start menu is visible +// +//********************************************************************** +BOOL IsAppVisible() +{ + OutputString(L"Checking for apps\r\n"); + BOOL fAppVisible = FALSE; + + ENUMDISPLAYDATA data = {0}; + + HRESULT hr = CoCreateInstance(CLSID_AppVisibility, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&data.pAppVisible)); + if (SUCCEEDED(hr)) + { + hr = data.pAppVisible->IsLauncherVisible(&fAppVisible); + if (SUCCEEDED(hr)) + { + OutputString(L"\tIsLauncherVisible:\t%s\r\n", fAppVisible ? L"TRUE" : L"FALSE"); + + if (!fAppVisible) + { + if (0 == EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, reinterpret_cast(&data))) + { + OutputString(L"EnumDisplayMonitors failed.\r\n"); + } + else + { + fAppVisible = data.fAppVisible; + } + } + } + + data.pAppVisible->Release(); + } + + if (FAILED(hr)) + { + OutputString(L"IsAppVisible failed: 0x%x\r\n", hr); + } + + OutputString(L"\tApps:\t\t%s\r\n", fAppVisible ? L"FOUND" : L"NOT FOUND"); + return fAppVisible; +} + +//********************************************************************* +// +// Waits for apps or Start menu to be dismissed +// Returns true if apps and Start menu are no longer visible +// +//********************************************************************* +BOOL WaitForDesktop() +{ + BOOL fAppVisible = IsAppVisible(); + + for (int i = 0; i < MAX_RETRIES && fAppVisible; i++) + { + Sleep(1000); + fAppVisible = IsAppVisible(); + } + + return !fAppVisible; +} + +//*********************************************************************** +// +// Checks UIAccess +// +//*********************************************************************** +BOOL HasUIAccess() +{ + BOOL fUIAccess = FALSE; + HANDLE hToken = nullptr; + + // Get process token in order to check for UIAccess + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + DWORD dwAccessInfo = 0; + DWORD dwInfoSize = 0; + + // Verify that the process has UIAccess + if (GetTokenInformation(hToken, TokenUIAccess, reinterpret_cast(&dwAccessInfo), sizeof(dwAccessInfo), &dwInfoSize)) + { + fUIAccess = (dwAccessInfo > 0); + } + else + { + OutputString(L"GetTokenInformation error:%d\n", GetLastError()); + } + + CloseHandle(hToken); + hToken = nullptr; + } + else + { + OutputString(L"Failed to open the token.\n"); + } + + return fUIAccess; +} + +//*********************************************************************** +// +// Outputs a string, either to a log file or to the console +// +//*********************************************************************** +BOOL OutputString(_In_z_ _Null_terminated_ WCHAR *pszFormatString, ...) +{ + BOOL fRetValue = TRUE; + + // Make the string for the variadic function + va_list args; + WCHAR szOutputBuffer[MAX_PATH] = {0}; + va_start(args, pszFormatString); + + int nCharWritten = _vsnwprintf_s(szOutputBuffer, ARRAYSIZE(szOutputBuffer), pszFormatString, args); + if (nCharWritten > 0) + { + // Output + if (g_fOutputToFile) + { + CHAR szMultibyteOut[MAX_PATH]; + int nBytesWritten = WideCharToMultiByte(CP_UTF8, 0, szOutputBuffer, nCharWritten, szMultibyteOut, sizeof(szMultibyteOut), nullptr, nullptr); + if (nBytesWritten == 0) + { + fRetValue = FALSE; + } + else + { + fRetValue = WriteFile(g_hFile, reinterpret_cast(szMultibyteOut), nBytesWritten, nullptr, nullptr); + } + } + else + { + wprintf(szOutputBuffer); + } + } + else + { + fRetValue = FALSE; + } + + return fRetValue; +} + +//*********************************************************************** +// +// ShowDesktop entry point +// +//*********************************************************************** +int __cdecl wmain(_In_ int argc, _In_reads_(argc) WCHAR *argv[], _In_reads_(argc) WCHAR *[]) +{ + int nResult = ERROR_SUCCESS; + + // Check input args for flags + BOOL fOverwrite = FALSE; + BOOL fIgnoreUIAccess = FALSE; + WCHAR *pszfileName = nullptr; + for (int i = 1; i < argc; i++) + { + // Flag to give help + if (_wcsicmp(argv[i], L"-?") == 0) + { + wprintf(L"Command line options:\n" + L"-o : Writes output to a the specified log file instead of the console\n" + L"-f: Forces the file specified in -o flag to be overwritten if the file exists\n" + L"-i: Ignores the return value of the check for UIAccess\n"); + } + + // Flag for force overwrite + if (_wcsicmp(argv[i], L"-f") == 0) + { + fOverwrite = TRUE; + } + + // Flag for output file path + if (_wcsicmp(argv[i - 1], L"-o") == 0) + { + pszfileName = argv[i]; + g_fOutputToFile = TRUE; + } + + // Flag to ignore the check for UIAccess + if (_wcsicmp(argv[i], L"-i") == 0) + { + fIgnoreUIAccess = TRUE; + } + } + + // Open the specified file for write + if (g_fOutputToFile && pszfileName != nullptr) + { + DWORD dwCreationDisposition = fOverwrite ? CREATE_ALWAYS: CREATE_NEW; + g_hFile = CreateFile(pszfileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr); + + if (g_hFile == INVALID_HANDLE_VALUE) + { + nResult = GetLastError(); + wprintf(L"Cannot write to the specified file, error: 0x%x\r\n", nResult); + } + } + + if (nResult == ERROR_SUCCESS) + { + HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(hr)) + { + if (fIgnoreUIAccess || HasUIAccess()) + { + if (fIgnoreUIAccess) + { + OutputString(L"Ignoring the check for UIAccess.\r\n"); + } + else + { + OutputString(L"UI automation access is allowed.\r\n"); + } + + if (IsAppVisible()) + { + ShowDesktop(); + + // Wait for the dismiss animation to complete and for the desktop to be visible. + Sleep(1000); + if (WaitForDesktop()) + { + nResult = ERROR_SUCCESS; + } + else + { + nResult = ERROR_CAN_NOT_COMPLETE; + } + } + else + { + // System is already in Desktop--no need to send Win + D + nResult = ERROR_SUCCESS; + } + } + else + { + OutputString(L"UI automation access is NOT allowed.\r\n"); + nResult = ERROR_ACCESS_DENIED; + } + + CoUninitialize(); + } + else + { + OutputString(L"CoInitializeEx failed: 0x%x\r\n", hr); + } + + if (g_hFile != nullptr) + { + CloseHandle(g_hFile); + } + } + + return nResult; +} \ No newline at end of file diff --git a/Samples/DesktopAutomationDismiss/cpp/readme.txt b/Samples/DesktopAutomationDismiss/cpp/readme.txt new file mode 100644 index 00000000..f7164c20 --- /dev/null +++ b/Samples/DesktopAutomationDismiss/cpp/readme.txt @@ -0,0 +1,55 @@ +Desktop Automation +============================= +Automating desktop applications may require an automated dismissal of the Start menu. This sample shows how to create +a program that can be used as part of automation to dismiss the Start menu and apps. This binary should +be run only for automated testing, and should be ran prior to starting an automation run. + +In order for this program to work, you must give it UIAccess privileges. See "Special build instructions" + +Special build instructions +============================= +These steps are meant only for test machines running UI automation. It will require the creation of a self-signed root + certificate + +1. Make sure that the UIAccess is requested in the application manifest. The sample already has this set, and can be + changed under Solution Explorer -> Properties -> Linker -> Manifest Tool -> UAC Bypass UI Protection. + +2. Create a self-signed root authority certificate and export the private key. Use the MakeCert tool to do this. + For example, the following command creates a self-signed certificate with a subject name of "CN=TempCA." + makecert -n "CN=TempCA" -r -sv TempCA.pvk TempCA.cer + + You will be prompted to provide a password to protect the private key. This password is required when creating a certificate + signed by this root certificate. + + It's important to keep this PVK in a safe place! Binaries signed with this certificate can circumvent a number + of security restrictions. + +3. Add the self-signed certificate to the trusted root store on the machines running automation. CertUtil can be used to do this. + For example, run this command with administrator privileges: + + certutil -addstore root TempCA.cer + +4. Create a certificate signed by the self-signed root authority certificate. Again, use the MakeCert tool. + For example, the following command creates a certificate signed by the TempCA root authority certificate with a + subject name of "CN=SignedByCA" using the private key of the issuer. + makecert -sk SignedByCA -iv TempCA.pvk -n "CN=SignedByCA" -ic TempCA.cer SignedByCA.cer -sr currentuser -ss My + +5. Sign the created binary(in this example, "DesktopAutomation.exe"). SignTool can do this. For example, the following command + signs "DesktopAutomation.exe" + signtool sign /f SignedByCA.cer DesktopAutomation.exe + +6. Install the binary to "Program Files" or "Windows" directories + +Troubleshooting +============================= +Q: The sample fails with error code 5 (ERROR_ACCESS_DENIED) +A: The sample is failing to get UIAccess privileges. + a. Make sure the executable is placed in Windows or Program Files directories + b. Make sure that UIAccess=true is set in the application manifest (see step 1) + c. If you have disabled UAC (LUA) via group policy, re-enable it. Set it to "Never Notify" mode if you must run your tests with UAC disabled. + i. Set HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA = 1 to turn UAC on + ii. Set HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ConsentPromptBehaviorAdmin = 0 to turn on "Never Notify" mode. + +Q: When running the sample, a dialog appears with A referral was returned from the server +A: The executable is not signed with a certificate, or the certificate does not chain to a trusted root authority + See steps 2-5 \ No newline at end of file diff --git a/Samples/DesktopToasts/README.md b/Samples/DesktopToasts/README.md new file mode 100644 index 00000000..99f87ff2 --- /dev/null +++ b/Samples/DesktopToasts/README.md @@ -0,0 +1,65 @@ +Sending toast notifications from desktop apps sample +==================================================== + +This sample demonstrates how a desktop app can display a toast notification and respond to events generated by the user's interaction (or lack of interaction) with the toast. + +The sample shows the metrics involved in the following scenarios: + +- Adding an item to a list +- Bringing a new page onto the screen + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[Quickstart: Sending a toast notification from the desktop](http://msdn.microsoft.com/en-us/library/windows/desktop/hh802768) + +[How to enable desktop toast notifications through an AppUserModelID](http://msdn.microsoft.com/en-us/library/windows/desktop/hh802762) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +**Important** This sample requires Visual Studio Professional 2012, Visual Studio 2013, or later versions of Visual Studio (any SKU) and won't compile in Microsoft Visual Studio Express 2013 for Windows. + +1. Start Visual Studio Professional 2012, Visual Studio 2013, or later versions of Visual Studio (any SKU) 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 F6 for Visual Studio 2013) or use **Build \> Build Solution** to build the sample. + +**For C\#**: Before you build this sample, you must download and install the [Windows API Code Pack for Microsoft .NET Framework](http://go.microsoft.com/fwlink/p/?linkid=160560). This provides a source code library that can be used to access some features of Windows 8.1, Windows 7, and Windows Vista from managed code. + +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**. + +How to use the sample +--------------------- + +In the sample window, click the **View Text Toast** button. A sample toast notification appears on the screen. + +As the user, there are three actions you can take: + +- Touch or click the toast. In a real-world app, this would commonly launch the associated app. +- Horizontally swipe the toast to dismiss it. +- Do nothing. The toast will time out. + +The action you take will be displayed in the sample window to demonstrate the receipt of the event. In a real-world situation, your app would respond appropriately to each of these events. + +Be aware that for a desktop app to be able to display toast notifications, that app must have a shortcut on the Start screen as this sample does. That shortcut must have an [AppUserModelID](http://msdn.microsoft.com/en-us/library/windows/desktop/dd378459). + diff --git a/Samples/DesktopToasts/cpp/DesktopToastsSample.cpp b/Samples/DesktopToasts/cpp/DesktopToastsSample.cpp new file mode 100644 index 00000000..fc9957c6 --- /dev/null +++ b/Samples/DesktopToasts/cpp/DesktopToastsSample.cpp @@ -0,0 +1,453 @@ +#include "stdafx.h" + +using namespace Microsoft::WRL; +using namespace ABI::Windows::UI::Notifications; +using namespace ABI::Windows::Data::Xml::Dom; +using namespace Windows::Foundation; + +// Main function +int WINAPI wWinMain(_In_ HINSTANCE /* hInstance */, _In_opt_ HINSTANCE /* hPrevInstance */, _In_ LPWSTR /* lpCmdLine */, _In_ int /* nCmdShow */) +{ + HRESULT hr = Initialize(RO_INIT_MULTITHREADED); + if (SUCCEEDED(hr)) + { + { + DesktopToastsApp app; + hr = app.Initialize(); + + if (SUCCEEDED(hr)) + { + app.RunMessageLoop(); + } + } + Uninitialize(); + } + + return SUCCEEDED(hr); +} + +DesktopToastsApp::DesktopToastsApp() : _hwnd(nullptr), _hEdit(nullptr) +{ +} + +DesktopToastsApp::~DesktopToastsApp() +{ +} + +// In order to display toasts, a desktop application must have a shortcut on the Start menu. +// Also, an AppUserModelID must be set on that shortcut. +// The shortcut should be created as part of the installer. The following code shows how to create +// a shortcut and assign an AppUserModelID using Windows APIs. You must download and include the +// Windows API Code Pack for Microsoft .NET Framework for this code to function +// +// Included in this project is a wxs file that be used with the WiX toolkit +// to make an installer that creates the necessary shortcut. One or the other should be used. + +HRESULT DesktopToastsApp::TryCreateShortcut() +{ + wchar_t shortcutPath[MAX_PATH]; + DWORD charWritten = GetEnvironmentVariable(L"APPDATA", shortcutPath, MAX_PATH); + HRESULT hr = charWritten > 0 ? S_OK : E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + errno_t concatError = wcscat_s(shortcutPath, ARRAYSIZE(shortcutPath), L"\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop Toasts App.lnk"); + hr = concatError == 0 ? S_OK : E_INVALIDARG; + if (SUCCEEDED(hr)) + { + DWORD attributes = GetFileAttributes(shortcutPath); + bool fileExists = attributes < 0xFFFFFFF; + + if (!fileExists) + { + hr = InstallShortcut(shortcutPath); + } + else + { + hr = S_FALSE; + } + } + } + return hr; +} + +// Install the shortcut +HRESULT DesktopToastsApp::InstallShortcut(_In_z_ wchar_t *shortcutPath) +{ + wchar_t exePath[MAX_PATH]; + + DWORD charWritten = GetModuleFileNameEx(GetCurrentProcess(), nullptr, exePath, ARRAYSIZE(exePath)); + + HRESULT hr = charWritten > 0 ? S_OK : E_FAIL; + + if (SUCCEEDED(hr)) + { + ComPtr shellLink; + hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); + + if (SUCCEEDED(hr)) + { + hr = shellLink->SetPath(exePath); + if (SUCCEEDED(hr)) + { + hr = shellLink->SetArguments(L""); + if (SUCCEEDED(hr)) + { + ComPtr propertyStore; + + hr = shellLink.As(&propertyStore); + if (SUCCEEDED(hr)) + { + PROPVARIANT appIdPropVar; + hr = InitPropVariantFromString(AppId, &appIdPropVar); + if (SUCCEEDED(hr)) + { + hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar); + if (SUCCEEDED(hr)) + { + hr = propertyStore->Commit(); + if (SUCCEEDED(hr)) + { + ComPtr persistFile; + hr = shellLink.As(&persistFile); + if (SUCCEEDED(hr)) + { + hr = persistFile->Save(shortcutPath, TRUE); + } + } + } + PropVariantClear(&appIdPropVar); + } + } + } + } + } + } + return hr; +} + +// Prepare the main window +HRESULT DesktopToastsApp::Initialize() +{ + HRESULT hr = TryCreateShortcut(); + if (SUCCEEDED(hr)) + { + WNDCLASSEX wcex; + + ATOM atom; + + // Register window class + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = DesktopToastsApp::WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(LONG_PTR); + wcex.hInstance = HINST_THISCOMPONENT; + wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = nullptr; + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = L"DesktopToastsApp"; + wcex.hIconSm = LoadIcon(nullptr, IDI_APPLICATION); + atom = RegisterClassEx(&wcex); + + hr = atom ? S_OK : E_FAIL; + + if (SUCCEEDED(hr)) + { + // Create window + _hwnd = CreateWindow( + L"DesktopToastsApp", + L"Desktop Toasts Demo App", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + 350, + 200, + nullptr, + nullptr, + HINST_THISCOMPONENT, + this + ); + + hr = _hwnd ? S_OK : E_FAIL; + + if (SUCCEEDED(hr)) + { + CreateWindow( + L"BUTTON", + L"View Text Toast", + BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, + 0, + 0, + 150, + 25, + _hwnd, + reinterpret_cast(HM_TEXTBUTTON), + HINST_THISCOMPONENT, + nullptr + ); + _hEdit = CreateWindow( + L"EDIT", + L"Whatever action you take on the displayed toast will be shown here.", + ES_LEFT | ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_BORDER, + 0, + 30, + 300, + 50, + _hwnd, nullptr, + HINST_THISCOMPONENT, + nullptr + ); + + ShowWindow(_hwnd, SW_SHOWNORMAL); + UpdateWindow(_hwnd); + } + } + } + else + { + MessageBox(nullptr, L"Failed to install shortcut. Try running this application as administrator.", L"Failed launch", MB_OK | MB_ICONERROR); + } + + return hr; +} + +// Standard message loop +void DesktopToastsApp::RunMessageLoop() +{ + MSG msg; + + while (GetMessage(&msg, nullptr, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +// Display the toast using classic COM. Note that is also possible to create and display the toast using the new C++ /ZW options (using handles, +// COM wrappers, etc.) +HRESULT DesktopToastsApp::DisplayToast() +{ + ComPtr toastStatics; + HRESULT hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastStatics); + + if (SUCCEEDED(hr)) + { + ComPtr toastXml; + hr = CreateToastXml(toastStatics.Get(), &toastXml); + if (SUCCEEDED(hr)) + { + hr = CreateToast(toastStatics.Get(), toastXml.Get()); + } + } + return hr; +} + +// Create the toast XML from a template +HRESULT DesktopToastsApp::CreateToastXml(_In_ IToastNotificationManagerStatics *toastManager, _Outptr_ IXmlDocument** inputXml) +{ + // Retrieve the template XML + HRESULT hr = toastManager->GetTemplateContent(ToastTemplateType_ToastImageAndText04, inputXml); + if (SUCCEEDED(hr)) + { + wchar_t *imagePath = _wfullpath(nullptr, L"toastImageAndText.png", MAX_PATH); + + hr = imagePath != nullptr ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + if (SUCCEEDED(hr)) + { + hr = SetImageSrc(imagePath, *inputXml); + if (SUCCEEDED(hr)) + { + wchar_t* textValues[] = { + L"Line 1", + L"Line 2", + L"Line 3" + }; + + UINT32 textLengths[] = {6, 6, 6}; + + hr = SetTextValues(textValues, 3, textLengths, *inputXml); + } + } + } + return hr; +} + +// Set the value of the "src" attribute of the "image" node +HRESULT DesktopToastsApp::SetImageSrc(_In_z_ wchar_t *imagePath, _In_ IXmlDocument *toastXml) +{ + wchar_t imageSrc[MAX_PATH] = L"file:///"; + HRESULT hr = StringCchCat(imageSrc, ARRAYSIZE(imageSrc), imagePath); + if (SUCCEEDED(hr)) + { + ComPtr nodeList; + hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"image").Get(), &nodeList); + if (SUCCEEDED(hr)) + { + ComPtr imageNode; + hr = nodeList->Item(0, &imageNode); + if (SUCCEEDED(hr)) + { + ComPtr attributes; + + hr = imageNode->get_Attributes(&attributes); + if (SUCCEEDED(hr)) + { + ComPtr srcAttribute; + + hr = attributes->GetNamedItem(StringReferenceWrapper(L"src").Get(), &srcAttribute); + if (SUCCEEDED(hr)) + { + hr = SetNodeValueString(StringReferenceWrapper(imageSrc).Get(), srcAttribute.Get(), toastXml); + } + } + } + } + } + return hr; +} + +// Set the values of each of the text nodes +HRESULT DesktopToastsApp::SetTextValues(_In_reads_(textValuesCount) wchar_t **textValues, _In_ UINT32 textValuesCount, _In_reads_(textValuesCount) UINT32 *textValuesLengths, _In_ IXmlDocument *toastXml) +{ + HRESULT hr = textValues != nullptr && textValuesCount > 0 ? S_OK : E_INVALIDARG; + if (SUCCEEDED(hr)) + { + ComPtr nodeList; + hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"text").Get(), &nodeList); + if (SUCCEEDED(hr)) + { + UINT32 nodeListLength; + hr = nodeList->get_Length(&nodeListLength); + if (SUCCEEDED(hr)) + { + hr = textValuesCount <= nodeListLength ? S_OK : E_INVALIDARG; + if (SUCCEEDED(hr)) + { + for (UINT32 i = 0; i < textValuesCount; i++) + { + ComPtr textNode; + hr = nodeList->Item(i, &textNode); + if (SUCCEEDED(hr)) + { + hr = SetNodeValueString(StringReferenceWrapper(textValues[i], textValuesLengths[i]).Get(), textNode.Get(), toastXml); + } + } + } + } + } + } + return hr; +} + +HRESULT DesktopToastsApp::SetNodeValueString(_In_ HSTRING inputString, _In_ IXmlNode *node, _In_ IXmlDocument *xml) +{ + ComPtr inputText; + + HRESULT hr = xml->CreateTextNode(inputString, &inputText); + if (SUCCEEDED(hr)) + { + ComPtr inputTextNode; + + hr = inputText.As(&inputTextNode); + if (SUCCEEDED(hr)) + { + ComPtr pAppendedChild; + hr = node->AppendChild(inputTextNode.Get(), &pAppendedChild); + } + } + + return hr; +} + +// Create and display the toast +HRESULT DesktopToastsApp::CreateToast(_In_ IToastNotificationManagerStatics *toastManager, _In_ IXmlDocument *xml) +{ + ComPtr notifier; + HRESULT hr = toastManager->CreateToastNotifierWithId(StringReferenceWrapper(AppId).Get(), ¬ifier); + if (SUCCEEDED(hr)) + { + ComPtr factory; + hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory); + if (SUCCEEDED(hr)) + { + ComPtr toast; + hr = factory->CreateToastNotification(xml, &toast); + if (SUCCEEDED(hr)) + { + // Register the event handlers + EventRegistrationToken activatedToken, dismissedToken, failedToken; + ComPtr eventHandler(new ToastEventHandler(_hwnd, _hEdit)); + + hr = toast->add_Activated(eventHandler.Get(), &activatedToken); + if (SUCCEEDED(hr)) + { + hr = toast->add_Dismissed(eventHandler.Get(), &dismissedToken); + if (SUCCEEDED(hr)) + { + hr = toast->add_Failed(eventHandler.Get(), &failedToken); + if (SUCCEEDED(hr)) + { + hr = notifier->Show(toast.Get()); + } + } + } + } + } + } + return hr; +} + +HRESULT DesktopToastsApp::TextButtonClicked() +{ + return DisplayToast(); +} + +// Standard window procedure +LRESULT CALLBACK DesktopToastsApp::WndProc(_In_ HWND hwnd, _In_ UINT32 message, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + if (message == WM_CREATE) + { + LPCREATESTRUCT pcs = reinterpret_cast(lParam); + DesktopToastsApp *app = reinterpret_cast(pcs->lpCreateParams); + + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) app); + + return 1; + } + + DesktopToastsApp *pApp = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + if (pApp) + { + switch (message) + { + case WM_COMMAND: + { + int wmId = LOWORD(wParam); + switch (wmId) + { + case HM_TEXTBUTTON: + pApp->TextButtonClicked(); + break; + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } + } + break; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + } + return 0; + case WM_DESTROY: + { + PostQuitMessage(0); + } + return 1; + } + } + return DefWindowProc(hwnd, message, wParam, lParam); +} diff --git a/Samples/DesktopToasts/cpp/DesktopToastsSample.h b/Samples/DesktopToasts/cpp/DesktopToastsSample.h new file mode 100644 index 00000000..5f2efc22 --- /dev/null +++ b/Samples/DesktopToasts/cpp/DesktopToastsSample.h @@ -0,0 +1,67 @@ +#pragma once + +#define LINE_LENGTH 15 // How many characters we'll allot for each line of a toast + +#ifndef HINST_THISCOMPONENT +EXTERN_C IMAGE_DOS_HEADER __ImageBase; +#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifndef HM_TEXTBUTTON +#define HM_TEXTBUTTON 1 +#endif + +const wchar_t AppId[] = L"Microsoft.Samples.DesktopToasts"; + +class DesktopToastsApp +{ +public: + DesktopToastsApp(); + ~DesktopToastsApp(); + HRESULT Initialize(); + void RunMessageLoop(); + +private: + HRESULT TryCreateShortcut(); + HRESULT InstallShortcut(_In_z_ wchar_t *shortcutPath); + static LRESULT CALLBACK WndProc( + _In_ HWND hWnd, + _In_ UINT message, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ); + + HRESULT TextButtonClicked(); + HRESULT DisplayToast(); + HRESULT CreateToastXml( + _In_ ABI::Windows::UI::Notifications::IToastNotificationManagerStatics *toastManager, + _Outptr_ ABI::Windows::Data::Xml::Dom::IXmlDocument **xml + ); + + HRESULT CreateToast( + _In_ ABI::Windows::UI::Notifications::IToastNotificationManagerStatics *toastManager, + _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument *xml + ); + HRESULT DesktopToastsApp::SetImageSrc( + _In_z_ wchar_t *imagePath, + _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument *toastXml + ); + HRESULT DesktopToastsApp::SetTextValues( + _In_reads_(textValuesCount) wchar_t **textValues, + _In_ UINT32 textValuesCount, + _In_reads_(textValuesCount) UINT32 *textValuesLengths, + _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument *toastXml + ); + HRESULT DesktopToastsApp::SetNodeValueString( + _In_ HSTRING onputString, + _In_ ABI::Windows::Data::Xml::Dom::IXmlNode *node, + _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument *xml + ); + + HWND _hwnd; + HWND _hEdit; +}; \ No newline at end of file diff --git a/Samples/DesktopToasts/cpp/DesktopToastsSample.sln b/Samples/DesktopToasts/cpp/DesktopToastsSample.sln new file mode 100644 index 00000000..90da10d6 --- /dev/null +++ b/Samples/DesktopToasts/cpp/DesktopToastsSample.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DesktopToastsSample", "DesktopToastsSample.vcxproj", "{77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = preSolution + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Debug|Win32.ActiveCfg = Debug|Win32 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Debug|Win32.Build.0 = Debug|Win32 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Debug|x64.ActiveCfg = Debug|x64 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Debug|x64.Build.0 = Debug|x64 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Release|Win32.ActiveCfg = Release|Win32 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Release|Win32.Build.0 = Release|Win32 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Release|x64.ActiveCfg = Release|x64 + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DesktopToasts/cpp/DesktopToastsSample.vcxproj b/Samples/DesktopToasts/cpp/DesktopToastsSample.vcxproj new file mode 100644 index 00000000..d7a2bb56 --- /dev/null +++ b/Samples/DesktopToasts/cpp/DesktopToastsSample.vcxproj @@ -0,0 +1,169 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + $(VCTargetsPath11) + + + {77CC36BE-AD64-4AD3-95C6-0F352F6A3FE3} + Win32Proj + DesktopToastsSample + + + + Application + true + v110 + Unicode + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + runtimeobject.lib;shlwapi.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) + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + runtimeobject.lib;shlwapi.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 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + runtimeobject.lib;shlwapi.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 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + runtimeobject.lib;shlwapi.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) + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + \ No newline at end of file diff --git a/Samples/DesktopToasts/cpp/Product.wxs b/Samples/DesktopToasts/cpp/Product.wxs new file mode 100644 index 00000000..6cbfd836 --- /dev/null +++ b/Samples/DesktopToasts/cpp/Product.wxs @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/DesktopToasts/cpp/StringReferenceWrapper.h b/Samples/DesktopToasts/cpp/StringReferenceWrapper.h new file mode 100644 index 00000000..860cd3f5 --- /dev/null +++ b/Samples/DesktopToasts/cpp/StringReferenceWrapper.h @@ -0,0 +1,60 @@ +class StringReferenceWrapper +{ +public: + + // Constructor which takes an existing string buffer and its length as the parameters. + // It fills an HSTRING_HEADER struct with the parameter. + // Warning: The caller must ensure the lifetime of the buffer outlives this + // object as it does not make a copy of the wide string memory. + + StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() + { + HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring); + + if (FAILED(hr)) + { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + + ~StringReferenceWrapper() + { + WindowsDeleteString(_hstring); + } + + template + StringReferenceWrapper(_In_reads_(N) wchar_t const (&stringRef)[N]) throw() + { + UINT32 length = N-1; + HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring); + + if (FAILED(hr)) + { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + + template + StringReferenceWrapper(_In_reads_(_) wchar_t (&stringRef)[_]) throw() + { + UINT32 length; + HRESULT hr = SizeTToUInt32(wcslen(stringRef), &length); + + if (FAILED(hr)) + { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + + WindowsCreateStringReference(stringRef, length, &_header, &_hstring); + } + + HSTRING Get() const throw() + { + return _hstring; + } + + +private: + HSTRING _hstring; + HSTRING_HEADER _header; +}; diff --git a/Samples/DesktopToasts/cpp/ToastEventHandler.cpp b/Samples/DesktopToasts/cpp/ToastEventHandler.cpp new file mode 100644 index 00000000..91be122f --- /dev/null +++ b/Samples/DesktopToasts/cpp/ToastEventHandler.cpp @@ -0,0 +1,63 @@ +#include "stdafx.h" +#include "ToastEventHandler.h" + +using namespace ABI::Windows::UI::Notifications; + +ToastEventHandler::ToastEventHandler(_In_ HWND hToActivate, _In_ HWND hEdit) : _ref(1), _hToActivate(hToActivate), _hEdit(hEdit) +{ + +} + +ToastEventHandler::~ToastEventHandler() +{ + +} + +// DesktopToastActivatedEventHandler +IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IInspectable* /* args */) +{ + BOOL succeeded = SetForegroundWindow(_hToActivate); + if (succeeded) + { + LRESULT result = SendMessage(_hEdit, WM_SETTEXT, reinterpret_cast(nullptr), reinterpret_cast(L"The user clicked on the toast.")); + succeeded = result ? TRUE : FALSE; + } + return succeeded ? S_OK : E_FAIL; +} + +// DesktopToastDismissedEventHandler +IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastDismissedEventArgs* e) +{ + ToastDismissalReason tdr; + HRESULT hr = e->get_Reason(&tdr); + if (SUCCEEDED(hr)) + { + wchar_t *outputText; + switch (tdr) + { + case ToastDismissalReason_ApplicationHidden: + outputText = L"The application hid the toast using ToastNotifier.hide()"; + break; + case ToastDismissalReason_UserCanceled: + outputText = L"The user dismissed this toast"; + break; + case ToastDismissalReason_TimedOut: + outputText = L"The toast has timed out"; + break; + default: + outputText = L"Toast not activated"; + break; + } + + LRESULT succeeded = SendMessage(_hEdit, WM_SETTEXT, reinterpret_cast(nullptr), reinterpret_cast(outputText)); + hr = succeeded ? S_OK : E_FAIL; + } + return hr; +} + +// DesktopToastFailedEventHandler +IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastFailedEventArgs* /* e */) +{ + LRESULT succeeded = SendMessage(_hEdit, WM_SETTEXT, reinterpret_cast(nullptr), reinterpret_cast(L"The toast encountered an error.")); + return succeeded ? S_OK : E_FAIL; +} diff --git a/Samples/DesktopToasts/cpp/ToastEventHandler.h b/Samples/DesktopToasts/cpp/ToastEventHandler.h new file mode 100644 index 00000000..72b79d98 --- /dev/null +++ b/Samples/DesktopToasts/cpp/ToastEventHandler.h @@ -0,0 +1,55 @@ +#pragma once + +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastActivatedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastDismissedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastFailedEventHandler; + +class ToastEventHandler : + public Microsoft::WRL::Implements +{ +public: + ToastEventHandler::ToastEventHandler(_In_ HWND hToActivate, _In_ HWND hEdit); + ~ToastEventHandler(); + + // DesktopToastActivatedEventHandler + IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification *sender, _In_ IInspectable* args); + + // DesktopToastDismissedEventHandler + IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification *sender, _In_ ABI::Windows::UI::Notifications::IToastDismissedEventArgs *e); + + // DesktopToastFailedEventHandler + IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification *sender, _In_ ABI::Windows::UI::Notifications::IToastFailedEventArgs *e); + + // IUnknown + IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_ref); } + + IFACEMETHODIMP_(ULONG) Release() { + ULONG l = InterlockedDecrement(&_ref); + if (l == 0) delete this; + return l; + } + + IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) { + if (IsEqualIID(riid, IID_IUnknown)) + *ppv = static_cast(static_cast(this)); + else if (IsEqualIID(riid, __uuidof(DesktopToastActivatedEventHandler))) + *ppv = static_cast(this); + else if (IsEqualIID(riid, __uuidof(DesktopToastDismissedEventHandler))) + *ppv = static_cast(this); + else if (IsEqualIID(riid, __uuidof(DesktopToastFailedEventHandler))) + *ppv = static_cast(this); + else *ppv = nullptr; + + if (*ppv) { + reinterpret_cast(*ppv)->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + +private: + ULONG _ref; + HWND _hToActivate; + HWND _hEdit; +}; diff --git a/Samples/DesktopToasts/cpp/stdafx.cpp b/Samples/DesktopToasts/cpp/stdafx.cpp new file mode 100644 index 00000000..a17fc26c --- /dev/null +++ b/Samples/DesktopToasts/cpp/stdafx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// DesktopToastsSample.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/Samples/DesktopToasts/cpp/stdafx.h b/Samples/DesktopToasts/cpp/stdafx.h new file mode 100644 index 00000000..95b9c064 --- /dev/null +++ b/Samples/DesktopToasts/cpp/stdafx.h @@ -0,0 +1,30 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once +#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") + +#include + +// Windows Header Files: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "StringReferenceWrapper.h" +#include "DesktopToastsSample.h" +#include "ToastEventHandler.h" \ No newline at end of file diff --git a/Samples/DesktopToasts/cpp/toastImageAndText.png b/Samples/DesktopToasts/cpp/toastImageAndText.png new file mode 100644 index 0000000000000000000000000000000000000000..1c55c1fc3a34f086a0713a0f56f285c8b35b3d59 GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0vp^J3yF&2}s@#+&BS9NtU=qlmzFem6RtIr7}3C7Mn1|``7fn zvqC~o@Af?N`|x%L4Gz|Y3L-5{0RmnA4FLjNPL3cE1WQ2#CI(c+1d#=+hw79Q{T_EV zd+~$o%@EBHvmnNROeNAlH}C6*-|am&>$)4*eq~ literal 0 HcmV?d00001 diff --git a/Samples/DesktopToasts/cs/App.config b/Samples/DesktopToasts/cs/App.config new file mode 100644 index 00000000..8e156463 --- /dev/null +++ b/Samples/DesktopToasts/cs/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Samples/DesktopToasts/cs/App.xaml b/Samples/DesktopToasts/cs/App.xaml new file mode 100644 index 00000000..ac287bf9 --- /dev/null +++ b/Samples/DesktopToasts/cs/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Samples/DesktopToasts/cs/App.xaml.cs b/Samples/DesktopToasts/cs/App.xaml.cs new file mode 100644 index 00000000..07487830 --- /dev/null +++ b/Samples/DesktopToasts/cs/App.xaml.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace DesktopToastsSample +{ + ///

+ /// Interaction logic for App.xaml + /// + /// + public partial class App : Application + { + + } +} diff --git a/Samples/DesktopToasts/cs/DesktopToastsSample.csproj b/Samples/DesktopToasts/cs/DesktopToastsSample.csproj new file mode 100644 index 00000000..8e6e7fbf --- /dev/null +++ b/Samples/DesktopToasts/cs/DesktopToastsSample.csproj @@ -0,0 +1,143 @@ + + + + true + bin\x64\Debug\ + DEBUG;TRACE + ;2008 + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + ;2008 + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + Debug + AnyCPU + {5DC8BE95-8440-4187-839E-43E1426D5B7F} + WinExe + Properties + DesktopToastsSample + DesktopToastsSample + v4.5 + 8.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\Windows API Code Pack 1.1\binaries\Microsoft.WindowsAPICodePack.dll + + + False + ..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\Windows API Code Pack 1.1\binaries\Microsoft.WindowsAPICodePack.Shell.dll + + + + + + + + + + + + 4.0 + + + + + + + + + MSBuild:Compile + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + Always + + + + + \ No newline at end of file diff --git a/Samples/DesktopToasts/cs/DesktopToastsSample.sln b/Samples/DesktopToasts/cs/DesktopToastsSample.sln new file mode 100644 index 00000000..fdd75df4 --- /dev/null +++ b/Samples/DesktopToasts/cs/DesktopToastsSample.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopToastsSample", "DesktopToastsSample.csproj", "{5DC8BE95-8440-4187-839E-43E1426D5B7F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = preSolution + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Debug|Any CPU.ActiveCfg = Debug|x64 + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Debug|Any CPU.Build.0 = Debug|x64 + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Debug|x64.ActiveCfg = Debug|x64 + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Debug|x64.Build.0 = Debug|x64 + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Release|Any CPU.Build.0 = Release|Any CPU + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Release|x64.ActiveCfg = Release|x64 + {5DC8BE95-8440-4187-839E-43E1426D5B7F}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DesktopToasts/cs/MainWindow.xaml b/Samples/DesktopToasts/cs/MainWindow.xaml new file mode 100644 index 00000000..38f1caee --- /dev/null +++ b/Samples/DesktopToasts/cs/MainWindow.xaml @@ -0,0 +1,9 @@ + + + + Whatever action you take on the displayed toast will appear here + + diff --git a/Samples/DesktopToasts/cs/MainWindow.xaml.cs b/Samples/DesktopToasts/cs/MainWindow.xaml.cs new file mode 100644 index 00000000..cea6d022 --- /dev/null +++ b/Samples/DesktopToasts/cs/MainWindow.xaml.cs @@ -0,0 +1,138 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Windows; +using System.Windows.Controls; +using DesktopToastsSample.ShellHelpers; +using MS.WindowsAPICodePack.Internal; +using Microsoft.WindowsAPICodePack.Shell.PropertySystem; + +using Windows.UI.Notifications; +using Windows.Data.Xml.Dom; + +namespace DesktopToastsSample +{ + public partial class MainWindow : Window + { + private const String APP_ID = "Microsoft.Samples.DesktopToastsSample"; + public MainWindow() + { + InitializeComponent(); + TryCreateShortcut(); + ShowToastButton.Click += ShowToastButton_Click; + } + + // In order to display toasts, a desktop application must have a shortcut on the Start menu. + // Also, an AppUserModelID must be set on that shortcut. + // The shortcut should be created as part of the installer. The following code shows how to create + // a shortcut and assign an AppUserModelID using Windows APIs. You must download and include the + // Windows API Code Pack for Microsoft .NET Framework for this code to function + // + // Included in this project is a wxs file that be used with the WiX toolkit + // to make an installer that creates the necessary shortcut. One or the other should be used. + private bool TryCreateShortcut() + { + String shortcutPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop Toasts Sample CS.lnk"; + if (!File.Exists(shortcutPath)) + { + InstallShortcut(shortcutPath); + return true; + } + return false; + } + + private void InstallShortcut(String shortcutPath) + { + // Find the path to the current executable + String exePath = Process.GetCurrentProcess().MainModule.FileName; + IShellLinkW newShortcut = (IShellLinkW)new CShellLink(); + + // Create a shortcut to the exe + ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetPath(exePath)); + ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetArguments("")); + + // Open the shortcut property store, set the AppUserModelId property + IPropertyStore newShortcutProperties = (IPropertyStore)newShortcut; + + using (PropVariant appId = new PropVariant(APP_ID)) + { + ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.SetValue(SystemProperties.System.AppUserModel.ID, appId)); + ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.Commit()); + } + + // Commit the shortcut to disk + IPersistFile newShortcutSave = (IPersistFile)newShortcut; + + ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutSave.Save(shortcutPath, true)); + } + + // Create and show the toast. + // See the "Toasts" sample for more detail on what can be done with toasts + private void ShowToastButton_Click(object sender, RoutedEventArgs e) + { + + // Get a toast XML template + XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04); + + // Fill in the text elements + XmlNodeList stringElements = toastXml.GetElementsByTagName("text"); + for (int i = 0; i < stringElements.Length; i++) + { + stringElements[i].AppendChild(toastXml.CreateTextNode("Line " + i)); + } + + // Specify the absolute path to an image + String imagePath = "file:///" + Path.GetFullPath("toastImageAndText.png"); + XmlNodeList imageElements = toastXml.GetElementsByTagName("image"); + imageElements[0].Attributes.GetNamedItem("src").NodeValue = imagePath; + + // Create the toast and attach event listeners + ToastNotification toast = new ToastNotification(toastXml); + toast.Activated += ToastActivated; + toast.Dismissed += ToastDismissed; + toast.Failed += ToastFailed; + + // Show the toast. Be sure to specify the AppUserModelId on your application's shortcut! + ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast); + } + + private void ToastActivated(ToastNotification sender, object e) + { + Dispatcher.Invoke(() => + { + Activate(); + Output.Text = "The user activated the toast."; + }); + } + + private void ToastDismissed(ToastNotification sender, ToastDismissedEventArgs e) + { + String outputText = ""; + switch (e.Reason) + { + case ToastDismissalReason.ApplicationHidden: + outputText = "The app hid the toast using ToastNotifier.Hide"; + break; + case ToastDismissalReason.UserCanceled: + outputText = "The user dismissed the toast"; + break; + case ToastDismissalReason.TimedOut: + outputText = "The toast has timed out"; + break; + } + + Dispatcher.Invoke(() => + { + Output.Text = outputText; + }); + } + + private void ToastFailed(ToastNotification sender, ToastFailedEventArgs e) + { + Dispatcher.Invoke(() => + { + Output.Text = "The toast encountered an error."; + }); + } + } +} diff --git a/Samples/DesktopToasts/cs/Product.wxs b/Samples/DesktopToasts/cs/Product.wxs new file mode 100644 index 00000000..6cbfd836 --- /dev/null +++ b/Samples/DesktopToasts/cs/Product.wxs @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/DesktopToasts/cs/Properties/AssemblyInfo.cs b/Samples/DesktopToasts/cs/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..7e000cfe --- /dev/null +++ b/Samples/DesktopToasts/cs/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DesktopToastsSample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("DesktopToastsSample")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Samples/DesktopToasts/cs/Properties/Resources.Designer.cs b/Samples/DesktopToasts/cs/Properties/Resources.Designer.cs new file mode 100644 index 00000000..040082da --- /dev/null +++ b/Samples/DesktopToasts/cs/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17353 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DesktopToastsSample.Properties { + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DesktopToastsSample.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/DesktopToasts/cs/Properties/Resources.resx b/Samples/DesktopToasts/cs/Properties/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/Samples/DesktopToasts/cs/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/DesktopToasts/cs/Properties/Settings.Designer.cs b/Samples/DesktopToasts/cs/Properties/Settings.Designer.cs new file mode 100644 index 00000000..c651df69 --- /dev/null +++ b/Samples/DesktopToasts/cs/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17353 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DesktopToastsSample.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Samples/DesktopToasts/cs/Properties/Settings.settings b/Samples/DesktopToasts/cs/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/Samples/DesktopToasts/cs/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Samples/DesktopToasts/cs/ShellHelpers.cs b/Samples/DesktopToasts/cs/ShellHelpers.cs new file mode 100644 index 00000000..06dfac8d --- /dev/null +++ b/Samples/DesktopToasts/cs/ShellHelpers.cs @@ -0,0 +1,133 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.WindowsAPICodePack.Shell.PropertySystem; +using MS.WindowsAPICodePack.Internal; + +namespace DesktopToastsSample.ShellHelpers +{ + internal enum STGM : long + { + STGM_READ = 0x00000000L, + STGM_WRITE = 0x00000001L, + STGM_READWRITE = 0x00000002L, + STGM_SHARE_DENY_NONE = 0x00000040L, + STGM_SHARE_DENY_READ = 0x00000030L, + STGM_SHARE_DENY_WRITE = 0x00000020L, + STGM_SHARE_EXCLUSIVE = 0x00000010L, + STGM_PRIORITY = 0x00040000L, + STGM_CREATE = 0x00001000L, + STGM_CONVERT = 0x00020000L, + STGM_FAILIFTHERE = 0x00000000L, + STGM_DIRECT = 0x00000000L, + STGM_TRANSACTED = 0x00010000L, + STGM_NOSCRATCH = 0x00100000L, + STGM_NOSNAPSHOT = 0x00200000L, + STGM_SIMPLE = 0x08000000L, + STGM_DIRECT_SWMR = 0x00400000L, + STGM_DELETEONRELEASE = 0x04000000L, + } + + internal static class ShellIIDGuid + { + internal const string IShellLinkW = "000214F9-0000-0000-C000-000000000046"; + internal const string CShellLink = "00021401-0000-0000-C000-000000000046"; + internal const string IPersistFile = "0000010b-0000-0000-C000-000000000046"; + internal const string IPropertyStore = "886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"; + } + + [ComImport, + Guid(ShellIIDGuid.IShellLinkW), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IShellLinkW + { + UInt32 GetPath( + [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, + int cchMaxPath, + //ref _WIN32_FIND_DATAW pfd, + IntPtr pfd, + uint fFlags); + UInt32 GetIDList(out IntPtr ppidl); + UInt32 SetIDList(IntPtr pidl); + UInt32 GetDescription( + [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, + int cchMaxName); + UInt32 SetDescription( + [MarshalAs(UnmanagedType.LPWStr)] string pszName); + UInt32 GetWorkingDirectory( + [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, + int cchMaxPath + ); + UInt32 SetWorkingDirectory( + [MarshalAs(UnmanagedType.LPWStr)] string pszDir); + UInt32 GetArguments( + [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, + int cchMaxPath); + UInt32 SetArguments( + [MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + UInt32 GetHotKey(out short wHotKey); + UInt32 SetHotKey(short wHotKey); + UInt32 GetShowCmd(out uint iShowCmd); + UInt32 SetShowCmd(uint iShowCmd); + UInt32 GetIconLocation( + [Out(), MarshalAs(UnmanagedType.LPWStr)] out StringBuilder pszIconPath, + int cchIconPath, + out int iIcon); + UInt32 SetIconLocation( + [MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, + int iIcon); + UInt32 SetRelativePath( + [MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, + uint dwReserved); + UInt32 Resolve(IntPtr hwnd, uint fFlags); + UInt32 SetPath( + [MarshalAs(UnmanagedType.LPWStr)] string pszFile); + } + + [ComImport, + Guid(ShellIIDGuid.IPersistFile), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IPersistFile + { + UInt32 GetCurFile( + [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile + ); + UInt32 IsDirty(); + UInt32 Load( + [MarshalAs(UnmanagedType.LPWStr)] string pszFileName, + [MarshalAs(UnmanagedType.U4)] STGM dwMode); + UInt32 Save( + [MarshalAs(UnmanagedType.LPWStr)] string pszFileName, + bool fRemember); + UInt32 SaveCompleted( + [MarshalAs(UnmanagedType.LPWStr)] string pszFileName); + } + [ComImport] + [Guid(ShellIIDGuid.IPropertyStore)] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + interface IPropertyStore + { + UInt32 GetCount([Out] out uint propertyCount); + UInt32 GetAt([In] uint propertyIndex, out PropertyKey key); + UInt32 GetValue([In] ref PropertyKey key, [Out] PropVariant pv); + UInt32 SetValue([In] ref PropertyKey key, [In] PropVariant pv); + UInt32 Commit(); + } + + + [ComImport, + Guid(ShellIIDGuid.CShellLink), + ClassInterface(ClassInterfaceType.None)] + internal class CShellLink { } + + public static class ErrorHelper + { + public static void VerifySucceeded(UInt32 hresult) + { + if (hresult > 1) + { + throw new Exception("Failed with HRESULT: " + hresult.ToString("X")); + } + } + } +} \ No newline at end of file diff --git a/Samples/DesktopToasts/cs/toastImageAndText.png b/Samples/DesktopToasts/cs/toastImageAndText.png new file mode 100644 index 0000000000000000000000000000000000000000..1c55c1fc3a34f086a0713a0f56f285c8b35b3d59 GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0vp^J3yF&2}s@#+&BS9NtU=qlmzFem6RtIr7}3C7Mn1|``7fn zvqC~o@Af?N`|x%L4Gz|Y3L-5{0RmnA4FLjNPL3cE1WQ2#CI(c+1d#=+hw79Q{T_EV zd+~$o%@EBHvmnNROeNAlH}C6*-|am&>$)4*eq~ literal 0 HcmV?d00001 diff --git a/Samples/DetectBootSector/README.md b/Samples/DetectBootSector/README.md new file mode 100644 index 00000000..ae1a484f --- /dev/null +++ b/Samples/DetectBootSector/README.md @@ -0,0 +1,65 @@ +FMAPI detect boot sector sample +=============================== + +This sample shows how to use the FMAPI [**DetectBootSector**](http://msdn.microsoft.com/en-us/library/windows/desktop/dd239110) function to detect whether the first sector on a volume is a valid boot sector. + +This sample is written in C++. + +**Note** FMAPI can only be used in the Windows Preinstallation Environment (WinPE). Applications that use FMAPI must license WinPE. + +This sample contains the following files: + +- DetectBootSector.cpp +- DetectBootSector.sln +- DetectBootSector.vcxproj + +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. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related technologies +-------------------- + +[File Management API (FMAPI)](http://msdn.microsoft.com/en-us/library/windows/desktop/dd239113) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +Build the sample +---------------- + +To build this sample from the command prompt: + +1. Open the **Command Prompt** window and navigate to the DetectBootSector directory. +2. Type the following command after the command prompt: **msbuild DetectBootSector.sln**. + +To build this sample using Microsoft Visual Studio: + +1. Open File Explorer and navigate to the DetectBootSector directory. +2. Double-click the icon for DetectBootSector.sln to open the file in Visual Studio. +3. In the **Build** menu, choose **Build solution**. The sample will be built in the default \\Debug or \\Release directory. + +Run the sample +-------------- + +**Note** All FMAPI samples must be run in a Windows 8.1 or Windows Server 2012 R2 WinPE environment. + +To run the sample: + +1. Navigate to the directory that contains the new executable file, using the command prompt or File Explorer. +2. Copy the executable file into a directory that is accessible from WinPE. +3. Boot to WinPE and open a **Command Prompt** window. Navigate to where the executable file is located. +4. Type the name of the executable file at the command prompt. + diff --git a/Samples/DetectBootSector/cpp/DetectBootSector.cpp b/Samples/DetectBootSector/cpp/DetectBootSector.cpp new file mode 100644 index 00000000..052e325a --- /dev/null +++ b/Samples/DetectBootSector/cpp/DetectBootSector.cpp @@ -0,0 +1,132 @@ +// 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. + +/************************************************************************************************************ +Note: This sample relies on FMAPI, which can only be used in the Windows Preinstallation Environment (WinPE). +*************************************************************************************************************/ + +#include +#include + +// +//Define program specific values +// +#define BOOT_SECTOR_SIZE 512 +#define VOLUME L"\\\\.\\C:" + +// +//Define the needed FMAPI structures as documented in FMAPI +// +typedef enum { + FileSystemUnknown, + FileSystemFAT12, + FileSystemFAT16, + FileSystemFAT32, + FileSystemNTFS +} BOOT_SECTOR_FILE_SYSTEM_TYPE; + +typedef struct _BOOT_SECTOR_INFO { + LONGLONG TotalSectors; + BOOT_SECTOR_FILE_SYSTEM_TYPE FileSystem; + ULONG BytePerSector; + ULONG SectorPerCluster; + BOOL IsEncrypted; +} BOOT_SECTOR_INFO, *PBOOT_SECTOR_INFO; + +typedef BOOL (WINAPI *FuncDetectBootSector) ( + _In_ CONST UCHAR* BootSector, + _Out_ PBOOT_SECTOR_INFO BootSectorParams +); + +// +//Read the first BOOT_SECTOR_SIZE bytes of a given volume +// +_Success_(return) +bool ReadVolumeBytes(_In_ LPCWSTR vol, _Out_writes_all_(BOOT_SECTOR_SIZE) BYTE* buffer) +{ + DWORD bytesRead; + + //Initialize buffer with nulls + memset(buffer, 0, BOOT_SECTOR_SIZE); + + //Open the volume + HANDLE fileHandle = CreateFileW(vol, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (!fileHandle) + { + return false; + } + + //Read the fist BOOT_SECTOR_SIZE bytes + BOOL success = ReadFile(fileHandle, buffer, BOOT_SECTOR_SIZE, &bytesRead, NULL); + + //close the volume + CloseHandle(fileHandle); + + return (success && BOOT_SECTOR_SIZE == bytesRead); +} + +// +//Program entry point +// +void __cdecl wmain(void) +{ + HMODULE hLib; + BYTE bootSector[BOOT_SECTOR_SIZE]; + + (void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); + + //Load FMAPI.DLL + hLib = ::LoadLibraryEx(L"fmapi.dll", NULL, NULL); + if ( !hLib ) + { + wprintf(L"Could not load fmapi.dll. Error #%d\n", GetLastError()); + return; + } + + //Read the first BOOT_SECTOR_SIZE bytes on the volume + if ( !ReadVolumeBytes(VOLUME, bootSector) ) + { + wprintf(L"Error reading from volume, Error #%d\n", GetLastError()); + return; + } + + //Dynamically link to the DetectBootSector function + BOOT_SECTOR_INFO info; + FuncDetectBootSector DetectBootSector; + DetectBootSector = reinterpret_cast( GetProcAddress( hLib, "DetectBootSector" ) ); + + //Detect the boot sector information + if (DetectBootSector(bootSector, &info)) + { + //Determine file system type + LPCWSTR fileSystem; + if ( info.FileSystem == FileSystemFAT32 || + info.FileSystem == FileSystemFAT16 || + info.FileSystem == FileSystemFAT12 ) + { + fileSystem = L"FAT"; + } + else if (info.FileSystem == FileSystemNTFS ) + { + fileSystem = L"NTFS"; + } + else + { + fileSystem = L"UNKNOWN"; + } + + //Display the boot sector information + wprintf(L"File System Type: %s\n", fileSystem); + wprintf(L"Bytes Per Sector: %d\n", info.BytePerSector); + wprintf(L"Sectors Per Cluster: %d\n", info.SectorPerCluster); + wprintf(L"Total Sectors: %I64d\n", info.TotalSectors); + } + else + { + wprintf(L"Boot sector not recognized."); + } +} diff --git a/Samples/DetectBootSector/cpp/DetectBootSector.sln b/Samples/DetectBootSector/cpp/DetectBootSector.sln new file mode 100644 index 00000000..8c63386a --- /dev/null +++ b/Samples/DetectBootSector/cpp/DetectBootSector.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DetectBootSector", "DetectBootSector.vcxproj", "{E4F0A1A4-D868-4610-8452-0F6B690F5B3A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Debug|Win32.ActiveCfg = Debug|Win32 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Debug|Win32.Build.0 = Debug|Win32 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Debug|x64.ActiveCfg = Debug|x64 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Debug|x64.Build.0 = Debug|x64 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Release|Win32.ActiveCfg = Release|Win32 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Release|Win32.Build.0 = Release|Win32 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Release|x64.ActiveCfg = Release|x64 + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DetectBootSector/cpp/DetectBootSector.vcxproj b/Samples/DetectBootSector/cpp/DetectBootSector.vcxproj new file mode 100644 index 00000000..cc95e055 --- /dev/null +++ b/Samples/DetectBootSector/cpp/DetectBootSector.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E4F0A1A4-D868-4610-8452-0F6B690F5B3A} + Win32Proj + DetectBootSector + + + + Application + true + Unicode + V110 + + + Application + true + Unicode + V110 + + + Application + false + true + Unicode + V110 + + + Application + false + true + Unicode + V110 + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Samples/DirectCompositionEffects/README.md b/Samples/DirectCompositionEffects/README.md new file mode 100644 index 00000000..ea0cb6d7 --- /dev/null +++ b/Samples/DirectCompositionEffects/README.md @@ -0,0 +1,56 @@ +DirectComposition effects with Direct2D bitmap content sample +============================================================= + +This sample shows how to use Microsoft DirectComposition to apply animations and effects to visuals that have Direct2D bitmap content. + +The sample creates two DirectComposition visual trees. The visual tree on the right consists of a single root visual, and the visual tree on the left consists of a root visual and four child visuals. Clicking the left mouse button applies animated 3-D transformation effects to the visual trees, including rotation, scaling, perspective, and translation transformations. In addition, animation is applied to the right visual's Opacity property to change the visual's opacity from transparent to opaque. Pressing the 1–4 number keys changes the color of the right visual. + +**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. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[Effects](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437372) + +[How to apply effects](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437379) + +[How to apply animations](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437377) + +Related technologies +-------------------- + +[DirectComposition](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437371) , [Direct2D](http://msdn.microsoft.com/en-us/library/windows/desktop/dd370990), [Direct3D](http://msdn.microsoft.com/en-us/library/windows/desktop/hh309466) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +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. Go to the cpp directory and double-click the Visual Studio Solution (.sln) file. +3. Press F6 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To run this sample after building it, go to the installation folder for this sample with Windows Explorer and run DirectComposition\_Effects.exe from the *\*\\DCompEffectsD2DSDK\\C++\\Debug folder. + +To run this sample from Microsoft Visual Studio, press the F5 key to run with debugging enabled, or Ctrl+F5 to run without debugging enabled. Alternatively, select **Start Debugging** or **Start Without Debugging** from the **Debug** menu. + diff --git a/Samples/DirectCompositionEffects/cpp/Application.cpp b/Samples/DirectCompositionEffects/cpp/Application.cpp new file mode 100644 index 00000000..159639b1 --- /dev/null +++ b/Samples/DirectCompositionEffects/cpp/Application.cpp @@ -0,0 +1,1534 @@ +// 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 "Application.h" +#include "resource.h" +#include + +CApplication *CApplication::_application = nullptr; + +const int CApplication::_gridSize = 100; + +// Runs the application +int CApplication::Run() +{ + int result = 0; + + if (SUCCEEDED(BeforeEnteringMessageLoop())) + { + result = EnterMessageLoop(); + } + else + { + MessageBoxW(NULL, L"An error occuring when running the sample", NULL, MB_OK); + } + + AfterLeavingMessageLoop(); + + return result; +} + +// Creates the application window, the d3d device and DirectComposition device and visual tree +// before entering the message loop. +HRESULT CApplication::BeforeEnteringMessageLoop() +{ + HRESULT hr = CreateApplicationWindow(); + + if (SUCCEEDED(hr)) + { + hr = CreateD3D11Device(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateD2D1Factory(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateD2D1Device(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompositionDevice(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompositionVisualTree(); + } + + return hr; +} + +// Message loop +int CApplication::EnterMessageLoop() +{ + int result = 0; + + if (ShowApplicationWindow()) + { + MSG msg = { 0 }; + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + result = static_cast(msg.wParam); + } + + return result; +} + +// Destroys the application window, DirectComposition device and visual tree. +VOID CApplication::AfterLeavingMessageLoop() +{ + DestroyDCompositionVisualTree(); + + DestroyDCompositionDevice(); + + DestroyD2D1Device(); + + DestroyD2D1Factory(); + + DestroyD3D11Device(); + + DestroyApplicationWindow(); +} + +/*---Code calling DirectComposition APIs------------------------------------------------------------*/ + +// Creates D2D Factory +HRESULT CApplication::CreateD2D1Factory() +{ + return D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &_d2d1Factory); +} + +// Creates D2D Device +HRESULT CApplication::CreateD2D1Device() +{ + HRESULT hr = ((_d3d11Device == nullptr) || (_d2d1Factory == nullptr)) ? E_UNEXPECTED : S_OK; + + CComPtr dxgiDevice; + + if (SUCCEEDED(hr)) + { + hr = _d3d11Device->QueryInterface(&dxgiDevice); + } + + if (SUCCEEDED(hr)) + { + hr = _d2d1Factory->CreateDevice(dxgiDevice, &_d2d1Device); + } + + if (SUCCEEDED(hr)) + { + hr = _d2d1Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &_d2d1DeviceContext); + } + + return hr; +} + +// Creates D3D device +HRESULT CApplication::CreateD3D11Device() +{ + HRESULT hr = S_OK; + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + }; + + D3D_FEATURE_LEVEL featureLevelSupported; + + for (int i = 0; i < sizeof(driverTypes) / sizeof(driverTypes[0]); ++i) + { + CComPtr d3d11Device; + CComPtr d3d11DeviceContext; + + hr = D3D11CreateDevice( + nullptr, + driverTypes[i], + NULL, + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + NULL, + 0, + D3D11_SDK_VERSION, + &d3d11Device, + &featureLevelSupported, + &d3d11DeviceContext); + + if (SUCCEEDED(hr)) + { + _d3d11Device = d3d11Device.Detach(); + _d3d11DeviceContext = d3d11DeviceContext.Detach(); + + break; + } + } + + return hr; +} + +// Initializes DirectComposition +HRESULT CApplication::CreateDCompositionDevice() +{ + HRESULT hr = (_d3d11Device == nullptr) ? E_UNEXPECTED : S_OK; + + CComPtr dxgiDevice; + + if (SUCCEEDED(hr)) + { + hr = _d3d11Device->QueryInterface(&dxgiDevice); + } + + if (SUCCEEDED(hr)) + { + hr = DCompositionCreateDevice(dxgiDevice, __uuidof(IDCompositionDevice), reinterpret_cast(&_device)); + } + + return hr; +} + +// Creates DirectComposition visual tree +HRESULT CApplication::CreateDCompositionVisualTree() +{ + HRESULT hr = ((_device == nullptr) || (_hwnd == NULL)) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateVisual(&_visual); + } + + if (SUCCEEDED(hr)) + { + hr = _device->CreateVisual(&_visualLeft); + } + + CComPtr surfaceLeft; + + if (SUCCEEDED(hr)) + { + hr = CreateSurface(CApplication::_tileSize, 1.0f, 0.0f, 0.0f, &surfaceLeft); + } + + if (SUCCEEDED(hr)) + { + hr = _visualLeft->SetContent(surfaceLeft); + } + + for (int i = 0; i < 4 && SUCCEEDED(hr); ++i) + { + if (SUCCEEDED(hr)) + { + hr = _device->CreateVisual(&_visualLeftChild[i]); + } + + if (i == 0) + { + if (SUCCEEDED(hr)) + { + hr = CreateSurface(CApplication::_tileSize, 0.0f, 1.0f, 0.0f, &_surfaceLeftChild[i]); + } + } + + else if (i == 1) + { + if (SUCCEEDED(hr)) + { + hr = CreateSurface(CApplication::_tileSize, 0.5f, 0.0f, 0.5f, &_surfaceLeftChild[i]); + } + } + + else if (i == 2) + { + if (SUCCEEDED(hr)) + { + hr = CreateSurface(CApplication::_tileSize, 0.5f, 0.5f, 0.0f, &_surfaceLeftChild[i]); + } + } + + else if (i == 3) + { + if (SUCCEEDED(hr)) + { + hr = CreateSurface(CApplication::_tileSize, 0.0f, 0.0f, 1.0f, &_surfaceLeftChild[i]); + } + } + + if (SUCCEEDED(hr)) + { + hr = _visualLeftChild[i]->SetContent(_surfaceLeftChild[i]); + } + } + + if (SUCCEEDED(hr)) + { + hr = _device->CreateVisual(&_visualRight); + } + + if (SUCCEEDED(hr)) + { + hr = _visualRight->SetContent(_surfaceLeftChild[_currentVisual]); + } + + if (SUCCEEDED(hr)) + { + hr = _visual->AddVisual(_visualLeft, TRUE, nullptr); + } + + if (SUCCEEDED(hr)) + { + for (int i = 0; i < 4 && SUCCEEDED(hr); ++i) + { + hr = _visualLeft->AddVisual(_visualLeftChild[i], FALSE, nullptr); + } + } + + if (SUCCEEDED(hr)) + { + hr = _visual->AddVisual(_visualRight, TRUE, _visualLeft); + } + + if (SUCCEEDED(hr)) + { + hr = SetEffectOnVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = _device->CreateTargetForHwnd(_hwnd, TRUE, &_target); + } + + if (SUCCEEDED(hr)) + { + hr = _target->SetRoot(_visual); + } + + if (SUCCEEDED(hr)) + { + hr = _device->Commit(); + } + + return hr; +} + +// Creates surface +HRESULT CApplication::CreateSurface(int size, float red, float green, float blue, IDCompositionSurface **surface) +{ + HRESULT hr = (surface == nullptr) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + hr = ((_device == nullptr) || (_d2d1Factory == nullptr) || (_d2d1DeviceContext == nullptr)) ? E_UNEXPECTED : S_OK; + + *surface = nullptr; + } + + CComPtr surfaceTile; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateSurface(size, size, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ALPHA_MODE_IGNORE, &surfaceTile); + } + + CComPtr dxgiSurface; + POINT offset; + + if (SUCCEEDED(hr)) + { + RECT rect = { 0, 0, size, size }; + + hr = surfaceTile->BeginDraw(&rect, __uuidof(IDXGISurface), reinterpret_cast(&dxgiSurface), &offset); + } + + CComPtr d2d1Bitmap; + + if (SUCCEEDED(hr)) + { + FLOAT dpiX = 0.0f; + FLOAT dpiY = 0.0f; + + _d2d1Factory->GetDesktopDpi(&dpiX, &dpiY); + + D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_IGNORE), + dpiX, + dpiY); + + hr = _d2d1DeviceContext->CreateBitmapFromDxgiSurface(dxgiSurface, &bitmapProperties, &d2d1Bitmap); + + if (SUCCEEDED(hr)) + { + _d2d1DeviceContext->SetTarget(d2d1Bitmap); + } + + CComPtr d2d1Brush; + + if (SUCCEEDED(hr)) + { + hr = _d2d1DeviceContext->CreateSolidColorBrush(D2D1::ColorF(red, green, blue), &d2d1Brush); + } + + if (SUCCEEDED(hr)) + { + _d2d1DeviceContext->BeginDraw(); + + _d2d1DeviceContext->FillRectangle( + D2D1::RectF( + offset.x + 0.0f, + offset.y + 0.0f, + offset.x + static_cast(size), + offset.y + static_cast(size) + ), + d2d1Brush); + + hr = _d2d1DeviceContext->EndDraw(); + } + + surfaceTile->EndDraw(); + } + + if (SUCCEEDED(hr)) + { + *surface = surfaceTile.Detach(); + } + + return hr; +} + +// Sets effects on both the left and the right visuals. +HRESULT CApplication::SetEffectOnVisuals() +{ + HRESULT hr = SetEffectOnVisualLeft(); + + if (SUCCEEDED(hr)) + { + hr = SetEffectOnVisualLeftChildren(); + } + + if (SUCCEEDED(hr)) + { + hr = SetEffectOnVisualRight(); + } + + return hr; +} + +// Sets effect on the left visual. +HRESULT CApplication::SetEffectOnVisualLeft() +{ + HRESULT hr = (_visualLeft == nullptr) ? E_UNEXPECTED : S_OK; + + float beginOffsetX = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 3.0f : 0.5f; + float endOffsetX = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 0.5f : 3.0f; + float offsetY = 1.5f; + + float beginAngle = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 0.0f : 30.0f; + float endAngle = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 30.0f : 0.0f; + + CComPtr translateTransform; + + if (SUCCEEDED(hr)) + { + hr = CreateTranslateTransform( + beginOffsetX * CApplication::_gridSize, offsetY * CApplication::_gridSize, 0.0f, + endOffsetX * CApplication::_gridSize, offsetY * CApplication::_gridSize, 0.0f, + 0.25f, 1.25f, + &translateTransform); + } + + CComPtr rotateTransform; + + if (SUCCEEDED(hr)) + { + hr = CreateRotateTransform( + 3.5f * CApplication::_gridSize, 1.5f * CApplication::_gridSize, 0.0f * CApplication::_gridSize, + 0.0f, 1.0f, 0.0f, + beginAngle, endAngle, + 0.25f, 1.25f, + &rotateTransform); + } + + CComPtr perspectiveTransform; + + if (SUCCEEDED(hr)) + { + hr = CreatePerspectiveTransform(0.0f, 0.0f, -1.0f / (9.0f * CApplication::_gridSize), &perspectiveTransform); + } + + IDCompositionTransform3D *transforms[] = + { + translateTransform, + rotateTransform, + perspectiveTransform, + }; + + CComPtr transformGroup; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateTransform3DGroup(transforms, sizeof(transforms) / sizeof(transforms[0]), &transformGroup); + } + + if (SUCCEEDED(hr)) + { + _effectGroupLeft = nullptr; + + hr = _device->CreateEffectGroup(&_effectGroupLeft); + } + + if (SUCCEEDED(hr)) + { + hr = _effectGroupLeft->SetTransform3D(transformGroup); + } + + if (SUCCEEDED(hr)) + { + hr = _visualLeft->SetEffect(_effectGroupLeft); + } + + return hr; +} + +HRESULT CApplication::SetEffectOnVisualLeftChildren() +{ + HRESULT hr = S_OK; + + for (int i = 0; i < 4 && SUCCEEDED(hr); ++i) + { + int r = i / 2; + int c = i % 2; + + CComPtr scale; + + if (SUCCEEDED(hr)) + { + hr = CreateScaleTransform( + 0.0f, 0.0f, 0.0f, + 1.0f / 3.0f, 1.0f / 3.0f, 1.0f, + &scale); + } + + CComPtr translate; + + if (SUCCEEDED(hr)) + { + hr = CreateTranslateTransform((0.25f + c * 1.5f) * CApplication::_gridSize, (0.25f + r * 1.5f) * CApplication::_gridSize, 0.0f, &translate); + } + + IDCompositionTransform3D *transforms[] = + { + scale, + translate, + }; + + CComPtr transformGroup; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateTransform3DGroup(transforms, sizeof(transforms) / sizeof(transforms[0]), &transformGroup); + } + + if (SUCCEEDED(hr)) + { + _effectGroupLeftChild[i] = nullptr; + + hr = _device->CreateEffectGroup(&_effectGroupLeftChild[i]); + } + + if (SUCCEEDED(hr)) + { + hr = _effectGroupLeftChild[i]->SetTransform3D(transformGroup); + } + + if (SUCCEEDED(hr) && i == _currentVisual) + { + CComPtr opacityAnimation; + + float beginOpacity = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 1.0f : 0.0f; + float endOpacity = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 0.0f : 1.0f; + + hr = CreateLinearAnimation(beginOpacity, endOpacity, 0.25f, 1.25f, &opacityAnimation); + + if (SUCCEEDED(hr)) + { + hr = _effectGroupLeftChild[i]->SetOpacity(opacityAnimation); + } + } + + if (SUCCEEDED(hr)) + { + hr = _visualLeftChild[i]->SetEffect(_effectGroupLeftChild[i]); + } + } + + return hr; +} + +// Sets effect on the right visual +HRESULT CApplication::SetEffectOnVisualRight() +{ + HRESULT hr = (_visualRight == nullptr) ? E_UNEXPECTED : S_OK; + + float beginOffsetX = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 6.5f : 3.75f; + float endOffsetX = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 3.75f : 6.5f; + float offsetY = 1.5f; + + CComPtr translateTransform; + + if (SUCCEEDED(hr)) + { + hr = CreateTranslateTransform( + beginOffsetX * CApplication::_gridSize, offsetY * CApplication::_gridSize, 0.0f, + endOffsetX * CApplication::_gridSize, offsetY * CApplication::_gridSize, 0.0f, + 0.25f, 1.25f, + &translateTransform); + } + + IDCompositionTransform3D *transforms[] = + { + translateTransform, + }; + + CComPtr transformGroup; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateTransform3DGroup(transforms, sizeof(transforms) / sizeof(transforms[0]), &transformGroup); + } + + if (SUCCEEDED(hr)) + { + _effectGroupRight = nullptr; + hr = _device->CreateEffectGroup(&_effectGroupRight); + } + + if (SUCCEEDED(hr)) + { + hr = _effectGroupRight->SetTransform3D(transformGroup); + } + + if (SUCCEEDED(hr)) + { + CComPtr opacityAnimation; + + float beginOpacity = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 0.0f : 1.0f; + float endOpacity = (_actionType == CApplication::ACTION_TYPE::ZOOMOUT) ? 1.0f : 0.0f; + + hr = CreateLinearAnimation(beginOpacity, endOpacity, 0.25f, 1.25f, &opacityAnimation); + + if (SUCCEEDED(hr)) + { + hr = _effectGroupRight->SetOpacity(opacityAnimation); + } + } + + if (SUCCEEDED(hr)) + { + hr = _visualRight->SetEffect(_effectGroupRight); + } + + return hr; +} + +// Creates Translate transform without animation +HRESULT CApplication::CreateTranslateTransform(float offsetX, float offsetY, float offsetZ, IDCompositionTranslateTransform3D **translateTransform) +{ + HRESULT hr = (translateTransform == NULL) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *translateTransform = nullptr; + + hr = (_device == NULL) ? E_UNEXPECTED : S_OK; + } + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateTranslateTransform3D(&transform); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetOffsetX(offsetX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetOffsetY(offsetY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetOffsetZ(offsetZ); + } + + if (SUCCEEDED(hr)) + { + *translateTransform = transform.Detach(); + } + + return hr; +} + +// Creates Translate transform with animation +HRESULT CApplication::CreateTranslateTransform(float beginOffsetX, float beginOffsetY, float beginOffsetZ, float endOffsetX, float endOffsetY, float endOffsetZ, float beginTime, float endTime, IDCompositionTranslateTransform3D **translateTransform) +{ + HRESULT hr = (translateTransform == NULL) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *translateTransform = nullptr; + + hr = (_device == NULL) ? E_UNEXPECTED : S_OK; + } + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateTranslateTransform3D(&transform); + } + + CComPtr offsetXAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginOffsetX, endOffsetX, beginTime, endTime, &offsetXAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetOffsetX(offsetXAnimation); + } + + CComPtr offsetYAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginOffsetY, endOffsetY, beginTime, endTime, &offsetYAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetOffsetY(offsetYAnimation); + } + + CComPtr offsetZAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginOffsetZ, endOffsetZ, beginTime, endTime, &offsetZAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetOffsetZ(offsetZAnimation); + } + + if (SUCCEEDED(hr)) + { + *translateTransform = transform.Detach(); + } + + return hr; +} + +// Creates scale transform without animation +HRESULT CApplication::CreateScaleTransform(float centerX, float centerY, float centerZ, float scaleX, float scaleY, float scaleZ, IDCompositionScaleTransform3D **scaleTransform) +{ + HRESULT hr = (scaleTransform == NULL) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *scaleTransform = nullptr; + + hr = (_device == NULL) ? E_UNEXPECTED : S_OK; + } + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateScaleTransform3D(&transform); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterX(centerX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterY(centerY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterZ(centerZ); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetScaleX(scaleX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetScaleY(scaleY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetScaleZ(scaleZ); + } + + if (SUCCEEDED(hr)) + { + *scaleTransform = transform.Detach(); + } + + return hr; +} + +// Creates scale transform with animation +HRESULT CApplication::CreateScaleTransform(float centerX, float centerY, float centerZ, float beginScaleX, float beginScaleY, float beginScaleZ, float endScaleX, float endScaleY, float endScaleZ, float beginTime, float endTime, IDCompositionScaleTransform3D **scaleTransform) +{ + HRESULT hr = (scaleTransform == NULL) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *scaleTransform = nullptr; + + hr = (_device == NULL) ? E_UNEXPECTED : S_OK; + } + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateScaleTransform3D(&transform); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterX(centerX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterY(centerY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterZ(centerZ); + } + + CComPtr scaleXAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginScaleX, endScaleX, beginTime, endTime, &scaleXAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetScaleX(scaleXAnimation); + } + + CComPtr scaleYAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginScaleY, endScaleY, beginTime, endTime, &scaleYAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetScaleY(scaleYAnimation); + } + + CComPtr scaleZAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginScaleZ, endScaleZ, beginTime, endTime, &scaleZAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetScaleZ(scaleZAnimation); + } + + if (SUCCEEDED(hr)) + { + *scaleTransform = transform.Detach(); + } + + return hr; +} + +// Creates rotate transform without animation +HRESULT CApplication::CreateRotateTransform(float centerX, float centerY, float centerZ, float axisX, float axisY, float axisZ, float angle, IDCompositionRotateTransform3D **rotateTransform) +{ + HRESULT hr = (rotateTransform == NULL) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *rotateTransform = nullptr; + + hr = (_device == NULL) ? E_UNEXPECTED : S_OK; + } + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateRotateTransform3D(&transform); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterX(centerX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterY(centerY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterZ(centerZ); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAxisX(axisX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAxisY(axisY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAxisZ(axisZ); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAngle(angle); + } + + if (SUCCEEDED(hr)) + { + *rotateTransform = transform.Detach(); + } + + return hr; +} + +// Creates rotate transform with animation +HRESULT CApplication::CreateRotateTransform(float centerX, float centerY, float centerZ, float axisX, float axisY, float axisZ, float beginAngle, float endAngle, float beginTime, float endTime, IDCompositionRotateTransform3D **rotateTransform) +{ + HRESULT hr = (rotateTransform == nullptr) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *rotateTransform = nullptr; + + hr = (_device == nullptr) ? E_UNEXPECTED : S_OK; + } + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateRotateTransform3D(&transform); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterX(centerX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterY(centerY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetCenterZ(centerZ); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAxisX(axisX); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAxisY(axisY); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAxisZ(axisZ); + } + + CComPtr angleAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginAngle, endAngle, beginTime, endTime, &angleAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetAngle(angleAnimation); + } + + if (SUCCEEDED(hr)) + { + *rotateTransform = transform.Detach(); + } + + return hr; +} + +HRESULT CApplication::CreateLinearAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **linearAnimation) +{ + HRESULT hr = (linearAnimation == nullptr) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *linearAnimation = nullptr; + + hr = (_device == nullptr) ? E_UNEXPECTED : S_OK; + } + + CComPtr animation; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateAnimation(&animation); + } + + // Ensures animation start value takes effect immediately + if (SUCCEEDED(hr)) + { + if (beginTime > 0.0) + { + hr = animation->AddCubic(0.0, beginValue, 0.0f, 0.0f, 0.0f); + } + } + + if (SUCCEEDED(hr)) + { + hr = animation->AddCubic(beginTime, beginValue, (endValue - beginValue) / (endTime - beginTime), 0.0f, 0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = animation->End(endTime, endValue); + } + + if (SUCCEEDED(hr)) + { + *linearAnimation = animation.Detach(); + } + + return hr; +} + +// Creates perspective transform +HRESULT CApplication::CreatePerspectiveTransform(float dx, float dy, float dz, IDCompositionMatrixTransform3D **perspectiveTransform) +{ + HRESULT hr = (perspectiveTransform == nullptr) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *perspectiveTransform = nullptr; + } + + D3DMATRIX matrix; + matrix._11 = 1.0f; matrix._12 = 0.0f; matrix._13 = 0.0f; matrix._14 = dx; + matrix._21 = 0.0f; matrix._22 = 1.0f; matrix._23 = 0.0f; matrix._24 = dy; + matrix._31 = 0.0f; matrix._32 = 0.0f; matrix._33 = 1.0f; matrix._34 = dz; + matrix._41 = 0.0f; matrix._42 = 0.0f; matrix._43 = 0.0f; matrix._44 = 1.0f; + + CComPtr transform; + + if (SUCCEEDED(hr)) + { + hr = _device->CreateMatrixTransform3D(&transform); + } + + if (SUCCEEDED(hr)) + { + hr = transform->SetMatrix(matrix); + } + + if (SUCCEEDED(hr)) + { + *perspectiveTransform = transform.Detach(); + } + + return hr; +} + +// The child visual associated with the pressed key disappears and the previously disappeared one appears again. +LRESULT CApplication::UpdateVisuals(int currentVisual, int nextVisual) +{ + HRESULT hr = _visualRight->SetContent(_surfaceLeftChild[nextVisual]); + + if (SUCCEEDED(hr)) + { + hr = _effectGroupLeftChild[currentVisual]->SetOpacity(1.0f); + } + + if (SUCCEEDED(hr)) + { + hr = _effectGroupLeftChild[nextVisual]->SetOpacity(0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = _device->Commit(); + } + + return SUCCEEDED(hr) ? 0 : 1; +} + +// Destroys D2D Device +VOID CApplication::DestroyD2D1Device() +{ + _d2d1DeviceContext = nullptr; + _d2d1Device = nullptr; +} + +// Destroys D3D device +VOID CApplication::DestroyD3D11Device() +{ + _d3d11DeviceContext = nullptr; + _d3d11Device = nullptr; +} + +// Destroy D2D Factory +VOID CApplication::DestroyD2D1Factory() +{ + _d2d1Factory = nullptr; +} + +// Destroys DirectComposition Visual tree +VOID CApplication::DestroyDCompositionVisualTree() +{ + _effectGroupRight = nullptr; + + for (int i = 0; i < 4; ++i) + { + _effectGroupLeftChild[i] = nullptr; + } + + _effectGroupLeft = nullptr; + + for (int i = 0; i < 4; ++i) + { + _surfaceLeftChild[i] = nullptr; + } + + _visualRight = nullptr; + + for (int i = 0; i < 4; ++i) + { + _visualLeftChild[i] = nullptr; + } + + _visualLeft = nullptr; + + _visual = nullptr; + + _target = nullptr; +} + +// Destroys DirectComposition device +VOID CApplication::DestroyDCompositionDevice() +{ + _device = nullptr; +} +/*---End of code calling DirectComposition APIs-------------------------------------------------------*/ + +// Main Window procedure +LRESULT CALLBACK CApplication::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + + switch (msg) + { + case WM_LBUTTONUP: + result = _application->OnLeftButton(); + break; + + case WM_KEYDOWN: + result = _application->OnKeyDown(wParam); + break; + + case WM_CLOSE: + result = _application->OnClose(); + break; + + case WM_DESTROY: + result = _application->OnDestroy(); + break; + + case WM_PAINT: + result = _application->OnPaint(); + break; + + default: + result = DefWindowProc(hwnd, msg, wParam, lParam); + } + + return result; +} + +// Provides the entry point to the application +CApplication::CApplication(HINSTANCE instance) : + _hinstance(instance), + _hwnd(NULL), + _tileSize(3 * CApplication::_gridSize), + _windowWidth(9 * CApplication::_gridSize), + _windowHeight(6 * CApplication::_gridSize), + _state(CApplication::VIEW_STATE::ZOOMEDOUT), + _actionType(CApplication::ACTION_TYPE::ZOOMOUT), + _currentVisual(0) +{ + _application = this; +} + +CApplication::~CApplication() +{ + _application = nullptr; +} + +// Creates the application window +HRESULT CApplication::CreateApplicationWindow() +{ + HRESULT hr = S_OK; + + WNDCLASSEX wcex = { 0 }; + + wcex.cbSize = sizeof (wcex); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = CApplication::WindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = _hinstance; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = static_cast(GetStockObject(WHITE_BRUSH)); + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = "MainWindowClass"; + wcex.hIconSm = NULL; + + hr = !RegisterClassEx(&wcex) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + RECT rect = { 0, 0, _windowWidth, _windowHeight }; + + AdjustWindowRect(&rect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE); + + _hwnd = CreateWindowExW( + 0, + L"MainWindowClass", + L"DirectComposition Effects Sample", + WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + CW_USEDEFAULT, + CW_USEDEFAULT, + rect.right - rect.left, + rect.bottom - rect.top, + NULL, + NULL, + _hinstance, + nullptr); + + if (_hwnd == NULL) + { + hr = E_UNEXPECTED; + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontTypeface[32] = { 0 }; + + hr = !LoadStringW(_hinstance, IDS_FONT_TYPEFACE, fontTypeface, ARRAYSIZE(fontTypeface)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + hr = StringCchCopyW(_fontTypeface, ARRAYSIZE(_fontTypeface), fontTypeface); + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontHeightLogo[32] = { 0 }; + + hr = !LoadStringW(_hinstance, IDS_FONT_HEIGHT_LOGO, fontHeightLogo, ARRAYSIZE(fontHeightLogo)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + _fontHeightLogo = _wtoi(fontHeightLogo); + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontHeightTitle[32] = { 0 }; + + hr = !LoadStringW(_hinstance, IDS_FONT_HEIGHT_TITLE, fontHeightTitle, ARRAYSIZE(fontHeightTitle)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + _fontHeightTitle = _wtoi(fontHeightTitle); + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontHeightDescription[32] = { 0 }; + + hr = !LoadStringW(_hinstance, IDS_FONT_HEIGHT_DESCRIPTION, fontHeightDescription, ARRAYSIZE(fontHeightDescription)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + _fontHeightDescription = _wtoi(fontHeightDescription); + } + } + + return hr; +} + +// Shows the application window +BOOL CApplication::ShowApplicationWindow() +{ + BOOL bSucceeded = (_hwnd == NULL) ? FALSE : TRUE; + + if (bSucceeded) + { + ShowWindow(_hwnd, SW_SHOW); + UpdateWindow(_hwnd); + } + + return bSucceeded; +} + +// Destroys the applicaiton window +VOID CApplication::DestroyApplicationWindow() +{ + if (_hwnd != NULL) + { + DestroyWindow(_hwnd); + _hwnd = NULL; + } +} + +// Zoom out to have all the picture on sight. +HRESULT CApplication::ZoomOut() +{ + HRESULT hr = (_state == CApplication::VIEW_STATE::ZOOMEDOUT) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + _actionType = CApplication::ACTION_TYPE::ZOOMOUT; + hr = SetEffectOnVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = _device->Commit(); + } + + if (SUCCEEDED(hr)) + { + _state = CApplication::VIEW_STATE::ZOOMEDOUT; + } + + return hr; +} + +// Zoom in to look more closely to the selected pictures +HRESULT CApplication::ZoomIn() +{ + HRESULT hr = (_state == CApplication::VIEW_STATE::ZOOMEDIN) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + _actionType = CApplication::ACTION_TYPE::ZOOMIN; + hr = SetEffectOnVisuals(); + } + + if (SUCCEEDED(hr)) + { + hr = _device->Commit(); + } + + if (SUCCEEDED(hr)) + { + _state = CApplication::VIEW_STATE::ZOOMEDIN; + } + + return hr; +} + +// Handles the WM_LBUTTONUP message +LRESULT CApplication::OnLeftButton() +{ + HRESULT hr = (_state == CApplication::VIEW_STATE::ZOOMEDOUT) ? ZoomIn() : ZoomOut(); + + return SUCCEEDED(hr) ? 0 : 1; +} + +// Handles the WM_KEYDOWN message +LRESULT CApplication::OnKeyDown(WPARAM wParam) +{ + LRESULT lr = 0; + + if (_state == CApplication::VIEW_STATE::ZOOMEDOUT) + { + if (wParam == '1' && _currentVisual != 0) + { + lr = UpdateVisuals(_currentVisual, 0); + _currentVisual = 0; + } + + else if (wParam == '2' && _currentVisual != 1) + { + lr = UpdateVisuals(_currentVisual, 1); + _currentVisual = 1; + } + + else if (wParam == '3' && _currentVisual != 2) + { + lr = UpdateVisuals(_currentVisual, 2); + _currentVisual = 2; + } + + else if (wParam == '4' && _currentVisual != 3) + { + lr = UpdateVisuals(_currentVisual, 3); + _currentVisual = 3; + } + } + + return lr; +} + +// Handles the WM_CLOSE message +LRESULT CApplication::OnClose() +{ + if (_hwnd != NULL) + { + DestroyWindow(_hwnd); + _hwnd = NULL; + } + + return 0; +} + +// Handles the WM_DESTROY message +LRESULT CApplication::OnDestroy() +{ + PostQuitMessage(0); + + return 0; +} + +// Handles the WM_PAINT message +LRESULT CApplication::OnPaint() +{ + RECT rcClient; + PAINTSTRUCT ps; + HDC hdc = BeginPaint(_hwnd, &ps); + + // get the dimensions of the main window. + GetClientRect(_hwnd, &rcClient); + + // Logo + HFONT hlogo = CreateFontW(_fontHeightLogo, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, _fontTypeface); // Logo Font and Size + if (hlogo != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, hlogo)); + + SetBkMode(hdc, TRANSPARENT); + + rcClient.top = 10; + rcClient.left = 50; + + DrawTextW(hdc, L"Windows samples", -1, &rcClient, DT_WORDBREAK); + + SelectObject(hdc, hOldFont); + + DeleteObject(hlogo); + } + + // Title + HFONT htitle = CreateFontW(_fontHeightTitle, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, _fontTypeface); // Title Font and Size + if (htitle != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, htitle)); + + SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + + rcClient.top = 25; + rcClient.left = 50; + + DrawTextW(hdc, L"DirectComposition Effects Sample", -1, &rcClient, DT_WORDBREAK); + + SelectObject(hdc, hOldFont); + + DeleteObject(htitle); + } + + // Description + HFONT hdescription = CreateFontW(_fontHeightDescription, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, _fontTypeface); // Description Font and Size + if (hdescription != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, hdescription)); + + rcClient.top = 90; + rcClient.left = 50; + + DrawTextW(hdc, L"This sample explains how to use DirectComposition effects: rotation, scaling, perspective, translation and opacity.", -1, &rcClient, DT_WORDBREAK); + + rcClient.top = 500; + rcClient.left = 450; + + DrawTextW(hdc, L"A) Left-click to toggle between single and multiple-panels view.\nB) Use keys 1-4 to switch the color of the right-panel.", -1, &rcClient, DT_WORDBREAK); + + SelectObject(hdc, hOldFont); + + DeleteObject(hdescription); + } + + EndPaint(_hwnd, &ps); + + return 0; +} \ No newline at end of file diff --git a/Samples/DirectCompositionEffects/cpp/Application.h b/Samples/DirectCompositionEffects/cpp/Application.h new file mode 100644 index 00000000..5f538e3a --- /dev/null +++ b/Samples/DirectCompositionEffects/cpp/Application.h @@ -0,0 +1,146 @@ +// 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 + +class CApplication +{ +public: + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +public: + explicit CApplication(HINSTANCE hInstance); + ~CApplication(); + + int Run(); + +private: + CApplication(const CApplication &); + CApplication &operator=(const CApplication &); + +private: + HRESULT BeforeEnteringMessageLoop(); + INT EnterMessageLoop(); + VOID AfterLeavingMessageLoop(); + + HRESULT CreateApplicationWindow(); + BOOL ShowApplicationWindow(); + VOID DestroyApplicationWindow(); + + HRESULT CreateD2D1Factory(); + VOID DestroyD2D1Factory(); + + HRESULT CreateD2D1Device(); + VOID DestroyD2D1Device(); + + HRESULT CreateD3D11Device(); + VOID DestroyD3D11Device(); + + HRESULT CreateDCompositionDevice(); + VOID DestroyDCompositionVisualTree(); + + HRESULT CreateDCompositionVisualTree(); + VOID DestroyDCompositionDevice(); + + HRESULT CreateSurface(int size, float red, float green, float blue, IDCompositionSurface **surface); + + HRESULT CreateTranslateTransform(float offsetX, float offsetY, float offsetZ, IDCompositionTranslateTransform3D **translateTransform); + HRESULT CreateTranslateTransform(float beginOffsetX, float beginOffsetY, float beginOffsetZ, float endOffsetX, float endOffsetY, float endOffsetZ, float beginTime, float endTime, IDCompositionTranslateTransform3D **translateTransform); + + HRESULT CreateScaleTransform(float centerX, float centerY, float centerZ, float scaleX, float scaleY, float scaleZ, IDCompositionScaleTransform3D **scaleTransform); + HRESULT CreateScaleTransform(float centerX, float centerY, float centerZ, float beginScaleX, float beginScaleY, float beginScaleZ, float endScaleX, float endScaleY, float endScaleZ, float beginTime, float endTime, IDCompositionScaleTransform3D **scaleTransform); + + HRESULT CreateRotateTransform(float centerX, float centerY, float centerZ, float axisX, float axisY, float axisZ, float angle, IDCompositionRotateTransform3D **rotateTransform); + HRESULT CreateRotateTransform(float centerX, float centerY, float centerZ, float axisX, float axisY, float axisZ, float beginAngle, float endAngle, float beginTime, float endTime, IDCompositionRotateTransform3D **rotateTransform); + + HRESULT CreatePerspectiveTransform(float dx, float dy, float dz, IDCompositionMatrixTransform3D **perspectiveTransform); + + HRESULT CreateLinearAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **Animation); + + HRESULT SetEffectOnVisuals(); + HRESULT SetEffectOnVisualLeft(); + HRESULT SetEffectOnVisualLeftChildren(); + HRESULT SetEffectOnVisualRight(); + + HRESULT ZoomOut(); + HRESULT ZoomIn(); + + LRESULT OnKeyDown(WPARAM wParam); + LRESULT OnLeftButton(); + LRESULT OnClose(); + LRESULT OnDestroy(); + LRESULT OnPaint(); + + LRESULT UpdateVisuals(int currentVisual, int nextVisual); + +private: + static CApplication *_application; + + static const int _gridSize; + +private: + HINSTANCE _hinstance; + + WCHAR _fontTypeface[32]; + int _fontHeightLogo; + int _fontHeightTitle; + int _fontHeightDescription; + + HWND _hwnd; + + int _tileSize; + + int _windowWidth; + int _windowHeight; + + CComPtr _d3d11Device; + CComPtr _d3d11DeviceContext; + + CComPtr _d2d1Factory; + + CComPtr _d2d1Device; + CComPtr _d2d1DeviceContext; + + CComPtr _device; + CComPtr _target; + CComPtr _visual; + CComPtr _visualLeft; + CComPtr _visualLeftChild[4]; + CComPtr _visualRight; + + CComPtr _surfaceLeftChild[4]; + + CComPtr _effectGroupLeft; + CComPtr _effectGroupLeftChild[4]; + CComPtr _effectGroupRight; + + int _currentVisual; + + enum VIEW_STATE + { + ZOOMEDOUT = 0, + ZOOMEDIN, + }; + + VIEW_STATE _state; + + enum ACTION_TYPE + { + ZOOMOUT = 0, + ZOOMIN, + }; + + ACTION_TYPE _actionType; +}; \ No newline at end of file diff --git a/Samples/DirectCompositionEffects/cpp/Application.rc b/Samples/DirectCompositionEffects/cpp/Application.rc new file mode 100644 index 0000000000000000000000000000000000000000..0b79f2c3b1dcab4e78891be79a5009c060730740 GIT binary patch literal 396 zcmb7=y$ZrW5QM*4@Et; di@!Ny?NsSP=T<2;;~j7g&lR1ci9CtDdtVz9Gp7Im literal 0 HcmV?d00001 diff --git a/Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.sln b/Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.sln new file mode 100644 index 00000000..3a779328 --- /dev/null +++ b/Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectComposition_Effects", "DirectComposition_Effects.vcxproj", "{96A886BA-A020-29ED-93C2-3028B08CF096}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96A886BA-A020-29ED-93C2-3028B08CF096}.Debug|Win32.ActiveCfg = Debug|Win32 + {96A886BA-A020-29ED-93C2-3028B08CF096}.Debug|Win32.Build.0 = Debug|Win32 + {96A886BA-A020-29ED-93C2-3028B08CF096}.Release|Win32.ActiveCfg = Release|Win32 + {96A886BA-A020-29ED-93C2-3028B08CF096}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.vcxproj b/Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.vcxproj new file mode 100644 index 00000000..872e83b2 --- /dev/null +++ b/Samples/DirectCompositionEffects/cpp/DirectComposition_Effects.vcxproj @@ -0,0 +1,91 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + Win32Proj + + + + Application + true + v110 + + + Application + false + v110 + + + + + + + + + + + + + true + + + true + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Windows + uuid.lib;dcomp.lib;ole32.lib;d3d11.lib;d2d1.lib;windowscodecs.lib;%(AdditionalDependencies) + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + uuid.lib;dcomp.lib;ole32.lib;d3d11.lib;d2d1.lib;windowscodecs.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/DirectCompositionEffects/cpp/Main.cpp b/Samples/DirectCompositionEffects/cpp/Main.cpp new file mode 100644 index 00000000..3e98cafe --- /dev/null +++ b/Samples/DirectCompositionEffects/cpp/Main.cpp @@ -0,0 +1,15 @@ +// 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 "Application.h" + +int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR pszCmdLine, _In_ int iCmdShow) +{ + CApplication application(hInstance); + + return application.Run(); +} \ No newline at end of file diff --git a/Samples/DirectCompositionEffects/cpp/resource.h b/Samples/DirectCompositionEffects/cpp/resource.h new file mode 100644 index 00000000..9016ebaf --- /dev/null +++ b/Samples/DirectCompositionEffects/cpp/resource.h @@ -0,0 +1,26 @@ +// 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 + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DCompEffectsD2D.rc + +#define IDS_FONT_TYPEFACE 101 +#define IDS_FONT_HEIGHT_LOGO 102 +#define IDS_FONT_HEIGHT_TITLE 103 +#define IDS_FONT_HEIGHT_DESCRIPTION 104 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Samples/DirectCompositionLayeredChildWindow/README.md b/Samples/DirectCompositionLayeredChildWindow/README.md new file mode 100644 index 00000000..d93b7978 --- /dev/null +++ b/Samples/DirectCompositionLayeredChildWindow/README.md @@ -0,0 +1,60 @@ +DirectComposition layered child window sample +============================================= + +This sample demonstrates how to use the Microsoft DirectComposition API to animate the bitmap of a layered child window.It consists of a simple video player that lets you apply animated 2-D transforms to the video window as a video plays. + +Specifically, this sample shows how to: + +- Create layered child windows by applying the **WS\_EX\_LAYERED** extended window style +- Animate layered child windows and apply animated 2-D transforms (translate, rotate, skew, and scale) +- Use the window cloaking feature to hide a layered child window's "real" window bitmap while DirectComposition animates the visual representation of the window + +**Warning** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU) and won't compile in Microsoft Visual Studio Express 2013 for Windows. + +**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample! + +To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696). + +To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697). + +Related topics +-------------- + +[Animation](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437348) + +[How to animate the bitmap of a layered child window](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437378) + +Related technologies +-------------------- + +[DirectComposition](http://msdn.microsoft.com/en-us/library/windows/desktop/hh437371) + +Operating system requirements +----------------------------- + +Client + +Windows 8.1 + +Server + +Windows Server 2012 R2 + +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. Go to the cpp directory and double-click the Visual Studio Solution (.sln) file. +3. Press F6 or use **Build** \> **Build Solution** to build the sample. + +Run the sample +-------------- + +To run this sample after building it, use Windows Explorer to go to the installation folder for this sample and run DirectComposition\_LayeredChildWindow.exe from the *\*\\DirectComposition layered child window sample\\C++\\Debug folder. + +To run this sample from Microsoft Visual Studio, press the F5 key to run with debugging enabled, or Ctrl+F5 to run without debugging enabled. Alternatively, select **Start Debugging** or **Start Without Debugging** from the **Debug** menu. + +To see this sample in action, you need to load a media file for the sample to play in its video window. You'll find a demo media file called vc1 in the *\*\\DirectComposition layered child window sample\\C++\\media folder. + diff --git a/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.cpp b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.cpp new file mode 100644 index 00000000..a20ac005 --- /dev/null +++ b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.cpp @@ -0,0 +1,1537 @@ +// 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 "DirectComposition_LayeredChildWindow.h" + +CApplication *CApplication::s_application = nullptr; +CComPtr CApplication::s_pPlayer = nullptr; // The MFPlay player object + +BOOL m_bHasVideo = FALSE; + +const float CApplication::s_fanimationTime = 6.0; // 6 seconds animation + +CApplication::CApplication(HINSTANCE instance) : + m_hInstance(instance), + m_bControlOn(TRUE), + m_hMainWindow(NULL), + m_hControlChildWindow(NULL), + m_hVideoChildWindow(NULL), + m_hTextChildWindow(NULL) +{ + s_application = this; +} + +CApplication::~CApplication() +{ + s_application = nullptr; +} + +// Provides the entry point to the application. +INT WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR, _In_ INT) +{ + CApplication application(hInstance); + return application.Run(); +} + +int CApplication::Run() +{ + int result = 0; + + if (SUCCEEDED(Initialize())) + { + result = EnterMessageLoop(); + } + + else + { + MessageBoxW(NULL, L"An error occuring when running the sample", NULL, MB_OK); + } + + Destroy(); + + return result; +} + +//------------------------------------------------------ +// Initialization +//------------------------------------------------------ + +HRESULT CApplication::Initialize() +{ + HRESULT hr = InitializeMainWindow(); + + if (SUCCEEDED(hr)) + { + hr = InitializeLayeredChildWindows(); + } + + if (SUCCEEDED(hr)) + { + hr = MoveLayeredChildWindows(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateD3D11Device(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompositionDevice(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompositionRenderTarget(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDCompositionVisualTree(); + } + + if (SUCCEEDED(hr)) + { + hr = CreateTransforms(); + } + + if (SUCCEEDED(hr)) + { + // Commit the batch. + hr = m_pDevice->Commit(); + } + + return hr; +} + +// Creates the main application window. +HRESULT CApplication::InitializeMainWindow() +{ + HRESULT hr = S_OK; + + // Register the window class. + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = m_hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = static_cast(GetStockObject(BLACK_BRUSH)); + wc.lpszClassName = "DirectComposition Window Class"; + + RegisterClassEx(&wc); + + // Creates the m_hMainWindow window. + m_hMainWindow = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, // Extended window style + wc.lpszClassName, // Name of window class + "DirectComposition Layered Child Window Sample", // Title-bar string + WS_OVERLAPPED | WS_SYSMENU, // Top-level window + CW_USEDEFAULT, // Horizontal position + CW_USEDEFAULT, // Vertical position + 1000, // Width + 700, // Height + NULL, // Parent + NULL, // Class menu + GetModuleHandle(NULL), // Handle to application instance + NULL // Window-creation data + ); + + if (!m_hMainWindow) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + ShowWindow(m_hMainWindow, SW_SHOWDEFAULT); + + WCHAR fontTypeface[32] = { 0 }; + + hr = !LoadStringW(m_hInstance, IDS_FONT_TYPEFACE, fontTypeface, ARRAYSIZE(fontTypeface)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + hr = StringCchCopyW(m_fontTypeface, ARRAYSIZE(m_fontTypeface), fontTypeface); + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontHeightLogo[32] = { 0 }; + + hr = !LoadStringW(m_hInstance, IDS_FONT_HEIGHT_LOGO, fontHeightLogo, ARRAYSIZE(fontHeightLogo)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + m_fontHeightLogo = _wtoi(fontHeightLogo); + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontHeightTitle[32] = { 0 }; + + hr = !LoadStringW(m_hInstance, IDS_FONT_HEIGHT_TITLE, fontHeightTitle, ARRAYSIZE(fontHeightTitle)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + m_fontHeightTitle = _wtoi(fontHeightTitle); + } + } + + if (SUCCEEDED(hr)) + { + WCHAR fontHeightDescription[32] = { 0 }; + + hr = !LoadStringW(m_hInstance, IDS_FONT_HEIGHT_DESCRIPTION, fontHeightDescription, ARRAYSIZE(fontHeightDescription)) ? E_FAIL : S_OK; + + if (SUCCEEDED(hr)) + { + m_fontHeightDescription = _wtoi(fontHeightDescription); + } + } + + return hr; +} + +// Creates the layered child windows. +HRESULT CApplication::InitializeLayeredChildWindows() +{ + HRESULT hr = S_OK; + + // Register the window class. + WNDCLASSEX wcex = {0}; + wcex.cbSize = sizeof(wcex); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WindowProc; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = static_cast(GetStockObject(BLACK_BRUSH)); + wcex.lpszClassName = "DirectCompositionChildWindow-Child"; + + RegisterClassEx(&wcex); + + // Create the playback control child window. + m_hControlChildWindow = CreateWindowEx(WS_EX_LAYERED, // Extended window style + wcex.lpszClassName, // Name of window class + NULL, // Title-bar string + WS_CHILD | WS_CLIPSIBLINGS, // Child window + 0, 0, 0, 0, // Window will be resized via MoveWindow + m_hMainWindow, // Parent + NULL, // Class menu + GetModuleHandle(NULL), // Handle to application instance + NULL); // Window-creation data + + if (!m_hControlChildWindow) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + SetLayeredWindowAttributes(m_hControlChildWindow, 0, 130, LWA_ALPHA); + + // Create the text child window. + m_hTextChildWindow = CreateWindowEx(WS_EX_LAYERED, + wcex.lpszClassName, + NULL, + WS_CHILD | WS_CLIPSIBLINGS, + 0, 0, 0, 0, + m_hMainWindow, + NULL, + GetModuleHandle(NULL), + NULL); + + if (!m_hTextChildWindow) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + SetLayeredWindowAttributes(m_hTextChildWindow, 0, 130, LWA_ALPHA); + + // Create the video child window. + m_hVideoChildWindow = CreateWindowEx(WS_EX_LAYERED, + wcex.lpszClassName, + NULL, + WS_CHILD | WS_CLIPSIBLINGS, + 0, 0, 0, 0, + m_hMainWindow, + NULL, + GetModuleHandle(NULL), + NULL); + + if (!m_hVideoChildWindow) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + // Enable visual styles for buttons. + InitCommonControls(); + + if (SUCCEEDED(hr)) + { + SetLayeredWindowAttributes(m_hVideoChildWindow, 0, 255, LWA_ALPHA); + + CloakWindow(TRUE, m_hVideoChildWindow); + + // Create Play/Stop button. + m_hwndButton[0] = CreateWindowEx(WS_EX_TOPMOST, + "BUTTON", + "Play/Stop", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 50, + 50, + 80, + 30, + m_hControlChildWindow, + (HMENU)ID_PLAYSTOP, + GetModuleHandle(NULL), + NULL); + + if (!m_hwndButton[0]) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + // Create Rotate button. + m_hwndButton[1] = CreateWindowEx(WS_EX_TOPMOST, + "BUTTON", + "Rotate", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 180, + 50, + 80, + 30, + m_hControlChildWindow, + (HMENU)ID_ROTATE, + GetModuleHandle(NULL), + NULL); + + if (!m_hwndButton[1]) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + // Create Scale button. + m_hwndButton[2] = CreateWindowEx(WS_EX_TOPMOST, + "BUTTON", + "Scale", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 310, + 50, + 80, + 30, + m_hControlChildWindow, + (HMENU)ID_SCALE, + GetModuleHandle(NULL), + NULL); + + if (!m_hwndButton[2]) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + // Create Skew button. + m_hwndButton[3] = CreateWindowEx(WS_EX_TOPMOST, + "BUTTON", + "Skew", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 440, + 50, + 80, + 30, + m_hControlChildWindow, + (HMENU)ID_SKEW, + GetModuleHandle(NULL), + NULL); + + if (!m_hwndButton[3]) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + ShowWindow(m_hControlChildWindow, SW_SHOWDEFAULT); + ShowWindow(m_hTextChildWindow, SW_SHOWDEFAULT); + ShowWindow(m_hVideoChildWindow, SW_SHOWDEFAULT); + } + + return hr; +} + +HRESULT CApplication::MoveLayeredChildWindows() +{ + HRESULT hr = S_OK; + + RECT rcClient; + UINT ichildX; // Position of the left side of the window + UINT ichildY; // Position of the top side of the window + UINT ichildcX; // Width of the window + UINT ichildcY; // Height of the window + + GetClientRect(m_hMainWindow, &rcClient); + + ichildX = rcClient.left; // Takes the value of the left side of the main window + ichildY = rcClient.bottom - 120; // Takes the value of 120 pixels above the bottom of the main window + ichildcX = rcClient.right; // Takes the value of the right side of the main window + ichildcY = 120; // Constant height of 120 pixels + + // Move the Control window to its location. + if (!MoveWindow(m_hControlChildWindow, // Window + ichildX, // New position of the left side of the window + ichildY, // New position of the top side of the window + ichildcX, // New width + ichildcY, // New height + TRUE)) // Repaint the window + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + // Move the Text window to its location. + if (!MoveWindow(m_hTextChildWindow, + ichildX, + 0, + ichildcX, + ichildcY, + TRUE)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + // Move the Video window to its location. + if(!MoveWindow(m_hVideoChildWindow, + ichildX, + rcClient.top, + ichildcX, + rcClient.bottom, + TRUE)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + return hr; +} + +HRESULT CApplication::CreateD3D11Device() +{ + HRESULT hr = S_OK; + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + }; + + D3D_FEATURE_LEVEL featureLevelSupported; + + for (int i = 0; i < sizeof(driverTypes) / sizeof(driverTypes[0]); ++i) + { + CComPtr d3d11Device; + CComPtr d3d11DeviceContext; + + hr = D3D11CreateDevice( + nullptr, + driverTypes[i], + NULL, + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + NULL, + 0, + D3D11_SDK_VERSION, + &d3d11Device, + &featureLevelSupported, + &d3d11DeviceContext); + + if (SUCCEEDED(hr)) + { + _d3d11Device = d3d11Device.Detach(); + _d3d11DeviceContext = d3d11DeviceContext.Detach(); + + break; + } + } + + return hr; +} + +HRESULT CApplication::CreateDCompositionDevice() +{ + HRESULT hr = (_d3d11Device == nullptr) ? E_UNEXPECTED : S_OK; + + CComPtr dxgiDevice; + + if (SUCCEEDED(hr)) + { + hr = _d3d11Device->QueryInterface(&dxgiDevice); + } + + if (SUCCEEDED(hr)) + { + hr = DCompositionCreateDevice(dxgiDevice, __uuidof(IDCompositionDevice), reinterpret_cast(&m_pDevice)); + } + + return hr; +} + +HRESULT CApplication::CreateDCompositionRenderTarget() +{ + HRESULT hr = ((m_pDevice == nullptr) || (m_hMainWindow == NULL)) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateTargetForHwnd(m_hMainWindow, TRUE, &m_pHwndRenderTarget); + } + + return hr; +} + +HRESULT CApplication::CreateDCompositionVisualTree() +{ + HRESULT hr = ((m_pDevice == nullptr) || (m_hMainWindow == NULL)) ? E_UNEXPECTED : S_OK; + + if (SUCCEEDED(hr)) + { + // Create the root visual. + hr = m_pDevice->CreateVisual(&m_pRootVisual); + } + + if (SUCCEEDED(hr)) + { + // Make the visual the root of the tree. + hr = m_pHwndRenderTarget->SetRoot(m_pRootVisual); + } + + if (SUCCEEDED(hr)) + { + // Create the control child visual. + hr = m_pDevice->CreateVisual(&m_pControlChildVisual); + } + + if (SUCCEEDED(hr)) + { + // Create the text child visual. + hr = m_pDevice->CreateVisual(&m_pTextChildVisual); + } + + if (SUCCEEDED(hr)) + { + // Create the Video child visual. + hr = m_pDevice->CreateVisual(&m_pVideoChildVisual); + } + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateSurfaceFromHwnd(m_hControlChildWindow, &m_pControlsurfaceTile); + } + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateSurfaceFromHwnd(m_hTextChildWindow, &m_pTextsurfaceTile); + } + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateSurfaceFromHwnd(m_hVideoChildWindow, &m_pVideosurfaceTile); + } + + if (SUCCEEDED(hr)) + { + // Set the content of the Control child visual. + hr = m_pControlChildVisual->SetContent(m_pControlsurfaceTile); + } + + if (SUCCEEDED(hr)) + { + // Set the content of the Text child visual. + hr = m_pTextChildVisual->SetContent(m_pTextsurfaceTile); + } + + if (SUCCEEDED(hr)) + { + // Set the content of the video child visual. + hr = m_pVideoChildVisual->SetContent(m_pVideosurfaceTile); + } + + if (SUCCEEDED(hr)) + { + // Add the video child visual to the visual tree. + hr = m_pRootVisual->AddVisual(m_pVideoChildVisual, TRUE, NULL); + } + + if (SUCCEEDED(hr)) + { + // Add the text child visual to the visual tree. + hr = m_pRootVisual->AddVisual(m_pTextChildVisual, TRUE, m_pVideoChildVisual); + } + + if (SUCCEEDED(hr)) + { + // Add the control child visual to the visual tree. + hr = m_pRootVisual->AddVisual(m_pControlChildVisual, TRUE, m_pTextChildVisual); + } + + return hr; +} + +HRESULT CApplication::CreateTransforms() +{ + RECT rcClient; + + GetClientRect(m_hMainWindow, &rcClient); + + // Create a translate transform for the control child visual. + HRESULT hr = m_pDevice->CreateTranslateTransform(&m_pControlTranslateTransform); + + if (SUCCEEDED(hr)) + { + // Set the offset of x-axis of the control child visual + hr = m_pControlChildVisual->SetOffsetX(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the offset of y-axis of the control child visual + hr = m_pControlChildVisual->SetOffsetY((float)rcClient.bottom - 120); + } + + if (SUCCEEDED(hr)) + { + // Set the offset of x-axis of control translate transform + hr = m_pControlTranslateTransform->SetOffsetX(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the offset of y-axis of control translate transform + hr = m_pControlTranslateTransform->SetOffsetY(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Apply translate transform to the control child visual. + hr = m_pControlChildVisual->SetTransform(m_pControlTranslateTransform); + } + + // Create a translate transform for the text child visual. + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateTranslateTransform(&m_pTextTranslateTransform); + } + + if (SUCCEEDED(hr)) + { + // Set the offset of x-axis of text translate transform + hr = m_pTextTranslateTransform->SetOffsetX(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the offset of y-axis of text translate transform + hr = m_pTextTranslateTransform->SetOffsetY(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Apply translate transform to the text child visual. + hr = m_pTextChildVisual->SetTransform(m_pTextTranslateTransform); + } + + //Create a transform group (rotate, scale, skew) for the video child visual + if (SUCCEEDED(hr)) + { + // Create a rotate transform. + hr = m_pDevice->CreateRotateTransform(&m_pRotateTransform); + } + + if (SUCCEEDED(hr)) + { + // Set the initial angle for rotation transform. + hr = m_pRotateTransform->SetAngle(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the center of x-axis for rotation transform. + hr = m_pRotateTransform->SetCenterX(rcClient.right / 2.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the center of y-axis for rotation transform. + hr = m_pRotateTransform->SetCenterY(rcClient.bottom/ 2.0f); + } + + if (SUCCEEDED(hr)) + { + // Create a scale transform. + hr = m_pDevice->CreateScaleTransform(&m_pScaleTransform); + } + + if (SUCCEEDED(hr)) + { + // Set the initial scale x-value for scale transform. + hr = m_pScaleTransform->SetScaleX(1.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the initial scale y-value for scale transform. + hr = m_pScaleTransform->SetScaleY(1.0f); + } + + + if (SUCCEEDED(hr)) + { + // Set the center of x-axis for scale transform. + hr = m_pScaleTransform->SetCenterX(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the center of y-axis for scale transform. + hr = m_pScaleTransform->SetCenterY(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Create a skew transform. + hr = m_pDevice->CreateSkewTransform(&m_pSkewTransform); + } + + if (SUCCEEDED(hr)) + { + // Set the initial horizontal angle for skew transform. + hr = m_pSkewTransform->SetAngleX(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the initial vertical angle for skew transform. + hr = m_pSkewTransform->SetAngleY(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the center of x-axis for skew transform. + hr = m_pSkewTransform->SetCenterX(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Set the center of y-axis for skew transform. + hr = m_pSkewTransform->SetCenterY(0.0f); + } + + if (SUCCEEDED(hr)) + { + // Create a transform group. + IDCompositionTransform *pTransformArray[] = { m_pRotateTransform, m_pScaleTransform, m_pSkewTransform }; + hr = m_pDevice->CreateTransformGroup(pTransformArray, 3, &m_pTransformGroup); + } + + if (SUCCEEDED(hr)) + { + // Apply transform group to the video child visual. + hr = m_pVideoChildVisual->SetTransform(m_pTransformGroup); + } + + return hr; +} + +//------------------------------------------------------ +// Direct Composition Transforms +//------------------------------------------------------ + +HRESULT CApplication::SetTranslation(float beginPositionX, float endPositionX, float beginPositionY, float endPositionY, float beginTime, float endTime, IDCompositionTranslateTransform *translateTransform) +{ + CComPtr offsetXAnimation; + + HRESULT hr = CreateTranslateAnimation(beginPositionX, endPositionX, beginTime, endTime, &offsetXAnimation); + + if (SUCCEEDED(hr)) + { + hr = translateTransform->SetOffsetX(offsetXAnimation); + } + + CComPtr offsetYAnimation; + + if (SUCCEEDED(hr)) + { + hr = CreateTranslateAnimation(beginPositionY, endPositionY, beginTime, endTime, &offsetYAnimation); + } + + if (SUCCEEDED(hr)) + { + hr = translateTransform->SetOffsetY(offsetYAnimation); + } + + return hr; +} + +HRESULT CApplication::OnRotate() +{ + HRESULT hr = SetRotation(360.0f, 0.0f, 3.0f, m_pRotateTransform); + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->Commit(); + } + + return hr; +} + +HRESULT CApplication::SetRotation(float rotationAngle, float beginTime, float endTime, IDCompositionRotateTransform *rotateTransform) +{ + CComPtr angleAnimation; + + HRESULT hr = CreateLinearAnimation(0.0f, rotationAngle, beginTime, endTime, &angleAnimation); + + if (SUCCEEDED(hr)) + { + hr = rotateTransform->SetAngle(angleAnimation); + } + + return hr; +} + +HRESULT CApplication::OnScale() +{ + HRESULT hr = SetScaling(1.0f, 1.0f, -0.1f, -0.1f, 0.0f, 2.0f, m_pScaleTransform); + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->Commit(); + } + + return hr; +} + +HRESULT CApplication::SetScaling(float beginScaleX, float beginScaleY, float endScaleX, float endScaleY, float beginTime, float endTime, IDCompositionScaleTransform *scaleTransform) +{ + CComPtr scaleAnimationX; + + HRESULT hr = CreateLinearAnimation(beginScaleX, endScaleX, beginTime, endTime, &scaleAnimationX); + + if (SUCCEEDED(hr)) + { + hr = scaleTransform->SetScaleX(scaleAnimationX); + } + + CComPtr scaleAnimationY; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(beginScaleY, endScaleY, beginTime, endTime, &scaleAnimationY); + } + + if (SUCCEEDED(hr)) + { + hr = scaleTransform->SetScaleY(scaleAnimationY); + } + + return hr; +} + +HRESULT CApplication::OnSkew() +{ + HRESULT hr = SetSkewing(90.0f, 0.0f, 0.0f, 2.0f, m_pSkewTransform); + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->Commit(); + } + + return hr; +} + +HRESULT CApplication::SetSkewing(float skewAngleX, float skewAngleY, float beginTime, float endTime, IDCompositionSkewTransform *skewTransform) +{ + CComPtr skewAnimationX; + + HRESULT hr = CreateLinearAnimation(0.0f, skewAngleX, beginTime, endTime, &skewAnimationX); + + if (SUCCEEDED(hr)) + { + hr = skewTransform->SetAngleX(skewAnimationX); + } + + CComPtr skewAnimationY; + + if (SUCCEEDED(hr)) + { + hr = CreateLinearAnimation(0.0f, skewAngleY, beginTime, endTime, &skewAnimationY); + } + + if (SUCCEEDED(hr)) + { + hr = skewTransform->SetAngleY(skewAnimationY); + } + + return hr; +} + +HRESULT CApplication::CreateLinearAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **linearAnimation) +{ + HRESULT hr = (linearAnimation == nullptr) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *linearAnimation = nullptr; + + hr = (m_pDevice == nullptr) ? E_UNEXPECTED : S_OK; + } + + CComPtr animation; + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateAnimation(&animation); + } + + // Ensures animation start value takes effect immediately + if (SUCCEEDED(hr)) + { + if (beginTime > 0.0) + { + hr = animation->AddCubic(0.0, beginValue, 0.0f, 0.0f, 0.0f); + } + } + + if (SUCCEEDED(hr)) + { + hr = animation->AddCubic(beginTime, beginValue, (endValue - beginValue) / (endTime - beginTime), 0.0f, 0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = animation->AddCubic(endTime, endValue, -(endValue - beginValue) / (endTime - beginTime), 0.0f, 0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = animation->End(2* endTime, beginValue); + } + + if (SUCCEEDED(hr)) + { + *linearAnimation = animation.Detach(); + } + + return hr; +} + +HRESULT CApplication::CreateTranslateAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **linearAnimation) +{ + HRESULT hr = (linearAnimation == nullptr) ? E_POINTER : S_OK; + + if (SUCCEEDED(hr)) + { + *linearAnimation = nullptr; + + hr = (m_pDevice == nullptr) ? E_UNEXPECTED : S_OK; + } + + CComPtr animation; + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->CreateAnimation(&animation); + } + + // Ensures animation start value takes effect immediately + if (SUCCEEDED(hr)) + { + if (beginTime > 0.0) + { + hr = animation->AddCubic(0.0, beginValue, 0.0f, 0.0f, 0.0f); + } + } + + if (SUCCEEDED(hr)) + { + hr = animation->AddCubic(beginTime, beginValue, (endValue - beginValue) / (endTime - beginTime), 0.0f, 0.0f); + } + + if (SUCCEEDED(hr)) + { + hr = animation->End(endTime, endValue); + } + + if (SUCCEEDED(hr)) + { + *linearAnimation = animation.Detach(); + } + + return hr; +} + +int CApplication::EnterMessageLoop() +{ + int result = 0; + + MSG msg = { 0 }; + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + result = static_cast(msg.wParam); + + return result; +} + +//------------------------------------------------------ +// In Action +//------------------------------------------------------ + +// Main window procedure +LRESULT CALLBACK CApplication::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + + switch (uMsg) + { + case WM_COMMAND: + result = s_application->OnCommand(wParam); + break; + + case WM_RBUTTONUP: + result = s_application->OnRightClick(); + break; + + case WM_TIMER: + result = s_application->OnTimer(); + break; + + case WM_PAINT: + result = s_application->OnPaint(hwnd); + break; + + case WM_CLOSE: + result = s_application->OnClose(hwnd); + break; + + case WM_DESTROY: + result = s_application->OnDestroy(hwnd); + break; + + default: + result = DefWindowProc(hwnd, uMsg, wParam, lParam); + } + + return result; +} + +// Handles the WM_COMMAND message. +HRESULT CApplication::OnCommand(int id) +{ + HRESULT hr = S_OK; + IDCompositionAnimation* pAnimation = NULL; + + switch (id) + { + case ID_ROTATE: + hr = s_application->OnRotate(); + break; + + case ID_SCALE: + hr = s_application->OnScale(); + break; + + case ID_SKEW: + hr = s_application->OnSkew(); + break; + + case ID_PLAYSTOP: + // Play/Stop the video. + if (!s_pPlayer) + { + PlayMediaFile(); + } + else + { + MFP_MEDIAPLAYER_STATE state = MFP_MEDIAPLAYER_STATE_EMPTY; + + hr = s_pPlayer->GetState(&state); + + if (SUCCEEDED(hr)) + { + if (state == MFP_MEDIAPLAYER_STATE_PAUSED || state == MFP_MEDIAPLAYER_STATE_STOPPED) + { + hr = s_pPlayer->Play(); + } + else if (state == MFP_MEDIAPLAYER_STATE_PLAYING) + { + hr = s_pPlayer->Pause(); + } + } + } + break; + } + + return hr; +} + +// Handles the WM_RBUTTONDOWN message. +HRESULT CApplication::OnRightClick() +{ + HRESULT hr = S_OK; + IDCompositionAnimation* pAnimation = NULL; + + if (m_bControlOn) + { + // Kill the timer. + KillTimer(m_hControlChildWindow, IDT_TIMER); + + // Animate the Control window. + // Adjust the opacity after the Control window is cloaked. + SetLayeredWindowAttributes(m_hControlChildWindow, 0, 130, LWA_ALPHA); + + // Cloak the Control window. + CloakWindow(TRUE, m_hControlChildWindow); + + // Hide the Control window. - Animating the control window offscreen + // Set the sliding in animation. + hr = SetTranslation(0.0f, 0.0f, 0.0f, 300.f, 0.0f, 2.0f, m_pControlTranslateTransform); + + if (SUCCEEDED(hr)) + { + // Animate the Text window. + // Cloak the Text window. + CloakWindow(TRUE, m_hTextChildWindow); + + // Hide the text window. - Animating the text window offscreen + // Set the sliding in animation. + hr = SetTranslation(0.0f, 0.0f, 0.0f, -300.f, 0.0f, 2.0f, m_pTextTranslateTransform); + } + + if (SUCCEEDED(hr)) + { + m_bControlOn = false; + } + } + else + { + // Animate the Control window. + // Show the Control window. - animating the control window on screen + + // Set the sliding out animation. + hr = SetTranslation(0.0f, 0.0f, 140.0f, 0.0f, 0.0f, 1.0f, m_pControlTranslateTransform); + + if (SUCCEEDED(hr)) + { + // Animate the Text window. + // Show the Text window. - animating the text window on screen + hr = SetTranslation(0.0f, 0.0f, -140.0f, 0.0f, 0.0f, 1.0f, m_pTextTranslateTransform); + } + + if (SUCCEEDED(hr)) + { + m_bControlOn = true; + + // Timer is used to dertermine DirectComposition end animation time. + // Kill and then set the timer. + KillTimer(m_hControlChildWindow, IDT_TIMER); + SetTimer(m_hControlChildWindow, IDT_TIMER, UINT((1000.0f/s_fanimationTime)*s_fanimationTime), (TIMERPROC)NULL); + } + } + + if (SUCCEEDED(hr)) + { + hr = m_pDevice->Commit(); + } + + return hr; +} + +// Handles the WM_TIMER message. +HRESULT CApplication::OnTimer() +{ + // Adjust the opacity after the Control window is uncloaked. + SetLayeredWindowAttributes(m_hControlChildWindow, 0, 130, LWA_ALPHA); + + // Uncloak the Control window + CloakWindow(FALSE, m_hControlChildWindow); + + // Uncloak the Text window + CloakWindow(FALSE, m_hTextChildWindow); + + // Kill the timer. + KillTimer(m_hControlChildWindow, IDT_TIMER); + + return S_OK; +} + +// Handles the WM_PAINT message. +HRESULT CApplication::OnPaint(HWND hwnd) +{ + HDC hdc; + PAINTSTRUCT ps; + HRESULT hr = S_OK; + + hdc = BeginPaint(hwnd, &ps); + + if (hwnd == m_hControlChildWindow) + { + // Paint the control window. + RECT rcClient; + + // Get the dimensions of the control window. + if (!GetClientRect(m_hControlChildWindow, &rcClient)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + // Drawtext on the control window. + HFONT hinstruction = CreateFontW(m_fontHeightDescription, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, m_fontTypeface); // Instruction Font and Size (Same as Description's) + if (hinstruction != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, hinstruction)); + + rcClient.top = 50; + rcClient.left = 650; + + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + + DrawTextW(hdc, L"Right-click if you want to hide me.", -1, &rcClient, DT_WORDBREAK | DT_CENTER); + + SelectObject(hdc, hOldFont); + + DeleteObject(hinstruction); + } + } + else if (hwnd == m_hTextChildWindow) + { + // Paint the text window. + RECT rcClient; + + // Get the dimensions of the main window. + GetClientRect(m_hMainWindow, &rcClient); + + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + + // Logo + HFONT hlogo = CreateFontW(m_fontHeightLogo, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, m_fontTypeface); // Logo Font and Size + if (hlogo != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, hlogo)); + + SetBkMode(hdc, TRANSPARENT); + + rcClient.top = 10; + rcClient.left = 30; + + DrawTextW(hdc, L"Windows samples", -1, &rcClient, DT_WORDBREAK); + + SelectObject(hdc, hOldFont); + + DeleteObject(hlogo); + } + + // Title + HFONT htitle = CreateFontW(m_fontHeightTitle, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, m_fontTypeface); // Title Font and Size + if (htitle != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, htitle)); + + rcClient.top = 25; + rcClient.left = 30; + + DrawTextW(hdc, L"DirectComposition Layered Child Window Sample", -1, &rcClient, DT_WORDBREAK); + + SelectObject(hdc, hOldFont); + + DeleteObject(htitle); + } + + // Description + HFONT hdescription = CreateFontW(m_fontHeightDescription, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, m_fontTypeface); // Description Font and Size + if (hdescription != NULL) + { + HFONT hOldFont = static_cast(SelectObject(hdc, hdescription)); + + rcClient.top = 90; + rcClient.left = 30; + + DrawTextW(hdc, L"This sample shows DirectComposition applying Transform properties on layered child windows based content.", -1, &rcClient, DT_WORDBREAK); + + SelectObject(hdc, hOldFont); + + DeleteObject(hdescription); + } + } + else + { + // Paint the video window. + if (s_pPlayer && m_bHasVideo) + { + // Playback has started and there is video. + // Do not draw the window background, because the video + // frame fills the entire client area. + s_pPlayer->UpdateVideo(); + } + } + + EndPaint(hwnd, &ps); + return hr; +} + +// Handles the WM_CLOSE message. +LRESULT CApplication::OnClose(HWND /*hwnd*/) +{ + // Close the MFPlay player object. + if (s_pPlayer) + { + s_pPlayer->Shutdown(); + s_pPlayer = nullptr; + } + + // Close the application callback object. + if (s_pPlayerCB) + { + s_pPlayerCB = nullptr; + } + + // Destroy the main window. + DestroyWindow(m_hMainWindow); + + return 0; +} + +// Handles the WM_DESTROY message. +LRESULT CApplication::OnDestroy(HWND /*hwnd*/) +{ + PostQuitMessage(0); + + return 0; +} + +//------------------------------------------------------ +// Destroy +//------------------------------------------------------ + +VOID CApplication::Destroy() +{ + DestroyTransforms(); + DestroyMainWindow(); + DestroyLayeredChildWindows(); + DestroyDCompositionVisualTree(); + DestroyDCompositionRenderTarget(); + DestroyDCompositionDevice(); + DestroyD3D11Device(); + CoUninitialize(); +} + +VOID CApplication::DestroyTransforms() +{ + m_pControlTranslateTransform = nullptr; + + m_pTextTranslateTransform = nullptr; + + m_pRotateTransform = nullptr; + + m_pSkewTransform = nullptr; + + m_pScaleTransform = nullptr; +} + +VOID CApplication::DestroyMainWindow() +{ + if (m_hMainWindow != NULL) + { + DestroyWindow(m_hMainWindow); + m_hMainWindow = NULL; + } +} + +VOID CApplication::DestroyLayeredChildWindows() +{ + if (m_hControlChildWindow != NULL) + { + DestroyWindow(m_hControlChildWindow); + m_hControlChildWindow = NULL; + } + + if (m_hTextChildWindow != NULL) + { + DestroyWindow(m_hTextChildWindow); + m_hTextChildWindow = NULL; + } + + if (m_hVideoChildWindow != NULL) + { + DestroyWindow(m_hVideoChildWindow); + m_hVideoChildWindow = NULL; + } +} + +VOID CApplication::DestroyDCompositionVisualTree() +{ + m_pControlsurfaceTile = nullptr; + + m_pTextsurfaceTile = nullptr; + + m_pVideosurfaceTile = nullptr; +} + +VOID CApplication::DestroyDCompositionRenderTarget() +{ + m_pHwndRenderTarget = nullptr; +} + +VOID CApplication::DestroyDCompositionDevice() +{ + m_pDevice = nullptr; +} + +VOID CApplication::DestroyD3D11Device() +{ + _d3d11DeviceContext = nullptr; + _d3d11Device = nullptr; +} + +// Cloaking removes the window from the view, +// while still allowing it to retain and update its bitmap. +HRESULT CApplication::CloakWindow(BOOL cloakHwnd, HWND hwnd) +{ + HRESULT hr = DwmSetWindowAttribute(hwnd, DWMWA_CLOAK, &cloakHwnd, sizeof(cloakHwnd)); + + return hr; +} + +// Show error messages. +void CApplication::ShowErrorMessage(PCWSTR format, HRESULT hrErr) +{ + WCHAR msg[MAX_PATH]; + HRESULT hr = StringCbPrintf((STRSAFE_LPSTR)msg, sizeof(msg), (STRSAFE_LPCSTR)(L"%s (hr=0x%08X)"), format, hrErr); + + if (SUCCEEDED(hr)) + { + MessageBox(NULL, (LPCSTR)msg, NULL, MB_ICONERROR); + } +} + +// Plays a media file, using the IMFPMediaPlayer interface. +HRESULT CApplication::PlayMediaFile() +{ + HRESULT hr = S_OK; + + // Create the MFPlayer object. + if (s_pPlayer == nullptr) + { + s_pPlayerCB = new MediaPlayerCallback(); + + if (s_pPlayerCB == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + hr = MFPCreateMediaPlayer(NULL, + FALSE, // Start playback automatically? + MFP_OPTION_NONE, // Flags + s_pPlayerCB, // Callback pointer + m_hVideoChildWindow, // Video window + &s_pPlayer + ); + } + + // Create a new media item for this URL. + if (SUCCEEDED(hr)) + { + hr = s_pPlayer->CreateMediaItemFromURL(L"media/TallShip-medium.wmv", FALSE, 0, NULL); + } + + // The CreateMediaItemFromURL method completes asynchronously. + // The application will receive an MFP_EVENT_TYPE_MEDIAITEM_CREATED + // event. See MediaPlayerCallback::OnMediaPlayerEvent(). + return hr; +} + +// Called when the IMFPMediaPlayer::CreateMediaItemFromURL method +// completes. +void CApplication::OnMediaItemCreated(MFP_MEDIAITEM_CREATED_EVENT *pEvent) +{ + HRESULT hr = S_OK; + + // The media item was created successfully. + if (s_pPlayer) + { + BOOL bHasVideo = FALSE, bIsSelected = FALSE; + + // Check if the media item contains video. + hr = pEvent->pMediaItem->HasVideo(&bHasVideo, &bIsSelected); + + if (FAILED(hr)) + { + ShowErrorMessage(L"Error playing this file.", hr); + } + + m_bHasVideo = bHasVideo && bIsSelected; + + // Set the media item on the player. This method completes asynchronously. + s_pPlayer->SetMediaItem(pEvent->pMediaItem); + } +} + +// Called when the IMFPMediaPlayer::SetMediaItem method completes. +void CApplication::OnMediaItemSet(MFP_MEDIAITEM_SET_EVENT * /*pEvent*/) +{ + HRESULT hr = s_pPlayer->Play(); + + if (FAILED(hr)) + { + ShowErrorMessage(L"IMFPMediaPlayer::Play failed.", hr); + } +} + +// Implements IMFPMediaPlayerCallback::OnMediaPlayerEvent. +// This callback method handles events from the MFPlay object. +void MediaPlayerCallback::OnMediaPlayerEvent(_In_ MFP_EVENT_HEADER * pEventHeader) +{ + if (FAILED(pEventHeader->hrEvent)) + { + CApplication::ShowErrorMessage(L"Playback error", pEventHeader->hrEvent); + return; + } + + switch (pEventHeader->eEventType) + { + case MFP_EVENT_TYPE_MEDIAITEM_CREATED: + CApplication::OnMediaItemCreated(MFP_GET_MEDIAITEM_CREATED_EVENT(pEventHeader)); + break; + + case MFP_EVENT_TYPE_MEDIAITEM_SET: + CApplication::OnMediaItemSet(MFP_GET_MEDIAITEM_SET_EVENT(pEventHeader)); + break; + } +} diff --git a/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.h b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.h new file mode 100644 index 00000000..1f69517f --- /dev/null +++ b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.h @@ -0,0 +1,206 @@ +// 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 +#include +#include +#include +#include + +#include +#include +#include "resource.h" + +#include +#include + +class CApplication +{ + public: + static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + static VOID ShowErrorMessage(PCWSTR format, HRESULT hr); + static VOID OnMediaItemCreated(MFP_MEDIAITEM_CREATED_EVENT *pEvent); + static VOID OnMediaItemSet(MFP_MEDIAITEM_SET_EVENT *pEvent); + + public: + explicit CApplication(HINSTANCE hInstance); + ~CApplication(); + + int Run(); + + private: + CApplication(const CApplication &); + + private: + HRESULT PlayMediaFile(); + + HRESULT Initialize(); + + // Initialize main window functions including layered child window + HRESULT InitializeMainWindow(); + HRESULT InitializeLayeredChildWindows(); + HRESULT MoveLayeredChildWindows(); + + // Initialize Direct Composition and D3D functions + HRESULT CreateD3D11Device(); + HRESULT CreateDCompositionDevice(); + HRESULT CreateDCompositionRenderTarget(); + HRESULT CreateDCompositionVisualTree(); + HRESULT CreateTransforms(); + + // Window message handlers + LRESULT OnClose(HWND hwnd); + HRESULT OnCommand(int id); + LRESULT OnDestroy(HWND hwnd); + HRESULT OnPaint(HWND hwnd); + HRESULT OnRightClick(); + HRESULT OnTimer(); + + // Direct Composition Transforms + HRESULT OnRotate(); + HRESULT OnScale(); + HRESULT OnSkew(); + + HRESULT SetRotation(float beginRotationAngle, float beginTime, float endTime, IDCompositionRotateTransform *rotateTransform); + HRESULT SetScaling(float beginScaleX, float beginScaleY, float endScaleX, float endScaleY, float beginTime, float endTime, IDCompositionScaleTransform *scaleTransform); + HRESULT SetSkewing(float skewAngleX, float skewAngleY, float beginTime, float endTime, IDCompositionSkewTransform *skewTransform); + HRESULT SetTranslation(float beginPositionX, float endPositionX, float beginPositionY, float endPositionY, float beginTime, float endTime, IDCompositionTranslateTransform *translateTransform); + + HRESULT CreateLinearAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **linearAnimation); + HRESULT CreateTranslateAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **linearAnimation); + + // Cloak/uncloak windows + HRESULT CloakWindow(BOOL cloakHwnd, HWND hwnd); + + int EnterMessageLoop(); + + // Destroy + VOID Destroy(); + VOID DestroyMainWindow(); + VOID DestroyLayeredChildWindows(); + VOID DestroyDCompositionVisualTree(); + VOID DestroyDCompositionRenderTarget(); + VOID DestroyDCompositionDevice(); + VOID DestroyD3D11Device(); + VOID DestroyTransforms(); + + private: + static CApplication *s_application; + static CComPtr s_pPlayer; + + static const float s_fanimationTime; + + HINSTANCE m_hInstance; + + WCHAR m_fontTypeface[32]; + int m_fontHeightLogo; + int m_fontHeightTitle; + int m_fontHeightDescription; + + HWND m_hMainWindow; // Main window + HWND m_hControlChildWindow; // Control window + HWND m_hVideoChildWindow; // Video window + HWND m_hTextChildWindow; // Text window + HWND m_hwndButton[4]; // Control buttons + + CComPtr _d3d11Device; + CComPtr _d3d11DeviceContext; + + CComPtr m_pDevice; + CComPtr m_pHwndRenderTarget; + CComPtr m_pRootVisual; + CComPtr m_pControlChildVisual; + CComPtr m_pTextChildVisual; + CComPtr m_pVideoChildVisual; + CComPtr m_pControlsurfaceTile; + CComPtr m_pTextsurfaceTile; + CComPtr m_pVideosurfaceTile; + + CComPtr m_pControlTranslateTransform; + CComPtr m_pTextTranslateTransform; + CComPtr m_pTransformGroup; + + CComPtr m_pRotateTransform; + CComPtr m_pSkewTransform; + CComPtr m_pScaleTransform; + + //MediaPlayerCallBack + BOOL m_bControlOn; + CComPtr s_pPlayerCB; + + enum + { + ID_PLAYSTOP, // Play/Stop button ID + ID_ROTATE, // Rotate button ID + ID_SCALE, // Scale button ID + ID_SKEW, // Skew button ID + IDT_TIMER // Timer ID + }; +}; + +// Implements the callback interface for MFPlay events. +class MediaPlayerCallback : public IMFPMediaPlayerCallback +{ + private: + + long m_cRef; // Reference count + + public: + + MediaPlayerCallback() : m_cRef(1) + { + } + + STDMETHODIMP QueryInterface(REFIID riid, void** ppv) + { + HRESULT hr = S_OK; + *ppv = NULL; + + if (riid == __uuidof(IMFPMediaPlayerCallback)) + { + *ppv = static_cast(this); + } + + else if (riid == __uuidof(IUnknown)) + { + *ppv = static_cast(this); + } + + else + { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr)) + { + AddRef(); + } + + return hr; + } + + STDMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&m_cRef); + } + + STDMETHODIMP_(ULONG) Release() + { + ULONG count = InterlockedDecrement(&m_cRef); + + if (count == 0) + { + delete this; + } + + return count; + } + + // IMFPMediaPlayerCallback methods + void STDMETHODCALLTYPE OnMediaPlayerEvent(_In_ MFP_EVENT_HEADER *pEventHeader); +}; \ No newline at end of file diff --git a/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.manifest b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.manifest new file mode 100644 index 00000000..f2e7273b --- /dev/null +++ b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.rc b/Samples/DirectCompositionLayeredChildWindow/cpp/DirectComposition_LayeredChildWindow.rc new file mode 100644 index 0000000000000000000000000000000000000000..ff88dfd143298a087b24f936758b6f7897c2b399 GIT binary patch literal 396 zcmb7=y$ZrW5QM*4@Et + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + + + Win32Proj + + + + Application + true + v110 + + + Application + false + v110 + + + + + + + + + + + + + true + $(LibraryPath) + C:\Program Files\Windows Kits\8.0\Lib\win8\um\x86;$(IncludePath) + + + true + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Windows + ComCtl32.lib;ntdll.lib;rpcrt4.lib;user32.lib;shell32.lib;kernel32.lib;d3d11.lib;gdi32.lib;uuid.lib;dcomp.lib;mfplay.lib;mf.lib;mfplat.lib;Mfuuid.lib;ole32.lib;oleaut32.lib;Dwmapi.lib;shlwapi.lib;%(AdditionalDependencies) + + + DirectComposition_LayeredChildWindow.manifest + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + ComCtl32.lib;ntdll.lib;rpcrt4.lib;user32.lib;shell32.lib;kernel32.lib;d3d11.lib;gdi32.lib;uuid.lib;dcomp.lib;mfplay.lib;mf.lib;mfplat.lib;Mfuuid.lib;ole32.lib;oleaut32.lib;Dwmapi.lib;shlwapi.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + Designer + + + + + + \ No newline at end of file diff --git a/Samples/DirectCompositionLayeredChildWindow/cpp/media/TallShip-medium.wmv b/Samples/DirectCompositionLayeredChildWindow/cpp/media/TallShip-medium.wmv new file mode 100644 index 0000000000000000000000000000000000000000..170e5bfc00935cb6b11f1d57e497a6cecb593616 GIT binary patch literal 4141440 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%0D^@z=_4%jWp922KXejH8 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 Ql2+>&Q;s-cEfmQzA8eswEbJS(izXzu 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

q-?Ci!_t1$ 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 z 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≺j~A>PPc=Y;*JAv+ah?7H%?(0hod~IiIW5+~ZOh#z=%VLTxM^?b+!EAgDvd#>%;zxm-at_dWxivsn?q5q;OUD_XFN zHxG78N{+I+8j^WL%d1TNVH?|4{r7i43qMRWx`&9eBmlx>2w=`)Vls0w_HLsK0(epb z3M7CnbC`L*2X;Rw-wAsll>F_xVzxkhfO@OHKMsE^ay(WBpnnADMN;WU@fXT7Y*EClKK!yOCLA(o-@Ykel!) zf$+&`eiAM*;%7zT`7@z7{>U_3qalRNT49cACi@Oy=)UF=;IMyp8ifG>>Ho9aQ5ax6 zE68CHto)d|J{-;e0rqtLix@HGNt4~*PlA9Z3uaeV!@eP|0k3_f(z|X}z{9%QxvBwO zz9eL&G!4jMRwrT8gSPUjM^h;Ma>F!X9>7T9=T=64yK$yZmV}&GO>NzIS342uYr9A| zQC;X$Td246Xgt@KIB)HJ@!u#Dm+JZ}MgCAGT(=8F&)vbhH05~I^txS1_}_(hGlo^q zko_m=wT2|bXtUkHN7msP=H{D}%T&xk!%lL&jiE+7%M5&-KSi5OL6@teokW^}bl?l)RoAnf<$j=BBOJ`F*bg zzUuvTZK$=PirFwFxNGvNyB#hDLnRPvhz_^2IFIK}-BNZyJ);)Qrt(aW!H*h{z-(fV z=amM3vqYiwN}x;c+!}DQ7FjBac3V@`z<>8sO)v<}-^h=@$-gb}nEuq2@b`xFB_qbf z2G3sva$++-amqtm{3uPiosx6^=`M0y`cd>L>r*~lz8Svl4Zht?Umvy>zLlt(7P=J* z#Go06tqtFhiZ?sS7Zo2ypCri%wi=hdf}64nAZ_#YDM1^QFga17fWsrwITjSKR>-ez zfZs9ks(Ct!3lmWg=Rt*_S=z)pnJ?#Te;XoQ7N?QgC0QTK*WKolYx(I9VD`I74b5|F z?Uc`#XF`_WuJz1^tvR(5--BA{^_XS{^|o0E$i$ z^32!>Y9G8&>%OO}=W?Ow-znB>4rpV1gTIXm=+#u3OKCr?yB+84FuoyC7k)weU(IM@ zEyXZ@pEep*Gb&bl_7smqy~&3)9na2BH)6@cPjKePe>W5xKciPKVC&b~rQzxVl<{YK z)OLhn@^wnNG#j_A#hg7UnbD!i0yHnVo*>GV6=X-9!+IQVpxg{%wi{ZFo+#aV5FePR`)^yOb8;*oOFR>QH=}w=`m(uN-uv z=PK|>&vUmyG-*#Ah*0!1Pyj8za`74-Xzz~d-<^(MY$Jngyd~82X4QZ=Hu6)0Sp-3(CO0fsuRz7e6^nae22$_ zNVC6%qnMp_z(mq&vDAlOL*!)M$*mJ^>c%eiKI@2m7<_IFJRfdDQXIjhvfNzX=zwrEfA z-mX}X#FrPj!R-hn;JV+Fcm0IA-^C5Nzv)Y$0w9BrS8qMLBfq8Rn&pq;FC83&So9Ga zYG7`rc2SEVW8|J(js>f7{`JxJ7OxkORxES(!5T`?94>q}RG&%fnKUxI(l5h`*Y^cg zjWa(y1{@nco}oYkLoYpiTnSg>J--4i>&QssrXA$IQpu;=gM@nl=~QdEZlFyxP@52( z`5PSm&om#Q++F+s+}#nXlPG7WUxSC<3Kn|V-+C~O?rquyqA=O}lZeCGiCbT1RhqK# zCiJICoQ&Bdf8Fz@yi?YU*el-Xz0WxFPs_(OUX6m6twFEj;AX4<7X)vO4=4n53vqFb zJSG8_{@5lTIA7R?yd|Z`u&HsnYGp8#+?AvPw?iF37XsJdWxao~RJJut`Sfw3syM+_ zf1BYV6aXT5v4kFTf612B^zu{arOpLqE%XCuY5g6fT1Iu~U+Ao;`@v_g0Z=k4t^AiT zmRG+WPu%xPIz*wkD7L`pVP+xhcxWM`37K!?03_f^W|^EefV=ljHGBOOwcMZiIevm zU9=k%28!;(dwXKTXffpNst{3Gwlbp{_Ad*yPWz4h3PA+`UI{i{BO7KIzdbhAOAMX_p%pJ4fbLKxv01g9O`alg3~I$q-Gean5*7OGpD~CQ*fY4 zmZ%{h%NT(kna!H+w-D`p@{4&wk0L1pViH(FZnV#eo4c!r^XjK?DVtC4ou&5h5Uo+N zE-l{d8>7|cZXnq=9#GLNRktP>r@`*|qdOXpks;yK#GvuSk2&z@oY+vC|A*(10yo;^ zsp(oi)z~}nI1&Hl3v~>i=9gv8{e$=4d3Asq(AbD#l`T?T;OPIP6)VekmmooQJnSTxF zswx1-9(Ua{t1)T=#qV+`AA6`kNpK0Lqgys|zRjORLjf%ILt4nMl(8SRsHVW;P&RkD zVPs-m3GdZ%ZVvBl38Izqx8_q6mWBc$OIzXn)=Abfc$Oi3g)SB#eE(%D#`(VHRH0e( z%J@;rjN}0G-6Hadig3E(3DRO`Eu$D2bjeOK|Dh`t2kNu-c7+sA^N4OKbP0OInh|GD zM@P+-q4BkBG{9v}ozyMEiy_iuQDDzgJ?_d*L4_$w!@w+QEY8;_|0FZQ#-B&05MNEE{l*eB~Ydq<-X=v8hUXjm+KVb@4STT-*2py2a=wNK-}P zp{DHEzlcZ)+hKHrh+)&B6N0foXz z82+l|@Z|J~qbmMLg~{2M9diz<`)%C(jJKU9GRHHxWCP>tdW{uJB?nAA^V`RaH-r-5 zj7Kb@f1GdgP!K1tU+2$57nFSc4TyZT8=N?c;@-t>z7ri`b(|z3%p3P8863}K@_9^<7WidoV5E`5N=gI#G{@f90yVY8pD2P)p*GiHOl0Z_EtKiDeh> zwyFP2wJ2bA=8kf80zdiR+*wy#DXTDr?B~~`oU-HTH?qMN23Z8?l9j1bawvf?eBa?b zSoG+sHRj5oVESW9vl z`H(U=`I{>Hcuj1~oB&Hv^5iQHm9-8NwZNO!O z_qB-^D}Y3aE#Y=d9bdq7o!0qQE1HFQR&#(bq99R1c00iZ<2J~L6$cI^i$gLM_jO1R5*K}Ns z^A3Qy=P(FyLA{EFn8uOeJN?l2bKqcWfZ^-+*ZLPx+zkMJ`*8fTQw{HpCICQJ1+bNi zi7P_wpiP_)BMn9)=Hz`lEV|kqC=OVF3N1PZq71p1$!_=#;Jc&a5d-f3JF1SxLvXMh zD(7;Sv$%*?%Ein}vzzu5^L?YpiqpWDRMJ;+#`vXNgx+09G_mzPvkA{oiLP!92=m!? z9G@dz=)l0V_4gpBOkq$>D0F?i@)@YSd!o1Xz+su9~R9+u5XWut^ZHC9XlM|+O z#!@U0Bs~-@{n6J_Qln2QymfbpIxPqW3bJOP;HZCh{uIT*KtuQcTR>0oK=3(=B3U%D z47jmB&>yV6)iuu~MgLAQMbO#>}S%%RnSQ4g53Hbg{3$ zes<~T{_5isg>&)F+<9jbiRg2Ph_HIcRfs<58-rh#7#gG8Lf@-qt{%pfLjGClak^X; zUFIKk_LXij@DFMv!1g=dHc1_7HN!}-k@czj`~A*Fz;Pc21G`J!YS6ZEMov(lN5tZ0 zUe2+`P^fQT*;;)8k@HuJ_1B=yKcfuY&B>5eVG5;vfL?@#Z;LzfNBs3v6D%!w+3gtX zm;QU$I@iT&0}b*w@A-XQ?A0$U1N1W@O;xlh|ZO*7?rPk&84<O$hD6F}?mvTF-7Q3SKe6DxFf!nbEXy_2mxOqf@$IY?`tSnCzGW@RM$GLy$N+KH zPq_)(Bz$)T&A5v^kd5|R2qB{$yt$-z+b&LHtV8mwvG)*hJfr>lyUMqOz5TU9;+$i{ zyh(vS487V9FJXh}e&r#X0Yh_PpQrBsK4+@!@{%^_7G5VLZz?z#Qc3M6?75&dPhUUY zO~Z(xxt}#T#9Bnum9MIG`g1=ma_i;fI+Pr(k%Nk-mSCZd)ZJ;cSBWED#DYX)J{yOteq>J zS2tk1*ZRWqMyoSL;1F^?dz0k%EfeKdsa1^fD92mZP$rWb8ct~)9zA`xh`~{4?%D{DaCSFBIhSCEzB(j_;y@N?iMXe zu;g1*q%$QjzTKCDG(6)W{Be~g^FkX9?rwe}SBT^ugCUds{Pw?(dW#Z%3POHryQhmt zzHhrHp=$ZNW{EduS-y>!p+~-S?XUHDUaC=y@i<8V|5Pq!NaBwv`hwVDH*we) zeLI+0G@Jz+XXCFTpZdTP99KWu44hgJOla{TAZ|Kfx}U_-40)#KAY7seD&=!5@J z)>#&!`wyMdfo>hh>Q0fmOfv;teR`u_JlWt`exg!5rM`K)b&yE1A{Uqi|>Xv2N|K@mLd z3kLNhah-Z#)~ZB#;PD46ZvZ~7)LJ)O9qLdm%teV4^TQ#kj-txOM_Rid-8HILKEg+4 z4fGiTC9a<7NxvWY{qf;4=tmS1`IwPB=$qbdJu^Di8VDcK!KeCjuiayN0K3eDiKBrK z6cbQWGkR%nF|mBvS(=hLD&@oVpe|xkNK5y0v8Yq`_wA3@p1$BDS29^wtduS{51*?y z?0V*rId{C`>Vw)0D)>GLxd3nJ?zd&{Eg^fa*m@*XbDcw|@KyTb__}Dx;ze=Koz8Y) z-?qP>u_Ct2RV@Pp0$-AuY&b233g)_=8Bk-r7N6+gWY=~~m7=e5XTo>&FOuWGSojPj zGgYq(@ssU~{8qK$dgdcQ6h{w06nFBf^RS22evvpd+NKr>f+%k3?mKpKWBu@-QS7&G z09GD!YTqB;U{tv~XbL5@l>e#d0P4H-R7?Zs{qUAQ$0d{3b^e%m$H4IwC*jHW_nT5V z^VxETrNjO#?tZhe^BR=qrUe$uGJ4F$n^Ol+cv!#`52ic|Y7F0;rx15dPl48`qA$Yw z6je~aY!C&uh$Ya7eL69Ak^TL zDfTWJ`iP+}UL`aE-IMC@_MR>?w@xRzCqsKS&-stM$Kh!YU9>yh^{@Kf@bu04?Cu#) z@h_V5TuC#o0Ku2jU+AWXjgPh|v1h_(>9jaq6Fza4(q$6IfJJ}reZuRV!hydZb}_xl zpIyf!T*Y8`q;}KXS){vjA0YF<&z0EDgnLGH+HX!V+wQRsXfkF9?o99|b_`(RJdPYi zGx>xSNk-Q0Qg?!lN*QBw(dAH;_iwe`ZvEIadp4EqZdiU}XS$C}Od9zg$nVH5?xjsn zkAc@sFm?V2!Y`r(%T*4uy^3?<)4Ar#T+_A>TwmUo6cGc%nr!%2j+^;4L)PE)@P2u*ycOHmjIHy_f8D-RWUw#lE9& zVtVE$fMX{Y_`F)f2D{VY&X>$msj);}jg6I0!OSF={@YO!dy4&oU2^ohz#H)NCl;C{A&IEtb%5e&0p&ej&w_4FHv>do672 zzDV+IEPE}B?jX}+Q8)QA)^Q713Hd^D9@+E@ANX4A&d$?xFjZi!GQFE<9$st&z8@@- z#ki3aO;xZ7=7-Uo<02~7PVCx;P%Wv=RO`!gl8bC)9to(G0 z2lRM&8a2iQEwVJIPb){eHztmY9qL8|9@z=BwN=fj#(kI1np0Y+l?`~wqVYRN;g@<_qeB^4h z>2D?&>D15M@M^{%m0#Unwtb;5MmK)OR6VfWh>3-1?V8!ZxRV}jm)be}?(xf?bp~rX zPU~`Qk4x=C5g;*VKBC+r=YBaF(x!6Sq%=96k+fh0d%ZK!>n{Qnd~Rq&(g$IxdhiET zsndz5=jAliF=c%G>2YU-b#imNNpG;zuo#c6+g_|pyX^5k;{JKWxK<)=_*K)=_mh89 z;gd3u6@i`=-=&*F_ntkG>d3G4M!ei+$8)B`X&oB)BQw7wjIWJ{f{$1`l7u;<;}?4LJ3iZ)5| zeCkU3LB4K0f4tHeiX@jw$7f=U4dIVvl1U@TjK2m+(-wA+aQNB`490+b$F{x7E`Ktt6&b@&Z#&wk_{T754#zd47} zp(9Yp4oD4{;PNCoCDQ%Ww(^Ia@rSaI#D{(sY|49KKhGu*r%S>=l`@_0ZO8Yy~+(# zI!za@BG`sYB94DA>1VzL)bNF%7F%F-|MRT&->1B_3siWa)k!Haa3P*2VJy`Sz++At zj(Q`$`rcnrCBDfMf2L%}50Sw&Ra3TvXH-`~cgt&VJ@s5AW>h;N7wa*leEMlmytm8a z>jS=_T>EC07W2K9fMW%fj4!J3f8W1MQfM;9sF_WLb$v>$Eh5`zU8o^lKYjf-X= zq?ged{ySKeIVRLv!Xge)7~#P1$gq?(XU8;UQ?m-&oegxxd~e3A7;9)^Dd}}mivN_)$rcFB;+9)*w)GvM$^^;4B&SM#_*EB0}H*r&UN+V6Ees!na{N7O$63J!XrKUcXR;W~e zl&9umL5OAe+_UaHE`QEvCwc)ZhhRoEw!xyd#W0OMRP0+qdE>Ml{8O`dahK?F^gQpQ z6{o!!cchi3%(K6xP}LpbbG0QhnPp;y-(fzHS4=UQ+^GZ(EtI~$eFH?g6I*L3NVlGw zN~%21VFw<>vL?DTzE_f*r!^fY{9;h4*T83xur}iG%;9g@s!vWp+O<+92)Alb?9NLS z#W$pw{0EVI+ubLl{pU|cw(d*8;RDc=>a*`2#dWvt=GX*HRKI_n`8f8)SZ9^BDZJ9_ zZ#%3(L^nIe%8(}Kx1}5+$uAMd`L6W)Oi;A;i*|{c6;8AuYsA9NE>4qigH9^(av@~- zUb~R{XZS{|Yy&Sw*^a8u4^d~fCpqli`m{1+`*pYvhAU|8Vm>hgd=(v%M*Huz=FCee z)-Nhnno(_|=ER!QGasAuCn=ha0XJ}P%s&l@Lsi;B{-+^vs7f0rnkFEK{TF174d#&- zSPX6K2vAvd`Z_hgrSu?mo5e&>QL*4OQVv1%+J~4MXz2koPV_IXmowyL(~gl_*dK!mTqHphId{ynS`jEzY}=*T_!q#Pd%Ca!_f zq99d-*la&DsM7Iq%;%z`UwnQH{nl?Ep|SimFpIK=eJJQF?};ItS~&*dUZ2F-t09Fc zSCnflJ~U)^z~%BH2>2{S#Ks0;j)4pVlT(LGIK3QskZ@)GKubB2X#F3<;6ZfqiM&TK zOo0NZ){k*?Cl+?cobZR=B0MS|qOr;-Ci#Zwm~2&vK(?x{aW5wSFc>_mH@4ZvCDlXU zjMtw!%ET~XPE7m&1;_q-K4T~gR`|b2Vhm-$uCzCTy6@3+KBGN^m=G1@^$=ohVJiXx zQ_r#NG+wEud}!oN-!5Sdrt8qQI^5T_LY8x6Ab*2gC)M|n*G#Zgnc`21COS!XTwp?YV&7q4XTZi1tbi+v=3{lxS`0|CIphNy1VVIvuK>rchr8^>r2#p z8V%=GBeFC3j`!%C(c94mGR{Fz`)i)*#7a zk~Y(fH>`9)N3$W)Dpqr6evdJJ*=}J`R$#Y8R(~9qnNS|`ObRL}=>5Lx+t%D6Pq94d zRkK!DpHBHrHpVZcl4GNLdxLJLQ3#KO4p(LIgsg_958iT~ik0lFVIPz(Zuvw*S#j+g@R4F?wKtd-#8p z*0jfNs23LUkkc&|vBi=D=7IVD240{)AQ2{@)$De!1O6g#UgWjO+lh7&zj z)(h7&IRZ9wQ#HehxRzjqOIC&jP&nj|Catmo^?-Lu$R;&TsZiOe-jux25$V^+s1<;a zbX3>p6`JWzrV$^~?lTklx>D3mGk0|{Bbvb*ht2%11eXy))j|LG-bV2T-5PmL1ySin zIoZ<(Ds*jg1h3l4UXy-5!!v}sCOyrvpoB_hVBWQ4l`{&M0uU4*mN$KVna>I6JKSDN zerz82!QUy_+Z@Nv|2gTjgA|)O=J=$Ibk1_ZcEARd+in-waP8M@^C>Ua-Xf`x9+f6K z<$ox9`V9Z-TeG(@3h{88H$QRlMN0Q**5GZ3EF}&8S5rO_8(b8&**5=WEv&hD`OZ_m z3`L|SG9*3EM?-SBud}13aOvioHZ2*5O+K2 zsQEY*lPcD`9XFNw(bOz84KP@<^3-zld9ojWxMX|2K#ur>Vh%hl!9|M0h$Q*BF{wU! zeg((<)9rqg?H&A|?d|{1_F|B|foSch*)XVGKsnWR;3BeyP?El9w}fxJ6{k9Iy)@iX zHr`IN9{jO$BKZ1vt7PCO=}}m?#kawc-X_f~q#a)J1-c;1@s2fwwCM^~_^QDXMrO?< zCjZB+G!pv*CW*Pgu6L*(OGHcw5dhBK(FH^Xv2u1nV3k6WHvmQJoaoim6ESxS6T_;N zcf%+gn$;Xo`R@6sV5zSq+=Uc?ob;P0X&ZKrk75E8esO>CasEpA;trpXkFc#`^aJQD z5C8_}_yOe8OQF*%s!VP{plBH3zP=~q(Xqu%sMm=7wxCjMMjX`WfJi@1A%5M^Am==B z%H;PYY;r}=FzO6E%8>%%rU9O}5q8>dobjg%&dcp-V1v8=eHf1MM#^1Ik##5D6*zo4 zUegM>J5gZ-F;ed?l9ln)It0jn%km~4j|_Z(XbruHh{(Tk?J$=O?T`EpStkfzTvy*&#Z>OjT~R-gXqsee3e+k`6dC^7BJ{%)BN^! zb*y=FZyEzfAp**hm!~8?H4>}v;~TLm(CAe-dBZA`0{c@)=Ku%C|9hx2H~_HwzlS=5 z1ByG#z`GI+xJbLH)9qKVJt>3~9J@iCKti4`fu{hJQLdksmqDgQ`m;5Y0+XFSCA#3o z2|!APzr-o*PKMp0Y@b;qq|o5M{F-_V698#g6cXNC`m8!0A8RtL_R)^CZ^en-WQd8L zUoUHVAF{s3zN4-YPIJq?CAHM!-vg;(*?3U zh3nF#??B|*5bY054HfiSkS!ji=9E}Y@NxUYq~bz}4bIXAA7AZ(*Q$nL@7fXn z;nUWz>7Cs;IGve6YPK4ja}GL#QTdO+lPtLjohoN~o4el@Y+)Ma465z-F=5lm-afS7U-o_DBn=S zIA9}8-_A*BcxDmzwP~XQO2R&&VcBh8)QqI3#?9(QXg)=mve0i~{m7bH16n9jQNsbq zBP^zg^&DWH7*EP?kk`y{ALbzo_p$VrKJIumb;1)}6)#h`lT0hdteWol7LAO?Qbt>{ z@s)|WU@8{wZ9b?MWVCVXU5!MkB1Vn4-_&4;*`FXh4+uVN#BSC~`|PK()8w=L69pa0 zte=a|gNSX}`_3xfk9<5ke}|OAoK`Au^I3PwKv1W6OJA~5q8w%;ATLYZ$1Dq{J2g(i zWHe#aeF0Y+hxdV%0lC*imE0YF^(bCG|Nb8+1ik6gg-EpCuP}Au{Vv)bk%7#FFQX~Z z7Lm(ET|4VCmCjwtP5kdKPa$8AXce*aA&x#3=k=1v?smix%*V=<4j!v3JWXhzzAGQS zMqqn5@?0s@Z2xldWw*>B(u%WvOs5am02@c`HIhO^Q$W1x3N}*0Z13He@>!B(`>y5n z&CZNQ`1(H=MBi=BPFo0Xf6|_kk*Gza;PvG}sYqOX0 zx5ZF&VQ7or9*SRc)^Cvy8E29#-c+!Z8p&9c$vy8r^mtW_=V~LG2>Y}BL^T+&qu^{x zYNjP4h#GrU&?wMd4A@`NSuDoB!j8*KKz8X$aaPhQjVywh5lx9PN*#E8W

s&&vjwkydxx|`Yor+B}fm2{gX5QhsD=9|R5Y}M)|a}lHd-A(zSAXr=EbTd>O zYJtBO#%EQs8|?t3NMAe`dmU1Blo_l)rn|W-+hJGMsMG%K~>>j$iZ)>AG~eTaun5cd@c$6z}HM|^6XXslfK$2sc1HQ}@xQQcOzYrz+zli_Au?Xx;^8lej-`=fcZ;=aUo?TP8KrM9xU6#NB zJU^6X$LJKswP=V)l3r2W!9zJ)Ium%U^XzpB=YVX!P$-iw%=0^KLctwYHr@b^C3ju z^me>6dr}6o9y3Hny)SVJw`Nv?FEKE9O1JPfwaYzQ}_(o6nl(-DeEzrGdm8 zKBx{{0=O%l@}B1%`)?O^VWVORIgtmLqmoZZ^7(bH3KOi&1Cw4W9|fuTO}WyQu<6g} za9me#Cw1@lM$WkJa(ah-Lv~s&i;bsl(bw%4U6#uqWGK|OPZn-&9v@zdCYc7L{%uKJ z(0gHF$L%qrYO3<-AcRizY1CbTvmaSc{9LXD4#>VVdv;Tye*0-@fjUpaz(v3lOZ0&7 zW_W^JR+mh@SR7553lkZ-Mv(v@>ruw`$}})rwCcBk?>6OVWeTHKOwR4k7;1xQOXk=l zpTD7x)jPhE(#!eJ)J_%;X1hpChJG-%yqxX$rDUqX7HS_@SN-R&-bz#STcnK$2UQLi zg30n3SC_lH>%@6=672M4lAFuvH}RLq<7bFGqf$!@kIuaQaj>iQr{=^ZgMd0LErpOx z$l|jC_}dnucjDb>Cf6rE=cVJ$4C~(K75M`3)V=uqNhtp@a{H63azyO@Nj_Tw>i`+C zANS8Y7mSQGix&XnMyq;iSh%t8Gi0FXK3{1|;Hi)Na;UR`t_fY|mwgqvf-ejTWBFKS zk2A^z@!UK$`#o_CP7d}I`WQmZlLQ;7*2pXIipO&o_wDH2k+r!fc5Qy))EDf+uY|7W zSM={P`7_PB!{kZ!e@(jz&4G#%p2RKp`wQn2>?=QB!<#Co1ZgG_9|ltsxF*|@nwHdm z08Ir3uT4}1y-ETn{0s5uQ1eIV^#37cm;roHG?N^Le;D7pHzW(!ORcZUp-G0XICawR zVw+z76^!}-;x8z)n{4M3X=^?0v6qrhuZh-Cdt@{;o%8PdcBmz%G>Q6AgfZ#+8fR7t!4IsRU z8b;4@D|?zmb}QbQ_tSaCR%K4d4IRbBp@=#v<$_p3zhC|Q6%cKeRw^c2#Qe7dwtpKsY=`M_aTC+yq!`v~xOgW1%oTGTM?u#ZU(@otnh%T1SGj$a+)Ydb z`tnJcye(&g=I^RczHj7kFLaD+P`xC85uw|s>_2aZ4jJz{TD3T%Qc!|?{Y%f+`yoJ=$ehgE#1aQ`+Ck<4DR z#K!`@Bi`{>dx9&Lv68;oDw5U%IJY3PQ`^L9`q^*x=G91c_!AO2UOQpKJnx!AcpyMm z!V9Y^$$qr`r*PRSH4L2iPpBGEg&y{QLd66$qJfDUt6WLg;xKkN+sIU2dzM4QG&oj| zC6bI1zfzdGe2&HDja3v_r6_EpeicHtr)WB}-C5dQyRrEdp05(ax7JY_=PbI?MH$qV z@nzLkj;L9b?aQ`)-eHT7QefAN6l99#OR3tD)9C}wc8r}3SGXbJC9@94x>wis+MI!V zsdUW4R@LE;c2V`48|vLrvZBk&<*l~Jil@GU2gzYOeyW|d&)!APsf1a|KWnhu?GCpm zOAr=tpJRRC1cE+7jh0g!1t$*Gybx%WE-elYrPS~Fq8~;wEulAA(G?6CgU$?VAI7mO zX>|mp2&-gqB2?CkJ8JK=3L#oVuWb_B01aZxonV z63N|A+#f|XO{=?7f%75i)i0=|)?tqH``K+}-_o^A{u#s*6tf8U)Ar}rJ1^Kj%QGEO z47GrIKM!>Lm=RvcL-rybGt+?P8HJPz6rVo(?`P4&g>~dxa|kOF7It5aUSR{TXr1;S zA3W4HcX!6Ph4U#fA^fICotOxkw(fD8Z!gUked-pSQ>-y0Wu^fG`VVNaPubf2U28N25oh$AI`! z5Z6}&t%^`+loKzuK)|?k^u0jq@&@-A*%Q;vu9kdX(g+vh5vNwrhOhh{lOvrtW@_n| z%cydewC1gipU|InI60d*-?KRsDjxSUGd&vGWceZH3@4#(4>hhd{H3Av#&iR1mJ%+w zbLWb(7MVOJAr%-q2C>vF&S_NGxJU8Jgd;SXk{{AM%!L0SG?FFWmrQR2^FL;y&70>d z`Z%w3q;&goGVYUNr&xE?HT_DEEp31PzNzM;EC0_z-zUC)5)pd?@%BHWiZW_~K= zS|nk1H}|}5@vZe4&%9TRjAaoWe3tvfskx#{LYA^c>DaIIt1HJFlUCCl8;gRyO#Dh? zjH5f12Qq$3Lu>jTBr=xdTL&j?vv6jvgu9 zAl*nxqoY&0OHyg+5KvM;0g;k!=`K+eZ$97qcb{`_XFEHue|FCM{d!;5^}6Eu=rUQo zp&mrRe>R+G710ahDHc=(_f)VisJYit7i4bdx&wHecI&@3#l&}q6t0`^{3-k;zJrTp z(mDRY&sUI$i&^?(KspCx3?pV0Z`;WoV(da-ut-8)tyeRX%{p;*VaxW*p~)hjwSS}O zYe8L-6(t5p@ZVGXKYI8L72ttj)j<{rX{oKPvI?Y9sudpoEu!64sen(S*cq(JVPiw~ z_6rMy`{xwDDUEb*NiQmFDk!d6%WvwH_4B!_RB@wXZ<9)(NSZUsDjJ8mO8_XAtJI>S zo`x$r2mVBktBKDE0S(dg=28iu@RHC8JwV#u(JXn-<+GYFr879pO2^T?ha^_^JG`GR z)>-ar6(90UzyCQreOb%lu{j~VBc5mHZ#s&i6bBj>ZYNI!)4h3R+(0vv4qL7HFcm69d_A^F;BHsLU+Ebd; ze)aoPrh-oCEydAPp`70c#OE}YoZ~i#fkepc4)35zk-Fn!z>KHjTb86a5u0*lDNF?? z!g`9{;!vs;UC$6amz~ba_6EzrGDk|y`_#H8(V;6g>hnE~Gq+q!WJ+W72;o}?M*ITc z&zcXMJ_-dwdc?l4aa|y~EOtMj%IS+QfYWMd1dGkL#06V~3_GaGkpN4L+dvBD$s&v* zTEd#j>F|5LPGYPZ{Z4>l(f5Hg4UZiPQ}I4ltjPtGML7F`(z6@$jUT~E*w$&J^@se8 z(M`=VA4Wv50krA{uYlY%ehjc z!35bsPL2T#URXG;U4(q}x*T&suZH7|fuDiR)ct=F<%xfLtDjpkXaeA_??96k3R(&z zPa(kz(^StI)cJ+T-Z`8|loUiWxsjhbYB(H%o3R9-U&kE_iNHi6PDnu&V}yV^4W>9v zmEH<7bm3hw0b9g!dX^fBS27&tWKp}`ZRZuf6C8-nZL0M%WnE~rs(uu#px9JbAMYl9 zz`7H{In`fgA&_|rPX9sk5 z2ToW8jA{73aqzU|#dbBLg<ACeQGKC5h;c zIwHl7Pe`D45awZxaS>&zZlhGbLi*lV8I&0g!wmoap_pKAQ`>VIpWR?>~eRBXgA#^*BQ%c8Ip zdZFMnMc@=f;28rzn^_k@l){m)y?J%@xS|Gykw*lydeTA?MgRgTN5CMLTm$Oy2+ri_ z>dKTI4wvQ+Ek7K59uGp^G|WBWUog;tP4W9tYbyp&m$#3prJK956lVz;Z)TJyyrO0) zP=ZwhPnyR_cc%CQ)_SkS%=|Y7o)aW6!iV20c~5y8w{Q}Ti6{`pT!Lo7^XE48fN-x)zI&m_%p#ec6s36XI{5tM`H8jl`B8& zo4p3SGQH$;bj4wUB0xD-MF3|`+bcPg79#-qhA&flK$p4@h#x<$8sCrKY_Eb>Ng8JJ zeVyb3Qdsmo&Z~u zSU-e3Yb$)bs)eFsX-4S}^H(2}ydc>6zz>e<@K&IWx1t7CFDVF2=d4BTTdD6Uha=_> zEL_kRAL)5g;!Zz_FM#)^Be!i{Qzp|Rp75NW z+#ry|S?9c8%LTOYpc}MAq|Ho8XNI95=GNWwsZ9>y>HPnt5WHu@+siQI9%aNtRfbo$L*cEOIq=o83CvLF7* znfUx_yG%`EEV3;Ax3#jN-GDe-TBID3v%*QigmrX`TmDC%&XpFo$gFt5VUhDr8ZIf$ zRn?qf0PD5_#~6=jgOll5+5uie6EQkyV-R7A`+^FTe=1L{(69+AM}c&gvu*yoY^tUS z?z1ucX;QE)lfd_Ow(?58TP=a_4n0M$|L1;GrzW}2l*+;;o-~z=luS1siID<& z%5}rsj65e z0a2FvzdB1}N9?QIsQv%}?e z1atrwmC5MxP#iacAKbFK!?>TajHwcwMaooEdGcvd6JR?Bzn};Ohe++H`%%tq)fxrj z01~;uNA|{ulvhNEJFX_&6FK6-n0dy`R1&Tn36G;#Y?hw6M0J6reFYK%!aW>%FZuX# zI5dRWl#hp`esiv*hLR{z32(U|U{LU%*N@biRNguQncqxn;@EcVAMNJAm=X9%ODy2yC5V*gykLG0|eC zZeYUgdHiQxN(w-(rxn`MXHpUI&$~mdB;2O-$!t45_`UrRgl;PoB*b^Ifzqjg2*q#LUId{;9W;Vz*%1WFcssAqMai*U>cA9ppPwwImdXf+@wEFBK z_W$C2j}>DrvdY(zl~AZ-=wM(Z)uCXRZ}XGqqy3qrw~3(e+%*^CdDO5;27dWeOaL}7 zHg250A1bF!57Y>+JPH#C$Jeq6Di zHs&9D+bBGtH>cw0gR&vxEH<_f&imr5!N=+Ov?#TBI^=rxsZi6)*5Z5B;q}$j9M=Q zJ?15$fgXM!W34`ck%O@EjC39U|0l~d3=eCp<{sR=HS5OHlutdCBIk6?&R7y zJYofA)q~6EAqQRq`e-rNox%O;9gmpq%UkK++u|ALp9X|wm6^9b;7cT9PRrP!7;3!S^ z-Fs$o^R<`D%vwL|Shk#<+}5GJ8nMlEjN)e_$?IRTSE>gixep<3qOVRx>!FguT7Ga zsCacE;<4I6;7}O;2EZ8idt|KFRCT|kv6sfH*Ao}zj=)gkr%`LsOtxpu5Bd(@Rq_+> zYDxXf3i&lTb#Gk4hJM=Zp${jfkMkr8Gdt0q8s=yA^4o2mfZiu|_zR2vim36%nUiYtZg2A%o;M5kfvOV@; zQXFt#UA#8Ldj_%`{Zm3-N3R^@2H7by_?AN{YO2lAU>c?dk?kqI(J}f#KSVW`(lX{U z3wonTX!>@E%I6mdif}kuD9?$bb|hT+jYy=EFTK+3xJfCAaGb9TXVibMO|_R41soKZ z0Z}F>Hqj)~QOKXL;A8rp?mI(1-_>OJOM20%*3C~Yp}Bvm(y@c_8je=P9>LdQNiPpxQ;cA1Y0F|7;W>#%4kL~Lpg=! zwjG*j5WDQXPETWvL7XEI&=s0TVaNmVkrGL&=O)l(Zs@uBs&FJ585vL#%VICkr|>7` z2)*}~RdwiZ&!Wv}nu-&XHMt;2qxii5hk5J+YjOb|EwHiK-uU~IfakdxF;V%Rx63Lk zlV`0A9}XVXkG%_pq}ECsOvf)nE%HS$Lzc(k@ zGL=h|Pc9I>fZTF@N!q*QN=4TZXi9P8VVrXotkD|%)kR{krbk=1kDW<|zNrCBQ7&tnE>azoX z03r~I=m>oLvQ*`&K}YBe7y=xWPcPh#!03JRv}{U@d1=2w2R{Z)DzAqZ0~i@S$S552 zIi7o3gtqLRTt=MbB#QG_>$4W}s(gYlkwc#VRCu*fp2nGK27sF0EmfTaGN z0aC>u4h@goEfQ=Von$Ip`?WFN@5AI4@iO%lp%%MA;YbLAuSkOl0*k)TL6*`D5so9q zLcBcPqnN@P|DJtPHfr2&9t{#ik-T7k2j73jBqPZWU<@xnY-cdWZe|7Ug1hpy&{PX5 z*H8RrItxC&UvOwVHnWcsC5*it^g2!onFJ99HchNtEpMN;LS_@bGEGI#(Xtk|yjOEPqOLv_6vp zX&1D3Q*5M6%&Li1L8qx~YsB$&-QkY(#Y%!iNKLX54V5f5qm#W2g#x{f_gs)$Xf6e3 z^k>H2$ND7pPG405w~bv9C8-J)TC=1JQZzBV+fQUzy0Ob|HK+-9#lQqHz&Ed zEc2aWBdPYo+l41K>bGPdC=A^g8~?;eHt|#-U8-8V!&w|95Hv0z8D(y`v(xH5eunTk zAXFUPX%%wSF%R2%_nKgqPYFfeBFsMnS7D?KvJ-en08iL

NAs2cU()tN0%{_e*drT`TYZ_~61_osk$blA(>p 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

%_ z$iIBoy8Gx5e#GAa6rgMZ+dPgEh0YRE{IKFz*m{o6=jJk~|K))i_)mS?TRyAKYam~v zxJxpkZ#F-h)MK?{KGMr3D2x~nb0EW({?$N(;#yCb5#iem+E<{bK;XwPtWOZmCwKnB3%gNIH7C1+&?x59J2K^#Fus;_ zv2W|qn4kdfjJmwk7$1Eujdf>*H{b<9P+F!cLBhC!$CU(#gjL3s6EKymv%b^Co!fMC zP%+z-9O6^c_A}eddB^>>2anmLiPrn4r~y2r@?tx#aLOdp!$I+R*h z-9-G*2_Db8MWxVqW+7ahKjdzEY4iQwNNxC#$@lvuj0|XV8}#d|(h>nj8fvE`t?rQE zWaFB{(!U1XDpRlbJyEv*pd9wCUub`!Zf{4T+{&6d+p#6i={AqgqGNQiz~DpkRMBCZ z6QxF|8>sj`@RD$blv9Bn_E%~sh@&1Tq00aY`_Ov1%Nk5obz1(Q+t>Ec)bir?jD*u( zd>}ACX=jyiB6Ck|NonReRXbA)Aex;9+kTE56qJq8#(o{i`7)R2V)CVajsUo5XQY)X z7=n&eW>Hjymq$9CLv0dQ7Jz~1{?t~FGP_EKv4)i@R9jR3H7bAcxb|UPsHd8hKh@N8 zX}*epv@nQL$M4EGu&JzdM&#;lvI1PS1=35kedG6hwaNft3^}P`5r!%V8J_JbEXI)f z&TzhJ=;C15SVK(Qcq1kWeH`fGs;I4KDPR``d$vj~;rkTXm@LkQs;e;W7;7_i6D{O< zq|n1zr#Ufg;Q7amrG3xNj>$-%a4InDam}jxy~|-1H8;qdnaqLT;|tNJ1JfkmpHP!cG$c`L@{Fi zv~}q7XE_r)(*OA}Vl&#00032A^-~oh#_b&h)bLZO2s&i7z}YJ zVV3c{U;#W_Q(;gYWmF(=wFBi=6`WkC3SnTwL4+F}U`jO`#$Z4=Td_c0HR8&WTV=+T zW#p2|Re_cXWaX12j$T}pkFspJH~`gQAXzk?0tM+w&QJ>CIb>P&5R_j*D5T&^gH;(R zg})j*yTzWYlJZW<7pGrz^*=66w9t3)?bbKl(%u#|qt$mn0;9VywqOk!Z_Q?6o}u1x zV9+&9yW1C}_5c=zq$V?}+=p^0CwG>6XLYNO7n$d2<_w3cRFF&6R_^=c?n{u{8z>Bd z4VLIQ1rD7BmgoATE0$g~cdFqO^2y$d#{J{pd22hCs-I`o-0N=VD+$PQnUQR5^;0mn zWTU&e{5y@RP#$Mwj6(pS)6aASiz3YwHx}!C`mHo(Zk2_|yI3ZPy$^`-W8bTca@7m2 zD8BZ89c}&3pBS8mQ|HIG)FGLj>NIz9-l@Bk;E32n5bz9s1~xLu-ez{Rt5&UAuMcgi z8}&!i3t|kp`nxl^2OjW;j;W%E>gLaHwHH}hJG+61krEGHWOVz8DW7se8#dUM$Y+90Rrj-*U@N_j^^1;8#-D zSAd3oZfQp`?XyE|m^)fZtGV@edc`;BXTUEa&M?ObK7#+7|*@Lw}sDFw86GHpt0Y&rgq+$s~!0odZ z!0EHJW_P*`_q&U1#k9fNp|?_{&(+w6oZ}qh9OE40cg6zexp+b~7`dJ3#mw#$Z#g`@ zYDc`X#cJ?@TIwfAMjodOnvpLV%hAW8^anWc+Z1!uTahZH2i5A@JG<5<(cSSER?>#s zGq?b3uHT$`0BkMltYJpyGcdOzE)Df!rLl}myhjNj}=+WxC7Ss-@6mtOD(cRwB z-S_AJm$EZqwcmD5&gwLyi%V1m7Kh>PsP69N0IeO~tP?}11l$jhY92Ehubc~|LXr7D z!BcnsEsMiF=Yuo3ZEB#449St<4$!UTlUhAjs$EQVedWFIlN}^!3;J!S`Ly9DXR1FI zGOa4rcVIV@9(1-Fg@tLWyB=FE!pAI|M{%-nBw86Tb|=GXtHsRYU1BRH;9}b0+Z`FC z?Cu4&-~suws`!IQ?G~$cX;vzWqfe!PuKIb9L^c zDHK5IM=F>-P%YTp090mh2H5<>hhwN3QwD$n%m4rY01WpU0028C00032App<~0tjhd z4L*ShHxl?rY$r}(a489ysQ_)%4h?o?fbtjv3P3S17+56&wSxcv0|Ed50|I+MV0>6# zwn+6yKJOq;xN0>ix{^?UDW6AS>>CDk-$zDcIlck$EN$kW&3_?usBFO!OY>b#_>B{x zKqD5xQMfLejMNQuqp&{are*M*s%D~F`<`Q9C-I_Fr8anQh*^nxjj9p#&q~YopDgQA2yPqR&901?@^$-LA?a|$~){gWR8kBXp zm>3@S;)%*W{`x+si@+xMIFVJuNvM~Qe6(T%iyQNr78$kibjDv*dtX@P2#arfx(*>R z%o#c~>hJNh-32ap3a>{wJ5;WUP6Eq;=~Wk8S!Z_kfZ~04bW_o>!G*K)fIq?(VB8d0 zD*#8DNx3}wbH-Iw250;@Au|6BM9J?8vu=Y32GZUf#T-k6y51nUcqxsY-3xk=dYmYL zRo1Vl6HP|yGZ@|14u&+A02=Urj2uw{4go~dji&{IwnmMkh6{!^i)xtQK7;n*bJPOl^W**fB%UAPcnd-#=j4e<7;bHXlo`IJD( zI?a_53mnKAAAxD0e?8V`?lpv)3mH%Rsi*h>TuKt7omrdIsCep8%Bt-_j;Z6Lm3RC6 z4wYdBlhMe@Z7W1{lFxqE86_v;6UtYFSY7G!)_(pA3f4g-JuH7agV zY(TjETcw4+7R|r)$igLzb_NHpSW}z3u>f=Fe&Ur@uag?M7Du3Ko0kxj_=53)r@$~Y z7#DpS$ZL0ugRl;EO%vVN`NglmF(1W3%-r`0FDot5>}akYiQII zNd>XqhIrHfQzm{q+#LWTP#!UVhPa(^6PNJZOvB66v!I?T}BfHOD* zV|>orZWXQ212ABd)nrsgVKd8oie^Rk5)=L>)c+x4W<(i}BMpC$vIpV^aVLddXTA<; z?HXYBsfR@=RhO17b#~j&=mV+Lqm@s39;wG>beHu*RXOQ)C85o25WH~$YUVgD!79Cj z1LMK?lj*RI-#`wZwP}We5_|@0Vjx3d#C5yUIyuwuGSgciNI9ie<9WP6P0=9g^<;_x z69XV?w=GUJt%3q7o~Kri+By7CSs815@_o>Wb^$hy9HOjYZ8{k$T7{P>TKOL*&I}KR z+xGtH7d=1FbbK;AoBSkr5buKvF|%>@vXeX1YPZs^2a;m>tEigL0oHR>2j4a!;L79> z>I|I6vd;K7V8HzJ*g!Z5GOIzD9UpzgRX3I<2!Dj8Hh9r+OQq4Q|JstE4~3N+g10GJ z9L67whhE4TeYkKGhLjFokArBma!p@fo&en&ziX5JBD(ZMzk_ig1_$Mc_dQ$zw+HTe zf&g+4=Zb69*4ceCh`n6=#s~R7`}y#zfM9$QzmB8|)SEkN;U=rj#f-rDmEm28hSQ7W z2LLCMFn2-%Iq=aWyDRo&ir(E#$4E8Rn8Iw^Pm?kL9^G1~WS}O0jO_cof=UODq+7%q ztSDyN`x|?pK4oIZ7C6*w)i<^t81@fYzz$&oge5TAzM}{aDKo7~RZ;x}nrAU>QmoU^ zay^C)X$mFCs`vhX3b`1G_KtAZTygP~ z`1qF<8{=6s@rJ$dbV~wuv0Mq-Fc%sHqNx#p_8rXH_4)$7gx?N;juR#PBCDGCfKEto z{1^l8s|h2-7e$&)@II_JQ||Lp%X1d)>=xoKv`iKj!{8U+>xc}D`r5}^*eBMGa4k_s z15!}`Bdfy&>cY7kVqU(F`|p@d-_-oIM7M&16|4p@7s*s|9&5k;QU3-jM?N?}inkpR zlvzoZ97`sQAFt8k3ZVgCkVa!y5Hi|P2;Z?xyufsxS_}wHW&IFj7}n15_P4G6DQVNp zMTF%DJutms>dC=16ai1zFg^=P__GIGhgF3Ri^Qpq{s3jf)TYGK@C*{nLG=@m$8E$C zaV2WT|B4Mg#U@r^mY~JxGczQ%|5usQ&;`JeDgvz%!udcYh2`D15j5za=0PiK2B5Gv zfO^IO8fE>fZXgSzHA=fz_w;i zeNqM3&>*q@iRHWXqMK;X^u=)(P@UD*5vGkv6hboB{G?Dp-KbbhBv7g!CtUy1OFXb_ z^6((Q_%Oe3@8q)1_-c7=hP1bgt&lrWXOfc$pe-KFl3TF z^C+WXLdm%hTQcK{Z<-8H5#on8BZk%yD?&9^8?KA?{F*wEKPR{39@DLNXl9*A?bl6E zsi1d)!zcqKW$Qs<)Zc}roij})8ISvZPD>X0g+j2p#-CHFx**ChDORjXjjiI}kQd!v z2-E68ztf`Gww+Er!X`j6n|iIk@HV`|<>{C=sDY(NW?%_Be|wFwbWtUMRSG0-V;k?r zyASA)5ElnB{;XJo3ItfWENW|sE|Z+A_zBS!WnBewry{2y(%=At1KWsFnwQvUd@W=p zyvB5?QEvcB2jo%8snMFFaw@Zvrk4*|X1QR%4{2NiV?z7GY0k2|REAd@bDR)GspEwu*IoD&Un8{sj) z1=M#_*88mo)M)U}lT$JxA6bc5o$=BDz#h9*(GAs8Cec#RlQ(Adi(pMb1z~JJ=4w7X z9+zM9wH6oDB58zEDmlLFk(qbGIWC|?0rx#cPDY|_)@uf{H^Dm0d^zxsDaPFtAbP0< zfr=W&0qkVJ=-LU?qm@twQNubpR|I;0L(%hwYsq_`u#>|2en(-okQLC}j!U!kNmd3z zE%UNnu>8j^Pw*#LBB&o15sTz}p8^aIf*bb!>w}hdY49}oE44IoxUu#B$29&24Gctx zcu@Hag3`RK zFlK{L)2XzRS*kA7!$8`?WA-v)Kp}bOp4U&L8sMrW)~YD4y(vrSe)ua!z++bAQ9w;B zEvfDuGh%LS7AcB#8wLlfce%7Sdg)my$cvEsOPN3iQ8A5ZSe_bl{tORtvY=fY{Kz2~ zfVS60W@in`t+uX>d6^m;#tJ-JJuAtb}93TW5lIJ#Wk=E3Lvl+GAbyGT)w>Mx%LrnD1h;){SG(Dba@AW zNb)}>_Nb}zK%RE_uI49mjHS^E(Xkjm?rcufFrg$8I#U2 zMvhDYAeIDW@NRGui^iuzQG<4Q)}~77vHd1VCiws>ayC6(P3_pt`U7v*`)ckN>|e8hO10`Lo+W_dm3S<7Xy6)c#VR11M+{|4ZmV3?)asse zx^KV(dg_r1!p&7`B(RE6mv77bClS5f6)vXwchO*20~ewZ_Fxr+P;#2zk)E%>V10fX zGU9$bBSpSxjAGnt2)>@QH7QYy%cthZS2riAr=MO4o90OLs8ezbS3~P*-4GqOuBWC| zb;0@$XFv{T1ZJne@KKGJi|c%*IZjPlwQ92|eSes|+JO0)TJi$}*oHVD{^h`L0D=Gj z30(n$8UO%70D}U|&#E)kLSMf zDt8w7cCdm|z>wSX<{$R32Fc+iT%Unw|Nygsxw<#N!P@u z>H2&q&s3Dq&UF^7Qxa zb3g#nAZ|?DYg?anY3vvuT=VMRL?3U^S(MNEmeSK~KV+>rn(5_4P4EyFJ29yHVr1pr z(}5czV!<-fw9`T1;$xyaSV~o`FsiDJF>)u9Og#pC z(!T!C(W7V>9`|Y|6fxp${(3uq%+y#$cqd)ZrT5~&f$wu!`M|fnWB$=;Ei*}NyEfdZ zP-Rjr-Z!QI*k{ygVli%ZL$@TWS30AkyS+*&MAfkbn$nX8-rw3RqG@9+l$z+H%Mexa z6nR4?(auFx(9r@kX!#t9tNO-SpGzEyonM5CKP%AI3{w_9=8jaSxLFAdYb_r|dQ-wk z9%nmqh)?FvVSo#@EdO*|Hpg=kA7>1d7XeC7e6gY*h!JO~P_DWtgTWW0iU|`(IW5CerTsn| z6ZAQ&9juf5C;H^LPknKC1vl-CV|V~g?J(iCAc>{7NGu%2kY9m-1Jn4egl0E^hDuTN zH?HMIOaXu>q=^le_(tOf1Wn{`zOqWho2jevJd-tr8*2u7gcF$FZeXU{3)9F#$3>ux z6huTKMze^nC5US&lcaziW0(ADRK|M^0!GTNjr+A2S@|qx=mIEIxh!Vb0%=LxlFaS^ zo9h|%3OeZS+nVtrjs|!n8@kWB9{AwE_OeK%MCR=Ki$ANr3GP^Q18vynME1bHMUWM) zvoP+C6wY#}64*&69JM9Kkx^+JgbaX|x8FXJP{nq*85psF0vI~rQM0Oh6)}pVr=JCi zBGewQx+&KXhcVUEOX%J85wvO3nWr7(3=8bj8F661@@g)Xe+*gD^2GXbk6Q-?yw>}` zI>Xs@G_zCz`GHC4W_zWVakg_yf5GP@+~OKWvGG(0+7#ps21EUX_|O3@{2kJ<0W^f? zcM0(LWJasR|44+9b3Gb5OHf|^gsaoE?dh{X(||-zupSW8(Sb#z+$~hT9Mc!~kXz`l@rD~EO08jZ)H#Y{%uX0$vgU}jCB#6!H&8LBVWGz zs>XB>^()nCt&hL}?*+Y{`}ssQ?O-LRxqtvSSGyDl>rmc-f$BpY5Qf?a7%~a;pnLxU z-dW3kI?d`;eiLh$fJM^g$LgWM zy1T6nd%3;Zcz_4tGGJAkPKOAn?)|SNVOd>BdP{%{t4@Ur?AM;7`mm?%9O&YZAE7MF zRb8_`yQW6I=(NKYPs_*8JV%*cE{6w+aPh4vg2-m1gvh1v#h|PJt+a5#Fzf<7>w`&` ztaR8?8hmf0>QsDeJ3Ov#XILRoU?u(3*jM=rFCnvt^^}d{K923>A*zX;^@`=UzR2=VLYzK&4&N`ef_qfhWGDh@&KAr{FH$NI~Yvu-L6vpHaqbW=S9bUkA{)KaFjoFxSDLMnm3gFi357m?8sG$fpZ6Hp@Y+X@EOGXTxcO zW{5xz(KECj9sLVIV^qigQZN>d3KAq|rvUZ?n+r3G=11Tq}%c98JY3jES7#^1J z53Bf4WI4GGS$0Y$pyo5I`iJF&K_(%#$HG;=9e{RMe)vu@3u9Yqf#%3A)q>oFkE*Lfpg{ z7KPWj>xx|0I&b`EPAJC&-(Rk3-`9l_4Q=nUA5odb4%CA9oY4Y=s3n5&IJVl5PPsc` z1kf-^1@BdVlz)Ds6GG4bR(@*6J3P0I_HD+l)h5}1#EXQYLpkL`ZAG0W%xYkw`WXG zHPJxXbXNbG6%pncGfO||Bse-+s~MJsNfjhLNLA{mN`L{e$Ykxl3K`y$OI0(oWB1f_ zyxo~cW{gAc)j$zOs>lJfdaP#ZQ%|R=tdyy$j;6d>+p50$u{Te&7OGan19f6%>-y`F zs0c`U263K~GD=JGQrr3~ss_w`#pK>A>hlolE_&Bg>uzhg$f$tqVvX}6{~yz0uGAo3 zUf2WaG0Kir&-wis-i|x|2kFU+c4#`q(^#_tv5cpeNRhA*v*Z}f)u%pa{X6Iw9#*zX zF_GOiiPB@Ee_nZTHZ&9H;nsq*6#XU?25pW#UN|s5-BQw3LoY5yoA&Fb zHSb45x|$DpL`DtidpZhwyMnU-2~o2) z?Ee5Q9<5a$y&Wj$&*9}&oZ!9{>Z8jm(r%824s2fzHW77V=eepZ3K7u%5-pyNpRMK9 zUvSR%Bt+PMT5jhW_a+M-ob~yp_J-0rlx0^4uy#qXiAFH~AU8vG^6RWGZ z1kys(a;(pwgDW=00tGH~SQ3yHXLV#l^2s8rpefP-gK0p6)z+VVyn~hPr_wIM~Ks=sr%Ok2jRMXMbT(S7*+yBtxVK^a`>AQb=7Bs^Z5~K z<8Rj9_F7JfqABGZf_GGO(73fqxzLk4v`yufP8kCO?7ry<#Am;blCaePS_?L4M_p<4 zH@QdjoK2`OfJbjFLC!AG$hY@9qKC)V1N?x^r7cGyr_eOr=j_4)Hf&4bEkueq5~o=6 z!RrpuO-`Wf7#}TTblOcc$4pjsW`Z)wMv1D(ie6jMyHjyYMHC7(qcmoRIU3Znr=kg?u5{O=iJtvLVx$TA}8> zJl5Mk-@xOZ%!3$eFYkR&z%Go`a;kqxwy5P?7rEfROVwp${5YL>Tq9_rH3T62|F_kk z`l)#xX$zFklp%8C~QB3sn=CTx4KX;HNKQ$l$!HlJdhes#S97>dXIm zW3fJ(*YLjh{HuO%OA&3HassU8ExM%5YWiQREir$_o4klV7xYNkb@I3>-;~e2<&pAt z>?E>SBQ3L|m*=iXQ-qvfPdnRBp>4*Ay_2%)nt>+CppXDFv-S_{TY_F^QZFRJ)mY7I z!kt#zZvYvXGYNRTmt_(3DTg>Pj2^y>%|`$k+kMf6oySj4tySI3Ik?+{=pP?j_Dv{S z9EF=EaQ2s%aaorPZ>>~x??-C7(7B=>VfI3dUgYzQZLW9CH$(-gGlBj}%^Ht;ka?(N>@UxMT)V_{*0Fwx@hA9SOUvnGK6wgD} zsYf{+ihC;z+XHWyi-qreH<1(^CS>ZnnzLG36nz|;jLyvCo$GNiCtQSl3uI3>>6)}? z24~duYMtIQyDa;aaWk2lF-CUbOg?73-4GpQujXB6{dcsdbbq{FJa zH-P7pn0LftS%p3Rg>Ol+m^;#T_$b(T#0I1)=*(8aMEioXigVx$IaO`IfMFp8z&slm zZ&QsCKa0jp|J)bB0f(#se=h`{UkMG`&s#jL+}kM_w|mS-CUBF#T=TF=)>$)zfQnXX zY%X#2OmqYfHpFNJHB@G+sACkeU1}Ps-_}xz;FDuA3fQ?Idw6DbXPRXtZ%hu=Hw_J; zZL_8Aw^L5hoL$VcIo#)-a}9&yts^WbXCMY*G+bSAcUzS*(8_ zw$n_9&xM6Gnv?v<&TPXvTHK=f;H{d}A?R9XpUzP{%K~x36P!Ej_@scqwE>WfpTyGw z(1OkY0000CWGw&yeI@_^0RbWax-7tf^2AZE6l{3@8@eT>%g%*4k35ChUrqG<6bCpVUob zu1o=#P(oyI496H}5yH}*af}!<`yhnGz%o*FvLHoHLV9hCfsKX=3Sc$>x7-aO<};30 zwh@O1xyWMKkz|#vCuj)|>lS_PGGQDn)KBpr-D+dT<8M}n1kcRh)J4$nnS_|uc>0wF zz!nxeSx7BH{iFZ_a*Z2W2-j2jhGbr8OhQU2Aq7)RYd7Hbm7~}JT1bCuC#QnO6eXoB zm=~5Qe#wNG&$;o{C4~&;f6Z%Sv|*b##>O;MwUVTqs0fo*IFK8tEcmdn0J3?KhQUR! zzpIjBXS*QU+d@Pzprm5~s~jz*ZP1bgH8OiBjODFj6bMp~NH~!YeT+sgU=ZSd@nrcH zprjw$Fq0hKHq#-77zhlUyw)2-0(3E}%vS09c%(27H2#)hm<^dC7t4eVR?A1`v+Nn8-ZBF?+P$&=^&EnT44r z^k7t7G!_xvvAn)VS7k^H1F690FKDnbFn|LvAgAOImQ8cLlSI(_4sDcGYwiLPY>>3sfBLXOF4)1*8sJ!%@PA!2v=XD1EmQz2M0hl67b1`qiW$p|B(bbNdg8~R3QMk@?am2PcI#bc>Lqlh}6vU z6743(#tN-k%`8?_%9vN|iz%e+rIvwjiR1ky;a-boP#AxKfoqfp7a2CL5uPxmW2P=g zVr{23X>{ROJWQR500zcI<60^BVNB`hcy9|y6GgDG+e+;HRz8?Z2khlihLq&f7E?%8 z%nVx063i6JlsF_4oPh=4?mrKpQ0k}F$H6; zwSFPb%)_=*ai2mrrmZxdQ$ zqahg4t8rv5_^K3esq#Jvq(%ZU(LW6)#;Nl(#S<2X{j(y)p(7MffpegA^+Jju%|78! zC6qrBPRB}_#|=${?gcbJTDW+SRwi;0>-8a&prMLNL{;;!pqC(8L-E}QI37nTQZFTy z)lNKYU2269b)bdd*^rQ%N`In?+$n%tX+4%i`kxgcg~p^i z0cGuGtG1SL`k7Fm3w#n%F7A!AN!!0c^;?GR#E5NwBr(hwB3hYgJdN z0$>9SIWWiHGlHi}L8eAbA0U`4y}3a2f>L3{czjT)1$H_N?F%Lg2)VJWQJ%EpD+~>Z zO8^|+6WO)|3yH~hqq{3@Ia{%|=@BngGMHRTJ1&%~P_Yz*fG~sGnu-f7O1_7o0S2n) zv=&BCUJ$Xso4^B1m{BmTG|ZqkGMwAbiO=!~(xj73`8mNn>=?w*S_)(!&F3@65UElf zAb^o5d$q7~pDUsujKC3)47dC?5HNobmfeE1orGrRGR6qJ6znwFk1lWuCnscaaB`qO zX@r;|oMQ4V3nrpTluyJavIW`)X27!u>jf5T5sjoNHl@{C2pK%+20D;?O_8|@a4;Lu znc2Ok|zmvAS;J(h6u- zRQ4}nGf*=lq-$6}P}bMEg|v()cKoNdPX6stI_J-^*I|R-{btPaLt_kISTM9sf7>Wk zzn3Z-55PDR!vO1Pd!5FEb_;2fWaNtC-})E)j4V@kf&&0TINc~o467JScfmB9wh|Ww zLJ6^+94NO74>pQV2|>kxTZ9=JRsb?`*zkkuoVd_YL5K3-?W>R>0J1I$00SWfvEX3{ zN=OVYUyY)*Fd1{P07Yxe4>F@@01I5Lui(2wc`W+a$~J`BS}LrqG%#l$@-|fn;4*F7 zQmaS-6@asdVeNY;dcarU0|%67vD8Vs*M(agm=V>wBQxz86$kO^$z+sevBgTd(^IuS zp>;%-39|&QlU)+vY(iHA!+jcJeX@J{f~xhcTS(7LY~=>bnNiDYdQdA92F#yk(N>Au z30d1IlpIytgl%P&WC)-@x#(@1Wr8e<^gn@D0N3_^xG;036ib0wzW}RmgM*Ipd=fHD zULVy6c-y}&mda!j!1O6GqNvg8{jd;Zs}2zFyKj~_>PxlbHa#K(K}-!yFvFp8?A|n9 zhiG69M%XL}d7A(U*Pxg;zy`GlM{Qar9(l($#%Q0FTObIIOv10tcqsOt z)oQg*N^25*vwpO2CV*!uzB&A;fY4nS93DuvYPN8Ffld+Hsmz51H8kJpZ1$*1DA&_x zYV4skSmocEFc8 zlx>BdW{x6vPi-4anSF6UgW7GConb2llP1s?!dVGvb%(eW2HF%yEcKhh>s zgYodrZpSaP!&g(MO-wlqbFgY`>ZyV(mgZvZ7>Jm80PV|I>#>dvBO4&7iI;g+|>}DSH)nqveQLw4-;-smDwS4)Jrc zO{ycC9MIs1ba@MOQDY=fI^1v+U2K+VN}rfLbk#6`vMWp@(+b9-3#Pk~K~#fHLZPB& zlTo7+lY#r-J}yGyn3)Kiuun6!?+7omhinvcZkdY$0N&fdfpDY(17gT4l{1y9;HqiR z5a^%$_7v!2R}`!)350o~aQIRrrc=zU>u#*#uo(`<`zrLeaG3R&5fiNps=S9VVg4L| zOlV360e3Q#_N_@Gd-_g5VFpWQcFCkf1C)I3>>l0#Ix4rMINe0(b)qZQ-K0IGbp;d~ z9l7AH2+JT+1lUBP`qjZdn=NAk{287GSQGXBOD>ODM1r$-ufJb}7jt*McYI8?B*rg* zMW9MJ!d_@T@mp_5!t(xxM$%k3d}1!L36~nQ*|^?_eS9u7OP&sCjlqlb=LoSh&+`_# z_+i6GU0CcvflLvALyk4Joz=7#q&AU?7dgRBL6C|IoCAb}Yk3lz3bYeUNoINqX%k}O zlL`ZW9P62?Aqzbn3v`5?nvvvs<=y!1*?lU$Fq)^P{QD`W_ai*FS|=1YK7V}w#krQj zEM_>Fmnl-VslwN_F$~FJ&4ps6CC=<*1v!?IjLfvsp+Vvv7|bd6-4YGv-=);m{h~*^aDbn!pnJ zHF(o`B_LCPi(@&kgVe29Q$gZ2V_-bA=+Y%Wk-wrpOEa*rHk9MI#|nHWkZ)V%Rz>va9qGz4!b6E;HeR(3?2nT7fTV|Fm;Dw~G>AM8W>VJW{X54bhI06)7a z@QFE)U+08YPodoJt(@pSsFRs-uYgS(iGmL%rU$=kI4j~%vCuW3v@&fNn*@TMkI~Cv za4;h_BriG5v(nyx>hC}x2|^qQusECPINC~78xkl!Kd;?(yH*PUP%^%sW-n3HePpc-UO*6JY$)&kZ*7N4+XQj)a->A$*B*=yeC9T z1qClRKT<5YT&@WdX2>t5E90NEfldTWs2p@5a<)o}Q>9UuRJu87d(d4TRp&YjpvsRsV5^7>i;_(_+w<(r*8qJW3VbO8Mpj~0DI~^TN91ht z&)-@KY%Dn101=8rWO{McialB<^5Z^$A_Jlp=zboO+Du`?5!6IR{YKz-Kg9Z#T=+0! z@_>{m5}&|F8#UJUrevojXHCQqC6MXgj-C)TX^NeJj4)JI@z+IR@mUX7j0HD3?hra` zNFqhSb~NNEv5w+n@}w3y@00bb<2{e2AkEumuo*UD^O~e>6NqCF0_7K}04rA4wS&8) zWIj_6*c5E`?E@Y`nmZ^9XW*c@Pz(jJ?fe$8ESw1n(2!G+uz)}V0fD=j7+#F@g~If8 zx2IMkQ|$;iBuvm{WC|vQvTV)?X=qm4cYg#(_UU@p0@>ot-}iPPG{Xp#W+&r5oB(=pqS*z&rzmFL&XicbgTjj#o<6 zRZ`uLupq+8-$Q_KvoYx)W9r`T$4-q-ILI7EsQt0w+GDc=7!~dBv1AI6ijX*X>2m7P61L68QPv4eOGGD@;?6N{ zk9aKhbIL*slkUo-%UHbwwmxks+FpGo6liz3p}5-Jymg{j?TJ7<-dXg8-~hyuMVu6r zVz{YYG%!>0d5$N5UAVTE=Wdsi&guww%a}Wp7rFz;iwSZ7V9s1{vMy{GMJXXP*b%Vy zLz{$WP+*|llW`Q_8j_@JNVY#&L1I8{A?^Mu26vjv?ul(he z5sF&cX{NTe(1_zE)3;;$GdTZ%pnqFtU;^@Ems%m@36Yo%L1n^(^wrvOCi}pphpH5wqbD*|!Lr zltoJR9n{rh29Ys=b0#M$5g-MvfQ{3p8bgn^HAd8uO**C(Z3fa|g_FdA=SX4rlM)9} z@m84HPtE6l0-LV{my%qG+{FEXujjhUL?j(QN>{nakY~0|VQ|N+20}>MuNDHxsy`h% zJ=lULpQ(=gdeqa4#AFjlaC$?ZHam_Q3S&VtfNGO&m~A##T6`W?TFq2$Ox&pUhrA5- zbIKp><`vio5`Dt50c063A~N5XKSHwN38>b~O#(Rx1Jco0lBsz#{@HXpLTyz0yYoOM zh|rUqa}MB_mAAbZVP*R;mFY=DgIvJ&N(9STeps$OHp@KGVySU^V? zWn^CzMB6dWnYUC{m1@d&>yjQ~vBHKdi>AeL1+z`SZ9}pg$~M>y&@>fF0jKxo-WK*Q zLNg_U_5o?r!q&hzzjPAYx3=FX?M{8eT_8LPV!~Heupw4HV$l!@ussEV zgbF)h!&!rV20^PPEYv1Bv2OtfNDTB#ge{lZMB>j%k!;Q$)a+aCk{{4`1vesFFxBvul2p32+gS>TpA&Av0KpmOPvNvf* zeo#@wDqEoyC5QxNxwPM^whL#*Xl$&xE`(#}a=C>x1uZ2uwh+2S1M#smhiS0{)FxdG z3SQbBB6x$ex+Q5aeO!@gPXPtgmu7cRp)Sqdc7dc#WO88QlH<+^x364-G;jw27yq)7 z#tRjh7mfcO=Q)c#tO76m@TEQo6CZQr{E;-Zj&bF@w_+$0u2 zpEA&0U9<-S1sMPv0|CB2_2{F2O`=@uK|tGJnXm*i0gkDI;d@{F#uI{C1n7*g7~>AZ z6Cv6gQk79fbzKf?{x)94MOz6ZE9E)l{W= zV=M5GAYo~4fa!T5g5et^S}_^2gQAS~a#uo|RJ0N$aQMGkM0XlCevnSLb!mbGHCv!S zg-<4m^{HTQVw?nG5D%nAgDsI#^bo`+*p&#Lpdz+|Xg(tTQXmB|U`Z@ViR>(9KkycR zlSV`2EaqUQ0Xx8Y#Nsv@L17#SJ!S_Iy?kj9`)_S}o1A&(;4TamH$YU%fP`2=&khm3Tg`pNuW(lyq6_X26W$1Bx5BI@iO%gy8>=#MP zT?}F)0gh5$HGQFji#*f~HwvW1njD`YgL`gdqj=p-jsQ#%5h;hs@=TGuhDgUc)~S(c zDT*Fbi($lAKee&1CuAJe4cncv=Mof*@N`wT>b%Qe2#iD-C!-Hdpee8^G5E-l%F{aV zp_pK{EV>;+>3uLyeID_bg=9cT;(BbD@4c&my>R zGJls+*!V(K>jVjaaR!vUsmB-wcu<~10U`+7MFU&F3vT5;cboUu7ZO4UM!94V$`Ei}hTjIeFn+Y4=s3C}K#I82yLpaNmgTS#C{ z>@g>mx?=!fvOvcW@>-yzKae)`DW#$SLWm+MCjDxN?7U-dZMxe-(8`AJM9T*gGx^7| z0tp48G6W73z3q`vH~e8*ObX|+dH=!6>?ofSVU?lj7E(mZbwXVMwqQBFNTJY5RP80| zB?`1N4B)}c#{nitSv)i(TR%wbMW*b_4_NcYNLgpqFt|UO{ynwfNWP*9h5`QzfDkh# z<(4K81i3Qx@r1=QA+}oB;5I>Wg;NKhaK+dF7Z7?OT#-oaB*N6(4HCy%@CU=_t2?J; zL%87deh?$O2*wux00RMxN^)78-ta*fUyvCJF)H>Tn{$ed1!pTQj*e+I5ytjf7=8F4 zk_GW^3iQE%OhAlpN#_Us!01d)ILO!3RcSv3H?iZaDc#J?Tqsy)jUKER7(|3X_6%gP zFmUK_w%!ymVa)M@IcGKr#`9qNi^|=!fEov|ma3G1Y)|#!!+5ddV0KjPE1)oXB&K6% zT?tvdK@$NZ8*8jY$Ot0d8cPXt*vLLpoW9q`avc`I$*z#al zNB{#boR+~{V50H8Q>Kiv7iJmwJwOvE*U3;@r${(@((r8!ju4G0lQwoy!5!h+GHYd} z2)1O@c$}aDe&ngqLWpD-RKoy1U__5Z)JmQM8qT53Fp2Rp`V{d3GH9AW)nlUu>)S~g z3TV`$u$M@c5+sB(53x%|(jd!XR(8-w1Vv+WVgf|BK=3B<5AA`K>&RaN>;T3%^2HX~ zhUf|+|MNW4OWkqbsFsFe$5W#BO;B?Sd$*i=Qw}Su(+ef95q9Y4y}vBlMRbHg3-*{& zXwbiTW<)?rhy=z`LMGdQPOM|%&5R(L`el_{aG^**WW;C*InY~V#=z)%5D1VDuIptB zA-Gh|(X0R$+~s1Cu|mIr763w30Oj7@RDf30AVLf&i8D3^I9Su@! z0L*6mn~jE`OT;L^>DdW{Bq5wfd%6i5Y|J1@za)}ICc$+ggck5%NREoLwUm z$`k==JZ-Us&%J`}ZK3HTku=jrAP3}2$zY|iFSI>s1{A&Rjiu+&wQp_^?SYv=oSnpi zbO~sfAYdic0W=ar72Npv$=bULvm3rGkKgvk1}pw9C$dwA7>>b{^2R2tJ;58Ui)p2L z8p3_d5Mdn4HGSH!f>VVxxw?6~+X0slsTgueNofLbeo0G_BEG0529!Z-6W#E;OAem*nt%yzRo8sV+ z7<qAsGOpU;xU1!jYT?0vACK#Nh?tVoD}1ZJbu5mh2dntPn^4xSrDyHZy#(dIrx8 zs?v#A(hv`VNET)|Rnp^T!1(eLzAimWHXQR=-aZ0Ox`1QTy};17H1KU9hoE1+5P)Lm@I#aXW#O{>;xg%sERiMOY~Tivg*>K zRlV>c3o}U1tN0M>Ni+vHwh)@k#wU;#f@LxmE-t`Z%!)3S_JV2!gkp0j1@?OpVQr?2 zG-JplJl^Rvm@4K7OasYvJcB4w8rWtT1YqD`DW@?KCd^JRN zU}aouus5dCZi1jD7Yl%_O$yR>w<<^)1-q&pE4xr=%0u<8t&RYZnHi2RV+v0!O^5<~ z#{Ybf<@QWHv-w_b_BMNzLvf1NF-c&fS9?9jW<}FgF=?54VU7DF28~uN zlB#0H3;*|@nN8N?0I4%m>wajF+Deh0=$+UKBw#PQ2*SJukY~ZS5bi}bO=wSZWQDV{ zAtYEJEFZl@GP4Sek%8h7ZOs*H#>40dBwXZD1i*2{q@*#XF+pru@2La^X_B^t^dw0F zCup_G+0vmRGmc`Ig97$+=wCCoY$;OAgkS1ep&0r$^k0xdE7L~s=oD4dIPo6NK_;emyA zgehB45unbYX+o@FfPe-8**^ z!kETCpeI9BB(?z*8n{w{u%NmgU=9>GL)ySnfTomzJB}VSk+P6?XkY*&FpP~)HQw*S zkZ;If84pnqbWuqUxt1*U78GafUoEq`)wcyns~Y8C9>yY)u{$Rlof%A~F)+gJCe)=) z>PU9Z--^?qx z;86(sm{X)eJml~xmUf~uXkZeY5C;qYfH@DKkd|a<$m%d zfIJzMEMa4y30iVRDAT@sR??e`{@Wt;#{wJ#m;{OwoBqvNv`n&e!vw!VgU;40w`Ma) zbfEY53>MJsR|`pm%yW?+He=8+S$V<2x$dbLZHweeo(i=`x=s5F1e!ES&<5<9O#*B@ zQUu5o6q}ie#k-;0eJf0031CaIdN~dvkC}HckQ|6W;=-h;hIDK$Qb6coHv6_%MA_PD z^SpeNJlcQ z7;%6aFi#s4RkdeEVPYsO$n4lWF>Pi77YX-55ONls6)qMUOmI+qg3DxVcHH45J%fZN zWH8O_u@iDDTas5>l~KV;tcZg4HL-@1M0Uaev5drK?Y5hpOqk;X(R&}GJdLdeQ5&A5 z5Dlg8dm_=4kbBS&067_waeJfmmLeVrB7JftxbxnT_w_O??gtqmXBjLqf8~T5HHK@j zCKvDnfwLxacuErn%ZS(i1U>Km==puNCC!f6k_ItDqfGlYEHP|;?uY#4wL0#fiada- z)rAf)5r_O#0+#H+TO8lcaQ&JjK8`X&6P%*I5)ih-W2S}ZX}J}6ivom7y&h76S&}GGXOm@be=eoHxex9KC`bz$$xD2 z3FMhxhW3qoUX_GNHYt2&l-RD?8KLUenkdETC?TxrKFA>oV;f;;PirwRA2n0#b{!MQ z6y>&L8X~!~#}UB#af#(e00>UVp%OHqXIZqK3*PQ3DEDG|Kp20qKu9#p&<(Nh00L$l zG80;y#@)(d!=A&ERn~Hw%MUfoNWNnwoMea4l&qUH%80ZjH~;Ev$*0%7j4mp{x} zCSJe7vQzxtyuQ%Q`7pMz@>odN=<&Y090ku$0JFtR@a%EFwr?i00`Mhs^F{D~Gkom-Z)qXIfEGEQXwLw^oa_Tm0j4%6 zZcc1C<~@`l_$F0A42%eKETa&!3!!Ye1iv7{6+GecGECzh9voMhV0oZ)fg7_{(`jJ3 zl#bu51rY9pV`Asdl9*Xz7lAsBWzW4V7%4f({DF(XGY<&CW)8c70&&ajLBZ$@1G838 zG&XUewm!WVJH!(k1XTiYbYOMy9AZ4gnvi}@YE7RE-7uD&`F*>BjRxED2d_{2bds%k z&Ms?2uD~UZH$qBRaMz*)U~bHVNRRUOrU{TTnJPggOlhWLXs<*DjF4dx)QksqMaDW= zgU}Isf+K;kTNjvFdKDNS>*MXTRO(6|ahLko@nT3M8RaW2Yd#xnx z`FrRgw`6F2*uWJ4$fy$QFfBqJ3qK*-jR_8k{)P;B07xN_>giBM6DsSfSV{z-{x(vTo;d8Y-rR2Hz^;Cb;3C@N6Jqzv_BD@ z)hC$`15y|>W~yz9h9Iwxr!3b8@5ySiYuG8VWPVEI5-IhZboMX}9bwz~-gx1MhB@=Nul8-f8?(JlKHj zq+Kix(js>}$r2c}-a0*@&>wqKm(jf@1Uoh`V;$gRD8?B#2nG28v9OdNV}bb>+;uV* zM6H5q9LeJeo^47eq&U-gg^;;sI96(WrvT%Fjvuj7lp#5Pba65=H%iDwlB%{NAV=g#_-jlX~6^r}1DlK^^ z2sT(uKpaR+EeTE8HjzchfQ+`yM28kt3Wf-DtOJNbMh|X>qi#0sCf1eQP@ffDztj`!*Q=a3tbSsloTS3LJDZ ztOJt5(9?S-w485Na*q0J3iu#k@+1hZfRpNP@O#=l?wXbGGLU3>HwMhEs=%vW%-G=lx0;)&x! z)U5{7018BAAqJQNhF<-WPl$ONI49MK00{FLHwb;r`IL2Pya0j#00~_I#TozrLjZ+> z&bllB01RX;004a^00032A^@rY#vIttlmL%2^_YU#7#bKR1OK$Z5`_LBuz*UIfM@M; zyMmnIWT*SS1D_|-*u^RU->?UB_6~}!A`(imq`K$~q_}Z~%oZl`Uuq`@>D^!CPo6TY&k1iJLK* zv+Giqb+QWGy`vXt4K&JU__Yjy08mMSIlEIKTf>Vo>>dKo00000415s)0G}oR0099Z z0DKXMAs_$&004jh7y!uux<%;_@?GEW!GZ3^2;YH$4Mtl5n4bb4b0Hq9&Y-1NcVSAk zUFr#zuO_WUg~>Wn8syb{FA7LnAS1EnLlcSs@ggAE4>ag~h!Kkc>{VeXXl2n?#UizS8O6;lLHTPLiRdLpln!RTlGn6_KuxHO1y8tj$nOCsCNQv(4=3yC|FgM*4E%~gAzVcU1p(aul62n-Kz6MkSHejn3w z#fz&pxIgRhU=KYh{{@EhX{oV}lGhK&2a~XL{9zfMXLryD+!alj8m~2}l+hKm>t!6* zcI4D8uQ8h7E!(mI+-Fo+iKjcHE3rWIWG;~{9Pl8C#EbyKfld#hCFo7btH~6{ zwyK9=HDG37N@~>^mj<&KSV=n=&7l?oV~oxW#GuUKOfb1x^mR>y*ifK%K75u~hby&) zh+ZOC!}W6Ib{wk<2ztR}x=W$+hl3!fFwj>ko8f}ukqIj#mK@J|EhGm3MjW!q3seAo z)nW?A5+HE_;Nm=ck=xiXJ<0moYz|?+6+~9W;3?wF=8$J5o;#2*>fhK*k%?tEy-3sq zAY@`kJXM*~`c&**B|A6iNrQQ-$Dkd*FR^;|FMSqh`cLw6mIV?nj1(rhJDYiw7#{xT z=t|RVGHwLoatQBWi~(Yjq$TIcVB-T-3TzekUaKfW3^qC-g`FUbNCk)i(?cXr`fzY;ODdfWmlPLbI{FhZ$gRH~c|$n@;FRITf(Fvl9$FgC ztw1bHSi6Yj(8GW`2Lyv2s9@H2do@cwv}|MjFhV3Nh(4-`E{H9vmlWTt$@UBnwlM~O zB8Cc(c5M9*^0ECB{R@*-5)yxh9Q{yYMkxJ4Np28ZzJ!#FKmve4WLX4QaiLFoDHMVI zSd=9Z-En$5$&zzJjHvG=`a9_kD~o_XCt%bCIEbXCqqy9SM_arh=+&B|c;hXCg|^i^ zocYao03mQKSa`=%HXrGc%ZbLIoEX5UAVBxw($gH>NK)-Ne+P+aQZ@q!J> zpME^KHD)15&P`BiNp4qAz@Wf%!vMCLUaVy}!&3#lZ1V8|f%bdq>h%6nQ7+41kd)j9 zRH^1}Fe7G-ingRxWj!6+cFCaOnDiloTNQB0NKg)vFR?)v+Z{qae3R3XUtm)r@zK## zF7NSx!1kidRsBG>(T}5!avDq?ylp61az)+C7s=%ESD0$@MG(=x0H>X=G2N7AM0Y$J(OUzIlW;0%7AysJX1zI}&;Kjl1 zCTmn=Gha=zzW@bLW%Q4%LC=yhqq;Ol9UM!HW-|5+4`TWua?M>@s6twS00`lh(;)$> zlnx>x1_1sO;J@pZW*l^j4`G6$dN=uO<7PbGwb zQdMB~Fho8i09-0b+(IVk!GQMdrv75pJ}y4PD$lQ zTf7hi05C`fY!74$6pwUvj?7%dW@cna^mI`^OQu82WmIMLQF2FhPey8lt5=dqRjbKx zZdR>ba$HP@jrlGh2GwWq`l8H1$)lQmtN>Zk!|~Y&0H*TN$k3PH;6Z`z!(}@pdY)o~ zJMgbOpalm^Uv?f*9b?8C$J`+GQ}ZAx13>WRA%c<_aeq4W3EKuR)huBJvp-|?rz= zu_tL{RcCI}r6d4w6<;K9%aX<=-j1M8XGc&Hn;}5C#;WKBhbiJObaip6-AefcZ5~c3 zq{ox@k%1XmXj5^58xwg=GzJSWqy5<8pvEFjl4tN-3iPrdWX8}RRUjt7%atrL36_4r zEIJZCpOSculk#~d>PthN-hc^4hqqR5t5y5;B~`?*95pkDgSlVN16q6 zn5bz%Odl3LPCo4b#yl+2?=jUPLH&AYt>Uxbg|q-Z59fu*y$z}y-!Ye&0fFq|24K7(3~$i#lG!Gm)q1G_ z0e7lE1J?9A26lW(wNxwCK0MFl#HyRZJ<8yuO;9n1gK0CCLPwV;lgaGp)3C|G>NuYs z`5*`6IJyJXL-HT**iP||yc9qBIwZnBOR2D@_icX)*Y+S&qRNh`=8)Fp(b9=cj`=4l z$CgJU1aU^_=;V1ADn7^1TWb%2BSg4i^x&(bw05{hP61(WC_aCiDge!*dn| znO1|srIl$vX57jqQv?N9l2S>Jju{e6Ak|Ev}vjfy|5HOIV znan9U;W*V=u2G@qw{Z`uAOOe+YW@I2E~eOiEC4~JGrMNN8;&!&5{5|$ENrIb^%VyK z>-NPzNIV-$1~raQ1W+`( zQSBKRLSS?bEQ$0=iI%G5gj@zMvjYR@qN08BcjGK^Y0c2+@^J?~>h!0XsyES6XEG83 zLL(O@u6Pwvh0jfwRe1vg*y=^1c5l$}%Y9Gp;NM;(nT1}Ir4ZHLh(-A#$0Pw{c&AjS zDQb+wf+vZkLnVWXD{>i_tTZl`Ms}4};lxu_R;r2~bxuQ6WG1ffR7_=63o@slP2Edu z^wyD}VZpgy)f@u(Mwneu&Bvy3W1UwKRWtP7@B_vAsZ(9n#0{r_BZjwZxatGS2== z{NjCwjC@y&@KcGy$Ha?{j21>IM_ltlt&E?bnLw3C6U|d~9=O(k;3hnT|9Kd6-~G&A zQ5dC-kCCVR`xPS{Xne$?61e|~Sjj}EKbKbv?f(5#{7P~Y;$sl$Kea2y{7PVo+9Z0c zAx7OED+(Ohg9+wz?`Du(^?Dqb*Z^Y9gc^=x$v3o#wMuCGfr0JttZJK&kavGA8R{(x zhs_^XF=w2|K83^R9)p{3VadUyIXs+7sLjNYkVH=I{SUBDw|?VdV8n1t5iEYYD3ch9 zzJ~;R>_v$o9DYOCA+tY_5p6R)Fh9J6_K|^aCOMq)&GpN1CTpBB(TfKX2|1BksFhRw zsxuG+YO!DkdaNg4pEW2{4C+A?$k}XSK^0HR2+@dWkZ2tfO2%WOar!h#J90c-7&hut z78?)UuMw%dvywplk&?;}B&Q)F-9)}K1(bZ))Z9#%#z~oYsNw;P2nkm=5+DhnNIU3> zAOy&A0Eyp?1-Uh3e-LIE;n?S5Rvm*1t?i|m!<;v@xgorCM`PwD%?hw!_|xQc#oymk z!kY2s=IdnsPm7A;Jx|6&pKZ)90atpi;_AD*IGJ7Dqu>`|6}C`8Ji>sOgn~9n7ox^F?EBnk>e?oC_v{^@YpSVj7Q5y;|5ke>#Hya1fUwJwC}>+MI%ry} zllR}p1_#l?(Bb3nllZY>BiP>~ier)+r8`hEMj*~PupY{hWGA>60_5_zB61`zdJ=ur zL;~q@1}|X@7_ts9M2t0q5VW<-Kx$MshLlTmlp+|^g`&Z=0j0S1wW7uc1bjD^mxDN! zTCY?<53Wr?0R5^c$`utksC4*Ri$~_t(R4%FJ64Xm<=)4^a8$Q-K9@kkttR8SF^l66ErEBG&cJILH836aWEd zu%&9uG8~&`PqP$JMZw}g2+3mRlL%!|`Z57U#n3uH7t?HJfn&Wp2+ikh`MNZ zFT|oV_>_leMtdFg99+wYfFQJ3l}@mUK{oF(+%k9QMV&xkNB}N@NGG;Gu&G$vsY#F}h{gh~Mv2B^;pX6B8IJ*cA#K*9h#(B?wS{y_BU(?#Qe z=N1euDwdS#q82(~Sa5BLkkZn{UuS`@olyW=1o#>1Zi0N)(zF6~){5hn2SQn+er0Wq{{v5FM z57m@1aMWujYb+rYmpLg*Rs{S2jX*~Yu?)tDj0%h}nBp@`CMy&8Z&A#YpB~c#Ys~VA zA_$=LAT}dU6v}7X$?c#cG&gx9%$vfox(3kEd$Ym>_0AP?PW$0K2etL8i#7 z0ze^HbXtI4P^bWSA&v@%XKEIDdXiZlb8x=tBHlToTVcM|@EhQvMPiDZ2e=^d5!NK+ z1be%Be|cAhlmHm9W1oI-De#@ZyEIe{TrpL<|MdVQP`n93hXfZ1wZ=tiYDl_7;D$wM ztYf|d5dw~jsz-Si$pVgxuo2!x++1_VvYKq~Qx;sUE=dnq4a?mf$YPFKf|OthQ36Aj zn8RdcfJ*KA6%n3!F z#x6re8NHWa{ym&^v31D)EM(-Os*S6UObQF~$!})BWgqVYuhZTN&6u4F+ zf{d)iv8L9L)Fs6lB;hIGSTSgrSZ>bZYUiBjKa#~Nh?DS;ExPdl*MgqDDcHta8}px-3t;FN&N06*~(a&GD|qMJ1SRRgo4)M zS^y324#8HOb_3H?f>d=%pi%@DwRcR;WgT}&EX2-3&)JAi2%?omJOQW+|WG?6-?;i54~OBpc`fC^Ug2;A>VK6_|;Ef$bZ z(?&@41?fjDrM}GpxGTx}M2Uf`5x`WHgSB-#mvtmK3)X`p6>?%pKU9)|gF72gZOxEV z@!pIHR1BaqC!u1s1IP*xlk^L_672QX(~`9W0`ghjNDg8Na8DB}b~(@Gaoh*LG5RSB zbRD1cEMo4(9O008YXjl2b|Rkc3FAC~cx)#BZE8Yd6M2Z$kgFQ!4 z))XHTo-B11)XPvu00v^JJ1D?Zf#+r@DD1=qNET0a&bSfdU=(=d4=xO?kyKfV?9L7| zH9bD)3Qpr-<0#?usDe)atGoqeC8~oDU^A;Q^PI1QkG$ zLXfmAj;gHSSRRaq?OK596_sFY_DYb>SlF-^ki?fD3t68H>XatJBvJcUYDx%5TmrXM za6zzDqW5H=Yi&Tp66BI1U)oWbgUN98054FiOF{ui1{ouuDk4I_1n}U3MYR5KygJ|6 zZQR6xpd!)ZM$od>PP7GgtC1$JVTY_Ck4>!r91TA^ z9-CSNI0L!{lbFqpdq5cD>>jHY326@OBEi~j!8+0|YDr9|3Il^?e`35L*^8<;qjkd4 zYfBRkfx?eq*hEhI3Fu$qcdWg{6BWmcb*C5Nviai`MkO`95fvfW=Uk zV!|QHAOO9#5R8WHZA!XLseypC(vAHKV@=bk-d7%~v@m#&ytPw(<+_8j4DK(ne+-Bl zRYUv+!;?=|=|v>F+gwDKw0#rONLopwhNx5yRiFB*3WzBQGPx4U(8GZnQ521EmFNj3 z$fRhLuRuq5C}9z)FzqozXD$YXbbYPJpGcO3g%(3B_)*}j(76JE?P}Lp4g_LAEaljx z{mTUk(r2SMw30zxmva`Y8%g*>ltftC9?=0-RftmI03^K52muK;f$;`mY#^VuyFAMD zAObRVc+6-l8g-{OwX~g>hA~kN;FkxW???JSp}Q~){Beam!Bs=&PAkO4GXH=H6)#-9 zcT>qQWWV$ zL8Yjuh=<>qGtVE-J+o)_E4XIe>)LC5K+`q4J`P~6ReB-yO#sD16X+e>y^5QVZ`?0v zg!1()8rp(u|L^Tn3(;>|qZyO`%|;GNrEcs)O2JhDBlAH12wj#SF zG^h5bbh`XTjAlr<;DwJvR#Q$wbn6x&vFahVr9w2&swg_~#_7%^O<^NIxVs=+osUrH z|DrXZZ~la#)f#{)x^uj#~|r<5uylI%;$q^mn>3m&r2#=*CJ z;01!o$?czDCoCeg1dqLn5U`^M$JZ{B-H}^$@Q@+jv_pJQxM`IYogDKmu3l}q z?XhzunDuV}{wn|DPHgn*(Wvw4(R-bDqFHkc>!fAm*)nH~U467x3EIaG=(vJjaD~HM zth$oJ%;)z0qk_+3gjFot^y50Qf07+Pl3DDnI@-Tdh^7ooLhP$%6P znzxJJ(@)nRF@kY#7R1vybpSHoEGdwZRSvq4%@5>dnyL9xAJziM^E>xyLfek|44eR% zX&0JmlQd2{T2G{u%j*#EYuhfdT1nj6bz43XuJx8uKdqAWLS<3Q(~gzI%8qFU6aa_i zuzX_+;Kl+7Zp&ijbtX*WZJRfBzP+ryY?Zyy%fW>D8;_BNG4I7P6={7hWfEEd<+J-c zn#^gw2$g-#zcFb4E|I44*=*NrBFmAz_pKzE>Rgv$WG%rmMcF63<&n(}`j>p1KKs`IDfhnL5ho zxk)cx{zlJa2~T>*npH~rUUxlv4r{Lj$=CwHxLx$P?3s0J(G<$vW@!3%RUh)@%-a{) zBRK<{L)Dr^iY_y;Vpv_aQBX(H*fz&ueunP0^kJiPEpbbC_cpMAM^p$yVp0%-qzmFs zObj!e2&?5njDlh-4L9tRWlh;3YlC$`?ph1|uX6xrl^5;IL)?i%Mc&rbANhb>oZ4hk zVwU6nG*qUMxH74Mt$lxKSem5w>=}C&lO63`nf^=^-H+#&>k2LbRifMl7tMA0l9`%~ zUB6fRzjb-Y-L_KOoPPpub*--B=DRAGluqp5oT*ssN4s$|-3bacDyMfS7G4An6vQPS zCZ~Tb+M^Et*)?{Nbb3vpCv3^`lW*{SYVIY3Ok^7A>)zjgBRyJW@2s%f?!BW0rF3fy zm9lg*gMzJ@)okyRQs>B@>MTOum)ZEg^-}LMn>f50`0-*IvE^M%qd3O>vovE#;|!np zvou}Xd=|b1t}+0NvH1Un(Zxmlf0s35pfJ;SoO%a>_OvxBL|AvlS2~6qaL=w+2%6!) zT~TCw9q;{F?`4a?+NE%*0+P?0=BR`lx7NSiYksM__~~-p{*d0}xN;-JYAc2OPW?EV#!~ca0lUq0#_FWj@<=U>5Btg3Xc?_VP`yQqPLfF$A)D9#s02&!_1i71D zdi{z1tcMv9jGM)B&qtYWYKG_%O7kyQ(Rx-z>6E=pM^uT}a#rTiQLU1xdSYRj213=Q zH&PGMN$@@M66PM>e+_q?@^?%s$k(49v%A^bP|#js!gkeZ50zf)AvpBKOSh|2>11$x zjS4*r*^iO0CBhm5e8vEPV>z$d+dp|}F8P}kNj`$onPQ(#R{0i}yiAvIzTccj(^CFA z01s2W=o&nN$%383W$lHzfwcXF_4|rqjae}6DQPVU0l`-2KIun&neJ|A;a)F zXjQb$Qs*}`O-MgTI*x_?p~VMV@d94d}t9MzRSZ$>V|K=l*S?A8KfU1=0_*(RNvbNaBa+b{aTRzvUh z{;f}~hCX5axkD_~9Ur_zhjS1xp*zwpwCx1={XhRzE_^}6;U}1!w74c_n#V}!zw3hT zTLsf6;mLuY_&Eqx(WT)E)9OhC*S8=3a=zHwg2xBONDZq+|62tLS*)_KX+LNrU-@s3 zh5jM=%DnvyZ7|dv03_kzb^k-8na}`DZI;MIr)DBUsP_D9iCf&Nw)8Md%2@hp$(Z6| z;wNjm0TVO_2Q4_k`@}@W^`~oewHMsCiOE7$2PiF>;MTAE!9Gz0(AjcXT-?rr7uO-< z1jb4eAg<{Qbu1FD(ua#bs2J`mm#dTXS5&G92F9mZl8NWaq}=e)VJD~Fvo=kAfa`xB zaKg_M8N0c!@pwA~kxTImp~nwyNn5#n|LX8SBu>M&KhZZit&;r`351%gM6srBjkwXXfBC z@21f)BTFR@`)DQs!GGTul#mVkY*r|zCwj~pdEYCS( z_-ycAaYM|*IudXeubRX0NxU^{;k+AJ{5-TN2(;J9<#_=mi&%PTOm6)m^ZZ&s@0-&( z%>`1@jLPMDkN!9`JKh>XueU~S`BZ(iPR3xQ%|Hh->_D)|4KNbSLWMWtG#8C;5;SQz zo9`0X`Rn)wm0rG>06m{{7unMZ&)UC_ztT z`dAS|&$l3`*8`(DaNSh(8^nSNa`0tbx~vO6@oaGy-7G={w$hD5?s$i<;&*D;YwGW~ zI)D7m)MQ>xC)0vgHAO!DZPOCIpW!0#2EgL`2sB;iO^za;A+iIk|dLMhM5UQe`U&|Z76@RpiIb5$ru>stTzvzukkWs!ik8xUpn>YJB> zdX~CBs2T0`Omu{`b;d{r6d-}D|DX55FZ@66MO?aUrKju8TmBg%wp*2-q{F?hnu-^$jFPcR|w9g4D@xNDevQGx4aB|V3IY?=Zyc|bG4bs(OwRE^y z5z)u#H;^JHkST7*Rc>dQwl~~QxBBOz)YBt|BjwW5i0v6Y^8vu<^UapGhj(pk?iCgG zOymZ!VF7~g;0$Ii*ZN z&Eyg5w5I@qZ(nI+oVc@h6f2%ylC-YnoFC3=8jTrI{mA&i8GbX-+Ru3~jU@r*sh48T zG@&)tr7Dd>a|p^UXmAQndm5-4=Ust?_1YsLI%nRKN79}8733MmRAb_K5moxbSEl|Q zTm%uCo5#iaKtBUqrOk-cBj_xC=28+e+5&d60MKWu`smX>{YOZ{9B!BvIzx_IMb8f$ z;mu_iAAc=Rh|eN$)u(Jl)tRd>kMNCXv_8(Qhd-osfp=p(X@Uv@yxhCOu#QLgcSj=@ zS;aOIPqyHh@?ri=3iUB`pL*U;N!(Ez%e+T-31aeAwvFe;`^JSDtLck`VES;@>U&4F zTRXRI7ilS(NR3x~DT%~Z^MBKAPB94s|BlV=#H+E9QacZBn6g2nZw!PMW>;7y@7W6K za~{53n?nM{(BHJ(%%+kI6I!7MkA*yG7LR!|W$1Tm<4Q-AqhoS=ho9j@C)h!jS8<0w z>jXcA{kVUFFM~>k!D#jIuxLrJQXm8&o!SILis6>J5oQ+*~d)h?4iCJrL#Pb_yAE)j9 zAUrh(JxB~n$&g$+bycV?Rx{Icw97ZLQ^tq^R3L8im|~w(D~e(H z)cr+al8@d*c`hftyTGR10fq7^TniH@16yPXM>*_1hQ1CvKFi8}un~yODPW=-tXzw3 zesdS$xbUyN3*fr~`>(s~C6zff7IyobzFH?ZhsHwx9muJ*JeytOW@x!h%y7CR)`$0j zlJEn~Me4YL*aMA{f&hi^doPby+gYsV_up;E{^QXXQn#6B*Y&oL`}0@n%wp`brQX8N zT3R~SHEXvCmn9K|*h4#SnQw;3n=~wfcz7W?FRj-(8||CPmXA0?Et^@`{9-TH z#NvwAX?g%~o;TqC*c@^Gs&P-G&Z@a*qJ@SZ$2{W`8=DdDS*CS`Vw!PxfxtxDYh2=3 zp(-TW&TuLjk(`VnvUQMh8D$>Pa1Ok0iIO*9%7=5b==L~d>Y?PNO)@mUAB0IGDFxv;r&KOoU7$Jj>7cMOs5 z!MP~nm2KZsS9hk1!uH+h6&|n_apWDotk3zIBA_1pTMiMbS;+(`(4!Jv8|Tf0{x&+n z-)8Cj%a;ba!rsL=wHd~p$$1op|7zuRymtDH3#_C*{n~enyyMVEXxs-dswb)oO6iRD z=j02=@-b*ea~YKpkfAQAn~t1^bpP6aKmVmhZ}{Ja{UCg4Vj0*>EoxG^Y*q=YkC%T4 zbA73Ua>_f9yCqv|Cs#KA%V(S8F$vd&sih*UTJ@RA`+FF=ZnNLf<=2Rq%mIk%pg-@u z;c*taPwM$>B`8?%_FJp`b-(S%FyXh=X)N%-i5x_a`iSW+4$-q@WF5-(?K|YmQkN*q zTX(8qmCmf$2$khw^r-5#tQ3rZhT86}q9Yy!HcbE5GIP&8`%{H%P{_F^?3HE=uoouH zc*sL1h!eVUE7n9}mX_&yxU~r$knX9QS#BK*8P`ir$LRB>7P>NR8XNHsM#r~^rbTIr znY6z47dtwT$L*&ZvzAQl@3PJ5KSZ*JNnEW?lcWt=VDg$kwV@Sv`&taIn%eTIwxf85 zI%-bOC0`TlqkqXi^6j)2=BHcOZ0JXBvVtsX%ZbTPx^IQ>B9phDD)Ltj+>Li63puFFb=jeb^A70-YT#-^%-32S}kM#%7QhU4S-v}qp zi}Dr)7hLBqs>Lh5hSlps9o~6DWuw^TDvS0?)w}p}Ltd zA2!5DQdd#T^uj((?sq1m=*S0;RdGSu>%SP4KF@?SvKdU|zy}M+VI(y1#f{UK&;Ggs z`Hv|@;+p!VuQT$49dza{c|89Tr8c(b*O2FV_XBrA@98S_ItBc(hA#vCl*W{<_i5ed zXz7y+;06k41<~H~8lM#ldo|0nIGR9jR-lg#*$e}p#hFg`Z_6BE5nq)dk(4yGUkg4G z?q|7yUR|67@4-q!{}>T%94A)3rVe|NlgD-Fib9wvBU2!P;ERDbpV0lxBizQbI{H~lL2>$5+WBQau#ziH%R zW_*Oz6NDF_$abA?_Kj|s=7#w12XfHox6h{!!t!|4?`64wTCP0S+AKqL`)xjEPlP}c z!5b3BNHeU6X&f^>*qwB!M*(1T+-B{9Pwc&{+g#nGM}u>;`q_63zS%Au5-G=#V8ndi zSKJfbHY4{JsfxIcS& zuQRL}yj2&Rm*#^_mc9EH(Wh^`PP{5Lp>74|z{`o!5=nGcY!G*LKG-@Ee;4Bu&$7Z? z`cHBfvKp7vXvbgSXFSDX?7p_o#;N*LrT=EY<)@`AvKV60TO#dA|HB=^#!sUCueDU> zWN)|RTT40t%mXC4#W5x8@$B3w2JX@|GxoK%cA!|?g-$a+N@_AbnpW$Ys`>e&i+8Kd zJ0RcCR<6MQzXq~vSYIcjU5B3p)pG)zs@bRs%!6$O`NrW^lZVQP0Z!1LfC_6o8wBw3 zsp@VrlsSY0jn{szRfQ}LHsSTOVRiOITptl8f86Jl)NFQ{ouBhJgrhnPE>G1zwnUUS z-FP1CW9@wTO0s;cn40^Uq0WI^UA;s~FRD!etGPtZ=4yq-PRZKbAigyoHPf;dzg)L~ zR%P(($E%Bh1rE0in13GA;SD!y$bqUD$E~$4KxAKnrVfTyOWXFJ$8nb@g{Pfnu z>KX?An4<1`@^$70nCNmTL)NgQN)ase^iej-Ct$2OfDG^`ELPl5iZTj(&1`$@&@$fGe)ga_IPg~}Tt#_#I}(;!A{ybcxP!ZX?M-CSaiQsU1UYBJx-Mp@ z${WZpaU93S>tI@Ag`V12)T@6Y8BrNzy9ck&H@0;P`OK6A>Z{iI!SA4Z zCW!3$e5SxIND=?LWcfh)r*Fq}zlrJ82qJ%EciX;kZ(`=M6lwYdyln8UtIgoD{hcKvmzmx02KN5{~2sYcgiwDdp7JlF5iB z^kh0IJaTxi4j2NFFlbmem}epWOTR< zw)5pfM~})05lEP-CII_BjtvTNkZcsVaute^6N2>v))(ZB$1|RUp&5klP(ht7;%vgj zUvxCbADRtnE-HHdI1Cj1Vm|B``jN;Qj!l|Ssyu{OWE@ck%w&GOTJ%vfec@@i(8tx)q!ilc(Q+G(7_@6M~#VLivb;`g(e+N@oNGrjc6o-(a(D4F5K&^>dk zqUvp69%+xcQ^O)Tqy*(RVQdG$Q{V2(QH4#n;`hm52Wz*AToCI8HIsrYL}9&yk=c^2 z7_ippuyoW3HICC1-p|p}r39YdX~ELa(6GwJd?7KAL!qw*ABJW**_8mu|hArcMn49!5TwAPYEeW3!?R8;zjCMIu;fec&!wHFLS zUE`Y%RM*AaTykmfEPVghKX~?oGP2V<>aKXakhKlmP`CLvTMo$eN$5q}u#$&x{X@!- z;MkSA0s{-R5rVL=0s~*8>sA#r{R*i_3tDrtKT!PbDt!CSnIH?>RJ=@Bw|SMesL7S* zR}JNAN`A~p-XWjcYLpS%e>mhQs#kxk_*IDzt1rq|xQkn@N-Mi3`7II9F!c-*I7Y!Lck~bkV z5rBd7#Khg3KBXB&IoD7OO!B-?@NR8}j7DuePKiDyqOiTGiVpsqOm?$w0=hH~4ayCu z0zaR`kzU9fkFw7p_G$;}!F+kU6Y{QVk|zEIZg3uY@)*cc04MkFgNh`Wu6m%}%~gl{ zjvnFW;JB}}G`6zgIj){^oKi3TdmGo# z$ylIL%H5re`87I68*p{N@Uu#ao!gk5Dt{oZC&PQ2)4(^;bJ47pYCb^jcM;c=Q93;c zA)y2|E8cSZYK|2yz0M50H;uYlv#9Te+e;ew<0zaMEN7wT=aG|fo{-L5?6#$wo#s(z zuX8S07$jOVr*d2tHemhm^f{))=CZqJ6e&eBPt?9{t8`T-J5#FY2EakJrEpm zS~rE1HmDPAOZaK8I;E5xB>H4ezGS33oW%u;CGoTBGcWMNrX7rRSE6nI6I3xNapPwr zePpHxxwqW?G|e(+BA?6v$5>Q@ORG>Yor9Vof=GXKctCE!S|IO%WYae4NvD)R@1Kxr z83HR0lcq1JH8*h+S(Y_!Pc87aU`z#wW^~VI)O|9{*ttJThtYPC=~`GT2hi!|K0uA@ zDvsSr%^;c-j7CBKA_7$$K*}Q4GpzWhfR*{do;325n(f_sz@|+TQFG{5V&~Gd!xry^ z*1Gj`yNiOlBsBt;x7Gb`O2k(Ds@pd(Tmk;@dz;;6`7xKmro#z&FL&|21tOMz<--7R zG#n#6CHLxK8$8Cmz^G26tI3>GLM0+et-f@lFumxIYoMYfR_Z-IL11oMVUyX)1)Ek|)~1F%!s)4~=$ zu72i=B(na--GNqJkn)I$D8-9G-X;aG{4oZg{KNVWs#^B7ZF;G2&!`yB*ogxX4@3)@ zpU5sC)(l|_kBuq{nfT89d7cLkc(M(T{BtRF#(Jjen0%quAHhE93?O0mGO zv_T(kXoL36QObUSW5?09M_N~P{fmc>v)i*sv_OtKC2~=lC$;&=|0=(99rwHex zQi=!=OA@BR6m1W;Ut=dYf9`~DT+uNWV(U(=1bhnPe1B$}4pTRuAO2ZHWpoO)?XZ=t!h{OCqw}FZ{)g))Oqf+79H{PTO z)`+ge_k>s)I{l^HbmUjSS3s;Vz0@8@ekI*f0P^EKiw_ask@0$O7zLGWF;a3IzE|*F z{oIkFZEnv+jm=(ID&BNSRtb}sYHm){D?6FbsXt62wldd_>2~-K!%P_uFbzSS1^Ne_ zJ*$~rtfqC!S7;g(6tY7KJQSePaLV7>Ih~WEiH8abS0f|7F_JeAn?6Ndp?zPs`kz}c z+vZw`q+0u2*J?zO3>E@(wM_$P^*5vlPGbc$(EBdD>W1O3V=dJyZTZ>H(Jv`KM!2x-D zYUhlYZ%N__9)x6x%6 z`-q-TJB~~CVbwO-KC}F8!>8d<*kg&3Ohidueb)Y&_Qg_(Ei7-@OwWuUiu0y;nM&|D$EBLSb^*q zUV=B3W|IgGdt-MexnzyOTzWnSiCW2bLVQ2mJv9Kx(g5t5e4T7LC?wF5h52$td-6+| z>YWc4%c^2^->RG}Cbq0B2pfcX@Z(A9)Z&Xyg85_=KsDHU7&+&^e1T`U-<0yqkHP(@ z+#5d1-kDK@TvHiz&FM+VE<0-4ce$?0_e{Y*p9%0^5}l|_6`Mvv)BgX=~UEN_=v%7@bBG);d7zHtz>aS!&gsig$RL{7)sb-Uk$Ea z^s;OY)Lw!%(bQ==uziV((C1oj1BA~C{fQHwIhJg34Vs!?yzLljEGEqXs0T?I+Q9Id zNA}HIgrH7UVS?_R(1KmYi0^Lty9jqGLPXTatT^SlCS)wxE3vEc@DkUJ9Cb`Gw-DaIdR>^F9-LMV_+t)UKH9kkYRY0SN9(>qMU-DKsBNl7;4tWGtPbpT1rAr&M>g6E zV1IAFkf}EieZ>cv)^IOmV`+%XaeQKjwmW>k4)Khy1?=LM+~R)K{5@q`G}TxH9z^rw;)-BxoG|BZDBLji5OT zF0O`|n+V!5wj?cA`~Q+p5@{}Dmx+{q@2SFLd-%xT-1ppF)EpkbijQyBB?(jJMrC<%wG6QQC)pG648$yzbjB%jMhP8F}j(PZ7*G!0+BZ zLS4x6N5&DTjg2>EG(p{%T^I~_Sm>bN`tWI?!n0d4N^%bp{f6|IzV>IeFM1^b+$lee z5sv=pPYm{5Ss8dr=?rq`ecObX6CMtZT;LG&DYr%AGFw19bnm6>!y0}VuzD1Ajc6YJ zWK(jLO|cZ@njV_zRGj6MLt}~^03+kVUSkgd+!XBxa@F6%Idqc4u%<6^J~En#7uSxu zWVy>b_=GaVUCW>2_4eXYK>qB?XQ5Yd&1fGt5v^Sc^sa=~1~SRdA7sCXCLVM)l|ibz z#+r-nCJkIKORmjgo3Elbkwa4~IzF%~sN8&ANSBYs0^DBEAdVW%iMrc2#4SHi>WYOb z*MhG<4sZP+NRkA0>?t*vqv@4-JGYEm0e@IT-K=?RbJ7BT1;!4Zy383KjLOs>5Z3LlQYK>h_-7afm|MBhGbY<4eLB+GBoS_l*{s7cwe& zwQeQzMqk_FxH_dOgn>MkV+S8{R6@K?V|yfwG9 zaJ11A;Ez4WTS*R^$peMq-%S?|M(JvIsAP?Yz;L}u%<$t*vG{*$!%lRkMYq*w+y?{K zM=h!g{R9bsDq(sEZ8ni)aL`Lktrp4Pw>fd|HGxa~imIKnA&82b2Cn$8z6;wGmV#?+ zpcP5G+h6=$mEuN;OXupBSV|%~V%maxh)KVFfi>CzD|B}#t8o4A)dRO**E}iZ#Tk?^ zbdA@aiR;6k}(D0(B%`eJJuq_*CrZd}tJr+@aTC`mg+%iz$FE*N}>^8~{Y29qBWXuCW z!ORb$s%65#Md{acB#>fL7`AYy%bA~sfrEe9BBOQPKuUYGK<1>gBi@B;*1uG*wN0N6 z&I#oAou7ZcW*P5^p$k_4Eh={IJn|kA7Vv7(7cU^`s2bdoUsa)#B8b4U2*td%s_oW# zza_n`V2u>LJpynN|-qkvR0licLxeOC8zL7`LseO@?Qa(8`Uh~mAj+J?XqDBaO* zTvJb=;LstO2i7ExLzB`bE=Ipn>Jg z?*QAsFc-+}`yr=TGb-_+H@!K$cHx>am{Iix>RMmM1JO<=4VK4q9f}!vT;vj$GQdH1 zyv9<0zmePeb5wN@;wmPGF-=!Obc6vjNLK;YXp{(HTP+FOBI}?=oOtA-0`5PC~DklO?`-9N|zz^J1>ar2t{sqCq^E2VwMw(1p;p| z%dqoS5sNk$)e@ZxzS?4+7C3x*Xv1C8Q~!`ic|epfQPK^n=Q4g>2$BzuEg-%Cq|N^{ zE@4HB&n#&3W2K*Wb8O$u9ymAJ4`4q4~vBre~nA=;{dGDV~5+|hv;+bWFKE+ht<#W~5u`2)c~ z=DyFd5nkyL*xfM>UGF)L&K(%ccDPjBRWJHSpVWDZLY6tk{X^-TEiC?C9SAR(@;RWW zJQ?bzSWGdh!Lx-5RJVOFB|7O`Z>wuq;^^RoZmOXRv;|}trHEPELVF@IYeIBU+K8*R z*r{{A@nE(X;(2hrS74z~^76me)SadA!>8w*vRFlN)OKO!XnetVW}Oge))|CyhDgdV`@e?E`LcDEeb% z4dvIO-iXahhZcl8RC2%P2likeZn$7Qub{1?pow7Gpeit#C0$Fe!~o;npxnPqZZ{V9 zYxwo2?BhXqoa<498 z{^oMp5Cc!$yNgH$s!z|eROFd@VhICJR!QL8HTn03qdVpRmDoLrM00G&ge>a=g5~=L zG;Dk@WMLg2db#Xic7k={lSOZ0d)fDA26$$5^-|cTj?)d=K3!3rP}G4_#8cB865BZ? z;P1q;WLf&)eUzp=WF8nXC`b1P^)x-zgD@yVsaWi4Y#P?; zRT5)-=;gU3JE?ZL)_$0|sQMiF4rJ%X7q8@1(uO!|Vw%@~Wi1zCF}8iRrp(}7d+9Q7 z`w_cnbF)oZ$K2CvE<3^~pgi#sG$VPlYd^eT43I3nuN1@tNb0S0txfv+eV)zj6|J=H zp_x;26p6>&6EGFbS;{gSWLM|+M)ln0+wKRJy}parvg{CLtWm%ssl6dv$j<#k@Y8Cw zxiXwR`-4Q{!0g=%N`?)hP3-n%=sBP-|4SjIXF4dWB zp7bMD>Ql#l=!MB;mH<}d+aGVAVI(E81V{dCamm_S<$Vd-_-*6<##Y48!2fqa$834I z7mq6=hVf}@41RlKG~B=8XSV&aJZhxW`ntr6NJG(?Kezbb0}}!rc66xcwev}SfDgF? zE+x5z^x~C}Kcs(4*>e970To!}tLj@Yz{D`$^rCi=Id!489R_zQs9jcUB>2L z^f7x{;=3kHo6BpPnLdifq92kkh3m=ic5NF!uI5$|_+o3D-QoIb7ce|)Sm>p#?okuZ zb!DeW(L}_+VPXj+{g@SSVzyF2h0Uj|Po3!|cQO-JthBy=JFHNev`bfJQ!@yp3hwZ!#!J1}#RX=|_vl9Uz zKCV{#weE){6FS$dc*N7)U+1H!`rTuV5g(ceDHn07IvwnSp$cb&M4+6Je%lnH-=iH6 z!1%HMYED^VXtY6Cm(bFw9nE7OKL}(}gk@{8DIhLT7XXhs&_SEK%n`ZLo0iMK!Y6c1 z#>F-W7|uU%0!NFydo{_sK(I7sV6QKJFs-runVLjiFE!|H_-JI)nBhy%b(9S^8=!Rd z3`g&lkTOKNfxgsy^qh`ZPM%guOgZ7%!yf#kv(GO zvSPoluswbBld7(RYybpUZa43h?Bk)>S_OzuPhG;{Jk-eM+iq9lI!JrTOCAzhxTc{n zvN@{iFu>=t+wb1aW{|qM*()b^JPFY$1%B>1r&(q%*eN0yw627O>V5T<7SbJ`lV{4@ z0w1`l*kS)M>R^*B7L2f|tD7SDK=>B~Ph~*G2eDfgG=d#J%E$TwH(>B1_u+xz z%Jmg`#QEbgfsDH**>aTw6;nL9IZ*>3Hy`00D7}9a{O{c>{Gt`~zCf#SE{*}3xUlB} zLS2A}bnzRO1Zs8-Sic>~SK7_W`UD1MNLE)9vVjCf0^^sQ``v1|SYSu41pDpD3nJ+F zVoXGn3J9{rB-sm0CiqMUcN~U3-Gw4ZHG7lg8`g{CLiyb{`bbyl9)Dk|+`T8bN&ODShbG5F89^l|}K?CG^B^Sdmo#g#b zZfq4pG;UwX6kdQ zje@58c}rL~h}#NNm27wk*ZliY3|l) z^?0Aplw5-J_Nuv0q`8i^u3&@DU`zsmzQtyKp5iCGMk|TQ*MyiI#x@8;z4-;}17884 zX#h{X;k(m<*&caV`uk{EiS$?{L5gwVP+rOI1EHm_i`AdGknba|`X!dmv{d8_1Tn|D zKi-cMyfkRO&G8eaE4#(5Q4e@^MPx*CIQP4Pw0++jw;LVTG(9*xlcUq7*05c=t|QL! z(?-G5x<6K15{Qj(pa_=P`_q+GcX>lddeN|UQ)Hwa-mjZY)>Tg!#3mmIla4gDzrN4o z27uPd$+y86OK&X~BT$MQdMl$pAQqI)>HmmVe!7cfZ{jF;I+z`Xb>zuwk)n}tjhZj7 z&>^|t(R1Zc@oi}zwy?R5K^`v_mU?;b#l-1jo&txtzN_{NHljQ)w3`#Bf_AG*IpICn zN07|%JW<^VO-fx;@tL*Ux5Qlh#{5R??Xi%e?TW{?!m6iCvVkI`@@MMbPgk0dtUnb) zAwy**wj&+kw~hvWDisOm1x5^SE^eE1Om1AB4KK~2iK%Zdo~SP$YpOCt*Ba>6F7Yle z^oeckjOnITy#C6QMN_voD#vgyozAprk?Cuyz?imQN5!)uZC7*wf4~Sh z=-C1!9=t5$9ivD?3DzEZg@L9;bRsjOsyas+>H`X%*s$N?lS-n8&aTRrFp({+x*&$j zJ#Y0g0^TDe8|aNMR^lMPy+N?Y2b%R8JwA&%w-LLhXI7K8%y%i=H)p$`f2EIxdYRK$ zKqBq7ikU$cHH7YAAwGC4CC@$moaV+mo%WAqj#j>VaJgYwXmb2Ei7s!;wI zm3S9ylzfZ$}WdTd=ppxiGe$E@&Mbqr4?FjIONU z6v>O#mjsEZ*ZqZHEwih~W|%H!D>?`c$<|!c!HMyWd|zJR>$PvNzyivFg4;h$_Z+0c zX%qlIwM!oV0~u3eX- z@)wd_>58Rze`AO79EJl?Hg#jzh-u;|TE|4o94@Ip`vm*?C`y%KB~LF$6GNC5S{d6H#l}?E?USgd(%Qt z2;Hf`>-e{jFPGVq7ukb9PZ-?#S5I)>Es>NDmQG8;5Vfn_xKKoO(BsMf5zJ) zpuV2PDYBPRuE((!$Pdp}WR*B@ZT~{BfAIC>;Z_m(%7hCR(qk%+r_HYXl3LdKwa|@` zTW-PgSoF!8DTuLKFV_@=XST|LuEI8>(w4Pu=rtFb2FX#e5Yf4adx8IqV{y!) zOZq&b=Cd~-HRLi473?HECJV-miHSGQPFj#Z@zp81lJRnuuWTFb%*H<^pjjWT?7bd-Qt=IgjM-sAg zcID<+&zJ2kARi!Q2-~(Rlu16B0L##GyJ#RZ$rQJIpM16X=B;M`tz!R+0UKk&EkrJc8JY!<+ntbAWp*S-g)%=PB|B508QHYcz?eLO?6+Wp; zqL-d!>BR@a{abDw^%h|fo(p%BhKxx;MHzh~1|sj|Zi(bjt0Odejvh{O{JF(>T>y1F zFjxJ;twz>hjkWnK)oLjU{`mRA!HBH4W7<8eWBK7kNEyFgwo^jnxy`*(T22+zMJw@) z4;JwF{{XE(Qop^RVVL|Df4Ydt;=W3eH>c|`0W!cdMdyrpA>2ecVBsTU`IeoHivC8z zF+&bV{WZ^kxiCP}V&OtSCq&U0a2NH$ILab)umpps7a6>1&~wAiFAFFEn=f%Wu7z*V z%yo(v1e2+St6E%U0RLx<1?i_>^-MYUx>=C(Et~|HO*wUwj<8BNs{;#R-U%NlN8w#{ zp~Qztqc)e2eP=QUv>zv$+E%APjTB1_3iC&lo?=6FDlpK)1emaf$x%q~k=g?qfFRW) zA^{?n%!gyVXQs*LCNf#2d%BqIv^eaDgSYAstyis58YPw%7GYP6M8FQMP5g}w9N3vX z^z9Oh*2;_1S+%~{jHPFm?O zfcPAT$ulq22gzU=x@tjYTIRG6`+sR9LM?{&h}^`++$I;f9YWfE+;dfe(YdgwISw|E zM3LW@1KM`bJ%n_s|#B}W2OeeQ#OJw z2HPL`=WW|Jj#x|}BYsj6C_f8tO2-8@$1oOKQwna};aGF-?AM!bHQOwJP5l^Hf2f^th8 zETde;A_rde=%l<8g?jH=9|0}g=x=__2zC)|3ZUS@%#FGDmBX1sO`3(wn&jJ9!6GsY zBy7qb?9H?{0#?urELRYo>T%*=WEIK8K^!C}rpCb+=uG0HlM5A_1ARi+qG=9v5i>?( zc%CN$XwX(-dxFo1+UY{VW7q#^31i!UVeJ>ByXiVc&|k92H)r&cfK5=0Q`(bAn@Br; z?%&(Ah9sky@03MTZA-gI!XQ%Jzi!+buUf3Yv;>q14LA7#rsil38|49xA2eM2=pPB^ z{}*UTWYKJb4?{CioL3x}-xiN?8mCOwEr7~nWrp@lks{Lj>8vF41agPUc4Y;#Xn@Lc z5Dh`a=cs5&g0We8`+2A&=^kL23^_kbNeqV|09Jjb=%W`ZB<$2n(q!S$vS?C1KgKQ%}YF^jieom72p!+gR zg?Q={=_H60WOogSQ8iX4Z{6SjbUGpXW;o|*9Hha$*yAb?P@C^~jW1PJ$>LbhoJ+7o zvI3tUKv`ffLok~ZJ7Bt#YzT3Wy;8`fPOY?x08uy!90ud^sR2QT$C{ZU9F&WYs*ou( zVAfax8KF*4%pUqkm#_jYlk@?RvNe)kGYtMgBx8y6AS5H3XckO4ZQRV%L%}35yF$y2 zhGT(F1TlE1aEH@DEO)i4R>u}tsKM+m5KLk;(tAM(I$X$i($xWj7&5wSFd()`b8K>1 z74a4~b+`~;2PQ@7Hn0cLrzk@?xi{RP5uJE6f`;TjlyRFtpV09>$f%_$*8phXixPJN zf|spmV|T&OMnNZESK6qk;|p(aQ1EIN8)2SZk37fMCqID%B*CU2o#f#GRJd8GYQha00OkG-t-+h0Qj^72Q<@`bzN+KDaH#$BjEIckp9fh1H~KejzDvH#^lJ+WqP)k znt@-i#YE*h2lr@o1?M59tKrbs~}UMoAWc=deVLN8`H^0ERPxVQrwWxW?wBQtT~<`NbhI zDrUe?7hoeQAT*@d&D}qL!n+IT1ad_vOn>k0i(XNo5(;~6(EMB^Z~_r=pu_IN=g?Ay zm~SPVs~atj^#=6KaM+wJoA1 zAIF6Ifm#b<33yVr8#GOh#Y0*9bjaBeFlWH@qs?jl!I(bFKwRUz$#SIPU@K0%^3g($ zgac2)?KoOVwjV8r2}XYO3WB|Kzhc7%Z9f^8CA)Zy4sI0=Y; zb9aXQ#(*%>OQMdLOtW%GT;Ww?@ni!CbYgkEg^M5+E}g4j8-XC{1+pA-qykcT4BKFA zW-4_|V*`^OK$l5U837hA&tVADmN=}CSOTuqAP)P$Fi^kIoM;#hA!OsRjCn-3w(*nh zd=%2IaLkRq*Cd=xD^?I07=%O2s5H@!%Q%Y8S_)_n%YaFC?oCx#QLqBYTycw(BgQu? z`W;T>0ffXr?fe$8ES-uPy^YUcVFo1t&LM(|4#<=BQ1o%Y0?_~f000bL6953=CIA2d z0U`ii6Nn)o00961F+j5eH90GrC;ksM@yh@JE4Um8i&F)FcFdEHjZTm>8>Ni^14F%5 z7fP>H*~KYVtJSC}L-on3c`%m0V~q2}RdE|highAQdZ29gjSF=vNRMBv@=BkOc(nwJ z@D;GtRclwORUG=elqPxZJC+lx)mTZ=Lc4s{@a^>|2m9c8vA*W!h{r0+eXd~t#$#CZ z8T|W}}}8>v+JDkg-f$r2F}rS*i?jLgDgw@{D=(yP>SDN4MP<;i0uUQbu6CrVVR z^-m!z_KC?kP)0A3E<)_&0^2|fX%QSXFU8n5$=FL8gB`ce5rUv#^AVfE0P{jrD0-uy z5sARCa4!t+K{#pPu;hVwXKHo`-l*p%$>L)r=f}AZ#@oA>qVRfM$^ObB;OC>{{J8+M z#g9!2U|d2={8V`#tTG@VA`Swu0IA(tq94@`N-=@~+h#F(gnYLXS~#)LOksK3Jy(*u>!l&Bw=z`Zk7v>3&MenDDRX^R)O`~0 zu$mXxN$9kZh9FRqm7(lNu{zAG|$#p1Xgd+^x5i369NE05iPwNK-V|9$bJo7Oc1F~ITlK~KMeTcVsQrZF|(6|Sgr`ofd7ppkQ zx?$0gJ#|U|R{dR+r7A2A)j2rD(2`CWsoL0C971C@zPc~!G3-_9W_i_T&;YaQZ`BcY zZuB{kc9Wx8?wds+^U-02AEXdrpJV5SE`I>SE`(5_<%96 z%u%hxs4`wpR2)nQ9}oeG1{6dfc7UZc1be0#G{#NB`eLngy5r^SoU#gR#K&wl^}9&O0*D@+k$PeRaJq$wr zK=ZvWQ|5f94f;Esd135)r^m*TWFF{tPWdIsWW<0Uey+j*iZxag`41ohuT$i8MKvWw zsUbiQBE*C|!01Q-+&jV@55SD$@M#d)@>sy8tLvbmVWyZc>AUW-Xnyax*?j#6cUY-~fZoFR^>AV;zG=T@vRO^TW|Z+Or^CMcGx?2Jr#r zm%i?jCeKfnEwh}n7W*xQDJZ0JA7P4`33c9Q2p}K8ltGa&S=9xOUO>p=6(N^AdeAW% zEpQCAIlP^yEzcK8u)D~xS#S-I>`g|8Illqs*kW5UQcZ)bztgGTc(K7>da(s=Itu;q=$q9-+q=^CmHXfESwO0i66X~$VFppeQNCz#zu{5BC zJyohXumV;Bfb&o5A2;T^W%9vFe$1DqAa9^mg=f*sdpbJr8Ht0-D1HTbRL=kw!-}XV zq~w#XhR224O{tqjsVGpI*E{FaHMkIn-j2kn^mo8u{YyJ?DN>?gd9}vh!tIV^mlK&1I;}!@Kcpnd#Py8altT! zCzP{UC^F=XxjPRb*PqFnSv-#403*J(dP%YIfCP+zH&9SDqpIzqql~JIyzCD(#>Hsp zKjc-@iKm3ZY(SgyEXL2(5CeLxjh}%mq$RQPzI$a>HU=*I2U=utw(X6M}7PP!RE4s1jc|{0`QX}L$y4S;_hE7 zG&HAth~=bbp;}5uM@0`uMqu{10JbsN)Z~eS*ydNp6P|l)s#r$+oM)VY5p`o$BN}lW z5vs36O0{a$PPBTf%w+xs@86u(Fz<}>$dLb%AOg_W+mpOv$Az01LpY9wvBYM8$SP}t zNrVA(8J{;{AjzNyQawo<;vWPFp8^jw@a(6vM`gXnC}zja_?Q0^9#8>KZXetjFm~UE zV$-CaHQ^p7=q>(Z5xg7_+`QwPOsJ95y7C6aD1MHC7CKpFZ)S)%BaZ0kxR>t&$}i_9 zqrDvxKcyImlu>xo37%S;S2-7cj`VgEBB@vsOeY$tSk!=R=e!mC07|I*v8q=rFrlr@ zB`ED3IGH2W9dk)V#8~n?)WqqHIy=$P%bxQt3R0@{0YD3{&Nx{M?~>KU`a3ax_zWNv z-@x@=YlwEnIKLm9MYxL_)WZ12FC;~td-Yd!Wll|AO;K7^$W`v*07(6N+#0o@%aQ|7 zM<0);_d~GR3(RG)JJH^&2m!w*VRYmjP-}(>j?ZV*tH~Z-@>oknRRy^0*>VcX<7P@C z)qYAXSLDs68>xq@2kLy<%71zMmV5xSuqpdW2NKf9rtXK37B()@Z_GLlmT^%awEyW- z#7fBYwb9!f8r;?;{ZolUTXQK&J4bE#sTs`Le3O&2_)6|w-@Lr%0xZ`(fe{bL)wCJ! z7Ep>qCRbezq|H5~x5$w%x6Mmq~e{B}R0%R~G{B(vkp7=q%6z z&pxc`=aX4zEIl4|U7T&z+*X^Z9Y>pmO>#n9mBmg;=gH)(01tkvJnct!s?Ujg+Pmgh)}{Pq$zu^>#=XUQuLWe}w~Jd?_+bZ8-j)OhFA^yRJsM~#t7 zM2(r!dYy{CldUK7U!AgUH)Z`fEMX2u9UT1+4>80m!~@QEHqFIsFa zlkX(G=w?FX-V{fYig}xXeXcK8T|zjhbOzMsahmk2xXiArp`E_^C^KAo)y6s>Zss@Q zrzG;LM|@a3+v8_Xxzgsve4mngzcrBH9@x&V>iRw2fi!goD8nKA|B%`Afx8@hIQ(CJD^6-8tOnHmR-;sU z`vGyF53ttGtLks#gUu5h@{DuBSvSo%lqUXA?# zO%SUnq`gP)bKO1Vd6{6rIb`FacnAnQBqymyYVujknQ2u_my!bpzQ-Z=xTY0~hHTty#ka`VmAhEWsq23< z2cNb5ee-smO5$Pa=bkbU0Jq=dhzEYCl|Lo<^iZj~lp$+J1!$7KgGbTh_pldccA&^z zQBnJ@vd`!ZUDj?-ma_%_Wxl5E5FPYUfC!-GYNFmCJlKR_7v_1~`0>9NV@$y}bjx6X zzE8>M>sDd_nhff*hyb=YPOSRsGm-a#MjHMt0wsw}uCKESFpX~klp!?0;2`P%KvFe+ zOy$eE=oA}=%64cH@6pP>*!1otRriOAH7ubZf! z-HsnNl--Xxm^WE4MAs%RHmyAK6YGZKpX3NJZl>Y@9fT*dIGd&Y6j(uf_ykK5@C?39 ztdRr>$ur4fn8WB^{1AyRWl_(_9%%Nzytx*!<9<{BcVq64#k58+!RS4#VCnM_e;4b- z8>iY!o_b$M+X_$bJU{qFsn6ba-6R4;I46atCaLe$a5RAK zKfp4LtLo8B_My;zRNY2!Hwllf^*Qo->Zr43y6u{AHsOm$s*tdoya2G`mJ%C}!;2 zCi~;{{|PYRC}1u<8M%h&)|rku1&g9utGv2Z-BR3S-UvKx%~)(7Qlo2j z?RjN6335?4JjolLNcyOJoefxPGLet$r*GOBsNi~i1PFu{%imsVc$YKgl18_Of`2d) z837UK=^B9Y58pRP_ykMLm^f6QOVoTKfh+F1<^k7Ls-)9=FZYKOf@xDpbR=;h*A8${ zFe80r0HToft^bAjSPc#6>t%yZQ4(%%A4<<&tLo?YclM_TT3Ro7O*^ z@!bF8<$gBY&$`SD#wkj!dxonDQQh5(00xfi_5ckWYcQF2H=LVeCWvMq0EU6hy^RB5 z02ipRbGv;q4m&UgC(PgdGd;k55rkEXJF{s-DS~T92|k3^E#&_3*rge&H60Ts&}D(X zN;K*!8Myr=;-5O^}-LQ4&$D7>d(g?7S1um(4uC#6)M%6>&!D4 zdot$qv`_{)Mc_w4F2KOAQ*bEpdKnln00@36rRm>qA?mo$r{LBBw z<2{M)M8{8k;tp!BO#GG<+?WLZ@fQaZ3wrM4twezD6`y&!?j{}H_pt^_JBfQ^KySE* z>?PD#DYo4~Bmp)uZH*djLk2*h(6K>7(;OFY(?8S#H9SizVJQ7r#sI~<>|O#T0!|VW zEd^h(n8;lkrAm}_iakSY74smI{QEZ(f|Me01Wvc0009g00032Apm>?0t>tpmj)FG z3M2D^;lOP-K)phtoPt~i@aG^kK&Y_-L`Y&lkW?iRZOCA9z+eDjAOHX=RJz<2AGZa8 z`AQ)ng2IT)BLg6-5k)*h5rfENa|4@)O_(hd0fL)=GUt9y$F#s&EnihWK~RQOIyP@=?3s2L>0$G+@}=LLE3A^(&jeEi9f5aRbqUXWMPH&Ec5 zd1wx1_JV*yH5&-l0?=?swsxIbN%SR(Y9tDfaSbX8Fkpef%upAGjvz1uULo*G5{8|2 z0VHLS-=H5CI6nJi5{e5|6p*dRHx+eMq7BEa(2<`E^D{N{+y*!p=5s!0;H}b>ptKyM z6oD-uMjT)Kl86-|X*j_z%=7p8m-STMSZ`wbdaSpr9fOA%UR>VDd=G1`UW++@SwE7S z&pzk!?En6@J0a^PJ4Kpjoz^tjH^7?!3(Dzd!d*rB6Sbns`iWyQK)I~XPXJCb4l;d4 zd$#C&W?t&Aj@A})OqI96^b3Q&%?OLqAN1mi(=(38SD*dIV%n*1GYTEk9+v3s;#E(b#$ zr~o!wvuu3>Ajv>wbwFo5pX`;eKvUQS58|N(-VR_O0SdRo8f?uq?_R%`8H{XnirN~MkI+_mNA~nQ9ytU7N)ftP+F)Yuy<9m%nGe!+>9Dk zzrr?ZpSGhW=)79#AwKCBB1IIshyDbw{#kB;mg?crjRPkEmvojU^p2spev1^gCjYw(N*|WB?t4Xz={lUXdOb! z;HXFbK&wVGLLa&c6cMm66iMZ$pa7>z14*c)7pTwQ)q-^$8(?+>SvR59U@A}`BN$jZ z7W(ON443p3M8ZCMvv@wRBz@ULa0I5XEmN8sZPqY=ixibz`nrh;W`$O=m0jxcSQ3?L zymebOu(0!swRbXFf=`0KdWJWg)2-CQoKlKJCRc1NK5E^h)^$P)dN`=h_5z!PC=I{J zLMg#%*F0^yD3XCYew7eLgH^p&d-pj*Ztn$D3L(u3zozE#wOtz+PLmf3b0UUHbvI}I z3Kj%)aD^W_SEpflNCI*&j-4yI0$g9=rPTz>nwA^jfY?N1{Fo>VYGRU~2d7D00D=Gj z30(n88vp=80D}V3d;|ah4EZ1c00Sog0099Z0DT;_fvcNm1UNwAhwg=3(O}t`T4wf# ze`o@svohr#eHd+Lh=QatIjgW6nuP}uL|pnsqTjd*KYywQR>i^L>9G(o#~dLtE8-4$ zh6qB**LtkbT|4V5VUDSASxL@VY{W6}#@J1o>W=-&s zF~RD%9+burC^#Mcn94VKXZah9|-a_@92}@ zIftVt5Cy1tndJc?{4vnT%`7tjK7cTQAXo!}) z@}*zqKkTk)+8hM!eZ&+PM-ip~PBkRd$&s|NjAfD@2NVV%f-HiFO*+3{P3dW%futnR zsKHlDlSpBL!UZ{=OF&AXGkVR9b<{CvaC!SY|0c&K+9LA7KU~W%E)1O#I8@n0rwy5} zD0;I8sQZicX-(`URsFIh@l?k@dXbjVxbr&<$50u!7z?B=WB`gC1yLn{1hPbRIylT6 zQS`;&jVMS6BOg*mU_F2pkZen#vVznCzzHa|Kmk{Jgg+dU^tyyMrIZ~j2;yKk0Pq}3 zSN;%^gdC%IS}Y|wcWM7(AO9>SNuW+C1dId#ao8%mmFTXLVhR#)CjAUEa~X&SnZK%! z|B+Ei~V2X(!st>D908x1JQ&=B!YpW#4=EFg(e6F*F=Hl&r42&2i_HV zZCiwooe(6@S84?0Y&abl`y%NOWLydnVp;$(3T>)LE|GmlA$0tM(7B+VZzIgZgWK|= zI6LlbDKu5oqyV@zefoCLL^WBTZLt&@&*Y)N#z8p>Jsf#6 zic%F9%=}hn;O`}T0$+=ksLd{~z*Tg^9tZo4RsarX0cwUQMkN-;MjIKHbHdY>+`=$y zRRAMFxGPOY>g6Azz_|Nsr}1$C&p-iCr4dxC-geJ_;&Hx9xL1Nq+044nr;4=9eq8SoueAbY#)(703*{?V)xCKr0yvatN0t&nRuMeg# zCKIJGmGGg{^&3WhyVbHl`!78)%H+%q{Wa% zha;j#gi!}YJ$>ot|A}SwaI9~s9h1LC%ODqYf3%VE0KCb=aoq<(j zY9^_gGFaqQcrzfcG9XBah?HSnwm5@)o~D>Eb%$f8%)m8t1ArCRGE%MloxU08zqF?; zlT+83=Q+z1>96Z18qa3b$7Ii#aq<_XCPr!&-m#;+C_Zl}1VJIk1Cu;gUmhwPCi&?I zk}Zb+J%=gSIk*v?n9!Z~+?+(yBryxogtw6aAqx89+wl1X{X4L~QjS&RXStaRicAeT z!p38p$s|*}tGwOP$95qV##>NcNmJ!hC-J{v7StvDvkb`X5WJ4yVK@hdamMgz>_b2V}3fx^Ykg3!sdY6=*~=<%}JKboD|6)nth zicD>RYL4=J^jSoosnz=HNzZ8(??%CAkwmhd9^HpOE(pl8W9z8(&n*)R;H)EOKT+mt z24{U?5D2oCZl_m{4>zfrG%9Rp?k(pR-)(ZJ1Eec;GS}2(b6b5(pdJmtSKJ!g=CRFI zBObAH*Aq@nxbk$O9IQ)YUZib~Oo15$hd3^rAAUiyN@^`;WM89sIK&(C@$S$h6Juuk zu9?uemhYB$A9)f7jsob1nOzvRqmQn+s#+Y)8JJU) znDodn3S)3jjjSLc&UIsV{vv?h3yq;vanDgcuhEtr%<`oYVWp z>+y+C8Wfd;E+})@LVrVUkWvU7BBPd@USUC7M^8K(2tngR7nmg2Gv;pM8bXuq2Kk+%1Nu~2&Qh&d8 zlbQ_A8HjQwgp*KFYU^;wzoH;oQ5pEY9MNlWJ{5^@`aWOnJcM=;uGTE`!+Six7*CWF zi^+h7ZmJYy7Se?bI2ZzgW^Daq_$d^M5)`M$H=u%p?tZ(VUk3kyxF`Ssp{n<e*t^2eA~byw;2Se?w6Jl+Pktb=nPQ9!Q_Xq8wF zVvwy-_}1M2Cv*(D%eHaymh`5w^XwjF97bQR2FftDinXL;?;csgU*+Bp;X*sdzDI`U z%<;+c0>S9XVS~v4VuZ_3c@N(y>MeN3{A07|)>8P)DFg-2;V@vnPZ^jKoBNVS)+l3< z875b9!un&WqY^o1gm;91Xvg*~gzNdA1kXN7VsdHC8<7M?Z>~xJerF=5RLLI7=%(A- zqn%Ul=%h@fF*L$h2=zxQ>kGyGA|eqUwF$?k&=7iphcj)xInc;qMdJZe>fp zzr_U+>W)eg?dNXP@FS3)MtI#cg6PUIgKnynQA2)eP?4|APskpBIWd>=IiJzLrTQ(? zhWM{F-9!fdn^)0-62=$@YSNWKr zmcb3pe1`a45=Efpk?_x&iXaHAlL9%M)MAn}5!Y|aq8Gp|D5|E;Xt;#1;6z?pg<v%hA`!3usdGWT|Kd zo1BBu%ikvgMgirN5&!q-F&T?(In0Bxj(7~!Cuw52n_l7;1r689YyC)sKE_tQO7_S2)3lpBBuWBNAzPV&lmnAAUgZG zTIJ~GaBLrpkb0e4rL`nk<^nr003EDEu~E9Tf8BzTT0ktd0;C~E0B4DpH<)IKTF{Fw zd?_S{Y-XhtCjT`kpEWv^=B{dj!j3;ER}-Ub^~_oBV%WQRg|hG@h)eB(G;)Gs&&f}e zU|oXEqpo5)K$2$7Q(zTDg1ege8I-!^mO3*BpPfKCEtyhUY10C5HU^j&%pRQU24fx! zjU}Wc*qjc?rA!DUR^SR~Wln8dOfv{0D>jbNL0}V2sGv?D?XN^ato`v|P73ne+OZ`= zTZk@&JRRFq3SjmTewPIn|NGD+&E8IDqkUE|8`Mj`5}9at)XZ;MDw!a6QBG78z`e!s za4|-Y9T!8j2^{*JT_Wjp0|WJFL=OEx)HkhB*ZrT1pn4|ioT(F!mS?XZ1o{p8acNqn zU`YUU-m8sI!RPh5DaRj%zK!}p8HOhJH~h?xHgxg>xlL|cPZT~GCK6y_?tEC{x_Ibr z=z@PxNRLk$v@bj34S_Npez;4VJ3AXVWL(D*M z7+`wq@T&a*RMJ2JxFdx~12b{UGzcC;hwn}06HcXn`yPT#kX2)^FOtZ0=CDY$J`M7E zrhr{I5Ev&%A5_2(x+%BF-+Yz7sQ^hS*p|!wAc)a=Aph0^63;FE9m@Y*2#l%%ON(9q z&()&7rjI5(wbF2etN%f*E+^(qC5$558+LM({E|AZ>W~fPsgO~}-*(&77!yLsS%4)P zfwrJ!)!Wmf3Hr)tA@fnj1}pJgKy-g(E_A0i!J5IRQKC(ocIe@Zt^fjt^&MsZa&|_T zohCp!W%FOi*8QGxTkgm+B#XsrEdLwRli+~|P>E5%(+CP+ml+su{uq$!3{6!PfZ%~m zi`@}{U37?eu~g%Y*{Q=)NPaX8ffl^B9sd6V=6q?8Dzgr=C^DkzN!H&>yac#1QQRV7jKIDLx+glUCxKsBtf$NoyY zNCU(uQn%vFBMBDCrosZp)mqr|47wbLDF5)X@Wxld;9~^A=`qP1^Mvr#<;BU8IWT|z?ISo~{3T8lY;J9gw=y<7ijp4>GK-x3 za$d1*%%UIcAM6ve&r?3D#wfT9s{F-K!t*2Fj@0v zG>C7fbZ~|c6LkC=Q|Kf!0rf}$x9yF`AS6RC?G_5?i>{~Y7~z;Iq{8Zi>QfN#)qKB$ zR08wM6%*=zK`igK<9%KNMYXnS;a!=^ud;Y6!67#DFK^)zG1dPksAnyoH*FAjnJ=#R zH#JR5(Qal@G%FbK1JCTkCp}cTnVNG~(wMQ7gekz3eiLq_+q*bRSRG?TR47_VXvDk` zVP>rm00SWAt&23nBtnp3aMV-_lbLRc)zFe_D+w|Q%FMdBYj+gRK8m2qO92oGe}wQ3 z2^}uE*9Zd-iF;DHh7keNCT!f|C9Z*p08$B-6rcVj<(M_e*)b#)VnL{QNA{V4aQOy_ zNPpnOUW!RG(Hr-o$N;%%E_vCqe~eK4KMSmGc5V>Ql{b?9^Rb z$ioyaYFY#(!(xOwFKai+>TKI34-jJii5m;>2uRb3_xgCUpdg|$9>jnLP`D9k%+O3j zy=jLn4nAo+mz0IC=6!Ukln|mXzq2OmfHjOw=;v0WHoB!8G{NDFgXHmeIS#*&$5*3+ zuNM3AC861|NlOZ_rU9{uMvzaG`cRnY z7T}?W6*<4CjN0}uBm|u+C92}~s<#>Zj;i^aVrG>F(|nGuF5$r=rVrJm0%GyE)%4k} zq#xhNYo2fAft19F=*{q?H}R&qz${>fo23f~q=3g*{uPr%^z&2b3#%-WsV8O-KgOcT ztJP-0Is&-DRKFxqj(?h~diOdP!6G+NEC2+N#pmbpOny^_{X~`Eobj%_3ESl7Lh$6w zbsTbx%T9!YZpguNgOm|~Zd=`wm|JdJV(b6Z>(9K^eS0$6C(^n^&o;&(;WHE`RrGPA zh9g`%w6fIExP4{y)ji9BSW*@y4w>9buo$TgfJYH!WR=adMZ{B&I53ENDeh77ua#T>T(d} z?=&o2+MSE~n6^0G31ikTkVE8{BNV2NabN*|X6Gp&1&g{IVt!8-K;~vX$kV$aA=V^= zPRg#CA-;&QMW;B=Bcikr zPB8iEEzsEWc4~5Qb!ZNg@6wdVjCN*A%||M+`cx_E2I%AToFHH}c;{wK zzD{Dm1-6AL&0N*ZT-58}u&^k(l7mQ3KwK-dZ~;6(n?=PM)_F;qWOdgW} zQuDwVthyznR7URLZhB3&JNDRH`+9StVY8=RpNrqab<44ob+-|hIh1YKe4ghA`u+L+ z$?xqye{h|2qfcIG{Dln`sN?CIVB2msQ}A-g2}vMSAzxLrL`p*Onvn)#y%}01oOvoc&UZ9#FjCKC!+$X z4A+|bKd&||Tr9T}2Q1zdIn9{Sti~jM&d0@qItRSjJ8q{_ecG)72dr>cz&|DZ9c_$@ z`LWtq-lv>grp9LZQ-%6CgN+EPLxmKZ`Bi>l4_^34KWJKa$OMR2w zB0G#C`6v0xB!-y^$*_8?+8g{j(yPpPA~|b=jZ<)!tqj_xdW50neRdkAx<^jKjo=dC z+gT+63hh(?&dX{{}34>?s%)K~z#MJ@SaSq(}%QQ25NN%5veVJT06?g4yYN0g*w zhJ?bn79)zUbhoa8dv#? z;9-^am3(UMr zJk%MAHcNpw*8!kNl~|OciZc`hPNgW~&B!*Ysjb)&G+!c3yliJn5@y6NKP-MNP^jHr zlbQLA?)bPGNT&Ku#n4X)cHB%GgqRutbtwo z6+8MbR!nSdkpkuw<}L8~z|j7JF=tJl0~&wov@Ka9pcVt%xB(n%TzAir-Vs8%5}*F= zhZYOdJ$K_Npb4a>%}xP;lAzD_pVSsS-=NY6OC5Mbcu1Hy*S$>dWcH`O5~)OHv4*SA z1o}Rv-d3sAXCCBEkc4B|z{R#?t8oqq8VKW{qGZ2;N8<(fr-u>SirAFRu|p0fzYDn>5OxBe!JWor(-7e z`y={vVJ#m8otdKK^v$Yt?RvlufYN>TW*3K6S-wWw?J+gMLnFr^RoHQJ9+b$KSKX%k zzhAw76zm%pfyaXard(~<^7;j{pgV}>OlQ9=j2m|ZamBNc)?b@4P?iArrVtRuHJ(@` zIg=L8YXy-a_12R-a-;|45YANqf10|!uoy;c zUsBlPff$asU!hlmnGA9KjSZ8%|HZ300&41U=gcm3z{H`9w5^)JfH1rPLX?w9Zgdtf zR7Q6L1cQNB9 zqyUUeWMNvX)ABWcXYUn?%sFU5iX=MQK(x#bTX*c30U@q*hM0EH(b00ljF{kAIvp_j zV zJ21_N++vbJsUsNhAQ>Tz`(UZW1C5uhGw81i!0FoP$X%+iqHq*wyf%A$3rlAf<-XXf z4;k~%%|C(25Sa%fS!m?Z-lpQ}lSX`^16XU#ZmFZPO(xNvg0fTf-{} zIg0dO$0G<+aYT&vgB*4iVq8xow--WDhZi|#y^o~^eO^@IC;yW|D6(2(AGcIQs=XY4MWizwB1O;rb>PhX_4rP~?84@@z>-IhS~eI2YqR_jVkMIR0O*;7mYSpy ziU0_F1E&JnU~a0v;?s-R45n_D5fCufU|=Iy^?Q;!kTD+;pMBg?bQBmy&I$;O&L%IG zR2ES5X;tMkFhylZD4b>%{N77LBy7Sg_rJl((wrpA?b`xRvzv%nSP&^<*=fHl{f*QD zff+AI$g1Vorcp_1KFD8~2{hK!EIv*B&ILrrbrb4uzkL;SHJXEh_A&uU62U!he-F%b z1^^I{q$^RzbX5H$T^^Wg@L=LMOQZwLk2VzPA0PmRju%3iEt;iB30AlaNs9BkuRiV7 zo?<@q%90&#Ck_LO}uv$Wc^=I{q8V_kPKI3L>099Hvy zp94I^r{o7FK|>d$Vf}lP51E4YLkGygVHS~;GW{s7b|| zV>Se=2wETwyEij>osMNdrJb76FF{EKScn$gR#e9_`V40dh2N2$->{G6=4$ya-2lNb zF?i|;yNRrGauFa}rw#G|tde0WW9C%U%-DobkMf{3IYx0MrB#mO1BFeAU0gumMjuoI=_fb@)9< zw>`jb5yAn~A^RUq+7tK71zUC=Q$!vwA#g=y1FR7@`HljNMn54@jC*xp0@DBh000aM z1pojfCjbBe0U-bi1&ArZ%nm_7slwR0E0?pj5O?fxdVq_>N?x25R>)LUrIt(OvaHsK zmiAQmS!6RfP%Hx2T^?e)`jf=BA$?_{3ydnrv#XX&|EgJ6>#I=CdSObA&-%o6MG|6)E%;8Sco6fI=V z8^btQ^%x>x=_AA&tS*}Fa(fS8?7 znVrhc8-VJuv!j(NM^W$mRrO=~NP$riciahKu>7Y?o%=u2{~z}^n;GVO+MLG>OCLeiX1!yMb3a>^+_IVCDJ=hK{3jwR$!R49@|m+O1Gez^8WJokP* zpO44=zO2HVvy!dk@EObf>E18$@D$ubskgmRBU4=bH{fHnQ%k$*QZ|6NbAev%+!!Dv zdFJi+94xTl`}J3!D+=~nn)HVM{;9NcKrMO^H&y-=@yj^RADZD^3AUJQT!pWikkMnBjA8n3kY`X3Rp9WqB(uzF1oZazN) ze0R#QN3enYn_JZbrCf8yMz;fFWFhNvu8Utzg?V9@}amU!If5hl`OM83XVB0mX(7mEKkpztp&QVzt_F` z@#!j_uJ)tmx{H#AHCN$R?SPt73>O0t1dbVrFTC?+N)ctHe5YAp4avi4QABI+e~b<+ zm~uI7?qTHHU-kq0n)h+i2|CcpY0ueAhtyMZgU#T4B?$LPD``x?t5@uP!ghY{dpWuRx>kh!yC&NI`(KY=R-0V_z^V zFJPW9Agfn`Bk~iC>J#j=zM;e^p+(9cSvV)Ao2lP7Uh7yPOYQB6!!347;`TLagg@&H zJkOLWU}!b`)c@5a7wg_Hcvd50J+hOiE&AZ_Faw}*Cv%eYRG(qdJs8-s40K;in9e`m zZmjhf?qO2yO*KxmjvXrBdS659UQdsWRClX&8F;?0G|cv61hjt^3$mGhj1H&2e=t1{ zwswYYVEJoZ)n0HrB+mbcU<|zWmWUjwz4%N%W8TF==Hv2UjCtb3$O+zdDd!H5ds*eF z*4b=Bjf7h*d)LgylvGah4Bz7!LR6O`=MG_ZyfLHs>yX!a3~kh_?;*?SR{*L`Zz8H1 zYOGQZ@pnt06P9yF#I4EoD6;wtzV&{)5fVYS7kgTM9@GA4g*AR z*8}gM(UFv)!=aKHmkLYs7Sb&JIoFkojn6xb{(O=!t#cAm_arX&R=usHzAB$yvsZ$_XUHcJ0{wzKlE z6wY%|Ij;N!ThGWl#X`kp@!WfA7Zpr16V|uG2;8k~vx_CA_**obMtt{go)Go$fP!M< zG@Vj(o|-dn0F=Q%DDUxA%O79pZsDLjr1GfeR{^Z)V~!q-#U%qW4HY zD=aSvR4{}HXWzxnSKN*hm&W4@G~5R(u^I#@KVZRW&fmtxi@V60bM!q#a{*tde-e2D z;EDdE(wO@PPCb!_I;Ar!F zOdzTA+rHOg1;&a4Em5TQI#b-|UDeH~DlRWzrKov{$*Dlg#Fh|S{X)VF0N?{bbZ47L zT^_s2tKD_wjyaQ;Oz2+~f5Ud6ts>aKKGVsbp{MQ)U>$ao-pyH)QJevBh_gqgVov5} z_sRxsP*9P>C&$Fb%;UnXN$t!C6v0#@@fY41{G|$~z&kiKglwZS2oI&!YV~Jiy`kC+ zniKjY8Vd|Gtj_6=Gn~c>`L6lT(DRUtlwOZ7(Po7;p!P3zLmGgU2dRj+Tmes?f^0_F zU>{dWkbJl)x5-mWniC83bYLBm5#?i#nfo^+d;W{$v3A_#DKO+aWp2fqAnM*_%wtdf7UL$JFn>FQNdWI#Z7UKH+p&12YI9si~dF|5R!Kv9t78 zIWw%4&3e@Y=3FXCl;Z>Hzc3aIrI_5yau%OjC%3?tX~X3p&63X$$AfoF%AOJauVIRI zjbHI^N=mh}OrR68k~G29=>>7Jv5%cInoeeFrA}2zc=aRjc9}ui88%oVJ@TdrMy%b)(Uw=>fyT1&J2l@$`vh z@&c~EP4C=BCuR(rgReER^l|FN#P4oCdL_1;%9HI@UoLLM?EFRnc1EuM+`2Manc$oLYVOMmy}qyqs&0H39FATf`{$>mwj7W z=K>yFVcWjw_2)i_%>kTB$@=!ALiH6dzgN5cn+58)X@OsAUCesA^b3t}jwuNN@YOg| zJRrvP+RF-S$B?8O1~^O6>XV>59*e0m;;23W3$D_P%}t~F9=ca*kZ#bpj&+`x&m(Eg z_^0{GsZ|=c%qc6deeKlKAjkRgstYci(9sD;z?E{$1GR(c&9!Caupkef84S` z4Co=7^0k~y~t*^x7!QJ)dJ7v^1ww)gQ1-6_-8vP{)3o^V?er-TNNgxbHZ50AYY%K?z?0UOvfUfU&ub?)i`0{?n3mp!ps55OGg>Rr1;xJ z_a4(5`zU(-oeW-5t@_9DcuiC-n~4EKn5O^S_6dfge5a6-~1n@XJNe~2{*_wwPa|z@_X5DsfY(2#c{Py{Kd1l2&gWF+& z?%;)*;+)ccFQTgEj*0qNJ=HE;mCK(jemkK&NUD5MXSs-5xK z6rpS7rCi3&z__AJzuxsNt{9Zprv)4K$ZHfF-_@;|Q?8%=X$mz53Ro;JHU-JwEcUx{ zHj?!`3xpRS^2#UlQ_+H^{2Z4f;4=Wm5}%Ler@y@w&w78Z3Je1x#Nr+rmfLy@UiK?V zPWgrveHOgoA%*Voq9-#>J{+L@gy1~z2H{gPp{uGztCj^|Bx`rhso& zh5-KDdjTe(lb#ABed4(X{Hk_E`>Y}{a zv_9+mqAVTC?M`5DOIY#zat?NJx_cvdjcdZ!8%595*N2=V^(`aA`+BZPB3 zmas^c8-~PqL)Krguy}u;$23jgK*dKUp~)}&uEJn25}+s2b@G%Y=ySbb2Lv^1p5~1i z>0EAet8Jc+F=?Lbnh1^mDCzv~60B7|-Xh@IIsx*9s)IwQj#Tg7Mw^rFx<3 zX>UaFO2wjs+hu0nXMF01vidvH-^9U(dukq$0K57JLx9K9xE{bW-K&wm;Y_$6@3yvQly52K!U_$}8Jgmwkr`43kEvaEMmX2&ujWCSzZ zMr~EiC)A@}KI+sG0DrvEv&C`q-X4kzUEingBM@r^$(UQ;Z@S4;K3TWk|HEd(`rJh8 zJtJ;+E9Cq*geK;sH6zB|7bW~XG2ymu7jR8}@H``Z@Pu3lSU~fi7I~ks$@LsF`eAw! zWbV{_cwUw<)fWU=yiaw{wCl_Deo}m*ofM;e(Bsx0isQ)j9J-?UIvLB{<$X&c;(M_V zHpYGEN0Th*n+LPw5zZ~IA<>#XrQE0b!WCXcE{I&P_WvpLocv7jD6Vu^=US^O3@Xq3d^orV!m@;72%`;W+Lkr(rbZQe1?etvgA?0%6@}JB zs^=@=0{ndjB?fj;@2-XU@_=C9O0`M%4x2jl*6LTt z0`pHzTj0F>fKV!3t_A$uYlAE4W+uq?mM#Cd*{T2XE)Zk+{yVBsq6#wSBQ{%bjID+Y zQ#Jn#cR+O9=S&}E6F>c%_|#gp-g9LFn`+$@uk@f%t#T{rlbzeOYmrtpl9qS_R;N271eVtnmZhZH*VX%T=9ABPrZo_bu7m#e>yqUR-BA5M}WIxxox<`&10nD9mf` z4VY*(lN_jajzaUv?cVsaDhQt&e_+Y?M(VWF2}4diFN27=e=q^2AME^Vi=Kg_J}V)W zE$d)L#vH+|gk9AasK!Jz9wkt{TlfaEk1Q_Epb=1t>3 z3Z@&OhH~j5#-gru7Gk-4%L^v0DNxre5nzeD8NoBJeyMQp@JJaETO}D0c03k=JvCqnuk)wUt0#Je>A%=!-RmOv zT>?$S*~oLJXSE-H|0rjFf(%)Nne+taoZUi+)cGxerx(EaUK@J-CJ2h#1SSkM^ck(V z%`X2kMcQ%`f*)FGx#T6#6(`MbN1qGU@RGf!32||`ymy$IFh+g0_DypF&4FA{T7-1h zYH?$B1zi5@vzFQaj2%PNIU#qZlvF2#w2tdRfYLR%oDgot>`BxO;n_MN!>zDys;dQwAa~Iw_rb{4Wh-{P{piNas}FL1Whlm zfcI~>9lB~<>*!lf++zupkokEf*M;|1tvLpri^r$O zgVLrN!~sLrQMme79Dz(jORN;LcsbfzJ-sWfVx)C|SJkBPymjmg=H0~GLrVc?ONBX= zM}snE-p1z;{Px1dRJ7h+Yn zP$(HD5<}L3w{i0t6iLAVbR>;6A*qL5?*ad;iDry~tXhXY`p}}+t3I<7fUx&?AEwTO zaEZq(Sav2880i!Z59FOv#dPiP-aPOvuu@s0P#iZD#8K`cE8E*BC$nH9(X21LSEVHI zZ@8S(Mu2OI45fY!bE@hTl_0B*y1WJZTwR%q2f5`h)_pLr_{Z-`8hfO>b|sL4lfmf= z#r_wsEw5ny-^v+w$uRJZ)Z6FlX-E{UeTc#&m2p0fm}5Uq)MEcK+s0@+G6TH0aUy%htN=t-^i$S9bkP<5 z1m4A?Y=kzZoaYP5rgp$rg2co{z2Ss&f~_?{U}~2PR=&zY3G^`7pQ$3Qw;|(fwA>kWEY#?YuDHnrZVoa1f<%3_-;+k z=!whM?eSwkHR519b?$Gh0OuYo8Tx0bCdN*W%&m4?c2e?+m#&ryHv+RfQyGHis6=Hk z_k$<{kFMn}`MnCA|M25c1@DYD$BXLB3G>dR{89i39*mjrcMTQS)qeJEYUk1&NMNNS?_-->@d!=ZOidti!X%5oHY zTP^%tiCa~L`8D_ny`PT;7b~KJT(_SPM+SpeR=fqDZqq%{%@NK47X4$rjB&+N&ckxe0SM}@XDPbzFXo{F07<>4=*2yo^1 zYAv2<;IrZ7i2e`1xWn<&|8~4+I$c=jWB!=#bDdlZ?n%L`xOOI3+;drkBcCPz|D~2_I zi0cvR>@k|=MKwa2{E}W&0EZJd*@j1Zf@G8mR{2g7+x5&B>^KsrieA%5rgP$D5!`BI z)|9VmCCiOMctE>%PNn!y)Hnb}o<-y~0m^x+$XnFh@<1{55ol)}AizmrZk=1TEtNOs zArVy6*A6vP%Xf`puF~&Y-+6etk3c8O3rroaDs-bHR&Pj6cGP-D=5fM$YiNuJ*?*)5 zh4L0OSujoMBv%7RFQnpgM`dF%iRnIuM973l5#>&y`G;hK92GiG7*XJ6IK}P;??xG`$>V*I!&k)Ogmto4+ zT-rIY-n@AnI>$WSdd}nDL;E`TD6I8Et4e6fFAu!EvBCa>7nhfKADx1o^Uscx~WmU%Bm%ii0gCB>{fT4HJ1hZ|IRpOaRmpi;D>h1DSfL>Qcvo)Dj2x)6}$8UrnoTtp35VE@T(gO=B!-9ZFr6 z>D8l~f6x8c?WjSIjW&YHr(;STy&ihz;Xqzr$F1p-rpJ`Okkb;AU*#Lo-3?c0pQz5O z`^KJYzsH+_OrY+kCc*y3okU)4*O;t3qIsMVGo0*ohwg=e=S^HPu85=KJ_HF8=Wui} z3|MKEwbRXd?_Hj8z&v_?)Wwf{N&*Xv5BBkdYZ`HDaGz$m4qMh{5jGzOc`UsKgJMfH z6U_axnx_S@;>J!^VqYDvVC{gh!-keb=&Ue%Bfj4_-U<0uWimB;&`DOrj`~>I-fJ2l zeTHIx`=mn&#&}N9PK+R!*sB&d<*nVt4q;3@>X@`OHHd~m-zV8>TBK89cF|W5lpEUD zMTT$jP?xjblGV}~EK+wR@VqLQ$DGMOhFfq@=pH zwoyiy1AmD%wi-{wXpX{}(B3fOX?`|1!$DpdF-p5a_n+7E!v41haf#f!+&{m-6-G(VSBf!Mj04c2AJJ;OS=m0gkLgwI^JwPwfwC( zCWjgw^#A(jCyMC*`Ohb7#83L?|NlAjmSnIE65lp}&Z+DpU2%u{uLGOl5C;0I<5JTT z6|*Zh3uHHh62E_+5GK3ald*d#D|-Rs_ufs;)#z|c(jZ%8=`#gd%#E@l0I&p-NClh+h0C@v*zJ9dSX*NdbLm4o~$djmSuONUn%2a*DCku zc)FL}=R5b`NjPA@x!9+(d@|w57b^Q7zHhBsu-_Tq4K)DAt~;24?d^eaE`v_vd0n}F zTFJcz`7bj>K=jiU7FfT_)&&}h!@0L)wA)we&j-b?6*5rQ1tBxP@Npx?Gva}$OtD&i zmcB;XHykRmMy+d-z)5Z zTcRZWd!fy@E+Zy(kC0B9m`U^wiM71C~CuDyK7ApU)^d*;tw#s}u zg{Mg-;C@BwKjV)#-gAyh6WsErYwPcha$R+;l>U<$!NystLb5S0g!QbOH0nPdLOIZp z**8NwBL=M5nE<%76SXlLIm*yBw0(D1B#?^KF8ZG#U89&RBHZu2CPu668)%n=q)R`jc%G+7a8Rzd5}Lo zd*cr*@j4x9$TK-rJk-*Zkw3rRdp3i`ja1GiHX)tG=zblk4_VV#?n^B3ka}ZYckm<$ zB5tqzYbmQQMoIF435ammd2IOrAfKwg8@o;Dk(%wU5Iq&qrdjH;CBFEjNEfI9TRCzk z*y7RGufMzv>D7SwNizVk0u=cbs{l zeoV}mlc*)2LAy59L#eN0YdL@gLV*b zWcRj5Kegvf+kG0N@@Zg97ZGx193kM|5K4w%B$Zfqn|19v+}?Y{+*$~Ov;Rfxb0WNF zR7%}=^q_ndB(B(uRn}fkZ8*SX9yy~fxMdkP#3!t4mVx9QTTW3IXYB8G_#DgVG06qO z>Hr*teDhfR`%N_4r&kj4-FNC@pC#kWh=+lHdF|;}8`jquq951G$E$r4%I3KlqXT)I_>G4X zyYqRkUMYK*=OW%-S(oJ^c?|hB_ncvi{_S|0np4r(&=;^PRg#+_Xkp3QH!2_Y(#tZc zXyRm(koqM^_I`a4S=ugD0I~qv2+3Ga4B)Vt1=->O0QPzvXE2)~6CJ2gt>Or-8%0)d zKzY%C9a*mr=T&x>yJ9AUv^2jrMfI4#)l7BzUjja?tNk>kQS%KCFZ*(z+xp&(ijl+rxS)xvhaT=V@$$6L?qz4l+@{t2BCX}Cf5Bk-8|9xy!$4OY zXm0BDFMuUlIsI1esFitUPVa=QcVcfxU+a7%Yu=Y9SZtwRrrOYT!r2bUxqp`tna|b2 zm5cfklW+Hapt6!Fr_4xkNCfTnKnK00@v(WV07&Ej%r2n$xa8sHqBR8}le!~WH%Mw1 zFMU*(3|L@isqBLHFM_^q%IJFmnjnW2;Rou8LqjE2O}ur*6|lvY!-i>> ziu_la`IYBgH|2u;GQ;LyVV1Lp8M@>ZE6I-28i^`NUz+Y&z5J{A{)y+^3l~}^RW{=Y zMFWBzKwr8#j3D!}^2K#;^NED@`K#?9!1Y2LYl}4EN7~bTLPdkXPhW<6s61B zh9o=Wgw|=}VpG}l662uV!=LQ~{fTdSV=Wt;sOcekG%vb_n`;HMr;#)wJ^h%FfRB4N zq~W(&Xh-#UcSni z#4%ph2vx3w|MEEvY?VdH4-k+?(Kfm+Upas>K3=9MP(w7p&9yjzkVLUGjLqtGZ^{tE zSL5L~VF>ik=c##_e{n$$kJZ#PER>>wY|H@4gXtJvF{F=>ww_7v) zNRN?M;MFgv=H5TW#kWd$UxHWui-#`dmAQw0%7s>gOn*MshZC?~T}!Na$n1?(azM;6t5Lk#l=5YpUQQDNBB`IkcsKm)$fg78lb6|nDw<{Jd+z`8xX7rDR%9aRs%u7Q^C4yB<+5dygiQoc}BM=wR(q zHDb;Ru#U4&OssoRBC6VVV?{0GbT*4q&3;{D(4P;!aZ@|zFy|yW$M%*0Iw($p#|@mW ztKyNYl6Ri?EZX|T8VQ1Em*B2SZ#3OWP*#gxZ#sPa=UdlQ$Sk*Te|m9Dl*KwJAOpFRS^5{8gM5 znm`QCDW(B5LA?8qpZU1<*X;FmNtNk-{>g&I^hc*ouDX;4!gq>7RhZzFOIBe8`DROX2Gh9fSJew+cu0RKD$dXn$>##x z!1OfO>~V3G(3!VcED!fbKPC#ONY_rlH#Se6#O&$BsjCPUFGr4T>vTobEXMJYlOB^t z>>6O?<#iFFi~wq|n0D4?j0!V^?#&&Sn`)vS*zYqe4bK77&NQ1hM9paZ<19{Lgsc|i zmWE+bJZI#dGNw>zEX-cCi2pEg)JAGsQs73?HAy#=(y{@&Hmp1%YKa~NY>NzK-dszL z%GRE-_V3Wvl_*E2+Xi954MrmsFPvXgUF85*c|Y||m`-p{r+%J|tF~*d;YwGdp?w6% z&Dke3nd}#q*=>By)SDf;05D>zlhxwV=Tp-rz8SO3f+gSfI~PJ5Nd2|1OIZC6pIkm? z|KI!|`d9PBG-T>YP_tN2%~=UXyeVg2mt7cNhOa@;-3rdPReF97E{>wLKy;OPV2yO7 z+NIHfcOC4P?LWWdhyPqyXj!|$g|Jlww z=RqYFpZ%8h&M5xxPRN@eBtTVN4)BqXNo(0@GsPI3`o503J(Wg1u(VK2ZT(jd95xN z(OJQ?v@Sfc$o_o)(i7^pDkbGvyXW?^uP#DJv&58{a__&mN&1gg;NV9h`dsn}lbDw` z&A$rlVYoQ^ttW*Bb>UO~^F(j4=67n8U6S~Y!%`khbx+q8>HTepU%J22@2&G^mH(D5 z@?fB@Ns|mVjHrcie_XqIKBPBUECeUkVAaw|6D%!WBYmnv_hARh&;0DT#lEW7Bk9F; zF2i)EJdvl)^J~beI*a?tlhled#i2CCPu;e-VfHcH&T^_xBuQ!kKy0iQv%p1d?@(AQ$eyUI4 z^=|sG&!7`LPOm;PREZ1F#box$xA1raSl$Q&vea&lgMUozaEHW~!oeHfQ!UCz)Xu76 zR7@H^Rj2e4t!)AejKqVf;7=VN%t0UhT+|Yp_3G1)GJCCm@llXlF751I%1DQ`el<&G z6Fy)VEq`W2=tFC?-jaW>`7_;b0BLzx_a3ZkNrTXtwC2lW(Ul%B**$`%2MqmhZbhX0>3ZE$$FHIV zK- z#TXrR_D)@K!qhDe=-qECn$@Ni%U+kPk>Ws-r)=KibDAKXh9i9!A~DqfM>PA>M(@+| z1TB8OH2sSLq{)v~S$*%q2o`eN^%wY}7vj?tbE+y7n?#mHf$WdE|KiJze3A!ifVsv# zrIuxJI%O#DTuvg&SrkPxYITBW2O>3Jy;=FD0>T-g}nd#I3YU@ISEIoVd6N zfLKCK1>1LD9{2IUUp;-JyQnw|W{eit@y;C$e^pzm9r#3`CAh;-Qys0IiNo_4NFr-r zA=1>fkmVxaFQRJ#m`F7SAI)&3eRLfG#hNX&woa3qc?@agZvVcDS<@S^JHIe|FBkp_ zjy?dUUat@vMGGyoHQDd1tv#u_qVilRze9pQ&U#Hhlnw|= zIfd*!uU?zJuv&9X_-ai5)BNFF$yoZuA%5nI{E;?^-08EaTgo zP3m|*7%_$8iRzYmF)=Bxw+1FBXuu{ScQ(w2md%uDnuFh~f3HE#EPjR0 zJ#?9g=eSL3*CWt`@`{Jtre4)Erfk|ws0L^~H8Q*)ez9#Qmm#G!qWf|DVL}kbjjqu>k#j3NZ&-ciXw8-$ zbQF%60f~KF_4XFYh4m?C6Yxm1%%NQ5Z#y1KP5h82C&XXr%eN4 zW>}+>MCO6g-PXBIoSDeUZX8#G7l`FdAF-a)DWV@RKqMI3WM|LOdA^K0F6uBC1Gr~) zziEO1_`Ik406G1}!O@(dhY4S52&h^ETP(4v9hL0asWDdXMD{!)GdipzI+LuGxePVO zUNRN{PVyZ2c#PONF#<3is@QCf5X`VV;{fn}w-}{-<#OC3Y9FyHlxI`b^jv?@J%DVz z++X0^)}#6W&7ZO`bdhkfjlIWB02fWxj)TLgDLKFr1&^&aJp)AUX56{XF-ES{=i3M%%JlI8a<@H#!i5q;&&h zMN)kE^QF-eBf1ZWP<=UcEIh>6l^D+=>Rlhtfw2~TpNa1Mx*IC3%|)^38+xzQ*J{6s zdENvWHGNCsT>xnlI3LrerOVDKHgDDh%45A&x)b%bG@EG2yv3epD{ zJ~*01TLj`2)aRM@Qk(W++s`^(_sk0_HeJ(QBE5X_Ggm0>fInT-Vm=rpCaGw1OB}Lh zY`OA7x)#}C_UCO;Wb|ngYuhs+Jx(YwPzsrehadc^@f3T4Iw!0t8c$+emnk~8Sz;?O zE19mr{#3n+Jo4Iz8^GB?ia13HfUZrI{=QAZDW!??G|csiAJl#KUOk|8M1-cEA2svc z7Q_o^Kq{gEy3dkzyUIRcR`edoIp7b+3{Jj!En9KExiHwOaY5ha$YQY<&i0p6}9%>Oz2wl zQnC_DzzlrS8s83|8m+`q{_@cHyh^cZ^us#%5`w2msYkKuh>ra7D9Wt@31iuL#@=>f z9N=Vo?MmVZu4o5yeugQzHz0fx^8_Q*^dm9Mp!n|IyWS_)jQ_Iti-vSctX)+b{K};i zdgg9eSvUf$SZs!Ix?``i+U14e-Mi!Z@0#MC=q@341>Lewfv|39fGhu1jGtpz+x`UmkyAf-ne`r$ys5?Fz2+Ur6)UE zklk+^^%N^R=-_#e%j$I8c!b^6pr$Qoyk0&R@qA=7?d;(dj7R*R#LDwGftBHx{`vTc z9=>Ih1BAa(DNnLE|LQVu$?n0^>!gznm-YPZlXoU*eswUZi%<|n0;|hI+ciElr8dt1 z;?}sM0F6qX76KDd` zULmIJMQVPG@;S=6`PLi;3WE38mQAb?mCztH!qbkqc4e#=#~qDs^;0q7mWWh`&rRMZ zO{gfhzldpd_Vg7F!}-)9O3qJp?q|Y7Z+=BL_t#@3wHxJYaIYJs`t`L$K9mi0l=w%5 z_Q&U!(H=ARWHNH0T$9A5qsLlkGOr-Usu-0#`z)hOL#M=6RJN#k=Z-v}P7m57 z4dbCq3FUDg{)8lqN1PKL38>Y^mW5}qwMt2wm>g-!x&=~u5`EQG;{-j&s%4!w=$J>{ zROs4kCfNJ$QSFq2JiFSSpfUiBh1|Nz3Fp|+5`GiUUe~kGv4rAzD6D|s;zvZ?#awM~ zr^NJOUyod!VJoJ~Snm>S-|M9sNq@@fPK5vQc3)~mpxGJ&=JGegvHzsiNyYV8MMdww zzxvCqGC6@j&ej>{X-#Z6JBxdO#T8awI=Mc^Re;2)F9l37`}yjI7Yafk2kCY#iEiH~ zLp3`P9f^X7WD9pt_8e!Ce~AA;=#*8=M2&HN7n-^pDC6EQpFc`J(|{S$d&2+R1MRaS?nNJ zn;H+mT9-`tOp?{0A*;K5apK@%pYspx=?!eTxIIvzjyf~>Ku+d2dd8!jrne3$S0jr? zT|N`7rv`1E)>M+&F2gtB1cy8eD+i)**8ha%)e5V|Z1S!P2gS5}JpSRP;GzVv=;@ff zn~c}F8l`L3FZ3Sg7bc8Wly*U%l}gje?arBt@o@R><7xyF?N5L9QTOYrn>7_lVrrCX z&<$O>xitVwS>Y}RYgKA8kn*I~nKjnA54j|BaHNE=Y6b-$Q3Ic)-GjbAyU# zfhe^^onHmK@o3+=%8zqDF+{#s*ovA=OtN(NyufMBISGgi110XnQTgbJwAxWNDDP0o zR2a>>x10Kp5HI!Ro+aQEA$r-Q*d?6DdN7be)G@^u3HI0?#d)qc$_{%=!{UOJA~-s< z#83pzXbzcO4egHev?-ZKM%!fXTVV;F6MU2-lA`TvAG) zL1=g`3}1$i5}D=Q|LU~O0sw&L|LU|zK=c2MsGzm$|Nh^v+xU#CIkY+i_8S?^I92O3 ztn||0zsCg?2XD6YKU?s=)d)82hOGit-v|MX%hqpE-TUG<~>eIwVGF5hdew*)7= zvto$qcIccRoq4CEz_*7@dNY~%r*&ja`4*3+ABfm%B+cp0H4!&LG$NwHXEF5NUdEOLC86Punf42x7 zYCCOO;}7dORg-4Q#z%~fVfl^aiul1=_!S(PE^e`J<-L1f zOa8uqlBH%N@2)0pG)8uBF>wlW8fXUb{jZyv^b z{gK*p-O^`1AL) z%dA?W!AmK8H6O8ey`tc&(szi`56|-+x;Sch4N3 zsQjK%ZTn<~!EZJs9WbPA)qPSZUQOBBor2WN;YF-?GWaHnKV;uMmML#v0y^le&B)vz z$e;8g9Up0>OkR3hn|f^Z-jvn7V>4En=Nz9o<*(Uo9^|in_1*PZyGs6>zvMB{M2()G z`(?t)ik(pe68Y=^dKc#z^2u9?;aQ1|x|>#?)})n)f9Dsq^1}2?%KC&D3D#1LHY?X` zmgL&_faA&I@|SV`d2+~w*mBAV?w6`Q3`uY1mNu)!|B!RWf5yzN&=Ek2I}++?s)o4Y zY?U0!r-`C<%ln})6V0e`p0#K71b?`*C!s`=Av^wc4ci+A1d523QkQ)~z(6HyU3A%Z zJWCzJ=UXkV+B%=pHcx|vMD(quo_=Sc4U^R4Ck+|nx+h9D#L2R^Ee4O@L*6pw@_#tR z161!{OT9%(4Nw*6yZ7y7l?eD5y~Vxd!K~}X*ThY?4a^?^B>Df2d-Tb519yYVYwrgx z&~Xh^A8OJgn? zR3Dt!iu^T@{-lf6!S(gdXM@6GV-d{q8vyl(rGC@BtHR!ap>Q@4XlVDg$FUk>Fz9=N z5uIq>wR+M&7)AVGsv_Zju7xQuC^Q|OF^W+zm zxnue~n|hstHd!tu3D!&jpEh;tPc2Z;C3tNQarah~;u z9i5ry?R2T1X>^D*H2_TCkCk5i4B}C-7_hRHoj)YBd;= z`ge4Bf4Nnw@=7xrzVP)?*r1?DGk#hGKnyB0>FWl3S`PtEsT#Da%&E@t-))8-5j>bg zl;*lgKg9!hYG0Q1SZx8DT3Ep7_0=6_%Wa9)kW9tkN`*tez#84Vb`Fm$u8Dg6uS;2gp1gD}&@7g(CBqjJRZ+du7DeUcurI%{{3ez>x7fInTncvKGX=!}IE*<)9fZ@JI z^NUB{9_mHLey*~k7r5|>d*wiwPb)OOpfuRyFVWeHkGfWylr=*oS9X6+*SotHKWb-X zt@RMn?W!a81|#7f{p02f&l{~jK3`S(wjTUj$D_e%0mrU|G$CczbmX=YT6uNRzx%%9 zC%K3Wwt>_jI-wAXsfKIL4>?rNA)K`=6`I`=2gfoKx~gxrV*bkaZc=U?`bFeG6PwYj zzkI*YjiiYS_h@BeBUN%jhHVz7#KhH<{~sV7YD2sz=iZsYx^oyZCJIw?7FTY;8|k0x z>cBhvt@s}>ujGbzaJP$8KuUwQQeg&A=#ue0VYbDAP50*3q7OXD2K^$%Nv; z-uqJdisUu4p1--nYI03vf_sDpI}8`%T%3J|)PqQZ01>T#f7jhZ(jD5}gxccl$Afx=C7BKk&GfE0Z8GHYT+uQM_@rz8A>zvCx9L<(L!ejT*M z`$n0YW#F`%31Alb&}UB(2o1T(%b;D2?Ih6ZS?4{1iS1g`=Oue?*WHUZ+jHfegX`j@vqPabB+}-Rn*GUJ>_0}H ziRk)CNrsGIx)28UXU0>}KF7B!baau}2d7|+!dwb;hNS1t1%_2cQr}^XHQS~Hbd(Xc zkuLP7c9JO53;M$A2;KF^+R12}pGx`Mt~>=e@I}GY=l*9SW5^@?6Vt4~ z$9R=5%J;wQwE#E`=bZ6!0224WC${e7RVq~$wYT5LKf2GL{o9KITIu)rsLxrm8MIl! zcx3BuWpx}PhiXw2RLMRt?;?A%JBz<#V@TR9$AueszTfW&F@N}-n-HBJ8T{u|$F0Il zFzzj{tNmsEU&Q{m<(Vz|Q#f_*-sZN!mxhb!wgBxx{o5o4dvEaSvx(M|=Y)`a@`ZoZ z!8YG+XFn-W&sQ)=AKcL6sy$Xe9yGWWQk_oc??}Pl4^h6#wjg-+&SZv?3)gj+ zb06zG$g3CcvTZ2xNg=*>SZKmLN4VKy=auw#e`TN)hzU{28k<|KE!q{S9XK>yZ*YzZ zCEbpE)l{;>l%3)!D5$xgLQS72qtVjUbU9zRxym}88|A^biN=RlmP2da2)W@OHW&-P z&P;%C6&nj>zuY`zjpxEFW$jH8p30S!x>YQ?CwZQ4^+hv{eU%BjPrz%e47ts${?5$H z0_dV1vHmW1F}RQYsiLb^f`DwNJ^2R8_+^?N6tyVdMkFNt@VhrR4#-vEE zYwf~gED&u(JjS~IS>?6*G~DHHj!7*_S>-3Lqwl=whb8G_dxWnGAAZL+-bnUh2O#^t z>Hi#QCRK%4LE}WTLC=fC{f*Tf*2`<0mNpa0>#g$4FcuR&F7~Y6#v+-A*`m8MtdM(e zagtrvA2{u@xoWNtdYMevb8Rf1z{KxThb_pZ<1!;qKuh+Vs|5NKBr)w$gVi8)uP% z4lCqWmcn9!WwV7FezSNk`zpV7@^^0OvDKE3)g~QmNN2SO;r^&fQ=<*#*uFUZPZ)$l zeeXO%qV2`v+89}M>RHEAi#MMeTFhVwV`mvCVpSVSmH74m5j~1sWOhJsNxUroNTX@Y^`!xXSRSIHBDql zgaR?5UBbMO=tN<-~bc8Ynf}N{2@@*I>-$2aO3f zKU}H5E^~ws{le$Z#&lf|r;2UW6S~mS>BrPT=r>(T9Xsv(giYY~p2^iOnSk+z#vOkx zt4x2^ph5T{&H3khKAkKF>t{asVRd&u*v{edhHbsmOgyIt4W{2fPAQf4?yqS2Sjd*1 z{j>nEQmm`h+l$+?{u-uYJ509$HsPckn9<<5^13>I>$g%`IbEPf2}Xn@2mknjxUcBt zcA&z2t=JXf@Vz|$LWNg^plp71U@u9?(KC4rZLSJxR*XNB-Y$~Q z#Wz`j>OOVy>-_$RNWwp%&`wD~6IX77~K%rCmu!y7lhPc zl~BuMU)n#|yUMswW`s7i@(+6gxnM)N@1+{d-g8U>;B;M zypdbAsbPLClffH2qKx#Bxys&Qgt))aT!{EpNv7&UOozF>dH8XN*ndUfv2omg!)3vc z@ZP<{T(!@#x}&9>@Q$^)R<(~U`8jsYT?E0$BOfD~=T^fdiJrx8-WeWWX3pr=9@u)` zZ8%m0f6x`sdlTgZ8PCGUx~&bKD%>ny+#x{Xe9y5%`HjBmSA~C;!2eq? z2IiY@G!*$aODGAEW%JeC-fvwtr1XakU!Uk#w&j>t1e5ZVp@!FAXv9hAGo@=zc5M~- zQ{2b@Npvv=MUyA7$jsQ#(FGI~3#&(1ruviB-`r&nQn1Xgt8K^=v)DtY6Ni2fmY%;i zrR}O@8{wJTfiuLg-a>f}> z*be3Puz9C}5`G9#WL}e8+%Irpq^_N~l>4jQj>sW2VpiXQ;!`U8N4%U*nDNsng3FcVLbb(!YW~(Qxv?dsKju27`t}} zAyT63k5DSo!hNmu{8d=Q!e5^3o+?xPxg1kdjgYa@67#O-sryjL^>@e`Pq$YJTx25M z>o1uY?lp)i(mX5Ojmfm6vrMz5;Hxu(6jHQ2F*BM_0udi!$B!ndn!XvD(P)Ujnkslp z*nQj{mbV1Wz9OUrfi8Q@9*=2%dz61DF@QA$nor2uJh@ZP8c)u)vpXmGvTWs{rlDS) z1@ps=Dx%fRkzd(*pD7LKJ31~(k>otZ7kBtpwk|dY4coC(W!U+!5^*x{f5TREar@Q( z!cs`KqDsCp-XJUR!ry9}K~U{wu=||&oX)et3;qy2<)<;3%QcOoVdDNo9?T4VkB&)= zPzZms>$w<$${txo^-pBYTgWwt&sRp>?GoPu-7DiyBYVl)qSh$EU|u3n4Upsmsz=|`#QhOvF{#tA6nb5Hm#KpC(+-nZlr|e%nYj^8 zJpjz{e^|VU2-C3M!2hs#!M9AC30%CxYoffsV=%;U!2HMS>CY=4|6}7>8C2hG?~Nvv z;kh>Ec6W3Wh`=i|0=e!80m**1EY&O_K@Wzh0RHr~lI2usap$bx+=TAkG zjQ7%~_l16!|36mVJ*u@Q{SYqW^Cy!W(WI?AgbP+c9Jc7Ph?;zk)GTgqd5JX6mMEWv^Sy4NJ`w~Ag<}X;9h4l%C1MU0 z=|Q@GUUs_&P)C)_BXmMPaPHNgW%hC_lj(x(O2gK9{AXtFG2e+cCQ zfYhODj-auGm7g`6^Jhhi+*SHD@t!0oya_;=OJFTMIA;%5*FwgQi!2B*8q2$5XeJCB zK-_Xk669r=zJEbcPYq3-_5??-bGfxb!HYogB_*VKbS8{xwy(5U0M8^`bGuF3OGMDq zWyxa_aG$hAVV_}9I=0W5$Ma=U>uImDnGC9z#CzEhCPg4Fijxq_X;A990JokGc_aVC zf48b5Hs2xcgKnS~qpHXlf}<$oB3_Q%rw|ws!)Uep2T6Mq*QFhTO!b{QlG>a<(ooXGR}K3vP{^wAN7vJ;34IsphC-0YxH!)8&|D0z`)& z;npZe5oBo1@6HZjpJY=Xa?zy6O*Lt5$Qa>FUvr95x2Q>Sfk=tv#bVHK&Uc!pAk6}^4}n@dC0Pa>uZ&FV z5vupI)>jmCaOU8$Cv@hc?gLn%kVGD{p>ORH37cp!Iay<1sTbnaac z?_{yP+gzOVzHgjl3x-r7nAz$8if#~F{37!*T#hsy{D9LuZ!-oTo}Adpsg~ znZObY>5tXt_l$TjIrdZWX#Hq6eISq4Vc0SGZTFsUtVE`U0-N6h7W%Mew#Af!7{Fis zfNqtWE6*=mJ;b0o7EI{Y0{}$4+xWUyMWqpKa?g^42Q8qh8z}<{6FHp1!B%4h4IrRy|UJgd{(5A~Gu{RSoasf4?g+ zyF<(O*ny(k@Rx^U(1BW%qtR_TU-#W`nsmZav~_~cnb<+$)?n~1QXew4@JBTFgK0J( z$b>|A54-hg3-pxgO-j2#qI0IKQUwc?++zwO(5iCwuU;duWgXFi?(b5sRDjM)30?ZV zcN|rFa1lhZrLMzJ8YT?sGDQ^q?fD_BS=l0(o2`saZg3;SS*b zyVr(sT?=*uMFUub2qvwF#aQPs4M#871D%MF@`XD<=zvjnx`q6f7F0TuJC8`88j4r! z!;4T#U#*Y*2=!i@-B1=Jf5EJnNwWFpM|r^;GP2=lrm|WW(|~a@-0%bGcK-Bl&-sjk zSrTCAf?}5n3<24vK-&PaAJqm(1>#VjLI#}0`7=Pt)!z&)N+%;@KnUw}`e?-(2|wbh zQ&bNvsax$H=1#^)+a=4Cu0y0ZGR(sG=}e$u|6c1|4PPL-_fENW z-L=%Tnq;cj4@Iqmc5U$)lPd3EEC5`|#z6}wZml(ZAuk72ophVDmn8vdCIGR0QEgQ5 zz1P5mCH+XoZ{KJNcHar8wN3ud3i(`D4K8ZbCsrj@RwQDIHGMukhB;a^6 zoy#g{PHs75*a$Vte+(aY=_yXHtrvdv!O+y851PV1_)0l&Q2yEe+3yN|kI&iM>H;{x zC6b#Ig3gl%4WuX4DA^V2P=UfTq9YKDIvJ$^ijYzOzcBN6cP0$A*dpk%V<4@~u%(_r z@bjypRYd&$_JmPXN@{Ki9+7nwtXsv$Z1E!Q4!Acy5JBqoKGLGWCs9^f()JwHP zAb7(J>#$pTG4w!&DuD-Fd0A+l40hJI#t!>?9zejDl87=vXm5W|g(2yN+f@$-hKdd6 zmvB%j$n8rza242;#nSU5YVh@NfhQU3YKzCNZQ%l;Z8qL7*qPst%}mm5npN32W!rU? zbCQ5wHoTcZu1Sow#Qk--JsUZ2qH)~I!6M6e@kF{rNCB?v$G>63oPq~Z*k?>w@1!}Ip%>CY3XBz8zuRNoP{T)J9$kcLY?jyOn=Tq)Y6c6!X*isV8!S1-ijfq>N=OVd zt@Xg{^vch<%m+rg+$v%fZhc@E`Hmz8xUlEF(7Joi2n>vCS#6cw;Cmk#Lw0ab3Hd*k z-^1>c9MgKY;TO9^Acj_z|AYBaRZl#Wn|)*X(-rs9v_;rNcwtiy;zi0A{Rp~7@^4*j z<8R#^H;{lbcT3ie0+JX6VDHPXiBf!nLkCZR_bIw%1ez&4-x#Kw#aY{dc6&(}QD89~ zqxWgF)Zcv0aJKqV_>e`#+ zc<(sP)<+B)CKgt<#*3UJ{V;FHusp-Kn^-7Nu$=+792smK-g4A%czX4zDiPHz@WX&h zB^MhXoTMxe99}R*jG(i!s9+pT^ySQ_z5!LvB5T+d1+ndi$eWy}N!MDd3 z3YEqZxhKlRRL-Udep@7kM%CXW>D2ALwP@BlDrU_gba$B+1*h%*zy9+{LjSn{AUb-Uftt{N z{{Jr;s%6z8-iiHKY&;73N1kdy>@iQ*Rj;={Im7cAEUfVM%RkSY%)lR?93`jz7z=23 ziMLSBL_*Efft*yxXN<{F2TxjCfO#1tVFw(nAAHZ zyA=?ih#Eg6wfgU8W{d2NtWE}BUK4lA5_yY^R;732T}{)8%qa*$$}GOO7X>#^cchd? z1RE{5NCb$c!Y(46X}_+kvjsf5<{lP$Ax~$Jpx_qmgQIuW5>4gZkil34Cj+ruX*e8bdyZ*KrRbp>(ERmeeOrkH$2ha2r+6t=9@uX z#AVZpCv7+L`u~+8;{>S0+W}P zNK#v43b-US?tS%+C5x{@9=+7f$5BKsmy}njlTPiQI#1qz3W;keM|ox@dlhJ#d;S@5 z!N{ZH5$IkP$&=ifNJp(?= z`NA@~B)7R&a-_0Lt|a=H?@6ckrq(6*bg*&Jn_M1dQWTgc00iW(G!Lqk{qw^=D+VD3 z2=kVRNBWsRo)F!`k%2OizQRL=d{hWBcw|0iDLO{ODCabOL2tOnu?5aX=%0!sx(AU{ zgpO>E`TJ=J)n_Xa(X=Wxis+%(qi5V=16koFPt$`J`x=E$71KqWrI%>rY6gYAM z@$Yqv%FpZ8ZGiO&Q^{sg4p!1nCo3l_+>Ab$oIw49*pRBGGZ-F%yP~4#`N*-qK(B}% zi>^N)VE@wR>w@?$9StmuVk}&tWuNunp*T0b*wrF0*3nckT84p7zJZ&zzAGYeRw$EOVbbUh*27` zR5O%Uj{DDR7tG{;$jh*r#DCOgT5(%BVEvFd7DW}FNR;3BZaBPF~NgzbxWaX)()%!D~t%72{xEXmnvxn`7&TrWis^-0BTnw^Or zkEXD{VmIPdr=TD{-0_X}&4g^{V%0DjmoDy<*mzTuy@FA}Jdhx3DSskS><8(cC1P9A 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

BdyQJc8eG{B3b;Tf(in-{nc(5Lv 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%0D9%y%7MU4T>UZc-&`X&x|s0T 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

    a>Fd6>3W*xWBFg{&)503F%XFTMkx+bXBc; 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

    f}U|^H% zt&eW)t~HCBF82%fCFbU$?Tch}Qu;n!rVyShfKzkekc< z;<>U_(4o;_EBHF1{>-6;=EBV|_KgUQ#g=)RYO4uF)WiX-4EqY|4p27_@j(s(QvMwT zn2cp5KpB=*@8e9SHNC*L=%GIyj!#YgA5&);)mF4c>kxtk3j_%eAi>?;2_d)_ch}-h z1t)0n;ts{FK+z(>p%g390>w(PQfQ&2)L!p>cf9fboPB#bQmL(ei zFn&Sq?dWv;` ze2Jp=!Uo7Iiqr zJY@c)59%Y1N{_93`NW#&y-uC$pVkYiOtzW(sk~(~&2yMFkdEIFf!#1E;|uiqOfdqB8k6l6N_?stXZ8-FghNBPki@$Wsna%D zZB)Nv;$_**=A~-O77i@m)qj!uo$p}RERmvJobSV8qN`0m#VZ#%<|MTayDZP}C4rSD z!^y?_cxVZ!3D`$1seeD}Q6@Ilxd)xCinIua3s<sC_G$P=|P*dz)#K6M6+L9mFrC z@k$yd9XWEjH>3KC5gFDfSBc0WjcV`Z9Qi%~;`HymtVef!Q1BvdQE0Za8))u9CC@ht z2DL6Cw~5j-7(O~l$+(wdlR40mk9}0P?#WU*pP@)#)V+?@C{se~NHn+MYk?{{Hi zeYn;oBnpbTkyr}mQ!cJg9FlyDo%i!+iqyPnzHGjFXUg$2kTI;@GwbX!3emy`!`B)i zG7YIOvutenYzFUaVL1Kg1WMp`QH_AK=2po#NvJ0Q#9Qp!>7nk43LUHo`c+Mw?HyI@`I-Z|!8 zcu=fJG?9v!VAeu4F(4S9ZJ+o6(j!z^bK#+&@_^83mk|P%gXKGAO1ia}Vlv{LXjssq z0=A>d=va>zUU!U3OS>d^w56MKXgi`?@xaZzse*JeW?cQs&8iD>y)G%eqg;vf-w@if zhX9oC>6#w!_jg7#U8o2EAN5+jMY1b%p3zHutu3qj^_9hLUcgzC8d3O;j-gI?dqu|T zC*{{W&tAVn5|v9ICK7CAh@yVrn_-DbRMdHHG7saN^QZtDk1Ln^s2VeIAD?%4`W-eE zd@lDS&oV|(92?Fi5EdpvQpm*}84R!Xv}ecsGT+P*7lTU4=jh(fm~_eIzX6hGL(9#^ zPNzIKITO4!3)CM`N3%Vx)x3Hmz$VMH2)xfTZK_KZSv476e-_yYQRSOf+uJhM*&}(D z^Q2%cglj*C1SH?j#0A|9^Kz1KYiZWv91V4KMeqVD8i4|+Ru!A)eFhky z6Seooiy9G$Z+VvrNmLvfYozqQq3?Cad30Gfaq3Z>hZ^Py$s2$Y&Yr2Q1ic(jVN8r% zXgXSNF!HTuDML@_mp!#5j4rE`{1Z)U9@gI1H*{8PHJ~@7{^m_B-i?x5c*n7z8ILN6 z$a#z+6}#_qP{pGPri6#2d2;1B8YXof61RXA-rnf1E#aPb0G}&nAU=JIkLQ7Ns!(8e zsgn*izhw}2W1FmEEBQPPEk_J%fNbm!@4;7DAgXG>tm=^=<`R4g8bsW0uJDta3dezu zhV2TnYHajY^pS&@MgYg+e+ZIN#xnwdV_*8x75LLnQ+*YmY<9;os1IF?!%%^7#J<6y z>WtyL=Of3NhUgX$X=<>F$GNLlOh7maIk;R-=1HH!Qa*7wxx1Xf67q!>%_Ek%Cz5zj(WWlv*lPuNY}Ghoqhx}=Ro9&qI+HUnO7e$VG!r{o->flm zdAv<^GCH0qcN}QGeVJDLyIaM&E}Fr}Htx~;Y1*~tr0!}k_$TXI%QcyYF_h&}VtTvW z$-{PEPX~u&QoUu}`fT$_&*Ku^;fpP>C7mJ6abuF9DixKk%xOmaxZnaVHrWo3?f+>n z&a(f}USK>xKU($}QrZq&e>#~1_hOj3o$cbZ9`^TpK9{VSd?9+OjVVbO8R-XRR=*#a%?U~8N?3J?eR^XmLM}eG}ONtbBIL&REy#k zogi`4a9R+ga*Q*PgxCS%hrMoWFxJj4g=O2tvhnQGg53HVGfmBYUwsf-AW8po^7!2| z{6?-ds_dC~8}i!J{hvW2YX?PS_iWse7i1C34-SoqO77T~`&!p!Yz#{we8&tlub0TK z&^4CldqZBk6H**Gk~RBV$C_;%Yv8P4Be+Do(UYq(KC%Xt>0aM4U(Rxz?(C)K3}v#C7$PAl zr><$6(>7(GQW582%!9G1kFFB-lenI=$5bRNxE^eVlX510*@I37vKbmAx(`djkRt@^ z8ujs`!jB}3fXus#rvbP)fOw=79`8jfY;&zKOZ0$X9G2h-y zlyg(^OFb@4Se({YP`Noo$46P%11&8Tsnut9! z`%Fy?Xs4f;CBpx(G`vZ$`k>D-U5b$w)MM5fQ8})9)n!Qq(bqy##M7+kLln~fNI0PT z-Lpe3G$5>}kK=OMcG*wN)p;heCtLZ2SDMMOb(O)E2GV;_04l zV;MCCGzAxo@NE2>vq@f&=!lH(K7QiJ2ouLew>sJ5+40D=yOSSD5Lxro}d;C zg8Sm?E%B!&$(%W3j4_&{X)YZGTYGm`H5Tii+CRCf@-Cv)RaEL2AkFvElY?ixfwXt0Immnr)Z=;Otwmvxkwid#`KW`K>hljz87e%3 zJ*bkP-vOYFj^y*-ML-tYr2rT{ZJTha4h&YV#velv6lWCZQUK)!oVJ2D=z4_MdE%Xp zo4*6oW_D**ogRJTc#V+7MlpjNMyM0i;^S5K3BLWP+AErF1en+4Y&b42HktvXP{hjd zar~j^%bcXg;#rhZ@&fq(Jp?dZ6s9m=t`cD=&bjh@Qmr|k??vQ_gRsuwyd+5!UkP+q z(ec*IWvpYn9&at(qW+k(1a^r;fHOV~0+~Bjt)>H;8UA1*Iw54y+lVO4R z)F0DYcL}(FoCq_bAC)=!$L;2<*o3oRj-yk=fD2dHlb3yPBRTTES$11wXdxl!C(mZ^>Z9A`k}z=bYW& zwzf7xAQ=eM=l%AGxzz_i2-YO4V6-9C284et4J9IAqNL>%9p3UfG;iB*{H(Et@lJPDvgeR#$q7R!2^D0Y=OLYx%d`A*3^>9-1~=;z4q1TGEVGaMS}jEpyN ztS4v$9wLl;@;+@x<|0LVovsYHD(LD->F~gJy?fE)X&PcGAhdRLG_`sMJJoz99u;*3 z0+ba_lgY^_B9o@Kyx#mI_SJd(OH)+By`kGJWowpZQA8n0U#tLQLKVmgZw{yxu1mDZ zwkPueZva}vu)ahVZ0SO9Mm33{iL3N6d2}$z z_m;=&vo?cjNi+=wK7|Xs^QkK#E(`lQxDV!_5dZ+q2|1~QS#m%9atQ^Q(hxXlf$*Ql zJpQ5vWVU#p5phlcP6Pn2yW;6b5uB=xjB<(YftuW_h2%zDFPB%zGzkNH6f9Cz0vBlW zkt6;-=NOeyDoqCq5wejkZ;zg|k({vR-Fon7Ty_<(6l}RkkSmaH>A=3dz1>LuL{+wB z$6Zhcnc62+;5ZWlvOkw!{s7=4s1prjXbE+AxOV>PzLmqbVurXiPnKOeE-yt3QI3Y% z_se|^@nf1EZ+@G`_)lSD9$G{L0c7(yH99aMsu3b#Y5)<|#t5mfGC1iXq+2h73H&Jl zLU>3=DC_xN%?p`ZacR0BX9SVyzJp~LfWzXSlAg>3BFH2Bi8^NPAlBhC`9xX~ii^ju zrp9}#8C_whPIo*W9h94er&5t3)Z{OPWQo;@g>Y!qQNm<1qXC4ua~73GBk#+<*Pv}0 zSGfv}%XD^-s^M=8sl9LZPcwl-TGo^F2F7l;)Q2ASW#1@dxc<^<5&)yADDS(5)|Uk% z5`rl#n3hYTFrb8|L&6e7L1qb^rzwsnTj0+pU-ivzPi^m3VWJFM^wwMHr z&1&Y=X87cYEKRR4St)vI_^s(lU49H^z>tX;bT1YzsYhy-0}EA z9>Sv35(6dJCo0g!l|cv=*bz-88~|oLIbV?bF~2(7N6oj0yC!cnHRX(Z*wH=LSkvy; zzKf@D{=qB^AF*=U_&)d#c zrEY{{5IvhW(cU^+6ww~@h@9U?r{W*)7=@@g3odR-8dPY{EDht?x*PEoiq=LB6D1MC z*AoG!{|u>zLOn*AeZDy}8l_KKc?b|+E^ zwD*HF$!sc;qKK{X2FmC|y-PX4(|iZuGIEkiROd>4rCm#IH^-QB09scMR*+(!Yn_ z>{oU7XUej~YpSKwAS4_7{Iz?Tv0s5qUi`Y2!=kM*V$Ntf+WT!|btd)HW2>3K9+l?9 zpPBgKfBX*LbBC>skVIGhqNiVhB=7i%Fn`oSaIhfRP-59AU>lfiAeLu0D}vUc`J4V~ zB!fg$=XoR9b3@=`zUi*5rYELWF!|Voao$`yN7Z-H*j^Lr%qXB%mf<9}W;-i1Jekm; zhgayPp)&^x`%6GD+xv&MGNA&)-J0@8DUED_zsh+Kq-2Hr(2^q%_;y%dJ3jU}{*~p( zhN1eof=Uxn+;mwN|NGB;eNeAO+#0MJk8XUnf4Jb^`ZFbyP`=#(Ob_K$X+9m*Om1_i`(gmnDuK z^Ih@#{uu$H&qlg<9^k;pRr5SgXOURA*kJ1@`yhTMaYZaZEDS-V3Ie!X0c%v2(UlaF ze80~3WS`qUqV2UAL{3Hb0Ng{p><%0Jc-47ofd%5(+VuV~A_VY5+*3CRa0N{=72+{w zu<41YCQMe{f8&S$#=#5F5^SDg(g_LKsU7~ugK%y6Qv|Eqt*Ib}fQ@o^nbje zf0VjC9K*r&)>+H5|9LQPh&=c``t{q0uK_$ic<_0&A#3HcMmVf9u5X-@xaX6}>z^3E zFC1BwN!RzQY0UCMepq7)s#^F~3O=jj|7J^@MbNnIPnQ}xXm~54XWmzD;rHHK34QX$ zRc5P$tlWVVG{pbRAJuJ5)Ye~IuuJXgw09V1Oj)DzgO+KK$}T?lUTh4auS!@c`#i4k zU=J1lP}0Asuy8J8LxAEQrAo@1m};#eOkd)Q9wg9>My(ApPL%ezGKnx4&T!iuC`^AY zs#IGzK%VPmXbB|hapO<_?;D|vNQiX9{I43lSKo&$_i5r@m}-T?+!}KeNdJ_nOH!Ap z^7;fo#oH!cLzn^_KXaGMg}UF%<)3i+askjB`**`wQfKI|Ptu^LX(GRR z)fB%L4X(7|j|zY&A#%9@{(}PI!WU$q=mHD&Zk4S{xRV*_a8#R}c6oR9cK{^FK9}5!5Lh=tZbNA8 zVBCXr0;IYkHnI^nE8`nbGgxd~+y&noKG^P_BU>~B2$dTjO zb@(VLZBfiErivGR!O;`*m-Q^`#`L8(Tl}F6$eZ)h|5yPjK0^64^2bK4Oe`Y_V#DoQykQzj| z*|PA;zeqwIgUC43Bs9L>a)}e{?rq56Qg4HZh%oqII_0CEiH{%-0D`WRAJQX&DxPh* z04isawp-B-cH+kVIw`CW|HkJ5%Ep2MgUfR0E@m`vId~*D1)Ufotu&D|FfGm_>DuWWfd-aHX<@Y+NaZIH(qa4)&m8|y_JC)Zts+7R?hsEfH64!A- z9hoEjtNczCYzsErH^Z%bzr*$HKD|wH2nqsPSBZ9p8r46+;YhiZ&t>h&fJJO8%+wICA;gqI+$oFggOvasfp>dE8Tr-BY4Sv z0S_t0K4#*k^qk4*ANUIO0~T3V%dP0Mtqj!Ibe&-w?JDQe`^y6kEM8JJeJkgGWoqTV zHu*g7le|4rSmH#(dNO%hc3V}?eTz|I2EOnn=VJxwOV#r3>jjt!{C)bpe^jK$x+6Oe zpLr2euI=PTU;QK+k}sR}cA@LJve>#Hbzq|3xOz@GK?VN$sCWovY=pPrWQchXQ(-XYllrW}Wf(YjCR-6117{;;Fx|!C z^q3lLu+W~I!0T=Hrc$~Oaf$ka4#v`1(@Sn&k99dJw-pQBL?qnpn`3}Mgt(WCg5c=g zQBG|)_(Z%X{|RLphjZdJNv>G5ziRFmV0%_W!P%tGTrVMl0Y+Bk=3j_}&sv`=W1Wi? zn97gsaG}yvyRt4!uk3lN#oJ}twwK<;YaMos?&9Q(cwH~J{|Rhkr0>>(x2VQ+?>~bR zOh`T4XX;dWB~ApRbN`m=_D7~2PjqHF(=XajYyVdn;KyzG^@#n%YbnmVFl7o@U&nxf z%hfxahO56(SzG{V{X0@6=swZ&5kt{FJKDuWUm&R$PNBN z52$b$HPJP(7;a`6!hj{=1wt`bPC;>Qhxerro=7CKm?113Cim?DyCI4yV(jS*qLi95fj`#0y(Ww3&6&IzYX`y8Ba)xN{06&SERP5*C%s$ymH7_wByD8(w7A|XVzdopYh0p_4AXxHHsc1?d*D_S8wS2MGxdm0UW>QH<)jpdlZa|2e{_)L zHn6>T_DfD-=lO>BV^6VwpWoYOuoQ{*(uBo#cjMfqc+r7Mg~>hWmr23`KBu&MGybda zR||8Vw_d>l)BXy+oF9iKLML+;c82F)4&-ONGphn(uYrE2ZiR|B*^w;|?*;M8Mz`x< zkRMlG4vDNvZKegSvw!`;Za$U=ac_NNZDe;(&C9^N#15BQrm24Tphiwc!vLqL8*@-mt(W$qf}U*%EX})Rea{AkO=^}hq?pNg z#qL7p*fu1~st!cP&~5r2WewC`zVY3`a-?*83eCe^;~Q2ElI72Rv`!KZ72gx#Yiy z?Q%KA_J&*{XDbAyuG@{wQ>L(q5B(@Ki=^*E^~fFBfmP4Np|ych9z}ga95CsLh1L&8 zwA61pHHG_CaVE5L7<_bl@|~bE8wx)VJ%(a1U6z%T<}RR;ekEDWou6MEDmbCL2gVoT z@qib+Rg3;`pG)ylRgyw#V>YxbwUswD4a~qi`xx(@lqROI=0{;td(3W7?3XIy7tH2` zO#{zS4kJ%xrVBks(%KSJ_*3=QJQq>|$Yva>pJruUt8e(lo<4_eSu?X~%e|DDX&juC z*57~3?oCb-u7wG7PI`quG7{Tf#CDQN>dlrvNh2lcrlyG4puBd8FM3aqdK2v;VG61X zoyY}+37Z65TZ-_>iVTrdHg>aXZtq^rQA3lsYBBmxxK!(>Oe<* z+b~!R1qa3$GjS5{d0q5`T;l7z0N+x6DTZH_-##LJkAnw6}6{)S98lEf{ZCn5Jn z{W%EZwBMWfC+F}X3e}yyB<+a#oKws=D#s=iY127*ZvW#7C+xg1W4;|uJ^%Yo94l1o zH*!uS;bLiCwk`j><3Lu>;~}2bZ8J^YaERmLm!}jz+BjAfJQmLQyVk-d8q5=RkMyX> zh?mnnrB%oOmwyfr5d{GB@lt`2+5hpM|Nl*EGgW>nVo^Jles5T*ydp_#Y3YmL2b;Bl z*cYH;;8fx(1B6CQU?5d^gR6=@6|0O3? z!u0l!HOUPJBL&UPkEkv76CsNMb*FvoHfK#Bt;t?1hpdghrSrq%wz0l|O*gZY^a114 ziHQee$O`WJAbz>dLb0RH7e~YIOjWnG*MH7y+YwvxgTsn4kkSm2x$zR|9FK~E7t>)f z*riFj_tGY~GuD@V>~>0og1r@D_t}r}(-@iWdKe!3DJ0nCOtKO&hYov$^!i!S5kJ(c zR%P}P`JU8Q{ga{B_7&GgJ!V&~b6$Cwtsy4a>p;6QHwpypePq0U>{wYSbkDbS^0Ihe zD3!G76T__j4s&>WvDd#OkqMw|6Z?IEwac(mj=4F1*&oJ7%`; z$w0j;j7ICAgh>+?V*!otC)75ROR>I9oR|eurjt=-8qR4=QbX4iPk*(&X3R#$yalXz2=nND^=v7B6+(-Te%&C2Ac5%UiASCKxkQ}ue2KPXLZb2`o^ z_{4#iiBpnQ-#1PFp4KaNE>|9X()|@+3#lxF&1JcM<{CnNe_nJPwUHdnUA0i^7<^xb zMC%ZTZ&GwTT$H;MqH=3Fv^?sf8{cyBJ?_E!J+G6MEQEAvl8A4Re!LG~$!xo^q=%s} z6B4b_xVUFv-%Oq7T*XjX>7-P6d123wI9$_u>h^h?qM=c&;O&f*6xjE5Y&Ks*85B4}oAs%>~6s zoaRGi%*ZM6|sFX)}a8Ee?Yoc4$vt zn&L6Xdi`PAThcvU;t%;+7`46}rwgSmj;$h7bNp4BYNO(o7S%n;h9cCB)YB4Os*ZhN zJnH!MubL-i;$-wQEw3$jv_@(U;Zy12`)nkKH#ptysX=86Zow%Na=z3{-*tN8SWWg> zp=wG|IsRE{>ZN~?@d`mdDVc>lGjv#_DYlPxdNIA@_Ez^@{#HLVgMP>wPF)+S9 z4$+oqoK?4um{$wu_L#soOD>?3T2Ye_w6N{5*k&-DE;oK8(eaDWhlWuoeez^&{-A8s zL-zx(=;~`3ZCdAtwIX(DW*p(s<@F?d9GPV(JSA46X`DkR8<&7O$-IpdM)Pt+MW_|~ z7`@m*zSCE+%)TM)d91;Na>^5b(SajLlbn-@Y##9cy~mIuG6gB&Uo`e?Po7zLt=Ckr zoOtq-dT~(KN`fIQhN*$4G$0s*0c!rRq#-QYn^`RE1Sd}6lENSY3^bypwq&)mi7P%c3$YSmQ0PY#K9cTK)ojMV z>?V}?;TAU0g%%mRk$@F~J!Q|wd;JJ(_+1(~LTT$}Qv8&*G}2|j?*n@8_r+emEJg=^ z?D-PuI%Og~5MDX%u52tx{ON$S^hS(X`=M*0+DliQ)2+WJU7C{@q1zbUyfgR_3{l$= z-am7a&GrcE<~HDL)vd52fzrduj!(D%53Dkqi`qv{WC@p47f)q)n-UB8Tk5!I+t}@& zDJI5a%BwO}!h0~!BT)jE)$DhLu-(0Yr_^U;H6UuUVrRn012R>pVaGCSRz~SLO+>g` z;wy-AP-buM^x`PV>iePI8+{iFBbCLzbIG3*cVU_@S)V3Op$xH)5Mtk&t>aV~h^J1c zdXme{7q8v3&?WGkW^Px<>ly});6!e<{Yd?s2FALw9I9XFQH$1gx(*x0m%WGBLM`x7 zS86~2n9Spd0mfSRP5b2>s2gp;1O*L1+1Syem|5N~cb!)Z7+kD4kvU zKUbGG74tYTaG@DR`zEoGF5~*C3f3W{hC7nBRoP=w?z)i?;R|x5oYOHUSuODFDl{yz z=2x^ZW0Q`y{X+M#Q0OD9^Nmz)n#y}j8EOJfV3wnsj4l)&&6R3g=uMJ%^te5x2lZ6l9d_(H4slJK7BRo z0JfvzP@C070arTR}C-pT6Y-hlyM3Aq})7p^bIzqnL^jTA({?!+F^u&y6qG7 z(*zeygss=Yq;pGRqOK9|WHvy|6|Wxr9DkBJE0HxI zQ)3!d7i^OM0rS|ck~z+R6Z~4~u15?gBaQKjOS}H-(HH(wvtP^NLyG7PLb%G4F+{cw z-2V^JfS*#redZKg^QO`eM$vYO;t7p09x>&r3EH{#9MzB_p)e`bldZji7iH>6;Dtg20x zpd{5N6vTH>MG?L{wm+7APY_Pj7#N!xJ>vBWp|5`>^Vza%$3Y9@nDg#!6zDu&(5mQ7 zo8w*TAnYs6hRAIH#v)`Rdt8Yt3wj zCtZgb;`Z4@;rX|GE9}_>j2Fh1gW7TodJbeJlA1R2@!ZK);qH>npbFH-PkS={J#FQE zJdlbpfGJ#uG4iSBZEitI;|jwhb*Url>aE1?>SCk!oS>i^w2P{_wx zE4Q@O$%c$nSY+--m_Et)GC1e^1f@wT4o8)1St~QhO->doYXqyui0*bGACih--_U@} zu#w(Gl)d7Wx;X-;mnaq3?pk4#iHJ{j$xP#Noig2m4$_i%U6KvupOFR}j~L%-J5aad zPaqusS)%XL{C*YstF2O|AA!sfiH^HxDl@nGV#p!u@`f?Bj$PTEL9y%0c*tsfLTHp` znhBmItlWSgmrE(5D$G)VH!77hjWP40z&c1W7MVD&^Q?XG556}ylSq=BNaCye^C-!rR2qFZfE`-k9+ZURTeRQRGR;%ux%_k*%q4Ta( zkc@j#9byKG(1a9GsE7!us~2Zx=3hV{Y%SgiORqM zN{-G$0IrHjlYx_MY}l?<(26&cyun=h2k{fc^HO7yxg#@wR#q%kFG{eLO6aJ$jsJGH z0wsvbj@#(zEVGh1vS_h|tGU(geLV^~aB3vCC`rTI7bS|!KK@WyYDYTD1UcSVAI(5_ z|7HS9F#>bEMEaCy%rVPkkO0xLq>5r_Nb6INQF~(DQLoKGp%wu6sV*vC%$K5K(c@4t z09*cV|A2bdbg4ZcRx=@Si?M^<)bNtggmN>Qkwhn~FJZ-f+r=l_?MUBh)SYq8{y@`@ z{3(Tt-KH^K+9o$O%!`JoLA{@3AzqVRLo3&{{0Ddy$hEf$dEbwZI}&eAzACPe#rus8 z$P2;t2SMZny=ZTowTJ^22>Cly>zi#89KU7dtLh{UYs<|_pQIS-g_cS*Y9lAy$Kj*( zXaviW$a`W5oLr^Gz0_@ocu5+uf>#!Aopa7G*CirdK0QoDhvP)r$(LrsHu5p**6FIm zOH*t0Y%K2}mXuv@7(B-(gY!#u#?;>-C1of3k&6Cy&C6`IEx~!Y?$TUR4_j0Bu}>0g zTBxUtJR3VdPWB3N*IZ>OXlk?6Q-Erg-N zD!9fgpV+PxkFi!^j|osgD7&GRYSOcrJDLy8Q0G7|^a9+Ol&W!m_NR!fjiuJOT(C6r zTISU?4#-f$kF;d0^I~|1m$&v<*s|W|?3MmkNk)y8jYp~WnuasXmj7Zop^_OKdxAPb z%7ov{J%M}%3^5JS-$|C!Jd`#@T%;9OeHmyp`8pz`1BV%>@g%<26HG6@Wb+Bgr+rl| z_p`MPUoJFD_LECRSZ&u0&^t-;5+@mljk;jl5PhGDkTjEgx-wcR3QZ%-tDWCtxc4np zYe}9gHyenz$dtj)#3kHjeLNaLadr>^!lkqqS<}CF~Y)LpOU@)Bs+8C_R2)cVn4?ACspr>Qqbz`M74y!)kl8Qc6YD_)5x2FtEJc@hODb^A*J*15a7Q4r{@aETF`Sw5F&R(%;T>c6*+P51x+Sn>Zxa5Uj#k@l}yRIJ)l zc)x5NSi5uCa*Sz8Q=5!dz$z6Z-m+7Fs`hjfUkSu*1z&O^4tFYIVzEjm{}DLY1HBM$<489 zeSiAkeAZ%&phic}>>jV)l|j9ILJwU@;ARlUg_g)6h76TQW8jzh&d4T#h#-1ZAez*A z4T4`3Bq16{GDmPL2^d{>Wk!< zKs5m!fO9N@T#SLup<{}!^aVj~Z{1Dr#^p##F8cW&<(5NH{V!?m1V094ia2=R^D?N! zfrde(6U%rOLfexkt4~1xvN#i_Wt^#*Qgps1(t0P7lHuWqGbfl{jgxRVKZyH<+R$;V z>;&v3!r-P(fT{hQfX=iuM7+KUu|yDSfEw*Q=HO2&^2O`PA6@Mu=CCnqkr4#KTv5UB z^UJ+x$GB8>#{h)@^JeM={)h<~0xW)t;LXGKAORI123S;W`67|ELRU2qu@@290et_R zmh&L_i|uYEv^UO|W}fROOyWB;uC(;j2`(bTi621{b|`>3ns{gU(tuPT5X6vNr4|=m zwD0V{+65;-8h3~}!Zv^xb@g{(Bf;^0IsL|Q)$xQZPl(8eaLshL4$HZtB8E0Q9 zr{ugZOa+aOANBSh{NokN4eEWKM%G!_3|w#tjxR!qFQ;%R0hB-!=DKN*onFTeFGaLglWW0)_F+S{Qo)16^yPX?Mp=WJU88pm}4O%bzJ#riKxfD&P>=xyZMNcIB2kZ zSu4__c|RnFZni|%x>@vBKkgE@LGeY8Y{(&R4+j^0SJo;gxaaVM=mBRqKh_rgnZzc2 z!|_dmq_cuatf7CuTXjO#a7}?}tZlE2IZubE_HO>EPB7+da+>| zuEFJ>zTiKw&AmUu)^Ob@KHcP$4S3Wc(IL)B6X5cZrX&yK%lNy!mvQ`Jw0*woB3{-Z z?;|*2{9UgeKS4+DO1r*IBmE!sVbYzS#*Rv`92~2~GxKC1U=7R%gKhGJh+1cJog z1D_~Y)NY76+_ zzx7*22mtW^uYSw^Wt2ZXkKepJT=>2M`PjjMC5TWW@B&(tKDjOo*#-Rz+ljv`sp1R! z5&j}ymcBlX$Z3T1>l`io`A?2tx!JaiY|#V=J}y$1UtTJmh5(weTx@@nHm{uiXnxF` zGzw2S1sc=Q2YTyb2oLhK-jH*ea`rb(gt%tg%p)YR#x&-Yn*C(PPB!ku_#bJu4CmgQ zgnzI??PbqY<)V3CXO3P|*N~re#WY>i3_SSlatXiQ>YLj^RyieO-O2pNj;k0Z4-C;i zsnW7io;N6rkBNy1-Gl2P0oT&GL~gU>cJy|zHSR(EBAG3Eu_U+BMLBLHIpmYt7~|;R z$sat!0V2wb9o}Yxa2dzm=$|;)VS%-27{nL$Gz?Oy#{5~`>pQ0`s(;5lPsYBN^UZYn z#|HxA(A#j4PjMJMJvJA&Q_&#B;QiM`5@Ohb=9$cbe@cH_^>dbv*ZfCZO|ulCKzUZi z+`Lz*R|J0yRs0_aLrq^5lo(_nhM7un9~~265B^#-Bc%}oWb(;Z1V8qft`szbM!7h| zz^OL@6tFdxaX8*PuV=q`gQWNv^mLHJzJ+zDtpEk-Z00&l`;J;%zr^64gbYa%olDrP z7}b4prWFXW3XjazIeJVWG{cPNl?*+4>Dl;%22^F!@IC#wJ#{VpLn^q|GZMWGdtyl> zq!`J|G()J`73x>Tj?Nm}`|`ybd2t*tfeRo+4EQQqINA6jXZ!~!MynwksWd5G;_n)o z1~MwOFPqf#6I<0-k`fi_i!G>6d#!Zs94S(q)P`S7v#IvlOpK@uk59rRcu+WV*3{sO zlV#IM<#<8t>IHVKKJ!%C2nn-I2*x3qlO;D^`oXC7jTrVlGFPCVK1t_u;mF6=9R{OP zZ~?&+d(qFDMYjwR4&$H>_+gHP?Y0(0(e-g}zQBr6%Y|DXp5lu?qw|!lmo*#@`9wr2 zHooid_g>zrzUO%^O;@-3!J|AY(Pn)kC#URQeMV^_yR@1PA;Baz95AMRg@z{K3taSw zYn+IdFy;ivaT^g>{l`X+E)8E54M$0^;5HH$wM~Mr6M>%5Q(3vQ3AfM5jL7vhPGh1S zSW(quoW98DuHt zQ$+#A#E144H-BU>bUCX2Kl<(%$S@xRr|9cMdh}M<$+D$*$*?X+hP%PcPvX@^c=KC6 zLKCiQysQD_cj&ezf>GxiRgnT8o<*o6jo#vkSr)Wd%bPEojn_2kc>>%|?O5`#(-!o>9FFTosYOWck{c$iX?PX6}4nsfdZbQC0` zVyFj~IBsmY55EvO>a^3t|4_yh@FFzbCYU`gQ550WUN?pxRztisFCvNk0v9aJ8k48Y z(KMY;QEY3T+~sItk`vcmH8`Vnig+m(=!eS-=;3zw6{EmJJ)%KG|7V9M8=jf%;1~D) z626wyw6oGFir!4|0}~r&M)EFl=wO9XkJR%8M(fxgN@aOQd#WYJ5J)-MUj#gdK9qz&6nIo$rX##BselJ`g!4) z_OCQ&@fMTNed12XN8;_aR0@;M^|N0ZV&}ON9aF}?CMWgC*+@@w2^F8gn*~a2=VsY0 z`(JKUDD*B$Dw{F}Lm_S-pOFP9zzxW>wdm#@ORyz_?V2%{dpU1pZe`^MRHRAc-#WHY z85%*J_pxe8T|7hJWHW5T69u=5o(Co5Jc#Re`Ltw)Al)Psu|+id{Oov{mcezsdmt0g zr6{Vj_b2r;CCWP^EWm79eY(>}WZ^F8jhevc#)R8MBjCAcW^u3m|6%I8gPMxAuR{n( zsG)}{p?5;>y@lR;kt)54fHWcWP^3%mO{9Z@h}6&pY0_&zihv@Z6j8st_j`YQnL8(Q zXU^Q*b7nGU?X~w_3)0SLf+PE?ev)B)!F!+4Hwt*0{A*XiokF5IsK@ZbQ!{e3`w{XGtXbWfP(UxU72 z`t#)0Y8QSbnfk~l;Y@d8M_AA@PD<^6$Hx4{N3lT=lwgf-A~E~WbYD;&pcm6PlK+@r z@{_^{?%7xT>z5rPDKh^A>GXP|l?aHu3{1<+IC-;cxUxTcQX$c1#$h*)jLjY8jchBN z>c3|HG&3_5;{`#K>b0BXd8=QUK8k)yIbg2c=tE-$DKXyAGs7{{I^i(mfa;m&8yK5u zKQ%KmGZs)OG{7erg2KHTs=u0<)HfJs^`2Sai!?N7n<+Ka1Ec=C+GK2+)c1b}bTT0j zk|?l)aN5adf3GEv4}=>AVCy+obZF<3JJz{V*||vlOM;MK&X^+)MqLG{wR% z#>BFG&DdQNbeJUlvdW6SAOnY<1`q`Lf=7;uxzU_T0rXA9;`k${8|Wc!32q)h8NjOg zr*F-n!Cge8v@G#{Wk-S>9~#N>2`xfaB*=Fc$^TDY>BR2>}CVz)`@e}XgknmTShmAlMi-VSxZaGzZ1K((`IS=dj6~?^6dnQRJzLQNg zv@<)umWZ!9APX5?6GG;^iS4gduoP^z95n@Eu;JKH{LU_?nllVnqsJlLAy-Z@XsBrC z!)x1NNMBOtOZ*OIkMMmF6=i;3(m+RoGGh3<4ynQr2?rKQ`xM81DJMqd2!=bIp6*1x z*9p|!2{`FlFA|sE{CxRqA^a@G^5akv#Er@kgL@+&F+@7=i9HkJ0Ia0a95GEm!~HXN zOVQ+3)xZq~a-Z`*JY{^&B0OdX?21{GCybO=6hurl1Ss=WUgaUS=EZK!hs$JR|5v4+SON3GD^ z$6PcgrFQU6n$9QM;(6dFe5g+t5bc@=1!cRo5<5)HRGf_$$yF4$hbtG5UUH?;rmLD{ zL`s>*ug4D`rgn;c`2zIWWo?|vNA1omj3ZqT7;$(72s`e0vPeq+L&EHf3{H{H=8!^H5HNEC)>l3OJ*YXt6> z;dnkc^1TrKF*aR)H-+D+TTt}ztSL<1F<=qiSH>*;m7js*-RSA^jnv%7=WHO$9hXgv zldWHwHNQGEBr#0EzQpm7?Z|{>@EbDN4Q67t*De9}5G|lEJ-n>6GMH^P^`Ve~qX;vX z3@&jjLh~zp23jk%oHZRL}#-Zx$g9b;>$R z=S0&YywX)s=cCulQ7i51V2m=Xc8u}?dM+a~CO|OfnBdpPy-cX1rCwK(H1RqQY1}~y zBR!R_>hf65N4?fA2FLDt7^V7?)P&n&zbrMqAup&M{5_*kmMYY_{!z}Gywp^Cq2bj$ zr(dM`iPfC3PiVM4KctZ@loD4``)wH^O5MJ*9PPm9o_L~=*B`V}5~+u2d-wq*#<;V< zb5@hPYi4{VwiCB%z9MvGA}ky%jJI2tt4;Ouj)&MWxmIhfli?RJ{voDa;<> zylguVpddj;Iz~y3d1mWg3v#9^Jf(nV4c zoby)<>`|XP%g5`^c^i`TCb%?mTE~dFnO*4)+t{WR9^Bc!2fW9y`=D7uTgYSh*r0Ji*~>&1&>7t^py*o?vwCl zzFSR0tPrHx1#$jGHW1As-j!79gXI3kRr@dqB|ycr!2X3#QR-b{U}THRfRjN29Q$8l zq#6kTNzlHuwH)`?PDf^0Hj3v#4-N+slmpz_#*?QwA9I(;v8_8C80+4rs-&YW1)L<^ zHJ6SkEzZFfK#Zc+L5&xEyn>*CGjy}hh-e;$o zi{JV@y4}lt-qa*TN7BL0a`=aq>o}3ETWsiYN;NGFVuo>rq1}cU$FPWi%%9}!OI>(S4va^kwec#&iTjE;`tPKU6*)nY+;CWPm; zLj&0PZG~^XM=}zmD%FxJRWOzx z8_BdB1LQ!;Tr@pwk^+V=FQkFiyD`e9LNij--xp}ggy`J~AfLo~ZqBxC_4VC9W;g|$ z_%F?>(y(Y%am+8&;5+vd?B+XsKvQ}s%aK)FkRQywPf{}Ue)q`d<Lku4OTwNKTra|(CI zD(fiPDq05n_c+jveS)b6HJWYZLHrEK!*h{vKU=(fN!byk<@Xp^G5VLN^hwCaE%A(L zk3qrhC}`aN0pWP-1Z&a@B1&BYo6anA&P1xo3Oyk1L%fO$k4MOo+7#fKO9A1N%X7oH zA?L!~RCxw5xN9nW{P39~xPXR;VtOI9TFhRZUpeyUq;M-03T07v>P^c{Ud+18SQQEQ z$iJ-m4JHroD|FzPrNdD~);CkOGlHatE}kp8A55zv4ikuCX+jheOjzm$dqpNe_;GLK z#KM%Lc6Yks`7=J+rajXAn=gPCm_?bhrB}MA1yK(13lGx|St7}`)JZbjh-N!YAbB_I ztQNZ$?%uO)P`&SQ$N>iQx!tsY(yL)7Y$2q5|p?;Pd~YQygqx&WrzHajbeP z&vUK0=R2%!ByHTot+05-mf!beb^3q7Qv+BBjsYMQK7jih2tYF+^cNTnU}sTQqGtW{ z&zcsmPzMbL5aFoYpW^_d`H=%K6%dX)9KWGD8UO%g^+W^IqlVdYo>Yf9L^n@%^Q#X4 z@&OPftdk9veg5BtQ;t`$0vOCddYRQ8s#wqAay^M|#RZNrvByEM6Y<&p)8hgFxQb2y zC=gcwpyK(22q+2npI*Z(S;cW5tzMy)^;TR&27oV_q8J|lR&9;Oi;%~P@+pBdXFMUw zKvEj)1AqVsjPxTE`&xv#f7ZUmGKpfX6DuBru4i$g@d4PE2Vg(Mvq64DHNsXrOYN z_^;$0Wt*LsI5WClZ?*ZzOK{qW&UNR=ol1CmC5 z57bB$!w_!#bwHlp=ETnuzJr#2NC`C>0!W-5%^ZGiQ0xYYy~cmB=iKVfOf)p{h;YT1 z7KVuB!KZa*)PmJh<8@<#1f!rM4tnXsrDaHRi#Yg8dWD0YumsFeiSS4& zJtpc+qH>>5?NAdd)IyERC0pB>ww|JZ%$Ajny+FrKmShoyJE!{)Kr&62CRG{xJRpm= zX1pe2J@#2k44##Or(nKb{2#|?rb5C7p16Z@THiEoy0lLm+~?2O%`fRY=>OK{8COcPo`bDp`7j8YHIexAyNc51rEeEz_jMpcf}x}DTi7gQ za~kj#KS5wn5)v=&GV63Bn9pgv^Af+&y4nk;S#r27nvqGZ*i|*`hxWJ8Bifj4-S&AC z%VI5z`k(@5jPT%S!kDQSq>51$xdY1rw3g1@{bfG}WWN45&+Ti~W?x zReRIv1d_Ppjvav3H0mX?z>9hJEPnG zb|{2|mCPN}a3Wo^!^;o7zb7)3=CN4pMkFq9#74}f2u0D5u#eSTpC8pl54X_p-C z;(dW6{#@glG_$0r19f4y%5+&$f`h3cnSxIvCDZPOAn?+Nh85z~n*{gLTB4=mz-OqjngmI-q=9a_`Ce3T4B7l@YNY_z=M;jPydEJB1f~8n z9H2T%dsX8`l3c@Ct&~0{gOI=caSlAzyEd5C6bjMd5wG!x=ZcXIdOSA9a{Uy=aV+8St<7+Pnbs!-J77Y>KP__s-&BAh?Gy{(!az7VMm zcvo9zx@(mR)f8_H5SdLG+(YAjam3kl_(y!4;HpwcNlha_pj`uE207&>sB4dCXpa$| z|HB7-?%?owz*S$YYq)^Y0}bIK1Cf0+R0+`C0EAP78MEL=A6&qI;gG1S<%qDmiz%Z5 z)!-Lrrk2=q9q#C2+Z6Q5Zq*l-r_LaHmqLCXU)Ug8>RwqMM_B8QW)~&M2z5P~(`Qj? zE+7WBMjIums3yUpq~*p>IghG{t!xeC%)50*n+)sZSiYK=+${Q57mSAq(1pL+db3My zbs(-5$w=eY)cr1oSjw~_Qx|9}u!Uo^$fEzS{RJjr9jldO64zs9V11qWMSu8S(?egz z=}d|^c7)1K82`6-s)PoyFpXC7g8jpcShW`)lG&YgDw0Z7LPK_h)a_OTI3@D5$*^)-?i1g6CFnMOy$gwEDV}fQ8#ZE3u4=MQx zwn3(TV>~-Og_x58#_ZW0{jKw-R46vrN(Glbw)YSd+v?GI_bNU^zOsgaFQLr4X}QsA z+hqSV%Y^i!dIoS*lK@etzFx&v=Ogy)dr!3DXpiOKNVOZV^<3-Wpqu6cfo?+xbB4(S zvdwst?s`{b@QTNdd`5i20wXg=@^f90uEgoapG%rcBSM_;^h-ZO>cjG01=!$y6`VXnOcbv3N0E&x_r+*Nsxr;ZyD-CnO7|D`IjN{)fP zQSn8B9IrT#XpHy?Ri7%-K0A4|CMofybTP$wJ&S}Ht_JHIK1@2*Vvg{{qA=oHU~)!J zL!Qj5+HTCLTYG2&?RxT^DApV><%hxG;EhzN_~krPGB`j}@Wzv?6l}ASAmwd!)Wd*0 zVelQ~a!;nS?23(`C#Twn>M$60d|4R=gBPgx@8k0FEAg{nwVM?QaL`%ixved$fCA0( zp!t?YcO@lq0zMd?HiL8yjn@=B4~S(@MN2t6^e%IkUjN}>%{}xQf2i@4D$b!=h}I!L z;YTc^y`3~pMg1&^?KckmT7-c+wU`j-#?3nJ#$kPIKtJa~3Zj2TjcI#nE0hP_#qz0K z`rHm{8wl4i7rXgJn?BcQ zMyXj^seR!z*zL&tP&tT+$O(R|b_O`TM}-!91Pp=0N<> zZ!_(-?i*N2X^(JQ8gZz!Rg6DYVY?Y1{=G0do>YV{O*P&Xi8?; zM>7!fBR~uo^Iy<*fF0-m2igv>v@+4ZxL1_$FyQzY zn{34e;OYVhh;jtsU_m8-C7b||+sg{astN#@=`wx)SO? zzlD7o$O51QhY$Sc4vsrOa;T5+09^hL#cvS+iFgyeI{$73 zSUtySo_ALbIpU1SRKZc9p_6`Zy^dwyadEtR2>_bZ(V(3jt^;pgLKeryS$cvIAomMB z#eZ=~ipLO5+>VeN5bl_9#t{mz&^|+_GFK*fg%ieFGYR~A;tQFtYj3=DbP9OgG{u0q z>uc!-X#Tdc$IaYrB%SP!vd<#7@b^eu!bhD2G7w5l{${%gzVQi25pQH>X4jfvCl$CPvh= zWJcLLJF=4cGe2c)WkR3^fVkyZ^7!yWeh7g()gwEgbu{PkU0*|@q~@^o_WV!$R@Y#J zBe5leT=vvBZp)Onh&Vy=#`mxfJgnwSQjcer%zOKOMn-(OqVG7n0N<{C5w=tA#>%xM zc>B%#YLSWx^w(_uSwjVhxlq`wFFv@3@^mEWTpsQ<_LU3-5cm zZMGPqBJlQJwL3DT=Uq`l`zO!umqot+MCbn$_O+DyRR^>Mjc*F>KNqZU8)F?0r(8C} z^EA5M`aH(%-1iJ0`c;qMecFJgO_y`S^rD+ntc!kks*cBQ1l6Bhx=E+^QVnF%O3|-= z;tOF7t#k^aTC(V@MxRT6arhO9n~f^4eCS+Z1~6bHxThd>&OYUbwi~t=dik0Pt+}bF$22M(qvm zQ2!io{I__!>+gqja>F*ui(zEsHa{)KeQ!zUF2@9dRyCVw^f&D1^Yod7+ujdZ$&b8( z5TupWQRPws$hGRZ6b%r58Rq1$ex|lA2LqrX)!!L3+B*(pfp-gp=*5yL z)77RIacFIJ*xNIQ1N4Ll87Xta+{1WrprBXeHF_Y4hju~6Mo0^sbhX50#d?S;!&YMJ z@(h({?CKK4QWw_py;f~&c%StMs`k^3rIj+zcgh2+SiI?G9ZF0X?W5E$Qfw&9r&G6R^gtW61+jd9EVI)0^^7;WNtEg zWAZ$P_Q|))-PX7wKacb#JeRV_USx1td*FYS)F*dy1Ttz$&l2*ui1B!h{TigJ+M{@1 zN1F5&z)1Aj!qL`M?{@-{K-vt2%@s#6_p+f&Ya5cu%47`q-8q1~m3KdBHyX`;eDC(} zGNSU|+E1LJcjr_WO?>n0{?M=Xsoj%9k$@qg0G9myCHr^ghQ-JmXYOaL?-OHKw(a{| zz)Vx4vO^ zn~h3qk^zK?_sN=odAbr|*mU&^=mtWzUsoi^>wELJjd(T{)n zVj9wUTaoHLw}sa1ak1tMb7NMwnowB#M$fitf-rpfjQ`|UKoMWAMH`5*-7Q<8$oMdo zd~~v_$%5ecy=Py~?{Qli-d6-LNQUDxSX_b(>-#wPISWhl5}4R(10lWaUCo+ZUPS$< z=EWzA^O-jn0nD!y-bfCl+WjVY*7Ni*-Q39Hw;-vi?A&i=`dgZupb9FnoLz0p<$-cBQ1BxqU{ip*z$IxnQ(w4oYfKc6O2I0KpemJq>0 zp9MrhxWD}byz0j$ytjLhR%`H1PyRA_p7H@dm)OtJTj71#8g`CxVsURjwXM{N#M;d9 zc8RENolQfhw0UhVc}Y@DfMgbqIbnGzY8hdTa!2g0*XAPK$=A9M&mz7hJS2&jNYS|5 zPQztsjWyhlMV^&h+`T^g7NlmReKC0Y;2R=>IylZ%v2~lJu6ixs?z;We-!cZd&nJ#8 z-9JBwibxL%T)taBvo{J3Wkp^fnFw;6M}CU5e@r7cJO4DNwEDWsg7o@O27|5ACtIo^ zft|PA?#Nwj1*-PDk}3DMfBoEwHA#vR??@&QxCX}l7xGYIiA!pQ|EpW2#1fYl_*Psv zK8-5@a>fGenfhoob3!|(AwmvUL*wB2#UV6J15GS7ZH6vkXW*m`yVd<`cN^+w+{^X; zmRUJn&=6pxNd+Xri85Bopuv)j^NBEXt8kiVHBel15?)RN zRhDHZ$5pW~FyvTr2>1JTVrkx|WErjF%Iwl|D%*+?j`aS3Lw!bV{fPb(Sszv@8THp3c<-N^$Ags)$wr1I(Xg7!3&Ka<+a+4+ZsoMQ^a?wNf}e}BX8_-?X*Vnm zuviythZ7|Nz%tFrz_<_C^%4L7%X0?Xq#cCMOh?Z(qtowKC* zq?9itPJWJ5O}9;%V|%cP_fOKL;VVi_Nsau?aGGktQ>)986be?UOr*_at~IyM=uC$V z-Nu>0UyEQaBJLfA`Ot_Xvp-jT@9>7$BPGi*NMoX+X;y065^QFi^<*II_v&2ngGjp7 zcNDZB&mo1AoB6G~&qmMGL&p6E@ghIGSh0+lAeNR*kB?x)7Qqp=wxLv1^@ip8-cI%x z4aL~n|Md<1o%!v7vfviC@8s7XaT-Eg84=zQ zyG$e#)Dxt%&RUf^lhxynw^K}mR`a|NPFuzLU6O0ZzfTS=$!6sE-Rz&sqfpEaTs_qN zCHOo@gTa`a{kGPX6BVcuUes=5yVylP$mz|&)r#hZ0JX*Ty0w`0QmPNwQ&oENLF*jx zMeJa5E8q;Q$+YPqwkHUF%XYm+-^>WTR;L$dDt~G*$>%P9A`<(J8EN}SKAnD8_gAA3 zw->Q!D@6UWEvM=6nZgsr=dvbiz0_A5vX@zcJL&!`t(1~6lu^IE`HBY*v2 z$@%sHQ!MHw!hwFBmV>V~Sm`GVcloGjsRG;?wZkr^21fL=oKimN2?)`)adJu^BO`>^ zr3v-z9k$tJ87rnHTgLQBAN-}U`4v03p`r2F>=1cELmZj&%St>#Xkt>}=9S73dxFug z8s4U4bzDZnr>PNQ;JhowMN!G(AMr)mrSKO6dMyoZM z%8$M(7N5~sa64Tlw%!%_@iymt6Xe-uc@07vZ%H0GhnNr1-6fDvX@+%`*uQuM%f0(Z z$YY21JJEO|wx2pUU>nk?i9h)vJtY?n3|6e+$0hq9m8XxM?NwSe+euwHvQ!p$?N^%l zN_#BwoWD~%Orqj5!4tMIUEL9YhHvCWCi~laetIL7!2Ce;O{)K98dr---|PM`SS2#` zNZ2klP==Lna`N5wZN?HhHu%-|?x{B+Bfp7x?~r_!honnKp)zpbAXrMv_cy6lpo%P%O5Q0Yb6} z$#U2$$}VV0vaOtGVatW$Dl`-Bsnu6{SQA~D5$D}(P!;(+=WY&0WmqXgC)CqQ57FV( z>r3}Ekr**&-8$sRl71R6A5`e-`W3<`_q>qs?CfU#jYLJBW|?!^YsW!{`b?d$^)E!R zo1-Ip7N$cEwSKwDt^hM3a&5veB1Q(+50%{UgSom!bkdS7F6#JpF%M=e`#?^viUv-z z*N0vqt7~K>c3~Tm-@mid_Fj*0H^0Rw4{yhlny}+Rdt|-}uW+yB0QmW_Y?ojxrv1u@QhcVp!e8y??(fwhaG@OyBm;EU5weIMq0b|ehb{#1}R zADhiUO5lGGbc!GN`;&TL8UuM#_d5DyV%uwizasi6r1}R!O)zuJP|0C#dib2rK|XXY z!Gl|$yMm2M`-|UGs^~?O?=F*7Np0=%frXzp;9J$47iyc~2NJXz@%Dp^;36kou|+*^+qPrl7K$9jC>rS!SIv)j zjL^ozQkxVEw3uS~ns*Z3f1Dqes>hK7J zv92mMijl9A^s0Lkl_6`DE(b+h-VI( zKDPHAN3?qlzi=H}Yn3V_mCn4B#QbjTVB3do2`@J^YL0Vl>?moDBj&DpWizSQ_^-!B z+`k9Yskj=(w)-g|jdBC!MCaAJboK*2m~D*lT_ulY8vVFGHS+OK;62lPU8U+-3>lKn zb>g%0*g}YD|5zV~r+zj3H4>yRbMD2o!`bV%K5|CX@s-H)ge;bKYzCn$Mj*WSW7E)5 zy>0S)nOyD9&9MTEl7C9y=l8jrqfX5%w^M#EKWiER(#8s(6i+I!TaEuEo5>UG{U}nd zhGZtm6K+FIwdaK1fA`ljdvNHiOK{hs+_Wt;7;=X?&LNu_OncdkxsGyz^Qd57SkYl>e+_Gzl+1!~+h+KMd=ew-yf|(|_cl za?gi&|7?wH!#s2{^md6C2Ag0{@xeE%gRsCOal!HqJOB~J@kRFpFEg?cbmG;*sB%K{&~R^fP0=1GbmoYDBb zvZ|KhZ4ubJz!`bF?gt-LJ5hQyVl|%esXR_t^=bG@1(JMz>BrvIRtEan=Ra5Gxz)ec zqs(kx4rE-}vsd!f-j}~1m|EXaia+vF@cRnn>3)FblpirOjcsp1_EGYM-y*Qi0Ccp- zz?Hs+FPXyZ(FG6A%-+V5lPNsi)Je#AUm6G6ey6%pnbpT+#_h4H^FgO8`<-wmtSuSl zurJ@XTz}%{?^|}@>RZM?N<1+myz{4>KGgrR4c5qf@>J(aR;Vj-%qL>+<@wdn&fen_ zKOIi4TJP@88No?-;JHRcjiyZ+{j0U!ASsC=c77DRX*028bnd0+tH{Bwv1c|bArb`4 z>kBfro9kA8gDGBPz7$dSW>^Gi4%r(y=vF21{dBr(cHMjKEIYA5m!V3!+c#_J*{~&& zran^_X%__@YnW+G{r)=*|D_Ofr^O-3aB)?~3-w_RdprTiL$-u_e_;H7VWlt@ep~z( zRO~cKHLYLhXuo^@=6`5&uh$k1{nc2)FS> zV(A3NVnqD&D0hzM5pV}aTDG2y@fuSxYEjCb9dTx&*(8`8S0?~Y&84GuL=fvb!ID@1 zuqFOhmWx?GON&cCCre9o7aR-x8FxYu@D22a2Cv~cDSq6AN|NMOp{W;W5Zp-x=K4k) z#7G@?B+^GKx4dNawG@EW)4Pk5&Jv02LYgqS}Z_iG;v~mI+zRNuLVr_ z?=JQ-0I^(;bl?Dp+AU7EWy#;21*k~D z07MDEj^(bMSpE}K08B(r)C<_jMtI1Ij^sRaeOqB~GH)>LB+7+>X={kFU6!3|SuGiJ zcY!M3{|I^*J0KWboR~=X;z4nhzL~hyiz}&t?*_@3oVW^yTC%64GD)Z;X4JCjHgO4-Kd6!lhi@Xc+hSwLfZ8%DD4MTZmr4@Lj4|B zX}`X#vA7A++?!q1f4;2Gu6!zocfaza@>gVoy(4%q4IL)TSJNPA&su*TBXO}6&;b(D zJi*ttU-0kDDsi5%4FR#Ue_1?}O^CC+H_AGn5tiskp|ke|$U#nB&nb5ktFGx-`PM|4bnjK3SC0FweXrBKa~mBMe(^W=q~E<0t}n{Y zcKEQVpBhvCC$ShHvo9~_As`JL2E_l`ZY*9V7FOJ*J~w9L6`?de^g!B6@-ewiD>%4jx_ z2XH3rlWlT9cm%KBRn*&O7_cCqH}qCZEu&Q5KH9J8)t8~J;ls`97$rA(IC>L0n${-K z9yLlnX@v$=>}$N~@f7+iTic!HU>;;O2TXZ7g{KU!c=id6$v0QmseVl-(k5Q6w-xX*y=2?GwR8GwB$f*o)I@ zerG^f6z7l;wypM2EL0<`luqTs&7kSh!b(C8KY(Fks92rU9T{Z1ia${0@{MIwmO98} zcmbO~OtJ{sLcqj%&Xy+}l+29a^Jerq)BwJT(~}+mV+xhbTiH)pe%|(k{l9QxMTCr1 ztR>yO@Dc-}lmwkwYbAmW(mXy6;FdH*I-UG6fzjtBqbuXI)J=zt5ZMLTtOYQqN-n%1DQV%^fN@~Fv^!7lfh`BW*nq>hpu&K$&+9Q1HxocFIgPq(GTsyiv(v zV>izqb*a72$Oz4k*$OI?8VQY54=pHBfFfxPvi~@qhUlx-8mP-0)pkx%l+;OxrYY)- z%65*#y&%y~ZiPU;22Z<{3qce_H}%rfIR6B+Xw7yIv%Mp6G{0}*Tvqv8r*SF>RI@C7 zdCbgPIC@tZtd$*?S`8i%iq^ig9W*b3_ z7uM|2nf1JS!3li+jcI#cQY0$_kK`edzq^k(-Hn*rSledi%;&hkW`Ao|fg(g^Cd3Jq z9vZ1_y&*p``RQn)jRp!xmC#g(0 zFKP}Qu>$J|ZvQMdlJ7;zgLBkOqw~u$<(%!FzuuSJEx!N0)vlQ&kmj(NM^y~Z@kC#j z2t*Y-JkF;T)*Ei&JN^^cBZ6iIoH6>%dFDKJYg|eDo@%Q~n3EDrq{PB9XQ8b;UFg#x zs|+64eGw`QU1wrh$9Ih0Gfgq6?lI<@jb3DkKpvy_gpM`7LGBIrzaTqf7&gpzGMn?J zs_0t9Nz~fNIXB~CcyN;Ny^pWE7pW381()unv(ki@uX)z83-yfJ0t5mi(PB~5=OJa) z!!MM?(gzr{${9YXk|@gbE*OW*YmNe9t4@+q(@bCBHxV_#Q({t?Pa_6qmtWNTrGR z?St{8Cy}m>EDbYi{h~Ey)OWMB;N`+iVE7@cN-c6xppyItj3`KOPhF2>R$8}>*R@+$ za}$^NJ7zo2BO9gV-+Pc?sgU#73}b!28F*l)R_H)-{N-HWL% zxcKl_ew54ykBqWfKdAEo1d|W{BunM%G;7EwmXn#%Y#EY5A_dEs zE`6_xwoLTLJB{Zkbg0h`Aim?B6h~7m%)*2M-YV+%Ib&mL6rsit`ge^CiOkm-U1^Qt zXFQ>C@B>~)E9yB}%e+aR)%Qw=DgI@jvx`>{0--N$GhRex#XJeyEq_8o4S5=Fb*4W! zv`mJNqO36Q3lh9Ni9z3Q0qH*SBaz*bZDSrNIo=Ia_fk>P4#Q-NJq1yfoaw!*;Vg}&b|^4{Au%;o(wV58iM^=Y!VH)qh<6Ov4SCdDet^ZByF4lJ>&$oJYtUDb}}PK`j}R zvGSJj2k~+H()K)anboROD@Sl_c9L2^ogWcfw~T*p5prUQJs(!K-cE^d8mh=2vQ{r~ zXl#}(6>y)UgiF9z&(ROP2f$vFE;V1Jx+yg$rO4N>aqvm9HYoF!eI-luIOyB5nJ_ca0N5mZYD- z2mOpmoNtG91!h0*bS4;P%+$n$nrVsUeQ<4zKFuFPK2COcK|o~Z?Ck8uyiNzgFXO9L z@sSb~2AGN%u)GdBWErB&qU9lnq;xq{Tb$@|(0(o>XPUDSXf4xEee9>=$OxaccO9rj z$rRT1f``?+Jy1ul1Q{(H&I?PrFZ~Y%;gOhKthSLkH~72ym!h0L1gC^RH!P0Q6(7)Y2aV z!=!tTEY;k_%ZIJ-&9)4nZ~Hr-CECO@WNw|(V0KrQ>7?kKPL}4}jpjvLwGzJ^cRDBK z!uLeOO&{}{r+52-iyKn;yp6@frz_rKd-#>D(PgeKY%zAOd2gxhy#wYwe~#!nw(2TP z_pO$;rfE;;Ei;9Rg-@fu;yja(WYDjCR;>s3z-*-6G4Jj}uxcNs=BC99BV!;9NYnPxjbrb`TUTw&)t~UNEHIC*`c!jZ{5^u^NjY1U>t3cz zt-*Wtie*S_*M_mi8BKkwCR-&dEQ}p@K8g9D2zGaScv6k?F*44B#MygA^jKpifSq7~Lu+C+6`Z&;k9eXRdrm>i z!Kkp|*NkRjL^Vh-$(YZ#r<2-+*YjKQX9eK#DX@&2igdZ+tU<+F6BC)^+bCFl7`Rxq zpGY}e&2qx!=^S6KKd;L-6d{_6RGX7%4<@|&byxD9Y*fsfhoiErzzbzs{gsK0lX!ZL zT~3#tjmMFxayZr}OH6QK=6fiv*VD1*4t4dnUjAwO?d>yNGhXlSO)`r&m@W;{D2w_i zZZ+IKh)A93`yZgl%jG$ypSv;VMuV5eI)UNQmCWmPqaz>3*G1Y_`+Jtu${**wc7G%G zYz4+e{7uo4#;i$7(CzFIpGdBS6WzzI>;=9Qn?9mfs>3tFWXwsZ3zo`1{rqEmXMCGg$f!vxR1>cqS>=JXNVJxuk$c}H~Z z8ebQG=#ZrD0khu4h1)O;^Dkua>-y-tB4bJ>@ZKt#gZ?6RP{#k*_|f0!JwYKfVJ)Hc zPnhsR-cV`w3CpKW3(%W`V~IMt&z)g6j;#ahVFJw=Qw)Q?pCg_nqVFg`OJdu81aEet z)zRpT4Tt1xQht%yR!$ykL`>|EsNQ#T`H>8!04K_tta$4!%8O|>VrVC~FJX*}WPoe& zfX@2)4kwXOfQ$bsVB?b3^`RH8mYC3$ilgWTWstvKMaR2CylRIUiU+w>-sED(bo$u@ zB%2?FpL6?A`tkfQ90@a{PwA5p!3sG@W)4(g+$geeKync>(}hsg1!B;%G#xt5d}xm zZ%PW^Me(JWEyoRmNnURF)EG?WJE^N(Y&x$ieR4`&P|r$AN@z$ zpO9_E&q3*O|^?sIStf7ok|4@3dp)I9EJ1yPBDhgE?6=FlfHJQj52xN@i zy<^C!?}UlyagG+eR3VnfB}WY)I<51IQ^Mfd$218u)fRfkHBG(FHPm<{vWPxNu1bJ( z`cEgvD*VK%sFXc!rfNe;^C^s0*LfNpb=zu!i(uWe&9u#Z_y+qdD+BAeHz9gVklD3Z z{x!Vw@7GaPHzIeeEGl`1K`pzBAmohT&Kg$KuO1U_D1=s7d#A$8vU}76Y}C$)S&FZ- zq@w4iGN&98HD!L=tD1<>%YmDUCJi1WZ9Vsp<3g07d=#b}N)WQenS_PB%&<;Y{ckMkIVI( zFgx&ebFiAC-`O8C8bA!%^Q~w$k$-?+Q_rbLc{ko8MOUTt-gl{pngs8L^JsI8qx?}b zIg4egY|`|DC9a!Uy;+)0?f4H`2|Y&Bi^VmC5xgQwkW&BpPz?P*v-Bl}({99Dx-^|X3B9eE zclh=l9=-24`b&7dnnvRd1+#zy1lsM-$qF84QQ2M$NOMmB5eABgEI4HawVv;z+{ufa ze!dz0lzbqRlITs4|K3%T(80uN!Ft3kzw7$pTDN+o&ODB9kgLZpp$g9D6-SMm!~{%& z#Seyl5r6Mx8}#;{$xo@X?33sjW)hKB9~7b5&(x~(QDq{QkxC^-k7Lb~M^J9s$Bs0& z$TW08$>^E)w^P!|L{<8Ba#J5MdQ&Big`Hk-64wqNuV73^zE&b$slfQEL{2@o+S#P@ zADOGkDfj$&qe}XM4F^@>J(;XVRr-bQkbt+0CjJ>h5~#vBcAt0pthA@^Gxvvizy~S# z5&HD$_PhU&sjm)eGVH$}W55Pu3`PtXIC`X`TShvN?o;C(W=RVKpe9k#{X8Dx5xp=v8O(OTWIfVpNFafRh zf))~$;@NW}0A)iC}zUyEJPz@K}mmRiQ?ctS0xs zn5Hr7eloxJQ&$0Z5B)KRZH%e8A)lOf70nGj-G<}||D3)cvd|`|{Z8WCZ?!!7WGhy6 zkaTKRSCH~i28$wzlvVNMwWCJw_DLmyQ0a1;3ftSJl9_QkM%g0BS>PpejNUNGqAJ<^ ziFdy3QQ~E@G^}0S5=T^^&!TeK*eiSdKP1}La?^NI*Yk`#AR%gW8DI0XHaxIVu% z-EKmXrkyJQm)r^%h1$Cs6L0vd4Ea!29yuNcn= z#D}oSoILp=g?k-7MV7aa%Q8dW{j&num&cLo83JAY^e_u>QP?&eEN!GUN>$;LPj2#; z1{cax&8DZl*l?rDEn^MAN~Kuj0%Gfl7TN2~f&4Qul=94#vJl@CSCf4~TG0t9AH#Q3 za}LgZ(`$|C-*_24%FACcb(A?qgd1hQ*iW6&(Is_Fmf>DvAjk^h-AU)(IHBH##5A>n zTSY^^_gF&L*Z26fKxyx2sr?6*?sQZdNplz|hUVM)PTCe$|JE+6eh@uTGtqws)WEmw z>)+Av-7M)F<}g?At%i(>V^ZmT<=38q57Ezw#l6vbqpM=pS*k3bRrC?^sh1dEtP0NY z&p^s#9O|^#Cw`3=tSPMsyS#`E`(!wob{TqC&kf zU%B3S3iauHX=RzzSa9eCwKYbV& zQuf@|K5jaYWWlZOMu$i`pTE2aJ%27!C?s}#shjHs695|^-eFJ9g&O)AbD@NTy;VB+ zERhz9lquD_!my63Wkg7FabkoTvq=8;kE6`2w9qVJ9==In; zvqs*jw10>->NuQg^sBJPH=E8qi+lU$mx*isSA#x|pfUS2WgV`kQA5%1C!8IaG7XQC^o+<>QDXO-zYG!7-8&H& zdG^J+bR9@>J!7Ot_hDj!*3+; zX`Wt}d*kK+x!oScr(pfs#=5+>GWGk9H-+r$C6yeO2alAygs%2oIbO>VmvcF_<~R&w zyq-^U7a?H)IhKAYXBy0_;GREynOxu{Eu3P(y&C&4-ZS=EhmajwfJMsFG zcdx4}f?oS{j?T{O>)9$Si%LJbU6vf#*T7euc*n}vh02jFH(!!vqOWwdd`^o>ulSu$ zq^rZeM4UhBU6^a!-Nbc~kjhy)J(gQ>z6@0p96YNj%4PW@b#;WNu)ar+)ALMXjF_aS zv$e1T-goSnoCSE-Y*Ohx^J8>VyetANL|)FKtIm^QiClcX7V}wLZwG9=gA+^N(9Y(x zf4TpvoEUSnKjCOnU?Ic9w2sTS#(V9@7A~TnCBf92m>R51mkGF7$aO<^dTk!>q z+k%pFf|z~scO!PVff3o-wS%0`Jq))*On2!a?|;^d4%bqal>R`wpIKIucp9VGDs(jq zk~RyxQT{Z0uU=>4x~cg!2Q|Y>f_0HvSYsEZZa=0R zAa~1FL_;9P?JO3Shp08gxqY$C7;YU&wilR3wq6&k&m@BljCB#;%5H@#Q6UslL%&vo zpBKx8XLeHAbPkK|kun6?5xu~K{}OsU7qn>p{|G%EDiR+dxt+e9RYKJbBB6bMBZ+1Q zXiU{MGW}s8;!(-zWg;+k;s+Mr$a0RnsTCa$z_v^B1>;C55>TN{QZI3!ghL6L&Dtgy zYF2i)0|y&rpntLshG+QAUC26c=E8t`1XHMlDH40^eoUX<_e)=}R#;ucxDem}Lpz9b z<&hT_9T7Ig0+|Iz0B;c=PXCuKq^45&2*6zkO!P^Lls+_7uSX@QmX-8AWb$&M z;L*4dPA2HyvjQtp3c@9TI*JaE<5El&0}uhU_mUT>uyj!|zj5GnI1*(`Ws?LV(xQQ+ z|IQfyh19z1e?&4r1PFG&v0-<~prix~{P!6Xgyny|>8PCeFs}9qWFY)PO7of$Sly2! zf;4baSn22#lsgu^M9r$3hkSVXoBji$AU|ru$hRDeVh#Y*@I21TMLIv)|M3GvvH*5- z_sJr9SSqJ|c8Bv4m2WzEz6)eSco9Uggl(X+ z72C{B#qgOX<8b+y4M;WQ_e+=vh55SZ3X8PvW{5(O0tZF>SWjBd-zEIHf-ED^8ivGj zW!Ie=a&ysc9&~Bp0~JKkED792L;d9UXswg5!0v|K?cbY$cPe5zNd5@Fq2(3nI*|tv zd;<5nxVNP4Ol5tk(c7^%HGPDeijP)K}{VH-O#yrc#ykC(GAD82&jcPaFd;+#bvR zP{a{i*$)jE8onEOn@3tljIJ;p|6={@ObvCotu6yy=%-(Xm=R%MCKm1 zok!o^_>CR-`ke&J7}^-xX`-6;MAGzMIv69=Vm(+m2RJFBCO;B;*82sqYxdHKf z#sV(=rYe?=tZOLFHM554()!POD7>dweF;@0`h%? zFf21|VxH90?$x36VrVErIPToZRT!`P;;W&|tvrvw>*y)BFWL zOd$J5N1I0j^uI4k)fawto8k<=Ml?MVC-U~c)8?fLaxY1J&OPy2l%BVS^l;nT;)h{<~qB|5g)+Va$r?6 zO+$`a?XoCYgc4ivR-5LrtPpVc4x<<5TIqJPDz+Bvu;e}i+1&M_#MqkJgGY@J& zn@zR^C08ZEb9ix#yI5k=0LuToU`ixcO1srsO3dZ$JxA?ai4?eVc8?PVQEII=MaYiYA>I_`UT9_f^<%dTdR>7K&Ef`Ld)Jr^@-14_==9c$+gI$ z=458(a=j(IA;0m5Q?oRIx1iE1{kQA5G-LW!_@2~EdVa=Xpj_Y;v04%fyIjk?u&a!>=m4qpea2j&sW|SQR zb!42VU0*1=@UNnJJo8e8gw*BNueAb77(WJgaPsoeH<{T@OH%=7dn`pS)^3-9^y9+PeN-rt!J~)pM+Q4_9)EMLkgH6|Mj%{*p0RyOThnhPgk`fGH;8hAZ`=iJc56Kw z8tCTAv8_Q_g84T>_WJW1?NAm;vkncc`H6Mf>U?V4sm@uuJyNYY$dxR>LEN_6x*>7=gvmmC*N$WYy{_)YS*ucs( z!g;yHxS!D=u(-Jb(`|(9f@>J0QC{eHrd?o#FV%N$&(PQO zCG*WO`&4L*MD=+em@8|Mra!(M#c_|c3v&wR*I7D_T&>S z62P&M0%V8ra^MiFq+1BT@D=m(8>kyHS3H5|kXnAp7Yv)Y7kg_r_`oJpbrd0{VMU}a zS5QA9vVRxeb4FrYTr`F(3xoQ@{l_^5z)J*LGOOxqt?qB&c2{Y&_t#V1tHzG9eOMQD zfrMp`um8wafOAL;QU)ln@Sx7IvH_t;B1d&$Xv#S%rXEUgDA-=3A}0*3>j;)?9x2Bum)1Ul1|G~0yXi3#e zHic55yXXs-A&_QaP;?X#0DuD|Bzn8&(WW%b6VI-Stb@B}m8%?-X>_=-K6-(27k_X& zXyI``PBG>}&Q;%HeovriYKYL}gj0S&XXG(CFSWV=G+9yX<&$KtNjMVNACcjxxo9#;9AWVd>%8)P~~-ng}6+m@vBc)%0ah zx33WiRyXh{uRK?5NN!QpZ(rs?i3#O$z=(#?+ zJYc#cqU+yXm3)_V(r=XZ%k>?zH3t#ry7o3z$ibr#@5(T&t)uv%@ z!1?LG(g2*0mYb*3r$B#%p&E~A*Gh&8R@F2VUS0~5Dtx@x{qCqY0Bk$NK7aBV5e0Sl zHi@u7%_^)uE)L5^NIBS}jX}$tlbE_3i3DSrsO}Tv4k-A-FBmH~>D1`~#g0nDI*$Ve zurpvUPIlxL35Tcy(Or&uW@+n%)Dr7!cUHQq?!s_Z$u)&Pxf0^&f=r#1Z;$@XGR>z3 zpnFgiWg8{F|5zM85bfB%NOw!6=*mIs{R8P@-jY`#RE^71U9L_Ex<5WG7hF4QP!oRN zkrfYdQ>GQUxLP)%Y)spQEX|}#4F(W~QldebTBXxiAy?Bv@sXpVrFEmYxC?UyEZN0! zC2_LnM${D~V{&2>SQ=uwvP2Z)8{~i->qkMAdD*XvJ8pkPEjv6>*wPnMZL*E1;$r?K z-F#TC+Ogk@3$c=v*qcx8k4V0Nd}&WW5R#g` z8?QI|2RswYA&_NNZLQa(P&Z`fvfI) zXSS2o>uKso#iym@1>)x2w{cuS%A?xht{uXk>r~ZWjD&%*cZJp4U00bQV6cH|YIEb$ zh4*~-ioRg>_~j8PwJ$|J44n|JQ+coS-xU^~<9UB{N4qI2xM*cV;F2#bku-LP>`eb| zW?b3$`PV5r`>lbjDgpc=K=+Y^>=Q2CDt^q;*zH=b$PezT!6-e7$qe%ZU~r4Pa)gOu z7(cKH_c7W8ldD$slsmFkF49<`;lpqBG$Uiamwzwxrr6{<&%zjn3@&KuEoeX!k6Fs!lsnDt zi|9mioPRdG*pqB>pmnYDMcg zt2!b(_&fw|M2l5~Xsh6YhO`X0N|&@J?XSPKE=G@#+r`*@D2jW>AVp`_n9f@p{gMmHJB` zrlOo3KEeBekR?J|2D0guAEB^z9eK;6zUS7U0o52z$j#Bc+fjP(v$i4_;RQlQ1-m-< z_6~UHRaK=g^HD^$Cl$-NV`yVc`>=EK+pg*Tkuiea;uPvd=X7{goWBXVT+1I!`^VH2 znHZ(m83MOSOP)uOke8UBt+Ya$l26DMuvt#lX)a|;%`l8Qff^9 zC2E$Ier2%WFgG8Gx22ojm^oAPO-=!qm!J93Sb zSV;N7txUr1tPPJVkGPKKx`l(qP+ANX?_6L?a&@eU`-uney+26@`@dX+f46H#;)C%Q zi5r9;Y3~)+Un)i3rzNALmylo1pRs-Sd>%}j6_!)>usjtz{(_n@FIR4cFL6kxeTM%& zLjr$u%rkXU!+u1%CHqxwDORIM%Fd8Y?XiMzjE)`NWL#YNqhcrm_h-}hyIY&-o zd_5r*M4ObpR7NmsU>$I7=Yt6JslgVqv()Oo8^q9WksbX7*gc+TNoe+;=z#Bqlv>4w z7kd>#5l&W z`?9ky>qg4PeWhZ4U)-B`0rsCCRwfDGiqmh9wecszm!KNs#TOo`Q$t_aDT?Ni8Gz$1 z(1AYw+fL34I1ZTnUx0P>qFRa8_&@o<)e8}au6*_{FeWEz?R6xBydr&B5*}{V-Xgh! z9TrnSBgD+Cx9zZP5k!ghW>Dw5%=ye^nF+9`*fn!YAYUtnNDrW4)708iLTY$|u3q3X zs@^jHtY81OqD)y!W5hIdsy=kA0D*j346Fb*j3xVM#+{qa@iL%(t(uyHNyNNql&)18 zVxE#~7~d(LOC^;XcFzbuSyLmCx&rac8Oh++HRW#?ugT!ofdVdAGNmM!{YxVmIwQAF zeXl*{KeWXjs*wp`z91c3GV2I49`Mfb3^EfE!oRCSK`ney3Ic*`|}o!~b04{3$a_4H1~~-?_EE&|Pc(Z*D16 zK!&%vwbFN{=^%5-bQ&+f%Ta8vkB1V|?gGxAG!l9NAb?BSrYRr|n-NbG5et|hCt;Dn z)>NecFte}2U_#`-C}zGR7{_s0>{}ug5hC$Yck~7R6lcyZy8enAbeuW${sYhR5S{dC zhlBFle1xpq*E%~SpWH)Ea--)g2g*CnX7i)vY&V!It|!U_Dj@jT&Yh`J1q3L3P=T*@ zG58(^$VtW6#+R@e=m2wLt!%FiX_DynkylTAa{D-T`mTmAH)0-tcp)lC)DIH9B3)zz z>qTkubizbUS+bvZ8-I=|=06kX>6iM3(0?1(2w3ykX#^P9yP1YNJ?$KL@34MXgjuzq3rXP!iukq3&%09i7V7qMOTtod5z!*L8TX$D?QHhKU50b32 zMLm>9xRhREwW#$%AsE!Sk#Xd0Gq~U_RZt7l4Qq)X)t!L<)1N2G0swJ<1Yio~;`BiO z|7Feui}?2$uZVO-jR?dm5n!7rt7+mwv%qS5ymGwjy%uJORi^XCc)xPH8_{shrI5!m-Y|=cGyNwhRFtnM8%KzAL@28oIThCy))u-t*^83d(zjfyPQ2^da23p9}gt(*-As{VZce zwK?wgGF`{zdqHp5s~UDCz=)Tj-U(>t;sowNL7=9ryFo&X^DQal*mL8c@@0g)JRj*+ z`HD{iw{h}%$UlqSdpzKWsq7t1?qVN>k8KoZ;bHbMskGzpvX}=1Y2W32y3NMKuzQO) zFn>!KD6LTh8s+>W{(S^K!7IXcf!vU%g$8qu!RE3pemwvvh~iRrJRXL|@oS!D(u zhLs8MHEZc($EFx^)W+y;{)Ktwm6;I6qk9ZGuDM13n9gNrH}fdJ;;&RAog1$p6Z1+4 zasgQeiPKxb+X4!5Tfy^@%g-+7$2e-lEq{+o`#jU@#;vZ|VigFI$0)|jXM6>%an{Bu zmJ5n;Z_6k=mufCMXMGc>`XGGB5Pn@dS0V!~uDCqfZKV1lnsltjxp~`aSoqvF{+4c; z)6W#A@PtcYa-T*IxKZE9m6S87nfdoamRY#ydi+BptLA?n=-GZ)kV+%GOG{DDC?V%6 zb?;yy#UxCEo6feSUL;T3pMS;K!*-l1fSZr&Z+(~b$vpKym`>1OSb4&3kgMm%xx@nX zuetEQ6`-b5Y;u>{q-FbZk0Nj=;o64Scp!I_9>0}l8MwG2KZ3O4nveUH*b$-FEPEC& zV5FgyzOqa|34CTHhYWZh!(Vh=B!HJY)05pnY`C(=iqzo{XoRF{{s>#HWemIsEpfSz zVu`_zoVk2{g17OD2X_2Wo|sE;$V#AfP`W$uPjj)STT=FVcn}`UyONd9uef71h~T z0(VUgDN^cro4y039fQ!G?2?L9<}&tXO8O|WCwzpHL3TyevRU5Eahum4+cHs;GyXc{ zCw^BPw~O4ZXn%klOJ1v~67NqPs_W7$-3ZRafo(^x_t0LxDaO41?UJR4M@|D59TTU_ z0j(cFHIn(E(3Ljv1j+mZLiRKJp$9yxJC>hC#6!b@daz)UojM?s@lyOIO4?=9Gvt`W zcg0c3HMcbkC4K7u_afA`)%8$9aI|aym6-UZSh0c;X>@Qsqj$|>V6o!$>#JW~*dKZX zLWjD<8^wn%YRn{)uh`62VFAC-Y>bb@y0$O&B-myCF}?OrsRYAacoX+%buI@+~*VrNlov6t0)==AreK^RAH+h__|vj!8tQPQ;1~r6i+MhE%rH z7Z?92-gFP{z5zL#e9RvRnGdA7!8h4={}4OWe=nr+$L@+YwNyN2i>e{9Nsfa;7twVS z(*As4eY1`wn)l^}@4cIlO4(+A(*R}HfpI5B z(wdEp^-%z=uG9eko)8J2oOpLZwLU=vSE^RZx4ofo$CR6DiU-gDe1nS_@>8IiH*eA8 z9m@HlDUAyqG^anPhmfMbu9;3q3hCXFWQ5-VXDA^UbrxkqOs?+yrDGR5l4M-mMIrY!{a9dFv~m?9O9Nc;hQFu#Vh6Lgeg6nLZ#HS8`No!(R85 zmJsIw%~GP|=b#VTfglGNYdN+$EY#qPL}%d=Q8ddhXB{E})x=b6Q6*{)faSEzw<3(P zKO#qN#M6ZSXk4PTlNkIS&^5-GAlx@VWvqfLLHAKOWEoXVRT#R9($_bBh-JKZ9=pvI zYZjHjjz6aqntp#1TF^Iuq-l9OmF%UU59v*R9N7*8d&=v3byr-F-TV`MdZRamR6s8*sJcAiSL^* z-L(eapWN+6^)%<3wtqWDa7K(m!zxJacqO9cuj(%G!W7-&YiX%QI2tXM;P>)L1F2pk ziW5eG#lk!7Ch=@;`vHs-@Qp-;70`rEh+Z8L=bDw^f_7!b2@g*KIcb*?@-xjYzf+;Cf6v z&Ku`VcAM*xib>ch@C4&s^A+LbnjeYpA3;tWRYn!^Vh;p>16CDZJiR&S3OIfaQni>> zDv|vza#Ti=j#Lv9fJ$*6{j!yE~Xnck9Z#xFV=24h9#>mmo_B}$KA~Y;b ze$7yu_FXU!1x)=f8g073DlY#;qx^uT3#4z_^nM33RvP4$ zc9!(n(t%^P0S>eEpV%J9#Tw5y&ktJViWY~AT$AXIG{3I%TBtK;5w3{_NfeUmulCWK z;~I!bQUDqhAmG=Ze~C)`Q62=iWhq%FF4MuDhE-(A6qF5+e3~UHF&K^$d9@T5>a!5~ z7AHk@E~t{sjFUZTisJ8@PjyO&MeOTlWYrux8_kmh??E!8G1!XOx84-2GsTqq%FX3YW~6Yst?EVChl-$))ue%4sB3=iSgoldTZ#m-)ieF^Vt*Jeu*hjQzn zY}OfOW0$7xE8kq~+dQ87Yn$*S_RKQlj$Bzv&giCV*>=&WwM5A5$i|qJ@d>F%S zpA59bX5K1>5&pNKk)Rn%abjc777iFJ#OUg=Nimd$B(jP%{G!Fg7@Sg;`$CcJhUTWl z*k_udw$z&uN7simqrih(kWwE6+E7G@vhjyS6oH81k8-3E_|GbWeV74&Y83#$ zhZ)1KnD}>A;cemGsMYY{PBH$)y)Pxb;~1=ily2Xnu?{%>^uXz*7)Q5-N+0gGC=_ed zDs|b_wYWozk7`Jrf#A}?NCoT~?N?|(=3ZiU{9SSyEc~XENLms~8@Z#$4?#|;+wf|o zWA7T3Uj8`k7}`7idCtW%5K(5-k-Vb+)}*D0SH+On)n|Ht(Yjt$8A05FMxl^pmng#z zCf1Uw)k|$t9V5o3`&uu>KXIkENbqKABt8iQSsWUnb@W5#6KdX_B50!u=d&?;LFVj= zotgWujItcP=K(U8-aKagjAZLihyXy?nSj&fTDWY~lj>R9s^7h(+v+-AJq0JdQE6_3 zu_RhFz!V3QObb#fk3yqadSOyj_(OPRpMXnGJVpVqNC`i8&HVZ%P%QJ9HV0RwEI~ZO ztMBW$Z1v<=s_s~r9Qb@KjZ1!oBY-F>wdK0-YxRDf>lX%@IrhP9SfE`au|dZZXDb~N z`bXlcrIf_NB;KzyO1vg6`=G-EMk4~gB3S*4lYI7C!T^Ud0$I^nLd{;g)j)W*_y&lq zJ$9%JTgf;y9gs*7p=S0x_jIZb`M{Xr9L(tywC_N#(kynS+Y9 z6~RcuqpOKxZ9l^LYuY#Fz+FuB*9v-~@8B!T-(;S#`e0o2;lZBqeY9w^Xg!PdqxYFW z*rg}c&XX+YcPtBn9C^TZv0BJLaAqUYBOv}Y55qhMj6oV8-I&84ah8d~S4cOvVHH@# zK7cq!0<_b8-ecd9c{jD-pGIbuKnVVq%=YU^sD z>{E9Ic-ey-Hz-L-s3m8i*eP*&*Tl-c^UTdFyvBN3mz30P`C4inl#~$VX{H)04*AHg z1wvQG5!Cuea2U)wZpkcNKdq96$3QagKcm))1}WOCA;Fw7?WGhjYjo)+x>2zFx)YgMcWtHn@a_-mKoKKAJ&E9((CD1TB*aBngZBg3(n-=G( zbiX7Xq#Estr*p6KZHT?EW9HqLm55Yw_$LSVvC~D z7>I$@dQv!>x*TUp6U5I}maxd6dDLpg<0w(F>e;MP(M=ns$}Y#xo}?y^h{xJ@|0ppK zZr4ojobXF6Oz8&6(b@@rfAIZ67JJEYax+)@s!b{w20e3V;;I?vN!1JlB~B;5dl0ta zut7B=X$b%$iR2KBZRaA0`;$I!sBVz*!Lr(b9i-fqI03lX8smbay=ECp&1E7Joxt}m zAOGk#m?f#Jw$sUA8(*u<)Gl>1gO&pi99(kO9I4-^Xonpa9S(|V4R#qbJ#vpuH-^v1Gf2uI7OA zuGYE@Z)PhtC@%1U0x;_%PtYidnQP*?J2P+ryp)z=s6`o)PiQ`4+K);%kxjr*y7}7a!%9C zl5NTnru}p5uq-&ZY+c9og3Xn^Xv8S}zfs@jb--C0)N7^UTn(o zbAEsCYxH>Vmb_wkb(r&?yu+t7y#Oz==Z1;Or^#dSU%PY;AvZvAPZw)b0i%?u;-rF~ z-((?O+1lD!EU$#??)?nFFZ6=)KTzzq95(plWCE05HPMfVTw)H1>kSENK*q%|v#3?3+wo6WZ?7x^)d!oU?dcD41Y4ef1#JL1~3hiM6bkv$4eso+OFybgdzh>1N>c6B{u{jfY3I+wl>5QUKmPrx*5Z*?xHUp+HKrWI zE1X-?Kh<2d_L6I}GP44Hy%X8*x3)2pA!gUQb~Pz=6|Kp-kp33mQ|@+GR;DiBdr(kR z!V1i%G-i3plg27qNuV^w6T@#_a%0n(4T%p_N74^y+ru4I*@d(Wjybj+*+G{!Q6XAp z3^@RaahoKre+vNSBQ=OtOuMwL_fN~`mbdrT0Hy-Qy;n8UDoi*y6HZFKX?fe$Ss%&Q z-&$kFJ*Q?;PsPmmsFYQn65F0h;b6Dsx3CA=W z|7dOQoZWU}3ld{1OQe_`YEAGG1i+qI@eS}L!sz)-oTp0#qkU2GmyD=H4+TmwlP-s>_WN*^EQ@2nzIGc5 z%Vhd33C6>Gk1G19=q+lD70qz-I{Qm2UwL-f+1L&?s#r07Q}FZYiWiwYaB17)C)OPQ z(m;`65>LM!o2(WoJdzdl!Bx1F^d@~$3j=oB%ZB~i2jH{9+2fc|67&gFvxN}N9ht%ZsFKUrC#^=(tmAo2#gd-%8XUve=rwxj-@#NhwJyr3 zo3s#2QJYj?pFrY+x1oM;u~ahudic;d2aPEjHAV!;@&oul^p5YG=7X4PyD}|=PeD|I zS-(XEik&bJ+Iq*k2Ge~Fs1G-pl#>Rbp)PAvqwc~1^`=h6FX(HjvfJ$TEC&u>pcARG zrrXlcrO_IXPH#Hi@t*E$2kJgWq8-vz1{b42e10tpU@i7#X|cR6L;kn#oKZlh(s8E= zz(sU%G$)xI%KyekKa6o&U-Y-e3kzZ3VPMYiLOoPm%gEY*KyN5ZkBxbunl|9Z@|cGh zcGpOuV&U+YfA69a!)l^4o@S}AG4wz(1^>5@Bdy^|4u)`jB9sG8m+Cg3=X<+1C*oJ3 zg5Urmg8j2Q?FSTxr39+w7v@)CF1jWLgjoP+2AF(hzf~pE!JO1Pu*!&wq^f<~c~Tw8 zbhi?~Q!Vsh)6uD$oZIda8vc%}tXKM+1Cn7pxk4u~ZPUnt@d(YIm2vcodW}b218S@6)@LSmSex$FXSuBWD~b0jDG28~g*tT(biqyfTi@2R)xOfPAU)JFRS2qyCG zifN8&YMB0$Qo39@cBs!=J2)Er2M6I`0)At~V=a1aQ9XIC19=jOR_HuXXMyvrQAOXx z@kaqORb3Vj%}beaQTjYhq0wH~#i?ZYS<$v{`J#It`%kw{f?2x5S?To{$dVQJwVex+ zj(XkFkuVdk)C^WjWi-@dR8wl#`Q#2S1Ln8vJR2&SW;KWUOr6LK7h{J<1>ntjG@YBE zH8`2n=wXa4Mrs0Mtq*&bH`SuaMNBy|iUx^_>kmY;lBvo~0aXBUD-}weN;1%y$x2Te zO>3VH5RCBxnAtR;K^FILv{WxM$Jth`iipy{>CIsPk%D>-GcH>K@U`z>1F*{2+fnz# zr-s2>n=av;QL5}x-t#_U13Qfnk5HmADpw&SWnCchgn*d(Y-kpbzzMagE!^-0&RLg^ z;!roDZGlu(EDdV&Xy;{S7NBP$6`if)QzhSv$6gy&l_SIrWpu&$cx0&-i1x<5TrM$B z^>)vTy)k$H&x97MkVYn|MTcWtF!3p%K|_9*;A#MN7T_bFIy*#>dAx!~;_cvr&SJfK zlBzkVA}wk0v6eV0t9$izc6~TJNz8QSU(}pWEVr8ZXt@o)(Zy~`*macsq#HnWJ?>Ly zu{e>=o_E@N z&?b?fxK0!3PK1qLno^ZabQKoTQxo{<`ZzY2E|Q1$!_{z;Bc;Oh#%qC$31$@wk1@Tv zGLNJCS9+-`ue##M_pqmMv@>T6;NCpLf{)nQ=~?kmTqPA;XsskE`dO&me9>#!uBNtm z`+iOasxjT1J{m}IaqgYOMEo~!Iv$|uMpd+jwx-jvSZUOV2hJ|CwKT$?PH4WGE!UN8 z%qtQoPCw4}I|2ZZ(;b43La5Y*uFLuSvjtqOJ7%PZVu$6Rj*5WWpP?Z*T2&7(0G%Fc zOAuwu5OHWnb>X%5zuL`(jfVbSG#S(Ab-iMLM9mB@y6kqv zlsHV$Y;AoJ=AOFt#SpV`O@I~%Q>4zbO_%gO-;ooFB5AUZKZDojA%0)O>Q$ZQPnxMl zBjc4moU@?#-@>UYuw})b8Z8*lQSl7RdZ@Cr(!xmkf{(yHEH%b4@DQRY!*y}tW zlx8e0`-}GB*+?RWDr#@rj2>eOS?9YGtgp+=Fq2qZ{PCiRx=Cxo-iqkzsH?8*0o!=Y z3)jL3v(NN~KG$v+($nTo0xvp2OE<;acTFeS#b$lH98u& z6=l`P6OPb0l0KUSAUfT#{hVbNx=zu=&-GIxn~>{=c%IFvlzyv`P3w3$+jTSK2kz3{qS}*(UHZ$p z{;9Bw(|_Oh?nCM>7+&{&4!*3!6@<&{kEV{^m=PqFpc8rHXotn(CGJ$X5>mg!gX?p- zp;oz|Gq5OJMr+A|V0F*MTO?>-YN$qU+s6 z$N;FG>08orIJdBk?_)4%+-XEHZWxl>ci*GOZG-9hppRS3*r)8$E?M>##N?v`0ix{) zElm`2X(hn<5Qng0j%q|(>=~!-wms)Z4nN{E)MT8A$Ys+^;N!>N>W5l6Rlm_`l!>)q z2yA{wHM^_wmc_~1w5>eOEc6`k*HN9SvZ_8Ozd^{JJR0KT+GM2Q(SRN+oISJK>{sT` zu3y=aZHOHxH?6MfI2_;I6bZn%vbUd;)hFlTOVPqCKK!PNRy;*J$l#102A>BPWamJ- z?8?WhreB)6e-;P2tylSG;=<79#CB@o!fR2tV?ftK(h1C=Xa?#)KR|Y*jx*C`Dr}fU z!!Lu|l;J_-NPTdhdPcN@BM$|MLs0@rH^U>Pd6|7&bf;r=X`t@#AC}`d+;+##<0W~$ zyqjt`HJ}dsrCBGh7=82rTJt4?_DxsD7&4lfn<99*AuGsI^P#3=xt=0mUHif5u7tsQ zz3hE+WY4LFp>%;?iJ3xH;YYy_j(G7_TsJIAm*uvUV$z#^CS#gIvAAvKrF~$!`F)$W zPsfv*IG?yUjxwxQ`}My1eLQ$#5%M~hPndIqc?ujdoi%42cRi)^!={Uoe)&AUFOm|S zxBIj-HnU`g;muyVWk8%z_)SZI{#G~BqD2rGe@D=2p%MhCht$zpvOCabj5 zox9Gd#D(SbH$euMdF*P%Y~^rt;eIT6@o~q%Qt41B^+}w>GYCtXGN>Vir6oOcA_>QG zgf&vUD@4GTHbN{`PSO!pk<{&ULJ@5g;ZCntZD&+) z+!Iu43SV8}0%1*F8(9Dne2)Y66x(TmS5AGJ;?3a8fA!*_3*=Z|z)Kk5#7GYodE*$3 zBCZS4Z%RJf|E2|#G`xu`*4V6yibFH#@WdU zVs{p~vK!fI<>Se!OAwSHupgF;A;i6zu1)+r&Sz4g=#-m=mn*6H!7G?a=;QpDz#JUz zpG$-aMIAUt-JhEQre?5S_0=b}5A@&WZqW z%v?p)Lv|5bEzlE*!VSw8dY_79C2V^mzPpn6T}!+tRpS-=|L_2jD)21|90-EYsux+i zp{ypbrPgc^??A-@2-d9xbO&Yx5f%!nIstQ`Y2Y%c#PEs~B5z^_SKV6l0Kk2r`KQkY zEBDR46gNz8Z66v1q+^IVLdaV1_4_p(Yt15vz+xFX@0|UrcOd4nQU-T?q|o{~t26FuvS6 zWW)dh9nBB{+XiqW1_I@fVA$MjR0204LF|S#T9R3j0`Q;)AR54iLIDWCkKkth7yA|j z#CRn5DF7vbPgTd}tqdwaH8RD@f#7Qed8h-q7B9MXkFocSr|Mx?#T(Hm2=+lQQWg;% zC75*9dg2!wRGO5h_kcZv2qy+;9!WMlvl;L!kBJ%>F{41OKp)8!sDO^>yyN_TgC&)H z((aPS#Mw30EGM|kZ3SF@ zO3=ZF(#2^)4?ealN+1Mw&k~@ZZ1C*Hn>28;8hodH;6tgk${`R&4n#_n1(-cugObRw zT)&~xXO0K{7Cq#P%uGDU)p9!3p^Z8l4zuj+u$wT96srK2vb6z4#E*M0j1a9nP;iCm zVyJ9#VYx5}DDGgp5X&JO&I3};%`xNY2F#12t!ylhVkne8cv}mW74Zx9rrpQA6ERu2 z1Fe{ikWg&r!;kQ?H)?F%>_0cs`!}X+E1#Lm6m)Rx<&-;81(kjfx4Mx)hcyQOC0TijU=8fg~9S!^%&%aC49I8pxeD4P!(BWBjG0dEL*u5ActJp!0+z z$njG%0umJEig4pY2@r08nhfzEkAXR&rn8?Env50&7s08+Eif)F7dsaEeKh0z<8XE!*IdiflT~L>=%Vb z-Hy#R&)o*z`OyP{j>!%@s+d`d``gZ*zVB#PBy&N=c zaxv>$_e1+nhmWCF0nqLnkL9rr@YRVs*b1#LJN-))69_pKl;Y20qn{Q#Xg>CBck$;S zXJVC5bUyO&ROb=UlPU>-MeT*ldS-}2qaHvKT~k92IYq*O+zZ6SAw^!4({W2{QbkZN zY(Wu|7XeM3f;+Mn8KALml}3x9&cy>FNJ1}&{T30ILc*_9B@9=vKuHW9?8>>amzvT7 zI8p&FFd=G?##RC`AVUEGIm@GTG%_MWlBEDBiS{a`9tCnG${pE&z=*&n_D(E9^ryy9 z;>Y~_WeeHNB^iMhJFFT^2Kfp*5Zdgn%}t6(%!vU9jAPj_^Fk%QB!r2fgijIXy#>&0 z#{wTh>kB?HWg-X{k{$%uN=ObbVet^O5V$VZ=VqR&LhIjThDSDD$*b-S_?Z6pfLbZl$d!|8b~wY*tZ5_UK7T{ zQIH4;!GWA^dmIaOBL&OvbG4&F3I&JREPVLyU1~1U_i8PIl{sHY(Mm@ zw5F+e!CBPotnx;X)=DlLwX`sqN})jsWs6pq`+Y9tKL%J(I=K?c_85Ob5E-c^5t2A! zDkRXdNMy$VFL|yddLqOkI4ccSgx0bG*G+krVJ~qg=U>r&sspu}3R2gKpwOPcOEZwf zw0elJP&k_oy^n7ms5^-OcszIr=Oe=d4eC~iCM8B!<$c_@hw&quiZdoekUX-WNl|3O zOBxrLs7cF$NQooJ(!uLJdP@cMarY}j3y<~yB3qEu5G>7?9g*C~ZdD7A(c`xHos8s!i*)rJX>*oRkzvG<4?7ABGAQ*Cv_ zbwfD~^ho+-aUdZD3kmW}jkG=J?yB0#ig+dQrH%9-cG-kUOdKme8L;j(;GsrXdoKlB z^|ieyEvWxh(FIEc)Dq>#6!*UlS-HH{tGccXCRK<9+gXQI%z)3N8q z>n0htsRC(xJH~{s@B{{i5S1(1y|Lh;brtkg*a+E!u+t#eYfPP0gtZl{nrK}ROpU5r zNNCQRJ3LqBX9a88$IC!30|E+V31~(Pz<%u5I17cc25>vN zI-&?B3~%f}0*(Lx000bs2LJ$sKL7v$0U-c?2LcfS%q{3yOUI)7Ua$-h01i%2A<5p- zK`oDx`XD9%01+{2l_G&qpaO}A1wgW*{lgZlpqd308coQuE zgSiqXcwTPH9N-C#4{G-YMfuo}Kn->P=e*3IJM3D3U2!?E%Hfo*1p>x+pgZhQ zWr+^QE3jeb*u{74Rh@Xj5s`r*hIz}HbfWBUj#hL#uVvoC2tkvbP#}q)KCz&C$Y<6R z@BDuC{-EEBvH4PnqwTq+AHs$nDzdp1zH1}9y17ECJife1;zy7|}d#!tn-^Qw`4GxBI8CCTFMTuqBBlE~3 zww1^XCqo_-7L9z<)=2^P22jkHI6q8Z@rl0 zNPROS=Pp{pK}M=#_LqZe4#>zdcRpTl%tQCbID{d7nfN?6{!34Xp!)gRt}OlIHz#WL zJmUfHlTOP=3x^){SE-*pZ1F7L zLy+^F_DGCLrUoeuNHIxnQ9}SCiKP-7RtweO7>Nwbwx&eFCy~H5b-DIRXjm%33%3MBC-u zK~{#a1VfH$v0M-o?OnYC%`|FiuKWP_Cc~DLffAsYf#3;Yj8!H>F^T|dW5OC$5;_D7 zJLm>0dxS#DE2xmrLmvEW%dT^DQRDg2s?Rlj_m%P-hW%bhcYLk(9CjvE`W0{SvU08e zj8#O+f_Ju#G5JYf>gaj#dqrYklVX7hXMQ#1VnY_ov|}FJLEoFz-#Z7iX!kCojpD;} zamOe-_XJ3M?FlOTON$R1XHAz!bfUwcO1?MiaaML#_OA8hy^Z(uqrXE9lvmMQw7Stn zVwdNV``(iV2@^-F;bdeY#WV2g(c?r(efJ&~`hh26$5c)TaV6)K_%z{+OorkZkd*4| zHH`*8CC0mq>CQoHo6YRw4#vtP1biDgXLrJzZ?e8nZ^#jq4zWZ;KvBl~=%OVD?5J2F zUK)fm&ex!vqC!_ZRrOJni}agY9H;eBs`Jo`0wo+RrWB6N>qXWnfIWm?}@##VcVHCo2v2`an@jmG%Uz8#Rk zzt;_Xx)K<*ULJ8MCy&oj4JJrEVNlDiGQ-?FJT2G2n@we+IdiVyn~Hk*(dBUoc!xM$ zX400~^bmta=bidg2nz|bet05;3csAnqTJ8Q2LU-eF?3b0od6$K1?sFEe>3aqJx z3UDZMK#(9ri%d+Zgz@M+$)&P>YC7M#=a+EtdF9X_oy=bA81l$z?9kdY$IA5z8{yZR zv&hb&C+T&IZ`am05LI_sLC}Pd+-t6xHxQMR8gzA$ey_BsHF-#wQ+tA|tF+%P{ki3> zugb^*U1^|{Hx2Gz&+7i>|5aPpS?$uZL=<&4Wo-nAp-a|A`!2!|BStb%O@pQjwwqPV zE(T%{(7>(31z#+$;Yqk?$$JfL__K-niu5Cv;Ue(0ct%@;5S#1kFuptCwXPbSaoKJq z+#P^dQNtcTJjnzit3*+_3Y{?0u8cG7xnim+D^TpD$0qH_pUk`A98e(hmRhO=GtVH0 z?*u|ych6T}s(+m`jE|_r7F+ZPi*86D0*?Ry000ci0001`KL7v$0U-d&0Ej6oI2J$g z075kG3M+BQh7bkPc8xU(eW71)UKsYlX;@gz8_N;(`#~vbY8*&s$hFf!?c379FJFoZ z(X<05cq~RFP6D=tZ0+NFb=-k_;FyYvVUSsZG+4#K1>Hv8RviuOgFK4Ztp-xc`p^60B~?9pxBq-N7whju790FaTP;GR0drg*o` zZYopZ-VY4xBmJGP`f#ym+@%Jz!V_Z9wb2qceNk{`&a|K z&@W$Nflyx`R;whZ$}*u&OLgD^m_)_4Icv$ zC-czr>Qhr<<>f&z0}v)-7eJzoScCPxWAjzjl0XtO&;b-sl@v^A3wFh9HgVb#Gj2*G z$`c{FB@C%cC{}ah2o5A>*F3(Jzp9jO`h1#UMU?6QV)K?HfN(N`Ic8{-1~9Au4|JC| z(f<`pg#vKe6b2jOp5o@W%VCrlAws_-CYM5s%@R=iIF^#Pl{$uRM3SW67stW*&h=+c zW}6ke7>l3EW)T}11l}i-a9Z^Jz?-A)-*ts=QlpRlXyqckP#u&8e$}N^e6aYHT0QgC zfT&t@y5dtlOx)2b2tn-|BGE+?*v^d8s=@$gryo#zX5$W9bP;v{9Oy4cY6EuFf z^Y^r@e-jIPs{3i$S13GOZ)`_8kKGKlEXySiEBGjTDUgifhy8kcBJ8iHa@FdRf>uk# zoQk(N1$HHUbZe~bzntkAFGGzdC_JR!RW*u1n2Dr*hcIg>d{I~kKP)C-o&r1&XV~?^ zY5U4JJ8Tt?y}4-vmoJKv_>(~baFk5Pa_K@*rd+0QgjB*4jP~{l-4lQvPJkH+8RePP zM?m#XLU$jE;~>vtteWQ6#XW?{-h`rRwaZ5?UltD>Nu<8yTD-q$e2P;e_9`8JA76^s zhCMl7YE&m4fR=iMQuMsJ)iJP{z%vt)CSxLZ0g$Hci7}6l+EGGOQJ2#tsUPdkhYVQd zU+nwNidsqwdHK8rez&Fb1kOEv^h$LKTjj_)(-#dgiF20YLU59DfucMTd*8p>yEnU5 z+I^zHmwI%XW=)nR%tBj3M4YxktF38fy}Z}KVaFGY)8!Q2DOlc zWxl05!@V_V9jjVaa)J!YXathk{U&)os`igRgpdVgk`j>-rzswRBtZ?U%Q_RSDMJ@^ z)9_WIU0=1jwM2)}2<1#lL>d)O2+uwwRY&<&@Ii2*PQ>R*5HgWOnF={CwJlUnU+U8m zl8lncl>m^LJ~YC(n+b$=9^K}u63JpIJ^ha~KcJvdXIpwaHZ9coF_NK0D=WoWBh1Wl zWQslBi-~URSS#3mk|c@Du|Uw0T>wT9Fe=0lNFqcT zOd24HJ{RFh${c6GiuVq)ylOibImpq+cu%G_r^}Dk&%Y0|^SgChwleZ(usK z4YJP0Zx1v0)DKEt_**YVPop^-!bo_v2dWnK4S0W0YJiGA{)_1FEu<2hVVq>VPyXue z-c(g@YA8!(j56gn7%9OXI}*wIAbs}Xk=f$JXgoFTgXptgn)72R*iK5?!1D!Br?cL%mJ=FgLrpxia2s3K)odC29A%~M6)R? zE=42h`l2We;(}F=!)|uRl5`|RrU1lSv%wdBDg2@eNuJtUKRoYhFGGe1 z>}53InmKZq12640b}zDHj&7_r)^P%|7MTe!m;hnU&RGJC9suSi7Jk#}#cP1lk!=Y< z7y?qm0sw*l00>gkRthgck{~TTywP7A6CuQINj^-w1&g+7AcZ8Z`{Z4&DGrb_G!~} zT<)sj zVJA(+tFDi?RsJpiTL;eooWc@Di78lQezXz9UIexcVW1&x7nugmPnkEAWeIa+vYFj! zCJ!$i^B?W!jx0LrPm9Ea+|eLWMJ)-XPG3+y-uCBm+}P!$MmU^pQ!u*k0NPlLOp?k(fi%CaRGdDVsNUZOP;z|i zJqec$+P3j_20(X?=TjvmLI;cq_=hkOW4~ta-NXLr`%nqf+O%eb;Asa-k(8y}rMqFa zW6_2NQFILDGQl67m(I>z$e^v%N#M>((9-|_l?G!pXWPt7N>|0p&Y_q_@tsCj27$o;8J_u}e|bA(Bww&4&i zz8r0vfX^^N6C|Y*gaZCT)%8;O+OZLBKoOw8Wtu3Id}SvL5rjC1yXN^r5%IMA2s^U=OiJ^Ge$Y-~2@ zYFO;{!*hk>MSQD5Q`><@>@ik%{qQ&c_eh1@2VtuE-~ztnmXkF^M5asu*%9IoG_~|- zKXAxnDS()uWGITTtR&0@06ZtPB&0#L+*tWT6Kq_r@Qd9DW%uM1_q-3qIiUO2m!zo{ zV9-j8;U_048XrOJ=FjcXTs-I3Qji2=Y2J7M0%alf;(+7Wpx&4GlnQBtiSQF`<-b_FOBWhq_{g#adKl0XQ| z{Q(sRd)5hIM2Fh-r^Z0aWO(B6dNF@aXgM#(>pfX-1iU|ya2&IhC?^oxtGP+-R0S`Yi%rYef ze`1Mw3)S>=TAud7EHtD~#hivn(KLJtqch+=h&^(vG0BP}d?#QoVI|zW<@7W7?^=q( z80b9GFZBWcfBf)ha72(0mxm@z05U@?<$*r~CVp?(qT8+SA5TaWQnHaGAabQCLq}HlqX{#W>cTA`D%QKR>sS`smoD29AQL$u z_O{uMJr5CFFZ*8O5af8`Mrh>fp6wjZJ_f%?%+nx|48+W(G!UaeAV?GOT)9Ecwe;0) zJ93AQ@fCtwEV8wg+Wu$fLVOx#Kwudu3O+JsA$%GG8ii;4 zJN`liU$cBP%&X5s;?9mw)7t%j`!yf9?yRtD#DPp@N>ph4T$WG3&sOof7V6lO=*oG5 z4|rYnv;PSDf@V{ONg4W5DJO(^@<)8_9z<^Vf1q&a#n|Fg7vlboO&a)FvBTBR=6o#) zOrQjj6mq7Niy3zYU?qrfNFdHcQ3Oyv6%pu>?DRLE96nx4C>3fAP_;wV0b^e1VKrFc zUNdN-eq^B7rIpo$nsoZ@%j}~;iN*jAnoRscs2qFgU3Z>IUe>4t-WLqQXv%^yDvVsdhWY2L*0x=y%1%jZwm4eL1 z+Yt4n#=IHatkVkLy{lWaxqZ8^Magr3_>1>tep9Q5uorUlw&C5)8A^nu^i7{@^cL0W zFn@{SaTmAv{jJ<@@bX~fy8$rSR8XRRC(p7}kU3FW3Wb=JT0p(%)pZXk|fNWnLZ%B*z2DAv47MyY}nirL>UrTIFXwIN)!qc zpNBL&aL)sj9$72^35zlH8}fU)=?tfbOzCL&g8z`SiXyzyMvvJV9zJH%kWHr`=sf&T z2@ebbqy*7{3Duy>{Las3+N537#ErRlHKL4$Tf3St2BYAVUTX^BYg}8l|5S(xWG|VL$CQ=|Jf)Gc*N^`mQ;}LYVZ|&ks zm)iz*?PhX82SQ=weui`1^KXJig>Mo;fp>w4!^&{c%MU!He%z+10WY=H$Bk^8S#4&m z#g*x9v}VkM{HS$!^%dWLS4Ue(u~$Mysm$@87Ujinh7jVoVn`&wUQ!5A`%b9wpQuBX z%mRrM5=L24omh}tGd{hC-2`yMDnlc3yNw9&t2~6zfgkBC3GxLK%#B^LgZ!u~yVaKB zF~wY`Fc#zpVajZ=bZ{b zg$8}FqU4}Y(C?Xk!uS7nS!3|1Afb+DGG>6lDAk~h?OVd?Eza~0gYW~z_dLaMt2xu; z$Z-Q9G+s(WO{2wQ3D*V6h^!Yhj%Yg)64F*G> zY4r!R{8JL)#Gjv+^HL&j$b%DG!dZV@3rk4Bgv{`6Iw5-2hpqma_LEfu-ndXl-P5(XBkvx zj#Uxya$Y7o(0LLOV?UvnLPAwzgggdBxkHmS>*^`myM`rGdG);&SUiZ(yT6HU@(tBu zG1nD#?#h{z2w^uTVhNN;28bQ3r8E#j>h_0rMnMdi1~lMD&uqVREHI>qx%tfrdvb%Y zJ%&A+Fr|m|%jccmv}!52_<(j_(7N783pVsvG7- zDq$jLctS7}N5vVo98Opb=%0)483ZRJq^y(36Q-d6NE<-fkkd`20odkC6E&S;cVaBi48Q2k(iQR zTkNG#$($p-fH!GTck}w}Vl8MW2A_uWO43+p5SH%P$chsvfzpq`=w@RzQWZGMtDLm^4J_PE!K`@lwl|Z|@f=%A875B8S0z<29WCS;Mgt zL>YtGNE?NMB!n}DNJ8RtNW;jWa;I1*Be=ZwR@wCaLPq5Wg`9r;$G20qLZNdqC{Z}* zoSFn0C&U#OKlL3s-wSXbM9Cs3PVlmf#UBGV|Ln?`1#T4SXv|)b@h9`a;eS6^HS>qE z#w%>Y9lk%nP?tX+;$Zfl_EruckGKI?6Q%+*Oz5J4l3r8L`;?EpgX~<7+?mFAtF3X+OgE-p#3fOa8%}3>W}FC=%g1SREf)&oe7#VoTWsEq2LPKbGsJY=#cs|ksk$s z`hL1dO-bw><-(wFh2AX=$1EB^RDB6xWD@^>1Y&Y+P@RjJL{J2pGm>1VlLo6Z-U{yt z{NtVcg0Rv8XyoWjpg}_`khU?wn+l z#GD4PnB@C+Aer(NZ)n@wI;1*>L5+;50gI5#3%igc0GTAv00d8oo@{L$W~|q{=Qr+l zE0{Q**;1&?=OG$~_%BsG@uO-1qjEIJ`eChhR%Q+bVNI z0Z1d_XQg3&`d*#fJ242dSQ$vXX$55~my5$y&RltFZH>L8i4cJxltia6mG+tMrN63w zmA}ixcHXvj%|?XWWtkBx(K;SK-bYT&Z1>1@XZ9ex!>$ZIZq59=k2g|@{@NJyDcJHz z$j}H0qvLjTsn94O^bnN$22$t>%17?{V4OvB#>gZ*mMIzmh^8omhcaQ5fclSl5#{j? z$<`|vSwzz_6d40IK#@RIu^ry za1@0BNzMZ^SxJAA&Q%}LYj%N4fV}4d84he~C@RZWuBzWNU*?#HQ;~G5*W?GLo_ZIv zqQVxsg4l=ZJhPdzh?s!(FKb}#(x0Ux;;;Ziz!Gx4f1@@oNZZusSdEtwGGHi-vT}w< zC7LK?{-b$r@}>253&#d6XC#gAu}myLnJc=+kCw5YC@S}(3z8= zMQ$b_pJ}W-ft?ZHJTvjF>4Q9Y0&(JZzPxdN2G{)_bR|bFQu&ZY6tWVku6I|!-#nqk z(Mu8}3!UM5XpmEl}$%pli=dflXDR){R&M-TBJ8G!Cgqy`YO+XU#z z{h-=zON~BO{w%LgVF%fj4*UAJV%8ntYkyumiU4nP3SQEVl08${bc-DBV9#tB z#19@0DtXm4E}iwO-kxS`01!x=g_533&>jHfiGmWr85feI1fbT?x~NvO=DCBvISWL< za9PSIWq_7af=9>6o^%ZI<(Koy96BKVS@;Hm5)zQ@0ZWjgmG=I5D?E~^|8fZ`U4L#c z`x9<7J4I@Q%z>R0OwZI0(x+;Spf1pj4I^K3+V5u#rkOwlO&L(|W$#MUuX`HSfp}fa zg8@X7gexS@+AebRZBO`{o~Z9K z(1|BJHUjgblStq&(C|EGrK@~x)v#IE%3!7Z)7)=_iRFXlNcTP0RgL@JMHkt%T3DFo10x0+<1$f;vQEVB%VGJ!iP{_J zqk&)HciC)Xu9>rmQiSA^KAD4rgY7%1+iYa)XCvvoV4m;1@!#Gi+(rtgF>XRiR+$DZF0iKc%~+h}yNapw!=Fnoi`B z?&m5}oV%9z2DskVrw+a9^RE|JfR`Ku05kv%^#$x|`TkdrVAiVJHn};lgt|Q*w1a)U zzh@}%(Lq{<5h0f4gAz~^G6Tc-Rl-1$NhF6!iTG?X(kNs}h;cB8IY$Ym#{L*y8T!y9 zSfTNLpsDuW`H6Ft)HT?xw$PS7!;*$q&XL6m;1+FUu-=PGOw*n-B65FeZMC^x^-(jp zZ;9bp^?(upMx03wD7AWqvGgUa1g2mzBh#CHH9@LBR7R+5;m{Wbu654=tJKS!ts?-- zE;&}~h9H(*THwTKI%gEJE>w>fA4LOwDBJ@Q*Y*|w4Hbx6H&x4(+e zmPq=3esJR~P^(DtVMoPacoLBvonyeX45{9&C3#CF@qIO963L&$@$z%vUztA?B(t4! z0vYX!L)AiyY-I7MUYwA?W!$3P?9vaXO9bU*rOJSx*f788KXXjQvH!(Fg znUe-$oPl2oy(vC)OMh)RUIS zGDwuXyTkgpYDcozmPUESXo|b?TMWBtS%IFaH9$G5LHIoxV|)?5{#T)p9Fp)EAjWbc zfXnPH4+zOV_#_DUF{oB5u*dRL=tgnxUE{mXd+V|`vtfzLN+OS^=x1F&?&Z3*Mo*#+ z0wp3nKWHm^#9z1l*swujP$^<`dxJaAvx@FGMY3LAnvAHWk(cSA++l@Wklg2_n``&Y zS|Qu3isw_ze_I6t-PUd6zpy9nwm_yPfI?HEJt(F9K@YE{_Bzg2edLs<<4|6!OHp>=z<9ZNP{VaqC0~($l$!Kn6@xyf?ZPb!}Mca?pO3L{*R~b1U^G^eK@@cY;t8mL)JinM+E`27vGf zt2y80>zx@sjO8r6k@WXE;7d|^`-R7N93gj$L$Tu{WBMhkr{Q-GpNaofvs4RE%=7ymeUhPr!LmX za3sXujJh8ZX#{9ic`jydd{U_d1m;M|1aDRMbQQ2L1cp*4?SX1N8v%f2qy}DEL{ID} zg_g{xa?S2ng)xiHc5~PpLC5&VW!?cKrV=KM$`eHRD~o@eH*|g?M=yCaerT)(#+S&$ zn8*R}L0L3U+i%PD%J~n)88KJNS|_lTiQ&GDxgu?hhmDPS${O*f!|jQ=4Xm{TfP>?6 zC1vT30tR5q-hwOf4eluSuuC6x-(dMAhy-LhHSl;?u)Bc#sM^l+Jdq#P75_9?=)8}TC(KPDgbc@SbWYC4^1WE{zJSRZDBHKyx zf&@H#zJ+t6TOxMj*m^qt71IhMrR)8?4m4Xz8!)j97#9Kr0VtzE0s;DqQu=eY-wS6# zNHL%&ggy-+F5!J|u3ee8hS@1*j#dCH4vr`Y(vxFxa_XdTB~@XDP~P{Glo&3Z7qvDSz2&?>;lqB*lZ>}4>14IpbfHAy_M ze90dD_g{=DpTwtK{}Vc@QSW`#jPGY4QyEk!(fGIzf^0?PX5%1p03F8ZjnzUv;GD$a zl1I}S6q6_3zj5o0)tsrsr3fikh453VsG1BAriAf5TMDy}PP!Fzu=%{>&epD>kuVEA4l=V^}1WsIMMm6Gu8 zXFQ*YyBYp(KWWRxLX895!i^t`_Qr&(07IX%Jr2tcvBT=|uBLh|^ZD*5KK8?UnW_YK zpVtFFo#i*BC*;zswx(R1q&z5M!FHLZL78%n0rnS}Yd|F<8YtO{1jI)^7os%b#Fs-; zLK-0eWJ(0!A6UOEyH{n9?UB>_i5HlybnTQh$6jSo3e$-Y079F}zVnO##vTJx6F(kv zqOc_Ld;_q*QVq5eqzL9~y_YuasW(BeUB{zvZZ4!_5PJpbp@g{J^%){kFp@HK7~mL7 z4M@@WFN%`YZ7o|E101}pcoF!-XoetZrG_nDTx1;l5zGZ|5{Cd_0$FKD8Ytx=jSxIu zzgM5)!afVeVKbIxDG4)>l$3%53KU7B;*m(N^Mn5t7%b$`TWbL=R%Vd~Q8_zg)Wx1JPc&2Ak949S^}&`@0>chVvyL%xCae1m}c4 z|6lS@-1)_r!vev8%4VCpqd6H$MzAYA)Y>o`bu_sW;8CLNLKIO$E?-b*$!=$`y}wRH zB23#(0i%{@M<+Na53vWJ(hrMW7ktkW1+$}F%1bQc3=1Fhbi$-Eds)$S*NjpIGzt?l zLRCU-1gIG0_yHJQ$_oooo>Ph5pSg6~BkuJpx!24T!G$bh%xK}>LK)FBIYTeOaaOZ( z7@Q7vuqR^>MuWO{@({+=e;SLL2>5p?C%#Z1Y>x%tJg^IeK{J#x9UCXN~2QU%E+0Sv=s$R7~De7@aY4Hp?wE+h^C3_lgV zd7JIt66+w|f zQUCV(bG|kREJ&gyF*#23$fXiI0bZvOSU7_Jq>95%mjg+(L)TRM%l9ykz&m3UNpg=h(uA#nU+k7tt=<~{MBoH zj=>F_xe5tSqMs~z{o^Nnx#Eo0_{TR$?$Izm$b z5K1#3$fOT}EmFyD2F}BR2-KkgjRNLEWFiqE53F~@N3XJjA3@8V10Ty+oojm8P-5UC z$S?(0H9fiFXVO8YPSTKtP$x0Urk}mR+k~%E$a#5Kre@w`(Gt?Sf>k zp`kO7pl5(02XYm!a>do#d9(Aj!E?Z`(kO-{EP+QQ^;PjVbRzyO3ry?ABKh*kP-<_k zfF0vG0UwVpo2JI1{@vak#eT&S36XFn2nQ%oCnks0#+loaN?f!pYS%3W*gH;W5j1j& zN5gZ@tkdsiOw3+oA%KDLNXg5=@?B&4i$QYZMjMx!wt^2)5k_F_Xh|b93Hk_K>w|4} zE93u(yS^zb7&H=`D3J`p2zc>64PXj2-ZTYt6B;sT-lC0leQ6M1QCZ_E+XkaAP3K_-MH0E<9$zv*H%wOq{=g!yF4 zwlpbn`2uL(rfsMm)MV!=Mv5os`)zZo z54I@@4@xufYfYAFq1&dG0V~ns9oF5glE6STCnUNvHJ3Yv{GaF`coh|AZmX=RRzGLO z#}?l z`M?_;V96qmPFTi*GC~+U7jvU2nazKa%_rVWBa8q53ArLc8p)&br|gjHoen(bL*SVo zi{ks@W{5c;;1WqoBp@=7?h#UZBl*HiF)Iv3!t$%f5D(=k)i7}v04U+5>H33PmtYuW zVJy}yff%sO3N&Swj#TQ!kNX*aQq}8(`Eyl>7Pmn;S*3cskVCnH2tK+8f`3(RDP$T8 zg$=0$P&fyHk0!&W0J)r~K{+MQ07{q6sk^Y6C{A)Tdmw`P`?nzIFo7u0AsLCuABd3p z-?Q_%<2aa!j_^awXefaQ+<=x$<_X;2 zCNwIsWBC~H?QcgRV*rf_NFjRgtw~4=34>JKq3ETjM!tJ~tdMqkaxG{hcwaxcsFcqI z0L%jsG6d0(?1yN7^%%U{#hL~a%P?BG(gXlR$dmybl^*3cq7)v%#@XEo;$@y^cIrP9 zkN5Al9oK4cjWTH*sZ60c3K>aYRjFW05J4b}q709L>a3tNENd$~Lb~D*Do>l?re!B8 z9~CbqkF8VAtkizvy0*cu5(P1pDI|U`#G~M6C8_w^t71;ZQy!F}kI)_0aoUSu@5B?B zoiGwUpNm<-C0voqpCgeQzI-q^bYkk-n75Z#kFL zE=o`Y$O_6wzw+u*G7rf^DuO>2uqJ5fH%9jXf?ep>??wQ9*$Yj!)OGFrGQ7>7~-#nG*1*1m2 zQ|!cz4#U;#ZiYkUpNlxr7iN?s3791_DUyH#CTI2v*!X5bdUcVi3vA%)C|q2YqtYi(}p2 zT$2wPng)PXM?t6=0W&%Mpp{d^)j3mvrMXasNadWmwJEQL%bn%>m9-zc6@6V8eFi;dgLa;L2t%^D$ z9!*z*ThM#xDf1j!z_Bx zD7m1Im}SZmf&;iowv)TI5B8$~H=MZufn@J<3GHemXnmh_`N|9eG+|u;fqE27gk#(V zX;-%RI_LOsa`j{gvs79b;&YkG85ay$pC?{)T=<}VvL~^KqPO`($b$>jkNdxEx|o`C z&B8Rt4(`?PYqXD1$k8`nmdzBxX)oqGdDKOs@`If-~^BX<#TTtUMY6SY`r2n?`a-5PK=BTE}pR zrGO2$$E%hq+m^)w0F2yjSD>5K{h`0!8++HS=$FKA4JEHxg4kjO)BhSFP#I__S08Ha zG(IdDfRFWB7~`<}g*oS0Gw~|1-^?(QbG7H%X8d_Aa5#lQQk^gh0x?dHFRK5=<_9rLV#2_jS5dL5f8xSP^ zTV7KfJD*$9zfB6nzCB?GMDGt?!8$^(`uN5ssoNQ)B}>$mo!5A}*44G~12)MJD-^T5 zgQ8>v>}qZiXSuMa5}VreQuk)fh{Ub$$4|22W1Uz zur%d?E0M1;oTrn*Gej?wF&!glM?mecc;1daU9Y2AF-)3LO__G<5DzfiSwk$EgAfr}|2a@4(iIHZkvxqe zhDwcPEVZ6o?dX~x6X*!u7kBw(3S4R4Q-WlWa%KE|f_rKRBlgoG{E;LaY!3MC8exnV zt|ag#0y}8`J7tf^^P!WJ@DHo&9ga`KV2+*Z^FX@_Uj|b#vloK60nq+mKxw$s0`5ux z0hd;|L=3UwFaHUQ>BsSE_6!13keJB<*k2mWF93xm%032YGr7`od)i1L4ge4t7QqLt-E)SY49${&Opl8{8fKAInz2drZ%W{_W_1t)BfZ8@ zXI>GV+yNxs>Gs6r;&I6@B2Hh72hn~^0{r`grRkWlC+VC^($_K&#|bM#KhdGuycmB@z(HqccKyPW(wdCxJ^vM4|vP zw6cU3)nVtZMHYg0)U1M-qF*BY<+kI9)vg?De#-=eho|EB9WmuyyYQ22{>0n+I@La> zIg%X8UY^Jdze$s1_d@h{GIHoi4+HV*vs`IQ)93<=haXHPqyT$BiRY<8_#qU2=Jxsu zn5OsvaLdRtpy7)a{*#EK{B{YL-lf<%;plCSMBQs$8jn!2kar&i;4L$!R=csSHpKGX z^g}R9GxVCrF(GV$Jhq*Y6y_=8@lVACv;CufIi(T}sP>0i4ImQ8KuqNj3PgQO>;;_( zklP?kkR}3H2${%98PS>_VVarx-kHj8`^CCg@6PT}#WTj37-q&30U5ch_t4uNJjfzb zksy(lh#-mNyM#vs@Nckv7o12p0Qklo%-*9Kq~wz&n&6k$HuIt<4=W=S6a*5(0Muw@ z%>Ahe^#1~-!#k3-teGo@oXm`!${4`}iSWv~`ByY_&ik1}zT`*n@7VRt zpu+T<(*71ll4%lIJ&{m{chRx+?Dig9GiTzOsq{_fsXZ=OwNe_B@>r8IH%5;XjhD*HMg=-3Pyw>M65r!K4$@%caK$TGSt-vyNC!R0bMk-ic)3@w@n`oK#xHgDAX& z&&0hxA4798mQpTZ5=a1!MF-`#5RM43>OG@>k*>SP7cb0m>Ch=zXABYuzC^gE!9XjQ z5nFWMj`Q42E*3j{pgbnfQ^l-Pqj8oCi=f3I-WNMdoKCL+ab5 z{!=0Vf+Qk~m zwzp+%^#+L}%`^_!K`qNDIVO;h#t-67u148{4WJkX9-ITR7M`Ut#C%hjC@h_7Z$yd% zD0+U`zOt>@V|`^pTVj&!K;)Nc%^$ZJ5NOftkGk=l6u%yEj!-v*jzv0K4rkq(wI?y# z73J+Ac`8$o%b;g0I$5HTtml`ATYgwL3`r!s=8T03`6y4c8A5>YHqEjcljK8sa~p@s z+$k>S=X(Y=hp)`YGdr0z5@bLDDHMm>o(^giPlfvA7NT$raOoekQ+@RFkSUN#Q;B-~ zcu#Zt(cgRc$pfWN;=J-F3Q}GCo-u_W-iUj6>54XYKyEywbG8X_qV9E}WvDE)Wo(Gh zA%pkg@`aez`DzeqVS$|oasW#Lvmq8IImn@JkMxFhN^UBbcX*$<+X)e(4D!VZNg|28 zM7L8c9Ft5DFR;w^n^D3yhHjGGC~4}+A3`U!naAJ-Y*N@06NXuMLKNFuI^}zt95J9w zfSz3gGnP?G6`JvI8j1BWYkoRTz5YG)+E(Eq;Rf^+zaP=AGn4yovOt+G2$0I7BQlK8 zkjgcjZ?uX2c=C+_w0)xCUL890ODldrR!|iTf9l8Ka$N&U`2_Y{7 zFzV{kEWcMuFml?+{wk%9q$eN3AlFB~`P1)G_fLZ3Dzj1yFV>yEQW9FzQC{~)%d7_hk{*<{2h^Sk?^&L zA3q+?E6Gl=J_@>=huQplAEZ28ul*m##(fb+tS*Q^;VQ?LYW_mOl*8*jr8(gR)TQ+V zD8}Aj-}SZ^Lng=E#b6OQL0AU~8qPfYwuuS2;!=xP?=)xfbVwwM1MGT0_!f{uxsO8P zZ=d9>!XNgG#yjKMqiP5M3wzW_c+K9KaG^X|T1MyOXNk=TEZ8)5~Ut9I^?>*PGdvE}p>=p7=6SC|OKd83U{;CI6Gwu@BdOkdcHc#u(beG{_Q>oXrW(FY822zqd)HeOBaO zIoLBqSDEA_W+ya$a9fW|&S*E+jR1lH=4Ogf`1GM9nUYC4WSNqdezByu5hp9lXuH3o zsgC?lGIV2kMXu*Bt25o1o9?yC5GcGV5)+XC8IX+RCJkjDG7&DB6kg-&;=Ai22!NYG zS;GLZ-W5~<4;J>YX6;9hQyI}rO&YuWXF~{^-3*|HQm3;T0P+aA6H++!yLLrT@i=da zKEOS@)-e~MCDbgn=vcFWY4ZVFaUAH~7yjGvK*!ywjy2Kjux=F-hYtfmDQF=>C6QKZ zd~VHX8HRT+JbY$w2$?|RlOaZVUqs&JKD6#uB3cY6<^ymTnb45Han4A6lWz|VxJv=# zoInYphJ8cb7yPoXqp>;A&juC?r$Rtzk_8F_Ezp~WBgDLLvrZiA0|hz5ZRfXQg%eSPNs<%*oU1+9P<#^#0}ZyID9U^7P8`vpBj8!%Mh`Vy z_?2ir_1=Jj(qFcB7@X(N4~e(9zzyiZz3LYZ+G0b5GQ<^|e20EG;s)VWwx(M}V65o8 z47ZVkRsGK_2CD^)MEnY{ck?Cxe;DukwT5iD|KAU@3OB_>KN zkIxtuwOqqNYjgzUX6A@#85v5A3b1QwLA~jZDiDQkNU;PL2@na9$sZMKP2%;*I?9BP z!J>XUO@>(b_tt?r%Ad#H#cH$%X9bCwoWX=81W-R|#x3Z`X8vuXD)5FG%6Uyh34z+| z7XoMjIku)qGc$T7avnT5GzjrN`Ugiyup$gH1OzB0AtZ-!$s{tJ$tO_&O_tcScp=2Q zQ9^=7V5C5vSJW2h@$o7w?i@%8gt4SkG=uIh>$UrtFdY^1Ybm4iE^+TseaHMvG##{$Xxymt zcjV-?X!wNa%hoi+6^VZ0Um>5C5_Co5y|ot3@!2Q3A5Bkg?=Flxu%!9s`AlQZ-CzQ`vzas#&{g4zlF zK(JJgbIFE%4=qmrU%AU@K}86rM$DWfSFP zYxdu3jkfX_0-Jv*RGTQ4CoV?5dkK2AAOZx5<(ed=;3lcqF%pxal-WZj=7~QZ&^O_LL`}!SS-OZmFpLihSCYX zU{q$Q*i~bplpTxYKQc!!A94ffS=dy$;U`J|*WJVpL0@DBm0J6G%fh3{cisQGxL(LJ z41_+P2-*p+=+iYhHk^dsH;p0Q@>36sNC3b9AOIjfCRS9tEY7xI z^CX=BXCRkAWe7@C#p+vaSVj?GyL;Az_qNcSk#ZPLa+Jvkqb|x}-_1qM`|uvx)OC$H zjUv8wfL*R!86Z%i=n?d__al7;2=iq|*BY{dXLiZ!he3EiE1B7c{qZwTpd}!A*lC=Q zFATDEoFo#w0gr5b@h)uRWSJoA1euBkc|w4L$7+iFky{S|0$o4*#=4y1<4y8Wrp9N| ziS*_T;)2Jd5;3HIZFN%c#mWfON9@!+J|J(k%kEv6vIygrtT@|}5d=aa@8F{=dGYUf z90KBvP3U*g)atXfFo`TDpn zWLdGbj3yXJ0^qeNiO8ID;zedxHO~L+zc#GXroFbZP%{KTVU0*oq4Wc%iLJQAxr`yF z4jvav1!08J86n}-n5lWz&#l{OJBMo+z}4+*P(cQeqdA$G&&FE(D2qw$95Y^7$X_^;>+zrf2cD*dyxoT)=A)rkc!#Q$*f@d0YA8Aih^jxsjQELlE zMP8qw`@PCY&p{WW5UYL+j&(LfNTDDN9F%~guyxGAvv4F@!Kj0LcpSmIb|&T(1HS9 z8%3CuQ8-F*hXO4zFocub``oRL9l74xVHT*eY2E@>98DAu@eQ*(D*qPf#!$RB@JI9M zaIae1OvxR~9zbES-b@ezfJ*Q%w>DNKbCyy?dfS=&z}Ch^Ietq<`U9Py1cGyB)0cr= zG!{{jQ8M|vyst-#7!*UYu0001j000SH z0S+_(0Av7!f{^1z000coTmS&ZKL7v$0U`kH6=frOawt8?s4(>W|K+6=jEEe${yxZL z@^`t?X+Pqd({5lnL4gFMP|67SoX&4Vp_1?!&-y1?2Pxgq$(d0DvOd@|2{U~u*9oZd z>{ATpPd0n=$D5ern6+fys5Nj+tI?1F<~(nw&;*yibVFGvFPgzi08Vd|kOGg5js(b? z(31)S0YfMC)xFUwA(EpL8B|BcGd$hoF=C?;B z2Z7Ij^`76b$}Vyqd$VhxZofFZ+*2$_>3_3=ofxjx8X6a-sa+r~9NM(N3pl6l?c zCHCA*WNy(RlBP%44;Lc~_vV_~-R;lJNKYsPWIlk7dwwQ~3Rc%FqYDY1!OJ3#Wptmk z2PKsl6Bpl|@L*EZw>9=8>A)lzBMG7iqH>4O+xLVP^EwahpAo()$h|Y{oM;o;G07af zo5Sq>Vro89Vn31b$hWXB$rF$tuH17hv95L{l5`GB#TvMQ>%5Hi{@$^XAFUr3!Km*t zx?k>J6X5(&=-fpz#o((aFz647kr5m)7cQ*jpWCn_mb1@D$Q#z3eoBhb6s~2cf0kK% zX+9c2BRB*3H}Ur15VY6F-(i<)sy>*la*~-Aecr!!tIsZc@8F3a1>o&ooTlXjN&-Ux z%mDa2D%;{Wpy#LdV$()VX&OC)WNO#6KN{g|HqI@BU;uH=Ao7s-sGvT2@)71;O7iD2 z>u!(Yxw0>|86ykj&QP{q8L~o&qLw^E&f$FZXWEX2n8+71GJ{me5Xh4S6aqcS{#MDR zH7si!LP$h2QyXzYWKtPIXc6@o9`!Zi6*n$C!(!HUfJne#qJc9g8&ZNEMmcwK076YX zVUr9elb?(tR>IT)vyYrElxwjDggV0syeR?M3|ZA~rU-T@eMM}N&Qi`_Wd+H(hLa$b z@rw6>TH$1uPcTqcnSaG4fm1wL6RSZkw&RG-?eii>A8i`Rdc$)|+!dSE^aFgD#v(c6RqLS&qv!z`2~;Agv;7!7FQdA_2SS+20-h zgd1vu?oQ(+hGUSs3TrL~R=#d+DVdBy-B4=bwFlG%tZw3ju#+&Q+#!|gZ8;D@$sDV~ z$hvG=Xci`kp%13;zJ(iS6CNah7Z}n21443{zyLBx_Xk7!mXsBrOz=z~#&Q``$&A0F zlt`TG6EP5&Nq00SKm?)LIvz7EyL%~z>rD`oO$pxDXVynlA80zJYLTh}zH40B)Pb+( zbIOw31AxoG#y1!C@G-PF5=zlw8V+M?pY*qFpWDy`MobS+&lQ>fiJ#C-aEy=+Nhx_k z_1qy`NM$Vros*+~p;uM@KZ44@kBSx zPx0(Bp8ZZeLGpV1)t$dM zk{eptDvSUDSr)0o!cB_N@E?Du4KyNkU$Ce)TgQ+G9M=dAefp)RegoVfJB^|zM7`;h zXx-wF$}j)L4v4SFLO!>HPWu8tSTYUOVxcpXh3U))MD{o0)4v!yPt#l%>tBqR^}Qas z200&%7uF6`g85@JKnFPn5vD*Te0h!d=^cV^KP|powFV@+-~di}KNlb+yYPAvA8gx2 zzpVBeS1M~U6&N+>@C#6?WK+Wl7chbwBvR6)_QaA*$tM9nR&z4n<1s9DiIo2xBrNrQzt&`!Zwo*rQ~SOLo9XK)^Dn_^*~Fk(Q?{Y0_xR zH=&1V_JwIzAv=Zv38C0p85H-v0@&%GDQVhaMKbR7+Q#M*@u@TtnJf|A5+;G55UdkM z#c1(gXL;lD@ajwkP|Ec9%5&0K|Bn7A6EmVFG?70?zt0+dsgy`y49P9L0**}lO1FZm zbKhbEY5(1pAryd%;ZQTm#t5aKnorY`Cn2;= z=)DDy11j~;(cakQCQyo6LlZ(&NI)bK&0C%oOyh(S(7Zna>6|>IW=n})y=#rCR0aTv zjDhi7V%b}u-;^#;Gq3=QNM(9!B&&><hCv4{QbG&!p1=D-xpvRH03Hy8nrm9MG&)3FlOgv>Lc-m=#ry+V`wgVWQ=`FEiYx42er1(8&ynPE@^*HAdN4 zGA29}N`a>e^iddtwK)vQ3c+sM*Ft+YS#^9s5PX>^0FV>({kPNa?!=`7GtRzHoQfrd z;pF=+aAo4$X5nnmulZTNO~>2oczkrvMs0u2stsL;D_BaMVrjOcy*Q!)9wfC#VhSlN zz+eo!TK|I5tx<)ViP$~_<`pf42L@jk!_pHx8FshwvHup7y`CJ31QC%`_LT+pgaP9u z3{Yvr480%4{90F*eAB}RnfRUzt3umO>;nQ&E(IK!@bVkd2Ij_ohxK>llpnXQCEj=% z|A{g|J1PKBB)}+%luYOW;CAl++L*=K=TZE|9iSy4+z;g@T(h-W&#Fgc`fAfzuU^3Z z_aI!;XnY^Vdc>?+j^GQlBxcwi^`MY-F|m~|XL>s00maT3GFfSv;3MrFBOpF_R;T}d zFQr+}F3DUlfhvqBU_JqE?Zr-?`!y`N?WQmZ{bqy+-ggnB-3r;;r`La!oA$u{UR&pQ z4KTqR0CQXJA{DWw)G-nwf9?V&d5j+NUWGCQ8nx`CpEQ$2} zY>7+sF$3WUp2qxIVS}{&G^6`|>-y`#V}+E2q!K2uf4BN|mZzp`210;?@e%B}xD4fq zVn#@UhEYQ=>;y;kO}=HW^4=&0g7zF!BelzxS99v4xIiVeho%Mk5<2wzna}VHBoc;1 zCnNw$IBwStf<)edJR)t701ixn%0QzUY60M@Ckns(B4-o%L)!)jKxGa*q*0a`id7dq zslqLGK9ZiD_t+v4Gy*9T7!S02TWHS_@Y7&R>`|O0B7+LON5NZue>ZAMQV?J#Aq>0J zC3qc(BIocoI`+lt(QShVA(4_ggc6o!;F;vfG9AKru@x&g#*z~#p*jehuxK09+)62& z;;&gb5<@R z=nTO3E&so7G&sB4s#2N)WS4R>htSOy>hHVQ6kv%b8{~;GUcoG_Od|kp&0&h*@cdKDOwz=-eq&n9~E3l)gF7fWVmmGUp-mz)E#%V-b48 z8nfr)q-WuMW_k|)Xtd@0+N}<&9}Mhv&M1N6+crXwz9%X!AfgX~t)xHv_omrKWW^s`LH08b+BAI{eIY3Xi$GNjA}JpQeY#IHrV9_ktynTH|9(R*lueV^;n^C$;sb?K@l4q5a=X zaKMv#%r4e;DWF0EL+!u&+MJ})&oqqy-U?B5?3}3&3rRLlJezj~?bqU}%{#5$kJVNv z=o3Vr9eE_rMYfpyq|fu=D3VgiJ}~<@?jb~c`9GZ3ZypcOPLSC6-$Z?`(m>UNJpL^1 zVC`BmBJlhcqCVB?muko2gBoB$*vZ4DEZR_$0Kj^3$wc5jFU3p9=l|8Y{c#nF&UdM? zuKr5 z0eaE9$4=aFb=JM;W1-xUS}k-g(UX^IlN_OXJS)~CtjU@0^h+_8w#5(*Q1L4$E|4I&a73mjISj$C z!ny$T>*|1CR6jmbbCHtgs}R2~I~SPFJAF%jf}y-Jlr6 zqHqet_Y=dwNPB0Y9=QG3_5S@<%jMu;uhPAnO*CgZ zF79C{#uAfwR!N|HL$W8x`-rJ)Y|Ps&DtgbmzS5p~cPylEf;+VqAkf3%(3)95UY`S# z%#P%n6w?!;>IHs3Y8@i!hnsk`jf;y=Icr z7feG$9>b=XSC~-+u?&pna*_h{la^~Dz1E=u#_3$MpxROAYw#cI&45zeFs09PAc_kZHPTTkW z$PnCbPGv~Uha(PJM0UNU8a@W^@338Xev#W2=%NhyB6I|@k)b3ofD61fOb6# zPYz^21rw9Ne#j2;(zTBrjL+%iUL%s3>wUT;5F`Nzc&kkA?(}}4$Mk$jHu2ly`fv-> zVb*>$&>(;S5P}j#kzJui+hwxy02H$|to+^Qkyx3MQpr9#@Vt#A)g=6`_mTqFhZKB1 zk#Y0i@aA`7JPO21>lyx#*N-ZQGBsk@H2$bUrfxl8wSd?)WH=a%CI(tr%O~=eOjl6} z`hF*;>SgKuT#z*YVJZMhh>|A&z&r!?QP4z4)i?_d=8~F|?4U9=Fy(Lg2`!AcR21o- zHGdl;EEKvVga^bzG{1>t1!Ek)rGm+aFYV>}pV3~IhX*k~Ln^$f1-@MBru0uqT`_l)N*apF)-VP|*JrEiPBojQm%o z5}(^296qDk#}_YIO8_GYbD%`N-C5od29NQXInwQf!24fp1N|)k<6l?fY4`!w158z} zw+zyu+}}+eO7`xZ>ik3P<|RYJ?dLBF@Q(t>`u~=v0GE~Xt%E-2c@(b|cmD5Qs^bm| z&^RFzJ+=n6WZ?-POz%zWI|4!?jar}TFO2(DAq>Jt(;73ctL)q2D(T{w;wV( za+!<%bf35$Vji%}6rez#h&zkjcfMYAck;%rw2XpK82HFIN=p;QtZf;vB7p+2x+!Ym zw6seA5lfeb0q|pEqERp`w(l!q!w6*?zNNjN4}b|88<21(B9W^j?R~j<)VaM9NE?+D zC*Th>pKWocQ#b&^1oDxZBjU`Iud0lT77~z^0o;7H;Bln&?gODY6GDuTMoDrad4Eyksww(@$|j%+THlawIV5cl7a&XMU4SLv z>})R2cNTBkmB9nV=c@$)AjBk5`j>JC6P#pn*Q0uzA&@C+*Bi5RYg_s5HuNp4NN# z;Pik1eXg(pm0P}%?Q?f^AbpSl6c7jEc)rM#lII#N;DO%%4)=M$lpNlgrx##CLRW{Q zz(xOesJwlTjbuv5tv~{i000003=I_k0O&se0099Z01Xw086W@v zeK5EjCV3>pa8ZVg0e+>Y`Ne?Ia9j}k20$<7DmcMGMG=Jr;$Xo>f^g(;05D=%{EgqJ zIFW$Oz|#YTz^Tr}O*Al%49Rq!}hQpuPq;YpM6!`2K!_mPc-^ z(n)%NL3>R(>Huo7`~czp=pHX4pP+J^kOu@FHVlX&GvCQsZQ0`XVwMzg=6~8vDFy-O zEk`n#=#XbxO?a4wUH3F7qvvi6U0pckgp6};ZyG;4P-w~8r8rw=Ok}n`WHVy0vSe}x zHDJ;$VKM&Zz&Is%9CHeQ%R;}Y3Z{Vez;FnoEolY-u~uq?)MxUIQeD_;wBjpvGhJ{0AC*0+yDtj5GSJIOW{=`@zs;u)@GL z4mH$+C5LDq0whNWz~fo5rzZ-et4zH_YeACaoR|(Y;OG?P5K4gMXYfXX&AAOd9`)%0=l1{XyJ@3gw5l#g?Kl+|DPGmJ^$lxHMndS`>I$gcV@mg@d3z zrl#LErTp#=B>t-KJoSP>cfax8!R~|ivkgSgDSQ!C`WF4mt^8_2 zDNK2L5f}luOzL3}(VIpqDmljG1GqBaYAeH5AweSdrlMS4c%+Jz&Ya=p?TQul0>&lh z9Cakdm}Cb5&Lmcy#ZVWmXCDS?@m0Z<1x-}0H2cjv|BGJs8EC@C7Y1MO6$9YV$42Rm zWrGET)04@8%w?s16=vYE1%pjjZfi1=%{c#MYnW+G^y+Tw*m?Dq25GW*wCFigM7iDu zC5`5Pa0?Ui&hzmhi2u{4az8lx!1jA;W{V~T8fu^M*a4&?lYcbVhDH!!*btPlw^5{b z@!o-`Ik<`e=Gp2)y>b8!&@h~C)*7HZT;;wj74W2=GL|{H)<7W?Vk*m%H^wLm=r8?Fb{qE;g!yH?^I4TrjdW@>+L8TpBZ$utv0RF=mcF5_36@L*?EAqwl{pa^+Y_ z66JqWFvVoB{|W6GZrtMQM&Uh4zB8AveKbX9RF(srYHm6#oLE;*tRnA{;rQJDJI1ue z1SW%muliZ%XvlKMa-~yE{pkiH)uCnp;#J|nV%O3{axquQ8#e@fa6J4f=S^~rQ*nd3BG6NY43qvRm1vJfS(AY zI2z|JTDA{EW?!r0CEtZ*ncz^0G!JanNC%_Yj03DkBg+$j5^Dzpab$tbAk<@!?g_w* z;wYq~iZDnoMs%$Fkr2+^q$mSm7lT9mM;`)p8i2Z&3L*nYR$M6LOpF>F5I_djJ4jG0 zzGUwTFzwEBUs#X=3v7IqC)t8U)4 zGmlQT?e3nK?X0m^q3V9bB)9Snjrx-nY6!Gov#>~wiQ!b7L9#u~vMi}iUyQA+Zb zV8%n13A_3BLB{9V)KBOthG?G&xPHLez$Dj}>4{?rlL3RWWuhKh`Yex)bl>!7;p0<> zP;*OK3Q<8ZR;@}Cdx$~J%2UnQ`dFYG)-+jdUjP)x{(wxH8pZ9c-QD7s?WQQVS!6S) zEIGQ{am^PT+)+;=jZh=kNP@behf&&*z!jv+CwdiuFpA(1p3mNZ1!cl4?!hAAdU5;r ziZJKF!wCw$C5eBk@1e{Q%t4N;%ar;K3E)9u79nC50bmvY=1*yIHbE~I6zp~x|B@J< z9-KQ8+788%V*UrWv)a%W>O)8(H;>2U9o=XxH&4q!z$90#ydlph_#bNE)>@^LI1z=K z;_`$tpfs14dex<&r)5Y?SFe)J@l;3Rc9)N%S#y2JDu`iz9$)fi8SMS?ydsCja?31~d2wm#W z>}nFhf_k*}YRj*b=hTiz0{H$0aaZMeu8*shPW6+&gaB=TKMJM*3~-|j$yaFipL^CG z{PvzbVzRR3BTV>o;3?t(WE%?=lfVE+@ERL)rgKTQ7FOREhU({9Hw8JI77G}a7`aLP z4F@Tr*Gi4ouPzG0un3SJ!J^R^9|ss^g93eh6jZ4NQgn>HpszaLzy1 z{F9TilFj-A691{Z{ks$PM3P+MCkcC&C{;G6uttfsvh`{4N4QR|oK~#NJxqCKKabUk zdR(A)T4<9IoXT`a{AlY0t0tMAH`^V`e7xbCR(Gzs_wQLd&;x!3r#vMhmizDDI0JX| z0Q&9W79Hb#%@0(ZqCuS~`84)O$6o|G z8zdSD2&Vduy$5^w+v715W%GBC)>v%n{32?QFm}UYB!*}5W!*O;IAK`M5$4l1F;El zif6H@CHBkS^>FvJZ&$XXeL50?0Qq0~KZ^b6&GeVnrP;`kWdrf~f2Mg-i$JZi$denS zcdyi8)`MW|hH9ritaMEgxT)JHy3$#kFF(kl!cqVI9UCV&Co?(?F3`}~+6 zj{I5VxpK8>@gvve`T^i!MD^0<)H>zX50Aj_A*QZtkKM6f!02Z8S!4W4F!hnp#)t>Y zH?gxr|4KeDf>-62Kgm4Vh_a%H&ub@($Eu+E*6te>z(E8e;Upnna!=abl6IaFmHk-w zyh@GFt~E>VCD|k5o;#jZElpFNFI7{*F54zo@7{-eJtGDAd^<(~*Q4&Jmo~ijQP&j{%ZowEkEQQSfBh7Atrh?7h-g4}rRGZ@;)S+y+Sz z2xY)|KI;xuFdS>uAmPOpB42>=+zjLt?GvW3{$GwFR16hV?3>~+5c~qYM~S!$haC3- z#&!N7n@`7XaaRP6L&i$+Z4egfVV!flKnfi{6b8onL|=bimDH#=bASEml$U z{lM>qwOtJ5g+|wt2RSftXU9)ZAmfb!&V=G;VD{;gWU#05%R19qCe+QzGC9|D;{Y{C)Oxr|u&jKFStwByQ^!7Ve z2zWlD>JGflO=JB(-{Oeg>!J`82{~`8qw}7%EIhqm^t;X_u=Ao_d|%~vEnv9khc9>E z`iM_`empO{Nk*5Z0|-tO&AbD`gm zLY^+k4LZI#adN)>RrXk%%s+~mqe^S}$2<2nNXGE7`)2<3gR=Dcm0N7;Kil4vL=c1{ zl~av03g`og&6`;cpc)JdNqhxZmaW(v9`Qw2Q4Zdh;5+Tt^9ZdP z4h?7U&NSXtKx`8Ak>l zu7Fu+)n`VIDF;Ak56aLw#2)_n=CA13rJkxjpF=;1X$bDz;D<9*&z6{9` zN!?;30R!F>1v6Y_!W;*1&X|w&Pxa_=XR-nHyJr|+=xz`gxI%eSa3;$IS`cgs=q_ zB+bPr*e^gMxy-R!hi3^7TXXFRof{Q1hU~VY3rjTf5xx7rj`1%X=MEUyeM*S*4_7~juGz4R6f4FS!-wqm1Pg6)VwMv{G7Gq-Agf=zhZ4z~fUNf$s zPzDO~XdzpYUUrPUE#aB~z@vSja43-wD*o4OTcH4(Hlgo0L074MW31Mcyw-pFSTHr! zccQkH4gtGudG42Y@)5FD>F(9bh0EUei%rnop@nJ7j+K)YH$iz-LnKOGR&)1zOpbUL zGOR{}Sv)#(9Z~qk7&)qxxmO<6)*Ww@SHTYD1vAy_Pn*uzok5Nyu(7y;TeOJ68>)*G z%x|YH!HlNh88SgqoLA%ORcL5mkgbT%@bUEUQwg=IaFUb}ytOZHana&j+Hg#$7ibji zI^n78Vq``1vq^6oMQ1(i%#Cot^>)sWyl4aKhK*QkeE@*EKN#eR%j8Xmv1$rSTiY3YYz zpw;tpwudg@xARBk`K`!A@$e~xaJ3AIZJEk^qKT(np)?SqPNjE_w7Z@>xCl^&Auf4I zPz2;Csn+H=q9#DTx`n=rb6CK;Xhu+D{cSr;q;5Wa6Z{;Je2Xdn_gw>9X(nfBs70Hs z$$C2NhlYR{*_6CpGvxlD*;tAU3nilyhfpMv6(CwjpbRZ0Ms>ygL5^TED-B5jC%9jQ z;HTg12hV;SgcSr;)3E0a&day2T_}@5{7;6h_+y-j&Sm~uEd~l?B_O{WtU(IKn_fhx z2Syd_Oq%!TE&198`CAN5e|A)r*Hm<-KEnHN6ZyGdW zY?B;X2Ek=;1WIgt4I^7LNS-5j%9dBGzVGeum$t6n|M;j}P%{_;sA z4toZSY8_FETQJOM{{qB%>W0e$fP#agoi3ziT#FvoxzQhV#B)G~RaD9rx_F=gKsZAJ z_`L>^GxaOIpRy}@A+=<=G&tX``nq<56|CD9>7FGQObyagM9v<8K$Vr#8|YJ7BLvHM z@^iyW_ns8e4Gq4|EF}X9w!#BCYr?Y*T5rGuAC`hrW;DSA+#B@ujX0vYGLG4b=CTmF zEdx}#HEw%6QMOkt>dvZf3#*iU+k>qb%OyrmVOnevT3@)S99^J!bV|iL^Dl55$wibzFlDbP-cF)d zMoVI3gRD!eS%EM--sm%@^zqXhPO zKwYF%u~H6SsL=MC$kd+QC>+6;xtVQ5w%-x=0Fxy1H|x$Dx!jevsgX{%l8ckaeOupE z2aGM$(~BowR_4m^4Hlv{;%kcWx7z{ z7>6qN-Wfk|XJ3VXy$_T)y?&FKxJcXZuWWO?IG*v!>+L%-`S{et6Jz6dfm!8m-+k0F zDWCdxf(*TxCjNXxdEDF;t*q0Xj8BPH}oEhshN|GfZY&av4azg0Y&)e z!hj(o04<>DLuiK4+Y6)BbPoeT*ERVM1+?d^Y5)L-68}4%k$CC{--Cjlh<*G~yY5QJ zo}S`L_ecdQb(|Eal*0~g`7AL>%X;^@evvricdP|)F+Bd=k}O-s+lQ+sw+Td5PfY(s zG(8?H#_7?RU9iSQF}}ROAlCS$mmu>uT$EJ(1{25#EtWBp#3w3P3RRE?FI4_8uxseX zR`lDWr~swfHBzFz0az5W5#bqXSOAKd9tn*edU2%#&GpVT0+FrCQ*jcum8qu6G3%ng zN2I)nPq|2xW8R^lC=OencjgE%H|n>WZ;ozPk{N=c*^g57#^t{Ca_WdtB zP|4`uE2PGE(<88^)WC-08hLo!N-^Tm9(pBr1|^ym>&_Y>>W=Dh5pE-^)s`24bFMsd z9iqVM)C=xG9LAvm1u09!pq;1Y&^-)txm=HmRHqfKM(5SGuumiXGW2#s&o_JY=D*e~ zt`Bx(qI?%1C&|)`nU$`N@Z}T4I1`ow8WQenDJ}nX*%GdQyja!p@?x#K?dtmWn=Hnf zN6Bq~y#NByLll&<5fNmvOv-IQhMHZ$1S1AKRv2I;WuN z8~GO|Q%+0AQ{1HVF0bmM2r-875yUHE;d_*@x^YG;2YZOpn{t6~%{y7nqxR~jPaOIX zp@`i#lc<_;uCZlnqWrO>O#(BLwXPbf?4?+Hn=$X`v%unTjy@D;n{6%Gc#`x@ot5nG z4X})!gGd!lwj>Kx{IM#lSDaTIB=QzDunh7>oC!k0?56DqU4u&3j#ldKOUA44?u`Y9 zqZ9RCD|zSZ&wCMQ_^VagMT2Ig)u75yOqbcvJ`VgNdgU&jA%rV_9bZBTA#`j}&Af(R z_~!_6Eo+S_wy?*Y;NXS+7wUDFF}%gmh3|5}?)K&23&TBo6c0>nri7wYs=2>zxhXMG zX5!L7h+qsomTe*}5d;=d2I%kKbAoEI;@O1&*Hz! zpra#~0jkpHOfthZZ1(%_fL|7h<@^GH%_kWd%~TmVr3<0%LZKis0unEFV!fyW_=k8H z>i5g#=eAJj%)L3>r2MPjC}-#>9P{T%`{nEX&P2f0Sn5o+n15?zM^aQ8D;3{`=ZJ70 zTjB5UCNaladX3M9<4&4C7_~ByO{c}O19zSBK|A?z<)sAQAUh`0H8Qrfdw zZVXNjjd3q4^ax%6xVHR9a|ellHbJ#TGQ*{LND(IFO7r+zM@Y<- zE}#E4X-H5lL*>^JTfoUh4Fhb|6AQk81F5vzucyq6S~}gvwV=u={_kD;b<^ZV)gDZ0 zpWWDSZVB6qZYI(K@y-TBa*cr9r(bDa9V61Ju+PO`%6qQOuts9dzpF;4GIR>3jP*Fz zz#-8*927fDq~@=d4wy4E3EJ&9vZoT`xP0sw3Bk+y86K{_T4iTWB|~a)^gXl?^o7Ld zcQg!#z-eRxXd@MaR&!KrcQ?EcgZ*~_Xz7qbP`l@iLAj9=o=7j zESJl1QuH`F)P`y}VSl7)m<%&ZWlOrr`#Ori^0;i#?6;)f;U6#sDi0*nrP?~7tS{o4 zEZ`LSdLUFJE|QW^gHa$x8nR7_xgUQxEZVHhmvSJL=N%klL7Q~0V3Rvbl=>yLlWPpu zJ>a|0Zwm3KyN2)ou&7IzLDc-gwkip))7#@@75r?L`zxZo2ZOLsHN(BxcSqABzXk^S zBu?{(T#6KA-z%tH%J<OC91$kPl_A7?MlohoK-aMz+E4`r>9Ec=h~Z-h%ow3 zK_PkqUkZyljkZr$9&>PWIYj0c>Ok^`VA**#JPJfe2Z<~MZ7ubv)ILbIFk>D-lZ>fB zZ5bm+Q{sl)?QJipk28;cK>)pSK5b1nsZR4{Bjv9 zYCGD>imV`)NR@C>U(kDF4=F>(^O`!GYFb2Jpy9U8I{vRGU%vf*jE7W4mnJ!u>R%## z=Wj<$6sI^FaUA>jj!ko470TXvaq@PSK4djBcz+Sz%T8tG{%x6=IWYmhc{~{xmH2R4Y_!(2^N;>fVRJ0d6oU1| z7X5236U>7Zf;GB_4UaC@le|Fp{}#Oh8C|)VPOc|tp2)z>Yn_~78t6EgYqjc*o z0r^x7An~!N9nl2-poEAF`xEN^x;BX#QJCW&XqfHKuu6ly;dDgl@{9H3cj2hPf`;%y z8%CP(IclheztbgeYP-t1>aGDXYQm@&XsX5XxM{^e;I<;{_hd=`M13_#FG~{TdEZya z2opg6JjeJgwC^++&#ab?!i#3+Q_gL8o8(XE`OU{%v?+$_eHTFI!m7p$iNsjIC61ii zz<`f1&i8fQAT#f&@@Cd>b5C7J&m;8xE&@gapc5Sums@l(7+JB}HTZSLZ(WQX;w1hJ znSY*@yIv#r!uzv8T}0uGNTD>?c`PmAbllOa z1Y;W``jqI(J?u&IIUN{8TV4*co+^v!Y&}m~Hi8@p-BO5v=cMqEo!9*zrwtip`NXZneiUk(`?j{?)1?yli#Bh-!?lJQW1`i^}nNw zs)|6;r5N!vUg+85?MuEtGG}iZIJDT9KOB*Fz?x~g7K59eT~X| zAvL^{o=^;R)^Mxij+O`usxx2wQAn!H^_s^K#l)*^eKHL4ao?B}w+IXIjwN@?kToPw zHi~7<886);FbKO2dLnE%kPbZCyA{!ruAiZ0EgyO|^oea}YX^1odJ`lh(o|T-MnH-p z2=?l3OD>t1F=8U+>$n*!A`Ujxo8TZ$TQd4|G6v2S0<;z{bGaX4wb(; zAj7prKyU$bKaCi2TkBHr%%2RbX(GErZ43L;dpW@K4a-2DMJ(F8==-B<$Z7m#+jP+U zLKuD~XM1vaNOw}OU{%;0%V+xi5Zg@|4djj4tt#3jIFlc z=P-B5I7!4@;J4-v`&IWzimdM&ZTP9+{0i?zKXhm}RNYFpd7zElsM94-VR8%ZnZy9& z6IcExN!s$`$gP!c-dnu<_(i%(U4O}t&C%jPOlSSzI;E{Ma>N8e`Dk^d@tTlzjN;Ym z?AFC!)voTKQ(o2x3- z>?2Zmuu|ovd~r4|29LDU{xIWHpZa{3R&N(MsF9FC1Zc0P*rCVtT{TB zRoe##j+q3ZL4qN*4If7MH=t_L7A`oo>~z8sx%hGQQ|sW^3R|iw&ZFAl`(1GA|Kx!f zQ~+TApF98qC{d!=NDdW|M~!*VMvk;oLO*@fMm1Jw6|{vSF#`1ZAq85!*t$AVm@Go} zrEOQRzF9iiN|?>WRJ3z>Tu6i@fc_ny1*$w@nV}8=jO0)Ob)Tv6_ZnkYDG1-gG?{dH z)r60;7kZ;%xI=7g0T_VYJH|Ay*OUKZq+_TXlHr0HxbYRmigaE1(* zA~}%M@_>Tg-*CIE+2HG)Dkc!wr)XoR<#TSzbuVszum0M{QTpuX+_z-P?t3$5urbV+ zr4f&?$LjiyI*L@KRk<52gk&SY56PpLH6=qvio9{iEQfTf8x4>T270nR7`(|5^DOCE zcdbjJ)x{7;%=~-%Zt%Pzb;}V^=eo(^cwfShv9i0&r{)V_wvS8SjIZ%fBZL$)!OgD@=_ZT$JTVh`tgu3>ja?Y_KAHwIs{?17g^<9)-%MQd zk#x00_v-M1{jWH0=jvW`J<4U94S=eBX00pZkdy}^&FQ5rVuVB!@WS9sN1hC;=4_3I z0pESa@vz>*LxF*0O3NYP$&VlqXvxMdX^Qcl++vcXFiRCv9Wf|i9JvC=tIqhXwB{ii z_ZBR=avD8K77pRT#Mnm73}@Nu&kWlzAp*KsSu$+q|0dK-Oiwm#O#wKu(fyu6L)+W# z<<}1hdL95{_3Q|oj(oXlcPUV>ZPN$LAK(dKVZ%``BYtk~MMrp((E*xgT{DelPh61I zXG=?<9B8L9lU-^C?5I3F>Xca^>MLuZ@}42Mtp0<~%0Ev`f5a)21Xvrx`w0E{_FURx3U`GgsiPzQv{lO)^yW5)vac(> z{#81U^e~b~v*5k`7rV5iF1fn#|K-o!p7ZAsKsY#+66M)_`2YWST);bhLfyW$LbNgK zbv+S~gjdZs7K$|xzUx||GKZJZS*9Q{>*&0zQpTT60wJN}(DW>s~)!E~v8@j%LgiS3+%VAGLfv^Rgf~d+PJ7NlaotN3rpZ`V=NL zp4b6~eFbIy_wuex_xszM%2mjB@)!?pN;MV-LwSab7>>o5o%?Q z_0s?8K%{0(oi7K&dM-n6m$Mt0Cx2R&aehF2Z6*C@1wxVc2{99INMX&q#k);G|Iqy^ zy`J$U3ep{Io|nGfl54QmuLZz|VF+?ybB1P(fT#)SE>wsk4|;fZK-EQ?!nA%^b`K1m z`6a5ns9+Yvo5e@NmjSCLfdGVKd((0P54d&WcYukBLy4Z-1h+jenio^LBwajGFLUup z-57W=Pwdnz&P~vq(zA-apm>?0fvKN-EQd`<$F#9YuCw`{S@JqNAJFD9o)~I2n2c`x zRZt<*js|ndg3cl#T^vis6J|u_SvMbedlmC9mwmgGHu;If0?z@|j(4LmUFbKf^uRlm z<9~*q=5OEccGb?`YVy^;@FU}DA9>4I1t%cTWZ$X1}7@?KB6+8P(z5H zcuxCJFv(gC?1xG@HU!`amW)T%7*7@>0Vo|`pFV1mKIkllhokv1hyF-Iz(La=vj?4z zU%MMbe2wlbj0l9V>^K^5(8pm`iS~rN|L`emg_|&HPZtDe_i5Smqo`0F4VfqW$k!b* z75y_IMv;fn1u$Wer?O1IIGN%C+FDFfA%}depLEk5AK&*kkW~P1aN7SW_!TJtDF3g5 z(*sweU`!u4k34~r6I@zjSpm*Q4oJh)B*9zMF{A;EgehP*laUElx_0zoBzO*RAcl4w zk>G*=I#gAFz#F9P4JE88MAkhOl=v4Qp8ioI|8FlSFlT@id0I0nK)HLwy2r;tCnoB; zIZf+k7bo>|#yhAC?K@+3t*I=!b5{Ea%h9UYJT9w23Sep^6VAQ;Qe8rU{#yE?^f>%R zz7fWCAkRe-HM@UVIPy)VFIrwvUZ>z~7qia(fAfe^f*I7J+@KzPX$lq%7Lh&+!p$$8 zoUlY-lt;FS*VR=r7A0d*>dS;EwSuJe1pq;!h6Elz;fRuV;g{wVm^0x|=OKtQEHM`v z={%$k-g*BQMwXe>%gDucv;R23Z7z<#4E|s;n1j9f4>1(VcUW?DAj&t4m^m_u4&c|S z>Rb5|%Gl`>&ex=DVwS&-U{GL}u8SgsHhj8JGx>8pMm#ZsmDAYK_tQf6{LqB(J0T?X zQ?M4l1nOtIv!A0oCW5guL1I0Dm49xO>zVjF4ZD<@uk%dOB&0}Pt_kn6TN%UPUjkD& zK92F#AB4^pM~kxGi3?@Sjrwb%8Vzfeodn$UdPF5>GokiaqQ^=5C1D7e&h8}gpK$57 zU3#6ZVos~K{ea$qOucrVzLI;a)Ymp2J=MBs7mmMqaUG>>o-UcFeUf{7J2)rW-c5Zz z>kLH`J1_RZM18CIz;c4BBL|Z%qF6+Z&WuGxW)W8PCh-{Z z7D{aYP1C53+n&fma$_@LFxBze)s+;MY;+LFGSZ0gK zClvQ36N;pM`=vlMmF~l45@jnvWRtkCQzLBP;gDwiXZo%VM`iAv|FRuv!AM0hQe~TV zudV#kAVt==?xd_KJm>;(|K-fAO1jF33n|^++9y1~iF5l3l(qXA>jUlg3k=O*Cy^g< zx?n+vQdko3IU3L1rOW$c{**FO^OS$rmC#DclkS7)eomZ%WA!JIKRN>$`kqOjN&YSO zYT=uVr7PL6{*0+em!zu=FF*epj+3M3`(3lobLP_Cr~n@CFPm-0Z)weT~Nd$y%Jt!gb2OBjk*34I3+ft zOX>r=+UCJ>?7C_%AQr z#y03J(|o;$0x?JOK1TYMZT5-qE8Z2NXm5Gcu!uD79vlN z(_nQ&nN*ez;rPo)NJ_<9@Q@iQ-C%flxCe%Eii$VsHzeI~Djk<)jBq_HTB&FzfUQNS zeBr84tcq=)=Hy#sW?FZ<8Xw9opjXlY|G7)uSXqK-WDzJ!XKj{ke9?TeAsdy!)c<0( z9~ye8*Bpt>M!@GH_#lhE{xs3NcBb4pN`U2Uv@QLn`)=-p8gp%|vQ?ws0ztnfN$hE5 zjN55`q9)Bgg`dGhYVZ!Zhv7x9KA!MSR9sPC)SU%ITb!}teU6KPbQ$V)s^t5>iCF1& z0?j%?D-Xlg0xaBLahj8?Gnwh_OEc4ltqEf_16{V8`@}*`eC*L`a4Xi(pOExHgzL=3gzQd?$Yr+k#<{CRP}7nkI z7>c>h{P*eECYMTS(c5p>TF!6X1E?YyH{ zSeYYf5{TImk-HiU3S0H1uhdc%zc_;7MW`%h;i7)TWj|2BdL#o90T7Gea^$F%Y#d5Z zNYbf1FP%DyzY!@3#tRHgH&!(a`BK5kSP1kLHd0L@H26)pND6aTBLVvfU{AhIh@!?t zrz6}vTOj&4jaTUGtN!OW-z%!=EafrrE@olc35~Zh?+M z_tSh~NG$>*D~K@0k0hu|Vkv*+g#%H_f;PwEe;<{hf$ZOiNBNM$Z$X$ckJ3(+LQy$H z-dNjF>n4d=79kBem2)L)N`uuv4=QsGjXuFtXfKba#e9B71>oWs4WC80fgE@lPPjb$L@rI5^tPi`uiDKhdW@<-F=i>vS(AZ<;g`&mh zDV|5RW7S#5cg&=J7|$G&jJ4-3XK`K`NZz{&dLx}ht*cy~4d>tSVfKn>se`!1O2TTc zcK`^6aWnCA*ki{e&hMjISiVH0{YC?^;9X1a3%g0M_ve}Wq`F7rAkn8k#*F03g>Hmx znDTUFx#>#&-n(ZeggM+>)TwJB=?he^H-UE8)3oMjVXDx4&$6yuT>j%2ESg|?j?PFNP`j`%KI?g^aZyO!&| zxdC5l^of`f56Q+`Y>uQhR4a7n#sJy(EriGZT0p5BPQr&EFW6a!-E`eQ;_j9%emw{! z@HVwRUf)~V$#by+`|<0>omG=vVlh=TD`~?T`c;#%?qBkSMxJ5pva20M5GRLc#U%yV zXy3p5GmLgFG1Q7KyZonz&aUrk1LEFfwp?EfS*=#FnWfJtBo8ayB?2|v= zjA4;>w>D;SSmhZ|ZFH)*rk{i(su`>HKMYX%H0=V>|nH105Revx`#f2`_-)%M24 ze=6;7ertq39&g&=D?x>SaDR9po?DDs3acd8NlQ35T6ssnBoAVO?oLL>w8UB2o}u1r zB&PIvHAN7md`Y`o1$-;^`}mQXxlfz95gltjh3ZWH_{^;x-;jp{TBARLPFS|f+^rqw zrNZTN2Sn}vS-E6eZwfpESs0lM^t7O4d`aQx(-Fd9>6+g0DEk7$WPT1rW&k8o{PkXa zE6K*7Bj@+0d1W&I1KhAt8p}DQNEPM5t3W)B7{V*N5?bIfhJ0*@X z8!ouOM9+tPnbl|4r5nKQ|I3}q82AG+qTryeEWjIVZ$J^2o!EOlqW8&2zQu$c8F@nv zA=(XN>#vrD5N2<=2KCz3{Edeyb%J=Qz-PE{&h;h82W@Bohgm^tXIMBDWOS%^@#p(t z-dzTWl-2uhY4Feb93N1GnVCw@+c>o1TXcTitZ4TJJ~m9CAc^JJj(RV`Fkc6qu|d;u zG2f|+v@glU=%XFL%fbIfoN%R-VZG+S7}v+36k1@`@5-)sLDKX@{5nO>b3IH2X>3?D zW*H`Y9kZ7hGS)Jl+gK3WBU=`9KfM)5j&Lk3hmUBR{@vKU!D{eT#BIR{)4!g@ss%T@cx%N z9$0@?d4sVu7$2?u4>4+3|6@;>o1sMRdl~kUelEJ@dJ1_LMuACfl@8>q-kfp}nc=Tn z>gzrtYJ56Y(vT`U&}4ii!6Q@Lhe-IoxddX;?Tw<(40>(fy8q~jE88ENGxbsWonk01 zdIoEQRBh)#cQ>1AKM|epZ!sTAt}hdu6}iX!PT( zoRrCC%3L*M0e8lj6s5EF+)Qkoa$_O4d!s4mnZ?pD)laZILo1)p%QE-$I3(0$3`?5RS)H{ET_K!~z=8S$Rthh-YfJdf z6M)~wPZqJX@cK#IYpt9o6oN5KS+E9qN|B#bm9f%_Drx?xP?s%HI(elEq|%M?;7D z9~r8Ab`9_8&r%hVtr2#NqyO}(G5YhW64{{eu_hSH$ zL=8?;wA#{J0W((ZVyCQ`X}B5;?79v<4ifx1sR-<#dPMcRm^BW&&(NR_WwM(~G8QtZ9m(=JL?I zq1Wqgc%rpZ{pDG*W#|+Pf?qTpy545Dc9v8LyTlg~ohs;xqHFMkV~WOD$9es6Nc*O_ zRfi{ih84z+K5idt?3l&HC= zD;;XZjO!R)ehoQ-5UBQ|URi38+H07b^q<6`zjY}X71Sye*ct>J!LDyHbS0dk8HPGi zW$mAKz%rfwS2S#DpI$v>FI1Tr`iYfK<*WZAasF3mRxn4$S&=N(6*IY!l4z4V#KY^r~N2*JXB0fHsAt1f| zMql(NKDOw%cDirjSTNz@GphOEl@nQq`_H+OW5}EE!w5EzylV`eY8L>&rer~8f0cBt zjb)Nua~r0bUAw8nI_x;1=ve9D^?4u*!CA0Pvw)t!umE>U$c$mqsnnRgDs4O`Dza|Z7#bub^xhkJD!Kr52p)_Nrf(~j& z1_BEy`6?2vYmB+DS78iM-xxjd{SXWUB9{yj|E|sS+Ml>GbU@^c#`DCT)HSud3}b2% z_R-^6i`nY?vq%sEd_jt~nur|YnX*tcY##AG%5k2?WYPu;6=^W^WmHl$W8GK|Y6S7` z4L)hsh#9%&c)WjUG}LPFglM!6F_63yb#qe)Ixw`;NyvGIFVp=l%>UD~`L0NI+^W=W zzzqmy<$ANdZfmD;UOa(P)+t^8nV45W3NO7KyT3_Mc-_Xb1hY?rRTA}wIQzokV;K=) zw!T5KHEM#U9(Pc-`S&bP)5h8a$DHoGZmtSpxN^LW0Lz~-~oaZ6!RCm}ah?glE z+To$&{3;5lx|?}|2Jo;vW_0Ac2=-)g_Ma~v(XILVoF@B%qZCJS~Dgu(0 zdIkCiE+_-8x++qBG{jWTaFzstns+R!Lou0Vj9}RLcGuzzO7pYq$RlnZ2mlAS8UYA1k4k>WDpl<*i;kWeuTVeJ4md>zbbtO z$B6LTU0L3 zs1TcrXTKiZy(X z^vRQszmK`wa)=y^>Or*;^9T50&g)m`>yIZT+2gzU>7wO25=^X{ ze4b|W50U7hpD`ytFoj^iKazPft1s!vQG~VPnK3QiqSveD7I!%vlXtN(7!pOVH+aWP zv4%&?s%Gz^$~Dkp+gA`_N*<_(C{a!~(_cf&-yjFcu}hkvVeNo@CAG2D$F#{Z+dzn* zqo4T-9G`LuybrR;Ml~J);fyF?|9kzl_mciT3`KZVBy1p>V~==26%5wU^OSSP=N4Mu zWP@uI{A?{^`7|TbbpnS})lYoQCfKz_pE^q<4Et{uL*dIhahRtsV`47q%pGOyuIrp2 zIQ@TG_(yaAaQdGX4g)@-N3oIeoJl>Frr3wK>Ygy|wh%63nWyw=fN_S@nYa1;uNPjA zE*-KMJmxbdrQVsPD3u~p7*X;vJnieT*f?8a4>_AeFo9rV=#X4(>`7`ZUK9w8E6KO))&L#MUCS~)j+ju1kel^Zu$HCJ02`CIeOn2Y*%(J zbn(>fs#I~D!?o%%(Z8tp5~}pF{_bS-5q&1B^;GVe0=Xn-U)7PW@~!w3ce%1~0<(8p z#>VO})Bi;OF8T=i(;zWwzGAehlNa}6@z)DY9rt+`;e&67H!EE`M071`THTf<;pxisgARR8jy`en+PK+<{v0j*;$!!&J;-6nbMx@!r__ z<##g^K3yO*=*?19v=2YC@aX+ru~fS)LfdDPZtdHAVgwiC&Db~TA-#_Y5^ku$i{=g{ z4bki26il@`;x2Rt3b}K1P~9QR$r@Q+zmOg)u!0EV6wkqU-bCX8TXadI4JZR;P4nv> z3BU9G7iZ1HnG(!+T6lIMFp2b|u+i z4>72Ye&=^JsoCQ#H`D@9`6I1yXF0CTsoTYWmN;F%bp7HV@;RzO2A14nq%9ReFarprs zk5hIganDR;587wWbG%m)sY#v(RbFbQ=n6n8VJMn64QD$N_=L{4B(r|BZy^Kipwj_Kt%|<@b@!z4bC&pn7 zX?H~OBuR%T%8;zd5{*$o^KQ$kc0ZLUQ&F`W+oHR;7ChQJM>_oJRPxPjw{X8(-XRE| zt92d|{>E}93T5z6JN;7c=SGVO)^AgzQR%PY^PkcpO#HuHed(uAH%Fn~->_Q8x%gRX z`J~t6Yu?mmGaJv9%z89&gB42b{fVSL?o%^uFNUz{MV+4I#4P3z|&3-$&nt%?x3aM0@9 zF|2s}DVIE;uWdHRh5++PDlke!aSiR~1}F=N@hBKU1Jd5;`|Bu}y#@H~%-`}|HO>f! zU{J2dR?z-okiWjIcW9|`ExTbuF)oicYnTDIp2T%8(od`^D&0HNRgji~wQaSnU6JIJ zmK8GMg zH|5!Jj0MAR>gyKmbE;jeRMw`FiDXi@f5iK-NCbXZf1QPOS{z z4yJI=+1)g&WN#X{)BGMZg&%|uCM7ylCDnARN(4z(#D3m2gO&VYT^Pc*m{taX0_@@- z*IijlQPPBLE>MMNMyc=>pCHtGeu`>NSoTo1scZo*%Ey!H$qz6OrJAg2z@jC|G0 z?kBeUhB!&@kZdloS=K6iGxl#(`KG1q8+$&w$dP&ywHHzB?cF~;7-CyoicvCm)midN zI{t^NEpTFQRoZl!Enx87;Jf;3mGct$C?88ipps9BRT%IZ%q^YlJ*0wsL;evxp!R$Lc+fIDTB^P*OLR<3(CoCl z95!XbWZ@3xe{)Q6-XqchxAn;%D9^6W?IeYy&sOTl8g3Ot{!K*->!xJ?(8oc!{8GHo z4tjmx{5IeOz$e2@+96?*$&mQtRvl9$fL?Gv34GMvlj)YP%Dxd_{$9T98zngo#!HR; zF~$@yx|`UXT^@VV{K)SqGr`P{{c@Lu)d2L~i2=P39b-_^NFkb+oa0;OeQxTmXqUo| zA7!@R`&?j}75lvzBP^Wle}6YLKdvY&vh8+>^orTiV$kziFc!G+gl~Iqcj$gY$1aj@ zn1Vu7UVwZozabdNh-HxI2D-QrdZQ78i1{XhcHL(VB6|cJobkW&+T(e4o%p}=njY|Y zo?U0G+p?%z^c@pLp^j%L8oCt#O{)mhV;2m;Sed7Fy9GV2JbzL)A3r2J5@ZKpxq!!c z)e68+pcjDj0+?Mu$Sr{Rw1$#T2X#MT{om|b=A<4a{|qoJz&d*>@Yjc{<@S5jK2AK{ z&6J){qsQlu+x^Yt)~rbvJeGVn6a3C$<2n=!OKf>B_O&tR$`f)axPzwH-u*!Hn^TP* zGn#u&=c{|cwN6kVB!Be7l13Q0rN5IV-Ma;;SgyRkJu7UOJWRTm28RFm@b?naB{uf z#DBk)=Kgu<@sgQXpOl;8YUMgDt7bD~l)CHfn5q8q+hbE}Hwd2j1uHSH!uaQ8pg}-4 zZe_uE{p0)U=CI+h1Q}GAfY@ec3dJ(GT*AtIB;;zE8M?o0$JXD1xVg+aiDgBtE$DbALVwVehkOE5q$ zzY2%5;&Z+2waDV()!wT1-9G~nO7bh`=6scUWa>1I0V)X>_aZFBt4lsOOh4TfKcFCb zYJU|Aq%tbqF)EGU?O(CDXQj#i=BZ&Ufos8-7cTb{IwYP39@f(a-~W^uUfMcNJd0km zEQ|16;$S6VJW6qR71Pc_7)alW3^x1*g;?uUuN;_#amCjK0Y5Bx|xH#6sJbJB$6$qD+FMr@0NcJ3!v&`T(%tA=sW1E+} zJ$wb(^vIf(-D}M60KNI-pQ(#XbE$PjN^y4*Ea)ep{)m_`(z8$Y5)`?CKv{-?&qvM_ zNip`P=M|93;3_i|8y)NSU&y~~0ZePbT{nub53=ii@oBE5Q#7wGLHNRw7x z%5E!ufC~&G@4dFwLr{jxVCMXi7}OXIUbICr=Qe4=CmzKl!+(C~Ym>Dc{wrrn-Y@l7 zUML?C&^`HF+A;kZ40$TiFYGs7OHQ_8`e30u7-*@ry-V`90}#V(3b^>>_SPC%ShpjK zpH75FwJE8nBH2TimT4$cxy6RoSW7zlnRGHXx>sRc!61SDHFg8y zjX%`xn9JTCHAk)jlertg)iYwo%GGna^hW8^r#d zOx`GX> z&pPiA4r#*qmOeM-)aJNF_EDDL&?k4zrFqN?j?(Ozew#J2bgot9T{PuSo;I;YKHn%} zAZ|#v-%yxIJtN;*+m0?QG%B*8=|V{4|%s~ z&zO4)ON?SJ)`lFfYF|I2&l;3YUWE;9jYkMyPGcugE{vRw-o+b2FnpLIe++I&n*R7~ zc-f-e>uV-A^4Z1y9U;T(yq5#3RUHb^DYV!sUDNj3SXuHZ^zFZS>aa-MDHR$AR#S8f zTl!ODLNi~Dq(eS$v9jjqHf7Mh<2sJK8+WIC7Z_-6#zW0P-4_{!)$?nLs4YnQiTi_q z42SWp0!t29?ubFLO@bm4y|scbQ+v{y2BhEqv5(4225&vQ*RH;v;g9LVhfD&jPJv9o zQL}_xmStOZ=M}vPD;gUDYLz3;MqqQ%c2&8ahRJ3a1?K+^7a71EuyW1ii`W*XKZU}J z-biwaZ4)rFsjov$rqC)j4D{OZC#d3n;;WDwnMu0v6&WJqsCUb9*MQ*vhpDsvit7Ku z{h48aAst}o?(XjH?rxA!X_02=?nZ=>E-8^vVrUSgK?J2+R8m?l_jA8L+<)M#^Iq?@ z&faJ5=k+{qgin1((Zxp*hdFWV_5d36m0*0tDdGv?aRZp4ox&`YPG5l{m4gf)-z|6M zlpm^LM>w**29*r>Et47mW{d;AXOhSm2-XckdQ|n-!(G`xWvBVoi0^qMnJ> z`+=bsv2ML5r~VqVP_O*;_YhlZmqfX}3xuB{NHz$WgV zEkEnm=Q(%&Y$BM590x=sMGd^DTp@bRfzdwq?D*5q2QAkC+ zIMSLA%r8NUo2aiC4qkbv*5%N)aK)pG5pqE^bJNz6MAaw$N+2=hx1Z#gwGyWmGH$8U zE9GRdCwt2kN_j=4q?S$zLQX}3sd$5MKi2`MA`rC4kLpGSA&gW@G3&BRF8JOfH3Z%$ zRgda}ugVFW$x9oFes$(2A2jn=V9H%7$oQmmaAQ*N#%c9hT=O$4mrqI2a{9(8X?NH? z1~kO+{bwT*5B7N2TQ&4fn(3n+Z~;`VAx^rarsQJru7e&+>3QxGxwxG@<~`DKTe@lk z85%xpwN)h^G#)m1ezpH6KRdXD9(K)}xlUU`?-1_0f!Bxo_ zUIz;#5EN5(IMOtTGc>0rI@fjpF9A+4_8oLn*tS4e$%?_$cc@)}qsaKAhfQ8(nDFz_DRsEW`nsxA9~`;&F^ z>z5L*?v-&dA&KQ!Go=5#(ExHuJPqM&EEI&8&8|;YMZyM6?0tA%{qRisa8l-Ah(eud z0*-24Ph5o!?6`x!PI6cs`)1%V9ha>ZH;zk2Aib^jH7jH(iWN(}QXa>G(e=-fZiby_ zdJ?l?-@c5glBJTZGY9wAxGMR)8zvrlrkuy~6RE|R=Kp1)m3$jfBJoT~fx7jyPIjMv zY;=fkk)iU3nKHN&1zopvgd&5QhSSr7-m&sn*o2jHnmtrlw)VYr=3K$ZBRZ?elVVWv znkc~?kIz@^&z;U^wk|p5zN5p?Lc!x@AFN8q_DkGnH4@TYo{n+ZsBdR?8jHTeYNo02 z*a>^FKx$C-O{R@5pMH`Hq1eLCFbQD~(VS1cke235L z2ED3Q{f`4=f|sw>-tgu;P2IKU!qI7MA*UKjqPK6kr{(XR$uLYN_)hHYyj>m{!V+{7gE=dAEtc3#SI*vmu8p~$ zl3z!ZCvC!Kx6jk*& zp%HE{Z7CN*{(!~if!WR)pn_E_S9QH4tSNs}uYyhY{n=-|RW{z3l5qva2g1mj?XpipS+5U-n%4Uo{8G0sz|5lD!Pq?4$v!(gNZLk!lqp=#0oBg_%W0$HGGda=CO z!$0hg#*4Ko!O8Xl3*fVbmP+bOrcXOhYz&TVNQ=K@)_9mq+&qnz-#Yr2w1S3y#L}z8 zoc4_xr=FFsxIM-zuvDWM^qDBf8WK?*;#|i_(9C8CU?F5soW_fX!{`Wk@4p&7`$~JT zV*=TW>OUQK-EFk)pAW}=&DFPL+#%QV$rQ;F{D2;UH>z*@!FHcqxrw;gKrCiiOJ0k$o`SJPgBcb|We5f8vN}f1r^e zVraW;n=b^&yOJQWksnN1os&+G`8# zPJ%PuJ-opzd0R+r{Ho4Wd!f_?<-`4T#Q8am~ z_Y)|zU+|ix@~LKlZPL5&2$RVmk7(E=N=5Vl-fi+kop{7xTz;CQ@1zM(%a*6PKbf1Mg=EIxf1))EeJMZ{Ju= zYyrRZ%|?f;7hA1YlVQ7+t!3(c)P6Wlsy-1-+XqdX5xhy3f|JDE{!tehYmPWnFb)2J zq6b1d$Sg1Cn>nV&VVcvNej}Y^t3qN@`;6qz7`HpWI$Ok~1k00g>o_o5Q+xibR)T_e z;doLi1;MBYGd(&wHp21xd+9%|?>`!1J81owsV>cVHJF~w$6V+3RsV$v+dZu|Pkc;R z2V?@nPYChplF=thhhL+$V|vX>ka#GVfRC=|#i6_`V!bopE6jMldAPq5#o{ z@t5cZGOPzWt&C1TAhb(Xf1RsnLQqiw~!6srdnnrSCu5ziSGl zpk!C$t`JK0ej?KU#Y)I3_ph=4UgryBb1;8c{3d{2`T&}G zY~#7o!A<~*q4(k9U_5PjKGMx&Sk44aHt5Y1QYIvjFsR5=7zwLPZj%sf>tErE0b?UE zViv{=G~~+Nd+itqdWxzHgM{k!e)0fpgjTQ#v#ou2j;~_YJia8O}4Gu)+G+ly4GWll>@v*I8WkY_|Q{NQ{j8fXsb6Kr27qYpO_$ow7UODn%yr?zp{? z6P{E1n5yEm?w}lNli_Z1O@c!6Ca~5zz99o`ODf8!7rPZZc};BX1O7|}W#3way~#GL zh6uKX@)cd}&;5!F5s~;qQnonkc99vl*od6uA%X=a7yf=BJi;D?CRcz_F)iIxmlNS% zv0{^HyuK1L8q8ho%TRya`CFTS<&Fb`PLWzhPRl5nh7(`v04O|SS{Vu5;&_G=$ijRT z?R=%|jj|t4HM-hMn-4dR*{YGtCH$+uF^H=NO|St=*Xb2^sOAjNty^=Gu|P(s5M6d4 zw2SxJ30N(3=^xeH$E=0@1}up1zwE8Kw{eg1==_v)7eUaI$MPDfe)tJJnXRZ7EdqXg zersZ3*jd^B>aJLd!|Q2&ZB^RBYkFDf7s1^Qbi{-^@6*;;hd#^9C?#t)uhFXuX3iL0 zyHB)zTUQ=SKE5&EDc;pkznE3|@KS}8kxo6Uf-Rfs%5K&u$ls@qy=o9^;F1&u)euv!o}&V*I9X_W z)yY}-LmNS`6)K;R!;)iu2>p|Z`eaI*`#;X<=Rhp8<=4+vtmwh^sfd3lekVw z<1paotJ#t6gXVe05g@S+j1o#3V16@#+^Sq1#cbbt{W^4vJrrgoy&*j&T~{fG^$*rq98AH?B%s%xaFh2J8q6^vkR-JsDM;dkb;^)+P(H$#`&)0DV zx?lW|yLrSwd}M2+?;ko4?XxKNrwwZh6m2&zjrtH*sza8F8OA%k@mF1=ys1c8dA^wVH%A4V?S5+Eg|-TBQU5^SdNjFBnr!$*W8wlWd1-)V1>W_QO3&; z#P&IxWafveCm^Ir=rtVzo9dxcJhI`*9n6(3_YFSF+G-QOvhX^sw}H3s6>G@7{yG^c zqbj%qg(Kv}PuQ5X`5)KffdXcjwqfHo}CT_qk#lshv3$0E~u`Z{UXTz>}nY39WzVaoBv< zwqAKb3o)j10_IHC+|NI%#(5apXQ3S$o)hgR*&{I4!Fm4;qQjs7(Dc7SbQVTDyCysV zCmk!*S@QhDi{eCM9JX4AA5OQ9885PW=$L=YIrPaHm?&`PjzM$9G$AoKW0})kzKKQ! z>^UCgEk9+6%ozZv7wnxgq;Y-|vHSYJba2dQ;@j#4VL(>L6D5w(|IJ1b}CuO6tH$s|dx}(W|e_^Y_{Gx{P@3 z4b*8|f(bW|^L{+z#5LZe9}hOnq~y$9do$e$o57q;t5hwu{(SLrS3h1$B0O2;pWhnm zeNE09la1}Omug0LXw7}H(gf&cG-l%}KzI7c7A^37zjgE^gT^GH^_RBXVzJFj3zw%; z-~OyORx0oP{-ii$y0sd8lq8c@#-=;-ep{xIW>7nDG=KWZ8>xy$-}0cH-=Zb-!lvrZ ziwGIBH$TKYSgtMPRTbi&b$kW?eWu*9A3MO*(>VO+@WKq1h4$u@wuQMV6!8uUO^xid zK~GB;f@CF^Tr>PGGP)Y>XSdun$dzDrkhK3!Tcz8~B_Vb<6|*DPk#{kSXIAhSec))P zFxa+%Nfh@s#K_9p$Xbp6vZ*ZfsS|NL=YR$yZG83yUb*!t$aI9mFIF87nZD*F!LRXZ zM#a8sKPJZ6ciWNhCCf$*J#7c+@Wv?1l(~H<0zysnF9y0a5i{ux0Rxg|BU%#^irZDe zQd1A2+Z#G})&&YQaID$2+cz@lHgdDII*?-g;TX2$1HTfD&HikSWgNfCM+)4Z6lE-E?D#QjA4Ag5YuOxXp;%PNoPOcMp~WlS`nYAW}xu??mP zCzTg$lG1?`nE^}<1dOn6!G5;9t_9CPTnLl`9E-fwIAd6 z)x)_8$JeqGg0L8u>>3fkNSy0H8&-3lPh|10C}j5_NmEDN?yC&pRjCG9ftZOfmb==V zjX=+-D%OX;eBYF<7R1amSRG&%^^x8eCzx>GiquX$(omnM8(d2M;y21ddOxw2uAPdy zu;oE~80=hC1f9XpYaMISJ>=*o>JW2dQqMzVC4bn{W14e3>=Qxnz(i*9j<5e>Y=O+0 z;7qYCw!*aFX{Qt{_0gt6HIZ+j@`qSF`l?<-gq^{WgKxNTu(Sg*&?+s>Wq#BYn^~^Y7L&J3bvFzIR~T z93R+<}#MMZuU+cS#nB&FxI%9Qu>zQzto1)e>*ARUyso2FgBK=ksW0)tn42;gqe0lWFZ!DG7lRIH$+{Jv+^ZAR= zmwQAs;SRPstIzuek9O8)ml=q+k4(R{(WkmLje~0^^b%g)~c@HdN=J#h9>W>lz4OqyF<5^X7Xy(I1bwg*C0M z-=00m7y-SX*ssQ8wllry?;vQSMM#$d3m}2YE8hTdYUi?~1avbbCS8B!!+YtERZy`x{d&(Aw3xXAQ>dF0RYvM?U`^Z&nU{REl6{}oQDl!A*vY1cjg_Q|qk zNEaKv4pHL#iR=kZ)_VDQWOpDwpTXIi2%^>C+k!bMZx-7~MB7ZG+f8ih=xHIA=V>!; zsseqKLHJX(C#vgyVXKk`_?|_4cz3YXk8rBP`K72MB8T^cjyY`t_0;B>+y0yzF(?u1S#Y4g4}$jZ4yN= zUj2p~P#ZL2B3v0BPx1&ElRY^BHVEtKySd?up_n_R6&LyxLejs?@M{T}bh?Q8Biz3a zR) zX020qDA=30pi=0gh}Pm$&24#LE%2YCVRI}Qstys`{XSYIW2@K6Wh9|LJT=)S=If13 z4_)tic8+!}mS)6DDJn zb+?6kd3QeGSts&q(vxs!Im29uc|x<#5?Kni;m0Z)g$&h5K_Iv3F)ef71?70^@@+!e zhU46nJA`W&gW$=;e~j8p!)gO=`vWr1%c&CQcK=lt9e$zPkAxniP!=5iS^KpgF$&uF zc4e6(Y7)+=QxIDemtAUCT9T-Ld3o!yDELm`JUv+1tZ41~$4o8QA&I_f7vWC+dypT= zrj=qnQz_0Rdb&kuytICD5xn+A#$KJ127jy>!H@YND8^1R9k z0Pm#AIu=f@$Gfx~K}iVrnD_6uF|GF$ADn&g2o%fM?t+^}KHhx@c(=^Vnk`C|!SmE6 zp%4BJW5k7znX?p7O$c}vm=8HXRKSy@sL3@LzwNq1#ES@m)^O1%2-KqpL+mH^p@;;Z z_k7V}89zSZ8jL3ljA{KQpttY3UBr0nU86%kyf8{Mwl#W`FpeG)EnX>SJ~Dc)w!g-6 z1#j9)3si|iDKYFg`^RLH`1sDs3YFiaRcB|3xq?VK_}eQ3@bw}(gEXVoYYTUcd{?>J z$d>vsRy*H`iIYUTu{`gB=+x00sLlc{SRMNFtW*;EYsVl!!j#o!|ZGiCTrsMrGj5VX-{BPabf(Ea+dNb47i;>?pP zIa4I_7Ddb?gIhK6pd1ZpY?zBUf8UIJu4pZSkiEVa5ncJ7H%~OLj;FewG{Wz*SJ!P3 zE(r~uj?lYJ2M8Yun{k4YYDIth4%xe7lda6{`T5(6J$|DK&rdNy%}ohe$SV#TR%|sL zXkpHf9hhI4o?K9skXzx69N-=%xQ;*<7~=)+(_pa6d)L}Q&rh0+=tN7W&AIRdY(Mu+ zDTA2zt?bY(A6MB}Cq%Ub_8MA#8(GT!LD;pH?d@f;hE`3`0Peeq(a-PlFUHaf)jvil zw+C8Rd77Q>DY`;EK-$8?)7mNu(bG@87)LEr=!UF7M3L#=-Q*0ylm6H<>0J}chDx+6 ztuM?PJM%%0vo=W)^v^X2Kk!HL3d}?hSvHf^uG_O3yecIucDbt%BjDHkYPjuvv!IRk zZNX5M5fQi7`cANbmYGUC&@rXTb0CA^wh+cu_Zv?6Z&8lBI{PkN0=wBwSB_{ajKqpO zd(zF%5@W|j{gNFh`}w7#@AXGXx8Spl_-vhXsZ70wf}P%Mn{E2L=6F(icQDAXe6A^fsU;27JFG*58Lno zv(Vxn|FSy1;A=pPlk;Pf0))8Gru@}_Y#OpP`G(l;<3F5O$>uNXi^<>)&KvAEN;!k8 zVzYFG=v)&Y1Irs;4|b{fOeaG_J$}uY7*IXTHr5iJ5MH>8@B+;Qq-X%ui+uu-9&zD) zlHq;>bP@EIBmrJcKN5_Z_PbNHv>-o+JBgdGOL9^e2|{BsHZceTqu89XB$1T8I`MKH z+q2{J5v&J(L6fer`=^N^7&myD-7OMz33@vewB&iCX6ucA2gD!cH;_6#EGLDoCLAko z6%zLH1*JelI9?Y46%I!v2pbH+5Qi*>5P7KmfiE7&Leiw)I)M}Iqtc$n32lK?w0k=< zV~n%OCk;rPOA9~Gr`6MQ3#d9NynBtl4y1hTBiP* zPjP7x^UPS3>mk$I8H1Rp_iQJOmV7@R?wCGGb(|=(PCw<9lb`z{99mQ13gZN0IpgET zyjv$cOZqap9id(;GXy$&R4E!U^*{kk*GF~fOq4rQ6gC5oAi{ogV-vG_yCq!CXEhb5kE3@;}PgX4FM9^V|YO9|(e)^`r z2xMle$5D44vLvyK*sRS$P5Fy=|B8m%O`e_`|AJ1e-MK;>n01 z5sRePbGf<*yCfk8xgGlO;61ZpYI~CPcwfHV=R+NCAIAwSIV!XI2V;oU2w9tcsQlKZ zbpmW=`^J4np@pX-f_#fR4tzyTHwwD+Q%hxd!-%C>hHL25N+qA(f}_6K;NGuHb-Oy7 z(zo*B|Lm^K@K_wK1D9`hfFPv;!j~~HPY(G*w4IlE0pjpJ)R*} zNylpMCP8mBSY3Z5o785tCZiS2FC+HNhXDzRFbA*hrgZ<|r~3iZl4(5+_eNILQSZ;| z{Lt`nETKm}Y$0*Y0VVWTcje`Bt`2^pE0jtgv!!y3bfjGQrQD%1GeAd|Akj(-8PsaNkKnXPFR5>tvWehm*sca8L( z5!@m%egFZ}?>#>PKQ8TPKgxz+Fq<^7ym87=s(^2c9U=wdiurDHPs#rUYDuT8h4eBz zXI?9qwJw6f3sWCE=?0{eC^Zd@&P=qY5uI3+7%2D1Kuz=Ld`i$XAIv5)4@nW&bF=JyBs0;+ZZ!2;? zRfFwB8ipib1JF}lKyuO62}dZ$9(potFR#BP1$fckTGL>NIc)Utf5gu>KqE1|DcdFh zr1Bf(%7&{jDF$BSPaR3^;{=q8O^UQhc%mae(B_)MUl4y{qY* zyY$q1;(l#m!*`rudZHYae+EP_5L2z?m7hp*-lwAL9rf*o)$&lnmvfPPnXQ739kb@( zm=tBRWBTo9@rfhg81C!Y%gc{ywaV;@fy9Zek?f?0Ps5k=S9h&it50#Gt!U5WHaqjc zvXQNG%n9H{}@D2!So2oEcwCSVU2V+2B$aXtN!Xj1_iWAu-52IP&k&c}{*pFiWx zqtKopu5tH+<=LiBsa2=nBGY;ijbBdGxZl8DrcQ=|Sv+BwE+_}b_t8TZCZbc%A@u^A zXBnY^S)4^i)q)z-G7s7h@8M{?XO#k(dBFe9x1=B2Veq3Xhm=Qym>Sp#7f8dW=Gh|<`TL7DSq&#(elw~97;b4_xoXW`5h zXh4BtDC<&x2Hk#~L9&v{lz23@)+ZxsbLm!KScg`ST8#_L-r;>3W*maWv=0i_N!!O^ z4oU`6ZR2y;89 zScP^LixkPdVL>i~V=)|P%2onVBcLzgS*!JXL;^IVDSStT{Wc^uGJ?G7$FG`l)MpD8 z2~OYHT5-Px!?+9%to+R>L;(K&NfgZugY`3qL!}&`@O%)-l-2xR-|T%k`{rx13gRY^ zo@|NI!BxcFjW>(B?f2Z<9<}C{H7X~OuSzlkbzB)!#Ua-DmS8m0U4GjeL~{e-3wuKD zi}ur<<1Y$fV~N31x`+q2rPEo3fA{Vl<4jFm`7hcol-su1WZc&f4-Rrfp89Te^<>Ww zj%XtiS0eSut?VGpkgp=@R4wEEyqCs?8#!UOMRTl07qnvYOMBAOkVQjS?kFWFVU6Kr zd`kT*;d7IJ!*%r$>lLOP)kXbq8LCPviU$9eyIuZify@nlv*r0hXT`Fv<>gwNezm&& zABZF2eh!+@Tm{hvzUa%h7}97Zm$bqvJ1fBT&rj0=+_PkY^No+6U&)J z(b%h7*~# z!UpR4NZIc!-{;0KMr1IGpz2wATO8&hT}gKfIRIsOeue&&-c8cmhb#7X$7s_P4y>P4 zVOof&YJyI3cQZQ?n5rtX!jC4pgmO+B_o6ju+pN}lX}b8^DBc~Ma9*))37*9K8T~JS z+;+Bmt*wVxvcqas8JAyt_O#W@_;}INvs%51y>wM5zu7cnKed!{+@g(lU>MqwL?H5u z2GHn+R*rp@P4=;I$7fpL)K*CL`tO{unVc_ynUFwk^i%Q~$vRSA@@$2MQ-kIisqTYA z%LmstNmUX+IKJU`r5QYe#ab6abKJG|NVL!0dLmd!9f@$O&vK9^wR{8nNYaO&jr(S6 zXMoKc&&`%y35y;5P6<2T#y*T;<>fv0j6pko){b!h8iY!@eq+oi-Q%PW(4o=ciAk?vuh4A2QM)~&yC4u6oyDqCV6 zZg(-)>Kvwd--8GT4MA*t7@~uJz7;ylbl#e3?r{L6QI})Fcx!Np2&NJE)ZtzWptJqN zFxANRfDN)d3axkXh^>ADdErJMSAkg+8L3WWsDeOwG0~3W!#RQ9;U#Oen zP>N^BCWGpGr6o}Jkvv>zi6KiSOUHK5yyVQCCG%%+g7Egn#mU!gHlu46rY{#=ooH@n z{0u_K{FAKpju(3b4z z0sfigeEQew4Sv341m5NI_<%OL$gKCatd27d1&V)l=0SHtPn$C8Vupc@F&bMK?Cm}g zdaxt0sc-F|vV6?NGD9Qed2G(yTspn8JlV};q1V-KXZe|1R_ZP6aa=?%MXopl6{4e`>N{K){}v(2#KCMuzk!-{v&G)&+>AofTN zC9OlzDm)~F^E$g4K|mrP^6_W)DFKO9Ttx$^J!%w}F=R9szigE06z($6U($f?poV zGR`1x%y#60;okJsnc<`H=bu=%Ay+qPaqQcC@PltIZ_%s9CtMYn)XI~n*Fj!`dna6b z{f2CcU_6Wb?)Y}!ax#F@4_NtCSZ>>)Cq*+D>g9t4ah=s3y)UGR)JcoS4@+R#sL>nc z=ZcEM+QAwhv%#m8RO;9E!(q3i4p!JkqhT1R)QFo3~GwV25d-X8Pic| zP$!|9)g7(*j?=qxPJkaVlIi^H=_wJIKXxZGabN5=bSiuAkDA#nY%|~KCScnGX(k2u z|1NS&?a}&zLg@3CF0j?qvSSR=ty<)v9(-#zEjD-r%58&L7)<%uy;rM+987rx=&+{Y z+%Edz5GkJ$FNJ|r-{Iiq#k0Z(&NP7w)4KvVHaq}zrdUvSRX{mW%8^aNjb#WuNgZBg zO`8wfze{im`xW4Ll8vTC{Ev)8iH<|9spmHNv~l}d5ID)KZ=w*^q(!3hn(HiTa39dg zww(hOG<;xWAk|Yu*}<@nDT3%l;-9sc&<`QnXW`LX)Mf{nYuC|HTD6}Hu^x)&KybZB z)PE$Clj=>Irm=w?re!2F@8~DqlRgVGO)>5)Z1lg@m0z<)Bt8Og^JupZc0kcH(u;JU zufIs|RRu@6VL6DsJYSgh&C_kD}chJDovzXU`C%7>BQ$kS;VTIfchz|t4A_?fTb zeKTrx?|-y%O9;PlVfs$li{>eKs%`#-P)WU&LtotnFgSNO1gF){i9g|f4pd{y#DB@} z%DHw5$Wc^bH(A&VVq*hEZBb1pDQ0}K5D{eGeM0Xn)t5|MgTKwNZ1g*&7Z;JN$RE-Z zh9zJm_8jE%ubBmMeH39V!NKf5Z93EPGa_#ndsTET<;C4|nARinh}oO+Yq@PFmalad zs}FFbpgeYPJr7k?yKNqG^z)`y{tXXZa!OPjzXEk$qK;qM+f)O8KyYVyT*`i-&=dHs z1;w+3R#pA!W8w#8*|WFImX3p;2tAXI<G`S2<>wACYw1%B7Ya)yy-L zihh7NLN^k#2$HB7bkZl(kK8EKP=R7(e0Fc-elW_91Yz7TB{+MBYsdbPkGgh!ks$^y z_-`Td?vejL`=5;C-6Q`mhhg~~fsv22{QQhA?{J~q+?g}IX{PS(g3R=soD%K?<}pk%(#tpwQxLL7YSG(xoWRS3P|WWd`RfHvs-Z{aS-V( z;s4Slp54=^VrMtAd`7 zhJlni*&#hMh~5g0hrjljVO}4`6gR(Nh31UPumh=y*c-)b4vPfG$|+xTWSrWEWk~UU zB^V!W5$3a>hK!221oSeCJ$oB}R&~-C3XYpOq8%GyQll&3dUMv_T`ODf8R!pQi+;{! zXZR~T(+=D{{B(&gD&)3vb4m}O%6)VzhqEo}l>dB#^<|Sg4KOXpS>H~S+=DH1l{ay z+v7kF$jv8S=5)FCinLippLx_qX}LP;7~;cYb2A3pJ&`r%67|@FhN3vt_(CtxTel;r zqxH7|l25|ldb#f%QW4Fw8;~~V+nl_-8qVkn)X4~6JR0iZj@ZgzvECllRdq{Vnj2f`=&dOMq8~2bUo26o*Igd%Ze-wbEusrssDCkD`laHGI{_Du}FG zsWfm`EfAk$z_oFmFT9Ld;}vq(vJtaJ;X-@3VTC_huam(Txv+7!GjiLlzha}^Q>Nqd z^rvOzPZC=W;1>^Lv(O?1VU}V3zPVh&-GZwtm9XkJ*oPr75tYl!al-q%EAz_BerlU|#4&iZ6w5xIU(s^d+xW1SZF_1$5R z*(ow?k;_(evEUV|M`NFCv&G-caA|@|902^B3fCNaOPXr@JG^MUc08IbJ{BsEIbIip z14-H)-t)16nYnYXn$JW0!vwyNo zJK^I$;##RA7EE?4_t4N}w8)oKoEJ55$l@E>#7vXomoP2QRl8a?Pqg?TSMWPdzwx^r z!?rDzb<@T|nA3vNSze_}xWwum7;8a3K`we@KCd<*k?c8VJmYK>z{m{XY6r+2Ppa$v z*uZ%`7{4aP(;6WE>-3Jg3)&o2eH^u+@%l0NN3Wj*@{54ddT)& zX>iUEX#nSMSC-r;$wwNy$MWaKOB_#Qj!4uP{JG_CJf_g_tmhOW?MK+NDtn3{y`qHv zG!Qm45(19^YV-)_(n;LT&oB1BgiwwWK}oPqzute;{{j-OX{oP18#J@G}Tj!+`N97?xK6Z7C8R)u@%Crzv>LAKFyGu^%svOs)$)Jkq@86L~e+**K zli`9NERR?lbbG(qZ^}FO+YsW!sgG)qb$itjyt{TRnjmfvImxJ+jKmKI1P8SQQ20cD zImeg5)MmcNH50DqR{J)05x?|^=hDL^s;U{~>-58M#l4s`eKYlI4~WUE9p~c76kGo4 z{r+S6XDzu!U9d=dfb?IFD&&_J`;&|jYmU4U;3>EZLzX@MlHDWquKFQ4m0Rfvv)zIC zB^_ZeSPtLp>zkKZlr;u2R7>l1xYW^u*aR$yTq&jKr-3?mHBE~4+to%ljFnw>f=$zj zCkjYWo)3rcH?R|(}YbwT9>E5=)2&YNEUVq2`&^pv6NxA9G*#7n_?dAz?gy=Q$M zPX^@ks&>Z1vaCMDn@j^1pEX%NA(SLPIJ{3~InUi9_EU#Qr_ZKS>uycG5>acF10lI> zoCvkXGT`2$bTond$8TiSik6H0TUAyWuTZ*sD8nKf17Jo_6 zd)&Xp4T;0-!5>Lo;9@aPf9rL{%q%5G@jTh$RHREqs>q5wn%DI0PtEEN4)JH`0A;^m zxlonVB`(uQdC^IJkI3fY2iJO~XFoAjY(9Y&l?O&pyb(EELBZK1m?6_`=2Uq zgA4zw;Ng#w2DtqHiz^K$14DP#(Q+cQd!c?*ZR7Q9Vmt8$1KL2_uyO>~Q4_;*H#WBc zHaGi=yxhp-4v+={`W)m6!JOt&JS{S?Z6kq-H3^d0`;%#@0oUP5&8Mb&Ib_m?h>+mvc(A3U;m?f$(}(t6oP2uF zekPOKtDLjnmD{*lGle=E7g;8jvfR=I@29Ox2%SIHK1rOq^h)eDC^6pvaf2K6-8f7A*2RiN+%uaOE0GRXhr=T26*O8vcWAOV4_*>=K^hX=YB& z0CgPaFVeNa7gKNn13My-98V`XRO6Lt{(?ZJtzt7CzGv4#0_`XwV`~wYv?YQQ5$C~* zQv6-*u1}t^Rt4if+Eqc2B zryL@Ai!L|AL>IL$pfy#hCXYGoRL};WdYEaDm!@C-PT?0>o^t&2N86832ZlhjBnj#{ z5l4o2?`)RwN$Q81&#TD1l7D@?16*X6L?piVVBsYgCP|l>5+?Z_K8VOY2Tf=FQ`hp$ zRr&2rDTrU9bYl~wVz&372hSsAv!mj^A(mA|#sCGqc|hL7Ok=Oq!__-))RhO(;|nzE zJUzvk!r3{#R&=^WY?(G1*&;T-wF#G~m;=Pw$xr7Pl3jl=UU+NLq&MPtzLN`d?mAx6 zHEi6)VbV+ImvdiQ4B~(N5i=sw#iMg(3mDC+{EJ?--}uotT*#XA zIRE^~=_hql@!~5 zX@#GjfNPiTbqh*tCd#YroAY#joq2RLZFY_GY(0eQGJ6L#(At0U3N&A(kN5BnSQqDg z#=1?9`+x678}3ffd9Dr|hhnHBlhHUEdwjzGr958`v^Q$42Mft!;L^r~i0y2e^q{9Y z9h6<^zMcM25+Xou`@r#PT81{G?5nqHe;ck$c5Xutx^IC^ zIT~{{u{H;>uhJR!ObHlr0(t?-`N!Ye_PQj?NCa{zR)wO1hRKwgTi3To)#*kQt@=n% zzJ-{0W0-00{S3{v(6C=Gg1)dy=N|$bh>j}y8=JSD&pGhsvh$S<;ch>3>Nh3+U60-^Q~f#4 zGN7$jiAGd^G-?f_k+&hcv@1A)I7dEGpA!MI{cj?Wt6A(p5Zr+l4Ru&2_~_w7nPgAE~2Jw6+8O~FFe4pRrr4E zH&H;e?z$8Gf3Zs>$S@1JNM9tm^sYEj{y9=|dtpJS__oDzHxBp1yFHjM*Z1_V zuYA+(*arU(0CGT$zmY6Rs-?c~hcH`@ygyvs9{*$B|G-mx?iti8v;2}Mah{Ryo~}D9 zADxkjyYzcz-rzUJkk|cZ@QztE>XPr5C{{2#TqVy>@c$kFX;H#g)Q^?HEl@dL z3~VM@-m|=JKq!_as~`Uqwq7HqH{~3nIF8F$daCr@gn{OdKh_LI?LUbRLLbL=fn%U@ z7-8(x&Ewt80i9Btyy>YX&XbgBKB1diJe}`02xhu<`|F}&`m@>9Bc~{U<)Up*xy5=i zd|hhJ{;JJpgNg&#z=$|th7>cFd+f5FV3Tuq>#6QN$wRM!YD%_01yV>;{o~ogJtIo+OxfXm!0zS8ihod z!0Ej5o0&JI5@r36l(9(Frm4%umGpPTgDHJhjU_*WS}T8iT(8Ye^yB_lzW@Kr@z)P! z*K@9&R(^BGxf@W;{f>VVoE_6%e$nOT^*ANzM_3>AlLS`AlfGB&-RnGZu8-wWoZ*}o zao6At<^cEveQbvOQB}qvdBx+c?O<}^^#?=0V!x_P+<$XvU3IKD zj;FW|iTFb;q)Q-3(y{zj4mC_J(X`W{8ypexv_TXw6@5$ES)^P2%iCz*^oxb|V~5^U zq<{OrQNEZ)B?UVd^@g-TW<)pM?cpW(b(E6tMOZ%z$J5#F)I*C^IUhpt>Wn*0KassM z+yDOrzxfuE(xu5H?k2ai9A^K;QvF`!iyrKxB-f^~?KvR+RC;{77jm(%ZD!DgWZ#1x1`0 zPEr(d9iwEX^rlIZMgIDW&-`A0eME!#ShcIXv`m-_rh!?fN5jZm$Gygs@{eOo2r~dYY21{DAOMoTnc1Jla_Ua}tkr zkh7pMw9to#G$1NQwF6#)gNx>S2MK0*78>ckJ1h0VMMb}DhSR-5h8Q)2j+EwA8i>E8 zaBgZ^F`!_80|xV$GMHzU;bi0%N`Dmkk^TRr!}RfXK-N%Kd7|Hp+q)MeEU;2keKa1WQ*x05p0=quDs^eHQw3TLRJ0;pW6uVNnB zGof$o+8O`w@uuq2+PNavgBs&W%hff?*!{0@OzQgI7l?>LN|+1?Hq64CCR(vg;8Xo$ zEql?X+m!@eugtwQcO>3b)<5dic%Ed~|Go~iAQvQWxtFCIduYbP;F0Z@{3)+al4qO6 z5>C`|o24}v)Mfy`gI8MQ;*gI#eYvUU+DQ^`sz2GIrUfmVAvqw zlwZkD2W*{n6i~HiWh@-J6uj#9fj}u0BS8-&zNupj*;?a;uvI4dEPhSxTwx~0j!yH; z@f;Q=r5I(W^qh$<;#5Xt#N-a!Gnmjn$lij3l)zjegqjXDoaF}~*jxqw>L!`ah{MME zp^MuQsF`;l&1q^RJJUyHV;|ni-J9Jtm*1HpBv-bf;^<{RohU$7$Nfuo75HAj{92AE zzp{euhdKl1r2OsJ(U~J4&Q$?vjaytfH(Mev2jGrt?}FfMDt>$F+fiw`l}AY`h3k%n zgtVp7eOn(-lTFqXUPFA_nw<&t6aUzUXn@B$z(iqy+0?oc-sJ?5AHV0UTVW~+?P>@ z5^!ShRFPAwiiyTvZdC1l`1ZUV--Hq)l(w=c{`_m{a`ac@XP)0~h^B)r&+h#)guIgUg*7W?*@^u*?aUX&mk9a>K_L>B#B3%DRr_Ns$_j(q+6$<*vKjY zu>pnX?+ljpf zv@u3BNY#CBv4+n}04MhAFX%-|BNGh)a+y2?b6sY&!WB=un+o~if>A(fy4wt}I zd<1`b)B@R z$Ntk6Ad%@M)a|cP&a?cIp^$K+WF)&?&4MpcrcFV^E76LR;eE9NCe_d!#*e(KJMT1# zQE*?5*uAh@eQ9Q}X5U>Acoa?>Hh1XH{h<$I-nj1|DmkQ5r~4@adVY3kj*i`~B^gri zvk%uW3TFi4qtu`6lyz)}O-CmW`+T7fAIsfKi_vx&(tFm=7Ru3&;jxQ2)T|y0Yw04T za}R;1EA`iQns5Wn28$#rSa$%5#|P7pmz+B4&h^XD+!Aa2B6m%1m0aIpE*h`*>f4d0 zcXdlGfowhXH>VK%Y!yVb)d>X(9GPX!|6k$LPV^|(XcS-~uLpU5&M9GBfafLE0I6Jp zY9Z>?c)QS%v`mrB^R=ktFE3eE+x+KmTRVSO{CTFxcZ9!JE6O;5P4py}qYS(}Fm&n; zau%OY;*1LQ^a4Xas=-dItH2bg!~~QaT#rHagCq<`8m*0VVw$jFs?(xZip3b|G!O=S zQvkV2fyWDeOM<8zTZY&<8p!uT-Fs>kN}Zknt@;OAJaxv;r;4$nS0@Q06UaeUz--Zo z27ktn3=O;vcNxo;1b%2$Gk^Te_qDsvW!f+aLD)bZ4kEVM<>%);>_=y3ZLwl&;pLNT zmc%d`^Sf-Y%UhmNmae{48P(S}D&+L^0Lx3Iw#9ZcW@<>4IsOF*?&O!+)ReA~d%V8_ z5qJCl>YLlO|DQao60Uz^eJnf>LJ<1EgkS6f>TlG$FXLueKm6dOP?9CVE6T^Wc;}q4 z))$XDO8slDwNzIbq{Zn$HStYoq;OMS`}n6<83X`=PHBmsyFRLt_4}Jg2V#T|D!PK3-3a&wkWicxn2O&rLqH{ z>OSXtcv6IC29zj4A5Y0Xr>qX8D`;rF71`N^ql16{%fk=mU|c4p0PXG4Y;>$}qwVlWG4^PjJ>3Wn{*Pz{U1z-5^%Tz!7 zlVe_2>pPQfJ#F*WwI@xNzo)r`qv78=*EERic_5AU>C?+D4HHwS@Hx(2Ca)c{hNW3G zLD>LE;hNV)3U=*m_4Zuj@&1_SS6L3@-*~LM-`*LWZL(l~KH0Ze$JUQW(M_Fe2yJM7GA7FkE9MS;L@5!_nvt$2H%?Y=uyS|~F_E_b z?XLBAv$qq9fBLd)C8vJ7)J)~U1M88j=vDS7ML z6 zJGUCce3K_Ak85o0*7dINng(ZwGQ$vKEa~QSfMZ%Z7yw_ZwHq{MCWFkhf7R4ymbSzl zKqsackG)l^?;Ku|9|}B3fS^?Y3J#sB4_bTrx_z!8nd`vsHW6pM@jy4^_IsD6;n-rB zn~~M+9rsfyc^Uxc>Z|;(R&i0uh(#FsvGfD)l*HEy5qN?OX^{QI(EH)y_I@7H=`*@urHRyUYo?zDHArPQe;dHWBdmTPzG9Z^Tj%2jEK~*4~L*((`Y&{f#l%kWCMU)9BhAV92Qv8 zR89DPWz$sDLiw7+~^&$!^GkrhmXL zthYlTvN3vw6@v7uq^N5P1#3IRF&2Fe>3RmJ46}{34QlM>IGm3eYICg-#R-FB`hJu_ zZ*|_egIUOU;(SaQ*#Jb|UWjVhnq4(iUO}xNC}cr%zUyH#rYBYgx!D+k*IFcr?&EI%}_kbFYi=XwcEH zV}pT{72rlJ#*M~&`ej8wC<*FgMsOTzj|zoF!{+E0JytDEBGdCF(2hm2s)5N}@;w=~ z4@LgQvDybf0QI^Y917)!vu+FQ;&#}@-9C+HSTm3T#T)4c{JrORTXm|c6^>xLEQL0p znE}Rax(+Pd=5P$1mJD#a#si!x{W?4IJlfHV20R@=Q+gsBdAd})=Y7QZ*(^m?hK|;* zm51kC;d6YoE&7}&DjDxG;1co{9$IdoiL(Xj6s`bI{Gl+WVCI_-{wN8jLC$I1xgxF6 z6NfYu88Vp9oC5&Cw4NFK3STV%X|rQD#OvsXQ<2VH91LIp9e~4ppn%+z>R|xLKx;F0 zHRtz_3-nsT>C+L-Gezt!kvSf^Bbry6-^r`c!90FV3uXswGz$2TX89j0#t1T;&?D+F7t>~~V&|5p`EpD&O0E`l%8KbRrS0UvAVhzWkUqW$RVJ!uVC7{va zj0xygC}-pEM|qJcF42jLc2|SU)nS*eLKvxo*m(Tf0R+sgaK_mfBIJJGikK-;0y#HEpLV&IF#heNNp{9#TfTvH{>ud~BUlfA_*jWrEgGtV~ejK*@LOkhE z66x4(7*Xt<;Gsb29lO(z_T2|2qNnB>Nyi%o3?o_Iv%ZR)Sk_OILt7l>Lp|Wax-U&H zYYpyz0-FE;000c52LJ#yK>z>&0U`kQ0*EP4gpZ|#Bx+j;szg*$v2CJwLdRBwUd5~` zT7-dDA0-`@QqUcg9dW1#1b~o~uq2d^iF%aQaNy8bQ3bn&fl^-80?UZ(`>0g5 zTX2PrODJ{$2#$i`R?Ew9-BQ{Bt5EO7?MvuiES4n*g}%S&zW~U+VPGo8QIre;`E(0R zb|F}qdzAetPu@fqTF6L2yU(Br<*KDzu#3dBg@ae&VM*bK`{*7q;f0F}MTyg$1alh~ zW7bk4MUi6Y^cYpc2s~&Z_J{JGoC-$~p#IpUa4!;WWYNF@KOA1Kcni}oiABN7T)|Er$1IHc4FnF?EMWZR0qNRk zVoKBJ`h@R$!}f=mPKo9?OtZrItOhRVw>_u!cJ7OF+J9pw8L{g9_pSS8iQ>X7V_`Ga zc8mUi*aW&5x-t<$Y#ZYE#^Xa-49ZW)b{9iD9mY`=@mCRyzlm1-WX0G%GX|c3|AhkQ zP`P!~9YPlcI2~>?f_W@33^=%;#|%W6ScCoZJ)e*^f~F_OF*{Wu*3!f_NFG4)oS;<$ z7*WfBL8}N+j5#ihCJAWb0yF#J6&*)uNh?a%q}h}uccx0WOh;$A%VQwL8% zBN1h2MbUvigFglsAm~33OJLdp8vEe$Z3*;Tbd{j6dkAM0J)A{AwIjGaq=v!>6UWy~ zDGLKLYyiB6MCU*qYgBHSU7H3FMzSyX4o9J@>IEng)n3Eo;T8r%{rT^QP>~>9_QCVa zOT-a?s*B&s&Aqzi3P#*N6$E}>cAB$utfbMC#Z-xk1lF=9h`byz8fME zXkO|7f&c&sT>*VH002V(g94lO0ssIEqXz&0H9-IX0RbWatptynHFb?`KAcjWYb0<) z@zj4{bLE!eBu$LTj8p+%JZgaTyG2m4!YEt^<+{1j0CO2Gi4lc}z9|=_q06xJ-^;K% zH^t*jAOg2Nk#tF%0jator4e_&p@&46;|tq?Xf6=&T)kxnf;-e&J;O z+Q_Qa6jP5$lH<%HN(@-(&q=~9xq*X(d2|!P+_~+`onXVCw)`D%ZJYwLuQ~u{LyIFT z`;&r@U#?(06iN{fk50rR)ru;|EBb<$TZtc=qd{|fs=71O01-bijRWz24$eu`D%yxm zCE%+?Vb{=kdvPP>Xy6j@DO3=H^$Qvc_$zKG@Wf5L_~R}oTHoXDumcDtzIU?vqUyG# z67CX}4!*qTXGBtw5=w<{Jzd=40TG2L=~$x6>w^Z)Iqw!5OFAY`zz`6% zc*YQTp~U#-nL7Tf-yrm4nfJlwyB6kGDB2K^x|-dZ*u~&^H(wkhZbXPdLGxkzVxzLH zrXy@7LKYb4a!3Ch`~fXTQYTAo3`|4-m$m3qYyu)V_(rfA0O$+^nt(}ly#pozFnUlx z2)Zj}!OL+S5$xw1pTI~QCz05d3YmC7B8Nm&;5AX*!4I?v0c%%~%nz>Axg^6_ia7YH z5y=EYv}H(EwM)8x;CI_`A`l3DH#(&kASGf z5A3e~J%xH<4WR>Obs!N<%>bgjF0Gz9EnX=m}Y@umpf5`lIFPveF%_ zUJPrPlcxGuIs##%fMxU!P^Oxx0WgSS-s~mqkw$<+`kfi$3PVG~N&aC|lCSvV2OlGG zk3|beSnLs!qc~Z{Q^dcTy%T z0(_qv>Rok&52xvL-oZ3Lpn#Txp&v`ju!3OkKphC%`6HYH!AZ;0yfDfn3)Ce9P(OO! z!j~m!)sF~;#yL;pFX$num!Y4R&LFzW!W0QKLMicT6_6<4ODzbHf$Q6o_D4lZMGbwP z=Kx%fDtq6A4pj448~q*cZwFy@Tb=+%3qAb8G+&y5|IE90;Yu5$DfY|!3Dj0 zRU&JF3!^h9Bp4hDH^UAy44q>{zW_xy8Z`pA;*8EF4XuF-7Xpj`Rxu>Dq$XG$GfXHS z0a_L)PK;D> z@qvKd9t6Ey00P58j?^7%0nUu1^G!4e>b7pV*#`(bKm-}QtinWEUxOn+@Bt!Wh<-2} z#&(3m!t^})-jRCKT<8KN0Fp#<_Hk8!RVXYF9OV}-Etm(fb1PU?mSF;5`$&&Wg4@Xe zP8W(sw_^jBGA@Aq*N9F zv;Ylk02bRxL1_YVtha$ehw_XQ{woVYh_EaK`~)aq2!H=Sz<}Y)@mMS{5C})&p(8`E z0015U?AtP1yoofn%JOAlpG&*^pW6!;mL3vMoJ$>f=!VD&7Mbndyx+<*Sc zeE=Zv;^3^#*=t*;4f77Wy-Shv9DY9&>Sflt=ieXIJB~<7Z~A)>NX>L|RBuwf%N+gc z)^5Y+r71hMCo5)^=a5rvjDfBB>HWD%;tyTIT2x#c!KZW}Cs+GbNFG|<+P3U33o`<+Ekd_|D^ zS=rqU?SWWlvG7M>vWou|ckgWF?k(%HEh&w!i)Q$OeQu9lm|JZ9xk2 zzs!feUxz0jMWJaWl6iw}ecz~G@+l-{-ll2SZgq}rN(4r4J-V{9NT{!PPFN=DZ_ZTq ziT5oAbE1jqffi{MMU*}6Z#!k;nl00t$_5N$;o*71eMb%=ljW)M4z(c*K9;t$FZnHI zu6;cnr}Ue^leqrJTJx|+_B95xi{xeJDh#}w==RrxkgIJeo>QAD`32WW1VtC zgMW=mT<8n)>8;Z@J#r)GAH;M-PnK29app#j(H1=t=bb=y_%nYjo6+a^zGNAysBAC0^3(p6a&(O+xyS`3M*1rtfQ-9qy|L>`95|anJ zLzngOwLnh#uMb10YMqBa$dVv*m7euhclw{bXlEjS^vk<-kbmI9pChk71sIncKH*_KRi;frjV(*frJjP%6a|%ndhkrdVf0Q ztih>RF@G9#!~#Ra6NuQnKNPg*`Fj}N*Zwk`6K7qNWIuk`3hB)?p7#e!2~ebOf<(RA z(*mmRoW~e0d+bpFPmXvS1qq4(HiZ;TsefKHSmDRrQ{VG@HiKhsc}{i4!lD%CTzi z;?>{&Z&a*vao~IRDs*4}4c0>@Fo@ud??4TVyY=UxAO`oMwqN<2 zM*ymSyDs+IHr%`%HFM-?jn(MoIrqgoi}ZRme>2@H8ln6(oCH{?yE!=&7^Hr<*9w2f z@49vT>~i$7`@3(08%d$k$9}mwmAkmY>~VR@0xYv`mZ1PjCgFR=W&dMZY(9>SHUQ zZdyI1&ThrK9oL5~T>X#4l%9Ukqq$m}_ig-05AqO58cOR%$C^qyQBR3JSvprnt7S|& z9fw-Ure>Kl{t)Hs7>coHVCmft>7qpzKCtezqAH$$S*-ZJZx(&2ApBgtC0#22Y;$-5 zhUa5-sro)`)69n%aiUb1!BW14@U_WG*FFn#tvJ&W0uS8KX|@70`@rD;=& z6B)yzy60~$uU1A#Q6%l{`^kbz-eB0@9f)z9~Nne#TA;;D#vCVaBf3=k@ z+%9;abM%Oi^1`~#>xu%$1+r9$Zt%V*MzY5^nhiMawP=E6dAF{&UMpUyl||q@(ud_x z96`&u+}U8f%)o7^kV;S@X>*z~@zz#wt8?+a^`S&nl@2&fNHnSJfO%|>Xq~t=f!S-V znN?)WXx(uN7z7Wmp6JavIay-Z;|aN#bCq5<7IvnTwYoo~Q=pUS?P&i$kbUK4ti50j z&YdbaqUvynB$Pr443}^x-BrW51t%bOlLAPk0)js{gW1m`W&+Fr#sJM6xKS6Y zxII-MW^Kr%5N~cDt@i3*zS)m-6)GO}p(6+#ygnr80UvMwRv-WVN%#WqEi+VO`@3?o zwFdy@(SBwJ#qm3FgU;1OWPdqcsd>Iw6pJXIi9905<(ui#$=Whr(X`w3A@<*mzA5>2 z&x~zR4Mm|6R_^o z>#YY{hq^Xd@qH$W%-tn7;`WT!I+(MgG75K2*BuAq6l&7H zw(WHNw06P2?VrP%*89M*(MWA&Z9Kc_2uvWU-GNSZu*duRe|leS#k($jk=jV>(uc0Wk6 zRP7olzSx`&TiQB z9Q3ZaB8tSroJe-j&Rf8nh;9 zY9d~lD7y1Wx%#B+a(}Gn=Sx*ln(sRl0`S_s{{QMz^~_SAtBn7llsIudM1!T|{+-=% zOmT(6{VqXN?fWuk|Dc^Whsd9t>yon5&g$2V@Dy!WT0Wp|qrOuijxX9a@PY}1M`4xY z@m~Y`2{F5LQN2{vb}vn&i42zih-AyWVb!Ac4=UZotz~Wu8D4t5-)cxxjrBF?Tpmjs zA9MX1kI!z>aRlpQ3{bVTXdf|Fo&C7t8fzm1cVu`j~K&C(f|! z?4FEf_B*lr3&iEg=pvIvWpU`nFe@9s{ezz}Z=R#Jme4kD?MoFGH4iFohBI?86 z7C_|51c32A8d3>el^rvr21H!Q5@G~sr^TM=atSk3op(U!E zB&Y)&WB@n#&^fC++gE4eUY)G;()KSS={w&T09VNV32Wp>fx7UZi-1uuV_izc{y^Gaw^oWg{NwO#F|hbzwv$W*&tsO>o`P(bt1suL zPydcN+0fzxBbR$eo6?Udo1CfX2r>PR9l*z z^t78v9c3}GstWQrOq_|A>ea@EoL&klb;nd)Ish%g(|JQazJ~vpDjV{W{Py)rbC)!e zWAOT)W#>!1NuBahe<{4~l-nEh zaVAS%*U7hjwvSnmFZza`d48{p^F`l3BGywmJ&Y!jW(V*6PGQ59XE)Yuv$3}E!^&+> zj4pH=KeyYidl$;ib+goD8|c1zx^M3!0z@%*yVjz=%#?rcoP@Oe&zloq# zz3uncrhF-^4NlV`-h05YmPlH2s$pFcEx8rvARW06Xi%$Qi zIZz1ua#}!qxZmBA`NzVC`D*vm`F~T``i;xHe*3a%*_{*C)t~j{P6JGYETm_Ppz}&s zo~nn+VhYTWuTLuV)o`WxWTRTY4h)Wg|NSR8jWaaV6=qDujU9Dodgwp?=x+6zLbvnr z-|spaa=|~1c?F>WTkj3wciH23Vbf*MUH8@1@+uoYb*g$^8U>mX;C8FAjmX!n06(lZ zY|D1rfLZmdpSd$svt-YnsjIA+e3=}_brXk zYU?Yz>@L2QKR4BzXVXl40*i2hhS6!iV#&L2t2gYW^-`d#v`a|Gxvil&l1Lz0+^ z98QEKrz~RL8GZQKpX(9D=%#Q!E-ryc$TH+4g8)#TH7^|UPMDGg4}`VRf)g`UYyApY zaYCZ!%)6agoteMqpqI9HZ8rSH_j$eabdjC&^*Ra>dHZ#{jrJ;TUCrP6Dca#T(cde} zm>eN7(m%BnLyVJ2*h)EdOdxA2ngBO^|Clj0*LDhr{$N=7`4M+s932%Nu1yuu+28U2 z7PF+rf>8ArkBVUD|MXxyWn+Ij#sv|r!QC);@JKt zU;QJERgPI(F^6>2-A>w^w7xx#0dlrM z2}uz^Wt2idcptcV&Gh^rJLgDAoS7g2lNpo%G-dO+X?=n%g)GSJdTY=NO?N04CsI8Su|DBsvM;ef&Xvi0l67QL-f@M(M zn*6)zuYWom`~d4c6qJ;NylwXXAFI+oJCY3^DG6s{Mb%H7pU;fiMwMGXkZFF(|GCZ5 zriA>gB_Pl_x6bz6YzpQ!a|;b!->Cy>7G7qFmQLM*($yX5*wnd}aR3e$Fbl+*IfTI& zfgsxMw8xgRxiFcXKoa)MFKlBdC$xeFe2BD2)Bp}hF$=*}`O8y2r$)aXriM8;J^&mX zGKf)8mSd$$R$YKL=q~EB2g$zr>~g##Rj1)vt8^~q>Z9N205Z*T13+Xp+W+zi1YO_% z_%NcHIoyIfVM+!sf!@RX{Z?V4b#`TF6QL*r|jP-37PlKZtHe8^;C5)8b6l! z_}B0A%{M@@oBcf-dyaH$-}&FHJ~-@)|Ky>eA7$u9=qLJ)YO7{CX>_%Zd`r43;uWS` zUUPTF)K-6b-Hq#QRNu~;wi|ZcE-_~PtaGiISAVK^o0&4{zv9I>e*C<>Xzjb4#RW(} z1LN#y?MvmNeIi=YQY81=s9>-*?8CYP7K;$2??i)d&` ^2xGP)Lx>Nsi-o?zwUW* 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

    f?X|Ro9HYkJ1qiP{Wu={dLm5pYZ@v#Swz88& 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%0D{o) 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

    33NjBGFgq?iL_fXdFu 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

No7x*tUUgt#ly0Hfw5 zq|mK-Y#%bg=SP#+1KBC-vnGkR^UxRYB(noKLgL1gVANov1_r?JAO6>{KEU8RjEg1! zcN~zxi7oeGXdw}_F%N@cEV;3NG>c3GhX-r>Fd(*bp9|2h|pv2SHr*tSEK*_I#72+`tt|m!GLWrNZp5!8)>x zbH^@WQ)Bw03;b2EJ&F57$r*Rm*+jnO3%^E%J@pTCZBMMXbSN*bIcA4a%?zuaa7>wG zhxk!0LFt@&e&icdgZMSP%y3)|6whAQXqVvWIiFX#^05_l0`jO(n2NT>bi%&}H z1q`pl7~?7sf?mC06oW81ikP)3@RQ4)U4OWj0|HzScp0J&h>$^lyyUG3#wkj>OjoE{ znY}Ro+Z^50F2S0`>WVBOL6NA{I(D$gV%}{)t$Hjc@3o+plp|pfYfs;32iO2cYrp3_??gbQoC^Jxu#9WI5g$oh0m_fO z0ET!V0D3ocL0lGs3yl??A%VU^EC0kGX`k5hyL(y`fLZ`5Ra!Zj5Uiq0&i1RQ^(s>& zD2S`#t(9jel&B{OR-}u92izvMUy{hO_wBZjBj;%n&iu6km-(q|o#iFOf+Lwc;DAvH z?snC0Mj&0e)X?c9DI}6dp`kJmZgepq=Tf=ean}Lq2S>gXR5}(Rk_}_PLueAAvQRj> zrgH?kQb`Cjl??$7=BHmwh6?aOdUl8a1es&SMoW8T*Q?_gZQ55hhYK1l7AyJ-Cw)d@ zeq){IVrD>yhW8RNptOfKze)-Bz78X(MnY=0qntxSr)3;5_3+Wl)*$6?!^E3Bt+N3S zeJ8F2Q%_gv8X+=17t6p+u*d`O)k?d* zF(EIzIxj=cHDs$<`6h=(dVtKz8T>znw$NRmyVi!YTi=Cko=8800bENi`>UiZ(5)7P z+BN;M-NJ{2@-ZDe%2^4n*@%*U!ZIDRa#xE(9?%b zF+-vcoq8Iz{mWb>MSj+eFR;B9A=%(Y#|X?D6NxR(RoxSYDTr4R1cy<0qviO!ubl*g z^$z}WKf=qz=uH)>fTu(gtu5g=A>@Z7Cv$W8pti$x1+{fzK+mQ_+0-oJIP^S%7$K;4 zzwkrIsq3{}(ON9bf*RH4yR%S5w<{g zswv_&&I^(nPK(o>tKnTb(W7Su@Q|NQX0{WyIb^Z)B-gHG`eJq?B@5Y24b0A_eADnT z8s-J4`BJqVmiA>v7}q+Lfq2@|ZS!n+AvL$eebnoqeZehQ#QPzkjrdZP7ow$ksBv+bV;ZLJy_h_|J1 z*>z55JI+?dgJDwW|A>vVI@?mC*A_;`wh9wAWW6xG8as`mFg7;PXn#_;vAXfO1mL-o z+9V@7za~bEnZsP#EegXcQ!Fd`(il=FSNr&gjk?oQx_{$!B#F|QYXZ*k-!V8!%C!|7 zOiFGd{cT7V)KSFO0;j1GxqTU85$X|P09Nri12YK~#z+W4!cjbdp_fN91P5>xtyAzn zLCOpRRrZXiI`W-lVPbZ zhc_Fah=rg6g!ksp0RZUw8I@C0m@QDtBl zGTPB3hCx$oJEfuMsSjG~kSuk@DX9(W<`xoR7N8{YGa=cywb82Vfj1h#R-G}ZVh)+m zu?I6oC6L@S33!1TD;XNWfj>kB+AWGO0l#A^->hM1z*wOSR?joTYKz+g1Uz%avv zE(lPj$COLZ^kt35MI|9*cZHAApxrsG=JTI!-zafRe_-C!{DNn)v?yjX86>U9X`dON z7a^mAmu@pn2Gi`~b0W_Qr%;j5PK-|kko*m6BH+TQM?4S=Go&H67l9z&br&J2(4T{o z<_*mNy2@^}mlt`uWg(10oh=iiBlSVOv`{y{dL3$U2&EGJ)Hw!}*A>%SLgR};h~)3g zNMfiq#rQ_Bz;kx$1Ib(G_6%x_BOO7(#gX8t5EnahP=LB|%!TmX0D=Gj30(oc2LJ$t z0EGfP3IzZF44fzc0Cp1q0099Z0Fomk(-3Q5R!6~lFfZx4GY=;}1mjA)T4SbQasx&+ z1DJCkU4wzo9WiwHODc$#sz*0sf1O*Av~=A#ARMN87lV`M_KM)DgG3s|SXrY~KtB4l z&sMo6oT@a zAaK5vU`5a=@gq=m27Mg$6KUH%fnTCYl3i`!ch}<;6 z9Zb8`#-(N`O{q_WUkWI-;9?l)TI@yIFe`{z7XYEF%IuWUTjVSv3A>lELwpnA9G_HJ z7F_KRlD03#>rDoUqbAa`+#s!Cq6sVR@d31!{8Z?Hsi`G&FK$j^k^Z>W*#9p(4jZzn~Py)AF~0+6lONU zjTNK~X@}IK8A4pA36y}U8HX-#!V*RIk{D0#1w`lhPp`3nT~c7act#NMo6;oL>nO;_ zqDXYEN&^C9te=1y-T$7C74T*0C2=%P#5VK8aW-F;m{_wyVGX8ZF zSLh*0%j!dm+IZzX>1L_mZc9o-*AVMW6Ah8Cu&nvf4;&crbPWw1RFh}hc+7a^zO8^`USt4vMILM&WN zQ}wAhzXsvKiXxt$ojz!V2*Jo!Gg4{hw=|Av&c@7S@A(3Op^nsj8o5>0n1DpxP3#1k4lU)nhR1n7E_Od4y1}h>Rx{f?egNos9aB4JQS4R*V!rr^>$r$E$ zNNJa(Pu9TM%%QlzpfLpcG#jmsIQl@*y+3s8>bR_8jW8@pxPV`XIjc8N8Yqj=f^+zQ zXSJfpnQbN0PO(iCR1g~kQH_E5X9cxtj?@8S%rU2nsul&|ux}l~xST_!Cy4na)fq07 zG(9Am$r(c8iL?#1!bk~P_d@9GSAi)=*z1ihj7t2sG^Pc zPOM>p8aj#cKz^TxBZ@7(T-3@Bpev{4)}G>)dyfmSMFPUOHcgIA6 z9#~*q2*k~?#JFQmfJCbBLOiU|AX1Rf!k$D3jIx06zXr`atXsrnhiQc2ZNmr-CL$tb z98PU9G8Q1~1XuB!2g&7fm4%FoD6EwnDtcC#w*}Of!;5V_O;$ETQH74Ae$8b1#H!lT za}))sQ;nTlM0d@s#wY|Y!fxkHZ(CAtXQDQ3nR_#C&EoUY_ZT?wcKS=uo$pZUXKyU* zyT~tvYW1=*6(?}A*xwF>Sf@sxRy#?Nw3bH#J*%Zz#hhWT^Uv&&nzEJrw35bv&at+c z<5`)bxLlt=rOWBfp3xhBZhAW@CH5GSaB)!8hJfep4lY53rzR>PF9L@v}pEEH${1oS33LCJ~a} zkX0}j;N8O_f_mHR>sr%kAi^k+8rLfq?39Zrsl{lcDO`!MVPUDv+`)z&49g*?R!o|@ zqM>oXX-?}Qb2f=cRxM1y#+t?OOx!D_BV(?ucv}3|!noZF3XEpfZamgo+gPSG%UXB9 zacu&vZG(ZbbBS8WjTDH_+EJ){%UP^@%fRGTd@C|}b!z0quH*K8R>MM63-Jq3^( zta8!#RHC679txf?i1X_Bq$)B+GJ;f0D5WC?fN-C5T1SX_F|FaM!^rqp=WFPnC+QK` zWq`v-jH&bsv}a9@#*7Q`Df|`*u_>&FXeI(;tSk|iq~>Gv z*?X@!FDckWp>a2{wplptfR!01(#@EH=)$FE>jwBA3=6A?!h>w3G4-|Bvr~20+H#i2 zFkhfz92(P-<;5hJIEQ>D^hfv+D#uk=gFTIlQO3N{%h^gvrm2}jZ%Ya5)=*%_f%w5a z(W!%CcB2Hf_b*bND>qvta%4eH{d9XpbsSBn(40Uu7sDKvy#Os0IyD0NF~=>!b^j2C zp-IFSS|rkeUL6OIpmb&{qM}U6G~(A!HI#Vf4hc0m>;YX{SnF{$nHOO7ONplt9z5{~ zUQ#RbxQQ`MTJ&BtVHXTm$w>jLuow*mn&CaYET)3ObVN)npqRnI{)RM`GQkbd3HArb zA@Y?fa%TF->bKLut=15~(xrB0|{^OdHOoG=Gjv93zH z@hx2Ta{y{z%oNtLeTg+j2$k1xgv>fHD}{-Me8w0piIS!VBhrC2O@^|xG^|4afQ05Y z;b|(mVquM3je>e}r1;&gjFOS17S$FU4CvmAgd3wH%JuqCdMEVJ4h=PrQbZGLOiy@* zoKg&qSHlEM63`|gMC8~At0$=AzNZDY0(!YKjL; zMCjp>sH#a?eNaAtPC;(uNXcD?)=N^R!jp?I#&w&MfH9OYS;o#TI%lIvRBUSwi+$-P zw21{J7r29Hyc1RR*nb{i$n|xG0cNsRdjp5mnBlO@;hFj!GG{2&6ru9yhU)Zf1!Gj* zs}X3}H5P=`Za1R1VpIC;kwNNOTWqOh=e@lKlbCHe+S$dc=+i_6&LSaR1#5aM0VrAo zw57!oP~wyabPPo^pwv&+0d9x}wX8{2>6B5!mSR)=Qh4JBMEV{-SV(Leix;dMM;s?h zo74^{j(3f8#Yvo7u>P4HqkwFC67>Wz7GZ)RO5s^$Ofade9~AI~At#6#Cstvs(pLIy z8v!iSlCPW^WZXN8KfN+fORZ~g`*I&-@;Hq|hS_TU9}`z=u#VwgC8H@rIbK*;S!<{l z4Ug0@)~oqfKLpBPiJsrEefk9W)b7B|d?(Se$aK)o%^m3ty=>hp(*oADJH~Ggw#f?I z)|=_(w8A4al>c!ks|vot6Id2~pjEa*h9J=4jbWw|oJ1@pDaPbr-^cwi(L9OxL1;W= zoM3v08S8GR3|j9Q3z<1Jn=>`dFtM>(BqzKaDF-NV)!KPUH&Jszx=6yr5zR(oWhAu@ zIwJ}VxFrN`IblMTh0j(^<9-!ESvZTPlMPr`wzG%HCdtD=K8P-10VzqdIz?h*p0NX% z{H42GU1%U|D2niFr_EyBN3{4fXu)+v<8hr%Sp}=3XrdfWTG-I4H97sQ9}7v!8{>{> zt4)G1tkFeIUX|$rdX}EW((q?Yl}R-eYv_4f7Xksg^j(yes*NU{m{Jy>Tu)HBy~<`L;AlsrSp^V_H1dGZSa2y>q->jbP9TkoYjm8$7c{hwtFIH4kgTr- zwnlL{;q{HXur(IwaVD_IS)4knh&&-Rwgs;$uxoTcM_qGqvQi|>zGH+Tl>uXGF-VCk zs8e<)P9bj0>~PBvyoA^%D(S8=A(t<9xJO49|WaF(ImIaii@ewh~qBj8a!kQP{eR%uY{arm3jrXLiQ#Ec4Hu8jpB52_f60B^hQX3Bq0~MkJpwxxIl0)=7Lcw^$0dh>c z*Xhf6&^r7>h{<%kM#9^chUd$v>R9Bo&rQKy5=D-ZVcAN=V$>*Ej9B8cWJ#Tb)N*Yt z$TM=`vT|N`v%1pr8WX1NO-g`h*hxV?ximMOA+cnscU_H=aEzr$2wF#!WlBj)J1cGk z!@S_)07c|Xl#pmC-CC@+pH>0sQ`6K4S)|1}dtEy>Es6Xf1CrlQpK{H;?sDa4qZRv% zEvK203JH1aKLM6`7V74M0@gSCjR>PSBD7JxKY=|FBJnqtW45-9)-glV^pP3nP8JOJ zQdFrA&8nGbH2FhOQxQ##G&3GAi3u-uG0k!hIPU50Gbc)Y#Nr-xYVkxFj>ipQG?+Kf zY!RAiq2a<2okz!AgzXzA+H*!?WV+kY<}+cabdqs|XA7^8$TjKSGK(}^J)v_bUx`k> zMBc6%4qpQ$5l2ODC)X=1rUuzGvv}}38MSNKQH1Dt^H8k{;7rPdc+t&-hdo7sz)Plx z^QrJAUkjv%%xUOq^3(ewF|NjgUQt?y$0!WU42ZzUuuKK5%%O_)Agpfxh#KJliL|B> znm1@hAs{}*}&+otN8kd}jI#jHsEgazz1i9;N4Igh1w$PmZiuHo!Il&UPr z?Js#X3w^<53AB+5_PP-$`uuEWb}*dVP?C`fsmTlp^nuQ7e@k(+Y|(uaTp1s$swNmD z!%?0gWh_25v|oDM`6Xjsu~lw2+Ai&rtG?-+U@?@p&iMFz#H-{T?APWo8E zZkrfx@Sc&4wL=tmWqwwa2ElcWjbuV{;TE$jUJWZ~s8p?7{URYskcBl#zcjf}gg|tg z6bGAKrL^KE;5jW#Q_JoHosGCvmi<=_@p&rXgwt($rr0d8WXM6$!hr)^JGH_hArD%X-__nV*q~TL5 zvi|FHNN7b%XI?hu#rGVDHIf#@3P|J}l^+*tFB2oty&?2XR;l^BovBY>g+7ZL-goUfl5%Gk%A7J zlWRm8Fxi7yw7)VkAB=>fHVHPO24PIzc5YN>hLHv>>v-OQmJZHsM9DowlQLyOK>oA} z+AjsqUAoi6qI3e_sE&#<3bYplY#8k=3gnc6s5!U;?S+gBG(7}yqeB)Eqf~Ag(Lvlp zz)HbbXrk#-@2`%?bZ584?iC%y^^yA0Q|jo?G(sN0zPh$`s#?qDC&9+Y=hUEOL9)mq zOpMR13k_)2WExAUHDhbSI<}n(4Ie26Kl18;AtDVeGnEeNRiLGXO=%u5n!oMqO#KfzU1u<} zg|vgb#QSdmfL7?fV1vykN=|DeS}t^QqV5fJz0pf3`%QDaT%N_a#WFWrME13vOk|BU zt*FQ5ma;M@(~PsY6%Edj=-AdUysYP3 z*5)Wi2M;WPiUDP3iS7+zU~nb1>0+JE#Uu;~>W$B|$0A0(cPciTdNjjwt450<+nC*z zqywbvKU&6HUKQQ}ij?E3W+eh}nS>j{65UNwLL^0lH3|YS}96fICo_uuhF>ycA)=CBn?WQCb;i(HKx-n&96$2;rAg5bX>*!$# zK0|IR=}EkEEF6le4ePXtHuXGnDJdr#o5S!HuUBv;DG6qcSx*{Dd@6{A(-7(tY35Qk zLh`AU8_=AkIU88ZO(ElhMTHJ3C!~015Wh;68Vz06;nE{WlMPBEK%vHM%a6dggwHNQ z6hXseMz9s=+?=97jZnL$h01z+ffY{i<1K>T;tpuV6ffZ2Y*~%+(wI1WT3@X@Pl3mv zoT|ab@v?_gH2t_4>EdC^mI-8pfU4Hm&AlwI^)dq4(i2kf+Ht16Du}V=RT?a+E~0HH zx1~d#;LC_^O+&X(ALA_2m8j6F;szQ+Z$>6Er6D1^89#)LVgA*V%j~6aT2)eD*j6EJ zh~5Tz26UwG7F(0WRH5#xN)qV=ATC5By1~ZJ^pLu^(AQ}8{UirX=PAjSjISw_3F!mS|J$5$t8I;mGN{S6zTZ3C~ z^hP=FO+KL0iSH_9Q($CZCK^dv7chHS4b;N_u_*|c<6LtNgHqPVbazd1EL#&tIVzDG zpr-?YkQWia$Ue*?`$ubEvy!pup=qFWcm5jg4obQxAjKU_Ny?YtSw1cfQUrEm>%?Kz zy{A;R=()eN5iy~H6Thp}p@asE^(k#O6AK-@NZ(pb9X44QS0_y!zjdu?AQ}^kedl89 z4ju(%0?7LeooBI(dqiGxjHbYdf%8Md^k`gx_yF=*otCl^pPq7l1|9?K2C z2=Lg$OsC>#M_PPr6N6evQ2ExTgxya1H7;iliPeg6+~y8+oi{^LZv*tAng}W(vHAwd zDU*q;8rra-3VMXo2pSv2D^PL8PlW04;*l2!=!K@}%w&@~z{q7WicALv^IC?ELk;%N zVI?F%Oj@GVVwY+}PZ~d@wXLa+noSY2heRVTce94@{iK_OHKsy1Gw}xl;fm4J!v>5F z(pKZgIGkxuNG+P-bqQ@5z6jnBhy*iAWp-3e3<>l}O&Y=8)>=97q;mlg?PgG`9S~sI5 zlFk$h;^`EF4Y5)LQ4YMKF|prFBXJ6jTqGK6bYq(;7m1H*r;wLn4;Ic$x{BtR5wE!q)I^HcW0Gaa#nYuxd1lOQlWA~x#$x81 zDtjXgzqJoZy-dZw!mY~&McCNFPWr9Z$%{`}xn=HHTf!AKwU#h$ZkVNE4E!|FBksyM zX4UYFL#gcyaMQSM~zEfo_voxZiv9a7Ooq zzBiiGXCzs?O?Kn!$j3?Shq!V~rh^|zT`^zk{bulVV0HeF8(Upu)kf$!uBcTh=Gh$` z=H@3*$|k8n&MRyFWDG{DaOv7hMsISw=}+w)@&brR9vANOK}I?ci1jIG?kMtM5^=c9 zj|=}5w|tvNbld|z130BSPlCU&JHsOLM=-+a4yQ^5{Jyb`FggRXZ>2c8Eip2}01123 zC(DOlquUhA9YjvF%0n7NEh0QJG^rgnZPRX$c!q3npch8wZx?p*uF0(oTpz~TBCS6g ziM7$_jjL%%?-Bt0>RMUZ-lvDu3%eR2Qd;P^&`5e!&7#GvUszW(JT*pBjb}{D(tl?J z?+DyvW5_|alJ1+?(a5ki9=y8sDlyA~CeijBzMUp^;o#)y`g&I3d~LIuM~);5%xtve z;MR-GK0+C`wXJZ^3K`)BnK@r)3eM2i9amXiCMc!>RJ}C3tHyZ= zF-s27GgS4qZ2*ad4Z+Hu60^nTnJ9$VGHg;HTr%8dwn{8ZdQq;a(mSW+Ku}j$_6h`8DW&B0;TiVf!)LiaA1Ez(@nM7yn) zqd+uQ=`%ZSW||VTVcK;RuwqlE>RZw%ZDag+sF}0Cg1OtCy)*B5cp`Sy z>}#A!x}H;zvvRe$UIaxq}^P z1&CgM{s2H#py-o6`@GCSn!mv%2kI~rJms!djv+MuJOUG4i_uYY2hS4 zwL+vr{`8Gb)?8GIm38S_m8w&SB$*4kNWK>*-iPDiaXE8MK0}nRW2lPN9ikf%>HaE3~8GdAI^EnAS{yJs1(Vh zk=We7wudGnoE4wI;u`h@4Xdj^Y_r2W>`C)!zvaFPG|};dIMVj1mRj#5?f*z^BMh~r z>jb)6owgWiz@TOL;$y|GMDUTx9udyfskor5h=#bj3_gre*g?E|sky8cn|}h+*cV9U z>s7qfon~=L{Y2Q}cQePfCT{!l(d5l=OB{^uR8_;sNMpz?zs6v~+xFDMQo0gqm)6@O zDA_n*1V3}zCML~|NpgpFnt~&fJk8t4!6~ZzCn=*q$;xoq=jqg@K$0~jBICPz- zX0?(gwnA`_AgG@YJQRHS?h}!MmbwdnciNTYrn!w_~0+@RKr4 z$X2)-$hPW)@U^cCQ-Bj*5re~LT6K4==tOspZaqEr&#loU(dpY9V%LT3UYy3Hy=}o_bHn|r_C1Cfe)m%-~dkamiOMKcWQja@`%}igmRi~9>+ft8S zz8&b)VYyi@+v$hT^R$;Rxyg-tRcy34O{&ojTP|;iv;ab7P1r>>=Ej8uI>3mTxE5JA zQ{|X0Go((LP#on~qbQhH@_;N(5D=(e;DQj|AM4#Sd#r!lK*tEcdoH2f^t zNgw_NfXSXzAS?UGEp!?) zsEA_8lFEF%M#X{W*+>#-NXm*_C$=2joTvP(ZcPC&zV|>sF&%nQu4x;s30vX;ac_QW)>trTUXJEb~ zu*UGd$+7FY`m8Sqsupc5z#A3Pq4R9iEtIp;JJ9zZ2yLdZZdd*GhO{$4>^}r&FB9Om zs;mi@J7KXbpe^;+QZ!L-<*qiL@`;4nI5vFy?za`eC?c6gA zi;ue&32Z%(4pr==#~F>X*GIOi1cq4m9`obst_j}+=bBk&!*y;-_v6uI{>L=xzEsA2 z`ah;o7d?bY1EnyTEy)z6v={Bx1wC&cfl-(qmS!63%h-z2WQ8VAPChoao4YS+KY61kovA070FWxJv4Om?vQk9ijyA}OnnqoWbz^2(6=OKos zGh%m~@#!eC9qS1txHIA)uvxa-xQl*UxMjtCj21Lk@>5#+xaH0|CptLE<$Mj(zoIFR zM$-7ZrsgpKK+xY5$uSq3@U-DJ|kP_?*F~=?7_-(_t{`Stb<3; zc(PNCHETXa^V`aB0Bfa9Sj%2SmYH)1LJSyp!E8(__={+6%;mQ}VdSn>3c&Eq+l;gv z0*U?IYlX7A95g?`*k08S^Z&f+)W)N&evBapZNf9ONs78GK$9cVY;fsa+FkIJG|D&RPF8{s1<2&6FTM7jhzg5lqW&!ne@WM6H0_(F>DTHZk_%QBD z1lb&W(OR!)+_FU;JKwWGM8I9!``%aExU+wu@Z;rUkT&<{E(Kbi$zOm%=2w?_!1$H| z)2O#HZ=j@ql}(nOK70QDDMtJ%=fQq?l5`mEmwW2>q1<2WyDTh$@Xw)$prC^Ba=MG) zu2YMZD5v=uh**NLZiBofn@6GT`R`c)WGc~9b+pg7mq{ooK z&M`WaOIn6xjAs%p$SCnRyj=NZ0el(q1A`KTU`~Ag zPz=jv;fNPqp#d^%hN}Y~;Vfm%wlg7M?=x{haD8IHByH-XoM2(311aYQocgyTfI|T* zjomn5Cs)*}Z~C-JN48?s8hfj(gOf~H9r{7(Vz7+g3_dc zVB}-IRJ4_X#t}&rq@9pGT(ch*@^}lwd|RnQ!3FO|ywu=1HKjQi(c|kU7v|6~GFC`B zv9e7avKn+- zBL%>DKjRPl>lwK?nmy97ibTO&IQlADXlO-MY67}$FUsZI%6ec#<^9n-Fr9)6ptnor zZS-1VFFo-Ui6~tHZapZC`y_FMI6e6i72+l;%0Rw`g}&Gk%LwM#Z;yv78FDyz+l?kB z?V;ZqIr|7<9q}nI{Q8g8JkiG!|5^C&p14Y*ozbJ_D2!0;CeI!R;z=m;9d``Hde7f4 zlV2b)odATFI3jz0BSID&@O=9{%t%ax9uyTehMuaZXW=Fa6Tv&^L_S)hp;FR8PhN$eR5Su-TI7QfJ}R~ZxoDi!y{V2j39l}W828tchf|txS{j+utOrNd z*;T3O^2z36txi??W4S#sXd?FUG)XATP7>xW$!Fp_CJ$@SCP}_pAW12Uc6zm7LjB^t zOb5iNV#)OsHV=(~p5cS+Wc-dl2D`Q>gPwrRjns#|_I!zd;q9g9r%o~!bw74B2+iBVhi~* zl_|*r%PsumvE6BB3+)n}JBjpgCF&@nV0>NIvf9HE_s4 z;YCC$(HJI+M>kxZj|0q+X&h@upUKfNfeU@A)$)iWA&a;^K%c@o^h6ZP+NeDL3CG8I zqR@Obg9_=kG|`F)1l8a5P<~N+3*B2b6ih)h=;eM9?G!Gc*>@9+ zuC3koh%kMm%O;I-$I&87$~*?KBTf4N&vVX=J=$q0gy=S#l&)IeQmf^IW|@ZYwGd%+ zMMF@ZViIrCSXI<4GG7OFvS`n1H<)d$z>6d0(Ioa@DT#vMmacl}&#D@etP}e%0Iw_- zmv=;>(vlk5)wm$-?@w|-HS*J;03#O|hyGR|BCI(w5tICW#dA(pYF}xxA{qy9#D_IT z3-!!dQ2QHdV&5MzVDfRx*G=V=37-{->97`u0N08;S~|tU!xJD|_lMc)Z(*FS>APA4 zP{7_^4pLx0@fE?uHu=4xcy;3x8NZl0caxs3ySB2&5?;2IRd0OjL7{g1G7fX4F~PO6 zkU8niAPYt`W?2EbQg%O{(?hbZCWi~(ZeydO!tht+o+I;H<=G+Dh`mTP?JFjN(SDCI ztoZU4r8>^@Gt{nLGM)meu~Mb?C%U9cKcB^bA)GYO!M$krVjP^Wn5vmrs@ADFl1o{z zxlU!toE*3)73-!$BCT;?OexT4U*=jPGn-)05|7GJ6^@mr$KA@0Ry|@e6PwOTA<14b z;gKpzc@VFa2oM;46i1lu|1OPqX@t1N8@#*WWEm?8GIe>vU{(Bnp$9$xyyood{ z7@Y(kPgln7|0!o9S|P_h3N8CZqPr>@QQ_GU@cZKQcem{7seNE>{Sfv&x`QEXp>V&w z1I#k#WK`YSYDuy}#wblTD8ihNa|wzNpg~h%@>tA0TPSIMTFCRI9qn8d$E`{%$TWjV zTfPJwA&-Rgd8frchfX3>WY{rn=NFAeLF=ECaOU`F7)Avq?0(Ta8+;7cD^=-)BPqy{ z;Nd~H9aU+T7*@B$K{o~|PZ-5sEhVu+iTD9d2ga7P@9qee_X$hWXh2~6!ge8;Fc9X= zPwWlv1bcEiELmb*rO>0NTHZuM%)$&!{z}5QzfQ4MyxuDyCbTx2W_`!0txZO1n3_dP z(a2Sm?0vjkXynkKEN>NFm$OuKvgSQQoVVyk2pL$2HVUwUSTv#jWx8a>s6^uwWr+2- z$GmdX013|wO|%cAQ!qpI0QRT)OO0r5U)Lu{8B4aYg(Avcjbn}S74<_+B@gA4gDFX_ zxsy8^TOfbkfdxD~M*8AMtD?i}-XYsQQ7l}0X{LJOT2b1ecp+B@htl_fR`i&~u1HC( z$SG{V5HY((Q8WI?s=ScvLULU#VV%__40*#W z`A)ZhG*9#QdXM&0cpCoF{TO>IAf^%T;cFr5runU5`RN~_F-X-)BPU_9%_7T~VI4k? zVK@jd&s#rHm;|roLyks$8CkbR0{pFM8^Nxj=1h}C@4wmaEzHQup`pz~uSm7vLC@cc z!yP$H5XVD2I!T*wU-~#DZII=ZFs^{Ka2lJ+0+VfJKjDTJrw3TcQLZXEwv!MIj41|* z)=mlO8zIs1Ld{%aMckQ6uJ?FO`=CAokZV+RgLw}4$#k2T2g!Ju!bCSX)(*n*!9?0+ zHt;t)f@i{!4V*6hkX@pS1Jrl?YxoMq=ZNDfAG}*4t+b@|iV3v8G^b{s?lqPskKac&{j9lEsAKvk{$;~Fk=)t; zo}i(M!3@p#&!Nadfft{Eyp<`N#yV;1)tcp8pV_H=fl64Y83{j8ux(e17>P&eBYRhv zFnHcW3k$Xx)AlP&yg@sk=rw^!E3M_GLP;Qxdj1uQsFZ|0eUqyFlg0CCYpJ+jCfR>k>c>a9Iw@)sQ8_Glx6uoBzLt_ zLtkQNd+1}fKz<%lG>XMD5zX6WBJ8b#UFUk3+UUz!Uq=-W;#4Vy_ANc`UlFjAA!twLTX6aStjfPr zw3`PXsZ|&A>H&>ta{oJ-ue`iB|L^*{@*$+Tuej#(gzDeHRkHnGH|NlKQ*8K^82eKQ!7qz z(F8!p5`ZVQZ#t1ah7zxJ!0Lq~r+@6x>#@xVJLx>A6TB>oVqZjU-lcy8PmKyN+1S7` zOOtNKd)1ur>2{RtCJ_>R!2h|-C95rwEs6RZb$;{M-!tSN`qZ`xoJYX7JGvVHXJkVh?#2E%vBztS*MhRF}{r6x5asUbt!4-!A%Ku)GJT~jj_%@Zpmz1?umtT1oX}zbGJg7`| z%i6NBt%Z&8eXt;m_I4n?BS^lkWRi%+I~s8{{-j+9VNd9y_7xY3x(5fD;h5X?BD%mv zQZEiE$zeniU)O-wXX=5pv}CH6X3WJzG?(!4lvMO2lG`+P%=e;Uaew9Kt7JR-6XAEi z@kAOqj5RkfnTB7g;k8W6Dqab~Ge+AQqX<@8H)J(l&{8)VpijP+llQQ2E?=K#iWh$U zoq^FX%0@yKq%Gdca!_7}si`}-8NU(B<$@3{gEvE!x8&c(PfPbk*#4G+h9geR(x$9p z)_>D&?mnO5GEanmjGnaKT`QTroP%PO;EF;oDMsqiJ@l?9s#1y1jioVN6}RI4K2V5s zd)O9hml!xit$PO-yut4J^%>{Hd|2uEYY~=Y z0DyAcBHC~rAuxVLrS-SPWx~+P<1I8qe-edj2r|qGqB>9 z8p)@j<*QeEo)r;<6s|Y^Gq1gFF{g_8dyY*p?Y%G?Z9O6yd712kv!Y=e8bioMve#u7 zsI{*pdlq3g@>rpszNDzaHSQFDO>*d{c71{U$JTX(eOGs~CB!-c%DL3h7ii;_^!$%R zjII=QSdppPOBYo1R%TF8M3GUVAd>p^1=JuC;WWY~0$S`>eRnWv(Tv1FY`J+f*V2;A zzFjj(v9nIxh@3GZI9Ww*UfJcU9G2NP-csik#eR|+x4=DF?P^_ePQG`gD?2oHlEE1DO)Y?kQts^_4rth4Fm=$s~=olm1MPfVV^p*^NQZEQ#9jsq|l8jID zO4?&=bu9Yokl=7|Lcvmaw~e0qSwd*VAtUeD4K+w0mD0@dySdgm_pcHxLu`~)!iH{n zhJ+*GorbT&-Xe1Zs_dig*}4A=m?`?io8JcZ2XS8Bpbx3|gBAqp(>4stVjcj(Q#xtq zG~)qVREr_@(3k~5B|j5B+!N|z_9=#YPvK=wD%&wM3+i`V0{AoUCHjFzdNs`WL92mEx>m397%=!e9tfV~X!RVIeC|M2a zT+Dn$?r`(dDJ7!536Ewf*ADjekhD^-czjloQQNeX+NCc`4l5AxlFG(>%5Ik?M@6gP zYh|Z+-(+7FQBlsiEV!+BF)^L#(ocuDI65is4e=nxqi^0X|2ZMwXg_jVl%bPJ3sZz0 zQ+KPhtJ5_85TQD8daKZERFkMrYKrhwDHi6}^|_Xf62O;bcJSZ3{^lRvh81%Dwe7d5 zxT1Ifu}88TlLS)07vL27ix~4T3C8}0qPBf-p`D>5NVmdEB4Df%SS73!~ZiI`qGMM4&6l+rIUzOx{iZ)@wa{$JK|(oA5qNY=jg*G zL(mgo%~2=%?ws`1-+@ zsv7C+U&PN$+sjGjVs*fiH>?q5Midx49m?~z2T&|zdbE`wZIrjmH0FLUc?OhOz!zkg zI)v-gnn8eryvM(`BEEK3gr41cC=Zsy^AmmZMr4*DI!4%d&2Kk&*xJJRM^#>lxoHFlN0RKy~|z`Pw}^|J@}3R@UQ{bp|PjtS0A5NA}a#roiWngIi+_KW!BrblO8Iqg*5LLmPDIcCd>mgbVG4XAlj6QVX` z6XE|ID~{%qc+)0)HhA8eB#yfh~ESt! z*r>cEz}#;e4gEPsNn%@X^aaxqu-MA}acoi*xe>*Hlm0vTi9sCtmUn)f6Y^^D$cg8L zbXNhfD_hs-Rrsk*JSv=UtCXJY+j2WMUYj=ET~#ul34y+X^$a`!P~DO0`xbE?e3!JE z@`||yOU8`Ii5iZ2Z4t=kD=UtVp?rAG=6;rX$;D@-n$yutaZ zNt|v9Ig6e0S%QM0rK3uzZ^OL#z&{xQ>I^j2-#gy}hJ1})MZH49cGL$7TDn_O;OkfO zk?B=MipT_a3>VMlXws^G`Hq!@W@Bq))Q-dIXsA54)o*FBXi?cC0c^o9|} zX~v&(?0&lV7PmqzMdWQ-Wgm#Vq9OX@>ZTT5#M{N2pe}i=L2dL7os6)(*zM$G7^1>m z?k|OiRZwsFus{_{=ps}yhZeCt_U(cW%M>c8Uyc^vZO~wfF5t2aL{cw4psoWfG4Ue>|>w_JrbMiP>skxT&tEcLLQNEDA;3XySlj``sf< z>My0M@e^$!w$|Pl!>naWj7GvQJqYJCNC@@CiPL2u-(5dCQzc#4aT^DY&QLv&(}@U;gjYurg=gG%TVtU8*^!&3vYec;vy zk&ZsBz@-sU6*o`SKJ-PhiN|cZj+Xokz3x;zsghKE&5Zky_MmN;Eq*G1`^VzG-l13J zj{JSzn)HG%Ei+{S5`m{hH&ZCnVj?vtOScc~icrTR+FM_ZW!YOrM+p&; z(p{;jXd%F-hNjI=4w3hXtU3WzJFx16Bq>b}6kSi|i3PS_V&cR+L4cPc70F=dVgI?K z3Ji{z-`bo4fi06`VcS}qPc*5Dug5<+70`tmg|ntz{`^%)j>ST18O(}Jo2V#kxWmUE z-{h06wC1`a+tC|1{7Pj_h(d1W3vR|OMJ}xejAu+v`1R?}M9DJ7nKxn~M;vc}Yy<)l z+f=6vD6Pf)^997scsDp#Q!EP@cF`D$vUpUAHq&DaNMeaZd~RRJN!tKSO}L^7tCX21 z84?H?mx||CW)^(csw4R<7#a(4YKN$V+U4;ry!Mf1eWNh8ua@SBO;=pY&5=A^A4(2d zYx34AdtnsIl@hd6f}#VrRNWj@jnhsABxhtwAY2i0#u3v9BdyrC`Dr8ulVt2_6RBoSRw zb~u~BN;5+44#qM{$nZA(zybOec@8>!9F$?zmJDW5NarMQ#TRdHr5)F|i6S74&$RXn zN2|tM{z9EcH0$y}W2yGFT(|V6)&8Sz)~{v;(HRoQ;?#U{bdypDE#!UX{q~1%4Yhdf{W@J&h%`W)i5>T(J}uVdH7D`!A-3nq1+*8DNGYlFj(26HW9QTM4`xOlomyTO3Sg4f|J|w%uW+Pa$7xla{KI!5PI3Z6)bg7##|g$s3;E7aSB* zX7MS1_Qy!qrEG!EfWgA;u`~{A)E2>7mCqkI_jSWsPM9^LbkmZ>J_sQ78~DQooCKx56Zd`h%o_iTAhg82rlEhm zWp0P)mMfHWcENN!?k=!^4FF{{N}5@q&q`=k3Eg?2pp#i39+@);reEgntrq`7gAPNu zCP9D%#8Vwjn&Dx|L{Qi!4$E`XM@DDC!gvH8^Y63L^3E^$5@i>I*I z5hi&7_g?Dw)=v!`9#`Ux5H0sJQbY?qSxoE62v68&<*SMwE4ch8^OkFmA(wn%Z7q!P zw9?nQdWfRxjb+1$K(AVx;nM@=2($&2B!|>8mB4mgzi1q2xCkg;m17P-J5?tkY}X{t z(aXq@)ac@}J^0Bn$&&r4tPv~CRMY{C;rau5Ch4%StH3+@MvcIkAaKK8gR#}Y!kTps zY+{QqN%`Cf?2N)J-ul4&QeYVsWpsX$nhBr6z=~BnFZ%Q{U`MrZ4vH8gP>DHoE)ww+ zsrS$-!Ai(2hC`Gl^_HqMNf{;8EBMG}T^_q|nesd_VO)g~UuPZ-=7br$%Ft6UqZ$t~ zCc-P)Cd~ZlXzCsuhR3MNb$1;4SRD*>wbbG@^W*Mtv{53kr&;_ImpJ28e^_d(-{}>b zpAizgzcbO9P=NU$j1ZXXHrF{l+thGtk#a>I_moo2-hJ%?pSPpOYjqn7cC;Zn5+zuS z1Dc`0`Fe%Dr3c3R=Gs+U5igEKh_%QJIA4t?Y+sytx?^Z@9x20 z&4szeeB=Z&AdWq&!bwOR!>CG>#9{N(6=Ajmsb4h4efvseQBGz|InMapz z!E5+yVNM-trHrY2hqg_9gOkM~jh2q-KrhR1olrA^v+?=1&{&B&5V#t9I9dF=>w*_3 z@i4XG>}1<;(ScrNy(j5T1;-_T2~$^!qTIrj$(9>BLEy67v(Walygu$FDQF#~t*K$E zgbwWH21cN{rePc3SHK+~0rxS_K}0tw62;ZP{6A&I@gMLgCYr}*7FDuwVe%}r3u-De z`xMMFtNN|sa`%^SfmvDHhS8bXM#R}VTLVWY1p4*HOJzm2`P6Td7%T9BwOMR&bUf8$ ztrY=|H!&?u;h;%{YBTRI0cxWwl1(h!bZ<9<&JHl_scbjhhg$LcVtR5#y_#BsHG>%! zD4%`XO7nQ_c$Bls~&v!E4$? zReA(U{$7}8CyY6+kusM*rxd7Qds5q>lFbUf?Z8ZdpnNhWCs+> zKv4?R)7+=f$U5c3MOgFHEo@#5hcRU-6wz&=6Ap~>2>W~^AiDx?!Pe?Bri{aNUUA9$ zW|ktl0?iMggDfkP~wp+zys9OFc-KX3>0cS*A@Pck6I1W+)+ zF{^K57hATFv9PA_L}%{Ep}-LK%G1;WTtMjn6+$SYy}kr(KcE>Inu_&QtUO&^(@a=? zwsvQjt|F-&%Y`EdU8vHTfhP&Ip_VE2CJQkO!(*|-!H__^GUViBN!^2xO66xY&TMAr z*m>i>yv?{u>)JUxYO16%Mbl^`k|tNAB9Mu12KWW5(EGOiDzhk`cd*70{*cYb0Z)zH zgxQ5hyNbVB*C(RgKWeUsFq1iGT;g%83u(i45Xqm^};YTNOo=n8uIK zNK2kV!r;&XHO1^RY9?S(0X1VRDS$_OEgcr}+C?Os)-w`6J-+qST8Ru1@U?oAjv>6P zWp&kg+A}E0r{6INK*yb9_JT8p+nrM===#Y)StMoVfYo6*l9y%BG#BMI@PxI_|zEm>ifRc z1?$IdU*u)^T68AZo`_u0yfQWAVx;cv^1~qJtE@Wjn_3&!+(2q=zBc6{qjMc&^GIV? zq3#W5u;G*z1!>W-V?K1`uc&CQCi0ItcF@k9M^uFqZ<}37>yLVRf4aUDBpJh|Ht*E$ zcygiIlLP>i#JgbR-Hxj$V``KVv1gFdANh@HfST#>mYK+;C7yEiEPa{%odOVSEBGdX zJnR6`k(rg3?WYn6bz^hys7w69>{;W?vsc{}Yh4whd15qWR?fwTJBswl8senb-x@oo`ll@#|-&&>!;sBl;+iKj6eyMC}vY8LTkQEXvv)hVtM^c`p8%P$d* z=D}*^%h4j%uuNynzmbAEVmySiQt5~hpDHaSo0U+XAoa}T9@5bBl&%*M?#tvYWPN8N1Mc+%fx1gwTqb>fMs= z-G%=W2m$o)k35J0L^Q}iP-8omB-;+LT@%4Y+T247g8~8Q6nOeZ*&Q#a-Er)OyY}?T z^MtmYG32O` z(fZQ0I{-PC+&ue%(dFKIHkA|p2VzJWLy=W@^au59vL!wC*mdSYb77%~g3n*!JH2{d z`JB<+hnI{lSDB)ltIk@~^@HTm-ce5N3^rP>`B$2Csj&oYKFQ0JotuBKM%<~dVzX&& z63O2vy?S+=f@b&Zl|`_{c~fu=&fWLbsGD4$(43O{CDKn4=f%AOvyfUB-~^8* z3?axfJkMKVL@NO|$jhyEAZ#^1X{1j{q}Kp@7fV1FHd{ccqOIT9z-N-UvWXW3;$znwgm(P7$!Z_DzLEj;3Z}hxXPNq9{av zuW8(?^6?-k4@N=Geu~x0TOx*udK?p*W}6+S!%fZ0xH$h@-~l}ZTgYl2iu=E>QKcnA zZ*jaE#LDCZnHl+rOE}Gu?PV05PKD$hxaL01qYeoip4YzV??daYH4?A2bKoccKAu0HPMBw?LLSt(YMO~KPB zP+O5FN7$~;VupX?Cx{%Y;|uz>^2}1gO(V6phu0{9QoyO?$eYdw4f9Dm^)BO=B5?Ji zKu4+lkigc}B<<3=kkBzg*q3K$LN}g#9Vf0qMJFaaG-6#BKc%1G{KfoRaFfKJ;!0W@ z_5An^t$w?V`l6FVtRAUlQldu&aXS;ha(Nu55r-y6dHkZ1 zNYt_cSklO;IQllb8M{?B824E(+y!R?=FK;DZ6u~_s=PpCIW=`#&LYrHntcvRwd%$Y zmMM8w?tJD4pG@M;SIp7yHBD>1NG=pse`2!3SAzi01Y2YoCib>5rXnPMKJ5T$nv~Z8 zDBbzMc$FGJ(PIvPS-57$Eq+#FjzrkVO=+X6+)VR%>?@jlC@QJI$uh(=u=OOH3I`xk zmBMhUJ*cUY{+6=xW5SoyNmNmGmTLWkSu_jjFB-&-3%y*M!89yg3R83Q3j`1t8Z!I! zaE=Y7Z~I3^2?KYFzO<6s_e>jwDo50MV5&2r%*e=gO^TYgKeQ~PSdQ1J&vF3%G)0;eMfhlpN z-#S(;-u%tUp6?!`ii947Iqbi&{PkLmM2WYwX2M}`t4DQK zoBv!k{f+Uevkjl;86=nnx1czgqlG8Vv#JinGil{w-b#6rJhTOB?3#YHV47DvF9e$! z3nVKe57j}l$I#d7V|G=Ljp=tnW!@m6F65z?1?wYcJ5jFW1*H$o(VhJaNM%^*jZbS^ z$>;(00Yc>YBtqOrBkiNoFk9<#dFTsmQPsM$2!0V1c*8qV#jm-W`68Z(@K2sZwQL1; zGoVG2U+PMyNkLN^eKA(`4NG*y@tjKfZ^!CTBE8_jzC4LV5WM@;$U4W@6@)V4#TkL| zx%mXd7sba8B>J31JDJ~-r@go7de$~E0eE86-?hX)S3Ro7aie_4YO@w|X2DurEu^uU zu1YaX^=Qm>b@KFIVmIuFx^9wKT~g8?LKu9q)G1F!AyPkl1ryyADAs*=6pvbH9Cs=q z+VMkKuP{A2w@(cs)mi$25I_4>8V5WD)+aZ?-NDR2#JBbS3`^nn{j{uW&LwpB28H$y zb+S}!)Tgt-RO-%=&cr*DVi0GH2WBobjrOM2pTer4%W7$K6nlB!Q zW1XZ_MGfresN3e2C$D)s7>_WzNdt%0qT5sc8`X&)b?JD}rr>f!TB!U$kyki0D{xz? z*m#(sKl+Ni6S82Ev6Y&; z@?+!5srQf$QE3@CH?VWiy?s!E1sSJUJ(`q7hp$&{?XgehC zM)Wt`E-BZ)ZgK`Dk~P1%uB0}1zQJ?>6$$T6@Vt-gUA;ekblhoYSNX}gX!OKDg4tM+6o7b$Z}PMEN%8}Fq) z_nOuuoALs|1&3|k5{=*?mk^#q8}(e|^JztJ31*7tfzQ2G6PLn@GOa5N&JzZwlj1TL z><>?B|Hkde?qP4QcX7tQ8SEP{+?J3=_dKm-Rice~XiZWicu`Rar=s2t%`-g~4)_XS< z?ChQU4Y2#Q=_<|4shikhFufrz7Sf1E^X>P|IgMW5j-}h8UtD;|-picc5lutlt24Ho zl}d~s91ZOqBm^IEskhnfd{h0mUS&qHaR)i?Ts07!xt#f`7wuID5zSJ*-(jhCQ3)<% zNDNBl0p2Pa`rk&^VG-z->ee&=cr7^t?+0yik5U)-uOo`AQaY6Hzvh{J*8g_HxAX18 zaH=)4`%*A0daXhI!)V^V6gj(_)A9YE!~dSziKI#L*Qd=hn*~Z)EKeIwhXYh3G(YSQ zJ?fZJ1mRhj$;{yY6XG|SD{P~GmC?Gsh(LQAJ=d}WI#lX&c*~7E5K^ill=0t|TUp9B z1w-RkyM3Eb|3EV?RZ+>nvhyYC>BT#r^RgtS^C;(0GN0_tPr?l&#-6(eqZ2r*0s=#> zTcl4n!oxfD7op6_BRYqs890+fso&dhDtx%{N39}hq|8^N_%z7}Jq;~c^h8(2BoufN zp6U8!8of-aFjE~Rs>(<;eFq7XvkH(-{@$!4$0c`HYjs@1xFqasjhidU?Do1TVvfL- zLbEaZ%?=trtq)`oq`Z`>_*pb8OK40Yu$4%rG;5b0FC)6o7*6YI0sN~n8A zxzC2zT2=QCkI3I(H=UmHwCr^AWdEfy5FQokNf*Dnlx<(@jZar|(Ha1BdUehwbtAe2mMtcb^&z=H_lgn!rQzDH8H} z=Tgdzk>0c#^@Kksa4qIwWTmNp1K!rIA)@urlZSwYmd~iFU_=>5oy4oT2xi28H zimg5br`Tk3h$6$6lIVvOMj@Iy3i+>S(v6HJ1@oo7=Lq&4khEsd4#zg?9Yz-cXx-oB z92ng4-+_Auc;r7ro0J*1rXp>e_A{&?GP zKe~E=DLFNw_92XO|GKe+B8)SV?LUNL{iSYFh+!s71p5bqSE?)c0D+1j6Q7iSm z3=z2X;S;UE2oqfO`(Jq6#22b90sp$!I%mJXTZdW94etFZo4M0^zz)8iUd;LxJSjzl zFVeS57GaDM0QXQBY8UzWXm*aVn7;)uLk!uNgTIMBu6>YqRs6Xwwle=%_-#7O5r>g9 za+H?{r4hr6xTe%d3x!nDn=f;)H}wm1LgYEwNZ^6Zhi_pc7%{yr%3=Oaz`b1eB--!LV;iP=+Z!7HV7*7F)B_iWr!q}B;7 zZ|29?Qy(089+0C!cH~4(tYc%;)&am#gas&6B~OMYfOyXb`^;fV(tha20D&(M+Bty0 zpr|;UNfsb7@{Acg$gwNTviAY9_wrby(~#i~>2*3MPdy0_a)9GsvC0Qv{K!E;GRB_A z|LDxx-4d(^nPYeywNTFZRZzXZF`yQe=~rk}X!+_TZerP}h4l!?d_$(Bix~6#aHSEp zw(p6C7Rn+|%{i=F*gz1<$0RU%TZu;ieTuc!)u;t;mW^qZ=o@$t`o1URPcCSqE_pyQ zxW}~efUCu(0K=Dx#U8i#Q^S89T9+DdET|5fv^p{}!r>gh3rTWv2< zhr)%63u2$b%m?0*V(c9?io~|oio~R}Iz-S;qkFg${0jXQCTFdfc%OUug@ll3`65DR z_%L-Go9!KI^peMzg4ocdbi}^zv1U@t5b#=<5=Y=!{N^hB%kcM^vRZ-i7pvGyD;*Dq zxjm5i`eE<%%+rX{+DM#P5WN4S7?x_+OLGKz_eAia7Ltb#>A_duek0AGsTHNjRWfSj zp*8C1qSxI=d;7yA5?;bU)pQtUGqS|NIB=9c25IootJbtbBRe0R13c+M(HDRitc<5a z2@gtRqA!=?$aNz^3Qcpok*fpzjFU`F2jkrxTcigNIjDs3q}2H@;pg05_BbJ3VTIDL zf>)Hd_kTm9mIMHOOeW+pd%YB@Xr4+7UXvX*=EuTp%=&AGOe-+HT-_b;!A2*uK;?i` zQEB~+v|cngsXN}oLpAj8Do9={R%JrdWspn3?;(KE`(PX|hcVs*`FlK{0NKMt>xp6* z=1qTkIg~4IA4{M#tS2|cQ&4hy2y1wHEhCcJv@#;=sYqv)Ic|2>FD&pX_zm#3x%V?r z9u4}x?KtfPWsv>9?KlmG6z{|d`2q6&Q}DLqhe!t}N+tbIlMb{>e%UdxCzcpoFMzMS z9U&wc1fM{io(oZDjR=nk+lz&SFv6X&JXlRBxM30|I^?J*?3R$?iXU>LD1~Tg4HvEZvfc#kE;t#NSeg z@~$&?sx{v2%?o>dkQRg*4D-ix{{%P%?fBhPz?fV*&qg9Mh*t|ROk9^f%6}(NWrlu= zQBmlodj7iE+M`$tq%~a$=BQXe@wkqSXBS_{yo5e0}NfmkVAKa zlypmXGeb8+gQAi{H%NDPN`t`A0@5Nwzf_V$yw+y}hE1Y4^G= z-MLy?*UD+%tL^5g@qSP$VvwOU3o>udlXqZO1%s-AMWx9;6$il|1&g(WIUQ1XlRi^m zfb7Xf)&?XEJU3r|gmh}+eHu(S^^&vuv+l2W`j=oX2~*#IO8QcMaxDj0_?=*86xdRD zGjV#XUlg-Rdw^nNFOzL~C=^~uL#s(tMkV?wzFYBzP2;X!_W7I0J?UlaS9S8m)<(ss zmj;m6|B2>OruiLt#3VpMgg7{sCfyKz{{xld>P8nA;t{L(k4?Cr;3~8(RODJf+r>}u zN7{HWS16Ij_EQVtZh;Lx&`sG`+rHQM0`)sOU8qZ*SsQHv3ODAm%brvEk`B3_Bt%{|A zYWa~~nc5ijqm0BTHp%TK4dSw`^J|(G9^y_;e;c=2x|tWOcZ)ADPOUld{MWfM;pSi$c?=G61e8|KhJPEwmeK@O_>%zV_+@a-FnMDY5N z&sSV*QAmH3IS`i^lj%;7W{t6PSOk(-46|@B3N$q8X zD8DhwP*#DJC?(Pn+sRaec#pXJM!&xot3H0J%(z?s;|tf$S6kT|F>2=s`AOLt8I;7HrTn{8|lycJwxCA{&U;y4{q`5 zgHDrkFkWj&I>_0qt7?X{wx#H)+ZvOzV-sf(qdJCIy$VhF7Js>QU|suj zb3XG)o%aniu>%h~kBxpD^Txy=$n43EGBepvp1uInJ$e_XCmTKr)&J`2V?Z(z?8?E4 znr8dXEveH()XeykLx1l3R$Uw7@@B<{qfLRTw&mo z920g`Y%wk=HZS{+%&rP|V?Xi&C7-$YqmpobOeDA%ZFfOqwI@WPOx|1+H#qxm&U~Z( z)59@I;CJI67Pj#JM+@_B$3r(;|UF{f>Le{%F85QLc9h$7NFqlD5D zkxy|d=QIo{7bL)>Rz3}{({U=r|Ni?j(+P$ z6DX5xP!~aSec2m+-oJIaLj;f4-+kxu>0SMmD)lPArF+V^$FJAKY*q1-jn3WV_o;|9 zdoqS%jnIp``z4dVp+PjbzLwJvm)f0Ie@Dz9VvK?c=aD$bU#tO)y)UP}Cnt}__1I&U z>QOaQ4!uR*?Q5W)xh(63%#R2KtxnYMb^8?#e(Gi=kNH2brY648kw{gdwl?qwI!Q{^ zg^b_jQb8OFK7r<~^e)lChESp{CBH>TAfd9EZu6J_WPY?JvO1y~T3Ea1YufiHeX9FO zTb{bC8@x5kr*I3AVihj4xU`8X)`0QE-^MLIT(WKR9{e}2A`ZGrA<*WSO=Gf;`jN*R z{qjdl0u!(Kcg&Md1|P=D9Zlt3<~UqxKF5Fr!w$xb@-&oULnV)E3`7XDNzs4+vJ=)< zNiIeoKh*8yh|n7)Db@0M{cw`*v8vo95*!?hoqE=ghA$w3nH+F6j^?&(SXDomG>VOE z&L@i}UwqCVW9&ckM(PS3rLBLFNz$VkU^Iig4Sg}3W*pe|JKADP`e3HL^QmHk8rlfF zCcJN&(W3T{vI*ktyS~mhiYLIF4{Zs&vsOGrGzBBy@Lr~HrH#B#mhAfvD*Exg#b#zg z^=vVrSINt7Eh#n{_c_Nnm_o_%2)h?zh~yQna$MG+rQlnjGUU8pj-%gzGJd6Z!`XCZ zp(asuiTfyO1atFkX5`8^rD0|WTP>02uc7zTyi}RR{me1QvMk2{#U550LmZtr}%gju*g8zfIVY2$k_vkdp?*u77bQ#p#Wy;y}>g+ zWfX+`vpe*6yTDH0^TCKe>+UiB`@~ozfWev|LOf>_|FG<{yrxr z8r}M>3vela38+{5_A#RSzmI?ZI|Z>pm_?XJH5jxKaJA~+nAZ9%aOxeC)z{*f{xWtj z!be_ye84vSn{C(L!)W&A;U{pn2MZ%5{pJo^<$srb0R{jf{;$5e0Fx6+N@N_+jLzsQ zEXaP{{59M{9uMcVa06o3GLxct!6P7|mG(UQqM0()56UbPV6iBr7;8G+P*r(qX}}ww z{~jLeF9K)vNXNdA(x+LDcNSEt>$zGE$74`Z<=DxxaR)x$)R7?#I*O4IPB`AUAGx-$ zE=SWHvZuK`t_4Gsq?0iwDL@TzNOSP59eR!-_Q{Bz+x-Bx;m2~QMtxO9qA^&qW^NBV z;#P>U{p9u)Yvr_8@JuNIrbX*KclPL&ZBT z9@%>{_-Q1uF(Zk_$S~gAZ3(fRqD%-m9X{cdyA|Y+`ftM^d$+w~4z#4PHq(-&xsFKp zMPe`oJe``vo-P-pa1SrYXQRY6w+iDMjXu0?emKD7s+Cds>S3~W$;jXat>6`~R7xi?v8%%5{ z0iPAfHDYAyQ&x%?BXd(^el|`bTEZh+%%3*KXw1ID;<#Hcu2l$@Qv{!2MhxjGGj06w-k<0WFook*`z$oMb;Rq7!JcKWS(rJ(PSq?$CiW|DP=4(-Ew-n43iV#8ZBn8n+esQA4%$rvgX<;3#$lb3Waa;) zB%i1B@J2S$O&vTzk;Q2eJNw%P#DXnDtZjta6$G%1$VxfLLD+FT-uP%@rqc`dgtNlc z=PSHD2P4rzi6t|^xyWdrd)0cx) zo0elqp@Oi)3rmP%9QI?&A@f9sWhK(@TFH-$++GP>B8h;)V*|$DDG3yX=^d4yCt!ay zfM-=9X^G;rN~u9OMkMjMuGS_)s!Ib<+`ummZA8@N(ZeCR_cXP%bd_*}Ry>tTQfF|a z(0R-fYCfi~lt#dkH(l=HEjdG@lTW@Md3^Usx-Jd6!w5Ri#aBXlX+?2})oN$ajPNB+ z%Vsdz7N5A`gd-{Kp? z-x{LTMTMu#_)jDx1B7sfGKo@6q5LqAo)8mSCJax5D_(Z=kNtd=o3?K(ng9x0xH_o3 z9IRC;2jwT+_wQhd>(?HgJ$iEv&NeWt=`GcVxIH+#;6HN!&OYiyr-1@Vn`m z6~}+SMl5{Nr95#bS8?S&NmxgUPSSGJ_7%foW7Y>GlmR^~3zu`q3BKC5zr^%?fKzR~ zUo1n!JFYn2X1Q76<_(lTB|Q3=Lr%^pw#2@i{9Hf!JQ(+cY*RTfiDG~JCXY~jV)Wdi z($=WkvFquiTAFd8(mz^mw@B(@Dq`QcY-ni8@Ce~2F(2(ydp==&DSFKY61ussX0CBm zvERj#8$*veF?HkRjctWbxL%Ii!*A9jJ;}b~x<#(HN6*B?eHgzIxh5|6!epd~WffVF z#5||Yzx1u}TW+Be(w}~&Fc%lQ?O>_kz3jE}s}%mRkDO~GwB0)l@2xjR!MC+0Pl!pq>f`;$dz4PRkYV*ZB7u><6;cn%o>5-6>H~@Gn`$jAhHC zuT;*!kt%AHL!>NN?cF)a(HjUKwIhjKM<^u0yrK1tYoRmKTZiSWq-ai8>^T3sH+XM= zWWH84L`*m#ehMtE=av1JRDI_Pk5;8bA8IvGobKeJJX3$ z%Eh_xq0ABubot^InTjqai<+)MyzwoYr(*7<0tctC^uZBrwf9*ZJ;jk|^z9IRKrWB) z3vT#VLJ`89MSxZJ62q)w1q1JFkZ^#-xJ?HuKlW2I`A4LNp4wTr$Wa-PgLW065iVX`UDh+KcB#j zETO=738vM4TtH(<#A)W!XzS=}|NLDl3aifIj0#X)GH0z&TI_KjRlL^d^WT^N!MMX%{IHhdX7dL{tIRj!Ms?Jig4kGU^k<#{RP{i zbOz0@h>_sY2(_Kc%hyba9Af=DRoDYoFxjGVY-BT=lxC(*eAj-6na~*{?!XA@(bKx| zlOTbwQ=1F&!2%|X^i}XQNfsm-kt}U=g~i9%cU?vo_vEW<%_$vMgz30)JdJhL8!m?M zaOFsFuZ3Z6m2NKCPsUCL22eV57c8nN&S*$H?*tZ$#g=0f5H&gh|Av?cQNZ5V>FhCk zlNhR^B&*%pk=k(rZOS3OWPc3L(Pa}9eFG>b(+r!;;adcs){v_FT%{5-DrX|G% zx=dR_E9!VPKTC9dW4%ZivyMg=M$_wR@TQCyR5t%h1+Dx+&91*uU+ zHem5ZdEGKU{XQ&sNEGrn7}?&T1JCOwa*sdaB+$v<6aZcnPr_0Y$-FYsqSU6;x|rng z?gZwps&%R(Y8xa7fZp;H28XOPQ+mvOn}*4_>o0`SBaeJ6LJ3iweP0d5N}4w$X)pEt${+v*G8N*qQtEy9zF>3o8TrPs!n z5h74w=-9z;F=i^i8;5yLt9XS`IR@vQ>PKz>1&eqYvcsW5DL9|Jl&ypt2t5+}yfaRJ zb=UmLDgEUv{2T3W^ZUX%Pmd)by_$B0eEU8b*%PD4hwZH2y_p}o%eQOj!ICDiN>M6i ztlylZIWKXS&-VZFUC>K!bidY>?h@(qr74wWr1-|)z=78khid)vgm^o)>{-wf%ZODM z8Hi=8G`H+S#TcRlTmcq~PrjHVd{=*z*3)_Sk1*(OU+c0p+t>u&GheGlQL+LtI?pJ& z0F#&-wlVk)lTLA^tPxRSZN}rWEGKl2I?LmCJ9*9q(-w?4198{knoU{1;*%9TwMHC-8w)$yEz9Oq*kC&U;?bP@$e0~AoBbiY6@)>u@-?m|=)5yPaL zOM>r21%m=y7`P3#@@N5(j_ivbe`vx*6mv(Cwe3mBu3{+*layE3|+~$4|kTnPCV(y?_Ir0Hv=VSQWHRDWt|4q0eXF z=tYpGPZsmfIc)>W{?qk%A+rH4kzzzk-j6kGhW{SVFctt%jrO#P^tB)VfyP1(>tz*k zlNfRj1h!gvJ>k#JXZffJtsWcUn+YI`4Z`^ zo}7{m<<#OwrK7uqQ(e^j*?IPrd}W0)WbtOF&BvQPp=86G(&TJtgxCu-*ogYB^>%UH zX2|SjA2xatf=IXbRYrsfe;7LZxJP!Z>uV&u6W=<)EF@+t4t4NV!D~!p&yI0YHsqs> zooA_J<*cm*zs3I(|AXpD#h z8bqp;D0FYFJ=2-CKbkVC>HStR70#HjyUjpCIWjJpZz2cbaGjOQd-a5_s1VHSKwO5$ z^45^qJO~@Bk-zKZ7js?lAGm(@A=-23BKBFWa(OHd=1s9g6_NJI#wSEhl^x&AO{!=? z+G5W1t+?&Z>1o;ulRHDlyG_t6(mDLm3$+N{r!r(gR5bRaEn>Qsd|RtrAK><^s&@K@11sqO~rvm>*0_HXJtYc3NvgSpklb9`q0tRM*FA?eph7vE>_H73#0o_Oq zubRe15%{Ca0sfQcKm|c?6ym42Q^d@qUUFbn<#j+%Ep3RU`v*Vn9HtgOiK6H?<`#J} zIEfn7YuowomQH)Vh@L+3@2Ed6r9&EQ_*7r0(8%IPH@R=GX$aUW#wG2Dxdr(0f0Aml zP&z!esr#7sxpSK7!QTw3NTs4yHT`32@Ip2V%=uV#G*0E;xc!**w8N$MpY|N;Gstu4 z+2()CWuKJPQ%~*tp*?eT$h${8I0x8XO+x$ysCX?<=FO*EP90#WuO8k+un{-G=*|E+ z6$DPjtUAyp5XupPwJ$dsk4xfKBZV&WWj%vzmO}pPEP9GHqcg+kRZKSKIL#!4H-V1X zQ{avgs9_I(F^HEs z$W)1kT+CBiEdFwyF#A0r=|?s4>E{X>?W~T@R5|EFj!iZ;&j&OSJbqa6E2!!71_b+uXr^ZaL6W7jpOn>H))Z$ zkXRWli;yKtrzw~|i;~eeahCbuq!yrzPfnAb6#bnfL1?%WI}D72Krn&AcZU$K z5W>!J)|?5jG=az2Em*v`l~2?XV7U4VCY+2+8Czu1kS~|IdqQli@-RYe4uNgY<3HL( zr$&ffNb&f}V{E|yZ%+z%L76_E&)b?8kT|qXU48aER;k3_s*hsURNj3;SLuG-bSx|c zzA&x^B1^6`M{rAwqK(4V1^VZLG)+Q0VJsL?Tg)d{^W0i)X>wANImt0WWgLbqZp|ky ziuGceq*lgVFP7t*=r8r|(N$l>?BE#@eoIK1)vE|t900ndu9B;lKPDLf0N)0S5FY>_ z#EQpOlg4}8KmY$H7wacGi4LQ8z*dZ}uYKr_E`L-_$f$WtE2WZ+1UbCzOMIIJSLtO5 zqh=U|)L2%5qIox7m*riigOx#Da;Jj@VT<$qc=TR}q)KL|Z+_a}gG+tA)>#@McVrc< z`M?85zvxQk6sigA4T3K2s03rQ5N^Qn^s6NXy5RO1IWO ze%CUV2`|TA0;zU#-_^|;!6debRrJ_WMg*Y=EIP6IXVIKOtyZKTg=5Dy8Z~GhPFxnd zXo)(iu@Qj28{XAq2-z9pvfPuISH9HlIUB9Pjjg5?hpsMzd%I5G{?iUzM+kqV$_Gyz zyzRTJ+ts254#}>9B)T&4C=EkONjKk+k*JZEk=isJ%I~&no|wwB?6P37C|YT!U(xT4 z8L;*flTjppatgu$9$|Yv!5CC(+RtO$m5a#p1!Jlc$Q^CXBOOBQJd z11GoUSDrg0_CKa2(u1Y9Of{J3^P;)fGO<)0a#`z(tgPSnY|2{+|OkzdFv*~-t3TM6Z#K-QKBe0asCR7=(j?iK+wTB2(P$XrTMd{}f z6!ipHhDlJ{V_lF5#2Ta%LJ5@u(3Vv@?+Qf&P0fVs%UTd0JFLqwp%QktzEb^%ZpAz*S0eEw^iV(BF8PdgpkA6{Ev( z)vCIpj+!`fvvU3!gpA2t&3#R4O0501@=Z<|b%6n~-bp;F8*UO-d5|^V`4=BPlZT(| zSfav5>W>{b$R#VM(me7Su`(3bQ;9~KhdouLfqxJoQ<^kRtFCDlrlHGYt~aVu-5 zjiJ_lCG|6&%mi*=f0}-~dWb3Hni%NBgiV#dlq_9Rd<`pzN>Q5CwWPuC-rsFdLNAH2 z#S~;5(k*7;b)}$fXj7H(WGL*r7o)l3;5s@&^MxnUG|%Ghe7K}oUKm9YOl?}kunZ1# z1*4r)ahsMe+C}VrZF5XG;h?XOB zxC-|up(s}C@o0e<=TcfP9tm}Iw6tW9KCR?v_d;V`>yI6Nm#^t;%DPq`r#lZP-UQqy zzAu;8`J!V|UBsTYY+kF^99_E#b=(apSsRv z+#D%_?4orRs}}FjEm;<^iMlIc;4-pmcKnImiNfo#Z5EWKr+NE)=BQ8iq{G+lsm{8| z5Ju3{vp{Q+QDt)ekw*IZJYPlN&}}hj3s-n?Oj0T#G>AeEQdz4JbOrrXe$uH{ttPsZ z7M)x?(Lkz-#gF*l!_lcS7+cX=VC{rAre6nFAJ$}A4gIry#l8fZby0P;-P>P9K(^MNH_3--K16MRHq4jL;cyl`94V%0p9g)0R zib3*L_2-l}$E0^7B${qb63O>;jqB%YVf2yjEQ49!lydYjYzz{b9)^~$r&jQE7Al~4VsYNT*Z z9?U@F@>1-2a7Oa&%EOM?U0B^hU@JWuSg0DZ=1yseNw3drOGR;s*zV-!NNk)Wnp@G?;RKABPp6tjAT~-!+eWrGc&i z%(ZD&8hQPS+0(No;08E;NKGh>O&On@)rYPAKQ-6%D7+5;Pti7Eg>yIV0?2k^zvu9z zE{`cbn-fjNmb-W|^v$dcqRjU_J;)PcJ*NM6O6gp0y;afIC$ZojA8VpTHG?JH3@pBD z(F4T7fdD|IfCgl_LNqyZG_chVfK5%AqlJZ?0aSVz=9lKp=dUNzJy+&M$f9M} zs>_8| zB2=liU8@;AP{=`|{F{x+$aDhzXH>ZyRkmt6WHGZ(r})S9(2R}mkPSo%BwdLjJcvlu zj!5ELN^!k`cvlV)wms1J_O6+DWm^??x(3tQ=6n1ZY6uXYU?cr!+OTlCxe-4)ffA0a zZ`6?eB>veH1s10%FI5Ly{0Lf#V;4_qJkZHT$CrEaXDFFLHDjg<||U{+hU zg01ntCs^~S$MLBCzaiurB632&`5$Ie+v)hKe;~~{{Bfa>XDwiSZo}w3WY#}gDvhXj zz9OWLKuw%bFcul${)n312WJAH3=(tsroj2;&0qQd{`(080JsG|FMroxNe6P>2HL4c zy_ODUF+;sGbwUFQwhBjoF6-DuljgBh$NQS&}x=_i!b}({%{@Szq#jgb)=Rfo? zpneX?dL&6M0(nEGngLQ${AqSbGF-q=#d|x&M@K}LVn=x0D~{<3{&QbA-rl#w55$ns zcTg(owG`60dJ%a{7)0t%sKl?gzmp28nt^6{dKMkiFbe>kZ1Ao)4`d62ZIJ^qPed0OjDIIehB8P!d*nwV|) zN5>4}aGU&ECCYQ$yG{^qZpY8X&AJI$L-f@s)J$I`?l_sg*R@o8dvRaPcgVWH{xC4; zkg8E&<#+5oUz)Axd&8bsMnat*8TW$iiGztX^0}_qp3pZkHd3Fy>5324cWzToXDX5u z%9NLoru-{HF|!mqG&tpc+NKCXu=Oo0{<2;(a|IDjlV5|bpvlVe)45q)4PV9aP> z-xv(EZ}YaO-y8}e*$OyhTKT6M0H4A(14WxdFHFAunlg0n^W}GWwp1C5Dtz%cZ2ZvB zHt%NQbz!QU0ZChna88@_-}}reVK^Nv%ev1nv(HxIS4tMI%{2nTXOqz!)6Tc>@K{pw zS9E1vro1X}_}KNXW;QM>>o7(ncrc$!#m|po<^2m5;SnprsLVl*z$nVPo~tZ68>hcN zs9fDXMdH9%^Km?}YPgK3G)lS4E<>sMdYRT2Hi}Na^)qF>SAJo3{Ga=uoJK$8wfb*G zXnyxH<=3i{x8(e?0tp@U>x8T`*1{;6z8mt@)}E*QlhLp0zmwjU*LS;xEWHkUo|@BF zcQlsnVbwx9nWyBpz!`PkS?k_Q-~0xwdixygZmUQC%c0j4OD`o*lZ>`g2535HQ^>7F z)8jtn{l|v>z!a4m>ZlWjD5ozzlYjc;El=N$3BoRoIki-|_Nwjup&W>kZKetFYk{SY zXZ%Kg@vDaor^M@hA)C#Tz&198+v~nwF46 zqA_l&SbFsMOeSSm5#KD3a$hDo=>C-&&-i&&lG{W1b+(?>M198z^O-*JenLy+S{>Cg zyB%Cb^4U7ifrh6Y=Dj4F{wOe(7&4sJqg=eS)adVnteQXi$3`$@+Msr(A9Uid8_>&9kzRC%q{Bct1YSKYX{?6B~0e;5p+7hdi312 zI`ZVKi7yZDc-+?MVxLKV|CRIiJm{n$8^yc*^U!z?9%Dkb_li7R4}I<4mj8+=dBOsn zj9WT8j-pSWO4=(YU+$5EUZy<^IAN1>d!;@znd~*6nc2cqne!}5eouJ!&i$Eg1hLPC zw<)713fH3cX=Rv=jrlrX)Ax0i%5tFpJyyzh<4Nk>18VI<;MZ!?9!eEbil}&td4F^~ zJ<%iFrfHBW6V3)c#V%xuLR~?1&YD+m-mqaC=!k8glSc;_2ULXrh`!PN3O335enXnJ zCR*!an&b-EvQGwzRpg8|gvCN{t(V)%2H%^|p4Svm7X-`K!J^Vb-6nm_0>ZTF%v6c) zw*{t6(B>Xn0cg;-B7f6+t?L?>W@THvjz$XQ^Kk>Q-G&dsL0;F0MSbt}w#`86;=~1; zBz*8^s^7o(+W;#fp5I9wX^IG0^eZBW(rKd8hNzJGe>+$pa|jDBiK>3{&`EbCS@5-V=tF z9Wv3ZU!{$R=Yf5Os(hKdJ}W;Jsmb`=EGcgxtokdnx1mS60jJj8lDo<4w}DvkZ1EXY z?eB|6sH4W|zlh|uw_%!*O~{@+N|z@L9_@MWK>g*zfz1i*T!?FZ`__)5%Arms z*maMSXHn{ukjFT!a9UEjREapBLR&qKQZN|n zHtH86&o@mleWSO2R_OAGo|v~RhZdW{BB#=~}S3=7m3*wDn?&HB8K`4l}R?rY_lNZJ`K-w{^&!RpY)7y2edCwyQ6^V?VOGQ5UkX ziT@CgJpzVlNEoJ^CI6T0cYj`YjBES(Skh$)+qg~FeQ0Saqx+)=LA^b@Vt4DxuTK*g zkh=7t>2?JJuB{dGfIS}F0k!fkQ{OEt-ir#B%!n`#{fR==^M*@*XGQ7e^jv~h^gs?n z&5+bMO1%{VulJ3r5bETvX^mDNie>XSRy=x*{vGfuDve5B^J6~FcasqURiRLkXMU5z z-1yK;D7cBnIG%v6yz>ect4hFnmQ^W~f~|9x9$}{^BNBT{OF8(YFj#MWwt{5I(U$Sw z)9;z%CeQRr12Ij4oe7)4c%!srhXXY71460U939&`qp{6-LZAHApG}os*X=Y=E~P&Y z%QJKIiJEVF4m}ObLxak|1TZofOSZ(3VTsgx16axA*QNF~p1_DSO6k+SZS%4&q2SW| z<4IFt(Q!7GD9L#%Ra zuv|4LkAbVlwHLDtS^ZI3#baywJt7UJL>ZsEB5#b7Hf($wZ^{{!CtdXag@EOfnQS=Bq)i#4;a^8g>_T`>SNqMgEC z4aaOTol3WLTFnPP)iBO12U=*tY)e+^PoW4p5&x0#`LN>E#wGccauggBuBBNL3? zyIIf)!FOot+A8;{z&~7%_?G4rqT1XMzYQZB|5QUr4|p^**0d+to+aB4)cj@0M%4Fx zNfyhD<9BESLp2U{|K0YZl%=id*iwE_6dr%)*81Bq^wnv^`y=to+44ERe!ONY@qo4= zW#X@PD%)JCo3ABQmWBwrTt@6HR$30w<~&s|xHGv;rynJ`A0&|>xn)5gS?_sLwz9N}!jILs&2)DVz&tfrQD13Tn zH1cvi68%ED-6yPE^{3D0Z2n(et$vP@-tQdEb&HuvRW3e-SeQzpK}QDW)MMYE=KWq7 zr!OY!e=*!XJvIs!V4~}NLYYvw@nNyXP~e>Rpq(KwMz@XKl z01!)~UorvL_Y_R>-#~{7&Grh85{taMo`QwZz+CBD*;CiS1(dKF&$o)RwS`|d=vO@D z${$$MEJFQ=Cgf^=rCVZ}jIE3hDIW;mL)a0kVCK2H7b5`ja^q+}P`MrOAa&}+ALqYP z5G&dEJG(tff_sl@&y>*9`FvF|_4l!&gja>#ga(hm5`r!M)?>aZ{gDHzjYb`uGct|b z7NJS2b2#`?khSUE44xZBGf%8)L$tJv0g%6(*hHE?Dxtepqr#c-oJ_*Vzj zReyS|r;+_yfWSDvELTqRjEcK+mZ$S{moDVaNzEE`mn+IgNHQ_`Ji8o`kbX`;oX`#( zs)!ylT|M8A+KefA}WfR3BUOf7)&TF>?M-yRiWF zAN$Er!y8(gQOOK3o*#vS*`Dmr{d8gI4|a(Z_ABJys!j>neo09M^2(bWsg`DrT55s?k#mYt zyNDEgeYer@NELYvXd1`!T>v2Nm7A0N^4hs^ONripyRw6C{@Z=*9T?g2X683QcAq6G zg6{Qeb4@ofG3M`C%ISJ^n7cjFP@>gS%t1uDQ`^2GlnHQ-BoTqJCvUY#IastiE_>Es ziK20jvvR_(M6^pNzjy`2wGkIIcPa=@1@Pu$YYPcTHU>oggk@r)1Z_CRWVxO>fL}n~ zq9`>42NMWl1t~lE=F|eMB}tF%O~ICtvTT`N)PyP=Bdu_{@l3XHlcDQMiVP3ocGP zE)Ym~U=$qrt@thX=v}V$NvUz}E6OjIPVra6WkZp)my?e_`p6Hx7*!;PA2&!p;h*HY z(F*Vn5rTbDKmW8z@Z=6utfBpsv_|do+e25olFd;Nh4C_jNNYJ>uyFIHyCMfCeu}$W zTLL4wd$?~iR4Mb)zJ!l1dHycnBad%{#P#zn3h{o+_0T8ZUf6gZ|28k=HzLAX84Uzn zrqqlfGm5gWWa-KMaIRE?ifz+SS+cF;h@{sEz8&8W(#d8o3ez;7m~Y3x`XPkj?x&a^ zi8`A#ozu4qFhL@24w%DdufOuu*iA7e$a}@{k_OI6U>=}vM5ldCsMy|~KyQ|h>zBQf z{^dZ$rZOLNNe+Onv~;jFY&@P-fRwpbW4@|GA*bZ<2zz}F1@9YMirauqGu+eC_%+eYLI22i;r@8V?v-j zJrki==ztFFH4j65GzPSE!b@u6P;{ylm91%}Wz`a}WM(P^AAm$wnqM>M)>=>jF8DH1T ze=f8x*XU{I{f1%~#fZj@@yCJG(-b*8xqM6XGw!MvreCRa+$cVbw8IYDi_dgygJ%qX zXVs9A3JormU)uKbk zj$UfRS1iIrCj%V89we%P0X={AIt#gbkUyu1*YzUZkv1{wE@Dwyua03QC*hjXA|bvy ziP4+DxDZezXU`@|nztb8fbT7{>v&e_!L)WrrwEL8sq_G1@uG?np<5BD*gDEeDacGq z3wR44mV@l$Ht6YH3wO$_^INJG>N7#086!!5}!~g#>#2?<>yqp6O&>i(u@2-HjzIp^|8kf(_tBPiZR0R8%<; zC(lOa@J|>g$rlOJ)NM-gCcs!UuL>5;idm1zibL*oa)W1P#YqZ<@UnyIggA{q+B!l*pc5Dq z%UYC@oGK!ZN%*$SR|DiIz;G|SX= zhS*}Bta|0$8wE}4r-80;Wz6SaJcbO?undqarx{yKrwUIPVFlSZ|GwtBxgcdWe$~J2MqdU-pP3NQw8t6pt0Y_xG(j#c#1c&Zo}mssnKzGy1jd zNDO?J{<~tWXf%X1PMn{$sR{+357%X=s5#(`cW@HyTz=(UR3{2n)*s@D8UNz{6`#3x z{i&E@WI(Wz(AD|2z=D6vjiV*al<%u9nH%pA2?a|k#}p-dxiX}YP0B{%h)};M(0L@0 zRLkwmpiE&^BOsI7D)}l>)@vkEkh2>sX~gW1g1;?Cmgi?5eI!w z?MqY5-*nJFlQMV^sG@Nhuy*HtVB>7%#`%AAfTdCm*7FSru zJv}`?N#X~F4c++By~w3l=Wk*HQgMdGks^Gq!`dlH=Oj?ilIlRJ__4`(2cD#+3hJi1>|%wP}GjBNv^zo*#iK{PNLQ}WL`PzF<| zE7L*h`!F8>{hD~6r8%-U@`=oR%db8aSS)e_B%h`-XlAg>DE z17vOZmDa?*tbLIP0l`bOBufX!TiFfjYNrkv{cSQtxvx5_Li$@y6`i0wyhKs3t59n- zEiON3S;c*5nsxcMT^%Ah)!1S=&s5c36@+$+wtdefRVt30jlz2yk$n>s^2_PPe8oSQ zDBx3S?kjZQQGekVqGaBpG_y`%Bg^G%Q3@eF`Ma5kDogn6jrnWC>z`%9c+anyOvhi2Eot2ZUScaAw(llvow{ouEjiyR{R{-Uv_-TeTP2qQ;t%#u;)>_lSgDXDWN~O1&PD~6J2MtCx zXfc=zQ`tY6RZUl(#(y>vVw*VX(fx^XwU$}PSvW4>jd5L!lcZ9@)Yb5Qp`313z?o7L z{^5lChl0;VD*Z%eYxB3iRh-x#`>`q|$c$*uLKh8|(?wKk%FMcolpuZ&ry64aGD-Z? zyU46OM!ImFOmC~vIU<5o4S8ukVi8yov5x8+E&~Ro){gQ^3gjMYAfV6wp2uBt@ipXQ z?A#)9bcvL1+;z%b|MuhTx!KhJW9mHP*?I%MAH-g72{j-J8HTC~(5obQpboYpm)^lUshPKsY(1Ne_Rt^-+=4xk=N~?88YPxW zJU7!hO7jag(TOO@<~BO7mgM)ifvC7vQ!UdWM+eI&CpfHhkK{ z`%%DV#r8^VS#^CI-?Mc-Hm$0W_=6qqM*=o(euWne#Sg%nqI~1~ z%+}{ua#YV*s&#@MZMRi?fAYgklt{&C+2vYzO7nF(vA=Q5G zIv`X)QdPlM(x2cIJ=RKo%pUL&d6EOJ;BPA=TZSGP(zDu!+kV}gxMzFw&Y){iNq>R0 z+mzjQYHi|ikTIvq%3ur6d%X=O$@i1h-&efd5u)PE1>1F=dT=3C<5e{mx;IZDn8uEDl0rxTCZ2NsA^8 zCRG%yBJE5WN+5m@k$sP6&p2AFcg@7aN2*?3r1rW$aIoOd?ybM&67>P_dY6_2VFzi+ zf-MHePQT-uAnCigzSpyFkl)h%V20yfxv{!Wa5kdc1$;6uB@vLCU%C74sF`_II<`)! zSU&s+EdQaMnQvAK!$(om@kaseTxL+(^VqG^xJo%y`Nu-t2{=p6=lUzJqz5IHNa0!9_dtDo3-QI*sYo@mNAx ziX?-^of(BU(uZ1eyl%E=!ac9}t^9_%x1ILOlij9dx24ZJ%HH>7<>GxQVsLb?GN4Zd zG!Mfaed7}i*ue#^8P%M%U+AqNlTTVdlt9StuTPL8Se{qgZ8C=o_eB06yR6o39Y*w8 z^S?l7Ud|QyeBu4=?5!=JGq%#kxyruyUleD$( zbG*TyJIjus5+6fuqWm*|-&h{X!-SQJ*4hMtRiV_ZT3tLDp9u0B&={d~{+}?9>1K_w4tx$-95vfQ41z7uAB(Cgar)Rg5OBUK$V$ z6{-MgDlCP0bL`D;QbcnjRE`hml_K13n)xq@&Hm**S^GjJhA~mMQcr8q4xSRwZl?!G z6lPu}eG9pFLX%6d0JKbitcX|0Yq|$u&Gz}vKGw4v0@J9;a1efr=h+|O+E`E~< z!p9K2ZwKah0fwWSK35pL)@bHfqJquB5^!-;AZx;UwZT~n?~_>NrsgE-Dpjhf6Q9nH zea93yz-a!ZM3yALhVt$0uBX7gFV8P$Jt^8xQ^~uq0OqC(54Vfg90~)Ny1M{TL)-%2 zo9CThB&p8r7>%EMX#CeKbJy>c>~;PZM`S5 zz4^xVc6IPQ0%JYL0Fe5BT<8-WJ*9;wH?uivRrpZ* z;7j^kd4=9M>lILCh$ByeT9wG7uZWPq#JuExCYI&Xa=F&uXP^GZOYq+f0T94A)27Bs zbzRu>#Aq-RIc~$KMW-wz#2!ESPJE2+FZ#%bI`~A0uJ0T}6bLfvJFOjMn{dCbB0K4D*pw{lHA)g9%HEM^#~hv1%yT(-)H zc6s`SF^q*MFmokS+Dz+hzyF9gTCYdjj$7K&sNQ36Nu1p^Pj@V56A|+K79FaP<#$14 zXl6)A$qXGK!_mCV>6=4J=l|rU9-%+LhMXwHukQ`vSjEAveh$WP_|*$Gci8w*L4Lzb zH@mek=&Yp#t*FP&J;rE|+(VIYwe}b_PVP{@z@bJZ{6J^qH07%n3O%mHSKD6OFZ6b$ zEqPDSS*Ns^pVgTi*MYfc4wT3VYLQT}5n2fv5`sD8W^0w}jLVUrH~b9ua=hyGtc?@h z<1u5%S3=F+EVa}nl$ZMwD-BPLKE6Xq)x*p~R@|U3w)IJwwDp0W_>P;x!5TFOVymCV zV+_t-&eTsuS$0xQ)12`A#|}}$jO|&+cL`v90koQ+kV?;f!thW^&t8f6Gg;mMk{r&S zqz-w-jya^F6(PN5vieO?8TB?*Hla5Ak|5bch%+KZdDyZY%crq`jy3vhxJbpVCM-B! z6;X@Qi_!0E;Z`DY`MU?ItZ*=>(m}LcQa1pHZiyz|i%yY!4I|fAcq>4+#DD=~2$%vA}^K*f%7A(G0 zbKUoADPT9`8T`PR2e=mnzX1Bqn8?0YDYorNKFH$^s+J7s*z@4{zWbwF&YA}#J&p^; z`Y)iLFpO{fb9TX)`&pd#1O=bjK%yIVymCx5`hKP|4|y;G>s z>L?I~OLH&i`~imz?F3ZSewWOjMRgzpQ(Aj2&&@z_Hu9LB$oZ^8#h*c~!gEvy7U|!& z7c-a-9qxuEbv7|Tln15U?KyR!n@NS*2b0yBebOf%$jP~hG^7}AAdbZ-%jE=-V(kQw zZC>Y}X=guH=&G#oz=z7ZI?i9sVdal4S_MCc^EmvLQBWdkcr7!B6@2$~C(vN)r;eJ} z*C!3fIC`1|;|`W-;qtjjOI)VxD=K{cR!l05JFh6=$jWziLYUO|YLFJL0P?=8h*x*2 zmfV-;D6RA{AXhF-^N8D4Oc~s12{rHm#XDrH7$>OTw8lDze_?R!e6Atc&@YYwyTrWi zN)(Cm^5d%DiD~>Kjg9=W%MtRpEi`L%{uTEG&j8!kPQkGN^_WhP14{H@ssXfiuP!0?jHR<#Ry z#GUYZjtUD(?kOM)S*~U!2IcgVL?ZJE+-8&hQ3nj#NH82F1el5EC2bH)?X!I2>VvSD zn@X~2pz5fz3o!Kl;Jva`Q$m6hSnqsUDY#8uI1QJT?#F-T~>Lp?SujzfSh|rcor?i49*QOXX5y z{?Jm4xFAk#*C6+G#!TKvp$)T5e{_Kj(f0Reg|ZplaXm8e*XgpgBEw`nvSv~#RZ*%D zz-h8uG1;`qEl|<#Km{|77__~gC1FF@;#Wc~WVmg}BQq`1bp339QmoYoC(_3T*W2cw`H-lN zz}o>4o2**lao9(6?_*UDm@nG28pC<1DZc#W;M*CF=_Jdl1P_Fj_8HhDEf2VyJ+#J- zN}VAd3_M-g3^weDd?R$H$y_-JmLEe8ifj5R8oDrz8j@7HsxQa$Nick0*&8ZJwB-ek zH==9^IpukO3>h#VR(a1YUE_Qi7YR%avVLu>{6i!L%#<*?AdLxA-bTI+&0x`Y6=$O( zOL7{(tFy`CbHl$ujH2jqqV@}w?I|I?7`kaJH7 zQ`K3!2}E&(Iv5`}(CsbDJ)awofl7CcKy-{p6g9`ui z6+ciJ*65h6P5>WL@>h=-ql)Dbt5@YHB68M=x5MYAF}7Wex%yYw=9`6ge4uJ1G~$86 zifim& zt%%^`EuEeUId)lQ1ZX3f-#w}&|GE(AH6dQmte0Uhkye6)HO*H;4-Lwr)if`RM7357 z`^cL4vzB~yW3P8>wr$Y%61E8PWu}wvWD2M6S z*^z<7=>|1uVWdv9Q}Lbr>7lrOhS73d5Qz_Q>Dem3Y0&|sHSfzAq|IgUdo5B zQ`09DpXr18D|R+iW&89n^{{Me@8I|=0e!0{JrKAUz_BWGwwI*(AvjImP!ZQtZJs>d zAwinEOvl&Tl0GyAOoa9<=HCYJ9mz{trG$ih{~;lH_;s2eai7H^LFcQ0AeEO{pjEKs z@RP?vI9y>jyxLfD-~Zc(#>oZTREilNDX(2ZrNu^kw)3s<3ZwhUA}E^6^ryxK^GBEK zD$lf#1p!{Xd_`HpyscVDH@g5{z(9IP#-DF_$D?YhuonIMtp^iRIyR0Md9FmSo_OIW z@1GpT=$GsGh5;YY#;>~*q1{E3z*i)hmToj%fp39L*jEOR{?bfJ(b86zV`bFy`&?5M zDM3bRm$UUdZQ1oB2}Mv9xz|u^j+41^Sg_AyZKmHdCxH)c*cMR9MH<)Z%oZ_nL%5&lMJ-w2)1w{LQnkGPnRw9y?tBs%juwnW-sD_GIo81G?@Y^w9d?X;cIXNG3l^XN1*Z;t#3XBU zMW7mKl3y7qz-G=dKJ1)Dxahc)L;2R|W@K&{8J?6ZvwgKv&rvFv&!ohdN9nGCd&)C% z(L0;%MxOjNWkfG?)qd@k=e{SmE6Q2M*CRNgbcu5Wo4#~SV15a zo+|Q59lhkRhnsSK_+UD=EHQgJ|3dx^=BO@85|Vp1Sx03Fe<}>C$;+gJ*1$lq>=@d2p1ueWo<)H;9*Mym1cSkXd93(|+#XT8OPj_X5Wjj@W&{gv2ISdVyNei)}`f zAwJ2;X*X{tbG3TY7M^(P-T}>!4W&$e)EE*<%_iSPq@X#zzbGUT=dFq|)IDcq5`&Nm zm&rh|z$&tkWgl+Pp8t`8|p1AJ=g7%_UDnz9yD;>X449 z_(#7;mN>j1%(Op93J-fGKU>luz2*}@bxC+!I=n%oB|&`sA#5K}>>s}RS6IG2K83Pl zfQnfnnsY7YP>n0G+Kz`VIAJcJJ1!@P=LIi0j)>bTF-~bv<7^2!43(;Jg#`f3WZZIy z#b?MW;B3msoTM%=4a$chYY`9=682p$F=@Lv&M1dn3}JGt84D-|HN2(H^vZch)qTxb zIpI?UDuumVs3lSjtGX=6Ab4_~-fqO1s8c;2a`k$w`>#G%1tLZ|<>=$mbeg+~;j*-l ze$`W>t@Ih0`x=~-Gz_xRr3LY`33a*^Z+sRsoC4Jj&IRYPO5x??mTg{T#q-@}^8>cW z>+L&3qQm&i18!=sxHoLNfd|r5XD7;4^%M!*-;de?k}gAO0tvdE)V{JtMuTh^>bRHl z(%?%0D>1imo)HjnEDs%kJbi#`rD{`G-^4OaqH~{Mn6h106f^=h3VOVFel%xb5x$m{ zvwQkTCi78RoxET|%iOoS z@*re1cwKBfAM=urcPl+yj^%6RM8nro$kQ>(g1DwbITjns!>Yjm91xB5m5%B zD<3+Y2%wMFzTe2UlQi7i0$05p6HO$a70HSWTcqSxmoVr#n%ud4Vo^ zs9D+TpQOrVb}GDR=K=A*8mSMHfu1cj#e)1J^KL}PVC? z>lgpvlA4a+#~LlPC&HK>Ua<;7*}%ES;*Ui*Wa-%yJq!Qnc>$Rc)PjnJ_T&70ZIj2g zi~7YtN8xCvU}-r7oNp7c1L$x3eMEewX%Sf63`dEFiwc|}g&s7ZBZ8jkp5+McxmZ?8 zgx({+r+tq_BOItBL&tcP3&9*$QA4;7HdM5_u8PeYUWTV_sSY1&@Ox?b(bu{dDlK$1 zS}}RKxO8+q#tD*rh?1~o7!f}LLgDp>ipX#=kx(|re{X#mOCjjjWZ)Fyc?ama+4Gve zBCGT1mv$j!%ib3R(Z#m=3L)K^;+zu1sd?S8-jGP1uKiQ~zk0VwFQ{!qNY|}Iz4LxM z=b8#*33P(m%~0pG*jo*Fu9P-bu6vm04?)<^%WpUZ@dO`VTGbK-Jy}SK1HY&#_GF|U z+da)8wiG!giwQPBs@A%vQSHRL@zQ*8t&gk^RVWr;`5!$~KWE25-OZFJA;5W70JErRjYY!KX0agDSd_RqV@n zxC*mBi-iT%Wp#`s$@LHPOF9OWksgD6Zpq5$49EoUV6~;w-!Tm)z6Pf{5?L?-V4spkfqVb}3z@}>_>TGf zFdMJBFpIgPm^$NOlp}z3Q_aY$k}yvxqmN};<7vzd*?G6boeC*tt8=sp0CNgT$VTr` zFbW4>8)jO64&urNJK|&Ija;Nvj{jwXRDmE>D%c1W;8u)($1ciY{wMYON29lGZLIB> zNEHBp5s?bm5pV;S%Iz)eJYN82(=!d*oX0Biu5bfl2=aFZsx+tNOWy4uqGQ0^1^+|1 z2+4P1T*gr7f3pRW7ZNFGq-+cT2Grj#FOR)Y~ujA3k$6gL2cE&UGI5%hWxKA|}7EQJ> z{76?D_UjXghD+4taPlC;|JnpLKyfx)P!cfc3mZ=yq3e@d3DCpA!;9G|SUGP{5yZ)F z*zZjUjPlMao;|=`;actGIX{lvOMaa0b>s9ETqefa%U=FvpZ_?%#%&+2R!)_O0(>|akkv)?#Fg#NN zLe@)zRD{jT-JHgj#II~|IgkIJ|D5@*_FN5+KxpvyZh)x%|M4-SVJ zv_b+ww~hsg?0YHPP}y$b1imsYf*J%y6o+98C>CZPe#k0_Wb$YR+y>Dc#4oinhB#Z% zdHRYar5dM=*<@<(>+e|1se-ZGnP9BP*VJC(0%XCp7;q-b@3&CQ2rc?nEy4#IF={P= zEz#0Mxh3H$VkAJm%%b@ym$XdK(g7lTSmkVq)47)xUlP7{G!9MCtkydryKfw9!}6J2 zrDF^F3fIL`;=3}ybl4M*reY!8R=Q7{TVcI5x-VGbkUXiP)|&;3Ig59xX&a3fW#U>k zta|FIi9-(O%?zQPLX|+8;B9)Ga&@|P-oAaDp7W(G!=eD4z zA59!D$%6YNojB|GEjYVueD4_HP^0@f`3^LZ?qGd1!uJY+D;xi{WG>*h9@u&ias=O% zj6EQ-bUJHp$((pvjp*pyNvM6|E-x0_cmVn|LU)u!86_CNW!gc+qecK%G$2mY=zAh7 zgTL2LwBD1#(ktXa$u|Nm5910HsMv9BVlibj zTuf!LUz{*tZ6P5JeTHxcmZbT-qF!JcD+llg?x7Ygc$kwX_NAGNtwi*1hMYQ&q}^2_ zu_;C%&kfuyYa>33flq=Nk`_mKob|~0oup+^?RcHFR{6o; zP5B}+w>rm<=_qK=#{{D4B;(uVxKA%^^+Q(;S1L!LAVp+ZQ00ijU_hSn)nFT}R&DW! zV8N|jpTI00b|12s`nHYSO(Sa6q%XdiOT`R$poX?Wou&iF9F@#|mOzSn(BdYLp+P>Dv9ClCh0a`tJCqEv8`nHxV z_uo@r1ssPSo&le&y?ywU9*ZMs`Wj}|$+~(S5&o>AT5=)ih0&LiiaFyqp~LoTu8xrj zi`cCI$}HFhUER+91J-;;p>@dhJAVDT;A7>+ZNvtZE~(Qyx)qmJ(c1q4+f4fDQ@_)? zV#b^61q!z3WWGVhr_&%K1Zq`KTp0P;u%(M5CGco)3!Gp_C&NO%?Qi;N@6xBRj+|gI z)AOpqUVv_J3jx}iAtQt7CMd{|ook|>QMrky|8Xti?$-Yh_z=7;&IWX27K&K}-JfK7&gc ztjyT|PL_6jHF~q<^{#Hv%pd9K=PMo z9vbk_*|Ul_pKA;oBV2%e zO~0?UBgxImD35g)Cx2@#APRH$ghTHmoRQH?$v!@E2i}CpbNp%>lwe*ZKBnb>hur?s zC2@EaO9eV?h@*x%Rj4!jZ8K3`x>M74#NId+Q^3**<~dL1F{2BelGMfmzVQf&UIEob z%LLN+*L?r@-O|Ig zkOn)77FPf4&5(44`>0Nj3~k3(k-%@D2y;-<^HE{)oNCqs0S2ddGO^*+keiM3hf!jA zQjih85=Zv=vJH5Fl^%(`6#Lc|QIX|+{ZzUlWHcd3A?$}+)k(}goG$IMhHV|7G4cdY zyxH13matA*DxFsNb$4icf113HM&^-j@k8}Bn2aR-9B<2jw#@uR#pmx7SrajOSm4_r zBb4?0i8XV#XWGY#oPsZxdWL5%ud&Dti8Mx%v|TpHQ5o5af{K9}W5`XUNrdn?>Wef> zPXYh#ocG+T=NcZvbaf;N__z)eHo1bGbiAv`nmVVFa;2gblhaPs^08qgp^}Is5BErd zptG?R-s@#Yu;);zGWeYXBocLgRFW7UbU+Tmvn>ltq#?a$k3S9D2LQ|4;V$%olXo*}FCfBnE{m4r9JjBk<>nhpa z#h;^w0*g*}*#`)E(J(d_V*Ywc?_;6NfT_RtBfEDt)Gp^PL`i9Bc(%VFHa$6p?D|6E zt)YFweuIL=LPTSnfZ%piWqs4GYB$ImN2+Hm8~T5oGr+-0DI2&&^vBX z=&tO(9<=0_fD5M2keXioY^rLkWztiC`+9dZWr7bnw0Ito6im8wFrR;@%aI$>W+t@+ zSwG0SvS$|4%w#FL*W!=WtmBeYBS;gKYGn%@i#lOKmWomvTrx9nO#GG47Yk_w zHkgZvtHZX-c|6U_of_H_LJZ4|7@Wq&=7psF4m^GvKs;v}N(vNH&66)ZkL97f>eFnQ zRu%PDN=b2}qM)g>g4(L5@{3{uyCeFth_&ucIWdLBjK#t0>T(f9*ZDu-!hiDfma8yjJH$2t3XeW?x%bOWzGat(KLe9ZxKQfq4QN)D(gwl z;d1Pc@;#;bmy_f~h65_SxddWLMJ331QeCY#)+S4_dbP^r!yA4J)%jmDD|aY8cZ#ZK zUmSbI6Aua)?76`T1)AYAN;b;**`C}X9`x9Lsd~@i+>7@-{Owd*Oaq#Ql*=36QV4xa z7x~;O72KeOXmpj`_+QHs-?Fs9ht}U&m0$O}=6@`B&&oDPnJo~eW0@X<1lrbZuO#!b zp)*ltH#xF%oN{w0g^^&VL^3mR;FMoHutbgB8caj84fA#G4;JF1{R9liIjs(?l{KzH zx<3xwUZ5^wX7m>s!H3?`N$xitjv=)H;>q$s^n~P{STDs;muY`rNx!}N2Dof~-5Ix28KNTt@?wSi)Ox^11(e4W z1P!HJI+iT>+nNlHjTHjtP8{adO{rC@Ao;TF+u<3UfHt&vA@>R)TQn0-m@+P1qkmF$ z*57E0Y5OIwZ-Lf|2CSysNQNUn=~8TGIje|XeRkdT$8wy zZP(t54OlN2s`#JnJ)h>%!9J#BlwI8O9!PO!VT#63;+2%R@cs)4i7OsaVV;&g*RK?@ z&(k7_50I!1(!|BOj5+f7(g(w>2flubtJ2crfofXyfB;KdfBB#EJxn#xqaVs#l{7h^ z&cW)#r;BOxFQM9M$DZaCtIQ(|m$$HdN{U*{b?oAG3zn4hA~g|Ce+gGx$bVltIG+#x zQ$&Wj;NTzsA{cKLO#aBHZpFv6oH9yip_R#to`xUH+`E}hO?b?3`5~et19QpEke1S6 zK~&_lqgvT4tBVEdiMM=Ar<7)sVjT)}BO)0+SDHIZD2iVb71T3Khi}PDCuG|1c`X-8 zstE6?U_~|_h@c{CJ=btvN{~gqezS=26~$=dw=@X!n$o8t)}I-pWUviCbf#T=o>m0O zLds9t7WKbMDiTtbjWba2=<WqQcgFwP-4+Ro;CDGceJ_#8l57na7%^_D7wZ!B$X?Cxis|KuB#rB{yo zFkUYc6x=8{5lVL0hnPZWFiqWq7LCVTsE)I}(L6kM(ynD?HuBnIk5C&nbRM-oR!mw~ zxv}h1hxm!g7Yg<)-Dl7~EWP(eom2YJ5~j*zb)rRKBR_jgixjJCbmdgp zVeM0^*K*QK3C)l5SxN1QkeAA=@aP_oQI%mT`iI^0akr1voA48!2UBQw(~ML3aD1bd zwMw~cE2|AfKBXLQs3m=OJT2tGA?L2`qcF3#{2oYD8r;v|qzu(J=v(i9*|}U6+ET&* zGHpHOiv?DuiRhaMtSUczhWHv$cmA&=Z-)}spxIzxPSq9uBC*GzKSuI6HEi*qjU}Wz zsA`gJS^Gl+wWq+KB>f|_*Syp+3B<2)m7A9?m0G$SO;k8u-TO|Gd+h?d43K0VTmaCR! zXWO|~G)k(c4+pY=u>K3}>?~j3X5T{wgdP=*aGCTLIWmBF?Z7I8hW`tqobS-m+5b^L z=R4}hRLoCo$4~*vim3vs@HigHFcb3=ld6+3>j6ZDk(}RRlVd7+@&R9W^AkE8nVcA_ zuFRZQH9&?Hl`S@NqUIH1T}?uS%$b0StT6yHoyjd>t2TfDMCKMv{Cruv=|#=*ROA~f zV&*fRM;0mk?4`%hVU&=cbT9MyZk9GK0~QO%Iff+?qohZrZ$KK zaO?u&PkNl}AT!TYI3bZON?Nm>I)nhy6M7Ota1qf%jczhgbO2z;<=NG*ho>MuRRSPr zFQ1#BJcCbvwq84vHX;V-`7JD3!cm8Sh-g0{EtBo|cE>I|QC0qA`bpkC*IwWB#UTV} zJ~zr8r$FAc3#sHD(ywf0b|rcAmm})}30eJ$o|P3N7o_rAdOT=R*VMk+RmwX9&#;n74@mkP{~0vpH5M~P;q z!cr{Cwhs!xz68ZUhLHS}%Csp!iZ?Tx!5Pzk+=T|0r5r*6{)nhiJWfrfj!$;pZP2WH z$Vr6XbB&8z={9HpM|7n80-Rq1Lf$PyI@`P*S*<}TwwLsnd9Guu|0!eM#C0o`pj~G& zHE7BFVtoNZR$bv(CvJUVmoROwt!M3T%Hj%7YnmD`xODceO(0KRVM`^(5aix+5zvtB zJQ!+?0|p#1M==E)i>Q&LK8Ds38*^69!S6YK`jzzNQ`3+1wHhUvtw_?klAd%mG}?&h zpvRhREP$C8;v`3OyVewE;6$;nDWXPGF4fV#I4!L?_t;l6Mgtg32^_|DtQIh8V5A`R zOgw?z)(I+`+MY{?)OpntFT3$df^(5Yr_?j7gU zEx3Dx=TY2R8YawIODgjc(SksmT<=6|uJO|h2S~+ajN(XIw~exh;=M?Z&V+5BSw^Td z27H&$f?h3^yKVeo1yIiP8Jp{Wl{Z12!mgs6YUBTgS$>N!bD~|Bgunahh%4IL* z9BR98O0482{BM^_O)H4A!f20ee~@6$_54QK{@1BN%a_i3^N67#2bdgkKZJiUo9K0% zCPnfV*@vS(y@0U0U|yM?^;cpNVaX2d))fiP4{G+>2{aKeQz!8EN-Gy*Oqwsxw*O@1 zAjo3a#RI>x5bTxoEoVK}2EcYh8kqB+RR7PfL){;LYt3>O_DA931yJwerRJt9K9kJ* ztW9`6ftps8;ftcj8EpB99On-01todtwF_R5_=eP)x)dH$yegN zIkc58UhIywD+Hzc2eu-}{&ANoXKEV8FEPI04i=i`xZ!cCsUeUle^OO;Zk6|f*V^`} z>=P;Z-~Wn9XLg!xcB^M9oX3*=MONS5bO{pXEc`~n5MTg+fp2g*ap4^)xjaec8h#~i z3jjD2<5o_}hChtC3m%)oQ>k+hf2zp`g0AUBP=jvo{Sc9YcM>k6nNLvX$t=U)j} z!BAmr#xB&q?U8fAhjM0moE`WMN!*7{_I~T!n_H=uFM!W@kOG+mpuHm3%jSu5$(>jN@iBr? zM`VO@b9>b-M3kIHDjmdGv+)G)W1L)?h|MV*w2u;IyRuRx3N#E5yn7oE%P@SpgR*p1 zX?-mL6(5>h`|cZYjd*9Tl7sF!`Beu8e>If|8i{rB`i9etkezkJH1JmA&S^h_mfZyZVxq82x z*?wtqyL;&IuZ^ghfcYDL$igwM*SgxHvQ3MVqugqo-M;OUCm}=NB`IckV|>DuycRLIeL{Yei*oS=B3o?=F8In1N%Sz0bG z@xRdfq~+^e-HS^MVV|g^b66?D$n1UycN@0*eEi%v?`$@Ov>%%){B?EqWwQKmoM@5} zJ6@}&Fk#RM<9`-fxKo@-o?P<~r21rd>8+3mvwg55A&>x+PY|zS!tr;+@@RX_a1lUG z+!`jnkJimQ0df{lx*;SUDe@81sH$%Ce(uXve^#k%y+@=5nI+dtrdxIs(X#u3dlLmh ziT0K?y+ju&Hc+}X7FCh0C!r^rAlbh3x(Q}V=HI0(xsB)Zk95DMlF|HpIJzWo^CPP= z?!gWrU&M9=4O&18Wx(q$u^~_Z+UkAgSN)_#aH$Y2apgl{*C_b%@|r@)OQHc~z1-pU z^KU>q_x(!12kbtrcmtThm$5vC5k^P)?B+7JGH#HOIoo~8)AN|}T4uH+C!^nWCVfKB zKk8yJeR#{4f1~i#tY29V#dI*209W8?K!94jcuJL3`UR}JrjO98K>J4oi~5Yu@5=VN z|Nf2`r+KtDGCmD_=Gy6zz0G9;{b|hWz3W~J7I-PY|6Z~5RmlBE_o0UelY}3IKi@_) z&EfGuE=M{`12h#UFj0hKI1CSSirpRo5@1M)s6ZrOJ}Q_t*fA3}v~3F$L^z^gLvv1O z?hzt9h8S(zfd~B0!QI6qgrkDo8EGAKms#nv`jc+=Sy$I9HYL4X?T!F6TS`s;^;jOA za@*}kMgWZBH>CcfIUkvKLZmc{@!4*cMfR1(=p3nveR-!0=Biiz^xr*`8dzYgu+hJM z0!|~?P>1S2SjY|~!qJiY+w@MX<8whh%cF{yT!0%@Hf;`Xqh#5vL&+FsI&5s?p;>57 zJ@|QL6M)+F1?kY^|9bzFkv2aMZK)9d!J(Q2SfhN-TnTvIZkIefCX9Qq|4>AY7GR!w zsnuaIdmpJ#G4EwB%~>^rnyM!KyNC&e{lo2Jf{o(F}AmQ;71tq9Ew@4tyPC zVr8D|iVt<~JM`4Mh>f&5S0BWD_c>Lf-5fXi04C8%Kb+4u@Kp+4QVHDhz-Yz_}+ssoGr%I|!Srcv@>^wcZq`cAwiNy}92 zSMmfV1EcM@S9Bapkay_;;6p9A+=L43GXdvaSdl{JWWe3YWVs0$?n5mtO^#!Zy%M78 z*NKf}O)2k8;^&&6GH}F1x&gmaO5hb8zlK|8fzhHSsaRt{EZka3K2t^=L!U8PXLM;% z<*{D{6vQRHTZYXF7Thh*7FKUTq3sUD{2$Ca6tF%vg%uW^xdE`W7QJDRHr9v#F+raVVlRm}NujrPU z&phhpFq}5n^xYu^-$heY1yxn=09~xHvEBYI`(bfOj@+9ivTTfeH?D|2gz_B+ou#^} z_EIBPe+u7wL~c*Hn8OjJ_r&R2?i|zjy`VWe(@iFUi#7WR#oeRgs}janoUdH7jlcNg zGB&`>asji&@!pRm`-hlXmKZbsc%SAe+k4jftW1x4H09~_nK9H_Pgl$~6w5?(Jro)3 zQgE2un3|f>^}YSf5Qp=k^QigV&Dm-&Mj6#AsLO7N$$6n*MpU`ve@^gaBTdMh(9D0Q zX%uwoz;pbSu>`cB37+`Y2yodl_^vwtA$We*h5s>xJ!hL)vIFg{gj;a2tT zqC5T-{*4Z`=r6Ko3E8>nXcAYTvEeXB|X*G-2jksH#+rHG66g*v4w;DLLp_n2tN z&d#v^jj5OA&6Xp(9#eK07)bhhb%VL@gmJ!eDoBURI>ix zAb%XroQ9fM^-P#;{sE=1(}Z(kC7%06ZkKRD8}goC9fahNc2$Z8xulnE?i?x#zwZ@o zR*(+%JA*wBuYBMq0^ z3oxT|njfqA66Qh9M`;B{OA3?4w}6VV(;8R>AgIdh2 zvvDqNLcL$x_QN?Si@(3JQuRLN#_FzP^bi38+120QY4W^gY{;Y-`_BXK0#g8gqu~ar z6>?0f6P2I{=I0aT0W_{e)rE3`Y9&Ds#-Mby>gt*hEiJ@nPLAE1ltL5F3R1xoYV0-J zP{MPxelaCFm>wz05$VRC*9-jUMwQ=?HIO8Ux>~|t7c?O9nRrq%t*aboO2`-tNAySK z@V3UBn%DDB*J)BjX-reHBI+69;W{A0hbey!^PAvm(Lzkt6zX;MQw0*+evL4R&|d{e zR&z8dU~QXaPa#(G@M+H~3V5WesVU(mGu#lmzbUVl^44O-TvpMB{hZ3G_27zUW|=9` ze3tBm)I%y`N-$BViNVh>WEZUb7QBT}5xnD67K-&2kE^qmlY_~W# zt=q&b=czI))=c7A6_adr)={%yQpV$Wy_*I-Nkv5%-#(2aDsH%Oo{o-7+;ZDXjTG_* z{wi+g5Zk|*^z%R9YUP~sRxX+axFB{jlj}Ka?r+;%_C}OyZ>G)fg4&|YTsFdu>NC}6 z%!|z)MHL&&Yd%j8dLPqK;E4xg<#gnGFn13MtWpm@^Jvn5$Ce_bgc`%IpZdKlJvY=eMm%C3?;$vXq;IHa zB_ck9vfibWYN=?ca&ipGO=uxjfr!r>dyGN6MI3t-pwGY{-om>#Pw;&#k2*|iim_vS ze31&7Bwn}YED~gPjgQx8NI^ZZ5-fi7kQn&Xo(w;x6nG)I)%!77{eC6=i4d6staw|j z4$7)|>d0VBXI*hm)oxw4l1nx!oZV~uJX@@71#aL@OKpzmaAioeP-)wfyjI- zM+r?EoXNedS4k)ebW3}&;m6x%bcI(BRz^vLfVlEk_fB1+D40l2jh=#H zVKq#WlS8abG&o@2ZbR@#2^pv%DPNUEI`3L{c)ucgobtj3r3uDKY@4g-Hi^5T`47^K z_~eo(tSgtPczn%?CGjS;!II<@8b<|K4Kl3JP|g_x%@`19%=DZ&7}ydiku(%sqzMN zgieWGt7$HhUpb`28{7w{(z>~wrVgY^HU=W{kUwC1xA&(3^xm|DbG6YQKQ8<~s@^iF zt?vsL4uJr{AxQAx4#9&5cXuuBZlzeU;O<)7U5ZwK;O@mraV;$sT1sjA^8dYe?#%s| z^&w~GoPG9r_F9hsNK_n_Wgfd|Ef^9TI8$d&dNXN^0EDEQ@9sd(3c=64IP`Z))u90_ zr799xN7WV309d-?-AHBT1OcWy#^;iwW2ye?C8V>QKl-?wD;!i%N z^WF5a61z-5=lK@Nj}b@j2N^nwtyz4Y(GmebV~+rJFxagCpWlPdUQ*)81jzg}a zrg0;lkf@iAdv5~!hsyu-8g=_@ z{v>W>E_^fE;|lw=@Kg~{sFQj&#ArtiMa)%<^qu>8j38Vsm9uLh&Q24Kv-WbX?g zQCwDaZVZgE7!5@#Z$Ik{H0}P@GQ3T*S{lsKILQOw6y#`s6RJPLOS7eBI8^(m2xxzn(g*vvv zd92o_{~Wi*E9tSPk9UNDHy`5{ss}{6oJ=eV7q-fF_vZLcyey0P&F9?*=B^HvLo_gL zLAZ7bq=^z%4aKHxBQ?38VSZ+<=Z^icJxeZ&1!qtE`V|O z%t5KMBp-z13#&sYWw>dPZbmW8ShL2GD`UGR1OgeBs(4i&C2BdM@8qCqOF@KtEe$ca z)*h$Syx%0ugDJzWhpd2J6A8gjRaK$_G5}}v=`{f?g*b>yN~KhZNrWDe-&9~g zde#!@{Fk|OU#74z-Ku_t-fy%`p)K#C6E!!nC!`2!K*t8DRX?tqxL7d0;GLjW`V&m! zCH)brK^rtr)mh{#8d^;QX&UVe%vj%&iC?3dgWrb?5LSZ^A3w4;K7)LVnbkg5m6G*+y zEP7#%sQ$J6H;?iUWi-DFd;(DQl_i-p8HukQl}SVowcH`$yu+8Uk6QYJB-yNqb#NO7eUlfB+%g%xeex z3YC;BkRX5rW>yXBM5aJt(y*qAd)Xbx3O*^BJ}A=`9A(xpLpsduFL=qXfMGQD6=Y9k z%K>CyaEXGc3qo6-n`Fvu93E4<Q%{eMbx~9v+hGchw%Aa(J z+Ci_>6+won&+NeWJDwes^CP&9U_>+kXe9d1(t3!th24$@UqBSl_j<5 zPrMcpTwMmSmx%5u+r;1N(vj>eiG^P|$FO`T096K&>OVO@k#0&3rtco1>`+NtcJyN- zljBX9A|QPl84F~7(*(BRY6p-x3jmjD)`1wAoGQm~x31!DOm;`jmb^=X5wBI)X`wMC zcF@}iDD};?k^^pFK$@x$6tlV}AnI}B4-dpO$AJDz7$WY+!q#tT-K%H5&9zQr)pqLR zlIvaL_>{UvRJDnzqq-kHcH_N3;!qqa&@ywpbZXASIXB419ps>x!`-aH-}kz-sff?J zI7Zs{ko#E(Ec%)k>U=zE{!iTv(ySG+t|xp_lH>nIxB_l-c-dT+y~? z+&9hNC1eg)Xd3(D0&%m>0O!m0&;qO{>p`m2kXQESKbSvojD%C|=`3J96}wn~4!)I4 znCCLPJGRDsgH2Ewm#z*fQOr8&j=E0S*Vr$n{`fXMB@I>%tq4cb$&lS*{PKP~`>FjG zy#2vu0>C=6_lU{YunIUa(mud&2cwy7qAzlU2cCL8cNPzaDIk$RyMVRu;ouk;)NVnN zTLK*wkX~Iua*8pBS)q6wkob5crJy@{gy(1JQR%jHQ=pVbY@#KS0PSo-Q)Tt0 z5YH`od$#ywM}V-)KnU)F7G_0sIwpHb zpyX+jfoomclq(!O_MAQS{1&w0_w~EmMw*f-GeTeMO~j&4_2<$PC^?J&MWDwx*+r6QV-wT%$@Vt%F3S$TPiK(4rB1+7$g@8>~reIMlKaf688zn1zmP4T5e^bPxV-}M&!6lY-!qx<|dX9U~+sGvH{8Fqcu zwKHuQC0dJkX4ccVb1+WBjzd)`1j?f6XjrdUi0^Qg^|+C%6?)L_eK}Hws*2}Z_RUMs#T3z6=X(>NHM|fIJt2FC@`N}RDe=-5k#c@yi6#rxez6wD z-s4%4AD+NhlN>J9CU%YcR zs5if0!+_)8mT?ku+i{Xc(c`!d>&N=}H}<53+h(xFnirFO2>9{&YdL(tsFs@8N_5zJ zE&b&Ec_YT;IPSH&rl@cfR<2Ox%^#L;Fo8|-N9j7Dtp&p4Lq&#(Jk|&7FLa5HJmf!< zJNPir!|L1_$JPZ8P?#r0*KS-nhF_NoIuy)BDaP63K68)tPVJT3 zN_SqdqiritCItAG${On@hZ-rPnbO3Nd|FI0=V60l`l$5h_#>yXWjGgUjCXp6WD|F$ zG&!MhP_Nj^@jG>{b!|6KW6?)1{JQ#hiG7jyvlzYs;i(8c640#Mj_n;FC*CFB!Qzca zuq0C%ad8aI*8vKX>**v@U;9?o4v|8)NqF;1&Nx8r&l8DqLF3O%I>8{-9_3LYOEZIZ{HEw4=~JxMu17B1q-K#Qq(Bw>WXR;9#({ z`R|wKM(UEM7a?MQw6-HZf64vjpcL2BdS&n|d@Jlpcf(CcWciHBvXr&#fa$sCONZ(Y zCrceE>Ccr7%4VnADf$H#J3e&zXny&;+#MDZ0@w*N+uE5sME|X2;P+s`rwP*hHNF!l z^?ge72=SwoHdH$l{2V2AIzl87^q&8obE4%Bc zNB*rUC$ISHzE=LBNF{DvCx^UtNPg#;gGu_kGO}VflRN$=@>?<+9^<9dEP_ zUK9jX>qO}n`sTSa`Exkps~G1BR=bV;bSh!j=ZGVK&$(!OW^SmTzxh?=C~Dyw+)i?6 zbyfCUm~i|Xg%;NQS8Y+ZLO;PfeV?KQUHQY<4VN!g$VVKGk-}BAu2f#Ee_An{yp05k zc?0hJ)`X}|v>a^x{)uvX{&WD=-MbsXh`NFB?2rVdnZ8kl8hBecvHw)gaP}u`gBr!z zSFnemhv^FtzsXYrBKfZn4KiMZvYmz=KAdNn>RE=##eVMPlgq@~_UF}de*-c5mu_O> zDs&z^dp-??)Y~zrG8HG;@bv-6+}bgJke4ud@-6-#dli+D@*o0*JurD9kH(k=Ab z;1|^%Of1GYz9>whB@nJ+X`nLQlrNFr+9UdYMBbd{^h}Sd{_z<4zdau*k@dLteK{>k z3G}Ow4wggP`fRyv(us>5KS{eJ(WF!estHwc<*mt^MDGl3#Pm8X7iPfQj1t`aZ@)>; zNB_h%BlRJm9Oi~Yq$dq7W}IK77)bohE-9eoG1OZAfz`qs09X+tP4h*>C;ZIf#-n6* zd8Rk>U_)ycm^$?fM91C2)=av~J>)1C+q>uz(qL0?XFbXp^ntkPZ2Kn_^qVE0{p&dw zmVtD-B$pOzKpju$fx&Bxiez5n%I2s9r6gfCld{CB5@4dl;1j z1oiG)9H20sz_KFs{mp2TL;d-_>BfW@<~)AWyI`vMRJ^eTpoCh?Vf9|%BfcD7KE8}5 zB_RA%>P9frCGLV=Y=eP6(Z_8@6R2r%en(4yI~q#x%_AI*w=nD+9KKZgmP6+2KzD7i zQwor;9CjbslSel{Q5`+ilnKwl*UZ$3l)9psehL|OrLNHrfVeACrj9=yd22%>S4t^o zNLlsjsR^~^Gp2cvNM@z|?3#5I?d3gCT~F#4EncDgtwMyaP$McToEh zs=2d^HlY|hN6@=|{^>s6k?ApZxpW+kg_ejP-^oPczt^)Ty{tno*fqIy@aleGjptQJb+*`UUWK^w~ZnY+ z_p3>oNky6&_I{+@PtkPwRU9vPiJ-QHCK4i&?snm7g&yf0lQQvQ6N-Y6o4kCW)`k89 z*=jh}ei46CB^ro|rx=mKKQCKPOfIA>Nox9tUx{l5>!&Q4_&rKMlIW2x!H_}CggXp(^J<^C;Uxaf& zn0&9?R0shSj9tYGP_447HR|5YNWp5R{tPnhPY@2{-}-p#{g`{+V!HlLig0Yb;qB9L z2Qw4tCst&e@i4rm^pOVhWVR}HejX;MV)95>X10CGnl^oyYB>LU#&qQyaSmaGsPOib z8rA+v^?SP}UlkeLz0FzPvRFrBg^M`#Y!PV-8oRmqUNY;bq^sx*BT&M?Z+rbCbxGLk-d76slc+U5% z`v_U7E>;h&d?0?W6hf=$Y^QRL5rZ95r;Kk*x`@y-3T8pCK0#;k)Iem!+&$lUkIPnjbWH!YUE{Qkxur8;_rz1i&3qH zlE@`~2rlUbn0Z{^7~HkSUnnemS{R85 zA61}DW@M_0BFpcP>+NL{WmKW zdSp+Y;aj*R7np9_A|$X>R-}U%rz(=?EpW?9zk^mfQ?{?^oIfEA=5(%j6kO6Nk($&y z@1+lR66oia@W&~kMZY}p>Vh#b+BD9Xj z+(!n-GUMaVLCPcJB`op15)0&h4x~ zOnw?Kdf4Z;3mp9#4d!}JoO$TT3ALx7pruXpMbplFVn(b^6|=JN0ivAfDe|p)(s7S~ zvazU}Es6KvWtj;`4hQ1CTp+|#2B!Gs)*`rcLYk3 zEs}t%W36XY7`3(5gB7jK?Pexm@EmM;eZR2a^yflGs_-s_A>SK zQ?|~TI(x^9EAQ|bOu~j4yQ9Mm4)L^mK3*b(IMBK9ZNeS96I^FJs{dOMCgqe+8>V$X zub>D|FDcFF?=`GwG2co22^A&CG;`uFdAlg~H4cQHHGxySSisx{)+Y*_olB(min@~Pf%(2qYh%G)BCv%nXf&k3Tx3vCezMGXsep!?;-;n(q0wuGSGeAp~Fc)C{ zxY-rHU*|b<#Nh}t$4!@6{O=EPR@#Z*)|Kw!ct6mP8?Q2fHw z;2}3q$Q?Ukk`6{yLQX9RZq-m36&VpQ$*A;k$+P|}1+76aTS*|$^uPJt_Js78?0eu6O@jc`j!vw{2{ z{ki#n`tvxT9_kTW{69El0!zzSMUO);CyC{oKPPJQHK&*;Z-@g^?EoNTT`;yiNja^a zi88+*6-&(|DX;#ZWznFnk|makwP|B!tCw6lhKZsrhbTbI#4C%GK%=DG{P-2lyK+xa zmcB;#7Q&Udqw>CcH|tO~_L#5TzUHuclA97gKzcM{;L7nVbChD2!agB`1e+o*gOqHz z&*b;0UX7NCyv8bx4o+L0l&R~d#Bn2&+*Ts&^i|4a!1Y%mC?fU1yom>&IGgojnn1Wd zz@NZ(k)-wjYh2l0WSV~O{K;TXB%%wdB2SdMtbq$Yhf>T_q~{a z6sm(`QMwijk_y6bN|mGZz;B&yPQM~M@_!Jg9OtxD4(yl_OG}%0D=w?FgkDD#fiYD=go0`;=J7=XxmLmG5Sqp`+=pVaCCdrsQ0zJM#!?g{%1ZkJ?wm+<^@jehBS z-eeV5x#r?r^-Lt)cY#3wsrRNpS*ZDB8aexckwxj zU5*RD3(>n5wLU6?ay`anCkDBC+#r| z;J>gdSM9Hv)e@Y=m&Xq)5%D1g+Aq^HrjrDBQd4cZ1UXgy91L&mgGH7bG86qzA0x`K zSVKyD@XC78g!sX!_U!)}Z!1f07@WAZ+$gr){eQxB^1|!RRfzi~$;A_etrtwaW zNsc4}T56#Q-svwPw$j1ciT0x#cX2mblmg%%Dii0A*P$`F_q%B%IvSLhF)#H=gN0)I zju)Pm^x^x7NsuTHp(-)%kGg{0bEEN5ORINPjyme5;vI>nA6&I#RKP_I-_L`-hz9zH zT=|wX*OH%EIpR8Rb8L>4atGgUgA*6VCDdO9tX_?#9N?~MNSfcxX{Ul%2rlO zRi)bUe?oI@3uBvUX{Nvz=>>D1$RWeu>sCap-i4il@~wLmrWK&r^{)Lka>|oQGYyyJ8lC5w^nqk;sEb=U z@Z0Y-RNZv7TMCCb#Tu3W!Sl&^v#Vu$sE4U=JcMS<#(MjRf`fP%sQ=#)tn^XwA@tu7 zj2Te+sQ7Ry_u^^aOsR6^03&1%3vG+NKiClz+>zuwQG$Osz$L+OhXDZc{wc@=TW-2v zNQz+)C5DEj!qV%KUyCs}Z*`QBsAuwOuRlBeGaAIBvH_U#H5jWPL7I}t%>TKT05q_o zu(GwVmEF2~BE`erRg->Twk7}_@Wo;vng|Jabdtd$Q4S!9>tF-vlBE8O z`Ll3FsFu#$;~76O-R}t)!}2Y!Ly##lIRxZm7QPqD?pOrAHD{_8iq8-RCl#}no|y;9 zmO5j9`~V?AK%hOAl^RQ6+-)wZ5wl0Dn5fe+m@ShTS#l|Ogzb2L7#OL9#K8IA1N%=a z^7io#c#yh^H>m-<9R22{`okQt?9Gbn=ZZ>2!~K7J;@k0dGLgOB;0{=UpZci{RQg^^ zb?zAdU{Di+J#{tv(L`bTkhPO7W_6GySiQZ=Rfvrd*II;tB)VaQHa}=mk|Voq0QmM zWqJo(1P5i)F8^rX3;w$nX#ucdbO6bsaJi$@9%!JB3|Er-E7#+S9RKJqv4qXsMS6WY$1B? z`%7||=ZW$bL~hYrYD%!6Q5ddbMb_fuaH9MMVeV9L|hIMVALKR}}(pht#f3h^&!iNKylZ2QV<>_h!0cJxgo^~5X|FAEy zk|0S<&E!I=I2svDCRo!|u#f}7>Gu@Madg;0k|~bLhnrQtGfyiqur6z=tb2+Y9V4lb zgtfRa6K5y!zAQ~1xaTIA0K;0O#k~QQK-cK7^Lnt_xrf(kYiht%#oya7^8#mT`}%Q7 zg1j}ZycU05jwcSzD;r->T#-StbOH)5`Muy*$xc9mx(m_KwHox)QF{CMUY`I_gu9El zYxlgQZ zR%HiKWl0RZp7yEC%iXl`_4M^@RXUb|0EEz!3~iJVvF?>BE?cXtzv;4pVW<0NEsX|( zBxeeBjB#Uh1Vr!g^G!=bNwKltXfTGTDS{vrn$1~X&2h6s&PSfAs&3(P-Pix%*zZ=O zRY6sXd-b>_90kQZ`Q4nQ&`O|#e2Uptlg39v@Z{(fnHm`@CQ<*naj8jY(P5Fi!vMZL zO=l^{C{MtaFVPy4GmfYh6UuD()oM^-MT5ihIbk%%f#rNO@Yq?4{>B!OjP1`YUib_t zsG_p00K&A=NN_DyoDd<2uEe)Ms1I$SQGW1rNmY_{Hg_C$1D+3IvIF{9b2S!p6}B>O zR(vukpc?#^^nMcAGx%6=66E1Fz~N%rNnjKm1xN(NRvf(HvZ(Ay&7>EnRd70mWWYZJGO`8C%?`veX z@J8`xQS;RllHbcH6$W~GvT8}H#}g^wlWSiFaFYK+)P7>QS(IY>bh2E*L(EX-i#J%# zy4&-NZEUHCV>c%^?=Gw~}bw(J=a9#npFqGNnG`KZ>?c~om@ z&-UZRfx7B!x@e_&-dz;XGw^@b`{M9OKg_IPyFQ;yb(dmEJR@RSkQBizVt9OsmX{Y) zg(N}vkJGm0WAy3VyG4K){0gS2TsY zQAa^m>o>Ut0<5mN9f1GYM;~QJ@J8x4(`oiql^2>42!#d7(?chh{sj~ zn~vnn#~mBUGC{q2x~`qy=SkJz?p!YQ-fF=e*jGxIB)83qXWLn)Ql3|{o(X#R_5D68 zd`~|SEPTM=J>F*jg&AT_yH2l>dTr?f{-?1IAVNwrqniMu#9}3^4)sTe^DHm2w)$09 zpEMkN_%JyeDf@@PoWte0z+NP$RU@*HE?b);7;`V4d~5fmdVk)(!y@x_^zZKJ!e8-H zPEr-S(XGO(7v(zblN&GBidu<9VV)8U=h_@2O4?=CS+oOx24#>N#M@H}Cm#MH-`1Ie zpR&HiUipMWJiO6!>#vn}a3{_gA|u=S#JfUw?M8dD{l&Ym%9pWszb=Ho$%!`y_$;6& z7b6`%JuCXKpk)~HJHi!3LcrizbmAQ_&7#9;5ct&)>!^nsD7gK5t=YK5*sa=tT{eh} zI;WxN;%jfKO!DPof`oiwR$b+f1&y+&Qhz6;I2Sbv)lXjcYy_ac&4Toq^mrZ8>4JrR zlOEj3hJ_}k-_k#0jv&(fnVYGZ>Oji$dU@u2QTCD`zhVl*6;=!IZCN)_c!uO_&Y-X< zQi)y*#InYr#9#PU=%}lzv6Qk}rtsZUv`IrWr0W=FBH<5g#gSJu#nIDGph|3m=lF%edziaVQRFJqrY#8>RDx zt3=Dxsnj>{3KSqqf0a4kOK2F)FFk$Vp#U5?qi$h5K5#qyo(KI~)ni3n&NeyPLT0R$ zXjm(N@;@lbqajWa^}rGE3fFz-QDr?Ow@FjQy7xUq&fBfWGISBgeBj~6d#i~`-}gfm zTN!e3+e{SN`Vh8w887`i{BOSZTXltk`n{e0bECply_i7RWy>P%qy60q?cISd(c4~R z%jxOU7%d~4x(@!cHLyKec0r0`f4qJ*B=ffzYtvI13fS3n>1U@JIk^CV+H-3CO0owsYnt!qhj-mo^038hM8KuqZG^K#Xcgz zJFdiA@RA_lCi+ujdjhvtI@68I03=^@E55@hHi(7zy=B(L-Vt1q}CaiT7!_s;gaPSoe`7yQUwpuv1~&>g#z|&8j>k zwHfdf(e!-T!cBKXpi685X01yNKPMwh;>5l$yO)@G7NL4z@1|F1|N$=0w z%u@W=73W#^G_O$25Y^;Ix~p_5F8cFQ-s~wDXLNiP-8PlTLBAL0iT~*x?#K_$4lR7g zqG43vnn!cMxmRHqR-?$V*nkpw))crV?t0N?ST6Q;roMIgO#68!t>(S z?aQNxBZ#^#OjZ2+JI~8LA`(O@)RgkM4WE9Py$yY^iKdcEi_a;~KtN zks|ZksaOFHhsuCq0BNfN8rr~`9pyx_8E)|i3<0~QSq{CqUP{D#U(&wTV-uKU-Ss%9 zWCE#;kD;o#7gV^OLJlSKRnqZ`2S^S?mKY6^(1)u0`ElF4VQPTZ`v-2tG}v%xrp*z( z$Kvq(n@6AW=`R8kGeGLsLVPiaqTO|)t8`+LK^3RM4uJ07AX!g-CPKwmCTbW$rbo`O zYqkWS;>Nf@V}+5>_6&1D<6=#|TLBju{$UD1?Cft+6+;t6NIZ;4)Y&2xJ{0(qr2+L{ zq|U!^9Lt6#xN_+kHFCE#P(X2*JYj+Yc%w|DQ=G7Bzj%kJ)aB`}ru}Us`z9AIa1Wa$ zT2emhkRVASH(l>ATdBo?(!^2M=E+@ei5UG;-obYU=u}-OJ;j{EN`JjjGcV(sFDl)B zp=4jI_ef5T_C68;2av9?Y%kEhMc>wV7A*{-WY z8QGgAJ#rC>em|~h^Y4jsI>vExf93=(R2Z~eUGpf{fal8%Uyp3($38_LOJ)3)U;3!y zP))*IU5Nq2#;)2tPtHz{!@|R*NwN2NF>eR1T=S6k=wRBcTfv^}yd`x{YMWo?BZ`h5 zFmU0$AFSay&gd0X421UBzY~I4)Ej2r-st-ko*(Rz6b7=2b)}fs>7@J=%TzW780=^M zSoIJqv?@F!PwF|SkK3(c?m=doGU9Wc7@clKy z{V)mkUW{^a)_p)9ACbD(axL30GKwpG=g=}Z$NWsC^KPB6itse~H_u1_^}=*_su1g} z@?G@IW2!1;PoCAd@(bcvegP}m33G)*X(MOaT|ly=ZG@_%<3Ba61I4RF3aqum+BlAl z!z`C~+^-4QU*ma2k&ewI@0F)Jq4TV4@y~xYW-;R==e3xgX-D5Q)1_STXNhxRcdfrS zvfVVIVxAnsc&Eqpj`F+V=tf_OkIw#E+S^*LZ}ofQ26Oj$mMJEAlCABme%_io0>h=YX&2yOcWSsR|etRbIx&;u3;UoJ`+m|_0s~_D-Z5AQ4JNcAo z?M^`ZhrB3PQRzU%yg%D6Hb1;K6W=!*S#H_#QG?o>4D361;(v_%7MHFQ4pjxaJuQ@p zWnAT@Pl_mP0+9>w`R?>^E}`H+R91C{DP3U!R&lv8(<(Wnj|`KpPSL zj%sStvaOj4qA!}m#0|CuOaYpj(mEI5QAw%_K#;LnZ#@@xrVQmzfU1_BM+1C`G41rwWzJ-Xp6~hrHXmW)4106Q7}aVibYd6 znm-Ct4f6N4(|pW5wXeRW{*4A_8{)7Jfl=WXEXy4cDA3AN$s2R#XeKuwos|!^|MnIh^z2}rcsQM`xr(jYU zR1iL?q`PTC4?!~K?f1!S{m&t`WxxH{vm8RSjha6;$7!zlu;7q{nEf#F8-Yz?M-$Q~ zv#4E;s27f0a&0*#&e`U22kPg9M3BR3e6=tz!!{DD8!TICq*^Aj$DI~I2GPj|AwNe;8ZD*W6>G>zlZ*W7L?(5QJcAM5l=3n(5^{sgUM%ph z57d9SUhDYKZVCExuiB3o1jP72skMq@a!k`!SF8$@KpMR_cJ->M1O+4}Dv9ZX4EcD; z{J2m)-!-o|l^I{2Hrb&EA65?G`sUq4+)m(XrS@w7)|rv_*VJXQd>`GaB;CHG4(BMH z{V}s`kaJ876pqG=fNSZq1Scv9T81E9_&%X_WfVhEFH>pEa=j0{o^51MADF_TRL%Ca zYA>k03+oUL^EjM+8Y(>NNh@7S;_LHHG3_Xl%2|xx`Aqfvbogfr*{oB#s;0>M9G_vjn;yHSJ820+Q-OO%FOUdVTJs`fqf1GS-N5kwZg=ACF6ZIqrY}F zLRoRZrENu3zHcgTm%e8?yHU56q7MVdsx4G<8}`POt8?x)Pp1Z!L#N!2bTbdW?0R9i zsfz;-v%Ul-$b07()3R{z_cPh>YmlJ^F{q*`Q!HWa7AoQPLC3gyzDoWqY)y$AN4_=Z ztAwQoaKw$DkCh<`7E7Iex%MgKjf>NBI~ zyRR?mr<+pq6wt1e=)ws$>~d}BDWEHva^WqP%xVMq9*xuHHnY=?q_UEw+t3-|dt@M@cuHqV2p@rL^KGW0%iw5NR?p zqi~b?@qC)}wUA}S;dOCFp-E&znm0vhKf`i9)A_#HLdBm^Jch!;^Mz9#<5X&tR#t#| zuP7O%IdCLq^WmKPbS)i^Fg8;k4Rv+tD0^eu6di=^=y&mPYzh&cDH~qG9`f=+<=~)d z^N%^H^?78FW-t(i1?B?x?Mvt%tr=_ zscdv;V5&Tth%+U{af?E$O$1gt-rv~mhgHgEg>nIFjIz^S#)NWRXw#E3E_J`<4P|dR z@A9wUSkEj%)eN!01g)fH-603s9P}I`OgTP#aPJ>w@W2e(Wo3IZ1^$Ugnhwo!kw+yv zT!_DVx-w->w4GBQ%djRB#@|3V=odJTAAeYL9MoV($MuwE{HvYGC&Hivwzg=HCmX#z zQPTIR4m#^PT&t5s7ABS;UR1JslwK5Fk=T#|SuM&_#7MDkvi z)l+AE?X}Z4$xRFA*~+Gj(^C=pmXOkpifsa`j5#{7k6E$iW^gS;-77|}j%zBGn4#hv zF$pVVlg`EH&#Q7L7THQY?P`bW1Ybv{zvPTDv5#k35NI*LpgHVRGee)-(u}@IbzUB6jVYWtJn5u5>Tt1ai|3gi#2*{mAh=TL7uQt`jO8J*%yerH zvVCaRS*O(~*UOdbhMd!LkJ(RT!(p!TtuMVsj0>g`^N8H&Y)dbvrY#{KDg9g4m1~AJ zf6a`KYt&bf1Ao{b(6}sL zf3Kcn-KF1S2FPFL4}s7q%Ze@0V&HBRQA<+cpTuvby@JEaiqtPR)#otowpBaQ|9 zmXrLaed9NX?-A{*wkr(=JMXIXv6qVAuTca8rI9f7MNGCiZUC;w=u2QF29M7wJ4Dq` z@n!lm*ch{zVPZB-l*Mbjz{YG{9H0-54D~+S^BC&+uFNsZx`{!8lR}L{PuDF``Bw>I zq!8%_cgNq$LMI8OmTKI>9pt%2B(Tx*!zvO6_KAF5d}}4NcJUZgKO_5rCUK#VH-3U> zf@VBcq@#rPnSlBH|WHdzEuA!fnWC6*7fIr9a1CpEPb))(0~n;eq<_y%!h5*v2` z8~P0~$sIAzNnU0(hKb||^$}f2F1%bNr%_X?B_*z%;rJOyF_A_*q4o%%8mY`D4;cde z4XHWyWA6POg5oVN&?*xkb~h5}wQ#j6o*i3@s&=V!(R(Y-m8H!ReD;p29u2X`9+)qp+vyN7+ ztRI5#9yCNgia!tO)rzC#2(^%O{AH(;ficc4Tu?Pc^!!J-&JvG+H%;K~~H$cjiX7Mn0;yyLe+JV`;55`OJ zO9_c3D-1SE(NpuetByBNy{uTD8&F~z3k#)n$E^BKt(W@JMpPGBp}s85GLno#enz~0 zv699=H3WB90(y?`gWEZe*2;wuokzY~IIV$saW^_tw%bduFT_Z%C{m#6a0yj)xNE4V zVXJH{3yrs!j&~cED2IIEnlPSNoD&%@m)vdFtTk+CL=o3*2-)WrPpfC!T6 zaxr3C_5;TU-gUIBV-){^AD+98PLjcU)kUV3qy7BD4@VSuctX^Y)<`JoSEP}E#x&85 zji$h|4e(6mJ#>RhTuVbSx7V;PSs*hFK0@Mb2`=- zD}tLstGm^-b_lS4>+jt6RLthv52xn?p=o&?%Sp3-3H4cps7tMO_5=Z3840THsAesT zXsEM!3~b+1cPg(#I*PCs6H?=LhmAqZ%T0Q>QnHcsjsj)<3D_YVBk=C>OlF^?DLH!X z-+c9pw#k52wUp=SqHhyBvs`k|d;(q9POHIVUv-R5I5+~a4od8GuNT_ zW7g16t!lnAMqW*8!d!ie-MMJZt2M;>RP65Q z!kUSPeU`_4J--_mml=~R%qD`nl-c4il#O(;IE3=yPx?&XyPvNN8aqNh2d46!Z|W;c zs2y0@k(ehk#H>v0JyUU1*%MDqX(ASxk`OD=W!2JJj$O#Q! z9ZMHUyi!!+LUs}Ae3}6IuUToOI?}GlyCyP^VKnWM%LoitkM(HRU+i=&ohYJQ*)V8z?zbP-Y9Yms}dDnumz0)~wNMrC!jC z>Y~#6A)stL&fMRc5Z3P#hCKo7smilNprFVR3;!BV)KOBLTNZuy=7V0{CIne#;cdl5@y|x7eQ_<)K=$q z3S*gZlew8`$y~+Q?Yd-3db*v#^C(@PGOb98Qs~DzD+7HxCf9{-tk{sk`_Y%)dl&`a zweIFOS^S(T2*E_(kHXcAl&Sl>#>%cHn&*4{6GlB3Xy^wVj?2^JFd}uYQSHF+SOTBm z*AX~y1>b|fGxG}%`RXN5km1CQoidHcuhzbVZ{#$#raFOTwPA&SD4>32P@$e}@}nfs zj#F&2C|M4Ok^|P_$-Hy{26mJOGt8Q3*k@h)S=6z=^@UbjKeHl>Wog%)Arq&V zQ!=o)hDUIQs$qo-hWmG;8t>V!@w>jj)jdjr7v#9#5YMu+>)+|;4x)QyndYff%nDDL z@;(+DWrzv@$BA~9J>0bciR=zQd)7!pq!`&g}-2UyM|$&YY7gD$}Uyn z;*ZEFe(^`?sP<#6oGF62hS}z{>|f!`Dfa=Xu1?YaoP}c5F1ZQiaiCy zMtujx%69=76_;T9JT&kIJ$f2ifBmPFYWuxrNLTG@rWVp7t(#2iRR3P(A>UiCbmcq& z1WR15y#oJ$Dybo|$|?9WQP32w})Fnx+G<_{(e^!nH9lIe4gyLMew?+ojB=;*WbO$i3; zp`YPa$UcewH`g#Y-T%kbSq8PWy>A;Q5Ijh5cMA|8I0Sd6XiEqd+zXVp5CQ}V?(R}t zORUOkjI$GuoG;8x_#Q@ebhW-Uo;=s?z zCJE@#g`BDyB6PY$`Zns@Uv80X+lsorn;-%^p||=q^AMdqCt?#p_F1^ZY+`{t=Uboe z3-f0pd3EH7^%?@obaLh=x6z4IQ-7Uol(6}7cve(CXBoYmBrF{Plj-V*?(sFE=k%L>h@!S#?%B2?v3$535nwU@OlR zBl%ctguWJQ0u3D{`$yr6%IYxI*&m5Ec-gn(eT=**87`D=o{X%02PDE1Yqwq+=AAq> zr9dgMz2o4Z)i@EY05w#-uiJ?o%&wOBuwHYNJv1qnMmgB<(0-7p}?*VhuW+|K@6$2}1=~YC_sZEx;r^t=p2Lpf)t8!uBV{$zm_T?8tF6g9LG|gW8j&cB zE>6&LvQKlpaDpqcXDLy7J;7+BZ9j}786dSc?}3vJReCouIyw#t*hnDqC9+`^T%9K* z{tw4LslNisXrehy;nkHYcKtzOl>+cRX~ofbN6f2DO6R+4u<1M%k)ZlyC?!>&**Ii2 zbQiyf4$(vY(Ug13bF({W$`^k-k<%qin+bYa{}u(PU+}1<95&hEEMxku1l6`=2SO|S zxB}w4-fMS#pWD=r|7v!ZiRyqh1%@jyCz6OyP6%s2Awk_bDboE{C%{#WM!7Jh_C$vh zy==vpxt8gm^iFLP%J#Q1-n#ZKN_uf7z&!>K-sfx#4-tB+SH96Z?}ZWx8zZh-+G7$g z=9<+-e(9UARLFb!iBv)pnMMV<(z0zt|HRfWomT?bx{$+?EJd%2y*hBdZ|u(iYjSbG>gNf6h@?pI<)WtRefVwbC&ph81%=#4aWgUw~)(0*F!7t@3ok91L0YM*<8Lf^{xqz6FG<;ty``G_0GLKLP4>i*>fwWJ7#0rX4{- z9$A#Dh&G06k&fKg%h8J;6ek5E1>T7Wv*Q4AC5`hE@dO7is4{aL+rlj&)Y zOW;kZqy4==VnJ|IR_5h#B5s*8poP0hwm(5sDiO)x!sW)Kx(-81k!9dK+Sm>NZ7NSUcQU3a@C)pv(yG;c5! z%v_E~MHNUfo(9TDoUpSN>mW|+Q)AI5GL|BUr&M+4;^&ixLPW1@bz54#-ZGF$W&cW= zzqP?`s#xfni^;-46y_@!T#ZRdW^vtOs$>9XgyFVqOdq4w3^Qj0^h{ z$niQsF7sPekXM~lo21n%-x~7zYr(%}fV2rrsO`S@i`jdxM*{`2ZFEuBn?%DNh!; z=212m+fT+>2rv=*@~deHWft@^Lrf$DE}voFEL}^#7z`>B7wl?C4GdtQ_J1?l`-Whvya?A+ zChyFy%tkTHyuB1qk8d61-|z;zyTz*xO>7YUb=4s4sI zS5tVJ@6)zuviQpslhe3m2a48Od62Uq>qCT(;agV^lB_C*w2$n_K57*$p%_RMaE!OGUzq>gcF|JRND5Gu}U*SQnyVj>OyDm zmF~}p<8q5DEpM9C8P}VsBMZW3HP^M~#1iMwz4mSWSsBu&ZcO>HLZxy&=YlLc!G%BH zNNKur2^8sYVVw`#`-K$M{hEa-=>ctV|H{J*P)np=TiWci{Et_X0rq2TXBCp6Qu6LhD&cLlV3?9lsgIa4>JiPk7q4bi;RGUk| ziP7^$CZ7`uox{rPvck8o-QWBv^0WR_S9_RNx*ySy)ye`%8!RK#dT%yM2&Z?d4_pClOTl6E$xp-k;ef8RoRI}j>oWpnrOS(Z|N68U z;cqz>qv4g2dP9|~3A#ju6*q!M65M_k)*dp8YablVR=z*2-a6c342(2sN7rPqxH%RV z8sFh7(Q!qv*)MUNC$Sf^EZ{GsAhW7eGF%YJ0S&9kU;>=Fp7RUu3~p)|nHVo*^aRa- z2#7H0O>yotq^0CLA+(t}uS$aZ38uK-)ENY|Py(CEmEmH^*x~o5%es?PecZI(dBrRV zKWq&te`{o`2cjz)0k&*eWU`k^+CLtP#XGMXs54sm8<)^{3rYkTjFKtq-)=KwI zZ(2k{Wj%6s<+UO)E@BsS1kae^ot`(1j~OQ{)P6s=mZ8P`D55WKKCl?jWAI6Aq*X<9-E^IGoqN;KV`_ttgT zHSkKRGgS5N#elPEem{$Q`x$qnN2Y|~2d~@aqBS?I`8Bm0nx=Q*+h3aPBrH21R2I_j zESru5E`&thTK>d|r3cwPOWz;y&aW+$!D`iUkIO?|dFnZz86FUr z+jQ7JBdHN)+4fR5Ejy~0E=E{xf|i?Gv`Uyc->lcLyNEMBo7?I#nE5A^$ugzD_8=)f zj?tT_#(hW2%Kv5-)YdXEl7%Sc```#5LH7~uK%W~|3o;45MEJyeakPW~QOtH7Shd2f z9g)MeRMe2Z2=q#W@L7jNC*<6DbZlbtm^a)+y7=)ngwWt`!%W|Ex~KO+0+}$Pw>5$` zppL5NN7)`DQbV1ZNs;;P50aHZCCq<(0p*~7J^&pr>$$(gp`(0dY|M(Tt7-Y-1d^`Gy^j;V_erSHY2NN zbG!fzYyMjBU(U8?^i`U01yIISKcUdxuKq1^Q8zy6aQ&s0y)RmjNtHxo>aTc}7}^Ny zeN&J9Wot5yc-`c%{eh8LKXYPY9&Wz!2*eMuQ?FA>qY$ZdL0LRJX>z@krSi@`K>fX;|NyokO(g_Ly_=OWl2en^N$$p zl|23?&o7=cV8rO^Ke|L=1__zBg~D+;c(u+GA%w42SV3i2jIJX|;SR!|x;VvAe$MDe z#2rq+i1Skr3|ICuKJ8*KldA8S>)7WlScC_p3A_0akK3oMHryu-*1}-4UI2sW(o7&^{L+n zxs{S(r%=4~Y&Wov!$}xY@i7r)^?P73+%H8zmm#;k75L!_FcXlGmGh%p}fG%tS7ZP;)j@>uqe5f`Fw%e*2?xI#&ct~R=$ zcq8PFZ{~utrd@OXEZji%21)rJP|flgOMiFombX)W6tfa_YY?9A36}dKE*x# z1esoQAVd_!l>D@EzLxSmAeVqQcr5CeL5@OHxQdqg>~TilV2P)8L3*BRPkrT45-A-U zZM$#@D&@l+QCs~Js{urTmiBmHcmy_@3y5zlMA4v~VId~D^d_fm?Z9Eq@+4bX=M+zG zhX{sU+0M-*rYaz(?0co1^!=@1PdcAhmF98_B$?HCR>l_aa-llksDCoA=uH8w)8V|h zsYPFqf%0%Le>2G9%3f)5vYwg%8#ABxH7&5AJvQ-YMMe#v z=I*qknm8jb+bOxRe5STy)EGv8dqP%`^J=m11K8(hZfCV$d#O13{1fYEKb4$kXSu2g zYSnJ9U>4paEf8cB)W_-FgP4mI7pNmXpst>Md@fu`eDj1MQ}(NDF(YUHOa2eftqSuv z*^WB+7#|8FAY;B?XBYPq;jvOUpPU--6v?Z_`T{|JR^ML^yHCAtPjQWhA`nj{{$g-% zkCFE3yntVZI*^^Ji4y5?pXwgeHT5hT1 z+tFwebnbc|rP4`FqwHCKTRdvTtN7|!!!SRP#q;eX-uN+Hh$K9}_!Tplr%rA*2%kk{ zRea!_E~2x9c`Mt^%Av22;&mYSgtMmkd&kA;IoJCKjrMK)9^{6OAlqdL^QPvvLgKx? zr7Q#|$y;(VF-*>-v#2*EyPPDHyjGRO#ORo*uFgQBir~0Y7AsAjKG5APuqvJH-jQO- zdTGMv7dkJz(KjY;lV~gI1g=oj|4wE8CsyQ6O=((=Isc60!y4XcHS~2MO1LNG(P+=? z&oR=br#pwzBXcWOpDgPx?%GNh4K&@L{re1|HF&2?lMAB+nhq?bh$pdkb?eMwFX zzwye0-j#S|R0S@pAAb-&=0YaCyv~pPV-(Oq=lcQKt!VkUdqE$h)3c@%-`{IG$skDa zTfa~Vttfo0)t(et_)~{P9`YSFn4;vW$>&y8hKr6S0kR>Bg=pibDZ^v$Q#HC z_<_Gt@#Xc;eWg~*CWk8#Md%M)lYFUCeB7OKG0Q=^Lo1<#{3M;7GL`u8Ip^4Sr+w9w zl>f`07yr$lPva#JSXc}E&7c4O+!-ms0IlbGtX3e&sDu5Bk6C3dh3qA(HHWxp&Dw5t z5aZy&+RR?Yi+mfNrq_(J>5Cs}&E-o}#viijkKbqv^@!fj1V2|Nd@q%CD^qMT`}BE` zc2-uO>&3^&@ITD_$$WB4E{tC1=aP&R*9!L}8{reAd9tcQkzNeC??RJl>ZdEnumT4kBp{v`vS{}lQ z_oJP9sTP`#=L;`aPvjLPw=Ny%J}TRgJl~tjL|A@NYJk1psSMhZF(JC^@{i5f5-A+y z>4t2itbg}Sg5JKux{)rJn%YnSZ`1nU(r%{Y=GtLR*x}3l>+wUkfROsfxvl$uby1Y> zwrfbXt{6?#rnL$w8HI@wmbUM$Tvzd5za9`e~$3@_@)@ zj%H}Rf}-q?Hx{jpb~%Q^B%=u||HmXo{tfVk{$GGM5^ z^S{6AqYyzf9-bLpb_GEg1$>rYoLHTp9$#Fv(wPW=m%;xYPh`^0Z=f>~(7I`x-e?BM z@X7Brv5jyv!NU`bEB{|;_HShO?`mPl>6IYz0-;0s@p8$A$qx%lZb2(4fzo(FF1^mP zJuLW&apk&@y@fGEA|mBAubc(Tzz#3KDImq>iAt zymy02B1gmrb6x}0v~KC13221bYotpMfm~w}V<|&^;{ovS z%IM$zp_(0l8jFJ_^o{;RwS}mC{_nq-BnZN2t8K!f?TP3IJ25on7fSd_=MUT3ONb*n-rNNz}oYmBL&OvbrHzLPDadK^y2M?-^X zlg(hf&LKYlhX5eo(fJM(V_*z;RWEU3#k{)SnPtl+{~q6GrcHF(Jc0v^v^50?$a4sd zi-_&1F^!RN38e4s2SR>Jt?)#(`+*Tyo;h$C=)_zZ9qpyzK=JhliNN@}>ym%r_!ef^ zxXOb0p2$c}1MhmvQNX!fnCd|5M<N_1*%5pOQ9u{wqHeK6Q=ki6KJT$ z;%T4wSd+lYK)WpPpo|^scZaGcq{MkP_BKa1>So++}h9Ipr!b#(IQB-Gz&a0m8+`2?G%r1U`v8 zx^nKNK4Sb%2Q){14bbUecHKA*FC14EX-%ei>kI!VH3m*!IqNzQ94A~Kk;n!TQp$=! z7EaB$x#Hv8?^YZFCVexkQlSFm(4)bqaKQ_41Ib!_TlEO*Fea>J{I{KFf}nts`MnW;>x2yt??E9@y(^btsoP(ezKqm(y|FW zbzrgv6=#ZM)gh-a==WI&Cu(De#CDK5}B{?-e{d4A4I zZckxVG4OleTy3l|6T{k@%4xv!_by(b^lzY-lX|uig@_Xp01}d+c7e&_|BlhzfLvT! z2Z~oQtOz;bc+_uWBn9`%GnV&mRQbJ)^h6_3;f46Fk62h+1Aj~*S7^SUxBK4eXRroD z^YKk6v6ya(na0hygND4LuiI>iv@Fr%(V``{+v$KJK4^#4_=m96m6(}-6lsSo8CK&F zqg(z(SQz6dPb8h~t?`6XJfKNp0xa7Z=Ma|x4+M@zd@OAeU}6op4|xZaQbm%D(guOz zb`dX%pJ4sRe~j}wm#X6Ff258|V54(>fpBGsTQQIprch-Z->d3c@2Suo2Bq|L@nT=~ zNGs8s3`1Y=eb=SsiHvr!VIr%JQ;;P&s`>#XNujzTj^ObeVfYN_j2h=#Rl;kDWs_|{ z_$h;K0DUfG$I0MQt)RAnK-Z!y#6imI2E-nQ~ZI@F4;Lbk=CUVAQ z#1MVZP2B6Sum$k;O?$`+#o@6JL?RrSlw5Mx zGLC-&l%P*aB5ON0<%+vSQ0SPd8+g6w75};~lD;-6jenbH;?5n5ggI0%d6uLjiu!n- zu^TnmLU}vLEh8p$iMxen^_|0f$lg>s`mwBR%o}oV1P)EXZx;!;QxY0w zr&*QL7#XMt@Nc+A#8db|&RlKsG+JU}*{o$t`t>bpC!M=i zd|QOU1<+Ao2NRSf$(QY6K_Uxy0@66`!A4IMO;tgM84Ph=mdvNjhfa2qoKnhxC=-|c ziEt;pBA!vm6NYUWU-WwxmrgyBF8%3gaKHM7fnIeEw>W|ue)}fU^YEmH?XNcw55GwV!9Yuut$(MJFc~_am=G0lTWFUulX?eNZnGItd zD);2IKvv6vV-B!13ywYYqjL$Fv9EAk(6SFYP`jdhwD*0$s#&%uM8znIcSO-S-}f@J z92INZGi;l9$}QF0i1eHKPUhqZ?SfZ>PtDn3RYY5GP{x+ikm%X*Xnmkjcu$w>pI2i% zP#eMV+oNqWeWi=E?~?7fMHhO;qbP5pkPVoC`rhPO(UV#W0_jbLW5O&n;;eZEcx&3k zoa1O*l|>?KND?TrD0Q~JWIak zo2NzzYz|niFZXn`$ri*JYgR-)rwU~Gkn0P-d_7Vb6uo7fYQjY>@dID)Fb`i9Y{n?5 zmn$w6cgrQt2AOW8&Q?YexU{#e@Zld5RQ;2$d2eeC=_nWyacJkI<(fsW zX&uGiW4p07N8UT_5I<9To#C9ikM>MlVx}V$egtix#%(9=E*m}KN_=JFpP2DOp9n-l z<;JwTw!CqlSgliKsM@P1xENiaTnc#YN%e|->$52iY#&u|S@|(t8=347VfD$^il=uQ>(tB68I=d9{! z`dSpUsPJUj5P%uaf|1;K`Er6i-$#Ay+Ni`cHJ43jknKcOUq}j*zl(3a$oFg+o;KCW z|507}AXJ}b%zq@drS3zcJ=wj&K1HGaI3YxZ-4B#_62*kd-1Z9oDci@Fm)&h7PqBj+g7P~L^5N|27Y)` zXK;^&_K&?)v`2unqD(;71nDy&&ik-uZ1)Z>Y_xUp6@y8NeqwqI1gB3RD{4L-DE?oVn43Irmrcv z{94(}qyO?8mX>)DF%>(!ph6>cE#7jZb zDa}KPon|!ek~JWke-mo1GAO+%eo22pExvR+M5Wqw+9PIw{)yf<8lPA^%$6W3L6`f@ zyHUH0Tt9ggC|^8n;@#L$%J`OmFXndMHH{T(<}4>EpQWugX(Q(TYT2hZ{f@K`X88~H3=g^^)^K*GdL0gWeENyjrLZBQrU?cJc11(QCxfvGF`Wc5Yt_cGS;ugfK!jP!F&A;!xTL81%G zNzd4_5|+weV1WPFBGJYo&rdf9)lb0=z15T7Wn>ey!0`dSH-~Gst~r~%U)x|)Atz$l zS~9AVVH0?`E4|C?-P|2}*F zZ?c)iixwU=WI1;06K(t~YH$DC*dyn_G?Im%&VFMpV^iGi%e%SV>YbY8SwPq8hRP0w ziC-`vvc%A01{JN@NNmv#YuNU9_wVa=CX?D_gt&(@=dTF{%pKUu^*;t30twA-v%g~$ z4bY&vG{@RnC~KL4-o&K#ChV1|nb)hVl@M!-K)$TC2GtC{i}S2CbH`KWP4dQ9=L0jK z9J1A#{hv=Czc`Y;G%1#W*^Rw?M{3O=DErH_Ge%8-+w_kHkrZBh4fa_{N-XHV&!&PO z2yFg$yx%-{c-#Lw9uMAc9@^v=n*m!jTu&jgdbKP@Buv%gW|Y3+W?+FhZf!sb6Tl2l zy$0P7mneqEe{~p*7fpjlz|sODBO@gp*EM;MzeMilQ{xO-{roy~<}vW`y(bIYU<*-F zE+eGGho11wH=@gZG};%%8y}jUtObq$SEqHI(Sx~^Ruf)XlsH}^wa6zfZ0kq3jzKkb z6QV9hEfxTtK{u}8_{jcvQ?ZJ~G-`+REE*hl)i~k92Ms4(!TScUxegGtDf0-N{*_Nj zn+r$_Yidx`@nhhYb!bMqPZ}-1$~KRS&qDt^$6N>hB2GgS*!|HmDL$+exS}~95BjT& zN3BWnR}dgE5c*?h&BQ(Id#AceaRY5roRXbRQvZUk)}7<2lXd;C^ka55dV|R&wb=jwc)jWQEM)aeI&;*K zGd8UEfz-ulq#Mmau@GNaavr08Xk2tjEgAMZT$<#qai{Bw%48&xl^~dmFGv8`$F*E* zwn$*^)?wub*n}hzqH#M}EdxjDtsi)QQyOA~lvKg3YJ zM~5A|HQW|=kWgl`R)@q8cEt*@Ho?KCok1q5kX z1Y~7r%j)vTe%xm&0OmXAmTPw! zC+MOJD9o=Zp@62X7HV7hXfmsSgTwR!Ic5EKE7+WJ?ULiU*fF0Xjf2~C^w)RrY~qL8!Je5 zxex+p8WwjdX+yoSKLWW1BC2P9Bs?*X^($mK!m4|o$_ctX4oKqaGo)eE0K^|B>DcZP ziGY!Q8qalXpQ34o7yDz0KJc7&Khx40Y3>bI_kMi1@W3~2PEC1u^lu#a@bk8T2z+!( zQ2{){d^y3&bLh3o2ggT4dw(8>Y#lnxtm9CBK{|9uS_URQ(BdZ~Q_kL}uGQ6Z*2aK( z=^)u$*>gT?{^oAWjF(sWAL>~@AW^k^LX@Zi0TWSnmiI{Ml#mH#S7>pq%j6|u1sRe< z$D*yw%f#|H-E3Dq80U1Y%2R? zIli35pmQ_U<_f08rLdW^d~I*T-2)R%Tx*S{~t#xf-Baz9JLAOC5ki7z8hGAORZv%+_m zSC3X_bv;bn50SAo@@pN>={pZ7_Hh-Q6<3hkQx89T*fA)hr+wErkpjB7E^!gA<1YwVOwU0@-Q}ce85ddOz zM}9zc2tW;quYTzz^59lY{E(&4uM7(`%YDu$a9Fz|E6%Y`R#2jepj;r8j>q}oqqtmc zVf1+|=;8-}+*maE*9!R?1{2YyqXpM+vl$rtAh3gFBLqVz&3YtnD`v|?_Ky`wrS>BP zfPiiGpB-1*u8Z~aNeh9--gCQ@l3Uhz=roODa#!=Il>X{;Ghq2joC2LoE~=I6V-m)Q zcREqLNSBmJ`!I3nQq;|4LZTgiW3dX);XUo%D0g6C8vt>uKtI-eLT1k)&JCYv@!`zX zs!BlW>X5KpU;(gEXjl&cHcE`!%aNY)9%P(0b)^g3he5Ol#8=>%68r7Fp);|$mM}#{ zye%_uV0_kD)l#n1pFQ7TUCT-(D=p7LVbUmV{Ji+UwGXGFw+T^Vt6)r>xirL{@7lNP zZCppqYL+n68nyjVwW%Pbg@&rARwo_f*|NwX7`DS9mlAeQEFse*Wklapr~scC2~$v| zE2}GEoK-$F6h|CkaY7==ye2`30t>g(}io zPEFog(&dFiyjT>AkC78(8vU9K$94(6!~um}GZEP05<$x*jd}36kAwq5d7!NgU1Cf_ zb1{loFRE{(*1o7N&TwI(DsBnmD3-L3DT2@YnIvx)?Xg&>X0Kq5f5iPOb%1_OXs}<> zm<0!)Z+C`2t2fQF)7%ebbfZj?lCqG8%xzd?bXpc99yc5b4UpZtW)NR~P9|A@Z+*NP zztF81SN8H)nJzL9BC4*qf zm{v+aS@Os>GQ-17y5VtCh@WVUI4!@$d8qOr#bE|uUddK>BtzTP?xVA!&3WB_IEh!c zm~$)cj_N6oSnYAsJK=Tkx;!KJgyUX`=ibeLA)B3gcA8f0`Qvou4n;y-Au0r%(pgy z&_WG@g!Emc8l&^4N9>V(zl~l5N~N?Fh|6(-P$a=LrhY=&gkYH{7KJLMM};Dl`#f~% zI?2glG(-Y({Aj39!&_$zFi|i7#-(+6?`K9ZO7n5p#|u$BqD>^0bn8zUhlx*|*p};m zwLfJkrWa+KV42K2$z!sy*JHRPoHX_Xi*#?FUjUxJAXf2xV1^+sAD0D*cT#L97uJOb z53&TZAXH?T>-bt(g+#N;C5YNR`Rj#MWgeAKPuBB!XdmAX+ulh_OR0>JVnxkARt)GU zGBXN7o~9fK2J=M{r980s(cgdN;?o>t*kBEFreV^f%gt<%uWe(hU45SiEq~y+l3a9n z8L~^YIxXK^n|bVH6ey1+6S<506;N(vO&Xnh(N6(FnV<0%{v2_}8Ib%#L;9X-a<7Vf zg%+7m;(3b>aPi(^Fw@&8O2or>IqU^7wgIKZ> zOHB_CzX-Q|ug(4Mu{)}QTPX4iaa6+Q$LyM-3e}+mjR9V0ckqKOx*`s%E!G(A2*{3w z{>+?L!8+udv8)>A!318La=$e4q0)HLI>qeSSKq_elp(Ig==pNRp_`gq-e6Hshsw_< zo4n2HAV*ckaspS0uS66Yxm>`j{$uvwu?Aol0;++5?mH@E#yYGj9HEa4yl!k>dcsyu z3C?+}V#;>-rp2nIfUsJ77Ie@sE#F=D3s%G4jkpE zjK0uwiY0PH3T*QsU_RfPQqB&u>=lf>`L-l0lK_EKNe?SaV;8g`P`6ymq8+fy^8jpG z1}SueLjh#vH#LBAi8`!Do&9ld5hxd@qOOdzk-VJtEldk>vX6y(MF3*QUK-re@fbUX zwT!5e{dBcP+Y3s?eh}i(Vg!&W?IujbX(@)F;=8B443AyxDDdlij%7k4lx;C&B`$$6 z_;it8#m&8DkPE%5Dq>kw@u+hHl^&aIE+}eTH>~TmPU!OwP%hao;?1Q}02wKvz0-bS$i z6Wqs+FJIQRU3hqWkmYoq6+|qA4UKZa88oTc1wQ6#D`_EeQR#KV=iw+>d|e%9IsZ}r zb&>GD0!ld>C)#*0e_|VpDo!�~t5P!Inm>e{jRk=gD#DCAyPl`>OW(-twFF63Qd8 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