[0.16]: Merge Preview Handlers in Master (#1516)

* Added project template for common library

* Added reference to stylecop.json

* Fixed xml documetation file path for common project

* Added reference to stylecop.json

* Added COM interface interpolations to C#

* Changed namespace to Common

* Added xml doc to com interfaces

* Removed AnyCPU configuration from solution file

* Added Preview Hander and form User Control Implementation

* Fix stylecop warnings

* Added test control and handler

* Added Xaml description for preview handler

* Added Xml documenatation

* Updated the control to form

* Added registration and unregistration logic for the handler

* Moved the files in separate folder and fix PR comments

* updated the name of previewhandler class to base class

* Added the DoPreview to PreviewHandlerControl Interface

* Modified the Dopreview and Unload as virtual method

* Uncommented the DocumentText to help bug repro

* HTML Parsing Extension for preview pane markdown renderer (#1108)

* Added Extension for html post processing

* Added unit test poroject for preview pane

* Added pipline test and base test function

* Added Tests for extension

* Added tests for url slashes

* Added tests for url and figure caption

* Markdown preview pane (#1128)

* Added Extension for html post processing

* Added unit test poroject for preview pane

* Added pipline test and base test function

* Added Tests for extension

* Added handler and control for markdown

* Tests added

* Locally working version for markdown

* Working image relative url's in markdown

* Added CSS to preview display

* Updates CSS for code block

* Removed html file write comment in markdown control

* Updated assembly version and web browser control test

* Add Svg preview handler (#1129)

* Added a new project for Svg preview handler

* Added initial implementation of Svg Preview Handler

* Fixed output path

* Added Unit Test Project

* Added StreamWrapper and Update Svg Control

* Updated Svg Handler Guid

* Removed migration backup folder

* Removed Fluent Assertions NuGet

* Added Comments for StreamWrapper

* Removed the manual GC collect

* Added unit tests for Svg preview Handler

* Updated the xml doc for stream wrapper

* User/lamotile/add_powerpreviewsettings (#1075)

* Added powersettings to PowerToys Settings UI

* added settings library

* updated settings-web

* updated project oncfiguration

* updated project onfiguration

* updated project .sln file

* removed .etl file and added it to git-ignore

* separated the PowerPreviewModule into split classes .cpp and .h

* moved PowerPreviewModule implemnetations to .cpp file

* fixed StringTable formatter

* fixed spacing in resource.h

* added m_ to member varibales

* initiliaze m_isPreviewEnabled in the base class

* removed duplication of objects by using pass by refference and std::move

* made the getters const

* updated naming convention

* Split test calsses

* Add const string

* Replaced move with const string

* Made attributes private

* Made attributes private

* removed unused constructor

* Update resource.h

formatted resource.h

* Adding unit tests for preview handler common (#1156)

* Changed the name of the Common library to PreviewHandlerCommon

* Added unit tests project for PreviewHandlerCommon

* Updated ComInterop accessor type

* Added unit tests for PreviewHandlerbase

* Added tests for file and stream based handler

* Added unit tests for StreamWrapper

* Added form handler unit tests

* Added Unit tests for FormHandlerControl

* Added file header

* Add Powerpreview project

* Add spacing in sln file

* swapped string refferences (#1199)

* added registry methods and enable/disable preview handlers (#1230)

* added registry methods and enable/disable preview handlers

* formatted .rc file.

* formatted resource file

* formatted .rc file.

* formatted settings.cpp

* formatted settings.h

* formatted SVGPreviewSettingsClassTest.cpp

* Formatted MarkDownPreviewSettingsClassTest.cpp

* using wide strings

* formatted settings.h

* FileExplorerPreviewSettingsTest.cpp formatting

* fixed typo and formatting

* closing Registry and fixing typos

* formmarted code using ctrl+k+d

* fixed naming

* fixed typo

* changed if/else reverse order

* Markdown preview pane  (#1220)

* Added rich text bar for information display

* Added infobar

* Added tests for extension and markdown control

* Added xml docstring for markdown preview handler control

* Updated assembly file for markdown preview pane

* Updated removal of script tag without modifying CSS

* Added info bar text string to resource file.

* Removed error with infobar display on first rendering

* Updated assembly version

* Remove script and image element from Svg (#1231)

* Added implementation to remove script and image tag

* Added Unit tests for SvgPreviewHandlerHelper

* Updated Unit tests for SvgPreviewControl

* Moved the hardcoded string to resource file

* Changed the LocalMachine to CurrentUser for preview handler registration

* Added unit tests for multiple blocked elements tags

* User/lamotile/update settings objects (#1263)

* added registry methods and enable/disable preview handlers

* formatted .rc file.

* formatted resource file

* formatted .rc file.

* formatted settings.cpp

* formatted settings.h

* formatted SVGPreviewSettingsClassTest.cpp

* Formatted MarkDownPreviewSettingsClassTest.cpp

* using wide strings

* formatted settings.h

* FileExplorerPreviewSettingsTest.cpp formatting

* fixed typo and formatting

* closing Registry and fixing typos

* formmarted code using ctrl+k+d

* fixed naming

* fixed typo

* changed if/else reverse order

* updated setiings_objects.cpp

* removed changes on files that are not part of this PR

* removed const ref on primative types

* updated pass by ref semantic and removed pas by reff on primative types

* fixed spaces in the commas

* fixed spaces in brackets

* Preview pane telemetry (#1299)

* Added telemetry base class and markdown telemetry class

* Updated docstring for telemetry event.

* Added telemetry to markdown for error

* Added try catch for markdown preview handler and display error bar

* Updated markdown telemetry to make event names global variable

* Updated parameter name to camel casing and telemetry event name naming.

* Corrected assembbly version for svg renderer

* Markdown Image files display (#1303)

* Added telemetry base class and markdown telemetry class

* Updated docstring for telemetry event.

* Added telemetry to markdown for error

* Added try catch for markdown preview handler and display error bar

* Updated markdown telemetry to make event names global variable

* Updated Markdown preview to display without vertical scrollbar and removed xml doc to html agility pack.

* Updated parameter name to camel casing and telemetry event name naming.

* Corrected assembbly version for svg renderer

* Removed duplicate function

* Add telemetry for Svg preview handler (#1314)

* Added telemetry events for Svg Preview Handler

* Added unit test in case preview handler throws

* Updated the Error event name

* Remove the not required return statement

* User/lamotile/add read me (#1332)

* add readme

* moved images

* re-added images'

* Fixed gramma

* Update figure number refference

* improve preview handler intergration (#1319)

* improve preview handler intergration

* Fixed typo

* updated typo

* updated enable() function

* updated is enabled()

* re-updated is enabled()

* added this-> key word

* (0.16) - Install preview handler with msix (#1339)

* Removed the registration logic from preview handlers

* Updated the output path

* Added logic to shim the activation of .net assembly

* Updated manifest file

* Fix the allowedsilenttakeover filed in manifest

* Updated the appxmanifest file

* Added AllowSilentDefaultTakeOver in manifest

* Fix returned error code by DllGetClassObject

* Moved the CLSID to a common header file

* Added info about where CLSID needs to be updated

* Added a .reg file for the Keys added in registry.dat

* Added comments for DllGetClassObject

* Svg Preview Handler block external component  (#1368)

* Removed the registration logic from preview handlers

* Updated the output path

* Added logic to shim the activation of .net assembly

* Updated manifest file

* Fix the allowedsilenttakeover filed in manifest

* Updated the appxmanifest file

* Added AllowSilentDefaultTakeOver in manifest

* Fix returned error code by DllGetClassObject

* Moved the CLSID to a common header file

* Added info about where CLSID needs to be updated

* Added a .reg file for the Keys added in registry.dat

* Added comments for DllGetClassObject

* Extended WebBrowserSite for setting flags in DISPID_AMBIENT_DLCONTROL

* Added XML Documenatation

* Removed the logic for deleting image and script element from Svg

* Updated Unit Tests

* Updated typecast of uint

* Forwarded calls to Type.InvokeMember

* Resolve PR Comments

* Adding MSI Installation for Preview Handler (#1436)

* Updated wxs for including dll and registry keys for preview handlers

* Changed the casing for registry key

* Resolve PR Comments

* Added comments for File element

* Call GC on preview unloading (#1456)

* Call GC collect on preview unloading

* Added github issue link

* Update Web browser control for Markdown Previewer (#1464)

* Updated Webbrowser control

* Updated Unit tests

* Disabled Navigation for Svg Previewer

* Fix power preview unit tests (#1508)

* Decoupled registry interaction logic

* Updated File explorer settings

* Updated unit tests for PowerPreview Settings

* Added Asserrtion for Scope of registry key

* Updated the registry value to match with installation registry value

* Sync master settings.cpp

* Merge settings changes from PreviewHandlers

* Remove newline changes added into in example_powertoy\trace.cpp

* Chaned .net framework to 4.7.2

* Updated Csproj files to auto generate Assembly.info files

* Updated msi installer to use version variable for preview handlers assembly

* Removed the signing of Assembly and updated wxs to not include PublicKeyToken

* Updated the Path in Packaginglayout.xml to modules from Gac and the registry hive binary

* Regenerated updated JS and html file

* Resolve PR Comments

* Readded the wprp file

Co-authored-by: Divyansh <divyan@microsoft.com>
Co-authored-by: Divyansh <somm14divi@gmail.com>
Co-authored-by: Lavius Motileng <58791731+laviusmotileng-ms@users.noreply.github.com>
This commit is contained in:
udit3333
2020-03-11 15:53:49 -07:00
committed by GitHub
parent f170cef506
commit 83ce8a2197
107 changed files with 8787 additions and 1850 deletions

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="..\..\..\..\installer\Version.props" />
<!-- We don't have GenerateAssemblyInfo task until we use .net core, so we generate it with WriteLinesToFile -->
<PropertyGroup>
<AssemblyTitle>PreviewHandlerCommon</AssemblyTitle>
<AssemblyCompany>Microsoft Corp.</AssemblyCompany>
<AssemblyCopyright>Copyright (C) 2019 Microsoft Corp.</AssemblyCopyright>
</PropertyGroup>
<ItemGroup>
<AssemblyVersionFiles Include="Generated Files\AssemblyInfo.cs" />
</ItemGroup>
<Target Name="GenerateAssemblyInfo" BeforeTargets="PrepareForBuild">
<ItemGroup>
<HeaderLines Include="// Copyright (c) Microsoft Corporation" />
<HeaderLines Include="// The Microsoft Corporation licenses this file to you under the MIT license." />
<HeaderLines Include="// See the LICENSE file in the project root for more information." />
<HeaderLines Include="#pragma warning disable SA1516" />
<HeaderLines Include="using System.Reflection%3b" />
<HeaderLines Include="using System.Resources%3b" />
<HeaderLines Include="using System.Runtime.CompilerServices%3b" />
<HeaderLines Include="using System.Runtime.InteropServices%3b" />
<HeaderLines Include="[assembly: AssemblyTitle(&quot;$(AssemblyTitle)&quot;)]" />
<HeaderLines Include="[assembly: AssemblyDescription(&quot;&quot;)]" />
<HeaderLines Include="[assembly: AssemblyConfiguration(&quot;&quot;)]" />
<HeaderLines Include="[assembly: AssemblyCompany(&quot;$(AssemblyCompany)&quot;)]" />
<HeaderLines Include="[assembly: AssemblyCopyright(&quot;$(AssemblyCopyright)&quot;)]" />
<HeaderLines Include="[assembly: AssemblyProduct(&quot;$(AssemblyTitle)&quot;)]" />
<HeaderLines Include="[assembly: AssemblyTrademark(&quot;&quot;)]" />
<HeaderLines Include="[assembly: AssemblyCulture(&quot;&quot;)]" />
<HeaderLines Include="[assembly: ComVisible(false)]" />
<HeaderLines Include="[assembly: NeutralResourcesLanguage(&quot;en-US&quot;)]" />
<HeaderLines Include="[assembly: AssemblyVersion(&quot;$(Version).0&quot;)]" />
<HeaderLines Include="[assembly: AssemblyFileVersion(&quot;$(Version).0&quot;)]" />
</ItemGroup>
<WriteLinesToFile File="Generated Files\AssemblyInfo.cs" Lines="@(HeaderLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
</Target>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AF2349B8-E5B6-4004-9502-687C1C7730B1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PreviewHandlerCommon</RootNamespace>
<AssemblyName>PreviewHandlerCommon</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DocumentationFile>$(SolutionDir)$(Platform)\$(Configuration)\modules\PreviewHandlerCommonDocumentation.xml</DocumentationFile>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DocumentationFile>$(SolutionDir)$(Platform)\$(Configuration)\modules\PreviewHandlerCommonDocumentation.xml</DocumentationFile>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="cominterop\IInitializeWithFile.cs" />
<Compile Include="cominterop\COLORREF.cs" />
<Compile Include="cominterop\IInitializeWithStream.cs" />
<Compile Include="cominterop\IObjectWithSite.cs" />
<Compile Include="cominterop\IOleWindow.cs" />
<Compile Include="cominterop\IPreviewHandler.cs" />
<Compile Include="cominterop\IPreviewHandlerFrame.cs" />
<Compile Include="cominterop\IPreviewHandlerVisuals.cs" />
<Compile Include="cominterop\LOGFONT.cs" />
<Compile Include="cominterop\MSG.cs" />
<Compile Include="cominterop\RECT.cs" />
<Compile Include="controls\WebBrowserDownloadControlFlags.cs" />
<Compile Include="controls\WebBrowserExt.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="examplehandler\CustomControlTest.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="handlers\FileBasedPreviewHandler.cs" />
<Compile Include="controls\FormHandlerControl.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Generated Files\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="controls\IPreviewHandlerControl.cs" />
<Compile Include="handlers\PreviewHandlerBase.cs" />
<Compile Include="handlers\StreamBasedPreviewHandler.cs" />
<Compile Include="examplehandler\TestCustomHandler.cs" />
<Compile Include="Telemetry\TelemetryBase.cs" />
<Compile Include="Utilities\StreamWrapper.cs" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\..\codeAnalysis\StyleCop.json">
<Link>StyleCop.json</Link>
</AdditionalFiles>
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers">
<Version>1.1.118</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Eventing.Reader;
using System.Diagnostics.Tracing;
namespace PreviewHandlerCommon.Telemetry
{
/// <summary>
/// Base class for telemetry events.
/// </summary>
public class TelemetryBase : EventSource
{
/// <summary>
/// The event tag for this event source.
/// </summary>
public const EventTags ProjectTelemetryTagProductAndServicePerformance = (EventTags)0x0u;
/// <summary>
/// The event keyword for this event source.
/// </summary>
public const EventKeywords ProjectKeywordMeasure = (EventKeywords)0x0;
/// <summary>
/// Group ID for Powertoys project.
/// </summary>
private static readonly string[] PowerToysTelemetryTraits = { "ETW_GROUP", "{42749043-438c-46a2-82be-c6cbeb192ff2}" };
/// <summary>
/// Initializes a new instance of the <see cref="TelemetryBase"/> class.
/// </summary>
/// <param name="eventSourceName">.</param>
public TelemetryBase(
string eventSourceName)
: base(
eventSourceName,
EventSourceSettings.EtwSelfDescribingEventFormat,
PowerToysTelemetryTraits)
{
return;
}
}
}

View File

@@ -0,0 +1,242 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace Common.Utilities
{
/// <summary>
/// Wraps <see cref="IStream"/> interface into <see cref="Stream"/> Class.
/// </summary>
/// <remarks>
/// Implements only read from the stream functionality.
/// </remarks>
public class StreamWrapper : Stream
{
private IStream stream;
/// <summary>
/// Initializes a new instance of the <see cref="StreamWrapper"/> class.
/// </summary>
/// <param name="stream">A pointer to an <see cref="IStream" /> interface that represents the stream source.</param>
public StreamWrapper(IStream stream)
{
this.stream = stream ?? throw new ArgumentNullException(nameof(stream));
}
/// <summary>
/// Gets a value indicating whether the current stream supports reading.
/// </summary>
public override bool CanRead
{
get
{
return true;
}
}
/// <summary>
/// Gets a value indicating whether the current stream supports seeking.
/// </summary>
public override bool CanSeek
{
get
{
return true;
}
}
/// <summary>
/// Gets a value indicating whether the current stream supports writing.
/// </summary>
public override bool CanWrite
{
get
{
return false;
}
}
/// <summary>
/// Gets the length in bytes of the stream.
/// </summary>
public override long Length
{
get
{
this.CheckDisposed();
System.Runtime.InteropServices.ComTypes.STATSTG stat;
// Stat called with STATFLAG_NONAME. The pwcsName is not required more details https://docs.microsoft.com/en-us/windows/win32/api/wtypes/ne-wtypes-statflag
this.stream.Stat(out stat, 1); // STATFLAG_NONAME
return stat.cbSize;
}
}
/// <summary>
/// Gets or Sets the position within the current.
/// </summary>
public override long Position
{
get
{
return this.Seek(0, SeekOrigin.Current);
}
set
{
this.Seek(value, SeekOrigin.Begin);
}
}
/// <summary>
/// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero if the end of the stream has been reached.</returns>
public override int Read(byte[] buffer, int offset, int count)
{
this.CheckDisposed();
if (offset < 0 || count < 0 || offset + count > buffer.Length)
{
throw new ArgumentOutOfRangeException();
}
byte[] localBuffer = buffer;
if (offset > 0)
{
localBuffer = new byte[count];
}
IntPtr bytesReadPtr = Marshal.AllocCoTaskMem(sizeof(int));
try
{
this.stream.Read(localBuffer, count, bytesReadPtr);
int bytesRead = Marshal.ReadInt32(bytesReadPtr);
if (offset > 0)
{
Array.Copy(localBuffer, 0, buffer, offset, bytesRead);
}
return bytesRead;
}
finally
{
Marshal.FreeCoTaskMem(bytesReadPtr);
}
}
/// <summary>
/// Sets the position within the current stream.
/// </summary>
/// <param name="offset">A byte offset relative to the origin parameter.</param>
/// <param name="origin">A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position.</param>
/// <returns>The new position within the current stream.</returns>
public override long Seek(long offset, SeekOrigin origin)
{
this.CheckDisposed();
int dwOrigin;
// Maps the SeekOrigin with dworigin more details: https://docs.microsoft.com/en-us/windows/win32/api/objidl/ne-objidl-stream_seek
switch (origin)
{
case SeekOrigin.Begin:
dwOrigin = 0; // STREAM_SEEK_SET
break;
case SeekOrigin.Current:
dwOrigin = 1; // STREAM_SEEK_CUR
break;
case SeekOrigin.End:
dwOrigin = 2; // STREAM_SEEK_END
break;
default:
throw new ArgumentOutOfRangeException();
}
IntPtr posPtr = Marshal.AllocCoTaskMem(sizeof(long));
try
{
this.stream.Seek(offset, dwOrigin, posPtr);
return Marshal.ReadInt64(posPtr);
}
finally
{
Marshal.FreeCoTaskMem(posPtr);
}
}
/// <summary>
/// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
/// </summary>
/// <remarks>
/// Not implemented current implementation supports only read.
/// </remarks>
public override void Flush()
{
throw new NotImplementedException();
}
/// <summary>
/// Sets the length of the current stream.
/// </summary>
/// <param name="value">The desired length of the current stream in bytes.</param>
/// /// <remarks>
/// Not implemented current implementation supports only read.
/// </remarks>
public override void SetLength(long value)
{
throw new NotImplementedException();
}
/// <summary>
/// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
/// </summary>
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
/// <param name="count">The number of bytes to be written to the current stream.</param>
/// <remarks>
/// Not implemented current implementation supports only read.
/// </remarks>
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (this.stream != null)
{
if (Marshal.IsComObject(this.stream))
{
Marshal.ReleaseComObject(this.stream);
}
this.stream = null;
}
}
private void CheckDisposed()
{
if (this.stream == null)
{
throw new ObjectDisposedException(nameof(StreamWrapper));
}
}
}
}

View File

@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Drawing;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// The COLORREF value is used to specify an RGB color.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct COLORREF
{
/// <summary>
/// Stores an RGB color value in a 32 bit integer.
/// </summary>
public uint Dword;
/// <summary>
/// Gets RGB value stored in <see cref="Dword"/> in <see cref="Color"/> structure.
/// </summary>
public Color Color
{
get
{
return Color.FromArgb(
(int)(0x000000FFU & this.Dword),
(int)(0x0000FF00U & this.Dword) >> 8,
(int)(0x00FF0000U & this.Dword) >> 16);
}
}
}
}

View File

@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.Cominterop
{
/// <summary>
/// Exposes a method to initialize a handler, such as a property handler, thumbnail handler, or preview handler, with a file path.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b7d14566-0509-4cce-a71f-0a554233bd9b")]
public interface IInitializeWithFile
{
/// <summary>
/// Initializes a handler with a file path.
/// </summary>
/// <param name="pszFilePath">File Path.</param>
/// <param name="grfMode">Indicate the Access Mode either STGM_READ (Read Only Access) or STGM_READWRITE (Read and Write Access).</param>
void Initialize([MarshalAs(UnmanagedType.LPWStr)] string pszFilePath, uint grfMode);
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace Common.ComInterlop
{
/// <summary>
/// Exposes a method that initializes a handler, such as a property handler, thumbnail handler, or preview handler, with a stream.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
public interface IInitializeWithStream
{
/// <summary>
/// Initializes a handler with a stream.
/// </summary>
/// <param name="pstream">A pointer to an <see cref="IStream" /> interface that represents the stream source.</param>
/// <param name="grfMode">One of the <see href="https://docs.microsoft.com/en-us/windows/win32/stg/stgm-constants" >STGM</see> values that indicates the access mode for <paramref name="pstream"/>.</param>
void Initialize(IStream pstream, uint grfMode);
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// Provides a simplified way to support communication between an object and its site in the container.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("fc4801a3-2ba9-11cf-a229-00aa003d7352")]
public interface IObjectWithSite
{
/// <summary>
/// Provides the site's pointer to the site object.
/// </summary>
/// <param name="pUnkSite">Address of an interface pointer to the site managing this object.</param>
void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);
/// <summary>
/// Retrieves the last site set using the <see cref="SetSite(object)" /> method. In cases where there is no known site, the object returns an exception.
/// </summary>
/// <param name="riid">Provides the IID of the interface pointer returned in the <paramref name="ppvSite"/> parameter.</param>
/// <param name="ppvSite">The address of the caller's void variable in which the object stores the interface pointer of the site last seen in the <see cref="SetSite(object)" />.</param>
void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvSite);
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// The IOleWindow interface provides methods that allow an application to obtain the handle to the various windows that participate
/// in in-place activation, and also to enter and exit context-sensitive help mode.
/// </summary>
[ComImport]
[Guid("00000114-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleWindow
{
/// <summary>
/// Retrieves a handle to one of the windows participating in in-place activation (frame, document, parent, or in-place object window).
/// </summary>
/// <param name="phwnd">A pointer to a variable that receives the window handle.</param>
void GetWindow(out IntPtr phwnd);
/// <summary>
/// Determines whether context-sensitive help mode should be entered during an in-place activation session.
/// </summary>
/// <param name="fEnterMode">TRUE if help mode should be entered; FALSE if it should be exited.</param>
void ContextSensitiveHelp([MarshalAs(UnmanagedType.Bool)] bool fEnterMode);
}
}

View File

@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// Exposes methods for the display of rich previews.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8895b1c6-b41f-4c1c-a562-0d564250836f")]
public interface IPreviewHandler
{
/// <summary>
/// Sets the parent window of the previewer window, as well as the area within the parent to be used for the previewer window.
/// </summary>
/// <param name="hwnd">A handle to the parent window.</param>
/// <param name="rect">A pointer to a <see cref="RECT"/> defining the area for the previewer.</param>
void SetWindow(IntPtr hwnd, ref RECT rect);
/// <summary>
/// Directs the preview handler to change the area within the parent hwnd that it draws into.
/// </summary>
/// <param name="rect">A pointer to a <see cref="RECT"/> to be used for the preview.</param>
void SetRect(ref RECT rect);
/// <summary>
/// Directs the preview handler to load data from the source specified in an earlier Initialize method call, and to begin rendering to the previewer window.
/// </summary>
void DoPreview();
/// <summary>
/// Directs the preview handler to cease rendering a preview and to release all resources that have been allocated based on the item passed in during the initialization.
/// </summary>
void Unload();
/// <summary>
/// Directs the preview handler to set focus to itself.
/// </summary>
void SetFocus();
/// <summary>
/// Directs the preview handler to return the HWND from calling the GetFocus Function.
/// </summary>
/// <param name="phwnd">When this method returns, contains a pointer to the HWND returned from calling the GetFocus Function from the preview handler's foreground thread.</param>
void QueryFocus(out IntPtr phwnd);
/// <summary>
/// Directs the preview handler to handle a keystroke passed up from the message pump of the process in which the preview handler is running.
/// </summary>
/// <param name="pmsg">A pointer to a window message.</param>
/// <returns>If the keystroke message can be processed by the preview handler, the handler will process it and return S_OK(0). If the preview handler cannot process the keystroke message, it
/// will offer it to the host using <see cref="IPreviewHandlerFrame.TranslateAccelerator(ref MSG)"/>. If the host processes the message, this method will return S_OK(0). If the host does not process the message, this method will return S_FALSE(1).
/// </returns>
[PreserveSig]
uint TranslateAccelerator(ref MSG pmsg);
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// Enables preview handlers to pass keyboard shortcuts to the host. This interface retrieves a list of keyboard shortcuts and directs the host to handle a keyboard shortcut.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("fec87aaf-35f9-447a-adb7-20234491401a")]
public interface IPreviewHandlerFrame
{
/// <summary>
/// Gets a list of the keyboard shortcuts for the preview host.
/// </summary>
/// <param name="pinfo">A pointer to a <see href="https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/ns-shobjidl_core-previewhandlerframeinfo">PREVIEWHANDLERFRAMEINFO</see> structure
/// that receives accelerator table information.</param>
void GetWindowContext(IntPtr pinfo);
/// <summary>
/// Directs the host to handle an keyboard shortcut passed from the preview handler.
/// </summary>
/// <param name="pmsg">A reference to <see cref="MSG"/> that corresponds to a keyboard shortcut.</param>
/// <returns>If the keyboard shortcut is one that the host intends to handle, the host will process it and return S_OK(0); otherwise, it returns S_FALSE(1).</returns>
[PreserveSig]
uint TranslateAccelerator(ref MSG pmsg);
}
}

View File

@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// Exposes methods for applying color and font information to preview handlers.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8327b13c-b63f-4b24-9b8a-d010dcc3f599")]
public interface IPreviewHandlerVisuals
{
/// <summary>
/// Sets the background color of the preview handler.
/// </summary>
/// <param name="color">A value of type <see cref="COLORREF"/> to use for the preview handler background.</param>
void SetBackgroundColor(COLORREF color);
/// <summary>
/// Sets the font attributes to be used for text within the preview handler.
/// </summary>
/// <param name="plf">A pointer to a <see cref="LOGFONT"/> Structure containing the necessary attributes for the font to use.</param>
void SetFont(ref LOGFONT plf);
/// <summary>
/// Sets the color of the text within the preview handler.
/// </summary>
/// <param name="color">A value of type <see cref="COLORREF"/> to use for the preview handler text color.</param>
void SetTextColor(COLORREF color);
}
}

View File

@@ -0,0 +1,88 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// Defines the attributes of a font.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LOGFONT
{
/// <summary>
/// Value of type INT that specifies the height, in logical units, of the font's character cell or character.
/// </summary>
public int LfHeight;
/// <summary>
/// Value of type INT that specifies the width, in logical units, of characters in the font.
/// </summary>
public int LfWidth;
/// <summary>
/// Value of type INT that contains the angle, in tenths of degrees, between the escapement vector and the x-axis of the device. The escapement
/// vector is parallel to the base line of a row of text.
/// </summary>
public int LfEscapement;
/// <summary>
/// Value of type INT that specifies the angle, in tenths of degrees, between each character's base line and the x-axis of the device.
/// </summary>
public int LfOrientation;
/// <summary>
/// Value of type INT that specifies the weight of the font in the range from 0 through 1000.
/// </summary>
public int LfWeight;
/// <summary>
/// Value of type BYTE that specifies an italic font if set to TRUE.
/// </summary>
public byte LfItalic;
/// <summary>
/// Value of type BYTE that specifies an underlined font if set to TRUE.
/// </summary>
public byte LfUnderline;
/// <summary>
/// Value of type BYTE that specifies a strikeout font if set to TRUE.
/// </summary>
public byte LfStrikeOut;
/// <summary>
/// Value of type BYTE that specifies the character set.
/// </summary>
public byte LfCharSet;
/// <summary>
/// Value of type BYTE that specifies the output precision. The output precision defines how closely the output must match the requested
/// font's height, width, character orientation, escapement, pitch, and font type.
/// </summary>
public byte LfOutPrecision;
/// <summary>
/// Value of type BYTE that specifies the clipping precision. The clipping precision defines how to clip characters that are partially outside the clipping region.
/// </summary>
public byte LfClipPrecision;
/// <summary>
/// Value of type BYTE that specifies the output quality. The output quality defines how carefully the GDI must attempt to match the logical-font attributes to those of an actual physical font.
/// </summary>
public byte LfQuality;
/// <summary>
/// Value of type BYTE that specifies the pitch and family of the font.
/// </summary>
public byte LfPitchAndFamily;
/// <summary>
/// Array of wide characters that contains a null-terminated string that specifies the typeface name of the font. The length of the string must not exceed 32 characters, including the NULL terminator.
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string LfFaceName;
}
}

View File

@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// Contains message information from a thread's message queue.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
/// <summary>
/// A handle to the window whose window procedure receives the message. This member is NULL when the message is a thread message.
/// </summary>
public IntPtr Hwnd;
/// <summary>
/// The message identifier. Applications can only use the low word; the high word is reserved by the system.
/// </summary>
public int Message;
/// <summary>
/// Additional information about the message. The exact meaning depends on the value of the message member.
/// </summary>
public IntPtr WParam;
/// <summary>
/// Additional information about the message. The exact meaning depends on the value of the message member.
/// </summary>
public IntPtr LParam;
/// <summary>
/// The time at which the message was posted.
/// </summary>
public int Time;
/// <summary>
/// The x coordinate of cursor position, in screen coordinates, when the message was posted.
/// </summary>
public int PtX;
/// <summary>
/// The y coordinate of cursor position, in screen coordinates, when the message was posted.
/// </summary>
public int PtY;
}
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Drawing;
using System.Runtime.InteropServices;
namespace Common.ComInterlop
{
/// <summary>
/// The RECT structure defines a rectangle by the coordinates of its upper-left and lower-right corners.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
/// <summary>
/// Specifies the x-coordinate of the upper-left corner of the rectangle.
/// </summary>
public int Left;
/// <summary>
/// Specifies the y-coordinate of the upper-left corner of the rectangle.
/// </summary>
public int Top;
/// <summary>
/// Specifies the x-coordinate of the lower-right corner of the rectangle.
/// </summary>
public int Right;
/// <summary>
/// Specifies the y-coordinate of the lower-right corner of the rectangle.
/// </summary>
public int Bottom;
/// <summary>
/// Creates a <see cref="Rectangle" /> structure with the edge locations specified in the struct.
/// </summary>
/// <returns>Return a <see cref="Rectangle"/>.</returns>
public Rectangle ToRectangle()
{
return Rectangle.FromLTRB(this.Left, this.Top, this.Right, this.Bottom);
}
}
}

View File

@@ -0,0 +1,166 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Common
{
/// <summary>
/// Form based implementation of <see cref="IPreviewHandlerControl"/>.
/// </summary>
public abstract class FormHandlerControl : Form, IPreviewHandlerControl
{
/// <summary>
/// Holds the parent window handle.
/// </summary>
private IntPtr parentHwnd;
/// <summary>
/// Initializes a new instance of the <see cref="FormHandlerControl"/> class.
/// </summary>
public FormHandlerControl()
{
// Gets the handle of the control to create the control on the VI thread. Invoking the Control.Handle get accessor forces the creation of the underlying window for the control.
// This is important, because the thread that instantiates the preview handler component and calls its constructor is a single-threaded apartment (STA) thread, but the thread that calls into the interface members later on is a multithreaded apartment (MTA) thread. Windows Forms controls are meant to run on STA threads.
// More details: https://docs.microsoft.com/en-us/archive/msdn-magazine/2007/january/windows-vista-and-office-writing-your-own-preview-handlers.
var forceCreation = this.Handle;
this.FormBorderStyle = FormBorderStyle.None;
this.Visible = false;
}
/// <inheritdoc />
public IntPtr GetHandle()
{
return this.Handle;
}
/// <inheritdoc />
public void QueryFocus(out IntPtr result)
{
var getResult = IntPtr.Zero;
this.InvokeOnControlThread(() =>
{
getResult = GetFocus();
});
result = getResult;
}
/// <inheritdoc />
public void SetBackgroundColor(Color argbColor)
{
this.InvokeOnControlThread(() =>
{
this.BackColor = argbColor;
});
}
/// <inheritdoc />
public void SetFocus()
{
this.InvokeOnControlThread(() =>
{
this.Focus();
});
}
/// <inheritdoc />
public void SetFont(Font font)
{
this.InvokeOnControlThread(() =>
{
this.Font = font;
});
}
/// <inheritdoc />
public void SetRect(Rectangle windowBounds)
{
this.UpdateWindowBounds(windowBounds);
}
/// <inheritdoc />
public void SetTextColor(Color color)
{
this.InvokeOnControlThread(() =>
{
this.ForeColor = color;
});
}
/// <inheritdoc />
public void SetWindow(IntPtr hwnd, Rectangle rect)
{
this.parentHwnd = hwnd;
this.UpdateWindowBounds(rect);
}
/// <inheritdoc />
public virtual void Unload()
{
this.InvokeOnControlThread(() =>
{
this.Visible = false;
foreach (Control c in this.Controls)
{
c.Dispose();
}
this.Controls.Clear();
});
// Call garbage collection at the time of unloading of Preview. This is to mitigate issue with WebBrowser Control not able to dispose properly.
// Which is preventing prevhost.exe to exit at the time of closing File explorer.
// Preview Handlers run in a separate process from PowerToys. This will not affect the performance of other modules.
// Mitigate the following Github issue: https://github.com/microsoft/PowerToys/issues/1468
GC.Collect();
}
/// <inheritdoc />
public virtual void DoPreview<T>(T dataSource)
{
this.Visible = true;
}
/// <summary>
/// Executes the specified delegate on the thread that owns the control's underlying window handle.
/// </summary>
/// <param name="func">Delegate to run.</param>
public void InvokeOnControlThread(MethodInvoker func)
{
this.Invoke(func);
}
/// <summary>
/// Changes the parent window of the specified child window.
/// </summary>
/// <param name="hWndChild">A handle to the child window.</param>
/// <param name="hWndNewParent">A handle to the new parent window.</param>
/// <returns>If the function succeeds, the return value is a handle to the previous parent window and NULL in case of failure.</returns>
[DllImport("user32.dll")]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
/// <summary>
/// Retrieves the handle to the window that has the keyboard focus, if the window is attached to the calling thread's message queue.
/// </summary>
/// <returns>The return value is the handle to the window with the keyboard focus. If the calling thread's message queue does not have an associated window with the keyboard focus, the return value is NULL.</returns>
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr GetFocus();
/// <summary>
/// Update the Form Control window with the passed rectangle.
/// </summary>
/// <param name="windowBounds">An instance of rectangle.</param>
private void UpdateWindowBounds(Rectangle windowBounds)
{
this.InvokeOnControlThread(() =>
{
SetParent(this.Handle, this.parentHwnd);
this.Bounds = windowBounds;
});
}
}
}

View File

@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing;
namespace Common
{
/// <summary>
/// Interface defining methods requirement by the <see cref="PreviewHandlerBase"/> control.
/// </summary>
public interface IPreviewHandlerControl
{
/// <summary>
/// Directs the preview handler to return the HWND from calling the GetFocus function.
/// Source: https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ipreviewhandler-queryfocus.
/// </summary>
/// <param name="result">Returns the handle of the window with focus.</param>
void QueryFocus(out IntPtr result);
/// <summary>
/// Sets focus to the control.
/// </summary>
void SetFocus();
/// <summary>
/// Sets the font according to the font set in Windows Settings.
/// More details: https://docs.microsoft.com/en-us/windows/win32/shell/building-preview-handlers#ipreviewhandlervisualssetfont.
/// </summary>
/// <param name="font">Instance of Font.</param>
void SetFont(Font font);
/// <summary>
/// Sets the Text color according to the Windows Settings.
/// </summary>
/// <param name="color">Instance of color.</param>
void SetTextColor(Color color);
/// <summary>
/// Sets the Background color. For instance to fill the window when the handler renders to area smaller provided by SetWindow and SetRect.
/// </summary>
/// <param name="argbColor">Instance of color.</param>
void SetBackgroundColor(Color argbColor);
/// <summary>
/// Gets the HWND of the control window.
/// </summary>
/// <returns>Pointer to the window handle.</returns>
IntPtr GetHandle();
/// <summary>
/// Hide the preview and free any resource used for the preview.
/// </summary>
void Unload();
/// <summary>
/// Directs the control to change the area within the parent hwnd that it draws into.
/// </summary>
/// <param name="windowBounds">Instance of Rectangle defining the area.</param>
void SetRect(Rectangle windowBounds);
/// <summary>
/// Sets the parent window of the previewer window, as well as the area within the parent to be used for the previewer window..
/// </summary>
/// <param name="hwnd">Pointer to the parent window handle.</param>
/// <param name="rect">Instance of Rectangle defining the area.</param>
void SetWindow(IntPtr hwnd, Rectangle rect);
/// <summary>
/// Called by Preview Handler to start the preview.
/// </summary>
/// <typeparam name="T">File Path or Stream reference for the file.</typeparam>
/// <param name="dataSource">Represents the source of preview data.</param>
void DoPreview<T>(T dataSource);
}
}

View File

@@ -0,0 +1,108 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
/// <summary>
/// Flags to control download and execution in Web Browser Control.
/// Values of flags are defined in mshtmdid.h in distributed Windows Sdk.
/// </summary>
[Flags]
public enum WebBrowserDownloadControlFlags : int
{
/// <summary>
/// Images will be downloaded from the server if this flag is set.
/// </summary>
DLIMAGES = 0x00000010,
/// <summary>
/// Videos will be downloaded from the server if this flag is set.
/// </summary>
VIDEOS = 0x00000020,
/// <summary>
/// Background sounds will be downloaded from the server if this flag is set.
/// </summary>
BGSOUNDS = 0x00000040,
/// <summary>
/// Scripts will not be executed.
/// </summary>
NO_SCRIPTS = 0x00000080,
/// <summary>
/// Java applets will not be executed.
/// </summary>
NO_JAVA = 0x00000100,
/// <summary>
/// ActiveX controls will not be executed.
/// </summary>
NO_RUNACTIVEXCTLS = 0x00000200,
/// <summary>
/// ActiveX controls will not be downloaded.
/// </summary>
NO_DLACTIVEXCTLS = 0x00000400,
/// <summary>
/// The page will only be downloaded, not displayed.
/// </summary>
DOWNLOADONLY = 0x00000800,
/// <summary>
/// WebBrowser Control will download and parse a frameSet, but not the individual frame objects within the frameSet.
/// </summary>
NO_FRAMEDOWNLOAD = 0x00001000,
/// <summary>
/// The server will be asked for update status. Cached files will be used if the server indicates that the cached information is up-to-date.
/// </summary>
RESYNCHRONIZE = 0x00002000,
/// <summary>
/// Files will be re-downloaded from the server regardless of the update status of the files.
/// </summary>
PRAGMA_NO_CACHE = 0x00004000,
/// <summary>
/// Behaviors are not downloaded and are disabled in the document.
/// </summary>
NO_BEHAVIORS = 0x00008000,
/// <summary>
/// Character sets specified in meta elements are suppressed.
/// </summary>
NO_METACHARSET = 0x00010000,
/// <summary>
/// The browsing component will disable UTF-8 encoding.
/// </summary>
URL_ENCODING_DISABLE_UTF8 = 0x00020000,
/// <summary>
/// The browsing component will enable UTF-8 encoding.
/// </summary>
URL_ENCODING_ENABLE_UTF8 = 0x00040000,
/// <summary>
/// No Documentation Available.
/// </summary>
NOFRAMES = 0x00080000,
/// <summary>
/// WebBrowser Control always operates in offline mode.
/// </summary>
FORCEOFFLINE = 0x10000000,
/// <summary>
/// No client pull operations will be performed.
/// </summary>
NO_CLIENTPULL = 0x20000000,
/// <summary>
/// No user interface will be displayed during downloads.
/// </summary>
SILENT = 0x40000000,
}

View File

@@ -0,0 +1,138 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Reflection;
using System.Windows.Forms;
namespace PreviewHandlerCommon
{
/// <summary>
/// Customized the WebBrowser to get control over what it downloads, displays and executes.
/// </summary>
public class WebBrowserExt : WebBrowser
{
/// <inheritdoc/>
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
// Returns instance of WebBrowserSiteExt.
return new WebBrowserSiteExt(this);
}
/// <summary>
/// Extend the WebBrowserSite with IDispatch implementation to handle the DISPID_AMBIENT_DLCONTROL.
/// More details: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa770041(v=vs.85)?redirectedfrom=MSDN#controlling-download-and-execution.
/// </summary>
protected class WebBrowserSiteExt : WebBrowserSite, IReflect
{
// Dispid of DISPID_AMBIENT_DLCONTROL is defined in MsHtmdid.h header file in distributed Windows Sdk component.
private const string DISPIDAMBIENTDLCONTROL = "[DISPID=-5512]";
private WebBrowserExt browserExtControl;
/// <summary>
/// Initializes a new instance of the <see cref="WebBrowserSiteExt"/> class.
/// </summary>
/// <param name="browserControl">Browser Control Instance pass to the site.</param>
public WebBrowserSiteExt(WebBrowserExt browserControl)
: base(browserControl)
{
this.browserExtControl = browserControl;
}
/// <inheritdoc/>
public Type UnderlyingSystemType
{
get { return this.GetType(); }
}
/// <inheritdoc/>
public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
object result;
if (name.Equals(DISPIDAMBIENTDLCONTROL))
{
result = Convert.ToInt32(
WebBrowserDownloadControlFlags.PRAGMA_NO_CACHE |
WebBrowserDownloadControlFlags.FORCEOFFLINE |
WebBrowserDownloadControlFlags.NO_CLIENTPULL |
WebBrowserDownloadControlFlags.NO_SCRIPTS |
WebBrowserDownloadControlFlags.NO_JAVA |
WebBrowserDownloadControlFlags.NO_FRAMEDOWNLOAD |
WebBrowserDownloadControlFlags.NOFRAMES |
WebBrowserDownloadControlFlags.NO_DLACTIVEXCTLS |
WebBrowserDownloadControlFlags.NO_RUNACTIVEXCTLS |
WebBrowserDownloadControlFlags.NO_BEHAVIORS |
WebBrowserDownloadControlFlags.SILENT);
}
else
{
result = this.GetType().InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
return result;
}
/// <inheritdoc/>
public FieldInfo[] GetFields(BindingFlags bindingAttr)
{
return this.GetType().GetFields(bindingAttr);
}
/// <inheritdoc/>
public MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
return this.GetType().GetMethods(bindingAttr);
}
/// <inheritdoc/>
public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
return this.GetType().GetProperties(bindingAttr);
}
/// <inheritdoc/>
public FieldInfo GetField(string name, BindingFlags bindingAttr)
{
return this.GetType().GetField(name, bindingAttr);
}
/// <inheritdoc/>
public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
{
return this.GetType().GetMember(name, bindingAttr);
}
/// <inheritdoc/>
public MemberInfo[] GetMembers(BindingFlags bindingAttr)
{
return this.GetType().GetMembers(bindingAttr);
}
/// <inheritdoc/>
public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
{
return this.GetType().GetMethod(name, bindingAttr);
}
/// <inheritdoc/>
public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
{
return this.GetType().GetMethod(name, bindingAttr, binder, types, modifiers);
}
/// <inheritdoc/>
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
return this.GetType().GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
/// <inheritdoc/>
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
{
return this.GetType().GetProperty(name, bindingAttr);
}
}
}
}

View File

@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO;
using System.Windows.Forms;
namespace Common
{
/// <summary>
/// This is test custom control to test the implementation.
/// </summary>
public class CustomControlTest : FormHandlerControl
{
/// <summary>
/// Start the preview on the Control.
/// </summary>
/// <param name="dataSource">Path to the file.</param>
public override void DoPreview<T>(T dataSource)
{
this.InvokeOnControlThread(() =>
{
var filePath = dataSource as string;
WebBrowser browser = new WebBrowser();
browser.DocumentText = "Test";
browser.Navigate(filePath);
browser.Dock = DockStyle.Fill;
browser.IsWebBrowserContextMenuEnabled = false;
this.Controls.Add(browser);
base.DoPreview(dataSource);
});
}
}
}

View File

@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
namespace Common
{
/// <summary>
/// This is a example custom handler to show how to extend the library.
/// </summary>
[Guid("22a1a8e8-e929-4732-90ce-91eaff38b614")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class TestCustomHandler : FileBasedPreviewHandler
{
private CustomControlTest previewHandlerControl;
/// <inheritdoc />
public override void DoPreview()
{
this.previewHandlerControl.DoPreview(this.FilePath);
}
/// <inheritdoc />
protected override IPreviewHandlerControl CreatePreviewHandlerControl()
{
this.previewHandlerControl = new CustomControlTest();
return this.previewHandlerControl;
}
}
}

View File

@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using Common.Cominterop;
namespace Common
{
/// <summary>
/// Extends the <see cref="PreviewHandlerBase" /> by implementing IInitializeWithFile.
/// </summary>
public abstract class FileBasedPreviewHandler : PreviewHandlerBase, IInitializeWithFile
{
/// <summary>
/// Gets the file path.
/// </summary>
public string FilePath { get; private set; }
/// <inheritdoc />
public void Initialize([MarshalAs(UnmanagedType.LPWStr)] string pszFilePath, uint grfMode)
{
// Ignore the grfMode always use read mode to access the file.
this.FilePath = pszFilePath;
}
}
}

View File

@@ -0,0 +1,158 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using Common.ComInterlop;
using Microsoft.Win32;
namespace Common
{
/// <summary>
/// Preview Handler base class implmenenting interfaces required by Preview Handler.
/// </summary>
public abstract class PreviewHandlerBase : IPreviewHandler, IOleWindow, IObjectWithSite, IPreviewHandlerVisuals
{
/// <summary>
/// An instance of Preview Control Used by the Handler.
/// </summary>
private IPreviewHandlerControl previewControl;
/// <summary>
/// Hold reference for the window handle.
/// </summary>
private IntPtr parentHwnd;
/// <summary>
/// Hold the bounds of the window.
/// </summary>
private Rectangle windowBounds;
/// <summary>
/// Holds the site pointer.
/// </summary>
private object unkSite;
/// <summary>
/// Holds reference for the IPreviewHandlerFrame.
/// </summary>
private IPreviewHandlerFrame frame;
/// <summary>
/// Initializes a new instance of the <see cref="PreviewHandlerBase"/> class.
/// </summary>
public PreviewHandlerBase()
{
this.previewControl = this.CreatePreviewHandlerControl();
}
/// <inheritdoc />
public abstract void DoPreview();
/// <inheritdoc />
public void SetWindow(IntPtr hwnd, ref RECT rect)
{
this.parentHwnd = hwnd;
this.windowBounds = rect.ToRectangle();
this.previewControl.SetWindow(hwnd, this.windowBounds);
}
/// <inheritdoc />
public void SetRect(ref RECT rect)
{
this.windowBounds = rect.ToRectangle();
this.previewControl.SetRect(this.windowBounds);
}
/// <inheritdoc />
public void Unload()
{
this.previewControl.Unload();
}
/// <inheritdoc />
public void SetFocus()
{
this.previewControl.SetFocus();
}
/// <inheritdoc />
public void QueryFocus(out IntPtr phwnd)
{
this.previewControl.QueryFocus(out IntPtr result);
phwnd = result;
if (phwnd == IntPtr.Zero)
{
throw new Win32Exception();
}
}
/// <inheritdoc />
public uint TranslateAccelerator(ref MSG pmsg)
{
// Current implementation simply directs all Keystrokes to IPreviewHandlerFrame. This is the recommended approach to handle keystokes for all low-integrity preview handlers.
// Source: https://docs.microsoft.com/en-us/windows/win32/shell/building-preview-handlers#ipreviewhandlertranslateaccelerator
if (this.frame != null)
{
return this.frame.TranslateAccelerator(ref pmsg);
}
const uint S_FALSE = 1;
return S_FALSE;
}
/// <inheritdoc />
public void GetWindow(out IntPtr phwnd)
{
phwnd = this.previewControl.GetHandle();
}
/// <inheritdoc />
public void ContextSensitiveHelp(bool fEnterMode)
{
// Should always return NotImplementedException. Source: https://docs.microsoft.com/en-us/windows/win32/shell/building-preview-handlers#iolewindowcontextsensitivehelp
throw new NotImplementedException();
}
/// <inheritdoc />
public void SetSite(object pUnkSite)
{
// Implementation logic details: https://docs.microsoft.com/en-us/windows/win32/shell/building-preview-handlers#iobjectwithsitesetsite
this.unkSite = pUnkSite;
this.frame = this.unkSite as IPreviewHandlerFrame;
}
/// <inheritdoc />
public void GetSite(ref Guid riid, out object ppvSite)
{
ppvSite = this.unkSite;
}
/// <inheritdoc />
public void SetBackgroundColor(COLORREF color)
{
this.previewControl.SetBackgroundColor(color.Color);
}
/// <inheritdoc />
public void SetFont(ref LOGFONT plf)
{
this.previewControl.SetFont(Font.FromLogFont(plf));
}
/// <inheritdoc />
public void SetTextColor(COLORREF color)
{
this.previewControl.SetTextColor(color.Color);
}
/// <summary>
/// Provide instance of the implementation of <see cref="IPreviewHandlerControl"/>. Should be overide by the implementation class with control object to be used.
/// </summary>
/// <returns>Instance of the <see cref="IPreviewHandlerControl"/>.</returns>
protected abstract IPreviewHandlerControl CreatePreviewHandlerControl();
}
}

View File

@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices.ComTypes;
using Common.ComInterlop;
namespace Common
{
/// <summary>
/// Extends the <see cref="PreviewHandlerBase" /> by implementing IInitializeWithStream.
/// </summary>
public abstract class StreamBasedPreviewHandler : PreviewHandlerBase, IInitializeWithStream
{
/// <summary>
/// Gets the stream object to access file.
/// </summary>
public IStream Stream { get; private set; }
/// <inheritdoc/>
public void Initialize(IStream pstream, uint grfMode)
{
// Ignore the grfMode always use read mode to access the file.
this.Stream = pstream;
}
}
}