Leaked source code of windows server 2003
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.

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