Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / Imaging / BitmapFrameDecode.cs / 1305600 / BitmapFrameDecode.cs
//------------------------------------------------------------------------------
// Microsoft Avalon
// Copyright (c) Microsoft Corporation
//
// File: BitmapFrameDecode.cs
//
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using MS.Internal;
using MS.Internal.PresentationCore;
using System.Diagnostics;
using System.Windows.Media;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging;
using MS.Win32.PresentationCore;
#pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages
namespace System.Windows.Media.Imaging
{
#region BitmapFrameDecode
///
/// BitmapFrameDecode abstract class
///
internal sealed class BitmapFrameDecode : BitmapFrame
{
#region Constructors
///
/// Internal constructor -- Creates new frame using specified decoder
///
internal BitmapFrameDecode(
int frameNumber,
BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption,
BitmapDecoder decoder
) : base(true)
{
_bitmapInit.BeginInit();
_frameNumber = frameNumber;
_isThumbnailCached = false;
_isMetadataCached = false;
_frameSource = null;
Debug.Assert(decoder != null);
_decoder = decoder;
_syncObject = decoder.SyncObject;
_createOptions = createOptions;
_cacheOption = cacheOption;
_bitmapInit.EndInit();
if ((createOptions & BitmapCreateOptions.DelayCreation) != 0)
{
DelayCreation = true;
}
else
{
FinalizeCreation();
}
}
///
/// Internal constructor -- Creates frame from another frame
///
///
/// SecurityCritical: Accesses unmanaged resources (_wicSource)
/// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical
///
[SecurityCritical, SecurityTreatAsSafe]
internal BitmapFrameDecode(
int frameNumber,
BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption,
BitmapFrameDecode frameDecode
) : base(true)
{
_bitmapInit.BeginInit();
_frameNumber = frameNumber;
WicSourceHandle = frameDecode.WicSourceHandle;
IsSourceCached = frameDecode.IsSourceCached;
CreationCompleted = frameDecode.CreationCompleted;
_frameSource = frameDecode._frameSource;
_decoder = frameDecode.Decoder;
_syncObject = _decoder.SyncObject;
_createOptions = createOptions;
_cacheOption = cacheOption;
_thumbnail = frameDecode._thumbnail;
_isThumbnailCached = frameDecode._isThumbnailCached;
_metadata = frameDecode._metadata;
_isMetadataCached = frameDecode._isMetadataCached;
_readOnlycolorContexts = frameDecode._readOnlycolorContexts;
_isColorContextCached = frameDecode._isColorContextCached;
_bitmapInit.EndInit();
if ((createOptions & BitmapCreateOptions.DelayCreation) != 0)
{
DelayCreation = true;
}
else if (!CreationCompleted)
{
FinalizeCreation();
}
else
{
UpdateCachedSettings();
}
}
///
/// Internal constructor -- Creates frame thats being downloaded
///
///
/// SecurityCritical: Accesses unmanaged resources (_wicSource)
/// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical
///
[SecurityCritical, SecurityTreatAsSafe]
internal BitmapFrameDecode(
int frameNumber,
BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption,
LateBoundBitmapDecoder decoder
) : base(true)
{
_bitmapInit.BeginInit();
_frameNumber = frameNumber;
byte[] pixels = new byte[4];
BitmapSource source = BitmapSource.Create(
1,
1,
96,
96,
PixelFormats.Pbgra32,
null,
pixels,
4
);
WicSourceHandle = source.WicSourceHandle;
Debug.Assert(decoder != null);
_decoder = decoder;
_createOptions = createOptions;
_cacheOption = cacheOption;
//
// Hook the decoders download events
//
_decoder.DownloadCompleted += OnDownloadCompleted;
_decoder.DownloadProgress += OnDownloadProgress;
_decoder.DownloadFailed += OnDownloadFailed;
_bitmapInit.EndInit();
}
///
/// Do not allow construction
///
private BitmapFrameDecode() : base(true)
{
}
#endregion
#region IUriContext
///
/// Provides the base uri of the current context.
///
public override Uri BaseUri
{
get
{
ReadPreamble();
return _decoder._baseUri;
}
set
{
WritePreamble();
// Nothing to do here.
}
}
#endregion
#region Public Properties
///
/// Accesses the Thumbnail property for this BitmapFrameDecode
///
public override BitmapSource Thumbnail
{
get
{
ReadPreamble();
EnsureThumbnail();
return _thumbnail;
}
}
///
/// Accesses the Metadata property for this BitmapFrameDecode
///
public override ImageMetadata Metadata
{
get
{
ReadPreamble();
return InternalMetadata;
}
}
///
/// Accesses the Decoder property for this BitmapFrameDecode
///
public override BitmapDecoder Decoder
{
get
{
ReadPreamble();
return _decoder;
}
}
///
/// Used as a delegate in ColorContexts to get the unmanaged IWICColorContexts
///
///
/// Critical - Calls critical, unmanaged method
///
[SecurityCritical]
private int GetColorContexts(ref uint numContexts, IntPtr[] colorContextPtrs)
{
Invariant.Assert(colorContextPtrs == null || numContexts <= colorContextPtrs.Length);
return UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(_frameSource, numContexts, colorContextPtrs, out numContexts);
}
///
/// If there is an embedded color profile, return it.
/// Otherwise, return null. This method does NOT create a
/// color profile for bitmaps that don't already have one.
///
///
/// Provides access to this encoders color profile
///
///
///
/// Critical - Access unmanaged code, codecs
/// TreatAsSafe - We are exposing specific, non-sensitive data that came from
/// a Uri or a bitmap. If the profile data came from a Uri, the
/// WebRequest we did to get it demandend the appropriate
/// permission and we did not expose the request or response. If it came
/// from a bitmap, it may be cross-domain, but the restricted
/// nature of the data combined with the fact that it has been
/// inspected by WCS which is hardened against malicious data
/// makes this OK.
///
public override ReadOnlyCollection ColorContexts
{
[SecurityCritical, SecurityTreatAsSafe]
get
{
ReadPreamble();
if (!_isColorContextCached && !IsDownloading)
{
EnsureSource();
lock (_syncObject)
{
IList colorContextList = ColorContext.GetColorContextsHelper(GetColorContexts);
if (colorContextList != null)
{
_readOnlycolorContexts = new ReadOnlyCollection(colorContextList);
}
_isColorContextCached = true;
}
}
return _readOnlycolorContexts;
}
}
///
/// Returns if the BitmapFrame is downloading content
///
public override bool IsDownloading
{
get
{
ReadPreamble();
return Decoder.IsDownloading;
}
}
#endregion
#region Public Methods
///
/// Create an in-place bitmap metadata writer.
///
public override InPlaceBitmapMetadataWriter CreateInPlaceBitmapMetadataWriter()
{
ReadPreamble();
if (_decoder != null)
{
_decoder.CheckOriginalWritable();
}
// Demand Site Of Origin on the URI before usage of metadata.
CheckIfSiteOfOrigin();
EnsureSource();
return InPlaceBitmapMetadataWriter.CreateFromFrameDecode(_frameSource, _syncObject);
}
#endregion
#region ToString
///
/// Can serialze "this" to a string
///
internal override bool CanSerializeToString()
{
ReadPreamble();
return _decoder.CanConvertToString();
}
///
/// Creates a string representation of this object based on the format string
/// and IFormatProvider passed in.
/// If the provider is null, the CurrentCulture is used.
/// See the documentation for IFormattable for more information.
///
///
/// A string representation of this object.
///
internal override string ConvertToString(string format, IFormatProvider provider)
{
ReadPreamble();
if (_decoder != null)
{
return _decoder.ToString();
}
return base.ConvertToString(format, provider);
}
#endregion
#region Freezable
///
/// Implementation of Freezable.CreateInstanceCore .
///
/// The new Freezable.
protected override Freezable CreateInstanceCore()
{
return new BitmapFrameDecode();
}
///
/// Copy the fields not covered by DPs. This is used by
/// CloneCore(), CloneCurrentValueCore(), GetAsFrozenCore() and
/// GetCurrentValueAsFrozenCore().
///
///
/// Critical - access critical resources (_metadata)
/// TreatAsSafe - All inputs verified
///
[SecurityCritical, SecurityTreatAsSafe]
private void CopyCommon(BitmapFrameDecode sourceBitmapFrameDecode)
{
_bitmapInit.BeginInit();
_frameNumber = sourceBitmapFrameDecode._frameNumber;
_isThumbnailCached = sourceBitmapFrameDecode._isThumbnailCached;
_isMetadataCached = sourceBitmapFrameDecode._isMetadataCached;
_isColorContextCached = sourceBitmapFrameDecode._isColorContextCached;
_frameSource = sourceBitmapFrameDecode._frameSource;
_thumbnail = sourceBitmapFrameDecode._thumbnail;
_metadata = sourceBitmapFrameDecode.InternalMetadata;
_readOnlycolorContexts = sourceBitmapFrameDecode._readOnlycolorContexts;
_decoder = sourceBitmapFrameDecode._decoder;
if (_decoder != null && _decoder.IsDownloading)
{
// UpdateDecoder must be called when download completes and the real decoder
// is created. Normally _decoder will call UpdateDecoder, but in this case the
// decoder will not know about the cloned BitmapFrameDecode and will only call
// UpdateDecoder on the original. The clone will need to listen to the original
// BitmapFrameDecode for DownloadCompleted, then call UpdateDecoder on itself.
// The weak event sink hooks up handlers on DownloadCompleted, DownloadFailed,
// and DownloadProgress
_weakBitmapFrameDecodeEventSink =
new WeakBitmapFrameDecodeEventSink(this, sourceBitmapFrameDecode);
}
_syncObject = _decoder.SyncObject;
_createOptions = sourceBitmapFrameDecode._createOptions;
_cacheOption = sourceBitmapFrameDecode._cacheOption;
_bitmapInit.EndInit();
}
///
/// Implementation of Freezable.CloneCore .
///
protected override void CloneCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.CloneCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
///
/// Implementation of Freezable.CloneCurrentValueCore .
///
protected override void CloneCurrentValueCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.CloneCurrentValueCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
///
/// Implementation of Freezable.GetAsFrozenCore .
///
protected override void GetAsFrozenCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.GetAsFrozenCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
///
/// Implementation of Freezable.GetCurrentValueAsFrozenCore .
///
protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.GetCurrentValueAsFrozenCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
#endregion
#region Internal Properties / Methods
///
/// Updates the internal decoder -- usually happens with a LateBoundBitmapDecoder
///
///
/// Critical - access critical resources
/// TreatAsSafe - All inputs verified
///
[SecurityCritical, SecurityTreatAsSafe]
internal void UpdateDecoder(BitmapDecoder decoder)
{
Debug.Assert(_decoder != null);
_decoder = decoder;
_syncObject = decoder.SyncObject;
WicSourceHandle = null;
_needsUpdate = true;
FinalizeCreation();
// Trigger a update of the UCE resource
RegisterForAsyncUpdateResource();
}
///
/// Create the unmanaged resources
///
///
/// Critical - access critical resources
/// TreatAsSafe - All inputs verified
///
[SecurityCritical, SecurityTreatAsSafe]
internal override void FinalizeCreation()
{
EnsureSource();
// Set the WicSourceHandle and Update the cached settings so that we
// can query the source for information such as the palette which we need
// to determine if we need to format convert or not.
WicSourceHandle = _frameSource;
UpdateCachedSettings();
lock (_syncObject)
{
WicSourceHandle = CreateCachedBitmap(this, _frameSource, _createOptions, _cacheOption, Palette);
}
IsSourceCached = (_cacheOption != BitmapCacheOption.None);
CreationCompleted = true;
UpdateCachedSettings();
EnsureThumbnail();
}
//
// Workaround for a change caused by a bug fix, CopyCommon checks this property when
// copying the delegates attached to events.
// Default implementation in BitmapSource, see comments in BitmapSource.cs for details.
//
internal override bool ShouldCloneEventDelegates
{
get { return false; }
}
#endregion
#region Private Methods
/// Fired when the decoder download has completed
private void OnDownloadCompleted(object sender, EventArgs e)
{
//
// The sender should be the LateBoundDecoder that we hooked when it was _decoder.
//
LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender;
//
// Unhook the decoders download events
//
decoder.DownloadCompleted -= OnDownloadCompleted;
decoder.DownloadProgress -= OnDownloadProgress;
decoder.DownloadFailed -= OnDownloadFailed;
FireChanged();
_downloadEvent.InvokeEvents(this, null);
}
/// Called when download progress is made
private void OnDownloadProgress(object sender, DownloadProgressEventArgs e)
{
_progressEvent.InvokeEvents(this, e);
}
/// Called when download fails
private void OnDownloadFailed(object sender, ExceptionEventArgs e)
{
//
// The sender should be the LateBoundDecoder that we hooked when it was _decoder.
//
LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender;
//
// Unhook the decoders download events
//
decoder.DownloadCompleted -= OnDownloadCompleted;
decoder.DownloadProgress -= OnDownloadProgress;
decoder.DownloadFailed -= OnDownloadFailed;
_failedEvent.InvokeEvents(this, e);
}
/// Fired when the original's decoder's download has completed
private void OnOriginalDownloadCompleted(BitmapFrameDecode original, EventArgs e)
{
CleanUpWeakEventSink();
// Update the underlying decoder to match the original's
// We already have a _decoder from the cloning, but it's referencing the
// LateBoundBitmapDecoder. When download completes, LateBoundBitmapDecoder calls
// EnsureDecoder to make the _realDecoder (something like JpegBitmapDecoder),
// then calls SetupFrames on the _realDecoder, which calls BitmapFrameDecode's
// UpdateDecoder to set _decoder to the JpegBitmapDecoder. So the original's _decoder
// changes after download completes, and the clone should change as well.
UpdateDecoder(original.Decoder);
FireChanged();
_downloadEvent.InvokeEvents(this, e);
}
/// Called when the original's decoder's download fails
private void OnOriginalDownloadFailed(ExceptionEventArgs e)
{
CleanUpWeakEventSink();
_failedEvent.InvokeEvents(this, e);
}
private void CleanUpWeakEventSink()
{
// Unhook the decoders download events
_weakBitmapFrameDecodeEventSink.DetachSourceDownloadHandlers();
_weakBitmapFrameDecodeEventSink = null;
}
///
/// Ensure that the thumbnail is created/cached
///
///
/// Critical - Access unmanaged code, codecs
/// TreatAsSafe - Getting thumbnail data is OK
///
[SecurityCritical, SecurityTreatAsSafe]
private void EnsureThumbnail()
{
if (_isThumbnailCached || IsDownloading)
{
return;
}
else
{
EnsureSource();
IntPtr /* IWICBitmapSource */ thumbnail = IntPtr.Zero;
lock (_syncObject)
{
// Check if there is embedded thumbnail or not
int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetThumbnail(
_frameSource,
out thumbnail
);
if (hr != (int)WinCodecErrors.WINCODEC_ERR_CODECNOTHUMBNAIL)
{
HRESULT.Check(hr);
}
}
_isThumbnailCached = true;
if (thumbnail != IntPtr.Zero)
{
BitmapSourceSafeMILHandle thumbHandle = new BitmapSourceSafeMILHandle(thumbnail);
SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette();
BitmapPalette palette = null;
int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
thumbHandle,
unmanagedPalette
);
if (hr == HRESULT.S_OK)
{
palette = new BitmapPalette(unmanagedPalette);
}
_thumbnail = new UnmanagedBitmapWrapper(
CreateCachedBitmap(
null,
thumbHandle,
BitmapCreateOptions.PreservePixelFormat,
_cacheOption,
palette
));
_thumbnail.Freeze();
}
}
}
///
/// Returns cached metadata and creates BitmapMetadata if it does not exist.
/// This code will demand site of origin permissions.
///
///
/// Critical - Access unmanaged code
/// TreatAsSafe - demands site of origin permissions
///
internal override BitmapMetadata InternalMetadata
{
[SecurityCritical, SecurityTreatAsSafe]
get
{
// Demand Site Of Origin on the URI before usage of metadata.
CheckIfSiteOfOrigin();
if (!_isMetadataCached && !IsDownloading)
{
EnsureSource();
IntPtr /* IWICMetadataQueryReader */ metadata = IntPtr.Zero;
lock (_syncObject)
{
// Check if there is embedded metadata or not
int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetMetadataQueryReader(
_frameSource,
out metadata
);
if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION)
{
HRESULT.Check(hr);
}
}
if (metadata != IntPtr.Zero)
{
SafeMILHandle metadataHandle = new SafeMILHandle(metadata);
_metadata = new BitmapMetadata(metadataHandle, true, _decoder != null ? _decoder.IsMetadataFixedSize : false, _syncObject);
_metadata.Freeze();
}
_isMetadataCached = true;
}
return _metadata;
}
set
{
throw new System.NotImplementedException();
}
}
///
/// Ensure that a BitmapSource is created
///
///
/// Critical - Access unmanaged code, codecs
/// TreatAsSafe - Getting frame data is OK
///
[SecurityCritical, SecurityTreatAsSafe]
private void EnsureSource()
{
if (_frameSource == null)
{
if (_decoder == null)
{
HRESULT.Check((int)WinCodecErrors.WINCODEC_ERR_NOTINITIALIZED);
}
//
// Its possible that the frame was originally created with a network URI
// and DelayCreation was enabled. In this case, the decoder may not yet
// exist even though the download is complete. The code below creates a
// decoder if one does not exist.
//
if (_decoder.InternalDecoder == null)
{
Debug.Assert(_decoder is LateBoundBitmapDecoder);
Debug.Assert(IsDownloading == false);
_decoder = ((LateBoundBitmapDecoder)_decoder).Decoder;
_syncObject = _decoder.SyncObject;
Debug.Assert(_decoder.InternalDecoder != null);
}
IntPtr frameDecode = IntPtr.Zero;
Debug.Assert(_syncObject != null);
lock (_syncObject)
{
HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetFrame(
_decoder.InternalDecoder,
(uint)_frameNumber,
out frameDecode
));
_frameSource = new BitmapSourceSafeMILHandle(frameDecode);
_frameSource.CalculateSize();
}
}
}
#endregion
#region Data Members
/// IWICBitmapFrameDecode source
private BitmapSourceSafeMILHandle _frameSource = null;
/// Frame number
private int _frameNumber;
/// Is the thumbnail cached
private bool _isThumbnailCached;
/// Is the metadata cached
private bool _isMetadataCached;
/// If the ColorContext is already cached
private bool _isColorContextCached = false;
/// CreateOptions for this Frame
private BitmapCreateOptions _createOptions;
/// CacheOption for this Frame
private BitmapCacheOption _cacheOption;
/// Decoder
private BitmapDecoder _decoder;
#endregion
#region WeakBitmapSourceEvents
// Used to propagate DownloadCompleted events for cloned BitmapFrameDecodes that are still downloading
private WeakBitmapFrameDecodeEventSink _weakBitmapFrameDecodeEventSink;
private class WeakBitmapFrameDecodeEventSink : WeakReference
{
public WeakBitmapFrameDecodeEventSink(BitmapFrameDecode cloned, BitmapFrameDecode original)
: base(cloned)
{
_original = original;
if (!_original.IsFrozen)
{
_original.DownloadCompleted += OnSourceDownloadCompleted;
_original.DownloadFailed += OnSourceDownloadFailed;
_original.DownloadProgress += OnSourceDownloadProgress;
}
}
public void OnSourceDownloadCompleted(object sender, EventArgs e)
{
BitmapFrameDecode clone = this.Target as BitmapFrameDecode;
if (null != clone)
{
clone.OnOriginalDownloadCompleted(_original, e);
}
else
{
DetachSourceDownloadHandlers();
}
}
public void OnSourceDownloadFailed(object sender, ExceptionEventArgs e)
{
BitmapFrameDecode clone = this.Target as BitmapFrameDecode;
if (null != clone)
{
clone.OnOriginalDownloadFailed(e);
}
else
{
DetachSourceDownloadHandlers();
}
}
public void OnSourceDownloadProgress(object sender, DownloadProgressEventArgs e)
{
BitmapFrameDecode clone = this.Target as BitmapFrameDecode;
if (null != clone)
{
clone.OnDownloadProgress(sender, e);
}
else
{
DetachSourceDownloadHandlers();
}
}
public void DetachSourceDownloadHandlers()
{
if (!_original.IsFrozen)
{
_original.DownloadCompleted -= OnSourceDownloadCompleted;
_original.DownloadFailed -= OnSourceDownloadFailed;
_original.DownloadProgress -= OnSourceDownloadProgress;
}
}
private BitmapFrameDecode _original;
}
#endregion WeakBitmapSourceEvents
}
#endregion // BitmapFrameDecode
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
// Microsoft Avalon
// Copyright (c) Microsoft Corporation
//
// File: BitmapFrameDecode.cs
//
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using MS.Internal;
using MS.Internal.PresentationCore;
using System.Diagnostics;
using System.Windows.Media;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging;
using MS.Win32.PresentationCore;
#pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages
namespace System.Windows.Media.Imaging
{
#region BitmapFrameDecode
///
/// BitmapFrameDecode abstract class
///
internal sealed class BitmapFrameDecode : BitmapFrame
{
#region Constructors
///
/// Internal constructor -- Creates new frame using specified decoder
///
internal BitmapFrameDecode(
int frameNumber,
BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption,
BitmapDecoder decoder
) : base(true)
{
_bitmapInit.BeginInit();
_frameNumber = frameNumber;
_isThumbnailCached = false;
_isMetadataCached = false;
_frameSource = null;
Debug.Assert(decoder != null);
_decoder = decoder;
_syncObject = decoder.SyncObject;
_createOptions = createOptions;
_cacheOption = cacheOption;
_bitmapInit.EndInit();
if ((createOptions & BitmapCreateOptions.DelayCreation) != 0)
{
DelayCreation = true;
}
else
{
FinalizeCreation();
}
}
///
/// Internal constructor -- Creates frame from another frame
///
///
/// SecurityCritical: Accesses unmanaged resources (_wicSource)
/// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical
///
[SecurityCritical, SecurityTreatAsSafe]
internal BitmapFrameDecode(
int frameNumber,
BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption,
BitmapFrameDecode frameDecode
) : base(true)
{
_bitmapInit.BeginInit();
_frameNumber = frameNumber;
WicSourceHandle = frameDecode.WicSourceHandle;
IsSourceCached = frameDecode.IsSourceCached;
CreationCompleted = frameDecode.CreationCompleted;
_frameSource = frameDecode._frameSource;
_decoder = frameDecode.Decoder;
_syncObject = _decoder.SyncObject;
_createOptions = createOptions;
_cacheOption = cacheOption;
_thumbnail = frameDecode._thumbnail;
_isThumbnailCached = frameDecode._isThumbnailCached;
_metadata = frameDecode._metadata;
_isMetadataCached = frameDecode._isMetadataCached;
_readOnlycolorContexts = frameDecode._readOnlycolorContexts;
_isColorContextCached = frameDecode._isColorContextCached;
_bitmapInit.EndInit();
if ((createOptions & BitmapCreateOptions.DelayCreation) != 0)
{
DelayCreation = true;
}
else if (!CreationCompleted)
{
FinalizeCreation();
}
else
{
UpdateCachedSettings();
}
}
///
/// Internal constructor -- Creates frame thats being downloaded
///
///
/// SecurityCritical: Accesses unmanaged resources (_wicSource)
/// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical
///
[SecurityCritical, SecurityTreatAsSafe]
internal BitmapFrameDecode(
int frameNumber,
BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption,
LateBoundBitmapDecoder decoder
) : base(true)
{
_bitmapInit.BeginInit();
_frameNumber = frameNumber;
byte[] pixels = new byte[4];
BitmapSource source = BitmapSource.Create(
1,
1,
96,
96,
PixelFormats.Pbgra32,
null,
pixels,
4
);
WicSourceHandle = source.WicSourceHandle;
Debug.Assert(decoder != null);
_decoder = decoder;
_createOptions = createOptions;
_cacheOption = cacheOption;
//
// Hook the decoders download events
//
_decoder.DownloadCompleted += OnDownloadCompleted;
_decoder.DownloadProgress += OnDownloadProgress;
_decoder.DownloadFailed += OnDownloadFailed;
_bitmapInit.EndInit();
}
///
/// Do not allow construction
///
private BitmapFrameDecode() : base(true)
{
}
#endregion
#region IUriContext
///
/// Provides the base uri of the current context.
///
public override Uri BaseUri
{
get
{
ReadPreamble();
return _decoder._baseUri;
}
set
{
WritePreamble();
// Nothing to do here.
}
}
#endregion
#region Public Properties
///
/// Accesses the Thumbnail property for this BitmapFrameDecode
///
public override BitmapSource Thumbnail
{
get
{
ReadPreamble();
EnsureThumbnail();
return _thumbnail;
}
}
///
/// Accesses the Metadata property for this BitmapFrameDecode
///
public override ImageMetadata Metadata
{
get
{
ReadPreamble();
return InternalMetadata;
}
}
///
/// Accesses the Decoder property for this BitmapFrameDecode
///
public override BitmapDecoder Decoder
{
get
{
ReadPreamble();
return _decoder;
}
}
///
/// Used as a delegate in ColorContexts to get the unmanaged IWICColorContexts
///
///
/// Critical - Calls critical, unmanaged method
///
[SecurityCritical]
private int GetColorContexts(ref uint numContexts, IntPtr[] colorContextPtrs)
{
Invariant.Assert(colorContextPtrs == null || numContexts <= colorContextPtrs.Length);
return UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(_frameSource, numContexts, colorContextPtrs, out numContexts);
}
///
/// If there is an embedded color profile, return it.
/// Otherwise, return null. This method does NOT create a
/// color profile for bitmaps that don't already have one.
///
///
/// Provides access to this encoders color profile
///
///
///
/// Critical - Access unmanaged code, codecs
/// TreatAsSafe - We are exposing specific, non-sensitive data that came from
/// a Uri or a bitmap. If the profile data came from a Uri, the
/// WebRequest we did to get it demandend the appropriate
/// permission and we did not expose the request or response. If it came
/// from a bitmap, it may be cross-domain, but the restricted
/// nature of the data combined with the fact that it has been
/// inspected by WCS which is hardened against malicious data
/// makes this OK.
///
public override ReadOnlyCollection ColorContexts
{
[SecurityCritical, SecurityTreatAsSafe]
get
{
ReadPreamble();
if (!_isColorContextCached && !IsDownloading)
{
EnsureSource();
lock (_syncObject)
{
IList colorContextList = ColorContext.GetColorContextsHelper(GetColorContexts);
if (colorContextList != null)
{
_readOnlycolorContexts = new ReadOnlyCollection(colorContextList);
}
_isColorContextCached = true;
}
}
return _readOnlycolorContexts;
}
}
///
/// Returns if the BitmapFrame is downloading content
///
public override bool IsDownloading
{
get
{
ReadPreamble();
return Decoder.IsDownloading;
}
}
#endregion
#region Public Methods
///
/// Create an in-place bitmap metadata writer.
///
public override InPlaceBitmapMetadataWriter CreateInPlaceBitmapMetadataWriter()
{
ReadPreamble();
if (_decoder != null)
{
_decoder.CheckOriginalWritable();
}
// Demand Site Of Origin on the URI before usage of metadata.
CheckIfSiteOfOrigin();
EnsureSource();
return InPlaceBitmapMetadataWriter.CreateFromFrameDecode(_frameSource, _syncObject);
}
#endregion
#region ToString
///
/// Can serialze "this" to a string
///
internal override bool CanSerializeToString()
{
ReadPreamble();
return _decoder.CanConvertToString();
}
///
/// Creates a string representation of this object based on the format string
/// and IFormatProvider passed in.
/// If the provider is null, the CurrentCulture is used.
/// See the documentation for IFormattable for more information.
///
///
/// A string representation of this object.
///
internal override string ConvertToString(string format, IFormatProvider provider)
{
ReadPreamble();
if (_decoder != null)
{
return _decoder.ToString();
}
return base.ConvertToString(format, provider);
}
#endregion
#region Freezable
///
/// Implementation of Freezable.CreateInstanceCore .
///
/// The new Freezable.
protected override Freezable CreateInstanceCore()
{
return new BitmapFrameDecode();
}
///
/// Copy the fields not covered by DPs. This is used by
/// CloneCore(), CloneCurrentValueCore(), GetAsFrozenCore() and
/// GetCurrentValueAsFrozenCore().
///
///
/// Critical - access critical resources (_metadata)
/// TreatAsSafe - All inputs verified
///
[SecurityCritical, SecurityTreatAsSafe]
private void CopyCommon(BitmapFrameDecode sourceBitmapFrameDecode)
{
_bitmapInit.BeginInit();
_frameNumber = sourceBitmapFrameDecode._frameNumber;
_isThumbnailCached = sourceBitmapFrameDecode._isThumbnailCached;
_isMetadataCached = sourceBitmapFrameDecode._isMetadataCached;
_isColorContextCached = sourceBitmapFrameDecode._isColorContextCached;
_frameSource = sourceBitmapFrameDecode._frameSource;
_thumbnail = sourceBitmapFrameDecode._thumbnail;
_metadata = sourceBitmapFrameDecode.InternalMetadata;
_readOnlycolorContexts = sourceBitmapFrameDecode._readOnlycolorContexts;
_decoder = sourceBitmapFrameDecode._decoder;
if (_decoder != null && _decoder.IsDownloading)
{
// UpdateDecoder must be called when download completes and the real decoder
// is created. Normally _decoder will call UpdateDecoder, but in this case the
// decoder will not know about the cloned BitmapFrameDecode and will only call
// UpdateDecoder on the original. The clone will need to listen to the original
// BitmapFrameDecode for DownloadCompleted, then call UpdateDecoder on itself.
// The weak event sink hooks up handlers on DownloadCompleted, DownloadFailed,
// and DownloadProgress
_weakBitmapFrameDecodeEventSink =
new WeakBitmapFrameDecodeEventSink(this, sourceBitmapFrameDecode);
}
_syncObject = _decoder.SyncObject;
_createOptions = sourceBitmapFrameDecode._createOptions;
_cacheOption = sourceBitmapFrameDecode._cacheOption;
_bitmapInit.EndInit();
}
///
/// Implementation of Freezable.CloneCore .
///
protected override void CloneCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.CloneCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
///
/// Implementation of Freezable.CloneCurrentValueCore .
///
protected override void CloneCurrentValueCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.CloneCurrentValueCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
///
/// Implementation of Freezable.GetAsFrozenCore .
///
protected override void GetAsFrozenCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.GetAsFrozenCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
///
/// Implementation of Freezable.GetCurrentValueAsFrozenCore .
///
protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
{
BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
base.GetCurrentValueAsFrozenCore(sourceFreezable);
CopyCommon(sourceBitmapFrameDecode);
}
#endregion
#region Internal Properties / Methods
///
/// Updates the internal decoder -- usually happens with a LateBoundBitmapDecoder
///
///
/// Critical - access critical resources
/// TreatAsSafe - All inputs verified
///
[SecurityCritical, SecurityTreatAsSafe]
internal void UpdateDecoder(BitmapDecoder decoder)
{
Debug.Assert(_decoder != null);
_decoder = decoder;
_syncObject = decoder.SyncObject;
WicSourceHandle = null;
_needsUpdate = true;
FinalizeCreation();
// Trigger a update of the UCE resource
RegisterForAsyncUpdateResource();
}
///
/// Create the unmanaged resources
///
///
/// Critical - access critical resources
/// TreatAsSafe - All inputs verified
///
[SecurityCritical, SecurityTreatAsSafe]
internal override void FinalizeCreation()
{
EnsureSource();
// Set the WicSourceHandle and Update the cached settings so that we
// can query the source for information such as the palette which we need
// to determine if we need to format convert or not.
WicSourceHandle = _frameSource;
UpdateCachedSettings();
lock (_syncObject)
{
WicSourceHandle = CreateCachedBitmap(this, _frameSource, _createOptions, _cacheOption, Palette);
}
IsSourceCached = (_cacheOption != BitmapCacheOption.None);
CreationCompleted = true;
UpdateCachedSettings();
EnsureThumbnail();
}
//
// Workaround for a change caused by a bug fix, CopyCommon checks this property when
// copying the delegates attached to events.
// Default implementation in BitmapSource, see comments in BitmapSource.cs for details.
//
internal override bool ShouldCloneEventDelegates
{
get { return false; }
}
#endregion
#region Private Methods
/// Fired when the decoder download has completed
private void OnDownloadCompleted(object sender, EventArgs e)
{
//
// The sender should be the LateBoundDecoder that we hooked when it was _decoder.
//
LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender;
//
// Unhook the decoders download events
//
decoder.DownloadCompleted -= OnDownloadCompleted;
decoder.DownloadProgress -= OnDownloadProgress;
decoder.DownloadFailed -= OnDownloadFailed;
FireChanged();
_downloadEvent.InvokeEvents(this, null);
}
/// Called when download progress is made
private void OnDownloadProgress(object sender, DownloadProgressEventArgs e)
{
_progressEvent.InvokeEvents(this, e);
}
/// Called when download fails
private void OnDownloadFailed(object sender, ExceptionEventArgs e)
{
//
// The sender should be the LateBoundDecoder that we hooked when it was _decoder.
//
LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender;
//
// Unhook the decoders download events
//
decoder.DownloadCompleted -= OnDownloadCompleted;
decoder.DownloadProgress -= OnDownloadProgress;
decoder.DownloadFailed -= OnDownloadFailed;
_failedEvent.InvokeEvents(this, e);
}
/// Fired when the original's decoder's download has completed
private void OnOriginalDownloadCompleted(BitmapFrameDecode original, EventArgs e)
{
CleanUpWeakEventSink();
// Update the underlying decoder to match the original's
// We already have a _decoder from the cloning, but it's referencing the
// LateBoundBitmapDecoder. When download completes, LateBoundBitmapDecoder calls
// EnsureDecoder to make the _realDecoder (something like JpegBitmapDecoder),
// then calls SetupFrames on the _realDecoder, which calls BitmapFrameDecode's
// UpdateDecoder to set _decoder to the JpegBitmapDecoder. So the original's _decoder
// changes after download completes, and the clone should change as well.
UpdateDecoder(original.Decoder);
FireChanged();
_downloadEvent.InvokeEvents(this, e);
}
/// Called when the original's decoder's download fails
private void OnOriginalDownloadFailed(ExceptionEventArgs e)
{
CleanUpWeakEventSink();
_failedEvent.InvokeEvents(this, e);
}
private void CleanUpWeakEventSink()
{
// Unhook the decoders download events
_weakBitmapFrameDecodeEventSink.DetachSourceDownloadHandlers();
_weakBitmapFrameDecodeEventSink = null;
}
///
/// Ensure that the thumbnail is created/cached
///
///
/// Critical - Access unmanaged code, codecs
/// TreatAsSafe - Getting thumbnail data is OK
///
[SecurityCritical, SecurityTreatAsSafe]
private void EnsureThumbnail()
{
if (_isThumbnailCached || IsDownloading)
{
return;
}
else
{
EnsureSource();
IntPtr /* IWICBitmapSource */ thumbnail = IntPtr.Zero;
lock (_syncObject)
{
// Check if there is embedded thumbnail or not
int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetThumbnail(
_frameSource,
out thumbnail
);
if (hr != (int)WinCodecErrors.WINCODEC_ERR_CODECNOTHUMBNAIL)
{
HRESULT.Check(hr);
}
}
_isThumbnailCached = true;
if (thumbnail != IntPtr.Zero)
{
BitmapSourceSafeMILHandle thumbHandle = new BitmapSourceSafeMILHandle(thumbnail);
SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette();
BitmapPalette palette = null;
int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
thumbHandle,
unmanagedPalette
);
if (hr == HRESULT.S_OK)
{
palette = new BitmapPalette(unmanagedPalette);
}
_thumbnail = new UnmanagedBitmapWrapper(
CreateCachedBitmap(
null,
thumbHandle,
BitmapCreateOptions.PreservePixelFormat,
_cacheOption,
palette
));
_thumbnail.Freeze();
}
}
}
///
/// Returns cached metadata and creates BitmapMetadata if it does not exist.
/// This code will demand site of origin permissions.
///
///
/// Critical - Access unmanaged code
/// TreatAsSafe - demands site of origin permissions
///
internal override BitmapMetadata InternalMetadata
{
[SecurityCritical, SecurityTreatAsSafe]
get
{
// Demand Site Of Origin on the URI before usage of metadata.
CheckIfSiteOfOrigin();
if (!_isMetadataCached && !IsDownloading)
{
EnsureSource();
IntPtr /* IWICMetadataQueryReader */ metadata = IntPtr.Zero;
lock (_syncObject)
{
// Check if there is embedded metadata or not
int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetMetadataQueryReader(
_frameSource,
out metadata
);
if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION)
{
HRESULT.Check(hr);
}
}
if (metadata != IntPtr.Zero)
{
SafeMILHandle metadataHandle = new SafeMILHandle(metadata);
_metadata = new BitmapMetadata(metadataHandle, true, _decoder != null ? _decoder.IsMetadataFixedSize : false, _syncObject);
_metadata.Freeze();
}
_isMetadataCached = true;
}
return _metadata;
}
set
{
throw new System.NotImplementedException();
}
}
///
/// Ensure that a BitmapSource is created
///
///
/// Critical - Access unmanaged code, codecs
/// TreatAsSafe - Getting frame data is OK
///
[SecurityCritical, SecurityTreatAsSafe]
private void EnsureSource()
{
if (_frameSource == null)
{
if (_decoder == null)
{
HRESULT.Check((int)WinCodecErrors.WINCODEC_ERR_NOTINITIALIZED);
}
//
// Its possible that the frame was originally created with a network URI
// and DelayCreation was enabled. In this case, the decoder may not yet
// exist even though the download is complete. The code below creates a
// decoder if one does not exist.
//
if (_decoder.InternalDecoder == null)
{
Debug.Assert(_decoder is LateBoundBitmapDecoder);
Debug.Assert(IsDownloading == false);
_decoder = ((LateBoundBitmapDecoder)_decoder).Decoder;
_syncObject = _decoder.SyncObject;
Debug.Assert(_decoder.InternalDecoder != null);
}
IntPtr frameDecode = IntPtr.Zero;
Debug.Assert(_syncObject != null);
lock (_syncObject)
{
HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetFrame(
_decoder.InternalDecoder,
(uint)_frameNumber,
out frameDecode
));
_frameSource = new BitmapSourceSafeMILHandle(frameDecode);
_frameSource.CalculateSize();
}
}
}
#endregion
#region Data Members
/// IWICBitmapFrameDecode source
private BitmapSourceSafeMILHandle _frameSource = null;
/// Frame number
private int _frameNumber;
/// Is the thumbnail cached
private bool _isThumbnailCached;
/// Is the metadata cached
private bool _isMetadataCached;
/// If the ColorContext is already cached
private bool _isColorContextCached = false;
/// CreateOptions for this Frame
private BitmapCreateOptions _createOptions;
/// CacheOption for this Frame
private BitmapCacheOption _cacheOption;
/// Decoder
private BitmapDecoder _decoder;
#endregion
#region WeakBitmapSourceEvents
// Used to propagate DownloadCompleted events for cloned BitmapFrameDecodes that are still downloading
private WeakBitmapFrameDecodeEventSink _weakBitmapFrameDecodeEventSink;
private class WeakBitmapFrameDecodeEventSink : WeakReference
{
public WeakBitmapFrameDecodeEventSink(BitmapFrameDecode cloned, BitmapFrameDecode original)
: base(cloned)
{
_original = original;
if (!_original.IsFrozen)
{
_original.DownloadCompleted += OnSourceDownloadCompleted;
_original.DownloadFailed += OnSourceDownloadFailed;
_original.DownloadProgress += OnSourceDownloadProgress;
}
}
public void OnSourceDownloadCompleted(object sender, EventArgs e)
{
BitmapFrameDecode clone = this.Target as BitmapFrameDecode;
if (null != clone)
{
clone.OnOriginalDownloadCompleted(_original, e);
}
else
{
DetachSourceDownloadHandlers();
}
}
public void OnSourceDownloadFailed(object sender, ExceptionEventArgs e)
{
BitmapFrameDecode clone = this.Target as BitmapFrameDecode;
if (null != clone)
{
clone.OnOriginalDownloadFailed(e);
}
else
{
DetachSourceDownloadHandlers();
}
}
public void OnSourceDownloadProgress(object sender, DownloadProgressEventArgs e)
{
BitmapFrameDecode clone = this.Target as BitmapFrameDecode;
if (null != clone)
{
clone.OnDownloadProgress(sender, e);
}
else
{
DetachSourceDownloadHandlers();
}
}
public void DetachSourceDownloadHandlers()
{
if (!_original.IsFrozen)
{
_original.DownloadCompleted -= OnSourceDownloadCompleted;
_original.DownloadFailed -= OnSourceDownloadFailed;
_original.DownloadProgress -= OnSourceDownloadProgress;
}
}
private BitmapFrameDecode _original;
}
#endregion WeakBitmapSourceEvents
}
#endregion // BitmapFrameDecode
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SqlFactory.cs
- DecimalAnimation.cs
- Helpers.cs
- DataGridViewHeaderCell.cs
- SafeViewOfFileHandle.cs
- Ticks.cs
- FormattedTextSymbols.cs
- DynamicActivityXamlReader.cs
- KoreanLunisolarCalendar.cs
- PageAsyncTask.cs
- DataSourceCache.cs
- Hashtable.cs
- TableLayoutSettings.cs
- _StreamFramer.cs
- LineGeometry.cs
- ScrollProperties.cs
- HighlightOverlayGlyph.cs
- FolderNameEditor.cs
- Table.cs
- EmitterCache.cs
- GPPOINTF.cs
- WebConfigurationManager.cs
- Matrix.cs
- UnsafeNativeMethods.cs
- returneventsaver.cs
- TemplateBindingExpressionConverter.cs
- Debug.cs
- MenuCommandService.cs
- Column.cs
- QueryStringParameter.cs
- MetricEntry.cs
- ToolStripPanelSelectionGlyph.cs
- ObjectViewListener.cs
- Mutex.cs
- GAC.cs
- DataGridTableStyleMappingNameEditor.cs
- GlyphRunDrawing.cs
- WhiteSpaceTrimStringConverter.cs
- StylusPlugin.cs
- SqlVisitor.cs
- PersistChildrenAttribute.cs
- RegionData.cs
- EncryptedPackageFilter.cs
- ActivityExecutor.cs
- WorkflowMessageEventHandler.cs
- DataMember.cs
- XmlAutoDetectWriter.cs
- TextBoxBase.cs
- XmlSchemaSimpleTypeUnion.cs
- BinaryOperationBinder.cs
- MetadataArtifactLoaderResource.cs
- XmlSchemaInclude.cs
- Activity.cs
- ExpressionTable.cs
- ComponentChangingEvent.cs
- PersonalizationProviderHelper.cs
- CssClassPropertyAttribute.cs
- CopyOnWriteList.cs
- FileUtil.cs
- DiscreteKeyFrames.cs
- KeyedHashAlgorithm.cs
- InkPresenter.cs
- FieldBuilder.cs
- CellTreeNodeVisitors.cs
- XPathDocumentNavigator.cs
- UpnEndpointIdentity.cs
- NullExtension.cs
- ReadOnlyDataSourceView.cs
- FigureParaClient.cs
- IndexOutOfRangeException.cs
- ParseElement.cs
- SessionEndedEventArgs.cs
- XmlSchemaGroup.cs
- ListViewItemSelectionChangedEvent.cs
- PathData.cs
- Propagator.JoinPropagator.cs
- FileClassifier.cs
- EventHandlersStore.cs
- SortedSet.cs
- RowToFieldTransformer.cs
- DefaultSection.cs
- ArrayHelper.cs
- objectquery_tresulttype.cs
- InlineUIContainer.cs
- StreamingContext.cs
- BitmapImage.cs
- SelectionProcessor.cs
- FunctionDescription.cs
- CustomValidator.cs
- FrameworkContentElementAutomationPeer.cs
- xmlsaver.cs
- SignerInfo.cs
- XpsFont.cs
- EdmSchemaAttribute.cs
- EntityCommand.cs
- HtmlTernaryTree.cs
- Error.cs
- XslTransform.cs
- ServicePointManager.cs
- Window.cs