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.

2507 lines
63 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: IItem.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 30 July, 1998
  12. *
  13. * DESCRIPTION:
  14. * Implementation of CWiaItem for WIA scanner class driver.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #include "stiexe.h"
  19. #define WIA_DECLARE_DEVINFO_PROP_ARRAY
  20. #include "wiamindr.h"
  21. #include "wiapsc.h"
  22. #define WIA_DECLARE_MANAGED_PROPS
  23. #include "helpers.h"
  24. #include "wiapropp.h"
  25. #include "ienumdc.h"
  26. #include "ienumitm.h"
  27. #include "callback.h"
  28. #include "devmgr.h"
  29. #include "wiaevntp.h"
  30. /**************************************************************************\
  31. * CopyDrvItemToTreeItem
  32. *
  33. * Create a CWiaTree object using a CWiaDrvItem as a template.
  34. *
  35. * Arguments:
  36. *
  37. * lFlags -
  38. * pCWiaDrvItemSrc -
  39. * ppCWiaTreeDst -
  40. *
  41. * Return Value:
  42. *
  43. * Status
  44. *
  45. * History:
  46. *
  47. * 1/19/1999 Original Version
  48. *
  49. \**************************************************************************/
  50. CopyDrvItemToTreeItem(
  51. LONG lFlags,
  52. CWiaDrvItem *pCWiaDrvItemSrc,
  53. CWiaItem *pCWiaItem,
  54. CWiaTree **ppCWiaTreeDst)
  55. {
  56. DBG_FN(::CopyDrvItemToTreeItem);
  57. HRESULT hr;
  58. *ppCWiaTreeDst = NULL;
  59. CWiaTree *pNewTreeItem = new CWiaTree;
  60. if (pNewTreeItem) {
  61. BSTR bstrItemName;
  62. hr = pCWiaDrvItemSrc->GetItemName(&bstrItemName);
  63. if (SUCCEEDED(hr)) {
  64. BSTR bstrFullItemName;
  65. hr = pCWiaDrvItemSrc->GetFullItemName(&bstrFullItemName);
  66. if (SUCCEEDED(hr)) {
  67. hr = pNewTreeItem->Initialize(lFlags,
  68. bstrItemName,
  69. bstrFullItemName,
  70. (void*)pCWiaItem);
  71. if (SUCCEEDED(hr)) {
  72. *ppCWiaTreeDst = pNewTreeItem;
  73. }
  74. SysFreeString(bstrFullItemName);
  75. }
  76. SysFreeString(bstrItemName);
  77. }
  78. if (FAILED(hr)) {
  79. delete pNewTreeItem;
  80. }
  81. }
  82. else {
  83. DBG_ERR(("CopyDrvItemToTreeItem, new CWiaTree failed"));
  84. hr = E_OUTOFMEMORY;
  85. }
  86. return hr;
  87. }
  88. /**************************************************************************\
  89. * UpdateWiaItemTree
  90. *
  91. * Update the application item tree. Called on the
  92. * parent of the new child item or item to unlink.
  93. *
  94. * Arguments:
  95. *
  96. * lFlag - Action to preform.
  97. * pWiaDrvItem -
  98. *
  99. * Return Value:
  100. *
  101. * Status
  102. *
  103. * History:
  104. *
  105. * 1/19/1999 Original Version
  106. *
  107. \**************************************************************************/
  108. HRESULT _stdcall CWiaItem::UpdateWiaItemTree(
  109. LONG lFlag,
  110. CWiaDrvItem *pWiaDrvItem)
  111. {
  112. DBG_FN(CWiaItem::UpdateWiaItemTree);
  113. HRESULT hr = S_OK;
  114. if (lFlag == DELETE_ITEM) {
  115. //
  116. // Unlink the item from the app item tree.
  117. //
  118. hr = m_pCWiaTree->RemoveItemFromFolder(WiaItemTypeDeleted);
  119. }
  120. else if (lFlag == ADD_ITEM) {
  121. //
  122. // Create a CWiaItem for this driver item.
  123. //
  124. CWiaItem *pItem = new CWiaItem();
  125. if (!pItem) {
  126. DBG_ERR(("UpdateWiaItemTree new CWiaItem failed"));
  127. return E_OUTOFMEMORY;
  128. }
  129. hr = pItem->Initialize(m_pIWiaItemRoot, NULL, m_pActiveDevice, pWiaDrvItem);
  130. if (SUCCEEDED(hr)) {
  131. //
  132. // Create a CWiaTree object for this node and add it to the tree.
  133. //
  134. LONG lFlags;
  135. pWiaDrvItem->GetItemFlags(&lFlags);
  136. hr = CopyDrvItemToTreeItem(lFlags,
  137. pWiaDrvItem,
  138. pItem,
  139. &pItem->m_pCWiaTree);
  140. if (SUCCEEDED(hr)) {
  141. hr = pItem->m_pCWiaTree->AddItemToFolder(m_pCWiaTree);
  142. if (SUCCEEDED(hr)) {
  143. return hr;
  144. }
  145. }
  146. }
  147. delete pItem;
  148. }
  149. else {
  150. DBG_ERR(("UpdateWiaItemTree unknown flag: 0x%08X", lFlag));
  151. hr = E_FAIL;
  152. }
  153. return hr;
  154. }
  155. /**************************************************************************\
  156. * BuildWiaItemTreeHelper
  157. *
  158. * Process the child items for BuildWiaItemTree.
  159. *
  160. * Arguments:
  161. *
  162. * pWiaDrvItem -
  163. * pTreeParent -
  164. *
  165. * Return Value:
  166. *
  167. * Status
  168. *
  169. * History:
  170. *
  171. * 1/19/1999 Original Version
  172. *
  173. \**************************************************************************/
  174. HRESULT _stdcall CWiaItem::BuildWiaItemTreeHelper(
  175. CWiaDrvItem *pWiaDrvItem,
  176. CWiaTree *pTreeParent)
  177. {
  178. DBG_FN(CWiaItem::BuildWiaItemTreeHelper);
  179. //
  180. // Walk the child items.
  181. //
  182. CWiaDrvItem *pChildDrvItem;
  183. HRESULT hr = pWiaDrvItem->GetFirstChildItem((IWiaDrvItem**) &pChildDrvItem);
  184. while (hr == S_OK) {
  185. //
  186. // Create a CWiaItem for this node.
  187. //
  188. CWiaItem *pItem = new CWiaItem();
  189. if (!pItem) {
  190. DBG_ERR(("BuildWiaItemTreeHelper new CWiaItem failed"));
  191. hr = E_OUTOFMEMORY;
  192. break;
  193. }
  194. hr = pItem->Initialize(m_pIWiaItemRoot, NULL, m_pActiveDevice, pChildDrvItem);
  195. if (SUCCEEDED(hr)) {
  196. //
  197. // Create a CWiaTree object for this node and add it to the tree.
  198. //
  199. LONG lFlags;
  200. pChildDrvItem->GetItemFlags(&lFlags);
  201. hr = CopyDrvItemToTreeItem(lFlags,
  202. pChildDrvItem,
  203. pItem,
  204. &pItem->m_pCWiaTree);
  205. if (SUCCEEDED(hr)) {
  206. hr = pItem->m_pCWiaTree->AddItemToFolder(pTreeParent);
  207. if (SUCCEEDED(hr)) {
  208. if (lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
  209. //
  210. // For folder items call BuildWiaItemTreeHelper recursively
  211. // to process the folders child items.
  212. //
  213. hr = BuildWiaItemTreeHelper((CWiaDrvItem*)pChildDrvItem,
  214. pItem->m_pCWiaTree);
  215. }
  216. }
  217. }
  218. //
  219. // Process the next sibling driver item.
  220. //
  221. if (SUCCEEDED(hr)) {
  222. hr = pChildDrvItem->GetNextSiblingItem((IWiaDrvItem**) &pChildDrvItem);
  223. }
  224. }
  225. else {
  226. delete pItem;
  227. }
  228. }
  229. //
  230. // Change S_FALSE to S_OK since S_FALSE simply means there are no more children to process.
  231. //
  232. if (hr == S_FALSE) {
  233. hr = S_OK;
  234. }
  235. return hr;
  236. }
  237. /**************************************************************************\
  238. * BuildWiaItemTree
  239. *
  240. * For root items, build a copy of the driver item tree and create a
  241. * CWiaItem for each node.
  242. *
  243. * Arguments:
  244. *
  245. * pIWiaItemRoot -
  246. * pIWiaMiniDrv -
  247. * pWiaDrvItem -
  248. *
  249. * Return Value:
  250. *
  251. * Status
  252. *
  253. * History:
  254. *
  255. * 1/19/1999 Original Version
  256. *
  257. \**************************************************************************/
  258. HRESULT _stdcall CWiaItem::BuildWiaItemTree(IWiaPropertyStorage *pIWiaDevInfoProps)
  259. {
  260. DBG_FN(CWiaItem::BuildWiaItemTree);
  261. //
  262. // Must be root item.
  263. //
  264. LONG lFlags;
  265. m_pWiaDrvItem->GetItemFlags(&lFlags);
  266. if (!(lFlags & WiaItemTypeRoot)) {
  267. DBG_ERR(("BuildWiaItemTree, caller doesn't have WiaItemTypeRoot set"));
  268. return E_INVALIDARG;
  269. }
  270. HRESULT hr = CopyDrvItemToTreeItem(lFlags, m_pWiaDrvItem, this, &m_pCWiaTree);
  271. if (SUCCEEDED(hr)) {
  272. //
  273. // Since this is the root item, initialize the root item properties with a
  274. // mirror of the DEVINFOPROPS (WIA_DIP_* ID's).
  275. //
  276. hr = InitRootProperties(pIWiaDevInfoProps);
  277. if (FAILED(hr)) {
  278. DBG_TRC(("BuildWiaItemTree, InitRootProperties, about to unlink..."));
  279. UnlinkAppItemTree(WiaItemTypeDeleted);
  280. return hr;
  281. }
  282. //
  283. // Process the child items.
  284. //
  285. hr = BuildWiaItemTreeHelper(m_pWiaDrvItem,
  286. m_pCWiaTree);
  287. if (FAILED(hr)) {
  288. DBG_TRC(("BuildWiaItemTree, BuildWiaItemTreeHelper failed, about to unlink..."));
  289. UnlinkAppItemTree(WiaItemTypeDeleted);
  290. }
  291. }
  292. return hr;
  293. }
  294. /**************************************************************************\
  295. * InitWiaManagedItemProperties
  296. *
  297. * A private helper for CWiaItem::Initialize, which initializes the
  298. * WIA managed item properties based on the driver item values.
  299. *
  300. * Arguments:
  301. *
  302. * None
  303. *
  304. * Return Value:
  305. *
  306. * Status
  307. *
  308. * History:
  309. *
  310. * 1/19/1999 Original Version
  311. *
  312. \**************************************************************************/
  313. HRESULT _stdcall CWiaItem::InitWiaManagedItemProperties(
  314. IWiaPropertyStorage *pIWiaDevInfoProps)
  315. {
  316. DBG_FN(CWiaItem::InitWiaManagedItemProperties);
  317. ULONG ulNumProps;
  318. ulNumProps = (m_pIWiaItemRoot == this) ? NUM_WIA_MANAGED_PROPS - 1 : NUM_WIA_MANAGED_PROPS;
  319. //
  320. // WIA manages the item name and type properties, so set the
  321. // property names here.
  322. //
  323. HRESULT hr = wiasSetItemPropNames((BYTE*)this,
  324. ulNumProps,
  325. s_piItemNameType,
  326. s_pszItemNameType);
  327. //
  328. // Set the name and type properties attributes.
  329. //
  330. PROPVARIANT pv;
  331. ULONG ulFlag;
  332. for (UINT i = 0; i < ulNumProps; i++) {
  333. if (i == PROFILE_INDEX) {
  334. pv.vt = VT_BSTR | VT_VECTOR;
  335. ulFlag = WIA_PROP_RW | WIA_PROP_CACHEABLE | WIA_PROP_LIST;
  336. } else {
  337. pv.vt = VT_I4;
  338. ulFlag = WIA_PROP_READ | WIA_PROP_CACHEABLE | WIA_PROP_NONE;
  339. }
  340. pv.ulVal = 0;
  341. hr = wiasSetPropertyAttributes((BYTE*)this,
  342. 1,
  343. &s_psItemNameType[i],
  344. &ulFlag,
  345. &pv);
  346. if (FAILED(hr)) {
  347. DBG_ERR(("CWiaItem::Initialize, wiasSetPropertyAttributes failed, index: %d", i));
  348. break;
  349. }
  350. }
  351. //
  352. // Get the item names and type from the driver item and set
  353. // them to the item properties.
  354. //
  355. BSTR bstrItemName;
  356. BSTR bstrFullItemName;
  357. hr = m_pWiaDrvItem->GetItemName(&bstrItemName);
  358. if (SUCCEEDED(hr)) {
  359. hr = m_pWiaDrvItem->GetFullItemName(&bstrFullItemName);
  360. if (SUCCEEDED(hr)) {
  361. LONG lFlags;
  362. m_pWiaDrvItem->GetItemFlags(&lFlags); // Can't fail, except on param validate.
  363. //
  364. // Set the item names and type.
  365. //
  366. PROPVARIANT *propvar;
  367. propvar = (PROPVARIANT*) LocalAlloc(LPTR, sizeof(PROPVARIANT) * ulNumProps);
  368. if (propvar) {
  369. memset(propvar, 0, sizeof(PROPVARIANT) * ulNumProps);
  370. propvar[0].vt = VT_BSTR;
  371. propvar[0].bstrVal = bstrItemName;
  372. propvar[1].vt = VT_BSTR;
  373. propvar[1].bstrVal = bstrFullItemName;
  374. propvar[2].vt = VT_I4;
  375. propvar[2].lVal = lFlags;
  376. hr = (m_pPropStg->CurStg())->WriteMultiple(ulNumProps,
  377. s_psItemNameType,
  378. propvar,
  379. WIA_DIP_FIRST);
  380. if (SUCCEEDED(hr)) {
  381. //
  382. // Fill in ICM Profile information
  383. //
  384. hr = FillICMPropertyFromRegistry(pIWiaDevInfoProps, (IWiaItem*) this);
  385. }
  386. if (FAILED(hr)) {
  387. ReportReadWriteMultipleError(hr, "CWiaItem::InitWiaManagedItemProperties",
  388. NULL,
  389. FALSE,
  390. ulNumProps,
  391. s_psItemNameType);
  392. }
  393. LocalFree(propvar);
  394. } else {
  395. DBG_ERR(("CWiaItem::InitWiaManagedItemProperties, Out of Memory!"));
  396. hr = E_OUTOFMEMORY;
  397. }
  398. SysFreeString(bstrFullItemName);
  399. }
  400. SysFreeString(bstrItemName);
  401. }
  402. return hr;
  403. }
  404. /**************************************************************************\
  405. *
  406. * InitRootProperties
  407. *
  408. * A private helper for CWiaItem::Initialize, which initializes the
  409. * root item properties to a mirror of DEVINFOPROPS.
  410. *
  411. * Arguments:
  412. *
  413. * None
  414. *
  415. * Return Value:
  416. *
  417. * status
  418. *
  419. * History:
  420. *
  421. * 9/3/1998 Original Version
  422. *
  423. \**************************************************************************/
  424. HRESULT _stdcall CWiaItem::InitRootProperties(IWiaPropertyStorage *pIWiaDevInfoProps)
  425. {
  426. DBG_FN(CWiaItem::InitRootProperties);
  427. HRESULT hr = S_OK;
  428. //
  429. // Write the root item property names.
  430. //
  431. hr = WriteItemPropNames(NUMROOTITEMPROPS, g_piRootItem, g_pszRootItem);
  432. if (FAILED(hr)) {
  433. DBG_ERR(("CWiaItem::InitRootProperties, WritePropNames failed"));
  434. return hr;
  435. }
  436. //
  437. // Copy the device information properties from source to destination.
  438. //
  439. PROPVARIANT propvar[WIA_NUM_DIP];
  440. ULONG ulIndex;
  441. memset(propvar, 0, sizeof(propvar));
  442. hr = pIWiaDevInfoProps->ReadMultiple(WIA_NUM_DIP,
  443. g_psDeviceInfo,
  444. propvar);
  445. if (SUCCEEDED(hr)) {
  446. hr = (m_pPropStg->CurStg())->WriteMultiple(WIA_NUM_DIP,
  447. g_psDeviceInfo,
  448. propvar,
  449. WIA_DIP_FIRST);
  450. if (FAILED(hr)) {
  451. ReportReadWriteMultipleError(hr, "InitRootProperties", NULL, FALSE, WIA_NUM_DIP, g_psDeviceInfo);
  452. }
  453. FreePropVariantArray(WIA_NUM_DIP, propvar);
  454. }
  455. else {
  456. ReportReadWriteMultipleError(hr, "InitRootProperties", NULL, TRUE, WIA_NUM_DIP, g_psDeviceInfo);
  457. DBG_ERR(("CWiaItem::InitRootProperties failed"));
  458. return hr;
  459. }
  460. //
  461. // Write out the property info from our private array.
  462. //
  463. hr = wiasSetItemPropAttribs((BYTE*)this,
  464. NUMROOTITEMPROPS,
  465. g_psRootItem,
  466. g_wpiRootItem);
  467. if (SUCCEEDED(hr) && m_pActiveDevice->m_DrvWrapper.IsVolumeDevice()) {
  468. //
  469. // This is a volume device. We must add some volume specific properties
  470. //
  471. hr = AddVolumePropertiesToRoot(m_pActiveDevice);
  472. }
  473. return hr;
  474. }
  475. /*******************************************************************************
  476. *
  477. * QueryInterface
  478. * AddRef
  479. * Release
  480. *
  481. * DESCRIPTION:
  482. * IUnknown Interface. AddRef and Release mantain a global refernce count
  483. * of all device objects on the root item.
  484. *
  485. * PARAMETERS:
  486. *
  487. *******************************************************************************/
  488. HRESULT _stdcall CWiaItem::QueryInterface(const IID& iid, void** ppv)
  489. {
  490. *ppv = NULL;
  491. if (iid == IID_IUnknown || iid == IID_IWiaItem) {
  492. *ppv = (IWiaItem*) this;
  493. } else if (iid == IID_IWiaPropertyStorage) {
  494. *ppv = (IWiaPropertyStorage*) this;
  495. } else if (iid == IID_IPropertyStorage) {
  496. *ppv = (IPropertyStorage*) this;
  497. } else if (iid == IID_IWiaDataTransfer) {
  498. *ppv = (IWiaDataTransfer*) this;
  499. } else if (iid == IID_IWiaItemInternal) {
  500. *ppv = (IWiaItemInternal*) this;
  501. } else if (iid == IID_IWiaItemExtras) {
  502. *ppv = (IWiaItemExtras*) this;
  503. } else {
  504. //
  505. // Blind aggregation to optional inner component.
  506. //
  507. if (m_pIUnknownInner) {
  508. return m_pIUnknownInner->QueryInterface(iid, ppv);
  509. }
  510. else {
  511. return E_NOINTERFACE;
  512. }
  513. }
  514. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  515. return (S_OK);
  516. }
  517. ULONG _stdcall CWiaItem::AddRef()
  518. {
  519. DBG_FN(CWiaItem::AddRef);
  520. TAKE_ACTIVE_DEVICE tad(m_pActiveDevice);
  521. LONG lType = 0;
  522. LONG lRef = 1;
  523. lRef = InterlockedIncrement((long*) &m_cLocalRef);
  524. GetItemType(&lType);
  525. if (!(lType & WiaItemTypeRemoved)) {
  526. lRef = InterlockedIncrement((long*) &(((CWiaItem*)m_pIWiaItemRoot)->m_cRef));
  527. }
  528. return lRef;
  529. }
  530. ULONG _stdcall CWiaItem::Release()
  531. {
  532. DBG_FN(CWiaItem::Release);
  533. LONG lType = 0;
  534. ULONG ulRef = InterlockedDecrement((long*)&m_cLocalRef);
  535. GetItemType(&lType);
  536. if (lType & WiaItemTypeRemoved) {
  537. if (ulRef == 0) {
  538. delete this;
  539. return 0;
  540. } else {
  541. return m_cLocalRef;
  542. }
  543. } else if (InterlockedDecrement((long*) &(((CWiaItem*)m_pIWiaItemRoot)->m_cRef)) == 0) {
  544. ulRef = ((CWiaItem*)m_pIWiaItemRoot)->m_cRef;
  545. //
  546. // If the combined refernce count of the root item goes to zero
  547. // first notify driver that client connection is being removed, then
  548. // unlink the tree and release all of the items.
  549. //
  550. //
  551. // But first cleanup any remote transfers in progress that are a
  552. // result of crashed or malicious clients
  553. //
  554. CWiaItem * pItem = (CWiaItem*) m_pIWiaItemRoot;
  555. while(pItem) {
  556. CWiaRemoteTransfer *pTransfer =
  557. (CWiaRemoteTransfer *)InterlockedExchangePointer((PVOID *)&pItem->m_pRemoteTransfer, NULL);
  558. if(pTransfer) {
  559. CleanupRemoteTransfer(pTransfer);
  560. }
  561. pItem = pItem->GetNextLinearItem();
  562. }
  563. HRESULT hr = E_FAIL;
  564. LONG lDevErrVal = 0;
  565. ACTIVE_DEVICE *pActiveDevice = m_pActiveDevice;
  566. //
  567. // Call drvUnInitialize if it hasn't been called yet (could have been
  568. // called if driver was unloaded).
  569. // Note that we must check flags on the ROOT item.
  570. //
  571. if (!(((CWiaItem*)m_pIWiaItemRoot)->m_lInternalFlags & ITEM_FLAG_DRV_UNINITIALIZE_THROWN)) {
  572. {
  573. LOCK_WIA_DEVICE _LWD(this, &hr);
  574. if(SUCCEEDED(hr)) {
  575. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvUnInitializeWia((BYTE*)m_pIWiaItemRoot);
  576. }
  577. m_lInternalFlags |= ITEM_FLAG_DRV_UNINITIALIZE_THROWN;
  578. }
  579. }
  580. DBG_TRC(("CWiaItem::Release, m_cRef = 0, about to unlink..."));
  581. UnlinkAppItemTree(WiaItemTypeDeleted);
  582. if (pActiveDevice) {
  583. //
  584. // Release the ACTIVE_DEVICE object. Notice that we release it AFTER
  585. // the item is through with it.
  586. //
  587. pActiveDevice->Release();
  588. pActiveDevice = NULL;
  589. }
  590. }
  591. return ulRef;
  592. }
  593. /**************************************************************************\
  594. * CWiaItem::UnlinkChildAppItemTree
  595. *
  596. * This method recursively unlinks the tree by calling
  597. * RemoveItemFromFolder on each item under the root.
  598. *
  599. * Arguments:
  600. *
  601. * lReason - Reason for unlink of tree.
  602. *
  603. * Return Value:
  604. *
  605. * Status
  606. *
  607. * History:
  608. *
  609. * 1/21/1999 Original Version
  610. *
  611. \**************************************************************************/
  612. HRESULT _stdcall CWiaItem::UnlinkChildAppItemTree(LONG lReason)
  613. {
  614. DBG_FN(CWiaItem::UnlinkChildAppItemTree);
  615. //
  616. // Check that we have a valid tree
  617. //
  618. if (!m_pCWiaTree) {
  619. return S_FALSE;
  620. }
  621. //
  622. // Delete the childern.
  623. //
  624. CWiaTree *pChild, *pNext;
  625. HRESULT hr = m_pCWiaTree->GetFirstChildItem(&pChild);
  626. while (hr == S_OK) {
  627. //
  628. // Get a tree items associated app item.
  629. //
  630. CWiaItem *pChildAppItem;
  631. pChildAppItem = NULL;
  632. hr = pChild->GetItemData((void**)&pChildAppItem);
  633. if (hr == S_OK) {
  634. //
  635. // If the child is a folder then call
  636. // recursively to delete all childern under.
  637. //
  638. LONG lFlags;
  639. pChild->GetItemFlags(&lFlags);
  640. if (lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
  641. hr = pChildAppItem->UnlinkChildAppItemTree(lReason);
  642. if (FAILED(hr)) {
  643. break;
  644. }
  645. }
  646. }
  647. else {
  648. DBG_ERR(("CWiaItem::UnlinkChildAppItemTree no app item on tree item: %X", pChild));
  649. }
  650. hr = pChild->GetNextSiblingItem(&pNext);
  651. //
  652. // Remove item from tree.
  653. //
  654. pChild->RemoveItemFromFolder(lReason);
  655. //
  656. // Delete the child item.
  657. //
  658. if (pChildAppItem) {
  659. delete pChildAppItem;
  660. }
  661. pChild = pNext;
  662. }
  663. return hr;
  664. }
  665. /**************************************************************************\
  666. * CWiaItem::UnlinkAppItemTree
  667. *
  668. * This method unlinks the app item tree.
  669. *
  670. * Arguments:
  671. *
  672. * lReason - Reason for unlinking the tree.
  673. *
  674. * Return Value:
  675. *
  676. * Status
  677. *
  678. * History:
  679. *
  680. * 1/21/1999 Original Version
  681. *
  682. \**************************************************************************/
  683. HRESULT _stdcall CWiaItem::UnlinkAppItemTree(LONG lReason)
  684. {
  685. DBG_FN(CWiaItem::UnlinkAppItemTree);
  686. //
  687. // Work off of the root item.
  688. //
  689. CWiaItem *pRoot = (CWiaItem*) m_pIWiaItemRoot;
  690. //
  691. // Unlink any childern.
  692. //
  693. pRoot->UnlinkChildAppItemTree(lReason);
  694. //
  695. // Finally, delete the root item.
  696. //
  697. delete pRoot;
  698. return S_OK;
  699. }
  700. /**************************************************************************\
  701. * CWiaItem::CWiaItem
  702. *
  703. * CWiaItem Constructor Method.
  704. *
  705. * Arguments:
  706. *
  707. * None
  708. *
  709. * Return Value:
  710. *
  711. * Status
  712. *
  713. * History:
  714. *
  715. * 11/11/1998 Original Version
  716. *
  717. \**************************************************************************/
  718. CWiaItem::CWiaItem()
  719. {
  720. m_ulSig = CWIAITEM_SIG;
  721. m_cRef = 0;
  722. m_cLocalRef = 0;
  723. m_pWiaDrvItem = NULL;
  724. m_pActiveDevice = NULL;
  725. m_pIUnknownInner = NULL;
  726. m_pCWiaTree = NULL;
  727. m_pIWiaItemRoot = this;
  728. m_bInitialized = FALSE;
  729. m_pICMValues = NULL;
  730. m_lICMSize = 0;
  731. m_pPropStg = NULL;
  732. m_hBandSection = NULL;
  733. m_pBandBuffer = NULL;
  734. m_lBandBufferLength = 0;
  735. m_ClientBaseAddress = 0;
  736. m_bMapSection = FALSE;
  737. m_cwfiBandedTran = 0;
  738. m_pwfiBandedTran = NULL;
  739. m_pRemoteTransfer = NULL;
  740. m_lLastDevErrVal = 0;
  741. m_lInternalFlags = 0;
  742. }
  743. /**************************************************************************\
  744. * CWiaItem::Initialize
  745. *
  746. * CWiaItem Initialize method.
  747. *
  748. * Arguments:
  749. *
  750. * pIWiaItemRoot -
  751. * pIWiaMiniDrv -
  752. * pWiaDrvItem -
  753. * pIUnknownInner -
  754. *
  755. * Return Value:
  756. *
  757. * Status
  758. *
  759. * History:
  760. *
  761. * 11/11/1998 Original Version
  762. *
  763. \**************************************************************************/
  764. HRESULT _stdcall CWiaItem::Initialize(
  765. IWiaItem *pIWiaItemRoot,
  766. IWiaPropertyStorage *pIWiaDevInfoProps,
  767. ACTIVE_DEVICE *pActiveDevice,
  768. CWiaDrvItem *pWiaDrvItem,
  769. IUnknown *pIUnknownInner)
  770. {
  771. DBG_FN(CWiaItem::Initialize);
  772. #ifdef DEBUG
  773. BSTR bstr;
  774. if SUCCEEDED(pWiaDrvItem->GetItemName(&bstr)) {
  775. DBG_TRC(("CWiaItem::Initialize: 0x%08X, %S, drv item: 0x%08X", this, bstr, pWiaDrvItem));
  776. SysFreeString(bstr);
  777. }
  778. #endif
  779. //
  780. // Validate parameters
  781. //
  782. if (!pActiveDevice || !pIWiaItemRoot || !pWiaDrvItem) {
  783. DBG_ERR(("CWiaItem::Initialize NULL input parameters"));
  784. return E_POINTER;
  785. }
  786. //
  787. // If optional inner component is present, save a pointer to it.
  788. //
  789. if (pIUnknownInner) {
  790. DBG_TRC(("CWiaItem::Initialize, pIUnknownInner: %X", pIUnknownInner));
  791. m_pIUnknownInner = pIUnknownInner;
  792. }
  793. //
  794. // Link to the items corresponding driver item.
  795. //
  796. m_pWiaDrvItem = pWiaDrvItem;
  797. m_pIWiaItemRoot = pIWiaItemRoot;
  798. m_pActiveDevice = pActiveDevice;
  799. m_pWiaDrvItem->SetActiveDevice(pActiveDevice);
  800. HRESULT hr = pWiaDrvItem->LinkToDrvItem(this);
  801. if (FAILED(hr)) {
  802. DBG_ERR(("CWiaItem::Initialize, LinkToDrvItem failed"));
  803. return hr;
  804. }
  805. //
  806. // Create streams and property storage for item properties.
  807. //
  808. m_pPropStg = new CWiaPropStg();
  809. if (m_pPropStg) {
  810. hr = m_pPropStg->Initialize();
  811. if (FAILED(hr)) {
  812. delete m_pPropStg;
  813. m_pPropStg = NULL;
  814. DBG_ERR(("CWiaItem::Initialize, PropertyStorage Initialize failed"));
  815. return hr;
  816. }
  817. } else {
  818. DBG_ERR(("CWiaItem::Initialize, not enough memory to create CWiaPropStg"));
  819. hr = E_OUTOFMEMORY;
  820. return hr;
  821. }
  822. //
  823. // Initialize the WIA managed item properties (name, full name, type, ...)
  824. // from the driver item. Must set m_bInitialized to TRUE so that
  825. // InitWiaManagedProperties doesn't attempt to InitLazyProps()
  826. //
  827. m_bInitialized = TRUE;
  828. hr = InitWiaManagedItemProperties(pIWiaDevInfoProps);
  829. pWiaDrvItem->AddRef();
  830. if (FAILED(hr)) {
  831. DBG_ERR(("CWiaItem::Initialize, InitWiaManagedItemProperties failed"));
  832. m_bInitialized = FALSE;
  833. return hr;
  834. }
  835. //
  836. // If this is the root item, build a copy of the driver item tree
  837. // and create a CWiaItem for each node.
  838. //
  839. if (this == pIWiaItemRoot) {
  840. hr = BuildWiaItemTree(pIWiaDevInfoProps);
  841. }
  842. if (FAILED(hr)) {
  843. DBG_ERR(("CWiaItem::Initialize, BuildWiaItemTree failed"));
  844. return hr;
  845. }
  846. m_bInitialized = FALSE;
  847. return hr;
  848. }
  849. /**************************************************************************\
  850. * CWiaItem::InitLazyProps
  851. *
  852. * Helper used to implement lazy initialization. Property initialization
  853. * is put off until the item is being accessed by an application for the
  854. * first time.
  855. *
  856. * Arguments:
  857. *
  858. * bLockDevice - bool value specifying whether a lock is needed.
  859. *
  860. * Return Value:
  861. *
  862. * Status
  863. *
  864. * History:
  865. *
  866. * 10/10/1999 Original Version
  867. *
  868. \**************************************************************************/
  869. HRESULT _stdcall CWiaItem::InitLazyProps(
  870. BOOL bLockDevice)
  871. {
  872. DBG_FN(CWiaItem::InitLazyProps);
  873. HRESULT hr = S_OK;
  874. LONG lFlags = 0;
  875. //
  876. // Must set to TRUE before call to drvInitItemProperties
  877. //
  878. m_bInitialized = TRUE;
  879. //
  880. // Call the device to initialize the item properties.
  881. //
  882. {
  883. LOCK_WIA_DEVICE _LWD(bLockDevice, this, &hr);
  884. if(SUCCEEDED(hr)) {
  885. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvInitItemProperties((BYTE*)this,lFlags, &m_lLastDevErrVal);
  886. }
  887. }
  888. if (FAILED(hr)) {
  889. m_bInitialized = FALSE;
  890. }
  891. return hr;
  892. }
  893. /**************************************************************************\
  894. * CWiaItem::~CWiaItem
  895. *
  896. * CWiaItem Destructor Method.
  897. *
  898. * Arguments:
  899. *
  900. * None
  901. *
  902. * Return Value:
  903. *
  904. * Status
  905. *
  906. * History:
  907. *
  908. * 11/11/1998 Original Version
  909. *
  910. \**************************************************************************/
  911. CWiaItem::~CWiaItem()
  912. {
  913. DBG_FN(CWiaItem::~CWiaItem);
  914. #ifdef ITEM_TRACE
  915. BSTR bstr;
  916. if (m_pWiaDrvItem && SUCCEEDED(m_pWiaDrvItem->GetItemName(&bstr))) {
  917. DBG_TRC(("CWiaItem destroy: %08X, %S", this, bstr));
  918. SysFreeString(bstr);
  919. }
  920. else {
  921. DBG_TRC(("CWiaItem destroy: %08X", this));
  922. }
  923. #endif
  924. CWiaRemoteTransfer *pRemoteTransfer =
  925. (CWiaRemoteTransfer *) InterlockedExchangePointer((PVOID *)&m_pRemoteTransfer, NULL);
  926. if(pRemoteTransfer) {
  927. CleanupRemoteTransfer(m_pRemoteTransfer);
  928. }
  929. //
  930. // Delete the associated tree item.
  931. //
  932. if (m_pCWiaTree) {
  933. delete m_pCWiaTree;
  934. m_pCWiaTree = NULL;
  935. }
  936. //
  937. // Release WiaDrvItem. If ref count of m_pWiaDrvItem goes to zero
  938. // it will be destroyed at this time. For the ref count to be zero
  939. // no other CWiaItem object may have reference to it and it must be
  940. // disconnected from the device item tree.
  941. //
  942. if (m_pWiaDrvItem) {
  943. //
  944. // Unlink from the app item's corresponding driver item.
  945. //
  946. m_pWiaDrvItem->UnlinkFromDrvItem(this);
  947. m_pWiaDrvItem->Release();
  948. m_pWiaDrvItem = NULL;
  949. }
  950. //
  951. // Free the item property storage and streams.
  952. //
  953. if (m_pPropStg) {
  954. delete m_pPropStg;
  955. m_pPropStg = NULL;
  956. }
  957. //
  958. // Free the cached ICM values
  959. //
  960. if (m_pICMValues) {
  961. LocalFree(m_pICMValues);
  962. m_pICMValues = NULL;
  963. }
  964. //
  965. // Set other members to empty since we're done with this item.
  966. //
  967. m_pWiaDrvItem = NULL;
  968. m_pIUnknownInner = NULL;
  969. m_pIWiaItemRoot = NULL;
  970. m_bInitialized = FALSE;
  971. m_lICMSize = 0;
  972. m_hBandSection = NULL;
  973. m_pBandBuffer = NULL;
  974. m_lBandBufferLength = 0;
  975. m_ClientBaseAddress = 0;
  976. m_bMapSection = FALSE;
  977. m_cwfiBandedTran = 0;
  978. m_pwfiBandedTran = NULL;
  979. m_lInternalFlags = 0;
  980. }
  981. /**************************************************************************\
  982. * CWiaItem::GetItemType
  983. *
  984. * Get the item type from the corresponding driver item.
  985. *
  986. * Arguments:
  987. *
  988. * pItemType - Pointer to the returned item type.
  989. *
  990. * Return Value:
  991. *
  992. * Status
  993. *
  994. * History:
  995. *
  996. * 11/11/1998 Original Version
  997. *
  998. \**************************************************************************/
  999. HRESULT _stdcall CWiaItem::GetItemType(LONG *pItemType)
  1000. {
  1001. DBG_FN(CWiaItem::GetItemType);
  1002. LONG lFlags = 0;
  1003. HRESULT hr = S_FALSE;
  1004. if (m_pWiaDrvItem) {
  1005. //
  1006. // Get the driver item flags. This is the flags basis for App. Items
  1007. // that were created as a result of copying the driver item tree i.e.
  1008. // non-generated items.
  1009. //
  1010. hr = m_pWiaDrvItem->GetItemFlags(&lFlags);
  1011. if (SUCCEEDED(hr)) {
  1012. //
  1013. // The App. item may have analysis-generated children, which the
  1014. // corresponding driver item wont have. So check whether this
  1015. // item has children, and adjust the flags accordingly.
  1016. //
  1017. if (m_pCWiaTree) {
  1018. if (m_pCWiaTree->GetFirstChildItem(NULL) == S_OK) {
  1019. //
  1020. // Has children, so clear File flag and set Folder
  1021. //
  1022. if (!(lFlags & WiaItemTypeHasAttachments))
  1023. {
  1024. lFlags = (lFlags | WiaItemTypeFolder) & ~WiaItemTypeFile;
  1025. }
  1026. }
  1027. }
  1028. *pItemType = lFlags;
  1029. } else {
  1030. DBG_ERR(("CWiaItem::GetItemType, Could not get the driver item flags!"));
  1031. }
  1032. }
  1033. return hr;
  1034. }
  1035. /**************************************************************************\
  1036. * CWiaItem::EnumChildItems
  1037. *
  1038. * Enumerate all child items under the current item, providing the
  1039. * item is a folder
  1040. *
  1041. * Arguments:
  1042. *
  1043. * ppIEnumWiaItem - return an IEnumWiaItem object to the caller
  1044. *
  1045. * Return Value:
  1046. *
  1047. * Status
  1048. *
  1049. * History:
  1050. *
  1051. * 11/11/1998 Original Version
  1052. *
  1053. \**************************************************************************/
  1054. HRESULT _stdcall CWiaItem::EnumChildItems(IEnumWiaItem **ppIEnumWiaItem)
  1055. {
  1056. DBG_FN(CWiaItem::EnumChildItems);
  1057. HRESULT hr;
  1058. //
  1059. // Corresponding driver item must be valid.
  1060. //
  1061. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1062. if (FAILED(hr)) {
  1063. DBG_ERR(("CWiaItem::EnumChildItems, ValidateWiaDrvItemAccess failed"));
  1064. return hr;
  1065. }
  1066. //
  1067. // Validate parameters
  1068. //
  1069. if (ppIEnumWiaItem == NULL) {
  1070. DBG_ERR(("CWiaItem::EnumChildItems NULL input parameters"));
  1071. return E_POINTER;
  1072. }
  1073. *ppIEnumWiaItem = NULL;
  1074. //
  1075. // Create the enumerator object.
  1076. //
  1077. CEnumWiaItem* pEnumWiaItem = new CEnumWiaItem();
  1078. if (pEnumWiaItem != NULL) {
  1079. //
  1080. // Initialize the enumerator object.
  1081. //
  1082. hr = pEnumWiaItem->Initialize(this);
  1083. if (SUCCEEDED(hr)) {
  1084. //
  1085. // get IID_IEnumWiaItem Interface
  1086. //
  1087. hr = pEnumWiaItem->QueryInterface(IID_IEnumWiaItem, (void **)ppIEnumWiaItem);
  1088. if (FAILED(hr)) {
  1089. DBG_ERR(("CWiaItem::EnumChildItems, QI of IID_IEnumWiaItem failed"));
  1090. delete pEnumWiaItem;
  1091. }
  1092. }
  1093. else {
  1094. delete pEnumWiaItem;
  1095. }
  1096. }
  1097. else {
  1098. DBG_ERR(("CWiaItem::EnumChildItems, new CEnumWiaItem failed"));
  1099. hr = E_OUTOFMEMORY;
  1100. }
  1101. return hr;
  1102. }
  1103. CWiaItem* _stdcall CWiaItem::GetNextLinearItem(void)
  1104. {
  1105. return m_pCWiaTree ?
  1106. m_pCWiaTree->GetNextLinearItem() : NULL;
  1107. }
  1108. CWiaItem* _stdcall CWiaTree::GetNextLinearItem()
  1109. {
  1110. if(m_pLinearList && m_pLinearList->m_pData) {
  1111. return static_cast<CWiaItem *>(m_pLinearList->m_pData);
  1112. } else {
  1113. return NULL;
  1114. }
  1115. }
  1116. /**************************************************************************\
  1117. * DeleteItem
  1118. *
  1119. * Applications use this method to delete items.
  1120. *
  1121. * Arguments:
  1122. *
  1123. * lFlags
  1124. *
  1125. * Return Value:
  1126. *
  1127. * Status
  1128. *
  1129. * History:
  1130. *
  1131. * 1/19/1999 Original Version
  1132. *
  1133. \**************************************************************************/
  1134. HRESULT _stdcall CWiaItem::DeleteItem(LONG lFlags)
  1135. {
  1136. DBG_FN(CWiaItem::DeleteItem);
  1137. LONG lItemFlags;
  1138. HRESULT hr;
  1139. IWiaDrvItem *pIChildItem = NULL;
  1140. LONG lAccessRights;
  1141. //
  1142. // Corresponding driver item must be valid.
  1143. //
  1144. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1145. if (FAILED(hr)) {
  1146. DBG_ERR(("CWiaItem::DeleteItem, ValidateWiaDrvItemAccess failed"));
  1147. return hr;
  1148. }
  1149. //
  1150. // Check whether item properties have been initialized
  1151. //
  1152. if (!m_bInitialized) {
  1153. hr = InitLazyProps();
  1154. if (FAILED(hr)) {
  1155. DBG_ERR(("CWiaItem::DeleteItem, InitLazyProps failed"));
  1156. return hr;
  1157. }
  1158. }
  1159. GetItemType(&lItemFlags);
  1160. //
  1161. // Root item can not be deleted, the application needs it
  1162. // in order to release the device.
  1163. //
  1164. if (lItemFlags & WiaItemTypeRoot) {
  1165. DBG_ERR(("CWiaItem::DeleteItem, Deletion was attempted on a Root Item"));
  1166. return (E_INVALIDARG);
  1167. }
  1168. //
  1169. // Folder can be deleted only when it is empty
  1170. //
  1171. if (lItemFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
  1172. if (m_pCWiaTree->GetFirstChildItem(NULL) == S_OK) {
  1173. DBG_ERR(("CWiaItem::DeleteItem, Item still has children!"));
  1174. return (E_INVALIDARG);
  1175. }
  1176. }
  1177. //
  1178. // Check whether the item can be deleted. Generated items can always be
  1179. // deleted regardless of AccessRights
  1180. //
  1181. hr = wiasReadPropLong((BYTE*)this, WIA_IPA_ACCESS_RIGHTS, &lAccessRights, NULL, false);
  1182. if (hr == S_OK) {
  1183. if (!((lAccessRights & WIA_ITEM_CAN_BE_DELETED) || (lItemFlags & WiaItemTypeGenerated))){
  1184. DBG_ERR(("CWiaItem::DeleteItem, Item can not be deleted"));
  1185. return (HRESULT_FROM_WIN32(ERROR_INVALID_ACCESS));
  1186. }
  1187. }
  1188. //
  1189. // If it's not a generated item, call the driver and ask it to remove
  1190. // the item from it's tree.
  1191. //
  1192. if (!(lItemFlags & WiaItemTypeGenerated)) {
  1193. //
  1194. // Call the mini driver to delete the driver item.
  1195. //
  1196. {
  1197. LOCK_WIA_DEVICE _LWD(this, &hr);
  1198. if(SUCCEEDED(hr)) {
  1199. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvDeleteItem((BYTE*)this, lFlags, &m_lLastDevErrVal);
  1200. }
  1201. }
  1202. if (SUCCEEDED(hr)) {
  1203. //
  1204. // Unlink the IWiaDrvItem from the device item tree.
  1205. // This will also disable any device access through m_pWiaDrvItem
  1206. // by setting the WiaItemTypeDeleted flag.
  1207. //
  1208. hr = m_pWiaDrvItem->RemoveItemFromFolder(WiaItemTypeDeleted | WiaItemTypeRemoved);
  1209. }
  1210. } else {
  1211. //
  1212. // Since there is no corresponding driver item, manually remove this
  1213. // from the tree,
  1214. //
  1215. hr = m_pCWiaTree->RemoveItemFromFolder(WiaItemTypeDeleted | WiaItemTypeRemoved);
  1216. }
  1217. if (SUCCEEDED(hr))
  1218. {
  1219. //
  1220. // Decrement the root item ref count by however much this local ref count
  1221. // contributed to it.
  1222. //
  1223. for (ULONG i = 0; i < m_cLocalRef; i++) {
  1224. m_pIWiaItemRoot->Release();
  1225. }
  1226. }
  1227. return hr;
  1228. }
  1229. /*******************************************************************************
  1230. *
  1231. * AnalyzeItem
  1232. *
  1233. * DESCRIPTION:
  1234. *
  1235. *
  1236. * PARAMETERS:
  1237. *
  1238. *******************************************************************************/
  1239. HRESULT _stdcall CWiaItem::AnalyzeItem(LONG lFlags)
  1240. {
  1241. DBG_FN(CWiaItem::AnalyzeItem);
  1242. //
  1243. // Corresponding driver item must be valid.
  1244. //
  1245. HRESULT hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1246. if (FAILED(hr)) {
  1247. DBG_ERR(("CWiaItem::AnalyzeItem, ValidateWiaDrvItemAccess failed"));
  1248. return hr;
  1249. }
  1250. //
  1251. // Check whether item properties have been initialized
  1252. //
  1253. if (!m_bInitialized) {
  1254. hr = InitLazyProps();
  1255. if (FAILED(hr)) {
  1256. DBG_ERR(("CWiaItem::AnalyzeItem, InitLazyProps failed"));
  1257. return hr;
  1258. }
  1259. }
  1260. //
  1261. // call driver to implement this device dependent call
  1262. //
  1263. {
  1264. LOCK_WIA_DEVICE _LWD(this, &hr);
  1265. if(SUCCEEDED(hr)) {
  1266. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvAnalyzeItem((BYTE*)this, lFlags, &m_lLastDevErrVal);
  1267. }
  1268. }
  1269. return hr;
  1270. }
  1271. /*******************************************************************************
  1272. *
  1273. * CreateChildItem
  1274. *
  1275. * DESCRIPTION:
  1276. *
  1277. *
  1278. * PARAMETERS:
  1279. *
  1280. *******************************************************************************/
  1281. HRESULT _stdcall CWiaItem::CreateChildItem(
  1282. LONG lFlags,
  1283. BSTR bstrItemName,
  1284. BSTR bstrFullItemName,
  1285. IWiaItem **ppNewItem)
  1286. {
  1287. DBG_FN(CWiaItem::CreateChildItem);
  1288. CGenWiaItem *pGenItem = NULL;
  1289. HRESULT hr = S_OK;
  1290. *ppNewItem = NULL;
  1291. //
  1292. // Create the new item
  1293. //
  1294. hr = wiasCreateChildAppItem((BYTE*) this,
  1295. lFlags,
  1296. bstrItemName,
  1297. bstrFullItemName,
  1298. (BYTE**) &pGenItem);
  1299. if (SUCCEEDED(hr)) {
  1300. //
  1301. // Get the driver to initialize the item.
  1302. //
  1303. hr = pGenItem->InitLazyProps(TRUE);
  1304. if (SUCCEEDED(hr)) {
  1305. //
  1306. // Return the IWiaItem interface to the calling App.
  1307. //
  1308. hr = pGenItem->QueryInterface(IID_IWiaItem,
  1309. (VOID**)ppNewItem);
  1310. if (FAILED(hr)) {
  1311. DBG_ERR(("CWiaItem::CreateChildItem, bad mini driver interface"));
  1312. }
  1313. } else {
  1314. DBG_ERR(("CWiaItem::CreateChildItem, Error initializing the item properties"));
  1315. }
  1316. if (FAILED(hr)) {
  1317. delete pGenItem;
  1318. }
  1319. } else {
  1320. DBG_ERR(("CWiaItem::CreateChildItem, error creating generated item"));
  1321. }
  1322. return hr;
  1323. }
  1324. /**************************************************************************\
  1325. * DeviceCommand
  1326. *
  1327. * Issue a device command.
  1328. *
  1329. * Arguments:
  1330. *
  1331. * lFlags -
  1332. * plCommand -
  1333. * ppIWiaItem -
  1334. *
  1335. * Return Value:
  1336. *
  1337. * Status
  1338. *
  1339. * History:
  1340. *
  1341. * 11/12/1998 Original Version
  1342. *
  1343. \**************************************************************************/
  1344. HRESULT _stdcall CWiaItem::DeviceCommand(
  1345. LONG lFlags,
  1346. const GUID *plCommand,
  1347. IWiaItem **ppIWiaItem)
  1348. {
  1349. DBG_FN(CWiaItem::DeviceCommand);
  1350. IWiaDrvItem *pIWiaDrvItem = NULL;
  1351. HRESULT hr;
  1352. CWiaItem *pItem;
  1353. //
  1354. // Driver interface must be valid.
  1355. //
  1356. if (!m_pActiveDevice) {
  1357. DBG_ERR(("CWiaItem::DeviceCommand, bad mini driver interface"));
  1358. return E_FAIL;
  1359. }
  1360. //
  1361. // Corresponding driver item must be valid.
  1362. //
  1363. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1364. if (FAILED(hr)) {
  1365. DBG_ERR(("CWiaItem::DeviceCommand, ValidateWiaDrvItemAccess failed"));
  1366. return hr;
  1367. }
  1368. //
  1369. // Check whether item properties have been initialized
  1370. //
  1371. if (!m_bInitialized) {
  1372. hr = InitLazyProps();
  1373. if (FAILED(hr)) {
  1374. DBG_ERR(("CWiaItem::DeviceCommand, InitLazyProps failed"));
  1375. return hr;
  1376. }
  1377. }
  1378. {
  1379. LOCK_WIA_DEVICE _LWD(this, &hr);
  1380. if(SUCCEEDED(hr)) {
  1381. hr = m_pActiveDevice->m_DrvWrapper.WIA_drvDeviceCommand((BYTE*)this, lFlags, plCommand, &pIWiaDrvItem, &m_lLastDevErrVal);
  1382. }
  1383. }
  1384. if ((!pIWiaDrvItem) || (!ppIWiaItem)) {
  1385. return hr;
  1386. }
  1387. //
  1388. // If we are here, the command has resulted in a drv item being added to
  1389. // the drv and app item trees. Find and return the app item.
  1390. //
  1391. if (ppIWiaItem) {
  1392. BSTR bstrName;
  1393. *ppIWiaItem = NULL;
  1394. hr = pIWiaDrvItem->GetFullItemName(&bstrName);
  1395. if (SUCCEEDED(hr)) {
  1396. hr = FindItemByName(0, bstrName, ppIWiaItem);
  1397. }
  1398. SysFreeString(bstrName);
  1399. }
  1400. return hr;
  1401. }
  1402. /*******************************************************************************
  1403. *
  1404. * DeviceDlg
  1405. *
  1406. * DESCRIPTION:
  1407. * Executes only on the client side.
  1408. *
  1409. * PARAMETERS:
  1410. *
  1411. *******************************************************************************/
  1412. HRESULT _stdcall CWiaItem::DeviceDlg(
  1413. HWND hwndParent,
  1414. LONG lFlags,
  1415. LONG lIntent,
  1416. LONG *plItemCount,
  1417. IWiaItem ***pIWiaItems)
  1418. {
  1419. DBG_FN(CWiaItem::DeviceDlg);
  1420. DBG_ERR(("CWiaItem::DeviceDlg, Bad Proxy"));
  1421. return E_FAIL;
  1422. }
  1423. /**************************************************************************\
  1424. * CWiaItem::GetRootItem
  1425. *
  1426. * return interface to root item
  1427. *
  1428. * Arguments:
  1429. *
  1430. * ppIWiaItem - return IWiaItem interface
  1431. *
  1432. * Return Value:
  1433. *
  1434. * Status
  1435. *
  1436. * History:
  1437. *
  1438. * 10/20/1998 Original Version
  1439. *
  1440. \**************************************************************************/
  1441. HRESULT _stdcall CWiaItem::GetRootItem(IWiaItem **ppIWiaItem)
  1442. {
  1443. DBG_FN(CWiaItem::GetRootItem);
  1444. HRESULT hr = S_OK;
  1445. LONG lDevErrVal;
  1446. //
  1447. // verify root is valid
  1448. //
  1449. if (m_pIWiaItemRoot != NULL) {
  1450. m_pIWiaItemRoot->AddRef();
  1451. *ppIWiaItem = m_pIWiaItemRoot;
  1452. } else {
  1453. DBG_ERR(("CWiaItem::GetRootItem: Bad Root item pointer"));
  1454. hr = E_FAIL;
  1455. }
  1456. return hr;
  1457. }
  1458. /**************************************************************************\
  1459. * FindItemByName
  1460. *
  1461. * Find an item based on its full name. Full name must be of the format.
  1462. *
  1463. * DeviceID\RootDir\[sub-dirs]\ItemName
  1464. *
  1465. * Arguments:
  1466. *
  1467. * lFalgs
  1468. * bstrFullItemName
  1469. * ppIWiaItem
  1470. *
  1471. * Return Value:
  1472. *
  1473. * Status
  1474. *
  1475. * History:
  1476. *
  1477. * 10/9/1998 Original Version
  1478. *
  1479. \**************************************************************************/
  1480. HRESULT _stdcall CWiaItem::FindItemByName(
  1481. LONG lFlags,
  1482. BSTR bstrFullItemName,
  1483. IWiaItem **ppIWiaItem)
  1484. {
  1485. DBG_FN(CWiaItem::FindItemByName);
  1486. HRESULT hr;
  1487. if (bstrFullItemName == NULL) {
  1488. DBG_WRN(("CWiaItem::FindItemByName, bstrFullItemName parameter is NULL"));
  1489. return E_INVALIDARG;
  1490. }
  1491. //
  1492. // Corresponding driver item must be valid.
  1493. //
  1494. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1495. if (FAILED(hr)) {
  1496. DBG_ERR(("CWiaItem::FindItemByName, ValidateWiaDrvItemAccess failed"));
  1497. return hr;
  1498. }
  1499. *ppIWiaItem = NULL;
  1500. //
  1501. // check for empty
  1502. //
  1503. if (wcscmp(bstrFullItemName, L"") == 0) {
  1504. DBG_ERR(("CWiaItem::FindItemByName, Full Item Name is NULL"));
  1505. return S_FALSE;
  1506. }
  1507. //
  1508. // try to find matching driver item from linear list
  1509. //
  1510. CWiaTree *pIChildItem;
  1511. //
  1512. // Make Sure the tree doesn't get deleted, then search the tree.
  1513. //
  1514. AddRef();
  1515. hr = m_pCWiaTree->FindItemByName(lFlags, bstrFullItemName, &pIChildItem);
  1516. //
  1517. // If the item was found, get the app item pointer and addref.
  1518. //
  1519. if (hr == S_OK) {
  1520. hr = pIChildItem->GetItemData((void**)ppIWiaItem);
  1521. if (hr == S_OK) {
  1522. (*ppIWiaItem)->AddRef();
  1523. }
  1524. else {
  1525. DBG_ERR(("CWiaItem::FindItemByName, bad item data"));
  1526. }
  1527. } else {
  1528. //DBG_WRN(("CWiaItem::FindItemByName, Item (%ws) not found in tree", bstrFullItemName));
  1529. }
  1530. Release();
  1531. return hr;
  1532. }
  1533. /**************************************************************************\
  1534. * EnumDeviceCapabilities
  1535. *
  1536. *
  1537. *
  1538. * Arguments:
  1539. *
  1540. *
  1541. *
  1542. * Return Value:
  1543. *
  1544. * Status
  1545. *
  1546. * History:
  1547. *
  1548. * 1/15/1999 Original Version
  1549. *
  1550. \**************************************************************************/
  1551. HRESULT _stdcall CWiaItem::EnumDeviceCapabilities(
  1552. LONG lFlags,
  1553. IEnumWIA_DEV_CAPS **ppIEnum)
  1554. {
  1555. DBG_FN(CWiaItem::EnumDeviceCapabilities);
  1556. //
  1557. // Corresponding driver item must be valid.
  1558. //
  1559. HRESULT hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1560. if (FAILED(hr)) {
  1561. DBG_ERR(("CWiaItem::EnumDeviceCapabilities, ValidateWiaDrvItemAccess failed"));
  1562. return hr;
  1563. }
  1564. //
  1565. // Check whether item properties have been initialized
  1566. //
  1567. if (!m_bInitialized) {
  1568. hr = InitLazyProps();
  1569. if (FAILED(hr)) {
  1570. DBG_ERR(("CWiaItem::EnumDeviceCapabilities, InitLazyProps failed"));
  1571. return hr;
  1572. }
  1573. }
  1574. //
  1575. // Add support for flags later.
  1576. //
  1577. CEnumDC *pEnum = new CEnumDC();;
  1578. if (!pEnum) {
  1579. DBG_ERR(("CWiaItem::EnumDeviceCapabilities, new CEnumDC failed"));
  1580. return E_OUTOFMEMORY;
  1581. }
  1582. hr = pEnum->Initialize(lFlags, this);
  1583. if (SUCCEEDED(hr)) {
  1584. hr = pEnum->QueryInterface(IID_IEnumWIA_DEV_CAPS, (void **) ppIEnum);
  1585. if (FAILED(hr)) {
  1586. DBG_ERR(("CWiaItem::EnumDeviceCapabilities, QI for IID_IEnumWIA_DEV_CAPS failed"));
  1587. delete pEnum;
  1588. }
  1589. } else {
  1590. DBG_ERR(("CWiaItem::EnumDeviceCapabilities, call to Initialize failed"));
  1591. delete pEnum;
  1592. }
  1593. return hr;
  1594. }
  1595. /**************************************************************************\
  1596. * EnumRegisterEventInfo
  1597. *
  1598. *
  1599. *
  1600. * Arguments:
  1601. *
  1602. *
  1603. *
  1604. * Return Value:
  1605. *
  1606. * Status
  1607. *
  1608. * History:
  1609. *
  1610. * 1/15/1999 Original Version
  1611. *
  1612. \**************************************************************************/
  1613. HRESULT _stdcall CWiaItem::EnumRegisterEventInfo(
  1614. LONG lFlags,
  1615. const GUID *pEventGUID,
  1616. IEnumWIA_DEV_CAPS **ppIEnumDevCap)
  1617. {
  1618. DBG_FN(CWiaItem::EnumRegisterEventInfo);
  1619. HRESULT hr;
  1620. LONG lItemType;
  1621. PROPSPEC propSpec[1];
  1622. PROPVARIANT propVar[1];
  1623. //
  1624. // Retrieve the item type and check whether it is the root item
  1625. //
  1626. hr = m_pWiaDrvItem->GetItemFlags(&lItemType);
  1627. if (FAILED(hr)) {
  1628. DBG_ERR(("CWiaItem::EnumRegisterEventInfo() : Failed to get item type"));
  1629. return (hr);
  1630. }
  1631. if (! (lItemType & WiaItemTypeRoot)) {
  1632. DBG_ERR(("CWiaItem::EnumRegisterEventInfo() : Called on non-root item"));
  1633. return (E_INVALIDARG);
  1634. }
  1635. //
  1636. // Check whether item properties have been initialized
  1637. //
  1638. if (!m_bInitialized) {
  1639. hr = InitLazyProps();
  1640. if (FAILED(hr)) {
  1641. DBG_ERR(("CWiaItem::EnumRegisterEventInfo, InitLazyProps failed"));
  1642. return hr;
  1643. }
  1644. }
  1645. //
  1646. // Retrieve the Device ID from root item's property
  1647. //
  1648. propSpec->ulKind = PRSPEC_PROPID;
  1649. propSpec->propid = WIA_DIP_DEV_ID;
  1650. hr = ReadMultiple(1, propSpec, propVar);
  1651. if (FAILED(hr)) {
  1652. DBG_ERR(("CWiaItem::EnumRegisterEventInfo() : Failed to get device id"));
  1653. return (hr);
  1654. }
  1655. //
  1656. // Ask the Event Notifier to create the enumerator
  1657. //
  1658. hr = g_eventNotifier.CreateEnumEventInfo(
  1659. propVar->bstrVal,
  1660. pEventGUID,
  1661. ppIEnumDevCap);
  1662. //
  1663. // Garbage collection
  1664. //
  1665. PropVariantClear(propVar);
  1666. return (hr);
  1667. }
  1668. /**************************************************************************\
  1669. * CWiaItem::Diagnostic
  1670. *
  1671. * Pass through to USD's diagnostic.
  1672. *
  1673. * Arguments:
  1674. *
  1675. * ulSize - the size of the buffer in bytes
  1676. * pBuffer - a pointer to the Diagnostic information buffer
  1677. *
  1678. * Return Value:
  1679. *
  1680. * Status
  1681. *
  1682. * History:
  1683. *
  1684. * 12/14/1999 Original Version
  1685. *
  1686. \**************************************************************************/
  1687. HRESULT _stdcall CWiaItem::Diagnostic(
  1688. ULONG ulSize,
  1689. BYTE *pBuffer)
  1690. {
  1691. DBG_FN(CWiaItem::Diagnostic);
  1692. IStiUSD *pIStiUSD;
  1693. HRESULT hr = S_OK;
  1694. hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
  1695. if (FAILED(hr)) {
  1696. DBG_ERR(("CWiaItem::Diagnostic() : Driver Item not valid!"));
  1697. return hr;
  1698. }
  1699. _try {
  1700. //
  1701. // Get IStiUsd
  1702. //
  1703. if (m_pActiveDevice) {
  1704. //
  1705. // Call diagnostic
  1706. //
  1707. {
  1708. LOCK_WIA_DEVICE _LWD(this, &hr);
  1709. if(SUCCEEDED(hr)) {
  1710. hr = m_pActiveDevice->m_DrvWrapper.STI_Diagnostic((STI_DIAG*)pBuffer);
  1711. }
  1712. }
  1713. } else {
  1714. DBG_ERR(("CWiaItem::Diagnostic() : invalid MiniDriver interface"));
  1715. return E_INVALIDARG;
  1716. }
  1717. }
  1718. _except(EXCEPTION_EXECUTE_HANDLER) {
  1719. DBG_ERR(("CWiaItem::Diagnostic() : Exception in USD!"));
  1720. hr = E_FAIL;
  1721. }
  1722. return hr;
  1723. }
  1724. /**************************************************************************\
  1725. * CWiaItem::DumpItemData
  1726. *
  1727. * Allocate buffer and dump formated private CWiaItem data into it.
  1728. *
  1729. * Arguments:
  1730. *
  1731. *
  1732. *
  1733. * Return Value:
  1734. *
  1735. * Status
  1736. *
  1737. * History:
  1738. *
  1739. * 1/19/1999 Original Version
  1740. *
  1741. \**************************************************************************/
  1742. HRESULT _stdcall CWiaItem::DumpItemData(BSTR *bstrItemData)
  1743. {
  1744. DBG_FN(CWiaItem::DumpItemData);
  1745. #ifdef ITEMDEBUG
  1746. #define BUF_SIZE 2048
  1747. #define LINE_SIZE 128
  1748. WCHAR szTemp[BUF_SIZE];
  1749. LPOLESTR psz = szTemp;
  1750. BSTR bstr;
  1751. psz+= wsprintfW(psz, L"App item, CWiaItem: %08X\r\n\r\n", this);
  1752. psz+= wsprintfW(psz, L"Address Member Value\r\n\r\n");
  1753. psz+= wsprintfW(psz, L"%08X m_ulSig: %08X\r\n", &m_ulSig, m_ulSig);
  1754. psz+= wsprintfW(psz, L"%08X m_cRef: %08X\r\n", &m_cRef, m_cRef);
  1755. psz+= wsprintfW(psz, L"%08X m_pWiaDrvItem: %08X\r\n", &m_pWiaDrvItem, m_pWiaDrvItem);
  1756. psz+= wsprintfW(psz, L"%08X m_pActiveDevice: %08X\r\n", &m_pActiveDevice, m_pActiveDevice);
  1757. psz+= wsprintfW(psz, L"%08X m_pIUnknownInner: %08X\r\n", &m_pIUnknownInner, m_pIUnknownInner);
  1758. psz+= wsprintfW(psz, L"%08X m_pCWiaTree: %08X\r\n", &m_pCWiaTree, m_pCWiaTree);
  1759. psz+= wsprintfW(psz, L"%08X m_pIWiaItemRoot: %08X\r\n", &m_pIWiaItemRoot, m_pIWiaItemRoot);
  1760. psz+= wsprintfW(psz, L"%08X m_pPropStg: %08X\r\n", &m_pPropStg, m_pPropStg);
  1761. psz+= wsprintfW(psz, L"%08X m_hBandSection: %08X\r\n", &m_hBandSection, m_hBandSection);
  1762. psz+= wsprintfW(psz, L"%08X m_pBandBuffer: %08X\r\n", &m_pBandBuffer, m_pBandBuffer);
  1763. psz+= wsprintfW(psz, L"%08X m_lBandBufferLength: %08X\r\n", &m_lBandBufferLength, m_lBandBufferLength);
  1764. psz+= wsprintfW(psz, L"%08X m_ClientBaseAddress: %08X\r\n", &m_ClientBaseAddress, m_ClientBaseAddress);
  1765. psz+= wsprintfW(psz, L"%08X m_bMapSection: %08X\r\n", &m_bMapSection, m_bMapSection);
  1766. psz+= wsprintfW(psz, L"%08X m_cfeBandedTran: %08X\r\n", &m_cwfiBandedTran, m_cwfiBandedTran);
  1767. psz+= wsprintfW(psz, L"%08X m_pfeBandedTran: %08X\r\n", &m_pwfiBandedTran, m_pwfiBandedTran);
  1768. if (psz > (szTemp + (BUF_SIZE - LINE_SIZE))) {
  1769. DBG_ERR(("CWiaItem::DumpItemData buffer too small"));
  1770. }
  1771. bstr = SysAllocString(szTemp);
  1772. if (bstr) {
  1773. *bstrItemData = bstr;
  1774. return S_OK;
  1775. }
  1776. return E_OUTOFMEMORY;
  1777. #else
  1778. return E_NOTIMPL;
  1779. #endif
  1780. }
  1781. /**************************************************************************\
  1782. * CWiaItem::DumpDrvItemData
  1783. *
  1784. * Allocate buffer and dump formated private CWiaDrvItem data into it.
  1785. *
  1786. * Arguments:
  1787. *
  1788. *
  1789. *
  1790. * Return Value:
  1791. *
  1792. * Status
  1793. *
  1794. * History:
  1795. *
  1796. * 1/19/1999 Original Version
  1797. *
  1798. \**************************************************************************/
  1799. HRESULT _stdcall CWiaItem::DumpDrvItemData(BSTR *bstrDrvItemData)
  1800. {
  1801. DBG_FN(CWiaItem::DumpDrvItemData);
  1802. #ifdef DEBUG
  1803. if (m_pWiaDrvItem) {
  1804. return m_pWiaDrvItem->DumpItemData(bstrDrvItemData);
  1805. }
  1806. else {
  1807. *bstrDrvItemData = SysAllocString(L"No linkage to driver item");
  1808. if (*bstrDrvItemData) {
  1809. return S_OK;
  1810. }
  1811. return E_OUTOFMEMORY;
  1812. }
  1813. #else
  1814. return E_NOTIMPL;
  1815. #endif
  1816. }
  1817. /**************************************************************************\
  1818. * CWiaItem::DumpTreeItemData
  1819. *
  1820. * Allocate buffer and dump formated private CWiaTree data into it.
  1821. *
  1822. * Arguments:
  1823. *
  1824. *
  1825. *
  1826. * Return Value:
  1827. *
  1828. * Status
  1829. *
  1830. * History:
  1831. *
  1832. * 1/19/1999 Original Version
  1833. *
  1834. \**************************************************************************/
  1835. HRESULT _stdcall CWiaItem::DumpTreeItemData(BSTR *bstrTreeItemData)
  1836. {
  1837. DBG_FN(CWiaItem::DumpTreeItemData);
  1838. #ifdef DEBUG
  1839. if (m_pCWiaTree) {
  1840. return m_pCWiaTree->DumpTreeData(bstrTreeItemData);
  1841. }
  1842. else {
  1843. *bstrTreeItemData = SysAllocString(L"No linkage to tree item");
  1844. if (*bstrTreeItemData) {
  1845. return S_OK;
  1846. }
  1847. return E_OUTOFMEMORY;
  1848. }
  1849. #else
  1850. return E_NOTIMPL;
  1851. #endif
  1852. }
  1853. /**************************************************************************\
  1854. * CWiaItem::GetTreePtr
  1855. *
  1856. * Returns a pointer to an items corresponding tree entry.
  1857. *
  1858. * Arguments:
  1859. *
  1860. * None
  1861. *
  1862. * Return Value:
  1863. *
  1864. * Pointer to a tree item on success, null if failure.
  1865. *
  1866. * History:
  1867. *
  1868. * 1/19/1999 Original Version
  1869. *
  1870. \**************************************************************************/
  1871. CWiaTree* _stdcall CWiaItem::GetTreePtr(void)
  1872. {
  1873. DBG_FN(CWiaItem::GetTreePtr);
  1874. if (m_pCWiaTree) {
  1875. return m_pCWiaTree;
  1876. }
  1877. else {
  1878. DBG_ERR(("CWiaItem::GetTreePtr NULL tree item pointer for item: %X", this));
  1879. return NULL;
  1880. }
  1881. }
  1882. /**************************************************************************\
  1883. * CWiaItem::GetDrvItemPtr
  1884. *
  1885. * Returns a pointer to an items corresponding driver item.
  1886. *
  1887. * Arguments:
  1888. *
  1889. * None
  1890. *
  1891. * Return Value:
  1892. *
  1893. * Pointer to a driver item on success, null if failure.
  1894. *
  1895. * History:
  1896. *
  1897. * 1/19/1999 Original Version
  1898. *
  1899. \**************************************************************************/
  1900. CWiaDrvItem* _stdcall CWiaItem::GetDrvItemPtr(void)
  1901. {
  1902. DBG_FN(CWiaItem::GetDrvItemPtr);
  1903. if (m_pWiaDrvItem) {
  1904. return m_pWiaDrvItem;
  1905. }
  1906. else {
  1907. DBG_ERR(("CWiaItem::GetDrvItemPtr NULL driver item pointer for item: %X", this));
  1908. return NULL;
  1909. }
  1910. }
  1911. /**************************************************************************\
  1912. * CWiaItem::WriteItemPropNames
  1913. *
  1914. * Write property names to all internal property storage.
  1915. *
  1916. * Arguments:
  1917. *
  1918. *
  1919. *
  1920. * Return Value:
  1921. *
  1922. * Status
  1923. *
  1924. * History:
  1925. *
  1926. * 1/19/1999 Original Version
  1927. *
  1928. \**************************************************************************/
  1929. HRESULT _stdcall CWiaItem::WriteItemPropNames(
  1930. LONG cItemProps,
  1931. PROPID *ppId,
  1932. LPOLESTR *ppszNames)
  1933. {
  1934. DBG_FN(CWiaItem::WriteItemPropNames);
  1935. if (IsBadReadPtr(ppId, sizeof(PROPID) * cItemProps) ||
  1936. IsBadReadPtr(ppszNames, sizeof(LPOLESTR) * cItemProps)) {
  1937. DBG_ERR(("CWiaItem::WriteItemPropNames, NULL input pointer"));
  1938. return E_INVALIDARG;
  1939. }
  1940. HRESULT hr = m_pPropStg->WriteItemPropNames(cItemProps,
  1941. ppId,
  1942. ppszNames);
  1943. if (FAILED(hr)) {
  1944. DBG_ERR(("CWiaItem::WriteItemPropNames, WritePropertyNames failed (0x%X)", hr));
  1945. return hr;
  1946. }
  1947. return hr;
  1948. }
  1949. /**************************************************************************\
  1950. * CWiaItem::GetItemPropStreams
  1951. *
  1952. * Get pointers to all internal property storage.
  1953. *
  1954. * Arguments:
  1955. *
  1956. *
  1957. *
  1958. * Return Value:
  1959. *
  1960. * Status
  1961. *
  1962. * History:
  1963. *
  1964. * 1/19/1999 Original Version
  1965. *
  1966. \**************************************************************************/
  1967. HRESULT _stdcall CWiaItem::GetItemPropStreams(
  1968. IPropertyStorage **ppIPropStg,
  1969. IPropertyStorage **ppIPropAccessStg,
  1970. IPropertyStorage **ppIPropValidStg,
  1971. IPropertyStorage **ppIPropOldStg)
  1972. {
  1973. DBG_FN(CWiaItem::GetItemPropStreams);
  1974. HRESULT hr;
  1975. if (!m_pPropStg) {
  1976. DBG_ERR(("CWiaItem::GetItemPropStreams, NULL internal property storage pointer"));
  1977. return E_FAIL;
  1978. }
  1979. //
  1980. // Check whether item properties have been initialized
  1981. //
  1982. if (!m_bInitialized) {
  1983. hr = InitLazyProps();
  1984. if (FAILED(hr)) {
  1985. DBG_ERR(("CWiaItem::GetItemPropStreams, InitLazyProps failed"));
  1986. return hr;
  1987. }
  1988. }
  1989. if (ppIPropStg) {
  1990. *ppIPropStg = m_pPropStg->CurStg();
  1991. }
  1992. if (ppIPropAccessStg) {
  1993. *ppIPropAccessStg = m_pPropStg->AccessStg();
  1994. }
  1995. if (ppIPropValidStg) {
  1996. *ppIPropValidStg = m_pPropStg->ValidStg();
  1997. }
  1998. if (ppIPropOldStg) {
  1999. *ppIPropOldStg = m_pPropStg->OldStg();
  2000. if (!(*ppIPropOldStg)) {
  2001. //
  2002. // Note that if the old property storage is NULL, we
  2003. // return the current value storage
  2004. //
  2005. *ppIPropOldStg = m_pPropStg->CurStg();
  2006. }
  2007. }
  2008. return S_OK;
  2009. }
  2010. /**************************************************************************\
  2011. * CWiaItem::AddVolumePropertiesToRoot
  2012. *
  2013. * This helper method takes a Root WiaItem and adds any volume specific
  2014. * properties to it. Note that this should only be called on the Root
  2015. * item of Volume devices.
  2016. *
  2017. * Arguments:
  2018. *
  2019. * pActiveDevice - Pointer to Root's active device object
  2020. *
  2021. * Return Value:
  2022. *
  2023. * Status
  2024. *
  2025. * History:
  2026. *
  2027. * 12/13/2000 Original Version
  2028. *
  2029. \**************************************************************************/
  2030. HRESULT CWiaItem::AddVolumePropertiesToRoot(
  2031. ACTIVE_DEVICE *pActiveDevice)
  2032. {
  2033. DBG_FN(AddVolumePropertiesToRoot);
  2034. HRESULT hr = S_OK;
  2035. //
  2036. // To add new FIle SYstem properties:
  2037. // Simply add the appropriate entries to
  2038. // piFileSystem
  2039. // psFileSystem
  2040. // pwszFileSystem
  2041. // pwszFileSystem
  2042. // wpiFileSystem
  2043. // Then, don't forget to add the current value entries to
  2044. // pvFileSystem
  2045. // before doing a WriteMultiple. Notice that PropVariant arrays
  2046. // cannot be statically initialized (will give problems on 64bit)
  2047. //
  2048. PROPID piFileSystem[] = {WIA_DPF_MOUNT_POINT};
  2049. PROPSPEC psFileSystem[] = {
  2050. {PRSPEC_PROPID, WIA_DPF_MOUNT_POINT}
  2051. };
  2052. LPOLESTR pwszFileSystem[] = {WIA_DPF_MOUNT_POINT_STR};
  2053. WIA_PROPERTY_INFO wpiFileSystem[] = {
  2054. {WIA_PROP_RNC, VT_BSTR, 0, 0, 0, 0}, // WIA_DPF_MOUNT_POINT
  2055. };
  2056. PROPVARIANT pvFileSystem[sizeof(piFileSystem) / sizeof(piFileSystem[0])];
  2057. //
  2058. // Write the File System property names.
  2059. //
  2060. hr = WriteItemPropNames(sizeof(piFileSystem) / sizeof(piFileSystem[0]),
  2061. piFileSystem,
  2062. pwszFileSystem);
  2063. if (FAILED(hr)) {
  2064. DBG_ERR(("CWiaItem::AddVolumePropertiesToRoot, WritePropNames failed"));
  2065. return hr;
  2066. }
  2067. //
  2068. // Write the File System property values
  2069. //
  2070. ULONG ulIndex;
  2071. memset(pvFileSystem, 0, sizeof(pvFileSystem));
  2072. BSTR bstrMountPoint = NULL;
  2073. DEVICE_INFO *pDevInfo = pActiveDevice->m_DrvWrapper.getDevInfo();
  2074. if (pDevInfo) {
  2075. bstrMountPoint = SysAllocString(pDevInfo->wszAlternateID);
  2076. }
  2077. pvFileSystem[0].vt = VT_BSTR;
  2078. pvFileSystem[0].bstrVal = bstrMountPoint;
  2079. hr = (m_pPropStg->CurStg())->WriteMultiple(sizeof(piFileSystem) / sizeof(piFileSystem[0]),
  2080. psFileSystem,
  2081. pvFileSystem,
  2082. WIA_DPF_FIRST);
  2083. FreePropVariantArray(sizeof(piFileSystem) / sizeof(piFileSystem[0]),
  2084. pvFileSystem);
  2085. if (FAILED(hr)) {
  2086. ReportReadWriteMultipleError(hr, "CWiaItem::AddVolumePropertiesToRoot", NULL, FALSE, WIA_NUM_DIP, g_psDeviceInfo);
  2087. DBG_ERR(("CWiaItem::AddVolumePropertiesToRoot failed"));
  2088. return hr;
  2089. }
  2090. //
  2091. // Write out the File System property attributes
  2092. //
  2093. hr = wiasSetItemPropAttribs((BYTE*)this,
  2094. sizeof(piFileSystem) / sizeof(piFileSystem[0]),
  2095. psFileSystem,
  2096. wpiFileSystem);
  2097. return hr;
  2098. }