Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
11 KiB

  1. #include "pch.h"
  2. #include "thisdll.h"
  3. #include "wmwrap.h"
  4. #include "MediaProp.h"
  5. #include "ids.h"
  6. // declr property set storage enum
  7. class CMediaPropSetEnum : public IEnumSTATPROPSETSTG
  8. {
  9. public:
  10. CMediaPropSetEnum(const PROPSET_INFO *propsets, ULONG cpropset, ULONG pos);
  11. // IUnknown
  12. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  13. STDMETHODIMP_(ULONG) AddRef();
  14. STDMETHODIMP_(ULONG) Release();
  15. // IEnumSTATPROPSETSTG
  16. STDMETHODIMP Next(ULONG celt, STATPROPSETSTG *rgelt, ULONG *pceltFetched);
  17. STDMETHODIMP Skip(ULONG celt);
  18. STDMETHODIMP Reset();
  19. STDMETHODIMP Clone(IEnumSTATPROPSETSTG **ppenum);
  20. private:
  21. ~CMediaPropSetEnum();
  22. LONG _cRef;
  23. ULONG _pos, _size;
  24. const PROPSET_INFO *_propsets;
  25. };
  26. // property set storage enum
  27. STDMETHODIMP_(ULONG) CMediaPropSetEnum::AddRef()
  28. {
  29. return InterlockedIncrement(&_cRef);
  30. }
  31. STDMETHODIMP_(ULONG) CMediaPropSetEnum::Release()
  32. {
  33. if (InterlockedDecrement(&_cRef))
  34. return _cRef;
  35. delete this;
  36. return 0;
  37. }
  38. STDMETHODIMP CMediaPropSetEnum::QueryInterface(REFIID riid, void **ppv)
  39. {
  40. static const QITAB qit[] = {
  41. QITABENT(CMediaPropSetEnum, IEnumSTATPROPSETSTG),
  42. { 0 },
  43. };
  44. return QISearch(this, qit, riid, ppv);
  45. }
  46. // IEnum
  47. STDMETHODIMP CMediaPropSetEnum::Next(ULONG celt, STATPROPSETSTG *rgelt, ULONG *pceltFetched)
  48. {
  49. ULONG cFetched = 0;
  50. for (ULONG i = 0; i < celt && _pos < _size; i++)
  51. {
  52. ZeroMemory(&rgelt[i], sizeof(STATPROPSETSTG));
  53. rgelt[i].fmtid = _propsets[_pos].fmtid;
  54. _pos++;
  55. cFetched++;
  56. }
  57. if (pceltFetched)
  58. *pceltFetched = cFetched;
  59. return cFetched == celt ? S_OK : S_FALSE;
  60. }
  61. STDMETHODIMP CMediaPropSetEnum::Skip(ULONG celt)
  62. {
  63. HRESULT hr;
  64. if (_pos + celt > _size)
  65. {
  66. hr = S_FALSE;
  67. _pos = _size;
  68. }
  69. else
  70. {
  71. hr = S_OK;
  72. _pos += celt;
  73. }
  74. return hr;
  75. }
  76. STDMETHODIMP CMediaPropSetEnum::Reset()
  77. {
  78. _pos = 0;
  79. return S_OK;
  80. }
  81. STDMETHODIMP CMediaPropSetEnum::Clone(IEnumSTATPROPSETSTG **ppenum)
  82. {
  83. HRESULT hr;
  84. CMediaPropSetEnum *penum = new CMediaPropSetEnum(_propsets, _size, _pos);
  85. if (penum)
  86. {
  87. hr = penum->QueryInterface(IID_PPV_ARG(IEnumSTATPROPSETSTG, ppenum));
  88. penum->Release();
  89. }
  90. else
  91. hr = STG_E_INSUFFICIENTMEMORY;
  92. return hr;
  93. }
  94. CMediaPropSetEnum::CMediaPropSetEnum(const PROPSET_INFO *propsets, ULONG cpropsets, ULONG pos) :
  95. _cRef(1), _propsets(propsets), _size(cpropsets), _pos(pos)
  96. {
  97. DllAddRef();
  98. }
  99. CMediaPropSetEnum::~CMediaPropSetEnum()
  100. {
  101. DllRelease();
  102. }
  103. HRESULT CMediaPropSetStg::_PopulateSlowProperties()
  104. {
  105. return S_OK;
  106. }
  107. HRESULT CMediaPropSetStg::_PopulateProperty(const COLMAP *pPInfo, PROPVARIANT *pvar)
  108. {
  109. CMediaPropStorage *pps;
  110. HRESULT hr = _ResolveFMTID(pPInfo->pscid->fmtid, &pps);
  111. if (SUCCEEDED(hr))
  112. {
  113. PROPSPEC spec;
  114. spec.ulKind = PRSPEC_PROPID;
  115. spec.propid = pPInfo->pscid->pid;
  116. hr = pps->SetProperty(&spec, pvar);
  117. }
  118. PropVariantClear(pvar);
  119. return hr;
  120. }
  121. // Internal enumeration class used when populating properties.
  122. CEnumAllProps::CEnumAllProps(const PROPSET_INFO *pPropSets, UINT cPropSets) : _pPropSets(pPropSets), _cPropSets(cPropSets), _iPropSetPos(0), _iPropPos(0)
  123. {
  124. }
  125. const COLMAP *CEnumAllProps::Next()
  126. {
  127. const COLMAP *pcmReturn = NULL;
  128. while (_iPropSetPos < _cPropSets)
  129. {
  130. if (_iPropPos < _pPropSets[_iPropSetPos].cNumProps)
  131. {
  132. // Go to next property.
  133. pcmReturn = _pPropSets[_iPropSetPos].pcmProps[_iPropPos];
  134. _iPropPos++;
  135. break;
  136. }
  137. else
  138. {
  139. // Go to next property set.
  140. _iPropSetPos++;
  141. _iPropPos = 0;
  142. }
  143. }
  144. return pcmReturn;
  145. }
  146. // Base media property set storage
  147. STDMETHODIMP_(ULONG) CMediaPropSetStg::AddRef()
  148. {
  149. return InterlockedIncrement(&_cRef);
  150. }
  151. STDMETHODIMP_(ULONG) CMediaPropSetStg::Release()
  152. {
  153. if (InterlockedDecrement(&_cRef))
  154. return _cRef;
  155. delete this;
  156. return 0;
  157. }
  158. STDMETHODIMP CMediaPropSetStg::QueryInterface(REFIID riid, void **ppv)
  159. {
  160. static const QITAB qit[] = {
  161. QITABENT(CMediaPropSetStg, IPropertySetStorage),
  162. QITABENT(CMediaPropSetStg, IPersistFile),
  163. QITABENTMULTI(CMediaPropSetStg, IPersist, IPersistFile),
  164. QITABENT(CMediaPropSetStg, IWMReaderCallback),
  165. { 0 },
  166. };
  167. return QISearch(this, qit, riid, ppv);
  168. }
  169. // IPersist
  170. STDMETHODIMP CMediaPropSetStg::GetClassID(CLSID *pClassID)
  171. {
  172. return E_NOTIMPL;
  173. }
  174. // IPersistFile
  175. STDMETHODIMP CMediaPropSetStg::IsDirty(void)
  176. {
  177. return S_FALSE;// sniff for uncommitted changed?
  178. }
  179. #define STGM_OPENMODE (STGM_READ | STGM_WRITE | STGM_READWRITE)
  180. // Any stuff we have to do at 'load time'
  181. HRESULT CMediaPropSetStg::_PreCheck()
  182. {
  183. return S_OK;
  184. }
  185. STDMETHODIMP CMediaPropSetStg::Load(LPCOLESTR pszFileName, DWORD dwMode)
  186. {
  187. // Allow Load only on existing files.
  188. if (dwMode & (STGM_CREATE | STGM_CONVERT | STGM_FAILIFTHERE))
  189. return STG_E_INVALIDFLAG;
  190. EnterCriticalSection(&_cs);
  191. DWORD dwFlags = dwMode & STGM_OPENMODE;
  192. _dwMode = dwMode;
  193. StrCpyNW(_wszFile, pszFileName, ARRAYSIZE(_wszFile));
  194. _bHasBeenPopulated = FALSE;
  195. _bSlowPropertiesExtracted = FALSE;
  196. _hrPopulated = S_OK;
  197. _bIsWritable = (dwFlags & (STGM_WRITE | STGM_READWRITE));
  198. _ResetPropertySet();
  199. HRESULT hr = _PreCheck();
  200. LeaveCriticalSection(&_cs);
  201. return hr;
  202. }
  203. STDMETHODIMP CMediaPropSetStg::Save(LPCOLESTR pszFileName, BOOL fRemember)
  204. {
  205. return E_NOTIMPL;
  206. }
  207. STDMETHODIMP CMediaPropSetStg::SaveCompleted(LPCOLESTR pszFileName)
  208. {
  209. return E_NOTIMPL;
  210. }
  211. STDMETHODIMP CMediaPropSetStg::GetCurFile(LPOLESTR *ppszFileName)
  212. {
  213. EnterCriticalSection(&_cs);
  214. HRESULT hr = SHStrDupW(_wszFile, ppszFileName);
  215. LeaveCriticalSection(&_cs);
  216. return hr;
  217. }
  218. // IPropertySetStorage methods
  219. STDMETHODIMP CMediaPropSetStg::Create(REFFMTID fmtid, const CLSID *pclsid, DWORD grfFlags, DWORD grfMode, IPropertyStorage** ppPropStg)
  220. {
  221. return E_NOTIMPL;
  222. }
  223. STDMETHODIMP CMediaPropSetStg::Open(REFFMTID fmtid, DWORD grfMode, IPropertyStorage** ppPropStg)
  224. {
  225. EnterCriticalSection(&_cs);
  226. HRESULT hr = _PopulatePropertySet();
  227. if (SUCCEEDED(hr))
  228. {
  229. DWORD dwPssMode = _dwMode & STGM_OPENMODE;
  230. switch (grfMode & STGM_OPENMODE)
  231. {
  232. case STGM_READ:
  233. break;
  234. case STGM_WRITE:
  235. if (!_bIsWritable || (dwPssMode == STGM_READ))
  236. hr = E_FAIL;
  237. break;
  238. case STGM_READWRITE:
  239. if (!_bIsWritable || (dwPssMode != STGM_READWRITE))
  240. hr = E_FAIL;
  241. break;
  242. default:
  243. hr = E_INVALIDARG;
  244. }
  245. if (SUCCEEDED(hr))
  246. {
  247. CMediaPropStorage *pps;
  248. hr = _ResolveFMTID(fmtid, &pps);
  249. if (SUCCEEDED(hr))
  250. {
  251. hr = pps->Open(STGM_SHARE_EXCLUSIVE, grfMode & STGM_OPENMODE, ppPropStg);
  252. }
  253. }
  254. }
  255. LeaveCriticalSection(&_cs);
  256. return hr;
  257. }
  258. STDMETHODIMP CMediaPropSetStg::Delete(REFFMTID fmtid)
  259. {
  260. return E_NOTIMPL;
  261. }
  262. STDMETHODIMP CMediaPropSetStg::Enum(IEnumSTATPROPSETSTG** ppenum)
  263. {
  264. HRESULT hr;
  265. CMediaPropSetEnum *psenum = new CMediaPropSetEnum(_pPropStgInfo, _cPropertyStorages, 0);
  266. if (psenum)
  267. {
  268. hr = psenum->QueryInterface(IID_PPV_ARG(IEnumSTATPROPSETSTG, ppenum));
  269. psenum->Release();
  270. }
  271. else
  272. hr = STG_E_INSUFFICIENTMEMORY;
  273. return hr;
  274. }
  275. CMediaPropSetStg::CMediaPropSetStg() : _cRef(1), _bHasBeenPopulated(FALSE), _dwMode(STGM_READ), _propStg(NULL)
  276. {
  277. _wszFile[0] = 0;
  278. DllAddRef();
  279. }
  280. // The only place this is called is at creation time.
  281. HRESULT CMediaPropSetStg::Init()
  282. {
  283. HRESULT hr = E_FAIL;
  284. InitializeCriticalSection(&_cs);
  285. _hFileOpenEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  286. if (_hFileOpenEvent != NULL)
  287. {
  288. hr = _CreatePropertyStorages();
  289. if (SUCCEEDED(hr))
  290. {
  291. hr = _ResetPropertySet();
  292. }
  293. }
  294. return hr;
  295. }
  296. CMediaPropSetStg::~CMediaPropSetStg()
  297. {
  298. if (_propStg)
  299. {
  300. for (ULONG i = 0; i < _cPropertyStorages; i++)
  301. {
  302. ATOMICRELEASE(_propStg[i]);
  303. }
  304. LocalFree(_propStg);
  305. }
  306. if (_hFileOpenEvent)
  307. {
  308. CloseHandle(_hFileOpenEvent);
  309. }
  310. DeleteCriticalSection(&_cs);
  311. DllRelease();
  312. }
  313. BOOL CMediaPropSetStg::_IsSlowProperty(const COLMAP *pPInfo)
  314. {
  315. return FALSE;
  316. }
  317. HRESULT CMediaPropSetStg::FlushChanges(REFFMTID fmtid, LONG cNumProps, const COLMAP **pcmapInfo, PROPVARIANT *pVarProps, BOOL *pbDirtyFlags)
  318. {
  319. return E_NOTIMPL;
  320. }
  321. //returns success if we support that FMTID
  322. // ppps and ppcmPropInfo are optional
  323. HRESULT CMediaPropSetStg::_ResolveFMTID(REFFMTID fmtid, CMediaPropStorage **ppps)
  324. {
  325. for (ULONG i = 0; i < _cPropertyStorages; i++)
  326. {
  327. if (IsEqualGUID(_pPropStgInfo[i].fmtid, fmtid))
  328. {
  329. if (ppps)
  330. *ppps = _propStg[i];
  331. return S_OK;
  332. }
  333. }
  334. return E_FAIL;
  335. }
  336. HRESULT CMediaPropSetStg::_ResetPropertySet()
  337. {
  338. for (ULONG i = 0; i < _cPropertyStorages; i++)
  339. {
  340. _propStg[i]->_ResetPropStorage();
  341. }
  342. return S_OK;
  343. }
  344. HRESULT CMediaPropSetStg::_CreatePropertyStorages()
  345. {
  346. HRESULT hr = E_OUTOFMEMORY;
  347. ASSERT(NULL == _propStg);
  348. _propStg = (CMediaPropStorage**)LocalAlloc(LPTR, sizeof(CMediaPropStorage*) * _cPropertyStorages);
  349. if (_propStg)
  350. {
  351. for (ULONG i = 0; i < _cPropertyStorages; i++)
  352. {
  353. ASSERTMSG(_pPropStgInfo[i].pcmProps != NULL, "CMediaPropSetStg::_CreatePropertyStorages: my COLMAP structure is null");
  354. // We want to give each property storage a list of the COLMAPs that it supports.
  355. // This information is contained in _pPropStgInfo[i].ppids and cpids.
  356. // We'll make a new array of COLMAPS
  357. _propStg[i] = new CMediaPropStorage(this, NULL, _pPropStgInfo[i].fmtid,
  358. _pPropStgInfo[i].pcmProps, _pPropStgInfo[i].cNumProps, _dwMode, &_cs);
  359. if (!_propStg[i])
  360. break;
  361. }
  362. hr = S_OK;
  363. }
  364. return hr;
  365. }
  366. HRESULT CMediaPropSetStg::_PopulatePropertySet()
  367. {
  368. return E_NOTIMPL;
  369. }
  370. STDMETHODIMP CMediaPropSetStg::OnStatus(WMT_STATUS Status, HRESULT hr, WMT_ATTR_DATATYPE dwType, BYTE *pValue, void *pvContext)
  371. {
  372. // This is callback from WMSDK while we're holding a critical section on the main thread,
  373. // waiting for this event to be set.
  374. switch(Status)
  375. {
  376. case WMT_OPENED:
  377. SetEvent(_hFileOpenEvent);
  378. break;
  379. }
  380. return S_OK;
  381. }
  382. STDMETHODIMP CMediaPropSetStg::OnSample(DWORD dwOutputNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void* pcontext)
  383. {
  384. return S_OK;
  385. }