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.

469 lines
12 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: PROPARRY.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 5/4/1999
  12. *
  13. * DESCRIPTION: IWiaPropertyStorage cache definitions
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. CPropertyStorageArray::CPropertyStorageArray( const CPropertyStorageArray &other )
  19. : m_nCount(0),
  20. m_ppvPropVariants(NULL),
  21. m_ppsPropSpecs(NULL),
  22. m_pstrPropNames(NULL)
  23. {
  24. Copy(other);
  25. }
  26. CPropertyStorageArray::CPropertyStorageArray(IUnknown *pIUnknown)
  27. : m_nCount(0),
  28. m_ppvPropVariants(NULL),
  29. m_ppsPropSpecs(NULL),
  30. m_pstrPropNames(NULL)
  31. {
  32. Initialize(pIUnknown);
  33. }
  34. CPropertyStorageArray::~CPropertyStorageArray(void)
  35. {
  36. Destroy();
  37. }
  38. bool CPropertyStorageArray::IsValid(void) const
  39. {
  40. // It's OK to have an empty list, but it isn't considered valid
  41. return (m_nCount && m_ppvPropVariants && m_ppsPropSpecs && m_pstrPropNames);
  42. }
  43. HRESULT CPropertyStorageArray::Copy( const CPropertyStorageArray &other )
  44. {
  45. Destroy();
  46. HRESULT hr = S_OK;
  47. if (this != &other)
  48. {
  49. if (other.IsValid())
  50. {
  51. m_nCount = other.Count();
  52. if (m_nCount)
  53. {
  54. if (AllocateData())
  55. {
  56. for (int i=0;i<m_nCount && SUCCEEDED(hr);i++)
  57. {
  58. // Copy propvariant
  59. if (!SUCCEEDED(PropVariantCopy( &m_ppvPropVariants[i], &other.PropVariants()[i])))
  60. {
  61. hr = E_FAIL;
  62. break;
  63. }
  64. // Copy property name
  65. if (other.PropNames() && other.PropNames()[i])
  66. {
  67. m_pstrPropNames[i] = new WCHAR[lstrlenW(other.PropNames()[i])+1];
  68. if (!m_pstrPropNames[i])
  69. {
  70. hr = E_FAIL;
  71. break;
  72. }
  73. lstrcpyW( m_pstrPropNames[i], other.PropNames()[i] );
  74. }
  75. // Copy propspec (propid)
  76. m_ppsPropSpecs[i].propid = other.PropSpecs()[i].propid;
  77. m_ppsPropSpecs[i].ulKind = PRSPEC_PROPID;
  78. }
  79. }
  80. else
  81. {
  82. hr = E_FAIL;
  83. }
  84. }
  85. }
  86. else
  87. {
  88. hr = E_FAIL;
  89. }
  90. }
  91. if (!SUCCEEDED(hr))
  92. Destroy();
  93. return hr;
  94. }
  95. void CPropertyStorageArray::ClearPropVariantArray(void)
  96. {
  97. if (!m_ppvPropVariants || !m_nCount)
  98. return;
  99. for (int i=0;i<m_nCount;i++)
  100. {
  101. PropVariantClear(m_ppvPropVariants+i);
  102. m_ppvPropVariants[i].vt = VT_EMPTY;
  103. }
  104. }
  105. void CPropertyStorageArray::Destroy(void)
  106. {
  107. ClearPropVariantArray();
  108. for (int i=0;i<m_nCount;i++)
  109. {
  110. if (m_pstrPropNames && m_pstrPropNames[i])
  111. delete[] m_pstrPropNames[i];
  112. }
  113. if (m_ppvPropVariants)
  114. delete[] m_ppvPropVariants;
  115. if (m_ppsPropSpecs)
  116. delete[] m_ppsPropSpecs;
  117. if (m_pstrPropNames)
  118. delete[] m_pstrPropNames;
  119. m_ppvPropVariants = NULL;
  120. m_ppsPropSpecs = NULL;
  121. m_pstrPropNames = NULL;
  122. m_nCount = 0;
  123. }
  124. bool CPropertyStorageArray::AllocateData(void)
  125. {
  126. m_ppsPropSpecs = new PROPSPEC[m_nCount];
  127. if (m_ppsPropSpecs)
  128. {
  129. ZeroMemory(m_ppsPropSpecs,m_nCount*sizeof(m_ppsPropSpecs[0]));
  130. }
  131. m_ppvPropVariants = new PROPVARIANT[m_nCount];
  132. if (m_ppvPropVariants)
  133. {
  134. ZeroMemory(m_ppvPropVariants,m_nCount*sizeof(m_ppvPropVariants[0]));
  135. }
  136. m_pstrPropNames = new LPWSTR[m_nCount];
  137. if (m_pstrPropNames)
  138. {
  139. ZeroMemory(m_pstrPropNames,m_nCount*sizeof(m_pstrPropNames[0]));
  140. }
  141. return(m_ppsPropSpecs && m_ppvPropVariants && m_pstrPropNames);
  142. }
  143. CPropertyStorageArray &CPropertyStorageArray::operator=( const CPropertyStorageArray &other )
  144. {
  145. Copy(other);
  146. return(*this);
  147. }
  148. int CPropertyStorageArray::GetPropertyCount( IWiaPropertyStorage *pIWiaPropertyStorage )
  149. {
  150. IEnumSTATPROPSTG *pIEnum = NULL;
  151. HRESULT hr;
  152. int nCount=0;
  153. hr = pIWiaPropertyStorage->Enum(&pIEnum);
  154. if (SUCCEEDED(hr))
  155. {
  156. STATPROPSTG StatPropStg;
  157. ZeroMemory(&StatPropStg,sizeof(StatPropStg));
  158. while ((hr = pIEnum->Next(1,&StatPropStg, NULL)) == S_OK)
  159. {
  160. nCount++;
  161. if (StatPropStg.lpwstrName)
  162. {
  163. CoTaskMemFree(StatPropStg.lpwstrName);
  164. }
  165. ZeroMemory(&StatPropStg,sizeof(StatPropStg));
  166. }
  167. }
  168. return(nCount);
  169. }
  170. HRESULT CPropertyStorageArray::GetPropertyNames( IWiaPropertyStorage *pIWiaPropertyStorage )
  171. {
  172. IEnumSTATPROPSTG *pIEnum = NULL;
  173. HRESULT hr;
  174. int nCurrentIndex=0;
  175. hr = pIWiaPropertyStorage->Enum(&pIEnum);
  176. if (SUCCEEDED(hr))
  177. {
  178. STATPROPSTG StatPropStg;
  179. ZeroMemory(&StatPropStg,sizeof(StatPropStg));
  180. while ((hr = pIEnum->Next(1,&StatPropStg, NULL)) == S_OK)
  181. {
  182. m_ppsPropSpecs[nCurrentIndex].propid = StatPropStg.propid;
  183. m_ppsPropSpecs[nCurrentIndex].ulKind = PRSPEC_PROPID;
  184. if (StatPropStg.lpwstrName)
  185. {
  186. m_pstrPropNames[nCurrentIndex] = new WCHAR[lstrlenW(StatPropStg.lpwstrName)+1];
  187. if (m_pstrPropNames[nCurrentIndex])
  188. {
  189. lstrcpyW( m_pstrPropNames[nCurrentIndex], StatPropStg.lpwstrName );
  190. CoTaskMemFree(StatPropStg.lpwstrName);
  191. }
  192. else
  193. {
  194. hr = E_OUTOFMEMORY;
  195. CoTaskMemFree(StatPropStg.lpwstrName);
  196. break;
  197. }
  198. }
  199. nCurrentIndex++;
  200. }
  201. }
  202. return(hr);
  203. }
  204. HRESULT CPropertyStorageArray::Initialize( IUnknown *pIUnknown )
  205. {
  206. Destroy();
  207. HRESULT hr = E_INVALIDARG;
  208. if (pIUnknown)
  209. {
  210. CComPtr<IWiaPropertyStorage> pIWiaPropertyStorage;
  211. hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage);
  212. if (SUCCEEDED(hr))
  213. {
  214. m_nCount = GetPropertyCount( pIWiaPropertyStorage );
  215. if (m_nCount)
  216. {
  217. if (AllocateData())
  218. {
  219. hr = GetPropertyNames( pIWiaPropertyStorage );
  220. if (SUCCEEDED(hr))
  221. {
  222. hr = pIWiaPropertyStorage->ReadMultiple( m_nCount, m_ppsPropSpecs, m_ppvPropVariants );
  223. }
  224. }
  225. }
  226. }
  227. }
  228. if (!SUCCEEDED(hr))
  229. {
  230. Destroy();
  231. }
  232. return(hr);
  233. }
  234. HRESULT CPropertyStorageArray::Read( IUnknown *pIUnknown )
  235. {
  236. HRESULT hr = E_FAIL;
  237. if (IsValid())
  238. {
  239. ClearPropVariantArray();
  240. CComPtr<IWiaPropertyStorage> pIWiaPropertyStorage;
  241. hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage);
  242. if (SUCCEEDED(hr))
  243. {
  244. hr = pIWiaPropertyStorage->ReadMultiple( m_nCount, m_ppsPropSpecs, m_ppvPropVariants );
  245. }
  246. }
  247. return(hr);
  248. }
  249. HRESULT CPropertyStorageArray::Write( IUnknown *pIUnknown )
  250. {
  251. HRESULT hr = E_FAIL;
  252. if (IsValid())
  253. {
  254. CComPtr<IWiaPropertyStorage> pIWiaPropertyStorage;
  255. hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage);
  256. if (SUCCEEDED(hr))
  257. {
  258. hr = pIWiaPropertyStorage->WriteMultiple( m_nCount, m_ppsPropSpecs, m_ppvPropVariants, WIA_IPA_FIRST);
  259. }
  260. }
  261. return(hr);
  262. }
  263. HRESULT CPropertyStorageArray::Write( IUnknown *pIUnknown, PROPID propId )
  264. {
  265. HRESULT hr = E_FAIL;
  266. if (IsValid())
  267. {
  268. int nIndex = GetIndexFromPropId( propId );
  269. if (nIndex >= 0)
  270. {
  271. CComPtr<IWiaPropertyStorage> pIWiaPropertyStorage;
  272. hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage);
  273. if (SUCCEEDED(hr))
  274. {
  275. hr = pIWiaPropertyStorage->WriteMultiple( 1, m_ppsPropSpecs+nIndex, m_ppvPropVariants+nIndex, WIA_IPA_FIRST );
  276. }
  277. }
  278. }
  279. return(hr);
  280. }
  281. int CPropertyStorageArray::GetIndexFromPropId( PROPID propId )
  282. {
  283. if (!IsValid())
  284. return -1;
  285. for (int i=0;i<m_nCount;i++)
  286. {
  287. if (m_ppsPropSpecs[i].propid == propId)
  288. return(i);
  289. }
  290. return(-1);
  291. }
  292. PROPVARIANT *CPropertyStorageArray::GetProperty( PROPID propId )
  293. {
  294. int nIndex = GetIndexFromPropId( propId );
  295. if (nIndex < 0)
  296. return(NULL);
  297. return(m_ppvPropVariants+nIndex);
  298. }
  299. bool CPropertyStorageArray::GetProperty( PROPID propId, LONG &nProp )
  300. {
  301. PROPVARIANT *ppvPropValue = GetProperty( propId );
  302. if (!ppvPropValue)
  303. return(false);
  304. if (VT_I4 != ppvPropValue->vt)
  305. return(false);
  306. nProp = ppvPropValue->lVal;
  307. return(TRUE);
  308. }
  309. bool CPropertyStorageArray::GetProperty( PROPID propId, CSimpleStringWide &strProp )
  310. {
  311. PROPVARIANT *ppvPropValue = GetProperty( propId );
  312. if (!ppvPropValue)
  313. return(false);
  314. if (VT_LPWSTR != ppvPropValue->vt && VT_BSTR != ppvPropValue->vt)
  315. return(false);
  316. strProp = ppvPropValue->pwszVal;
  317. return(true);
  318. }
  319. bool CPropertyStorageArray::SetProperty( PROPID propId, PROPVARIANT *pPropVar )
  320. {
  321. PROPVARIANT *ppvPropValue = GetProperty( propId );
  322. if (ppvPropValue)
  323. {
  324. PropVariantClear(ppvPropValue);
  325. return(SUCCEEDED(PropVariantCopy(ppvPropValue,pPropVar)));
  326. }
  327. return(false);
  328. }
  329. bool CPropertyStorageArray::SetProperty( PROPID propId, LONG nProp )
  330. {
  331. PROPVARIANT *ppvPropValue = GetProperty( propId );
  332. if (ppvPropValue)
  333. {
  334. ppvPropValue->vt = VT_I4;
  335. ppvPropValue->lVal = nProp;
  336. return(true);
  337. }
  338. return(false);
  339. }
  340. int CPropertyStorageArray::Count(void) const
  341. {
  342. return(m_nCount);
  343. }
  344. PROPVARIANT *CPropertyStorageArray::PropVariants(void) const
  345. {
  346. return(m_ppvPropVariants);
  347. }
  348. PROPSPEC *CPropertyStorageArray::PropSpecs(void) const
  349. {
  350. return(m_ppsPropSpecs);
  351. }
  352. LPWSTR *CPropertyStorageArray::PropNames(void) const
  353. {
  354. return(m_pstrPropNames);
  355. }
  356. void CPropertyStorageArray::Dump( int nIndex )
  357. {
  358. #if defined(WIA_DEBUG)
  359. WIA_TRACE((TEXT("Dumping IWiaPropertyStorage:")));
  360. int nStart = nIndex < 0 ? 0 : nIndex;
  361. int nCount = nIndex < 0 ? Count() : 1;
  362. for (int i=nStart;i<nCount;i++)
  363. {
  364. PROPVARIANT *pPropVar = GetProperty( m_ppsPropSpecs[i].propid );
  365. if (pPropVar)
  366. {
  367. TCHAR szValue[512] = TEXT("");
  368. switch (m_ppvPropVariants[i].vt)
  369. {
  370. case VT_I4:
  371. wsprintf(szValue,TEXT("%d"),(LONG)m_ppvPropVariants[i].lVal);
  372. break;
  373. case VT_BSTR:
  374. wsprintf(szValue,TEXT("%ws"),m_ppvPropVariants[i].bstrVal);
  375. break;
  376. case VT_VECTOR|VT_I4:
  377. {
  378. for (int j=0;j<(int)m_ppvPropVariants[i].cal.cElems;j++)
  379. {
  380. wsprintf(szValue+lstrlen(szValue),TEXT("%08X"),(LONG)m_ppvPropVariants[i].cal.pElems[j]);
  381. if (j < (int)m_ppvPropVariants[i].cal.cElems-1)
  382. wsprintf(szValue+lstrlen(szValue),TEXT(" "));
  383. }
  384. }
  385. break;
  386. case VT_VECTOR|VT_UI1:
  387. {
  388. for (int j=0;j<(int)m_ppvPropVariants[i].cal.cElems;j++)
  389. {
  390. wsprintf(szValue+lstrlen(szValue),TEXT("%02X"),(LONG)m_ppvPropVariants[i].caub.pElems[j]);
  391. if (j < (int)m_ppvPropVariants[i].cal.cElems-1 && j % 4 == 3)
  392. wsprintf(szValue+lstrlen(szValue),TEXT(" "));
  393. }
  394. }
  395. break;
  396. case VT_LPWSTR:
  397. wsprintf(szValue,TEXT("%ws"),m_ppvPropVariants[i].pwszVal );
  398. break;
  399. default:
  400. wsprintf(szValue,TEXT("Unknown Type %d (08X)"),m_ppvPropVariants[i].vt);
  401. }
  402. WIA_TRACE((TEXT(" [%-3d %ws] = [%s]"), m_ppsPropSpecs[i].propid, m_pstrPropNames[i], szValue));
  403. }
  404. }
  405. #endif // defined(II_DEBUG)
  406. }