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.

1233 lines
27 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: WiaTree.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: reedb
  10. *
  11. * DATE: 27 Apr, 1999
  12. *
  13. * DESCRIPTION:
  14. * Implementation of the WIA tree class. A folder and file based tree with
  15. * a parallel linear list for name based searches.
  16. *
  17. *******************************************************************************/
  18. #include "precomp.h"
  19. #include "stiexe.h"
  20. #include "wiamindr.h"
  21. #include "helpers.h"
  22. HRESULT _stdcall ValidateTreeItem(CWiaTree*);
  23. /**************************************************************************\
  24. * CWiaTree
  25. *
  26. * Constructor for tree item.
  27. *
  28. * Arguments:
  29. *
  30. * None
  31. *
  32. * Return Value:
  33. *
  34. * Status
  35. *
  36. * History:
  37. *
  38. * 1/19/1999 Original Version
  39. *
  40. \**************************************************************************/
  41. CWiaTree::CWiaTree()
  42. {
  43. m_ulSig = CWIATREE_SIG;
  44. m_lFlags = WiaItemTypeFree;
  45. m_pNext = NULL;
  46. m_pPrev = NULL;
  47. m_pParent = NULL;
  48. m_pChild = NULL;
  49. m_pLinearList = NULL;
  50. m_bstrItemName = NULL;
  51. m_bstrFullItemName = NULL;
  52. m_pData = NULL;
  53. m_bInitCritSect = FALSE;
  54. }
  55. /**************************************************************************\
  56. * Initialize
  57. *
  58. * Initialize new tree item.
  59. *
  60. * Arguments:
  61. *
  62. * lFlags - Object flags for new item.
  63. * bstrItemName - Item name.
  64. * bstrFullItemName - Full item name, including path.
  65. * pData - Pointer to items payload data.
  66. *
  67. * Return Value:
  68. *
  69. * Status
  70. *
  71. * History:
  72. *
  73. * 1/19/1999 Original Version
  74. *
  75. \**************************************************************************/
  76. HRESULT _stdcall CWiaTree::Initialize(
  77. LONG lFlags,
  78. BSTR bstrItemName,
  79. BSTR bstrFullItemName,
  80. void *pData)
  81. {
  82. HRESULT hr = S_OK;
  83. //
  84. // Tree items must be either folder or file.
  85. //
  86. if (!(lFlags & (WiaItemTypeFolder | WiaItemTypeFile))) {
  87. DBG_ERR(("CWiaTree::Initialize, bad flags parameter: 0x%08X", lFlags));
  88. return E_INVALIDARG;
  89. }
  90. //
  91. // Initialize the critical section
  92. //
  93. __try {
  94. if(!InitializeCriticalSectionAndSpinCount(&m_CritSect, MINLONG)) {
  95. m_bInitCritSect = FALSE;
  96. return HRESULT_FROM_WIN32(::GetLastError());
  97. }
  98. m_bInitCritSect = TRUE;
  99. }
  100. __except (EXCEPTION_EXECUTE_HANDLER) {
  101. m_bInitCritSect = FALSE;
  102. DBG_ERR(("CWiaTree::Initialize, Error initializing critical section"));
  103. return E_OUTOFMEMORY;
  104. }
  105. //
  106. // Root items are always valid. Other items are valid only after
  107. // insertion in the tree, so set not present flags.
  108. //
  109. if (!(lFlags & WiaItemTypeRoot)) {
  110. lFlags |= WiaItemTypeDeleted;
  111. lFlags |= WiaItemTypeDisconnected;
  112. }
  113. m_lFlags = lFlags;
  114. //
  115. // Maintain the item names for by name searches.
  116. //
  117. m_bstrItemName = SysAllocString(bstrItemName);
  118. if (!m_bstrItemName) {
  119. DBG_ERR(("CWiaTree::Initialize, unable to allocate item name"));
  120. return E_OUTOFMEMORY;
  121. }
  122. m_bstrFullItemName = SysAllocString(bstrFullItemName);
  123. if (!m_bstrFullItemName) {
  124. DBG_ERR(("CWiaTree::Initialize, unable to allocate full item name"));
  125. return E_OUTOFMEMORY;
  126. }
  127. SetItemData(pData);
  128. return hr;
  129. }
  130. /**************************************************************************\
  131. * ~CWiaTreee
  132. *
  133. * Destructor for tree item.
  134. *
  135. * Arguments:
  136. *
  137. * None
  138. *
  139. * Return Value:
  140. *
  141. * Status
  142. *
  143. * History:
  144. *
  145. * 1/19/1999 Original Version
  146. *
  147. \**************************************************************************/
  148. CWiaTree::~CWiaTree()
  149. {
  150. DBG_FN(CWiaTree::~CWiaTree);
  151. HRESULT hr;
  152. //
  153. // Item should be disconnected.
  154. //
  155. if (m_pNext || m_pPrev || m_pParent || m_pChild) {
  156. DBG_ERR(("Destroy Tree Item, item still connected"));
  157. }
  158. //
  159. // Free item names.
  160. //
  161. if (m_bstrItemName) {
  162. SysFreeString(m_bstrItemName);
  163. m_bstrItemName = NULL;
  164. }
  165. if (m_bstrFullItemName) {
  166. SysFreeString(m_bstrFullItemName);
  167. m_bstrFullItemName = NULL;
  168. }
  169. //
  170. // Delete the critical section
  171. //
  172. if (m_bInitCritSect) {
  173. DeleteCriticalSection(&m_CritSect);
  174. }
  175. m_bInitCritSect = FALSE;
  176. //
  177. // Clear all members
  178. //
  179. m_ulSig = 0;
  180. m_lFlags = WiaItemTypeFree;
  181. m_pNext = NULL;
  182. m_pPrev = NULL;
  183. m_pParent = NULL;
  184. m_pChild = NULL;
  185. m_pLinearList = NULL;
  186. m_pData = NULL;
  187. }
  188. /**************************************************************************\
  189. * GetRootItem
  190. *
  191. * Walk back up the tree to find the root of this item.
  192. *
  193. * Arguments:
  194. *
  195. * None
  196. *
  197. * Return Value:
  198. *
  199. * Pointer to this items root item.
  200. *
  201. * History:
  202. *
  203. * 1/19/1999 Original Version
  204. *
  205. \**************************************************************************/
  206. CWiaTree * _stdcall CWiaTree::GetRootItem()
  207. {
  208. CWiaTree *pRoot = this;
  209. CWiaCritSect _CritSect(&m_CritSect);
  210. //
  211. // walk back up tree to root
  212. //
  213. while ((pRoot) && (pRoot->m_pParent != NULL)) {
  214. pRoot = pRoot->m_pParent;
  215. }
  216. //
  217. // verify root item
  218. //
  219. if (pRoot) {
  220. if (!(pRoot->m_lFlags & WiaItemTypeRoot)) {
  221. DBG_ERR(("CWiaTree::GetRootItem, root item doesn't have WiaItemTypeRoot set"));
  222. return NULL;
  223. }
  224. }
  225. else {
  226. DBG_ERR(("CWiaTree::GetRootItem, root item not found, tree corrupt"));
  227. }
  228. return pRoot;
  229. }
  230. /**************************************************************************\
  231. * CWiaTree::AddItemToLinearList
  232. *
  233. * Add an item to the linear list. Must be called on a root item.
  234. *
  235. * Arguments:
  236. *
  237. * pItem - Pointer to the item to be added.
  238. *
  239. * Return Value:
  240. *
  241. * Status
  242. *
  243. * History:
  244. *
  245. * 1/19/1999 Original Version
  246. *
  247. \**************************************************************************/
  248. HRESULT _stdcall CWiaTree::AddItemToLinearList(CWiaTree *pItem)
  249. {
  250. CWiaCritSect _CritSect(&m_CritSect);
  251. //
  252. // Validate the child item.
  253. //
  254. if (pItem == NULL) {
  255. DBG_ERR(("CWiaTree::AddItemToLinearList, NULL input pointer"));
  256. return E_POINTER;
  257. }
  258. //
  259. // this must be a root item
  260. //
  261. if (!(m_lFlags & WiaItemTypeRoot)) {
  262. DBG_ERR(("CWiaTree::AddItemToLinearList, caller doesn't have WiaItemTypeRoot set"));
  263. return E_INVALIDARG;
  264. }
  265. //
  266. // add to single linked list
  267. //
  268. pItem->m_pLinearList = m_pLinearList;
  269. m_pLinearList = pItem;
  270. return S_OK;
  271. }
  272. /**************************************************************************\
  273. * CWiaTree::RemoveItemFromLinearList
  274. *
  275. * Remove an item from the linear list. Must be called on a root item.
  276. *
  277. * Arguments:
  278. *
  279. * pItem - Pointer to the item to be removed.
  280. *
  281. * Return Value:
  282. *
  283. * Status
  284. *
  285. * History:
  286. *
  287. * 1/19/1999 Original Version
  288. *
  289. \**************************************************************************/
  290. HRESULT _stdcall CWiaTree::RemoveItemFromLinearList(CWiaTree *pItem)
  291. {
  292. CWiaCritSect _CritSect(&m_CritSect);
  293. HRESULT hr;
  294. //
  295. // validate
  296. //
  297. if (pItem == NULL) {
  298. DBG_ERR(("CWiaTree::RemoveItemFromLinearList, NULL input pointer"));
  299. return E_POINTER;
  300. }
  301. //
  302. // this must be a root item
  303. //
  304. if (!(m_lFlags & WiaItemTypeRoot)) {
  305. DBG_ERR(("CWiaTree::RemoveItemFromLinearList, caller doesn't have WiaItemTypeRoot set"));
  306. return E_INVALIDARG;
  307. }
  308. //
  309. // Root item case.
  310. //
  311. if (pItem == this) {
  312. m_pLinearList = NULL;
  313. return S_OK;
  314. }
  315. //
  316. // find item in list
  317. //
  318. CWiaTree* pPrev = this;
  319. CWiaTree* pTemp;
  320. //
  321. // look for match in list
  322. //
  323. do {
  324. //
  325. // look for item
  326. //
  327. if (pPrev->m_pLinearList == pItem) {
  328. //
  329. // remove from list and exit
  330. //
  331. pPrev->m_pLinearList = pItem->m_pLinearList;
  332. return S_OK;
  333. }
  334. //
  335. // next item
  336. //
  337. pPrev = pPrev->m_pLinearList;
  338. } while (pPrev != NULL);
  339. DBG_ERR(("CWiaTree::RemoveItemFromLinearList, item not found: 0x%08X", pItem));
  340. return E_FAIL;
  341. }
  342. /**************************************************************************\
  343. * CWiaTree::AddChildItem
  344. *
  345. * Add a child item to the tree.
  346. *
  347. * Arguments:
  348. *
  349. * pItem - Pointer to the child item to be added.
  350. *
  351. * Return Value:
  352. *
  353. * Status
  354. *
  355. * History:
  356. *
  357. * 1/19/1999 Original Version
  358. *
  359. \**************************************************************************/
  360. HRESULT _stdcall CWiaTree::AddChildItem(CWiaTree *pItem)
  361. {
  362. CWiaCritSect _CritSect(&m_CritSect);
  363. //
  364. // Validate the child item.
  365. //
  366. if (!pItem) {
  367. DBG_ERR(("CWiaTree::AddChildItem pItem is NULL "));
  368. return E_POINTER;
  369. }
  370. //
  371. // Not using sentinell so check enpty folder case.
  372. //
  373. if (m_pChild == NULL) {
  374. m_pChild = pItem;
  375. pItem->m_pNext = pItem;
  376. pItem->m_pPrev = pItem;
  377. } else {
  378. //
  379. // Add to end of folder list.
  380. //
  381. CWiaTree *pTempItem = m_pChild;
  382. pTempItem->m_pPrev->m_pNext = pItem;
  383. pItem->m_pPrev = pTempItem->m_pPrev;
  384. pItem->m_pNext = pTempItem;
  385. pTempItem->m_pPrev = pItem;
  386. }
  387. return S_OK;
  388. }
  389. /**************************************************************************\
  390. * CWiaTree::AddItemToFolder
  391. *
  392. * Add a tree item to a folder in the tree. Parent must be a folder.
  393. *
  394. * Arguments:
  395. *
  396. * pIParent - Parent of the item.
  397. *
  398. * Return Value:
  399. *
  400. * Status
  401. *
  402. * History:
  403. *
  404. * 1/19/1999 Original Version
  405. *
  406. \**************************************************************************/
  407. HRESULT _stdcall CWiaTree::AddItemToFolder(CWiaTree *pParent)
  408. {
  409. CWiaCritSect _CritSect(&m_CritSect);
  410. HRESULT hr = S_OK;
  411. //
  412. // Validate the parent. Parents must be a folder.
  413. //
  414. if (!pParent) {
  415. DBG_ERR(("CWiaTree::AddItemToFolder, NULL parent"));
  416. return E_POINTER;
  417. }
  418. if (!(pParent->m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments))) {
  419. DBG_ERR(("CWiaTree::AddItemToFolder, parent is not a folder"));
  420. return E_INVALIDARG;
  421. }
  422. //
  423. // First add item to linear list of items.
  424. //
  425. CWiaTree *pRoot = pParent->GetRootItem();
  426. if (pRoot == NULL) {
  427. return E_FAIL;
  428. }
  429. hr = pRoot->AddItemToLinearList(this);
  430. if (FAILED(hr)) {
  431. return hr;
  432. }
  433. //
  434. // Add the item to the tree.
  435. //
  436. hr = pParent->AddChildItem(this);
  437. if (FAILED(hr)) {
  438. return hr;
  439. }
  440. //
  441. // Remember parent
  442. //
  443. m_pParent = pParent;
  444. //
  445. // Item has been added to the tree, clear not present flags.
  446. //
  447. m_lFlags &= ~WiaItemTypeDeleted;
  448. m_lFlags &= ~WiaItemTypeDisconnected;
  449. return hr;
  450. }
  451. /**************************************************************************\
  452. * RemoveItemFromFolder
  453. *
  454. * Remove an item from a folder of the tree and mark it so that
  455. * no device access can be done through it.
  456. *
  457. * Arguments:
  458. *
  459. * lReason - Reason for removal of item.
  460. *
  461. * Return Value:
  462. *
  463. * Status
  464. *
  465. * History:
  466. *
  467. * 1/19/1999 Original Version
  468. *
  469. \**************************************************************************/
  470. HRESULT _stdcall CWiaTree::RemoveItemFromFolder(LONG lReason)
  471. {
  472. CWiaCritSect _CritSect(&m_CritSect);
  473. HRESULT hr = S_OK;
  474. //
  475. // Reason for removal must be valid.
  476. //
  477. if (!(lReason & (WiaItemTypeDeleted | WiaItemTypeDisconnected))) {
  478. DBG_ERR(("CWiaTree::RemoveItemFromFolder, invalid lReason: 0x%08X", lReason));
  479. return E_INVALIDARG;
  480. }
  481. //
  482. // Folder items must be empty.
  483. //
  484. if (m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
  485. if (m_pChild != NULL) {
  486. DBG_ERR(("CWiaTree::RemoveItemFromFolder, trying to remove folder that is not empty"));
  487. return E_INVALIDARG;
  488. }
  489. }
  490. //
  491. // Remove non-root from linear list
  492. //
  493. CWiaTree *pRoot = GetRootItem();
  494. if (pRoot == NULL) {
  495. DBG_ERR(("CWiaTree::RemoveItemFromFolder, can't find root"));
  496. return E_FAIL;
  497. }
  498. if (pRoot != this) {
  499. pRoot->RemoveItemFromLinearList(this);
  500. //
  501. // remove from list of children
  502. //
  503. if (m_pNext != this) {
  504. //
  505. // remove from non-empty list
  506. //
  507. m_pPrev->m_pNext = m_pNext;
  508. m_pNext->m_pPrev = m_pPrev;
  509. //
  510. // was it head?
  511. //
  512. if (m_pParent->m_pChild == this) {
  513. m_pParent->m_pChild = m_pNext;
  514. }
  515. } else {
  516. //
  517. // list contains only this child. mark parent's
  518. // child pointer to NULL
  519. //
  520. m_pParent->m_pChild = NULL;
  521. }
  522. }
  523. //
  524. // to prevent accidents, clear connection fields
  525. //
  526. m_pNext = NULL;
  527. m_pPrev = NULL;
  528. m_pParent = NULL;
  529. m_pChild = NULL;
  530. //
  531. // Indicate why item was removed from the driver item tree.
  532. //
  533. m_lFlags |= lReason;
  534. return S_OK;
  535. }
  536. /**************************************************************************\
  537. * CWiaTree::GetFullItemName
  538. *
  539. * Allocates and fills in a BSTR with this items full name. The full item
  540. * name includes item path information. Caller must free.
  541. *
  542. * Arguments:
  543. *
  544. * pbstrFullItemName - Pointer to returned full item name.
  545. *
  546. * Return Value:
  547. *
  548. * Status
  549. *
  550. * History:
  551. *
  552. * 1/19/1999 Original Version
  553. *
  554. \**************************************************************************/
  555. HRESULT _stdcall CWiaTree::GetFullItemName(BSTR *pbstrFullItemName)
  556. {
  557. if (!pbstrFullItemName) {
  558. DBG_ERR(("CWiaTree::GetFullItemName pbstrFullItemName is NULL "));
  559. return E_INVALIDARG;
  560. }
  561. BSTR bstr = SysAllocString(m_bstrFullItemName);
  562. if (bstr) {
  563. *pbstrFullItemName = bstr;
  564. return S_OK;
  565. }
  566. return E_OUTOFMEMORY;
  567. }
  568. /**************************************************************************\
  569. * CWiaTree::GetItemName
  570. *
  571. * Allocates and fills in a BSTR with this items name. The item name
  572. * does not include item path information. Caller must free.
  573. *
  574. * Arguments:
  575. *
  576. * pbstrItemName - Pointer to returned item name.
  577. *
  578. * Return Value:
  579. *
  580. * Status
  581. *
  582. * History:
  583. *
  584. * 1/19/1999 Original Version
  585. *
  586. \**************************************************************************/
  587. HRESULT _stdcall CWiaTree::GetItemName(BSTR *pbstrItemName)
  588. {
  589. if (!pbstrItemName) {
  590. DBG_ERR(("CWiaTree::GetItemName pbstrItemName is NULL "));
  591. return E_INVALIDARG;
  592. }
  593. BSTR bstr = SysAllocString(m_bstrItemName);
  594. if (bstr) {
  595. *pbstrItemName = bstr;
  596. return S_OK;
  597. }
  598. return E_OUTOFMEMORY;
  599. }
  600. /**************************************************************************\
  601. * CWiaTree::DumpTreeData
  602. *
  603. * Allocate buffer and dump formatted private CWiaTree data into it.
  604. * This method is debug only. Free component returns E_NOTIMPL.
  605. *
  606. * Arguments:
  607. *
  608. * bstrDrvItemData - Pointer to allocated buffer. Caller must free.
  609. *
  610. * Return Value:
  611. *
  612. * Status
  613. *
  614. * History:
  615. *
  616. * 1/19/1999 Original Version
  617. *
  618. \**************************************************************************/
  619. HRESULT _stdcall CWiaTree::DumpTreeData(BSTR *bstrDrvItemData)
  620. {
  621. #ifdef DEBUG
  622. #define BUF_SIZE 1024
  623. #define LINE_SIZE 128
  624. WCHAR szTemp[BUF_SIZE];
  625. LPOLESTR psz = szTemp;
  626. wcscpy(szTemp, L"");
  627. psz+= wsprintfW(psz, L"Tree item, CWiaTree: %08X\r\n\r\n", this);
  628. psz+= wsprintfW(psz, L"Address Member Value\r\n");
  629. psz+= wsprintfW(psz, L"%08X m_ulSig: %08X\r\n", &m_ulSig, m_ulSig);
  630. psz+= wsprintfW(psz, L"%08X m_lFlags: %08X\r\n", &m_lFlags, m_lFlags);
  631. psz+= wsprintfW(psz, L"%08X m_pNext: %08X\r\n", &m_pNext, m_pNext);
  632. psz+= wsprintfW(psz, L"%08X m_pPrev: %08X\r\n", &m_pPrev, m_pPrev);
  633. psz+= wsprintfW(psz, L"%08X m_pParent: %08X\r\n", &m_pParent, m_pParent);
  634. psz+= wsprintfW(psz, L"%08X m_pChild: %08X\r\n", &m_pChild, m_pChild);
  635. psz+= wsprintfW(psz, L"%08X m_pLinearList: %08X\r\n", &m_pLinearList, m_pLinearList);
  636. psz+= wsprintfW(psz, L"%08X m_bstrItemName: %08X, %ws\r\n", &m_bstrItemName, m_bstrItemName, m_bstrItemName);
  637. psz+= wsprintfW(psz, L"%08X m_bstrFullItemName: %08X, %ws\r\n", &m_bstrFullItemName, m_bstrFullItemName, m_bstrFullItemName);
  638. psz+= wsprintfW(psz, L"%08X m_pData: %08X\r\n", &m_pData, m_pData);
  639. if (psz > (szTemp + (BUF_SIZE - LINE_SIZE))) {
  640. DBG_ERR(("CWiaTree::DumpDrvItemData buffer too small"));
  641. }
  642. *bstrDrvItemData = SysAllocString(szTemp);
  643. if (*bstrDrvItemData) {
  644. return S_OK;
  645. }
  646. return E_OUTOFMEMORY;
  647. #else
  648. return E_NOTIMPL;
  649. #endif
  650. }
  651. /*
  652. HRESULT _stdcall CWiaTree::DumpAllTreeData()
  653. {
  654. //
  655. // start at beginning of item linear list
  656. //
  657. CWiaTree *pItem = GetRootItem();
  658. //
  659. // Find the matching tree item from the linear list.
  660. //
  661. DBG_OUT(("Start of TREE list:"));
  662. while (pItem != NULL) {
  663. BSTR bstrInfo = NULL;
  664. pItem->DumpTreeData(&bstrInfo);
  665. DBG_OUT(("%ws\n", bstrInfo));
  666. pItem = pItem->m_pLinearList;
  667. }
  668. DBG_OUT((":End of TREE list"));
  669. return S_OK;
  670. }
  671. */
  672. /**************************************************************************\
  673. * CWiaTree::UnlinkChildItemTree
  674. *
  675. * This method recursively unlinks the tree by calling
  676. * RemoveItemFromFolder on each driver item under the root.
  677. *
  678. * Arguments:
  679. *
  680. * lReason - Reason for unlink of tree.
  681. *
  682. * Return Value:
  683. *
  684. * Status
  685. *
  686. * History:
  687. *
  688. * 1/21/1999 Original Version
  689. *
  690. \**************************************************************************/
  691. HRESULT _stdcall CWiaTree::UnlinkChildItemTree(
  692. LONG lReason,
  693. PFN_UNLINK_CALLBACK pFunc)
  694. {
  695. HRESULT hr = S_OK;
  696. //
  697. // Delete the childern.
  698. //
  699. CWiaTree *pChild = m_pChild;
  700. while (pChild != NULL) {
  701. //
  702. // If the child is a folder then call
  703. // recursively to delete all childern under.
  704. //
  705. if (pChild->m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
  706. hr = pChild->UnlinkChildItemTree(lReason, pFunc);
  707. if (FAILED(hr)) {
  708. break;
  709. }
  710. }
  711. //
  712. // remove item from tree
  713. //
  714. hr = pChild->RemoveItemFromFolder(lReason);
  715. if (FAILED(hr)) {
  716. break;
  717. }
  718. //
  719. // If a callback has been specified, call it with the
  720. // payload as argument
  721. //
  722. if (pFunc && pChild->m_pData) {
  723. pFunc(pChild->m_pData);
  724. }
  725. pChild = m_pChild;
  726. }
  727. return hr;
  728. }
  729. /**************************************************************************\
  730. * CWiaTree::UnlinkItemTree
  731. *
  732. * This method unlinks the tree. Must be called on the root
  733. * driver item.
  734. *
  735. * Arguments:
  736. *
  737. * lReason - Reason for unlinking the tree.
  738. *
  739. * Return Value:
  740. *
  741. * Status
  742. *
  743. * History:
  744. *
  745. * 1/21/1999 Original Version
  746. *
  747. \**************************************************************************/
  748. HRESULT _stdcall CWiaTree::UnlinkItemTree(
  749. LONG lReason,
  750. PFN_UNLINK_CALLBACK pFunc)
  751. {
  752. CWiaCritSect _CritSect(&m_CritSect);
  753. //
  754. // this must be the root item
  755. //
  756. if (!(m_lFlags & WiaItemTypeRoot)) {
  757. DBG_ERR(("CWiaTree::UnlinkItemTree, caller not root item"));
  758. return E_INVALIDARG;
  759. }
  760. HRESULT hr = S_OK;
  761. //
  762. // Unlink any childern.
  763. //
  764. if (m_pChild) {
  765. hr = UnlinkChildItemTree(lReason, pFunc);
  766. }
  767. if (SUCCEEDED(hr)) {
  768. //
  769. // Remove root item.
  770. //
  771. hr = RemoveItemFromFolder(lReason);
  772. //
  773. // If a callback has been specified, call it with the
  774. // payload as argument
  775. //
  776. if (pFunc) {
  777. pFunc(m_pData);
  778. }
  779. }
  780. return hr;
  781. }
  782. /**************************************************************************\
  783. * CWiaTree::FindItemByName
  784. *
  785. * Locate a tree item by it's full item name. Ref count of the returned
  786. * interface is done by the caller.
  787. *
  788. * Arguments:
  789. *
  790. * lFlags - Operation flags.
  791. * bstrFullItemName - Requested item name.
  792. * ppItem - Pointer to returned item, if found.
  793. *
  794. * Return Value:
  795. *
  796. * Status
  797. *
  798. * History:
  799. *
  800. * 1/27/1999 Original Version
  801. *
  802. \**************************************************************************/
  803. HRESULT _stdcall CWiaTree::FindItemByName(
  804. LONG lFlags,
  805. BSTR bstrFullItemName,
  806. CWiaTree **ppItem)
  807. {
  808. CWiaCritSect _CritSect(&m_CritSect);
  809. if (ppItem) {
  810. *ppItem = NULL;
  811. }
  812. else {
  813. DBG_ERR(("CWiaTree::FindItemByName NULL ppItem"));
  814. return E_INVALIDARG;
  815. }
  816. //
  817. // start at beginning of item linear list
  818. //
  819. CWiaTree *pItem = GetRootItem();
  820. //
  821. // Find the matching tree item from the linear list.
  822. //
  823. while (pItem != NULL) {
  824. if (wcscmp(pItem->m_bstrFullItemName, bstrFullItemName) == 0) {
  825. //
  826. // Item is found. No need to increase ref count, taken care
  827. // of by caller.
  828. //
  829. *ppItem = pItem;
  830. return S_OK;
  831. }
  832. pItem = pItem->m_pLinearList;
  833. }
  834. return S_FALSE;
  835. }
  836. /**************************************************************************\
  837. * CWiaTree::FindChildItemByName
  838. *
  839. * Locate a child item by it's item name. Caller takes care of increasing
  840. * the reference count of the returned item interface.
  841. *
  842. * Arguments:
  843. *
  844. * bstrItemName - Requested item name.
  845. * ppIChildItem - Pointer to returned item, if found.
  846. *
  847. * Return Value:
  848. *
  849. * Status
  850. *
  851. * History:
  852. *
  853. * 1/27/1999 Original Version
  854. *
  855. \**************************************************************************/
  856. HRESULT _stdcall CWiaTree::FindChildItemByName(
  857. BSTR bstrItemName,
  858. CWiaTree **ppIChildItem)
  859. {
  860. CWiaCritSect _CritSect(&m_CritSect);
  861. CWiaTree *pCurItem;
  862. pCurItem = m_pChild;
  863. if (!pCurItem) {
  864. return S_FALSE;
  865. }
  866. *ppIChildItem = NULL;
  867. do {
  868. if (wcscmp(bstrItemName, pCurItem->m_bstrItemName) == 0) {
  869. //
  870. // No need to increase ref count, taken care of by caller.
  871. //
  872. *ppIChildItem = pCurItem;
  873. return S_OK;
  874. }
  875. pCurItem = pCurItem->m_pNext;
  876. } while (pCurItem != m_pChild);
  877. return S_FALSE;
  878. }
  879. /**************************************************************************\
  880. * CWiaTree::GetParent
  881. *
  882. * Get the parent of this item. Returns S_FALSE and null if
  883. * called on root item.
  884. *
  885. * Arguments:
  886. *
  887. * ppIParentItem - Pointer to returned parent, if found.
  888. *
  889. * Return Value:
  890. *
  891. * Status
  892. *
  893. * History:
  894. *
  895. * 1/27/1999 Original Version
  896. *
  897. \**************************************************************************/
  898. HRESULT _stdcall CWiaTree::GetParentItem(CWiaTree **ppIParentItem)
  899. {
  900. if (m_lFlags & WiaItemTypeRoot) {
  901. *ppIParentItem = NULL;
  902. return S_FALSE;
  903. }
  904. *ppIParentItem = m_pParent;
  905. return S_OK;
  906. }
  907. /**************************************************************************\
  908. * CWiaTree::GetFirstChild
  909. *
  910. * Return the first child item of this folder.
  911. *
  912. * Arguments:
  913. *
  914. * ppIChildItem - Pointer to returned child item, if found.
  915. *
  916. * Return Value:
  917. *
  918. * Status
  919. *
  920. * History:
  921. *
  922. * 1/27/1999 Original Version
  923. *
  924. \**************************************************************************/
  925. HRESULT _stdcall CWiaTree::GetFirstChildItem(CWiaTree **ppIChildItem)
  926. {
  927. HRESULT hr = S_FALSE;
  928. //
  929. // Check special case: if ppIChildItem == NULL, then just check
  930. // whether there are any children.
  931. //
  932. // S_OK if child exists, else S_FALSE.
  933. //
  934. if (m_pChild != NULL) {
  935. hr = S_OK;
  936. }
  937. if (ppIChildItem == NULL) {
  938. return hr;
  939. }
  940. *ppIChildItem = NULL;
  941. if (!(m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments))) {
  942. DBG_ERR(("CWiaTree::GetFirstChildItem, caller not folder"));
  943. return E_INVALIDARG;
  944. }
  945. *ppIChildItem = m_pChild;
  946. return hr;
  947. }
  948. /**************************************************************************\
  949. * CWiaTree::GetNextSibling
  950. *
  951. * Find the next sibling of this item.
  952. *
  953. * Arguments:
  954. *
  955. * ppSiblingItem - Pointer to the returned sibling item, if found.
  956. *
  957. * Return Value:
  958. *
  959. * Status
  960. *
  961. * History:
  962. *
  963. * 1/27/1999 Original Version
  964. *
  965. \**************************************************************************/
  966. HRESULT _stdcall CWiaTree::GetNextSiblingItem(CWiaTree **ppSiblingItem)
  967. {
  968. CWiaCritSect _CritSect(&m_CritSect);
  969. if (!ppSiblingItem) {
  970. return S_FALSE;
  971. }
  972. *ppSiblingItem = NULL;
  973. if (m_pNext && m_pParent) {
  974. if (m_pNext != m_pParent->m_pChild) {
  975. *ppSiblingItem = m_pNext;
  976. return S_OK;
  977. }
  978. }
  979. return S_FALSE;
  980. }
  981. /**************************************************************************\
  982. * ValidateTreeItem
  983. *
  984. * Validate a tree item.
  985. *
  986. * Arguments:
  987. *
  988. * pTreeItem - Pointer to a tree item.
  989. *
  990. * Return Value:
  991. *
  992. * Status
  993. *
  994. * History:
  995. *
  996. * 1/27/1999 Original Version
  997. *
  998. \**************************************************************************/
  999. HRESULT _stdcall ValidateTreeItem(CWiaTree *pTreeItem)
  1000. {
  1001. if (!pTreeItem) {
  1002. DBG_ERR(("ValidateTreeItem, NULL tree item pointer"));
  1003. return E_POINTER;
  1004. }
  1005. if (pTreeItem->m_ulSig == CWIATREE_SIG) {
  1006. return S_OK;
  1007. }
  1008. else {
  1009. DBG_ERR(("ValidateTreeItem, not a tree item"));
  1010. return E_INVALIDARG;
  1011. }
  1012. }