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.

1060 lines
29 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: IPropItm.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 19 Feb, 1998
  12. *
  13. * DESCRIPTION:
  14. * Implementation of WIA item class server properties.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #include "stiexe.h"
  19. #include <regstr.h>
  20. #include <wiamindr.h>
  21. // #include <wiadbg.h>
  22. #include "wiapsc.h"
  23. #include "helpers.h"
  24. //
  25. // Strings used to access the registry. REGSTR_* string constants can be
  26. // found in sdk\inc\regstr.h
  27. //
  28. TCHAR g_szREGSTR_PATH_WIA[] = REGSTR_PATH_SETUP TEXT("\\WIA");
  29. /*******************************************************************************
  30. *
  31. * ReadMultiple
  32. * WriteMultiple
  33. * ReadPropertyNames
  34. * Enum
  35. * GetPropertyAttributes
  36. * GetCount
  37. *
  38. * DESCRIPTION:
  39. * IWiaPropertyStorage methods.
  40. *
  41. * PARAMETERS:
  42. *
  43. *******************************************************************************/
  44. /**************************************************************************\
  45. * CWiaItem::ReadMultiple
  46. *
  47. * This method reads the specified number of properties from the item's
  48. * current value property storage. This method conforms to that standard
  49. * OLE IPropertyStorage::ReadMultiple method.
  50. *
  51. * Arguments:
  52. *
  53. * cpspec - Number of properties to read.
  54. * rgpspec - Array of PropSpec's specifying which properties
  55. * are to be read.
  56. * rgpropvar - Array where the property values will be copied
  57. * to.
  58. *
  59. * Arguments:
  60. *
  61. * cpspec
  62. * rgpspec
  63. * rgpropvar
  64. *
  65. * Return Value:
  66. *
  67. * status
  68. *
  69. * History:
  70. *
  71. * 9/3/1998 Original Version
  72. *
  73. \**************************************************************************/
  74. HRESULT _stdcall CWiaItem::ReadMultiple(
  75. ULONG cpspec,
  76. const PROPSPEC __RPC_FAR rgpspec[],
  77. PROPVARIANT __RPC_FAR rgpropvar[])
  78. {
  79. DBG_FN(CWiaItem::ReadMultiple);
  80. HRESULT hr;
  81. LONG lFlags = 0;
  82. //
  83. // Corresponding driver item must be valid to talk with hardware.
  84. //
  85. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  86. if (FAILED(hr)) {
  87. return hr;
  88. }
  89. //
  90. // rgpropvar must be valid
  91. //
  92. if (IsBadWritePtr(rgpropvar, sizeof(PROPVARIANT) * cpspec)) {
  93. DBG_ERR(("CWiaItem::ReadMultiple, last parameter (rgpropvar) is invalid"));
  94. return E_INVALIDARG;
  95. }
  96. //
  97. // Check whether item properties have been initialized
  98. //
  99. if (!m_bInitialized) {
  100. //
  101. // Check whether the properties being read are the WIA Managed properties.
  102. // If they are, there is still no need to initialize the item.
  103. //
  104. if (AreWiaInitializedProps(cpspec, (PROPSPEC*) rgpspec)) {
  105. return (m_pPropStg->CurStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
  106. }
  107. hr = InitLazyProps();
  108. if (FAILED(hr)) {
  109. DBG_ERR(("CWiaItem::ReadMultiple, InitLazyProps failed"));
  110. return hr;
  111. }
  112. }
  113. //
  114. // Check whether the properties requested are all cacheable
  115. //
  116. hr = (m_pPropStg->AccessStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
  117. if (FAILED(hr)) {
  118. ReportReadWriteMultipleError(hr, "CWiaItem::ReadMultiple", NULL, TRUE, cpspec, rgpspec);
  119. //
  120. // Property attributes are not required absolutely, continue without it.
  121. //
  122. } else {
  123. for (ULONG i = 0; i < cpspec; i++) {
  124. //
  125. // The client requests a property not read yet or non-cacheable
  126. //
  127. if ((rgpropvar[i].vt == VT_UI4) &&
  128. (! (rgpropvar[i].lVal & WIA_PROP_CACHEABLE))) {
  129. break;
  130. }
  131. }
  132. //
  133. // Clear the access flags from the rgpropvar
  134. //
  135. FreePropVariantArray(cpspec, rgpropvar);
  136. //
  137. // If all the properties are cacheable, then take the quick path
  138. //
  139. if (i == cpspec) {
  140. hr = (m_pPropStg->CurStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
  141. if (hr == S_OK) {
  142. //
  143. // Check whether all the properties are retrieved correctly
  144. // some properties might not have been read from the storage
  145. //
  146. for (ULONG i = 0; i < cpspec; i++) {
  147. if (rgpropvar[i].vt == VT_EMPTY) {
  148. break;
  149. }
  150. }
  151. if (i == cpspec) {
  152. //
  153. // All the properties requested are found in cache
  154. //
  155. return (hr);
  156. } else {
  157. FreePropVariantArray(cpspec, rgpropvar);
  158. }
  159. }
  160. }
  161. }
  162. if (SUCCEEDED(hr)) {
  163. //
  164. // Make sure all PropSpecs are using PropID's. This is so that
  165. // drivers only have to deal with PropID's. If some of the
  166. // PropSpecs are using string names, then convert them.
  167. //
  168. PROPSPEC *pPropSpec = NULL;
  169. hr = m_pPropStg->NamesToPropIDs(cpspec, (PROPSPEC*) rgpspec, &pPropSpec);
  170. if (SUCCEEDED(hr)) {
  171. //
  172. // Give device mini driver a chance to update the device properties.
  173. //
  174. {
  175. LOCK_WIA_DEVICE _LWD(this, &hr);
  176. if(SUCCEEDED(hr)) {
  177. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvReadItemProperties((BYTE*)this,
  178. lFlags,
  179. cpspec,
  180. (pPropSpec ? pPropSpec : rgpspec),
  181. &m_lLastDevErrVal);
  182. }
  183. }
  184. if (pPropSpec) {
  185. LocalFree(pPropSpec);
  186. pPropSpec = NULL;
  187. }
  188. }
  189. if (SUCCEEDED(hr)) {
  190. hr = (m_pPropStg->CurStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
  191. if (FAILED(hr)) {
  192. ReportReadWriteMultipleError(hr,
  193. "CWiaItem::ReadMultiple",
  194. NULL,
  195. TRUE,
  196. cpspec,
  197. rgpspec);
  198. }
  199. }
  200. }
  201. return hr;
  202. }
  203. /**************************************************************************\
  204. * CWiaItem::ReadPropertyNames
  205. *
  206. * Returns the string name of the specified properties if they exist.
  207. * This conforms to the standard OLE IPropertyStorage::ReadPropertyNames
  208. * method.
  209. *
  210. * Arguments:
  211. *
  212. * pstmProp - Pointer to property stream.
  213. *
  214. * Return Value:
  215. *
  216. * Status
  217. *
  218. * History:
  219. *
  220. * 9/3/1998 Original Version
  221. *
  222. \**************************************************************************/
  223. HRESULT _stdcall CWiaItem::ReadPropertyNames(
  224. ULONG cpropid,
  225. const PROPID __RPC_FAR rgpropid[],
  226. LPOLESTR __RPC_FAR rglpwstrName[])
  227. {
  228. DBG_FN(CWiaItem::ReadPropertyNames);
  229. HRESULT hr;
  230. //
  231. // Check whether item properties have been initialized
  232. //
  233. if (!m_bInitialized) {
  234. hr = InitLazyProps();
  235. if (FAILED(hr)) {
  236. DBG_ERR(("CWiaItem::ReadPropertyNames, InitLazyProps failed"));
  237. return hr;
  238. }
  239. }
  240. return (m_pPropStg->CurStg())->ReadPropertyNames(cpropid,rgpropid,rglpwstrName);
  241. }
  242. /**************************************************************************\
  243. * CWiaItem::WritePropertyNames
  244. *
  245. * Returns the string name of the specified properties if they exist.
  246. * This conforms to the standard OLE IPropertyStorage::ReadPropertyNames
  247. * method.
  248. *
  249. * Arguments:
  250. *
  251. * pstmProp - Pointer to property stream.
  252. *
  253. * Return Value:
  254. *
  255. * Status
  256. *
  257. * History:
  258. *
  259. * 9/3/1998 Original Version
  260. *
  261. \**************************************************************************/
  262. HRESULT _stdcall CWiaItem::WritePropertyNames(
  263. ULONG cpropid,
  264. const PROPID rgpropid[],
  265. const LPOLESTR rglpwstrName[])
  266. {
  267. DBG_FN(CWiaItem::WritePropertyNames);
  268. PROPVARIANT *pv;
  269. PROPSPEC *pspec;
  270. ULONG index;
  271. HRESULT hr;
  272. //
  273. // Check whether item properties have been initialized
  274. //
  275. if (!m_bInitialized) {
  276. hr = InitLazyProps();
  277. if (FAILED(hr)) {
  278. DBG_ERR(("CWiaItem::WritePropertyNames, InitLazyProps failed"));
  279. return hr;
  280. }
  281. }
  282. pv = (PROPVARIANT*) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cpropid);
  283. if (!pv) {
  284. DBG_ERR(("CWiaItem::WritePropertyNames, Out of memory"));
  285. return E_OUTOFMEMORY;
  286. }
  287. pspec = (PROPSPEC*) LocalAlloc(LPTR, sizeof(PROPSPEC) * cpropid);
  288. if (!pspec) {
  289. DBG_ERR(("CWiaItem::WritePropertyNames, Out of memory"));
  290. LocalFree(pv);
  291. return E_OUTOFMEMORY;
  292. }
  293. //
  294. // Put PROPIDs into the PROPSPEC array.
  295. //
  296. for (index = 0; index < cpropid; index++) {
  297. pspec[index].ulKind = PRSPEC_PROPID;
  298. pspec[index].propid = rgpropid[index];
  299. }
  300. hr = (m_pPropStg->AccessStg())->ReadMultiple(cpropid,
  301. pspec,
  302. pv);
  303. if (SUCCEEDED(hr)) {
  304. //
  305. // Make sure the properties are App. written properties. If a valid
  306. // access flag for a property exists, then it was written by the
  307. // driver and not the App, so exit.
  308. //
  309. for (index = 0; index < cpropid; index++) {
  310. if (pv[index].vt != VT_EMPTY) {
  311. DBG_ERR(("CWiaItem::WritePropertyNames, not allowed to write prop: %d.",rgpropid[index]));
  312. hr = E_ACCESSDENIED;
  313. break;
  314. }
  315. }
  316. if (SUCCEEDED(hr)) {
  317. hr = (m_pPropStg->CurStg())->WritePropertyNames(cpropid,
  318. rgpropid,
  319. rglpwstrName);
  320. if (FAILED(hr)) {
  321. DBG_ERR(("CWiaItem::WritePropertyNames, WritePropertyNames failed"));
  322. }
  323. }
  324. } else {
  325. DBG_ERR(("CWiaItem::WritePropertyNames, Reading Access values failed"));
  326. }
  327. LocalFree(pspec);
  328. LocalFree(pv);
  329. return hr;
  330. }
  331. /**************************************************************************\
  332. * CWiaItem::Enum
  333. *
  334. * Returns a IEnumSTATPROPSTG enumerator over the current value property
  335. * storage. Conforms to the standard OLE IPRopertyStorage::Enum method.
  336. *
  337. * Arguments:
  338. *
  339. * pstmProp - Pointer to property stream.
  340. *
  341. * Return Value:
  342. *
  343. * Status
  344. *
  345. * History:
  346. *
  347. * 9/3/1998 Original Version
  348. *
  349. \**************************************************************************/
  350. HRESULT _stdcall CWiaItem::Enum(
  351. IEnumSTATPROPSTG __RPC_FAR *__RPC_FAR *ppenum)
  352. {
  353. DBG_FN(CWiaItem::Enum);
  354. HRESULT hr;
  355. //
  356. // Check whether item properties have been initialized
  357. //
  358. if (!m_bInitialized) {
  359. hr = InitLazyProps();
  360. if (FAILED(hr)) {
  361. DBG_ERR(("CWiaItem::Enum, InitLazyProps failed"));
  362. return hr;
  363. }
  364. }
  365. return (m_pPropStg->CurStg())->Enum(ppenum);
  366. }
  367. /**************************************************************************\
  368. * CWiaItem::WriteMultiple
  369. *
  370. * This method writes the specified number of properties into the item's
  371. * property storage. Validation will be performed on those property
  372. * values. The properties will be restored to their old (valid) values
  373. * if validation fails.
  374. *
  375. * Arguments:
  376. *
  377. * cpspec - Number of properties to write.
  378. * rgpspec - Array of PropSpec's specifying which properties
  379. * are to be written.
  380. * rgpropvar - Array containing values that the properties
  381. * will be set to.
  382. * propidNameFirst - Minimum value for property identifiers when
  383. * they don't exist and must be allocated.
  384. *
  385. * Return Value:
  386. *
  387. * Status - S_OK if writes and validation succeeded.
  388. * E_INVALIDARG if validation failed due to an
  389. * incorrect property value.
  390. * Other error returns are from
  391. * ValidateWiaDrvItemAccess, CheckPropertyAccess,
  392. * CreatePropertyStorage and CopyProperties.
  393. *
  394. * History:
  395. *
  396. * 9/3/1998 Original Version
  397. *
  398. \**************************************************************************/
  399. HRESULT _stdcall CWiaItem::WriteMultiple(
  400. ULONG cpspec,
  401. const PROPSPEC __RPC_FAR rgpspec[],
  402. const PROPVARIANT __RPC_FAR rgpropvar[],
  403. PROPID propidNameFirst)
  404. {
  405. DBG_FN(CWiaItem::WriteMultiple);
  406. HRESULT hr;
  407. //
  408. // Corresponding driver item must be valid.
  409. //
  410. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  411. if (FAILED(hr)) {
  412. DBG_ERR(("CWiaItem::WriteMultiple, ValidateDrvItemAccess failed"));
  413. return hr;
  414. }
  415. //
  416. // Check whether item properties have been initialized
  417. //
  418. if (!m_bInitialized) {
  419. hr = InitLazyProps();
  420. if (FAILED(hr)) {
  421. DBG_ERR(("CWiaItem::WriteMultiple, InitLazyProps failed"));
  422. return hr;
  423. }
  424. }
  425. //
  426. // there is no point in going further if there are no properties to
  427. // write
  428. //
  429. if(cpspec == 0) {
  430. return S_OK;
  431. }
  432. //
  433. // We do not want to fail users who erroneousely attempt to write
  434. // to write to read-only properties IF that the values they
  435. // are trying to write are the same as current values. To achive
  436. // this, we first current values of the properties they want to
  437. // write:
  438. //
  439. PROPVARIANT *curVals = (PROPVARIANT *) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cpspec);
  440. PROPSPEC *newSpecs = (PROPSPEC *) LocalAlloc(LPTR, sizeof(PROPSPEC) * cpspec);
  441. PROPVARIANT *newVals = (PROPVARIANT *) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cpspec);
  442. ULONG newcpspec = cpspec;
  443. if(curVals == NULL || newSpecs == NULL || newVals == NULL) {
  444. DBG_ERR(("CWiaItem::WriteMultiple, failed to allocate memory"));
  445. goto Cleanup;
  446. }
  447. CopyMemory(newSpecs, rgpspec, sizeof(PROPSPEC) * cpspec);
  448. CopyMemory(newVals, rgpropvar, sizeof(PROPVARIANT) * cpspec);
  449. memset(curVals, 0, sizeof(PROPVARIANT) * cpspec);
  450. hr = m_pPropStg->CurStg()->ReadMultiple(cpspec, rgpspec, curVals);
  451. if(SUCCEEDED(hr)) {
  452. //
  453. // Now for every property value they want to write we check if
  454. // it is the same as the current value
  455. //
  456. ULONG ulNewEltIndex = 0;
  457. for(ULONG i = 0; i < cpspec; i++) {
  458. if(curVals[i].vt != rgpropvar[i].vt)
  459. continue;
  460. if(memcmp(curVals + i, rgpropvar + i, sizeof(PROPVARIANT)) == 0 ||
  461. (curVals[i].vt == VT_BSTR && !lstrcmp(curVals[i].bstrVal, rgpropvar[i].bstrVal)) ||
  462. (curVals[i].vt == VT_CLSID && IsEqualGUID(*curVals[i].puuid, *rgpropvar[i].puuid)))
  463. {
  464. // the value "matches", wipe it from both arrays.
  465. if(i != (cpspec - 1)) {
  466. //
  467. // Move a block of values/propspecs.
  468. // The number of elements to move is 1 less than the
  469. // remaining number of elements we still have to check.
  470. // Move these elements up in the new value array - put
  471. // them after the elements we've decided to keep so far
  472. //
  473. MoveMemory(newVals + ulNewEltIndex,
  474. newVals + ulNewEltIndex + 1,
  475. (cpspec - i - 1) * sizeof(PROPVARIANT));
  476. MoveMemory(newSpecs + ulNewEltIndex,
  477. newSpecs + ulNewEltIndex + 1,
  478. (cpspec - i - 1) * sizeof(PROPSPEC));
  479. }
  480. newcpspec--;
  481. } else {
  482. //
  483. // We want to keep this element, so increase the element index.
  484. //
  485. ulNewEltIndex++;
  486. }
  487. }
  488. // It could happen that all values are the same, in which case we
  489. // don't want to write anything at all
  490. if(newcpspec == 0) {
  491. hr = S_OK;
  492. goto Cleanup;
  493. }
  494. }
  495. //
  496. // Verify write access to all requested properties. If any of the
  497. // properties are read ony, the call fails with access denied.
  498. //
  499. hr = m_pPropStg->CheckPropertyAccess(TRUE,
  500. newcpspec,
  501. (PROPSPEC*)newSpecs);
  502. if (FAILED(hr)) {
  503. DBG_ERR(("CWiaItem::WriteMultiple, CheckPropertyAccess failed"));
  504. goto Cleanup;
  505. }
  506. //
  507. // First create the backup.
  508. //
  509. hr = m_pPropStg->Backup();
  510. if (SUCCEEDED(hr)) {
  511. //
  512. // Write property values.
  513. //
  514. hr = (m_pPropStg->CurStg())->WriteMultiple(newcpspec,
  515. newSpecs,
  516. newVals,
  517. propidNameFirst);
  518. if (SUCCEEDED(hr)) {
  519. //
  520. // Write was successful, so do validation
  521. //
  522. LONG lFlags = 0;
  523. //
  524. // Make sure all PropSpecs are using PropID's. If some of the
  525. // PropSpecs are using string names, then convert them.
  526. // This is so that drivers only have to deal with PropID's.
  527. //
  528. PROPSPEC *pPropSpec = NULL;
  529. hr = m_pPropStg->NamesToPropIDs(newcpspec, (PROPSPEC*) newSpecs, &pPropSpec);
  530. if (SUCCEEDED(hr)) {
  531. //
  532. // Let the device mini driver know the properties have changed.
  533. // Device only gets propspec, must read prop values from item's
  534. // property stream.
  535. //
  536. {
  537. LOCK_WIA_DEVICE _LWD(this, &hr);
  538. if(SUCCEEDED(hr)) {
  539. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvValidateItemProperties((BYTE*)this,
  540. lFlags,
  541. newcpspec,
  542. (pPropSpec ? pPropSpec : newSpecs),
  543. &m_lLastDevErrVal);
  544. }
  545. }
  546. if (pPropSpec) {
  547. LocalFree(pPropSpec);
  548. pPropSpec = NULL;
  549. }
  550. } else {
  551. DBG_ERR(("CWiaItem::WriteMultiple, conversion to PropIDs failed"));
  552. }
  553. } else {
  554. DBG_ERR(("CWiaItem::WriteMultiple, test write failed"));
  555. }
  556. HRESULT hresult;
  557. if (SUCCEEDED(hr)) {
  558. //
  559. // Validation passed, so free the backups. Use a new
  560. // HRESULT, since we don't want to overwrite hr returned by
  561. // drvValidateItemProperties.
  562. //
  563. hresult = m_pPropStg->ReleaseBackups();
  564. if (FAILED(hresult)) {
  565. DBG_ERR(("CWiaItem::WriteMultiple, ReleaseBackups failed, continuing anyway..."));
  566. }
  567. } else {
  568. //
  569. // Didn't pass validation failed, so restore old values. Use
  570. // a new HRESULT, since we don't want to overwrite hr returned
  571. // by drvValidateItemProperties.
  572. //
  573. hresult = m_pPropStg->Undo();
  574. if (FAILED(hresult)) {
  575. DBG_ERR(("CWiaItem::WriteMultiple, Undo() failed, could not restore invalid properties to their original values"));
  576. }
  577. }
  578. } else {
  579. DBG_ERR(("CWiaItem::WriteMultiple, couldn't make backup copy of properties"));
  580. }
  581. Cleanup:
  582. if(curVals) {
  583. FreePropVariantArray(cpspec, curVals);
  584. LocalFree(curVals);
  585. }
  586. if(newVals) LocalFree(newVals);
  587. if(newSpecs) LocalFree(newSpecs);
  588. return hr;
  589. }
  590. /**************************************************************************\
  591. * GetPropertyAttributes
  592. *
  593. * Get the access flags and valid values for a property.
  594. *
  595. * Arguments:
  596. *
  597. * pWiasContext - Pointer to WIA item
  598. * cPropSpec - The number of properties
  599. * pPropSpec - array of property specification.
  600. * pulAccessFlags - array of LONGs access flags.
  601. * pPropVar - Pointer to returned valid values.
  602. *
  603. * Return Value:
  604. *
  605. * Status
  606. *
  607. * History:
  608. *
  609. * 1/15/1999 Original Version
  610. * 07/19/1999 Moved from iitem to ipropitm to implement IWiaPropertyStorage
  611. * interface.
  612. *
  613. \**************************************************************************/
  614. HRESULT _stdcall CWiaItem::GetPropertyAttributes(
  615. ULONG cPropSpec,
  616. PROPSPEC pPropSpec[],
  617. ULONG pulAccessFlags[],
  618. PROPVARIANT ppvValidValues[])
  619. {
  620. DBG_FN(CWiaItem::GetPropertyAttributes);
  621. HRESULT hr;
  622. //
  623. // Check whether item properties have been initialized
  624. //
  625. if (!m_bInitialized) {
  626. hr = InitLazyProps();
  627. if (FAILED(hr)) {
  628. DBG_ERR(("CWiaItem::GetPropertyAttributes, InitLazyProps failed"));
  629. return hr;
  630. }
  631. }
  632. //
  633. // RPC has already done parameter validation for us, so call
  634. // GetPropertyAttributesHelper to do the work.
  635. //
  636. return GetPropertyAttributesHelper(this,
  637. cPropSpec,
  638. pPropSpec,
  639. pulAccessFlags,
  640. ppvValidValues);
  641. }
  642. /**************************************************************************\
  643. * CWiaItem::GetCount
  644. *
  645. * Returns the number of properties stored in an item's current value
  646. * property storage.
  647. *
  648. * Arguments:
  649. *
  650. * pulPropCount - Address to store the property count.
  651. *
  652. * Return Value:
  653. *
  654. * Status
  655. *
  656. * History:
  657. *
  658. * 9/3/1998 Original Version
  659. *
  660. \**************************************************************************/
  661. HRESULT _stdcall CWiaItem::GetCount(
  662. ULONG* pulPropCount)
  663. {
  664. DBG_FN(CWiaItem::GetCount);
  665. IEnumSTATPROPSTG *pIEnum;
  666. STATPROPSTG stg;
  667. ULONG ulCount;
  668. HRESULT hr = S_OK;
  669. if (pulPropCount == NULL) {
  670. DBG_ERR(("CWiaItem::GetCount, NULL parameter!"));
  671. return E_INVALIDARG;
  672. } else {
  673. *pulPropCount = 0;
  674. }
  675. //
  676. // Check whether item properties have been initialized
  677. //
  678. if (!m_bInitialized) {
  679. hr = InitLazyProps();
  680. if (FAILED(hr)) {
  681. DBG_ERR(("CWiaItem::GetCount, InitLazyProps failed"));
  682. return hr;
  683. }
  684. }
  685. hr = (m_pPropStg->CurStg())->Enum(&pIEnum);
  686. if (SUCCEEDED(hr)) {
  687. ulCount = 0;
  688. while (pIEnum->Next(1, &stg, NULL) == S_OK) {
  689. ulCount++;
  690. if(stg.lpwstrName) {
  691. CoTaskMemFree(stg.lpwstrName);
  692. }
  693. }
  694. if (SUCCEEDED(hr)) {
  695. hr = S_OK;
  696. *pulPropCount = ulCount;
  697. } else {
  698. DBG_ERR(("CWiaItem::GetCount, pIEnum->Next failed (0x%X)", hr));
  699. }
  700. pIEnum->Release();
  701. } else {
  702. DBG_ERR(("CWiaItem::GetCount, Enum off CurStg failed (0x%X)", hr));
  703. }
  704. return hr;
  705. }
  706. /**************************************************************************\
  707. * CWiaItem::GetPropertyStream
  708. *
  709. * Get a copy of an items property stream. Caller must free returned
  710. * property stream.
  711. *
  712. * Arguments:
  713. *
  714. * pCompatibilityId - Address of GUID to receive the device's property
  715. * stream CompatibilityId.
  716. * ppstmProp - Pointer to returned property stream.
  717. *
  718. * Return Value:
  719. *
  720. * Status
  721. *
  722. * History:
  723. *
  724. * 09/03/1998 Original Version
  725. * 12/12/1999 Modified to use CompatibilityId
  726. *
  727. \**************************************************************************/
  728. HRESULT _stdcall CWiaItem::GetPropertyStream(
  729. GUID *pCompatibilityId,
  730. LPSTREAM *ppstmProp)
  731. {
  732. DBG_FN(CWiaItem::GetPropertyStream);
  733. HRESULT hr;
  734. //
  735. // Check whether item properties have been initialized
  736. //
  737. if (!m_bInitialized) {
  738. hr = InitLazyProps();
  739. if (FAILED(hr)) {
  740. DBG_ERR(("CWiaItem::GetPropertyStream, InitLazyProps failed"));
  741. return hr;
  742. }
  743. }
  744. return m_pPropStg->GetPropertyStream(pCompatibilityId, ppstmProp);
  745. }
  746. /**************************************************************************\
  747. * CWiaItem::SetPropertyStream
  748. *
  749. * Set an items property stream.
  750. *
  751. * Arguments:
  752. *
  753. * pCompatibilityId - Pointer to a GUID representing the property
  754. * stream CompatibilityId.
  755. * pstmProp - Pointer to property stream.
  756. *
  757. * Return Value:
  758. *
  759. * Status
  760. *
  761. * History:
  762. *
  763. * 09/03/1998 Original Version
  764. * 12/12/1999 Modified to use CompatibilityId
  765. *
  766. \**************************************************************************/
  767. HRESULT _stdcall CWiaItem::SetPropertyStream(
  768. GUID *pCompatibilityId,
  769. LPSTREAM pstmProp)
  770. {
  771. DBG_FN(CWiaItem::SetPropertyStream);
  772. HRESULT hr;
  773. //
  774. // Check whether item properties have been initialized
  775. //
  776. if (!m_bInitialized) {
  777. hr = InitLazyProps();
  778. if (FAILED(hr)) {
  779. DBG_ERR(("CWiaItem::SetPropertyStream, InitLazyProps failed"));
  780. return hr;
  781. }
  782. }
  783. return m_pPropStg->SetPropertyStream(pCompatibilityId, this, pstmProp);
  784. }
  785. /**************************************************************************\
  786. *
  787. * Methods of IPropertyStorage not directly off IWiaPropertySTorage
  788. *
  789. * DeleteMultiple
  790. * DeletePropertyNames
  791. * Commit
  792. * Revert
  793. * SetTimes
  794. * SetClass
  795. * Stat
  796. *
  797. * 9/3/1998 Original Version
  798. *
  799. \**************************************************************************/
  800. HRESULT _stdcall CWiaItem::DeleteMultiple(
  801. ULONG cpspec,
  802. const PROPSPEC __RPC_FAR rgpspec[])
  803. {
  804. DBG_FN(CWiaItem::DeleteMultiple);
  805. return E_ACCESSDENIED;
  806. }
  807. HRESULT _stdcall CWiaItem::DeletePropertyNames(
  808. ULONG cpropid,
  809. const PROPID __RPC_FAR rgpropid[])
  810. {
  811. DBG_FN(CWiaItem::DeletePropertyNames);
  812. return E_ACCESSDENIED;
  813. }
  814. HRESULT _stdcall CWiaItem::Commit(DWORD grfCommitFlags)
  815. {
  816. DBG_FN(CWiaItem::Commit);
  817. HRESULT hr;
  818. //
  819. // Check whether item properties have been initialized
  820. //
  821. if (!m_bInitialized) {
  822. hr = InitLazyProps();
  823. if (FAILED(hr)) {
  824. DBG_ERR(("CWiaItem::Commit, InitLazyProps failed"));
  825. return hr;
  826. }
  827. }
  828. hr = (m_pPropStg->CurStg())->Commit(grfCommitFlags);
  829. return hr;
  830. }
  831. HRESULT _stdcall CWiaItem::Revert(void)
  832. {
  833. DBG_FN(CWiaItem::Revert);
  834. HRESULT hr;
  835. //
  836. // Check whether item properties have been initialized
  837. //
  838. if (!m_bInitialized) {
  839. hr = InitLazyProps();
  840. if (FAILED(hr)) {
  841. DBG_ERR(("CWiaItem::Revert, InitLazyProps failed"));
  842. return hr;
  843. }
  844. }
  845. hr = (m_pPropStg->CurStg())->Revert();
  846. return hr;
  847. }
  848. HRESULT _stdcall CWiaItem::SetTimes(
  849. const FILETIME __RPC_FAR *pctime,
  850. const FILETIME __RPC_FAR *patime,
  851. const FILETIME __RPC_FAR *pmtime)
  852. {
  853. DBG_FN(CWiaItem::SetTimes);
  854. HRESULT hr;
  855. //
  856. // Check whether item properties have been initialized
  857. //
  858. if (!m_bInitialized) {
  859. hr = InitLazyProps();
  860. if (FAILED(hr)) {
  861. DBG_ERR(("CWiaItem::SetTimes, InitLazyProps failed"));
  862. return hr;
  863. }
  864. }
  865. hr = (m_pPropStg->CurStg())->SetTimes(pctime,patime,pmtime);
  866. return hr;
  867. }
  868. HRESULT _stdcall CWiaItem::SetClass(REFCLSID clsid)
  869. {
  870. DBG_FN(CWiaItem::SetClass);
  871. HRESULT hr;
  872. //
  873. // Check whether item properties have been initialized
  874. //
  875. if (!m_bInitialized) {
  876. hr = InitLazyProps();
  877. if (FAILED(hr)) {
  878. DBG_ERR(("CWiaItem::SetClass, InitLazyProps failed"));
  879. return hr;
  880. }
  881. }
  882. return (m_pPropStg->CurStg())->SetClass(clsid);
  883. }
  884. HRESULT _stdcall CWiaItem::Stat(STATPROPSETSTG *pstatpsstg)
  885. {
  886. DBG_FN(CWiaItem::Stat);
  887. HRESULT hr;
  888. //
  889. // Check whether item properties have been initialized
  890. //
  891. if (!m_bInitialized) {
  892. hr = InitLazyProps();
  893. if (FAILED(hr)) {
  894. DBG_ERR(("CWiaItem::Stat, InitLazyProps failed"));
  895. return hr;
  896. }
  897. }
  898. hr = (m_pPropStg->CurStg())->Stat(pstatpsstg);
  899. return hr;
  900. }