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.

508 lines
12 KiB

  1. // Copyright (c) 1998 - 1999 Microsoft Corporation. All Rights Reserved.
  2. BSTR FindAttribute(IXMLElement *p, LPWSTR name);
  3. DWORD ParseNum(LPWSTR p);
  4. LONG ReadNumAttribute(IXMLElement *p, LPWSTR attrName, LONG lDefault = 0);
  5. LONGLONG ParseTime(LPWSTR p);
  6. LONGLONG ReadTimeAttribute(IXMLElement *p, LPWSTR attrName, LONGLONG llDefault = 0);
  7. BOOL ReadBoolAttribute(IXMLElement *p, LPWSTR attrName, BOOL bDefault);
  8. class CFakePropertyBag : public IPropertyBag, public CUnknown
  9. {
  10. public:
  11. DECLARE_IUNKNOWN
  12. CGenericList<WCHAR> m_listNames;
  13. CGenericList<WCHAR> m_listValues;
  14. CFakePropertyBag() :
  15. CUnknown(NAME("property bag"), NULL),
  16. m_listNames(NAME("names")), m_listValues(NAME("values"))
  17. { }
  18. ~CFakePropertyBag() { EmptyBag(); };
  19. // override this to publicise our interfaces
  20. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) {
  21. if (riid == IID_IPropertyBag) {
  22. return GetInterface((IPropertyBag *) this, ppv);
  23. } else {
  24. return CUnknown::NonDelegatingQueryInterface(riid, ppv);
  25. }
  26. };
  27. STDMETHOD(Read)(LPCOLESTR pszPropName, VARIANT *pvar, IErrorLog* pErrorLog);
  28. STDMETHOD(Write)(LPCOLESTR pszPropName, VARIANT *pVar);
  29. void EmptyBag() {
  30. // delete the stored strings....
  31. BSTR p;
  32. do {
  33. p = m_listValues.RemoveHead();
  34. if (p)
  35. SysFreeString(p);
  36. } while (p);
  37. do {
  38. p = m_listNames.RemoveHead();
  39. if (p)
  40. SysFreeString(p);
  41. } while (p);
  42. }
  43. };
  44. HRESULT HandleParamTags(IXMLElement *p, IUnknown *punk);
  45. HRESULT GetFilterFromCategory(REFCLSID clsidCategory, WCHAR *lpwInstance, IBaseFilter **ppf);
  46. #ifndef NO_QXMLHELP_IMPL
  47. BSTR FindAttribute(IXMLElement *p, LPWSTR name)
  48. {
  49. VARIANT v;
  50. VariantInit(&v);
  51. HRESULT hr = p->getAttribute(name, &v);
  52. if (FAILED(hr))
  53. return NULL;
  54. return V_BSTR(&v);
  55. }
  56. DWORD ParseNum(LPWSTR p)
  57. {
  58. DWORD dwRet = 0;
  59. WCHAR c;
  60. while (((c = *p++) >= L'0') && (c <= L'9') )
  61. dwRet = (dwRet * 10) + (c - L'0');
  62. return dwRet;
  63. }
  64. LONG ReadNumAttribute(IXMLElement *p, LPWSTR attrName, LONG lDefault /* = 0 */)
  65. {
  66. BSTR val = FindAttribute(p, attrName);
  67. LONG lRet = lDefault;
  68. if (val) {
  69. lRet = ParseNum(val);
  70. SysFreeString(val);
  71. }
  72. return lRet;
  73. }
  74. LONGLONG ParseTime(LPWSTR p)
  75. {
  76. DbgLog((LOG_TRACE, 4, TEXT("ParseTime: parsing '%hs'"), p));
  77. WCHAR c = *p++;
  78. // !!! could handle SMPTE frames here?
  79. DWORD dwSec = 0;
  80. DWORD dwMin = 0;
  81. DWORD dwFrac = 0;
  82. int iFracPlaces = -1;
  83. while (c != L'\0') {
  84. if (c >= L'0' && c <= L'9') {
  85. if (iFracPlaces >= 0) {
  86. ++iFracPlaces;
  87. dwFrac = dwFrac * 10 + (c - L'0');
  88. } else {
  89. dwSec = dwSec * 10 + (c - L'0');
  90. }
  91. } else if (iFracPlaces >= 0) {
  92. break;
  93. } else if (c == L':') {
  94. dwMin = dwMin * 60 + dwSec;
  95. dwSec = 0;
  96. } else if (c == L'.') {
  97. iFracPlaces = 0;
  98. } else
  99. break; // !!! allow for skipping whitespace?
  100. c = *p++;
  101. }
  102. LONGLONG llRet = (LONGLONG) dwFrac * UNITS;
  103. while (iFracPlaces-- > 0) {
  104. llRet /= 10;
  105. }
  106. llRet += (LONGLONG) dwMin * 60 * UNITS + (LONGLONG) dwSec * UNITS;
  107. DbgLog((LOG_TRACE, 4, TEXT("ParseTime: returning %d ms"), (DWORD) (llRet / 10000)));
  108. return llRet;
  109. }
  110. LONGLONG ReadTimeAttribute(IXMLElement *p, LPWSTR attrName, LONGLONG llDefault /* = 0 */)
  111. {
  112. BSTR val = FindAttribute(p, attrName);
  113. LONGLONG llRet = llDefault;
  114. if (val) {
  115. llRet = ParseTime(val);
  116. SysFreeString(val);
  117. }
  118. return llRet;
  119. }
  120. BOOL ReadBoolAttribute(IXMLElement *p, LPWSTR attrName, BOOL bDefault)
  121. {
  122. BSTR val = FindAttribute(p, attrName);
  123. if (val) {
  124. WCHAR c = *val;
  125. if (c == L'y' || c == L'Y' || c == L't' || c == L'T' || c == L'1')
  126. bDefault = TRUE;
  127. else if (c == L'n' || c == L'N' || c == L'f' || c == L'F' || c == L'0')
  128. bDefault = FALSE;
  129. else {
  130. DbgLog((LOG_ERROR, 1, TEXT("Looking for yes/no value, found '%ls'"), val));
  131. }
  132. SysFreeString(val);
  133. }
  134. return bDefault;
  135. }
  136. STDMETHODIMP CFakePropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pvar,
  137. IErrorLog* pErrorLog)
  138. {
  139. USES_CONVERSION;
  140. if(pvar && pvar->vt != VT_EMPTY && pvar->vt != VT_BSTR)
  141. return E_INVALIDARG;
  142. HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  143. POSITION pos1, pos2;
  144. for(pos1 = m_listNames.GetHeadPosition(),
  145. pos2 = m_listValues.GetHeadPosition();
  146. pos1;
  147. pos1 = m_listNames.Next(pos1),
  148. pos2 = m_listValues.Next(pos2))
  149. {
  150. WCHAR *pName = m_listNames.Get(pos1);
  151. if (lstrcmpW(pName, pszPropName) == 0)
  152. {
  153. WCHAR *pValue = m_listValues.Get(pos2);
  154. hr = S_OK;
  155. if(pvar)
  156. {
  157. V_VT(pvar) = VT_BSTR;
  158. V_BSTR(pvar) = ::SysAllocString(pValue);
  159. if (!V_BSTR(pvar))
  160. hr = E_OUTOFMEMORY;
  161. return hr;
  162. }
  163. }
  164. }
  165. if(pos1 == 0)
  166. {
  167. ASSERT(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  168. }
  169. return hr;
  170. };
  171. STDMETHODIMP CFakePropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pvar)
  172. {
  173. // !!! look in list of values to see if it's already there?
  174. BSTR bstrName = SysAllocString(pszPropName);
  175. if (!bstrName)
  176. return E_OUTOFMEMORY;
  177. BSTR bstrValue;
  178. if (V_VT(pvar) == VT_BSTR) {
  179. bstrValue = SysAllocString(V_BSTR(pvar));
  180. if (!bstrValue)
  181. return E_OUTOFMEMORY;
  182. } else {
  183. VARIANT v;
  184. V_VT(&v) = VT_EMPTY;
  185. HRESULT hr = VariantChangeType(&v, pvar, 0, VT_BSTR);
  186. if (FAILED(hr))
  187. return hr;
  188. bstrValue = V_BSTR(&v);
  189. }
  190. m_listNames.AddTail(bstrName);
  191. m_listValues.AddTail(bstrValue);
  192. return S_OK;
  193. }
  194. HRESULT HandleParamTags(IXMLElement *p, IUnknown *punk)
  195. {
  196. HRESULT hr = S_OK;
  197. CFakePropertyBag bag;
  198. IXMLElementCollection *pcoll;
  199. hr = p->get_children(&pcoll);
  200. if (hr == S_FALSE)
  201. return S_OK; // nothing to do
  202. long lChildren;
  203. hr = pcoll->get_length(&lChildren);
  204. int iParamsFound = 0;
  205. VARIANT var;
  206. var.vt = VT_I4;
  207. var.lVal = 0;
  208. for (SUCCEEDED(hr); var.lVal < lChildren; (var.lVal)++) {
  209. IDispatch *pDisp;
  210. hr = pcoll->item(var, var, &pDisp);
  211. if (SUCCEEDED(hr) && pDisp) {
  212. IXMLElement *pelem;
  213. hr = pDisp->QueryInterface(__uuidof(IXMLElement), (void **) &pelem);
  214. if (SUCCEEDED(hr)) {
  215. bool fAdded = false;
  216. BSTR bstrTagName;
  217. hr = pelem->get_tagName(&bstrTagName);
  218. if (SUCCEEDED(hr)) {
  219. if (!lstrcmpiW(bstrTagName, L"param")) {
  220. BSTR bstrName = FindAttribute(pelem, L"name");
  221. if (bstrName) {
  222. BSTR bstrValue = FindAttribute(pelem, L"value");
  223. if (!bstrValue) {
  224. hr = pelem->get_text(&bstrValue);
  225. }
  226. if (bstrValue) {
  227. // add this name/value pair to bag
  228. if(bag.m_listNames.AddTail(bstrName))
  229. {
  230. if(bag.m_listValues.AddTail(bstrValue)) {
  231. fAdded = true;
  232. ++iParamsFound;
  233. }
  234. else
  235. {
  236. bag.m_listNames.RemoveTail();
  237. }
  238. }
  239. if(!fAdded) {
  240. SysFreeString(bstrValue);
  241. }
  242. }
  243. if(!fAdded) {
  244. SysFreeString(bstrName);
  245. }
  246. } else {
  247. hr = VFW_E_INVALID_FILE_FORMAT;
  248. }
  249. } else {
  250. // !!! unknown other subtag?
  251. }
  252. SysFreeString(bstrTagName);
  253. }
  254. pelem->Release();
  255. }
  256. pDisp->Release();
  257. }
  258. }
  259. pcoll->Release();
  260. if (SUCCEEDED(hr) && iParamsFound) {
  261. // load properties from the bag
  262. IPersistPropertyBag *pPPB;
  263. HRESULT hr2 = punk->QueryInterface(IID_IPersistPropertyBag,
  264. (void **) &pPPB);
  265. if (SUCCEEDED(hr2)) {
  266. if (iParamsFound == 1 && !lstrcmpW(L"data", bag.m_listNames.GetHead())) {
  267. DbgLog((LOG_TRACE, 1, TEXT("Using IPersistStream instead of IPersistPropertyBag")));
  268. hr2 = E_NOINTERFACE;
  269. } else {
  270. hr2 = pPPB->Load(&bag, NULL);
  271. if (FAILED(hr2)) {
  272. DbgLog((LOG_ERROR, 1, TEXT("Error %x loading parameters"), hr2));
  273. }
  274. }
  275. pPPB->Release();
  276. }
  277. if (FAILED(hr2)) {
  278. DbgLog((LOG_ERROR, 1, TEXT("Filter doesn't take parameters?")));
  279. // !!! loop through properties handling special cases?
  280. // if there's an "src" param, send it to IFileSource/Sink
  281. VARIANT v;
  282. v.vt = VT_BSTR;
  283. hr2 = bag.Read(L"src", &v, NULL);
  284. if (SUCCEEDED(hr2)) {
  285. IFileSourceFilter *pFSF;
  286. hr2 = punk->QueryInterface(IID_IFileSourceFilter,
  287. (void **) &pFSF);
  288. if (SUCCEEDED(hr2)) {
  289. hr = pFSF->Load(V_BSTR(&v), NULL);
  290. pFSF->Release();
  291. } else {
  292. IFileSinkFilter *pFSF;
  293. hr2 = punk->QueryInterface(IID_IFileSinkFilter,
  294. (void **) &pFSF);
  295. if (SUCCEEDED(hr2)) {
  296. hr = pFSF->SetFileName(V_BSTR(&v), NULL);
  297. pFSF->Release();
  298. }
  299. }
  300. SysFreeString(V_BSTR(&v));
  301. }
  302. v.vt = VT_BSTR;
  303. hr2 = bag.Read(L"data", &v, NULL);
  304. if (SUCCEEDED(hr2)) {
  305. BSTR bstr = V_BSTR(&v);
  306. IPersistStream *pPS;
  307. hr2 = punk->QueryInterface(IID_IPersistStream,
  308. (void **) &pPS);
  309. if (SUCCEEDED(hr2)) {
  310. // convert hex data into an IStream....
  311. UINT dwLen = SysStringLen(bstr);
  312. HGLOBAL h = GlobalAlloc(GHND, dwLen + 1);
  313. if (h) {
  314. LPBYTE p = (LPBYTE) GlobalLock(h);
  315. for (UINT i = 0; i < dwLen / 2; i++) {
  316. WCHAR wch = bstr[i * 2];
  317. if (wch >= L'0' && wch <= L'9')
  318. p[i] = (BYTE) (wch - L'0') * 16;
  319. else if (wch >= L'A' && wch <= L'F')
  320. p[i] = (BYTE) (wch - L'A' + 10) * 16;
  321. wch = bstr[i * 2 + 1];
  322. if (wch >= L'0' && wch <= L'9')
  323. p[i] += (BYTE) (wch - L'0');
  324. else if (wch >= L'A' && wch <= L'F')
  325. p[i] += (BYTE) (wch - L'A' + 10);
  326. }
  327. IStream *ps;
  328. hr2 = CreateStreamOnHGlobal(h, TRUE, &ps);
  329. if (SUCCEEDED(hr2)) {
  330. hr2 = pPS->Load(ps);
  331. ps->Release();
  332. }
  333. }
  334. pPS->Release();
  335. }
  336. SysFreeString(bstr);
  337. }
  338. }
  339. }
  340. return hr;
  341. }
  342. HRESULT GetFilterFromCategory(REFCLSID clsidCategory, WCHAR *lpwInstance, IBaseFilter **ppf)
  343. {
  344. ICreateDevEnum *pCreateDevEnum;
  345. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  346. IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  347. if (hr != NOERROR)
  348. return hr;
  349. IEnumMoniker *pEm;
  350. hr = pCreateDevEnum->CreateClassEnumerator(clsidCategory, &pEm, 0);
  351. pCreateDevEnum->Release();
  352. if (hr != NOERROR)
  353. return hr;
  354. pEm->Reset(); // !!! needed?
  355. ULONG cFetched;
  356. IMoniker *pM;
  357. while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
  358. {
  359. if (lpwInstance) {
  360. IPropertyBag *pBag;
  361. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  362. if(SUCCEEDED(hr)) {
  363. VARIANT var;
  364. var.vt = VT_BSTR;
  365. hr = pBag->Read(L"FriendlyName", &var, NULL);
  366. pBag->Release();
  367. if (hr == NOERROR) {
  368. if (lstrcmpiW(var.bstrVal, lpwInstance) != 0) {
  369. SysFreeString(var.bstrVal);
  370. pM->Release();
  371. continue;
  372. }
  373. SysFreeString(var.bstrVal);
  374. } else
  375. continue;
  376. }
  377. }
  378. hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)ppf);
  379. pM->Release();
  380. break;
  381. }
  382. pEm->Release();
  383. return hr;
  384. }
  385. #endif