windows-nt/Source/XPSP1/NT/shell/ext/media/mediaprop.h
2020-09-26 16:20:57 +08:00

293 lines
14 KiB
C++

#ifndef __MEDIAPROP_H__
#define __MEDIAPROP_H__
// These should be moved into some central location
#define PIDISI_CX 0x00000003L // VT_UI4
#define PIDISI_CY 0x00000004L // VT_UI4
#define PIDISI_FRAME_COUNT 0x0000000CL // VT_LPWSTR
#define PIDISI_DIMENSIONS 0x0000000DL // VT_LPWSTR
#define IsEqualSCID(a, b) (((a).pid == (b).pid) && IsEqualIID((a).fmtid, (b).fmtid) )
typedef struct
{
const SHCOLUMNID *pscid;
LPCWSTR pszName; // Propstg string name for this property.
VARTYPE vt; // Note that the type of a given FMTID/PID pair is a known, fixed value
BOOL bEnumerate; // We don't want to enumerate alias properties.
} COLMAP;
#define DEFINE_SCID(name, fmtid, pid) const SHCOLUMNID name = { fmtid, pid }
DEFINE_SCID(SCID_Author, PSGUID_SUMMARYINFORMATION, PIDSI_AUTHOR);
DEFINE_SCID(SCID_Title, PSGUID_SUMMARYINFORMATION, PIDSI_TITLE);
DEFINE_SCID(SCID_Comment, PSGUID_SUMMARYINFORMATION, PIDSI_COMMENTS);
DEFINE_SCID(SCID_Category, PSGUID_DOCUMENTSUMMARYINFORMATION, PIDDSI_CATEGORY);
DEFINE_SCID(SCID_MUSIC_Artist, PSGUID_MUSIC, PIDSI_ARTIST);
DEFINE_SCID(SCID_MUSIC_Album, PSGUID_MUSIC, PIDSI_ALBUM);
DEFINE_SCID(SCID_MUSIC_Year, PSGUID_MUSIC, PIDSI_YEAR);
DEFINE_SCID(SCID_MUSIC_Track, PSGUID_MUSIC, PIDSI_TRACK);
DEFINE_SCID(SCID_MUSIC_Genre, PSGUID_MUSIC, PIDSI_GENRE);
DEFINE_SCID(SCID_MUSIC_Lyrics, PSGUID_MUSIC, PIDSI_LYRICS);
DEFINE_SCID(SCID_DRM_Protected, PSGUID_DRM, PIDDRSI_PROTECTED);
DEFINE_SCID(SCID_DRM_Description, PSGUID_DRM, PIDDRSI_DESCRIPTION);
DEFINE_SCID(SCID_DRM_PlayCount, PSGUID_DRM, PIDDRSI_PLAYCOUNT);
DEFINE_SCID(SCID_DRM_PlayStarts, PSGUID_DRM, PIDDRSI_PLAYSTARTS);
DEFINE_SCID(SCID_DRM_PlayExpires, PSGUID_DRM, PIDDRSI_PLAYEXPIRES);
DEFINE_SCID(SCID_VIDEO_StreamName, PSGUID_VIDEO, PIDVSI_STREAM_NAME);
DEFINE_SCID(SCID_VIDEO_FrameRate, PSGUID_VIDEO, PIDVSI_FRAME_RATE);
DEFINE_SCID(SCID_VIDEO_Bitrate, PSGUID_VIDEO, PIDVSI_DATA_RATE);
DEFINE_SCID(SCID_VIDEO_SampleSize, PSGUID_VIDEO, PIDVSI_SAMPLE_SIZE);
DEFINE_SCID(SCID_VIDEO_Compression, PSGUID_VIDEO, PIDVSI_COMPRESSION);
DEFINE_SCID(SCID_AUDIO_Format, PSGUID_AUDIO, PIDASI_FORMAT);
DEFINE_SCID(SCID_AUDIO_Duration, PSGUID_AUDIO, PIDASI_TIMELENGTH); //100ns units, not milliseconds. VT_UI8, not VT_UI4
DEFINE_SCID(SCID_AUDIO_Bitrate, PSGUID_AUDIO, PIDASI_AVG_DATA_RATE);
DEFINE_SCID(SCID_AUDIO_SampleRate, PSGUID_AUDIO, PIDASI_SAMPLE_RATE);
DEFINE_SCID(SCID_AUDIO_SampleSize, PSGUID_AUDIO, PIDASI_SAMPLE_SIZE);
DEFINE_SCID(SCID_AUDIO_ChannelCount, PSGUID_AUDIO, PIDASI_CHANNEL_COUNT);
DEFINE_SCID(SCID_IMAGE_Width, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_CX);
DEFINE_SCID(SCID_IMAGE_Height, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_CY);
DEFINE_SCID(SCID_IMAGE_Dimensions, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_DIMENSIONS);
DEFINE_SCID(SCID_IMAGE_FrameCount, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_FRAME_COUNT);
// Docsummary props
const COLMAP g_CM_Category = { &SCID_Category, L"Category", VT_LPWSTR, FALSE}; // Alias property of Genre
// SummaryProps
const COLMAP g_CM_Author = { &SCID_Author, L"Author", VT_LPWSTR, FALSE}; // Alias property of Artist
const COLMAP g_CM_Title = { &SCID_Title, L"Title", VT_LPWSTR, TRUE};
const COLMAP g_CM_Comment = { &SCID_Comment, L"Description", VT_LPWSTR, TRUE};
// Music props
const COLMAP g_CM_Artist = { &SCID_MUSIC_Artist, L"Author", VT_LPWSTR, TRUE};
const COLMAP g_CM_Album = { &SCID_MUSIC_Album, L"AlbumTitle", VT_LPWSTR, TRUE};
const COLMAP g_CM_Year = { &SCID_MUSIC_Year, L"Year", VT_LPWSTR, TRUE};
const COLMAP g_CM_Track = { &SCID_MUSIC_Track, L"Track", VT_UI4, TRUE}; // NB: This is exposed as a WMT_ATTRTYPE_STRING for mp3. We may need to change it.
const COLMAP g_CM_Genre = { &SCID_MUSIC_Genre, L"Genre", VT_LPWSTR, TRUE};
const COLMAP g_CM_Lyrics = { &SCID_MUSIC_Lyrics, L"Lyrics", VT_LPWSTR, TRUE};
// Audio props
const COLMAP g_CM_Format = { &SCID_AUDIO_Format, L"Format", VT_LPWSTR, TRUE};
const COLMAP g_CM_Duration = { &SCID_AUDIO_Duration, L"Duration", VT_UI8, TRUE};
const COLMAP g_CM_Bitrate = { &SCID_AUDIO_Bitrate, L"Bitrate", VT_UI4, TRUE};
const COLMAP g_CM_SampleRate = { &SCID_AUDIO_SampleRate, L"SampleRate", VT_UI4, TRUE}; // samples per sec
const COLMAP g_CM_SampleSize = { &SCID_AUDIO_SampleSize, L"SampleSize", VT_UI4, TRUE};
const COLMAP g_CM_ChannelCount ={ &SCID_AUDIO_ChannelCount, L"ChannelCount", VT_UI4, TRUE};
// Video props
const COLMAP g_CM_StreamName = { &SCID_VIDEO_StreamName, L"StreamName", VT_LPWSTR, TRUE};
const COLMAP g_CM_FrameRate = { &SCID_VIDEO_FrameRate, L"FrameRate", VT_UI4, TRUE};
const COLMAP g_CM_SampleSizeV = { &SCID_VIDEO_SampleSize, L"SampleSize", VT_UI4, TRUE}; // different from audio sample simple
const COLMAP g_CM_BitrateV = { &SCID_VIDEO_Bitrate, L"Bitrate", VT_UI4, TRUE}; // different from audio bitrate
const COLMAP g_CM_Compression = { &SCID_VIDEO_Compression, L"Compression", VT_LPWSTR, TRUE};
// Image props
const COLMAP g_CM_Width = { &SCID_IMAGE_Width, L"Width", VT_UI4, TRUE};
const COLMAP g_CM_Height = { &SCID_IMAGE_Height, L"Height", VT_UI4, TRUE};
const COLMAP g_CM_Dimensions = { &SCID_IMAGE_Dimensions, L"Dimensions", VT_LPWSTR, TRUE};
const COLMAP g_CM_FrameCount = { &SCID_IMAGE_FrameCount, L"FrameCount", VT_UI4, TRUE};
// DRM props
const COLMAP g_CM_Protected = { &SCID_DRM_Protected, L"Protected", VT_BOOL, TRUE};
const COLMAP g_CM_DRMDescription={&SCID_DRM_Description, L"DRMDescription", VT_LPWSTR, TRUE};
const COLMAP g_CM_PlayCount = { &SCID_DRM_PlayCount, L"PlayCount", VT_UI4, TRUE};
const COLMAP g_CM_PlayStarts = { &SCID_DRM_PlayStarts, L"PlayStarts", VT_FILETIME,TRUE};
const COLMAP g_CM_PlayExpires = { &SCID_DRM_PlayExpires, L"PlayExpires", VT_FILETIME,TRUE};
// Describes each of the property sets an IPropertySetStorage uses.
typedef struct {
GUID fmtid; // fmtid for this property set
const COLMAP **pcmProps; // List of all properties that exist in this set
ULONG cNumProps;
} PROPSET_INFO;
enum MUSICPROPSTG_AUTHLEVEL
{
AUTH = 0, NON_AUTH
};
enum PROPSTG_STATE
{
CLOSED = 0,
OPENED_SHARED,
OPENED_DENYREAD,
OPENED_DENYWRITE,
OPENED_DENYALL
};
class CMediaPropSetStg;
// Base property storage implementation.
class CMediaPropStorage : public IPropertyStorage, IQueryPropertyFlags
{
public:
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
//IPropertyStorage
STDMETHODIMP ReadMultiple (ULONG cpspec, const PROPSPEC rgpspec[], PROPVARIANT rgvar[]);
STDMETHODIMP WriteMultiple (ULONG cpspec, PROPSPEC const rgpspec[], const PROPVARIANT rgvar[], PROPID propidNameFirst);
STDMETHODIMP DeleteMultiple(ULONG cpspec, PROPSPEC const rgpspec[]);
STDMETHODIMP ReadPropertyNames (ULONG cpspec, PROPID const rgpropid[], LPWSTR rglpwstrName[]);
STDMETHODIMP WritePropertyNames (ULONG cpspec, PROPID const rgpropid[], LPWSTR const rglpwstrName[]);
STDMETHODIMP DeletePropertyNames(ULONG cpspec, PROPID const rgpropid[]);
STDMETHODIMP SetClass(REFCLSID clsid);
STDMETHODIMP Commit(DWORD grfCommitFlags);
STDMETHODIMP Revert();
STDMETHODIMP Enum(IEnumSTATPROPSTG **ppenum);
STDMETHODIMP Stat(STATPROPSETSTG *pstatpropstg);
STDMETHODIMP SetTimes(FILETIME const *pctime, FILETIME const *patime, FILETIME const *pmtime);
// IQueryPropertyFlags
STDMETHODIMP GetFlags(const PROPSPEC *pspec, SHCOLSTATEF *pcsFlags);
CMediaPropStorage(CMediaPropSetStg *ppssParent, CMediaPropStorage *ppsAuthority, REFFMTID fmtid, const COLMAP **ppcmPropInfo, DWORD cNumProps, DWORD dwMode, CRITICAL_SECTION *pcs);
HRESULT SetProperty(PROPSPEC *ppspec, PROPVARIANT *pvar);//called by the parent to set the initial data
HRESULT QuickLookup(PROPSPEC *ppspec, PROPVARIANT **ppvar);
private:
~CMediaPropStorage();
HRESULT Open(DWORD dwShareMode, DWORD dwOpenMode, IPropertyStorage **ppPropStg);
void _ResetPropStorage(); //Resets the Propstorage to a known empty state
HRESULT CopyPropStorageData(PROPVARIANT *pvarProps);
void OnClose();
HRESULT DoCommit(DWORD grfCommitFlags, FILETIME *ftFlushTime, PROPVARIANT *pVarProps, BOOL *pbDirtyFlags);//flush the data to the parent
HRESULT LookupProp(const PROPSPEC *pspec, const COLMAP **ppcmName, PROPVARIANT **ppvarReadData, PROPVARIANT **ppvarWriteData, BOOL **ppbDirty, BOOL bPropertySet);
BOOL IsDirectMode();
BOOL IsSpecialProperty(const PROPSPEC *pspec);
HRESULT _EnsureSlowPropertiesLoaded();
virtual BOOL _IsSlowProperty(const COLMAP *pPInfo);
LONG _cRef;
COLMAP const **_ppcmPropInfo;
PROPVARIANT *_pvarProps, *_pvarChangedProps;
PROPVARIANT _varCodePage;
BOOL *_pbDirtyFlags;
ULONG _cNumProps;
MUSICPROPSTG_AUTHLEVEL _authLevel;
CMediaPropStorage *_ppsAuthority;
CMediaPropSetStg *_ppssParent;
FMTID _fmtid;
FILETIME _ftLastCommit;
PROPSTG_STATE _state;
DWORD _dwMode;
BOOL _bRetrievedSlowProperties;
HRESULT _hrSlowProps;
CRITICAL_SECTION *_pcs; // The parent storage set's critical section.
friend class CMediaPropSetStg;
};
// Base property set storage implementation.
class CMediaPropSetStg : public IPersistFile, IPropertySetStorage, IWMReaderCallback
{
public:
CMediaPropSetStg();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IPersist
STDMETHODIMP GetClassID(CLSID *pClassID);
// IPersistFile
STDMETHODIMP IsDirty(void);
STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode);
STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember);
STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName);
STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName);
// IPropertySetStorage
STDMETHODIMP Create(REFFMTID fmtid, const CLSID * pclsid, DWORD grfFlags, DWORD grfMode, IPropertyStorage** ppPropStg);
STDMETHODIMP Open(REFFMTID fmtid, DWORD grfMode, IPropertyStorage** ppPropStg);
STDMETHODIMP Delete(REFFMTID fmtid);
STDMETHODIMP Enum(IEnumSTATPROPSETSTG** ppenum);
// IWMReaderCallBack
STDMETHODIMP OnStatus(WMT_STATUS Staus, HRESULT hr, WMT_ATTR_DATATYPE dwType, BYTE *pValue, void *pvContext);
STDMETHODIMP OnSample(DWORD dwOutputNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void* pcontext);
virtual HRESULT FlushChanges(REFFMTID fmtid, LONG cNumProps, const COLMAP **pcmapInfo, PROPVARIANT *pVarProps, BOOL *pbDirtyFlags);
HRESULT Init();
virtual BOOL _IsSlowProperty(const COLMAP *pPInfo);
protected:
HRESULT _ResolveFMTID(REFFMTID fmtid, CMediaPropStorage **ppps);
HRESULT _PopulateProperty(const COLMAP *pPInfo, PROPVARIANT *pvar);
BOOL _bIsWritable;
WCHAR _wszFile[MAX_PATH];
BOOL _bHasBeenPopulated;
BOOL _bSlowPropertiesExtracted;
HRESULT _hrSlowProps;
HRESULT _hrPopulated;
UINT _cPropertyStorages;
CMediaPropStorage **_propStg;
const PROPSET_INFO *_pPropStgInfo; // Indicates which propstorages to create, etc...
HANDLE _hFileOpenEvent;
~CMediaPropSetStg();
private:
HRESULT _ResetPropertySet();
HRESULT _CreatePropertyStorages();
virtual HRESULT _PopulatePropertySet();
virtual HRESULT _PopulateSlowProperties();
virtual HRESULT _PreCheck();
LONG _cRef;
DWORD _dwMode;
// This property handler needes to operate in a FTA because of the content indexing service. If
// we're created in an STA, it turns out they can't properly impersonate a user across apartment
// boundaries.
// This is a critical section we use to provide very "simple" synchronized access to our internal
// members. Basically, we just wrap every public interface member in Enter/Leave. The WMSDK
// doesn't throw any exceptions, so we don't need any try-finally's (and hopefully the AVI and WAV
// code doesn't either).
// All public interface members in the CMediaPropStorage class are also protected by this same
// critical section.
CRITICAL_SECTION _cs;
friend class CMediaPropStorage;
};
// Class used to enumerate through all COLMAPs for the properties supported by a propertysetstorage //
// Used internally by a PSS when populating properties.
class CEnumAllProps
{
public:
CEnumAllProps(const PROPSET_INFO *pPropSets, UINT cPropSets);
const COLMAP *Next();
private:
const PROPSET_INFO *_pPropSets;
UINT _cPropSets;
UINT _iPropSetPos;
UINT _iPropPos;
};
#endif //__MEDIAPROP_H__