using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Versioning; using NPSMLib.Interop; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("ADeltaX")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A NowPlayingSessionManager wrapper library - used for controlling SMTC apps\r\n\r\nSupported Windows 10 versions: 10586+ (1511 or newer)\r\nCompatible with UWP")] [assembly: AssemblyFileVersion("0.9.14.0")] [assembly: AssemblyInformationalVersion("0.9.14")] [assembly: AssemblyProduct("NPSMLib")] [assembly: AssemblyTitle("NPSMLib")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ADeltaX/NPSMLib")] [assembly: AssemblyVersion("0.9.14.0")] namespace NPSMLib { public enum NowPlayingSessionType { Unknown, PlayTo, Local } public enum MediaPlaybackCommands { Play, Pause, Stop, Record, FastForward, Rewind, Next, Previous, ChannelUp, ChannelDown, PlayPauseToggle, Max } public enum MediaPlaybackRepeatMode { Unknown, None, Track, List } public enum MediaPlaybackDataChangedEvent { PlaybackInfoChanged, MediaInfoChanged, TimelinePropertiesChanged } public enum NowPlayingSessionManagerNotificationType { SessionCreated, CurrentSessionChanged, SessionDisconnected } [Flags] public enum MediaPlaybackProps { Capabilities = 1, State = 2, Mode = 4, AutoRepeatMode = 8, PlaybackRate = 0x10, ShuffleEnabled = 0x20 } [Flags] public enum MediaPlaybackCapabilities { None = 0, Play = 1, Pause = 2, Stop = 4, Record = 8, FastForward = 0x10, Rewind = 0x20, Next = 0x40, Previous = 0x80, ChannelUp = 0x100, ChannelDown = 0x200, PlayPauseToggle = 0x400, HandleEndpointChange = 0x800, Shuffle = 0x1000, Repeat = 0x2000, PlaybackRate = 0x4000, PlaybackPosition = 0x8000 } public enum MediaPlaybackState { Unknown, Closed, Opened, Changing, Stopped, Playing, Paused } public enum MediaPlaybackMode { Unknown, Audio, Video, Image, Podcast, AudioBook } public class MediaPlaybackDataSource { private class MediaPlaybackDataChangedEventHandler : COMInterop.IMediaPlaybackDataChangedEventHandler { internal COMInterop.NPSMEventRegistrationToken Token { get; set; } private MediaPlaybackDataSource CurrentMediaPlaybackInstance { get; set; } public MediaPlaybackDataChangedEventHandler(MediaPlaybackDataSource currentSessionInstance) { CurrentMediaPlaybackInstance = currentSessionInstance; } public void OnMediaPlaybackDataChangedEvent(object source, MediaPlaybackDataChangedEvent dataChangedEvent) { CurrentMediaPlaybackInstance._mediaPlaybackDataChanged?.Invoke(CurrentMediaPlaybackInstance, new MediaPlaybackDataChangedArgs { MediaPlaybackDataSource = new MediaPlaybackDataSource(source), DataChangedEvent = dataChangedEvent }); } } private const string ID_MS_MEDIA_SCHEMA_PHOTO = "{6FB2E74A-B8CB-40BB-93F3-FAC5F00FA203}"; private const string ID_MS_MEDIA_SCHEMA_VIDEO = "{DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B}"; private const string ID_MS_MEDIA_SCHEMA_MUSIC = "{D1607DBC-E323-4BE2-86A1-48A42A28441E}"; private static PROPERTYKEY PKEY_Title = new PROPERTYKEY { fmtid = new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), pid = 2u }; private static PROPERTYKEY PKEY_Music_TrackNumber = new PROPERTYKEY { fmtid = new Guid("56A3372E-CE9C-11D2-9F0E-006097C686F6"), pid = 7u }; private static PROPERTYKEY PKEY_ThumbnailStream = new PROPERTYKEY { fmtid = new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), pid = 27u }; private static PROPERTYKEY PKEY_Music_Genre = new PROPERTYKEY { fmtid = new Guid("56A3372E-CE9C-11D2-9F0E-006097C686F6"), pid = 11u }; private static PROPERTYKEY PKEY_Music_Artist = new PROPERTYKEY { fmtid = new Guid("56A3372E-CE9C-11D2-9F0E-006097C686F6"), pid = 2u }; private static PROPERTYKEY PKEY_Music_AlbumTitle = new PROPERTYKEY { fmtid = new Guid("56A3372E-CE9C-11D2-9F0E-006097C686F6"), pid = 4u }; private static PROPERTYKEY PKEY_Media_ClassPrimaryID = new PROPERTYKEY { fmtid = new Guid("64440492-4C8B-11D1-8B70-080036B11A03"), pid = 13u }; private static PROPERTYKEY PKEY_Music_AlbumArtist = new PROPERTYKEY { fmtid = new Guid("56A3372E-CE9C-11D2-9F0E-006097C686F6"), pid = 13u }; private static PROPERTYKEY PKEY_AlbumTrackCount = new PROPERTYKEY { fmtid = new Guid("BAC8804B-BAA1-4E3F-9A11-EFB3EA519859"), pid = 2u }; private static PROPERTYKEY PKEY_Media_SubTitle = new PROPERTYKEY { fmtid = new Guid("56A3372E-CE9C-11D2-9F0E-006097C686F6"), pid = 38u }; private readonly object playbackDataSourceIUnknown; private readonly COMInterop.IMediaPlaybackDataSource_20279 playbackDataSource_20279; private readonly COMInterop.IMediaPlaybackDataSource_10586 playbackDataSource_10586; private readonly int numSelectInterface; private MediaPlaybackDataChangedEventHandler eventHandler; private readonly object subscriptionLock = new object(); internal object GetIUnknownInterface => playbackDataSourceIUnknown; private event EventHandler _mediaPlaybackDataChanged; public event EventHandler MediaPlaybackDataChanged { add { lock (subscriptionLock) { if (this._mediaPlaybackDataChanged == null) { eventHandler = new MediaPlaybackDataChangedEventHandler(this); COMInterop.NPSMEventRegistrationToken token; if (numSelectInterface == 20279) { playbackDataSource_20279.RegisterEventHandler(eventHandler, out token); } else { playbackDataSource_10586.RegisterEventHandler(eventHandler, out token); } eventHandler.Token = token; } _mediaPlaybackDataChanged += value; } } remove { lock (subscriptionLock) { _mediaPlaybackDataChanged -= value; if (this._mediaPlaybackDataChanged == null) { if (numSelectInterface == 20279) { playbackDataSource_20279.UnregisterEventHandler(eventHandler.Token); } else { playbackDataSource_10586.UnregisterEventHandler(eventHandler.Token); } eventHandler = null; } } } } internal MediaPlaybackDataSource(object playbackDataSourceIUnknown) { this.playbackDataSourceIUnknown = playbackDataSourceIUnknown; if (playbackDataSourceIUnknown is COMInterop.IMediaPlaybackDataSource_10586 mediaPlaybackDataSource_) { numSelectInterface = 10586; playbackDataSource_10586 = mediaPlaybackDataSource_; return; } if (playbackDataSourceIUnknown is COMInterop.IMediaPlaybackDataSource_20279 mediaPlaybackDataSource_2) { numSelectInterface = 20279; playbackDataSource_20279 = mediaPlaybackDataSource_2; return; } throw new NotSupportedException("QueryInterface failed due to non-available interface/guid"); } public static MediaPlaybackMode MediaSchemaToMediaPlaybackMode(string mediaSchema) { return mediaSchema switch { "{D1607DBC-E323-4BE2-86A1-48A42A28441E}" => MediaPlaybackMode.Audio, "{DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B}" => MediaPlaybackMode.Video, "{6FB2E74A-B8CB-40BB-93F3-FAC5F00FA203}" => MediaPlaybackMode.Image, _ => MediaPlaybackMode.Unknown, }; } public MediaObjectInfo GetMediaObjectInfo() { string title = ""; string artist = ""; string albumTitle = ""; string mediaClassPrimaryID = ""; string albumArtist = ""; string subtitle = ""; string[] array = new string[0]; uint trackNumber = 0u; uint albumTrackCount = 0u; COMInterop.IPropertyStore ppMediaObjectInfo; if (numSelectInterface == 20279) { playbackDataSource_20279.GetMediaObjectInfo(out ppMediaObjectInfo); } else { playbackDataSource_10586.GetMediaObjectInfo(out ppMediaObjectInfo); } if (ppMediaObjectInfo != null) { if (ppMediaObjectInfo.GetValue(ref PKEY_Title, out var pv) == 0 && pv.vt == VARTYPE.VT_LPWSTR) { title = Marshal.PtrToStringUni(pv.union.pwszVal); NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Music_Artist, out pv) == 0 && pv.vt == VARTYPE.VT_LPWSTR) { artist = Marshal.PtrToStringUni(pv.union.pwszVal); NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Music_AlbumTitle, out pv) == 0 && pv.vt == VARTYPE.VT_LPWSTR) { albumTitle = Marshal.PtrToStringUni(pv.union.pwszVal); NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Music_TrackNumber, out pv) == 0 && pv.vt == VARTYPE.VT_UI4) { trackNumber = pv.union.ulVal; NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Music_AlbumArtist, out pv) == 0 && pv.vt == VARTYPE.VT_LPWSTR) { albumArtist = Marshal.PtrToStringUni(pv.union.pwszVal); NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_AlbumTrackCount, out pv) == 0 && pv.vt == VARTYPE.VT_UI4) { albumTrackCount = pv.union.ulVal; NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Media_SubTitle, out pv) == 0 && pv.vt == VARTYPE.VT_LPWSTR) { subtitle = Marshal.PtrToStringUni(pv.union.pwszVal); NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Music_Genre, out pv) == 0 && pv.vt == (VARTYPE)4127) { uint cElems = pv.union.calpwstr.cElems; array = new string[cElems]; for (int i = 0; i < cElems; i++) { array[i] = Marshal.PtrToStringUni(Marshal.ReadIntPtr(pv.union.calpwstr.pElems + IntPtr.Size * i)); } NativeMethods.PropVariantClear(ref pv); } if (ppMediaObjectInfo.GetValue(ref PKEY_Media_ClassPrimaryID, out pv) == 0 && pv.vt == VARTYPE.VT_LPWSTR) { mediaClassPrimaryID = Marshal.PtrToStringUni(pv.union.pwszVal); NativeMethods.PropVariantClear(ref pv); } } return new MediaObjectInfo(albumArtist, albumTitle, subtitle, title, artist, mediaClassPrimaryID, array, albumTrackCount, trackNumber); } public Stream GetThumbnailStream() { Stream stream = null; COMInterop.IPropertyStore ppMediaObjectInfo; if (numSelectInterface == 20279) { playbackDataSource_20279.GetMediaObjectInfo(out ppMediaObjectInfo); } else { playbackDataSource_10586.GetMediaObjectInfo(out ppMediaObjectInfo); } if (ppMediaObjectInfo != null && ppMediaObjectInfo.GetValue(ref PKEY_ThumbnailStream, out var pv) == 0 && pv.vt == VARTYPE.VT_STREAM) { IStream stream2 = (IStream)Marshal.GetObjectForIUnknown(pv.union.pStream); stream = new MemoryStream(); int num = 4096; byte[] array = new byte[num]; int num2 = 0; do { IntPtr intPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int))); try { stream2.Read(array, num, intPtr); num2 = Marshal.ReadInt32(intPtr); } finally { Marshal.FreeCoTaskMem(intPtr); } stream.Write(array, 0, num2); } while (num2 > 0); stream.Seek(0L, SeekOrigin.Begin); NativeMethods.PropVariantClear(ref pv); } return stream; } public MediaPlaybackInfo GetMediaPlaybackInfo() { MediaPlaybackInfo pPlaybackInfo; if (numSelectInterface == 20279) { playbackDataSource_20279.GetMediaPlaybackInfo(out pPlaybackInfo); } else { playbackDataSource_10586.GetMediaPlaybackInfo(out pPlaybackInfo); } return pPlaybackInfo; } public MediaTimelineProperties GetMediaTimelineProperties() { MediaTimelineProperties pTimelineProperties; if (numSelectInterface == 20279) { playbackDataSource_20279.GetMediaTimelineProperties(out pTimelineProperties); } else { playbackDataSource_10586.GetMediaTimelineProperties(out pTimelineProperties); } return pTimelineProperties; } public string GetParentApplicationId() { string value; if (numSelectInterface == 20279) { playbackDataSource_20279.GetParentApplicationId(out value); } else { playbackDataSource_10586.GetParentApplicationId(out value); } return value; } public bool SendMediaPlaybackCommand(MediaPlaybackCommands command) { if (numSelectInterface == 20279) { return playbackDataSource_20279.SendMediaPlaybackCommand(command) == 0; } return playbackDataSource_10586.SendMediaPlaybackCommand(command) == 0; } public bool SendPlaybackPositionChangeRequest(TimeSpan requestedPlaybackPosition) { if (numSelectInterface == 20279) { return playbackDataSource_20279.SendPlaybackPositionChangeRequest(requestedPlaybackPosition.Ticks) == 0; } return playbackDataSource_10586.SendPlaybackPositionChangeRequest(requestedPlaybackPosition.Ticks) == 0; } public bool SendPlaybackRateChangeRequest(double requestedPlaybackRate) { if (numSelectInterface == 20279) { return playbackDataSource_20279.SendPlaybackRateChangeRequest(requestedPlaybackRate) == 0; } return playbackDataSource_10586.SendPlaybackRateChangeRequest(requestedPlaybackRate) == 0; } public bool SendRepeatModeChangeRequest(MediaPlaybackRepeatMode requestedRepeatMode) { if (numSelectInterface == 20279) { return playbackDataSource_20279.SendRepeatModeChangeRequest(requestedRepeatMode) == 0; } return playbackDataSource_10586.SendRepeatModeChangeRequest(requestedRepeatMode) == 0; } public bool SendShuffleEnabledChangeRequest(bool requestedShuffle) { if (numSelectInterface == 20279) { return playbackDataSource_20279.SendShuffleEnabledChangeRequest(requestedShuffle) == 0; } return playbackDataSource_10586.SendShuffleEnabledChangeRequest(requestedShuffle) == 0; } } public class MediaPlaybackDataChangedArgs : EventArgs { public MediaPlaybackDataSource MediaPlaybackDataSource { get; internal set; } public MediaPlaybackDataChangedEvent DataChangedEvent { get; internal set; } } public class NowPlayingSession { private readonly object sessionIUnknown; private readonly COMInterop.INowPlayingSession_14393 session_14393; private readonly COMInterop.INowPlayingSession_10586 session_10586; private readonly int numSelectInterface; public IntPtr Hwnd { get { IntPtr pHwnd; if (numSelectInterface == 14393) { session_14393.get_HWND(out pHwnd); } else { session_10586.get_HWND(out pHwnd); } return pHwnd; } } public uint PID { get { uint pdwPID; if (numSelectInterface == 14393) { session_14393.get_PID(out pdwPID); } else { session_10586.get_PID(out pdwPID); } return pdwPID; } } public string RenderDeviceId { get { string pszRenderId; if (numSelectInterface == 14393) { session_14393.get_RenderDeviceId(out pszRenderId); } else { session_10586.get_RenderDeviceId(out pszRenderId); } return pszRenderId; } } public string SourceAppId { get { string pszSrcAppId; if (numSelectInterface == 14393) { session_14393.get_SourceAppId(out pszSrcAppId); } else { session_10586.get_SourceAppId(out pszSrcAppId); } return pszSrcAppId; } } public string SourceDeviceId { get { string pszSourceDeviceId; if (numSelectInterface == 14393) { session_14393.get_SourceDeviceId(out pszSourceDeviceId); } else { session_10586.get_SourceDeviceId(out pszSourceDeviceId); } return pszSourceDeviceId; } } public object Connection { get { object ppUnknown; if (numSelectInterface == 14393) { session_14393.get_Connection(out ppUnknown); } else { session_10586.get_Connection(out ppUnknown); } return ppUnknown; } } internal NowPlayingSession(object sessionIUnknown) { this.sessionIUnknown = sessionIUnknown; if (sessionIUnknown is COMInterop.INowPlayingSession_14393 nowPlayingSession_) { numSelectInterface = 14393; session_14393 = nowPlayingSession_; return; } if (sessionIUnknown is COMInterop.INowPlayingSession_10586 nowPlayingSession_2) { numSelectInterface = 10586; session_10586 = nowPlayingSession_2; return; } throw new NotSupportedException("QueryInterface failed due to non-available interface/guid"); } public MediaPlaybackDataSource ActivateMediaPlaybackDataSource() { object ppMediaControl; if (numSelectInterface == 14393) { session_14393.ActivateMediaPlaybackDataSource(out ppMediaControl); } else { session_10586.ActivateMediaPlaybackDataSource(out ppMediaControl); } return new MediaPlaybackDataSource(ppMediaControl); } public NowPlayingSessionType GetSessionType() { NowPlayingSessionType pType; if (numSelectInterface == 14393) { session_14393.get_SessionType(out pType); } else { session_10586.get_SessionType(out pType); } return pType; } public NowPlayingSessionInfo GetSessionInfo() { object ppInfo; if (numSelectInterface == 14393) { session_14393.get_Info(out ppInfo); } else { session_10586.get_Info(out ppInfo); } return new NowPlayingSessionInfo(ppInfo); } public object BeginInteractionWithSession() { object ppSessionInteractionToken = null; if (numSelectInterface == 14393) { session_14393.BeginInteractionWithSession(out ppSessionInteractionToken); } return ppSessionInteractionToken; } } public class NowPlayingSessionInfo : IEquatable { private readonly object infoIUnknown; private readonly COMInterop.INowPlayingSessionInfo_19041 info_19041; private readonly COMInterop.INowPlayingSessionInfo_10586 info_10586; private readonly int numSelectInterface; internal object GetIUnknownInterface => infoIUnknown; internal NowPlayingSessionInfo(object infoIUnknown) { this.infoIUnknown = infoIUnknown; if (infoIUnknown is COMInterop.INowPlayingSessionInfo_19041 nowPlayingSessionInfo_) { numSelectInterface = 19041; info_19041 = nowPlayingSessionInfo_; return; } if (infoIUnknown is COMInterop.INowPlayingSessionInfo_10586 nowPlayingSessionInfo_2) { numSelectInterface = 10586; info_10586 = nowPlayingSessionInfo_2; return; } throw new NotSupportedException("QueryInterface failed due to non-available interface/guid"); } public bool GetInfo(out IntPtr hWnd, out uint PID, out string DeviceId) { if (numSelectInterface == 19041) { return info_19041.GetInfo(out hWnd, out PID, out DeviceId) == 0; } return info_10586.GetInfo(out hWnd, out PID, out DeviceId) == 0; } public bool Equals(NowPlayingSessionInfo other) { bool pfIsEqual = false; if (numSelectInterface == 19041) { if (NowPlayingSessionManager.OSVersion.Build >= 19582) { (info_19041 as COMInterop.INowPlayingSessionInfo_19582).IsEqual(other.infoIUnknown, out pfIsEqual); } else { info_19041.IsEqual(other.infoIUnknown, out pfIsEqual); } } else { info_10586.IsEqual(other.infoIUnknown, out pfIsEqual); } return pfIsEqual; } } public class NowPlayingSessionManager { private class NowPlayingSessionManagerEventHandler : COMInterop.INowPlayingSessionManagerEventHandler { internal COMInterop.NPSMEventRegistrationToken Token { get; set; } private NowPlayingSessionManager CurrentSessionInstance { get; set; } public NowPlayingSessionManagerEventHandler(NowPlayingSessionManager currentSessionInstance) { CurrentSessionInstance = currentSessionInstance; } public void OnChange(NowPlayingSessionManagerNotificationType notificationType, object pINowPlayingSessionInfoIUnknown, [MarshalAs(UnmanagedType.LPWStr)] string unknown) { CurrentSessionInstance._sessionListChanged?.Invoke(CurrentSessionInstance, new NowPlayingSessionManagerEventArgs { NotificationType = notificationType, NowPlayingSessionInfo = new NowPlayingSessionInfo(pINowPlayingSessionInfoIUnknown), SessionTypeString = unknown }); } } private readonly object sessionManagerIUnknown; private readonly COMInterop.INowPlayingSessionManager_19041 sessionManager_19041; private readonly COMInterop.INowPlayingSessionManager_10586 sessionManager_10586; private readonly int numSelectInterface; private static readonly OSVersion osVersion = Helpers.GetOSVersion(); private NowPlayingSessionManagerEventHandler eventHandler; private readonly object subscriptionLock = new object(); internal static OSVersion OSVersion => osVersion; public NowPlayingSession CurrentSession { get { object ppSession = null; if (numSelectInterface == 19041) { sessionManager_19041.get_CurrentSession(out ppSession); } else { sessionManager_10586.get_CurrentSession(out ppSession); } if (ppSession != null) { return new NowPlayingSession(ppSession); } return null; } } public ulong Count { get { ulong pCount; if (numSelectInterface == 19041) { sessionManager_19041.get_Count(out pCount); } else { sessionManager_10586.get_Count(out pCount); } return pCount; } } private event EventHandler _sessionListChanged; public event EventHandler SessionListChanged { add { lock (subscriptionLock) { if (this._sessionListChanged == null) { eventHandler = new NowPlayingSessionManagerEventHandler(this); COMInterop.NPSMEventRegistrationToken pToken; if (numSelectInterface == 19041) { sessionManager_19041.RegisterEventHandler(eventHandler, out pToken); } else { sessionManager_10586.RegisterEventHandler(eventHandler, out pToken); } eventHandler.Token = pToken; } _sessionListChanged += value; } } remove { lock (subscriptionLock) { _sessionListChanged -= value; if (this._sessionListChanged == null) { if (numSelectInterface == 19041) { sessionManager_19041.UnregisterEventHandler(eventHandler.Token); } else { sessionManager_10586.UnregisterEventHandler(eventHandler.Token); } eventHandler = null; } } } } public NowPlayingSessionManager() { Guid uuid = new Guid("3b6a7908-ce07-4ba9-878c-6e4a15db5e5b"); Guid uuid2 = new Guid("A7052211-8B56-43C4-8F26-12852F7303A3"); if (NativeMethods.CoCreateInstance(ref COMInterop.CLSID_NowPlayingSessionManager, null, 1028u, ref uuid, out sessionManagerIUnknown) == 0) { numSelectInterface = 19041; sessionManager_19041 = (COMInterop.INowPlayingSessionManager_19041)sessionManagerIUnknown; return; } if (NativeMethods.CoCreateInstance(ref COMInterop.CLSID_NowPlayingSessionManager, null, 1028u, ref uuid2, out sessionManagerIUnknown) == 0) { numSelectInterface = 10586; sessionManager_10586 = (COMInterop.INowPlayingSessionManager_10586)sessionManagerIUnknown; return; } throw new NotSupportedException("CoCreateInstance failed to create an instance due to non-available guid"); } public NowPlayingSession[] GetSessions() { uint pdwCount; IntPtr pppSessions; if (numSelectInterface == 19041) { sessionManager_19041.GetSessions(out pdwCount, out pppSessions); } else { sessionManager_10586.GetSessions(out pdwCount, out pppSessions); } NowPlayingSession[] array = new NowPlayingSession[pdwCount]; for (int i = 0; i < pdwCount; i++) { array[i] = new NowPlayingSession(Marshal.GetObjectForIUnknown(Marshal.ReadIntPtr(pppSessions + IntPtr.Size * i))); } return array; } public bool SetNextCurrentSession() { if (numSelectInterface == 19041) { return sessionManager_19041.SetCurrentNextSession() == 0; } return sessionManager_10586.SetCurrentNextSession() == 0; } public bool SetCurrentSession(NowPlayingSessionInfo pInfo) { if (numSelectInterface == 19041) { return sessionManager_19041.SetCurrentSession(pInfo.GetIUnknownInterface) == 0; } return sessionManager_10586.SetCurrentSession(pInfo.GetIUnknownInterface) == 0; } public bool RemoveSession(NowPlayingSessionInfo pInfo) { if (numSelectInterface == 19041) { return sessionManager_19041.RemoveSession(pInfo.GetIUnknownInterface) == 0; } return sessionManager_10586.RemoveSession(pInfo.GetIUnknownInterface) == 0; } public NowPlayingSession FindSession(NowPlayingSessionInfo pInfo) { object ppSession; if (numSelectInterface == 19041) { sessionManager_19041.FindSession(pInfo.GetIUnknownInterface, out ppSession); } else { sessionManager_10586.FindSession(pInfo.GetIUnknownInterface, out ppSession); } if (ppSession == null) { return null; } return new NowPlayingSession(ppSession); } public bool Refresh(IntPtr hWnd) { if (numSelectInterface == 19041) { return sessionManager_19041.Refresh(hWnd) == 0; } return sessionManager_10586.Refresh(hWnd) == 0; } public bool Update(bool fEnabled, IntPtr hwnd, uint dwPID, ulong unknown, MediaPlaybackDataSource pSource) { if (numSelectInterface == 19041) { return sessionManager_19041.Update(fEnabled, hwnd, dwPID, unknown, pSource.GetIUnknownInterface) == 0; } return sessionManager_10586.Update(fEnabled, hwnd, dwPID, pSource.GetIUnknownInterface) == 0; } } public class NowPlayingSessionManagerEventArgs : EventArgs { public NowPlayingSessionManagerNotificationType NotificationType { get; internal set; } public NowPlayingSessionInfo NowPlayingSessionInfo { get; internal set; } public string SessionTypeString { get; internal set; } } public struct MediaPlaybackInfo { private readonly MediaPlaybackProps propsValid; private readonly MediaPlaybackCapabilities playbackCaps; private readonly MediaPlaybackState playbackState; private readonly MediaPlaybackMode playbackMode; private readonly MediaPlaybackRepeatMode repeatMode; private readonly double playbackRate; private readonly int shuffleEnabled; private readonly long lastPlayingFileTime; private readonly long padding1; private readonly long padding2; private readonly long padding3; private readonly long padding4; public MediaPlaybackProps PropsValid => propsValid; public MediaPlaybackCapabilities PlaybackCaps => playbackCaps; public MediaPlaybackState PlaybackState => playbackState; public MediaPlaybackMode PlaybackMode => playbackMode; public MediaPlaybackRepeatMode RepeatMode => repeatMode; public double PlaybackRate => playbackRate; public bool ShuffleEnabled => shuffleEnabled != 0; public DateTime LastPlayingFileTime => DateTime.FromFileTime(lastPlayingFileTime); } public struct MediaTimelineProperties { private readonly TimeSpan startTime; private readonly TimeSpan endTime; private readonly TimeSpan minSeekTime; private readonly TimeSpan maxSeekTime; private readonly TimeSpan position; private readonly long positionSetFileTime; private readonly long padding1; private readonly long padding2; private readonly long padding3; private readonly long padding4; public TimeSpan StartTime => startTime; public TimeSpan EndTime => endTime; public TimeSpan MinSeekTime => minSeekTime; public TimeSpan MaxSeekTime => maxSeekTime; public TimeSpan Position => position; public DateTime PositionSetFileTime => DateTime.FromFileTime(positionSetFileTime); } public struct MediaObjectInfo { private readonly string albumArtist; private readonly string albumTitle; private readonly string subtitle; private readonly string title; private readonly string artist; private readonly string mediaClassPrimaryID; private readonly string[] genres; private readonly uint albumTrackCount; private readonly uint trackNumber; public string AlbumArtist => albumArtist; public string AlbumTitle => albumTitle; public string Subtitle => subtitle; public string Title => title; public string Artist => artist; public string MediaClassPrimaryID => mediaClassPrimaryID; public string[] Genres => genres; public uint AlbumTrackCount => albumTrackCount; public uint TrackNumber => trackNumber; internal MediaObjectInfo(string albumArtist, string albumTitle, string subtitle, string title, string artist, string mediaClassPrimaryID, string[] genres, uint albumTrackCount, uint trackNumber) { this.albumArtist = albumArtist; this.albumTitle = albumTitle; this.subtitle = subtitle; this.title = title; this.artist = artist; this.mediaClassPrimaryID = mediaClassPrimaryID; this.genres = genres; this.albumTrackCount = albumTrackCount; this.trackNumber = trackNumber; } } } namespace NPSMLib.Interop { internal class COMInterop { public struct NPSMEventRegistrationToken { private readonly long value; } [ComImport] [Guid("3b6a7908-ce07-4ba9-878c-6e4a15db5e5b")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSessionManager_19041 { [PreserveSig] int get_Count(out ulong pCount); [PreserveSig] int get_CurrentSession([MarshalAs(UnmanagedType.IUnknown)] out object ppSession); [PreserveSig] int AddSession(NowPlayingSessionType type, IntPtr hwnd, uint dwPID, [MarshalAs(UnmanagedType.LPWStr)] string appId, [MarshalAs(UnmanagedType.LPWStr)] string szSourceDeviceId, [MarshalAs(UnmanagedType.LPWStr)] string szRenderDeviceId, [MarshalAs(UnmanagedType.LPWStr)] string source, [MarshalAs(UnmanagedType.IUnknown)] object pMediaControl, [MarshalAs(UnmanagedType.IUnknown)] object pConnection, [MarshalAs(UnmanagedType.Bool)] bool fMarkAsCurrentSession, IntPtr processHandle); [PreserveSig] int RemoveSession([MarshalAs(UnmanagedType.IUnknown)] object pInfo); [PreserveSig] int GetSessions(out uint pdwCount, out IntPtr pppSessions); [PreserveSig] int FindSession([MarshalAs(UnmanagedType.IUnknown)] object pInfo, [MarshalAs(UnmanagedType.IUnknown)] out object ppSession); [PreserveSig] int SetCurrentSession([MarshalAs(UnmanagedType.IUnknown)] object pInfo); [PreserveSig] int SetCurrentNextSession(); [PreserveSig] int Refresh(IntPtr hwnd); [PreserveSig] int Update([MarshalAs(UnmanagedType.Bool)] bool fEnabled, IntPtr hwnd, uint dwPID, ulong unknown, [MarshalAs(UnmanagedType.IUnknown)] object pSource); [PreserveSig] int RegisterEventHandler(INowPlayingSessionManagerEventHandler pEventHandler, out NPSMEventRegistrationToken pToken); [PreserveSig] int UnregisterEventHandler(NPSMEventRegistrationToken token); } [ComImport] [Guid("A7052211-8B56-43C4-8F26-12852F7303A3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSessionManager_10586 { [PreserveSig] int get_Count(out ulong pCount); [PreserveSig] int get_CurrentSession([MarshalAs(UnmanagedType.IUnknown)] out object ppSession); [PreserveSig] int AddSession(NowPlayingSessionType type, IntPtr hwnd, uint dwPID, [MarshalAs(UnmanagedType.LPWStr)] string appId, [MarshalAs(UnmanagedType.LPWStr)] string szSourceDeviceId, [MarshalAs(UnmanagedType.LPWStr)] string szRenderDeviceId, [MarshalAs(UnmanagedType.LPWStr)] string source, [MarshalAs(UnmanagedType.IUnknown)] object pMediaControl, [MarshalAs(UnmanagedType.IUnknown)] object pConnection, [MarshalAs(UnmanagedType.Bool)] bool fMarkAsCurrentSession, IntPtr processHandle); [PreserveSig] int RemoveSession([MarshalAs(UnmanagedType.IUnknown)] object pInfo); [PreserveSig] int GetSessions(out uint pdwCount, out IntPtr pppSessions); [PreserveSig] int FindSession([MarshalAs(UnmanagedType.IUnknown)] object pInfo, [MarshalAs(UnmanagedType.IUnknown)] out object ppSession); [PreserveSig] int SetCurrentSession([MarshalAs(UnmanagedType.IUnknown)] object pInfo); [PreserveSig] int SetCurrentNextSession(); [PreserveSig] int Refresh(IntPtr hwnd); [PreserveSig] int Update([MarshalAs(UnmanagedType.Bool)] bool fEnabled, IntPtr hwnd, uint dwPID, [MarshalAs(UnmanagedType.IUnknown)] object pSource); [PreserveSig] int RegisterEventHandler(INowPlayingSessionManagerEventHandler pEventHandler, out NPSMEventRegistrationToken pToken); [PreserveSig] int UnregisterEventHandler(NPSMEventRegistrationToken token); } [ComImport] [Guid("431268cf-7477-4285-950b-6f892a944712")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSession_14393 { [PreserveSig] int get_SessionType(out NowPlayingSessionType pType); [PreserveSig] int get_SourceAppId([MarshalAs(UnmanagedType.LPWStr)] out string pszSrcAppId); [PreserveSig] int get_SourceDeviceId([MarshalAs(UnmanagedType.LPWStr)] out string pszSourceDeviceId); [PreserveSig] int get_RenderDeviceId([MarshalAs(UnmanagedType.LPWStr)] out string pszRenderId); [PreserveSig] int get_HWND(out IntPtr pHwnd); [PreserveSig] int get_PID(out uint pdwPID); [PreserveSig] int get_Info([MarshalAs(UnmanagedType.IUnknown)] out object ppInfo); [PreserveSig] int get_Connection([MarshalAs(UnmanagedType.IUnknown)] out object ppUnknown); [PreserveSig] int ActivateMediaPlaybackDataSource([MarshalAs(UnmanagedType.IUnknown)] out object ppMediaControl); [PreserveSig] int BeginInteractionWithSession([MarshalAs(UnmanagedType.IUnknown)] out object ppSessionInteractionToken); } [ComImport] [Guid("B363BB85-9230-436B-92DC-516E7AD29A85")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSession_10586 { [PreserveSig] int get_SessionType(out NowPlayingSessionType pType); [PreserveSig] int get_SourceAppId([MarshalAs(UnmanagedType.LPWStr)] out string pszSrcAppId); [PreserveSig] int get_SourceDeviceId([MarshalAs(UnmanagedType.LPWStr)] out string pszSourceDeviceId); [PreserveSig] int get_RenderDeviceId([MarshalAs(UnmanagedType.LPWStr)] out string pszRenderId); [PreserveSig] int get_HWND(out IntPtr pHwnd); [PreserveSig] int get_PID(out uint pdwPID); [PreserveSig] int get_Info([MarshalAs(UnmanagedType.IUnknown)] out object ppInfo); [PreserveSig] int get_Connection([MarshalAs(UnmanagedType.IUnknown)] out object ppUnknown); [PreserveSig] int ActivateMediaPlaybackDataSource([MarshalAs(UnmanagedType.IUnknown)] out object ppMediaControl); } [ComImport] [Guid("443dcf9d-ce15-408c-866e-e6d0c434548a")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSessionInfo_19582 { [PreserveSig] int GetInfo(out IntPtr pHwnd, out uint pdwPID, [MarshalAs(UnmanagedType.LPWStr)] out string pszDeviceId); [PreserveSig] int IsEqual([MarshalAs(UnmanagedType.IUnknown)] object pInfo, [MarshalAs(UnmanagedType.Bool)] out bool pfIsEqual); } [ComImport] [Guid("443dcf9d-ce15-408c-866e-e6d0c434548a")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSessionInfo_19041 { [PreserveSig] int GetInfo(out IntPtr pHwnd, out uint pdwPID, [MarshalAs(UnmanagedType.LPWStr)] out string pszDeviceId); [PreserveSig] int IsRunningInContainerOS([MarshalAs(UnmanagedType.Bool)] out bool pfIsInContainer); [PreserveSig] int IsEqual([MarshalAs(UnmanagedType.IUnknown)] object pInfo, [MarshalAs(UnmanagedType.Bool)] out bool pfIsEqual); } [ComImport] [Guid("59EE9066-BDE7-4EE3-8224-731FF9823E49")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSessionInfo_10586 { [PreserveSig] int GetInfo(out IntPtr pHwnd, out uint pdwPID, [MarshalAs(UnmanagedType.LPWStr)] out string pszDeviceId); [PreserveSig] int IsEqual([MarshalAs(UnmanagedType.IUnknown)] object pInfo, [MarshalAs(UnmanagedType.Bool)] out bool pfIsEqual); } [ComImport] [Guid("c4f66b80-df04-4f79-afc2-bee3fc7c46e3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaPlaybackDataSource_20279 { [PreserveSig] int GetMediaPlaybackInfo(out MediaPlaybackInfo pPlaybackInfo); [PreserveSig] int SendMediaPlaybackCommand(MediaPlaybackCommands command); [PreserveSig] int GetMediaObjectInfo(out IPropertyStore ppMediaObjectInfo); [PreserveSig] int GetMediaTimelineProperties(out MediaTimelineProperties pTimelineProperties); [PreserveSig] int RegisterEventHandler(IMediaPlaybackDataChangedEventHandler handler, out NPSMEventRegistrationToken token); [PreserveSig] int UnregisterEventHandler(NPSMEventRegistrationToken token); [PreserveSig] int SendRepeatModeChangeRequest(MediaPlaybackRepeatMode requestedRepeatMode); [PreserveSig] int SendPlaybackRateChangeRequest(double requestedPlaybackRate); [PreserveSig] int SendShuffleEnabledChangeRequest([MarshalAs(UnmanagedType.Bool)] bool requestedShuffle); [PreserveSig] int SendPlaybackPositionChangeRequest(long requestedPlaybackPosition); [PreserveSig] int GetParentApplicationId([MarshalAs(UnmanagedType.HString)] out string value); [PreserveSig] int GetMediaObjectInfoAsSet(Guid guid, [MarshalAs(UnmanagedType.IUnknown)] out object ppUnknown); [PreserveSig] int GetIsRunningInGuestContainer([MarshalAs(UnmanagedType.Bool)] bool runningInContainer); } [ComImport] [Guid("0F4521BE-A0B8-4116-B3B1-BFECEBAEEBE6")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaPlaybackDataSource_10586 { [PreserveSig] int GetMediaPlaybackInfo(out MediaPlaybackInfo pPlaybackInfo); [PreserveSig] int SendMediaPlaybackCommand(MediaPlaybackCommands command); [PreserveSig] int GetMediaObjectInfo(out IPropertyStore ppMediaObjectInfo); [PreserveSig] int GetMediaTimelineProperties(out MediaTimelineProperties pTimelineProperties); [PreserveSig] int RegisterEventHandler(IMediaPlaybackDataChangedEventHandler handler, out NPSMEventRegistrationToken token); [PreserveSig] int UnregisterEventHandler(NPSMEventRegistrationToken token); [PreserveSig] int SendRepeatModeChangeRequest(MediaPlaybackRepeatMode requestedRepeatMode); [PreserveSig] int SendPlaybackRateChangeRequest(double requestedPlaybackRate); [PreserveSig] int SendShuffleEnabledChangeRequest([MarshalAs(UnmanagedType.Bool)] bool requestedShuffle); [PreserveSig] int SendPlaybackPositionChangeRequest(long requestedPlaybackPosition); [PreserveSig] int GetParentApplicationId([MarshalAs(UnmanagedType.HString)] out string value); } [ComImport] [Guid("d22f448d-39dc-415f-8325-91eddf0d5264")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaPlaybackDataChangedEventHandler { [PreserveSig] void OnMediaPlaybackDataChangedEvent([MarshalAs(UnmanagedType.IUnknown)] object source, MediaPlaybackDataChangedEvent dataChangedEvent); } [ComImport] [Guid("d25f31a2-8cae-4058-967e-8a4497e1cdbc")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface INowPlayingSessionManagerEventHandler { [PreserveSig] void OnChange(NowPlayingSessionManagerNotificationType notificationType, [MarshalAs(UnmanagedType.IUnknown)] object pInfo, [MarshalAs(UnmanagedType.LPWStr)] string pszSource); } [ComImport] [Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPropertyStore { int GetCount(out uint cProps); int GetAt(uint iProp, out PROPERTYKEY pkey); int GetValue(ref PROPERTYKEY key, out PROPVARIANT pv); int SetValue(ref PROPERTYKEY key, ref PROPVARIANT propvar); int Commit(); } internal static Guid CLSID_NowPlayingSessionManager = new Guid("BCBB9860-C012-4AD7-A938-6E337AE6ABA5"); } internal struct OSVersion { private readonly ushort major; private readonly ushort minor; private readonly ushort build; private readonly ushort revision; public ushort Major => major; public ushort Minor => minor; public ushort Build => build; public ushort Revision => revision; public OSVersion(ushort major, ushort minor, ushort build, ushort revision) { this.major = major; this.minor = minor; this.build = build; this.revision = revision; } } internal class Helpers { internal static OSVersion GetOSVersion() { NativeMethods.RtlGetDeviceFamilyInfoEnum(out var pullUAPInfo, out var _, out var _); return new OSVersion((ushort)((pullUAPInfo & 0xFFFF000000000000uL) >> 48), (ushort)((pullUAPInfo & 0xFFFF00000000L) >> 32), (ushort)((pullUAPInfo & 0xFFFF0000u) >> 16), (ushort)(pullUAPInfo & 0xFFFF)); } } internal static class NativeMethods { [DllImport("ole32.dll", SetLastError = true)] internal static extern int CoCreateInstance(ref Guid clsid, [MarshalAs(UnmanagedType.IUnknown)] object inner, uint context, ref Guid uuid, [MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject); [DllImport("ole32.dll")] internal static extern int PropVariantClear(ref PROPVARIANT propvar); [DllImport("ntdll.dll")] internal static extern void RtlGetDeviceFamilyInfoEnum(out ulong pullUAPInfo, out uint pulDeviceFamily, out uint pulDeviceForm); } internal struct PROPERTYKEY { public Guid fmtid; public uint pid; } internal enum VARTYPE : short { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_PTR = 26, VT_SAFEARRAY = 27, VT_CARRAY = 28, VT_USERDEFINED = 29, VT_LPSTR = 30, VT_LPWSTR = 31, VT_RECORD = 36, VT_INT_PTR = 37, VT_UINT_PTR = 38, VT_FILETIME = 64, VT_BLOB = 65, VT_STREAM = 66, VT_STORAGE = 67, VT_STREAMED_OBJECT = 68, VT_STORED_OBJECT = 69, VT_BLOB_OBJECT = 70, VT_CF = 71, VT_CLSID = 72, VT_VERSIONED_STREAM = 73, VT_BSTR_BLOB = 4095, VT_VECTOR = 4096, VT_ARRAY = 8192, VT_BYREF = 16384, VT_RESERVED = short.MinValue, VT_ILLEGAL = -1, VT_ILLEGALMASKED = 4095, VT_TYPEMASK = 4095 } internal struct CAC { internal uint cElems; internal IntPtr pElems; } internal struct CAUB { internal uint cElems; internal IntPtr pElems; } internal struct CAI { internal uint cElems; internal IntPtr pElems; } internal struct CAUI { internal uint cElems; internal IntPtr pElems; } internal struct CAL { internal uint cElems; internal IntPtr pElems; } internal struct CAUL { internal uint cElems; internal IntPtr pElems; } internal struct CAFLT { internal uint cElems; internal IntPtr pElems; } internal struct CADBL { internal uint cElems; internal IntPtr pElems; } internal struct CACY { internal uint cElems; internal IntPtr pElems; } internal struct CADATE { internal uint cElems; internal IntPtr pElems; } internal struct CABSTR { internal uint cElems; internal IntPtr pElems; } internal struct CABSTRBLOB { internal uint cElems; internal IntPtr pElems; } internal struct CABOOL { internal uint cElems; internal IntPtr pElems; } internal struct CASCODE { internal uint cElems; internal IntPtr pElems; } internal struct CAPROPVARIANT { internal uint cElems; internal IntPtr pElems; } internal struct CAH { internal uint cElems; internal IntPtr pElems; } internal struct CAUH { internal uint cElems; internal IntPtr pElems; } internal struct CALPSTR { internal uint cElems; internal IntPtr pElems; } internal struct CALPWSTR { internal uint cElems; internal IntPtr pElems; } internal struct CAFILETIME { internal uint cElems; internal IntPtr pElems; } internal struct CACLIPDATA { internal uint cElems; internal IntPtr pElems; } internal struct CACLSID { internal uint cElems; internal IntPtr pElems; } internal struct CLIPDATA { internal uint cbSize; internal int ulClipFmt; internal IntPtr pClipData; } internal struct CY { public uint Lo; public int Hi; } internal struct BSTRBLOB { public uint cbSize; public IntPtr pData; } internal struct BLOB { public uint cbSize; public IntPtr pBlobData; } internal struct CArray { public uint cElems; public IntPtr pElems; } [StructLayout(LayoutKind.Explicit)] internal struct PROPVARIANTUNION { [FieldOffset(0)] internal sbyte cVal; [FieldOffset(0)] internal byte bVal; [FieldOffset(0)] internal short iVal; [FieldOffset(0)] internal ushort uiVal; [FieldOffset(0)] internal int lVal; [FieldOffset(0)] internal uint ulVal; [FieldOffset(0)] internal int intVal; [FieldOffset(0)] internal uint uintVal; [FieldOffset(0)] internal long hVal; [FieldOffset(0)] internal ulong uhVal; [FieldOffset(0)] internal float fltVal; [FieldOffset(0)] internal double dblVal; [FieldOffset(0)] internal short boolVal; [FieldOffset(0)] internal int scode; [FieldOffset(0)] internal CY cyVal; [FieldOffset(0)] internal double date; [FieldOffset(0)] internal FILETIME filetime; [FieldOffset(0)] internal IntPtr puuid; [FieldOffset(0)] internal IntPtr pclipdata; [FieldOffset(0)] internal IntPtr bstrVal; [FieldOffset(0)] internal BSTRBLOB bstrblobVal; [FieldOffset(0)] internal BLOB blob; [FieldOffset(0)] internal IntPtr pszVal; [FieldOffset(0)] internal IntPtr pwszVal; [FieldOffset(0)] internal IntPtr punkVal; [FieldOffset(0)] internal IntPtr pdispVal; [FieldOffset(0)] internal IntPtr pStream; [FieldOffset(0)] internal IntPtr pStorage; [FieldOffset(0)] internal IntPtr pVersionedStream; [FieldOffset(0)] internal IntPtr parray; [FieldOffset(0)] internal CAC cac; [FieldOffset(0)] internal CAUB caub; [FieldOffset(0)] internal CAI cai; [FieldOffset(0)] internal CAUI caui; [FieldOffset(0)] internal CAL cal; [FieldOffset(0)] internal CAUL caul; [FieldOffset(0)] internal CAH cah; [FieldOffset(0)] internal CAUH cauh; [FieldOffset(0)] internal CAFLT caflt; [FieldOffset(0)] internal CADBL cadbl; [FieldOffset(0)] internal CABOOL cabool; [FieldOffset(0)] internal CASCODE cascode; [FieldOffset(0)] internal CACY cacy; [FieldOffset(0)] internal CADATE cadate; [FieldOffset(0)] internal CAFILETIME cafiletime; [FieldOffset(0)] internal CACLSID cauuid; [FieldOffset(0)] internal CACLIPDATA caclipdata; [FieldOffset(0)] internal CABSTR cabstr; [FieldOffset(0)] internal CABSTRBLOB cabstrblob; [FieldOffset(0)] internal CALPSTR calpstr; [FieldOffset(0)] internal CALPWSTR calpwstr; [FieldOffset(0)] internal CAPROPVARIANT capropvar; [FieldOffset(0)] internal CArray cArray; [FieldOffset(0)] internal IntPtr pcVal; [FieldOffset(0)] internal IntPtr pbVal; [FieldOffset(0)] internal IntPtr piVal; [FieldOffset(0)] internal IntPtr puiVal; [FieldOffset(0)] internal IntPtr plVal; [FieldOffset(0)] internal IntPtr pulVal; [FieldOffset(0)] internal IntPtr pintVal; [FieldOffset(0)] internal IntPtr puintVal; [FieldOffset(0)] internal IntPtr pfltVal; [FieldOffset(0)] internal IntPtr pdblVal; [FieldOffset(0)] internal IntPtr pboolVal; [FieldOffset(0)] internal IntPtr pdecVal; [FieldOffset(0)] internal IntPtr pscode; [FieldOffset(0)] internal IntPtr pcyVal; [FieldOffset(0)] internal IntPtr pdate; [FieldOffset(0)] internal IntPtr pbstrVal; [FieldOffset(0)] internal IntPtr ppunkVal; [FieldOffset(0)] internal IntPtr ppdispVal; [FieldOffset(0)] internal IntPtr pparray; [FieldOffset(0)] internal IntPtr pvarVal; } internal struct PROPVARIANT { internal VARTYPE vt; internal ushort wReserved1; internal ushort wReserved2; internal ushort wReserved3; internal PROPVARIANTUNION union; } }