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
1233 lines
27 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1998
|
|
*
|
|
* TITLE: WiaTree.Cpp
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: reedb
|
|
*
|
|
* DATE: 27 Apr, 1999
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of the WIA tree class. A folder and file based tree with
|
|
* a parallel linear list for name based searches.
|
|
*
|
|
*******************************************************************************/
|
|
#include "precomp.h"
|
|
#include "stiexe.h"
|
|
|
|
#include "wiamindr.h"
|
|
|
|
|
|
#include "helpers.h"
|
|
|
|
HRESULT _stdcall ValidateTreeItem(CWiaTree*);
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree
|
|
*
|
|
* Constructor for tree item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaTree::CWiaTree()
|
|
{
|
|
m_ulSig = CWIATREE_SIG;
|
|
|
|
m_lFlags = WiaItemTypeFree;
|
|
|
|
m_pNext = NULL;
|
|
m_pPrev = NULL;
|
|
m_pParent = NULL;
|
|
m_pChild = NULL;
|
|
m_pLinearList = NULL;
|
|
m_bstrItemName = NULL;
|
|
m_bstrFullItemName = NULL;
|
|
m_pData = NULL;
|
|
|
|
m_bInitCritSect = FALSE;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* Initialize
|
|
*
|
|
* Initialize new tree item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags - Object flags for new item.
|
|
* bstrItemName - Item name.
|
|
* bstrFullItemName - Full item name, including path.
|
|
* pData - Pointer to items payload data.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::Initialize(
|
|
LONG lFlags,
|
|
BSTR bstrItemName,
|
|
BSTR bstrFullItemName,
|
|
void *pData)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Tree items must be either folder or file.
|
|
//
|
|
|
|
if (!(lFlags & (WiaItemTypeFolder | WiaItemTypeFile))) {
|
|
DBG_ERR(("CWiaTree::Initialize, bad flags parameter: 0x%08X", lFlags));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Initialize the critical section
|
|
//
|
|
|
|
__try {
|
|
if(!InitializeCriticalSectionAndSpinCount(&m_CritSect, MINLONG)) {
|
|
m_bInitCritSect = FALSE;
|
|
return HRESULT_FROM_WIN32(::GetLastError());
|
|
}
|
|
m_bInitCritSect = TRUE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
m_bInitCritSect = FALSE;
|
|
DBG_ERR(("CWiaTree::Initialize, Error initializing critical section"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
//
|
|
// Root items are always valid. Other items are valid only after
|
|
// insertion in the tree, so set not present flags.
|
|
//
|
|
|
|
if (!(lFlags & WiaItemTypeRoot)) {
|
|
lFlags |= WiaItemTypeDeleted;
|
|
lFlags |= WiaItemTypeDisconnected;
|
|
}
|
|
|
|
m_lFlags = lFlags;
|
|
|
|
//
|
|
// Maintain the item names for by name searches.
|
|
//
|
|
|
|
m_bstrItemName = SysAllocString(bstrItemName);
|
|
if (!m_bstrItemName) {
|
|
DBG_ERR(("CWiaTree::Initialize, unable to allocate item name"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
m_bstrFullItemName = SysAllocString(bstrFullItemName);
|
|
if (!m_bstrFullItemName) {
|
|
DBG_ERR(("CWiaTree::Initialize, unable to allocate full item name"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
SetItemData(pData);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ~CWiaTreee
|
|
*
|
|
* Destructor for tree item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaTree::~CWiaTree()
|
|
{
|
|
DBG_FN(CWiaTree::~CWiaTree);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Item should be disconnected.
|
|
//
|
|
|
|
if (m_pNext || m_pPrev || m_pParent || m_pChild) {
|
|
DBG_ERR(("Destroy Tree Item, item still connected"));
|
|
}
|
|
|
|
//
|
|
// Free item names.
|
|
//
|
|
|
|
if (m_bstrItemName) {
|
|
SysFreeString(m_bstrItemName);
|
|
m_bstrItemName = NULL;
|
|
}
|
|
if (m_bstrFullItemName) {
|
|
SysFreeString(m_bstrFullItemName);
|
|
m_bstrFullItemName = NULL;
|
|
}
|
|
|
|
//
|
|
// Delete the critical section
|
|
//
|
|
|
|
if (m_bInitCritSect) {
|
|
DeleteCriticalSection(&m_CritSect);
|
|
}
|
|
m_bInitCritSect = FALSE;
|
|
|
|
|
|
//
|
|
// Clear all members
|
|
//
|
|
|
|
m_ulSig = 0;
|
|
m_lFlags = WiaItemTypeFree;
|
|
m_pNext = NULL;
|
|
m_pPrev = NULL;
|
|
m_pParent = NULL;
|
|
m_pChild = NULL;
|
|
m_pLinearList = NULL;
|
|
m_pData = NULL;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* GetRootItem
|
|
*
|
|
* Walk back up the tree to find the root of this item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Pointer to this items root item.
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaTree * _stdcall CWiaTree::GetRootItem()
|
|
{
|
|
CWiaTree *pRoot = this;
|
|
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
//
|
|
// walk back up tree to root
|
|
//
|
|
|
|
while ((pRoot) && (pRoot->m_pParent != NULL)) {
|
|
pRoot = pRoot->m_pParent;
|
|
}
|
|
|
|
//
|
|
// verify root item
|
|
//
|
|
|
|
if (pRoot) {
|
|
if (!(pRoot->m_lFlags & WiaItemTypeRoot)) {
|
|
DBG_ERR(("CWiaTree::GetRootItem, root item doesn't have WiaItemTypeRoot set"));
|
|
return NULL;
|
|
}
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaTree::GetRootItem, root item not found, tree corrupt"));
|
|
}
|
|
return pRoot;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::AddItemToLinearList
|
|
*
|
|
* Add an item to the linear list. Must be called on a root item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItem - Pointer to the item to be added.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::AddItemToLinearList(CWiaTree *pItem)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
//
|
|
// Validate the child item.
|
|
//
|
|
|
|
if (pItem == NULL) {
|
|
DBG_ERR(("CWiaTree::AddItemToLinearList, NULL input pointer"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
//
|
|
// this must be a root item
|
|
//
|
|
|
|
if (!(m_lFlags & WiaItemTypeRoot)) {
|
|
DBG_ERR(("CWiaTree::AddItemToLinearList, caller doesn't have WiaItemTypeRoot set"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// add to single linked list
|
|
//
|
|
|
|
pItem->m_pLinearList = m_pLinearList;
|
|
m_pLinearList = pItem;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::RemoveItemFromLinearList
|
|
*
|
|
* Remove an item from the linear list. Must be called on a root item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItem - Pointer to the item to be removed.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::RemoveItemFromLinearList(CWiaTree *pItem)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// validate
|
|
//
|
|
|
|
if (pItem == NULL) {
|
|
DBG_ERR(("CWiaTree::RemoveItemFromLinearList, NULL input pointer"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
//
|
|
// this must be a root item
|
|
//
|
|
|
|
if (!(m_lFlags & WiaItemTypeRoot)) {
|
|
DBG_ERR(("CWiaTree::RemoveItemFromLinearList, caller doesn't have WiaItemTypeRoot set"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Root item case.
|
|
//
|
|
|
|
if (pItem == this) {
|
|
m_pLinearList = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// find item in list
|
|
//
|
|
|
|
CWiaTree* pPrev = this;
|
|
CWiaTree* pTemp;
|
|
|
|
//
|
|
// look for match in list
|
|
//
|
|
|
|
do {
|
|
//
|
|
// look for item
|
|
//
|
|
|
|
if (pPrev->m_pLinearList == pItem) {
|
|
|
|
//
|
|
// remove from list and exit
|
|
//
|
|
|
|
pPrev->m_pLinearList = pItem->m_pLinearList;
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// next item
|
|
//
|
|
|
|
pPrev = pPrev->m_pLinearList;
|
|
|
|
} while (pPrev != NULL);
|
|
|
|
DBG_ERR(("CWiaTree::RemoveItemFromLinearList, item not found: 0x%08X", pItem));
|
|
return E_FAIL;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::AddChildItem
|
|
*
|
|
* Add a child item to the tree.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItem - Pointer to the child item to be added.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::AddChildItem(CWiaTree *pItem)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
//
|
|
// Validate the child item.
|
|
//
|
|
|
|
if (!pItem) {
|
|
DBG_ERR(("CWiaTree::AddChildItem pItem is NULL "));
|
|
return E_POINTER;
|
|
}
|
|
|
|
//
|
|
// Not using sentinell so check enpty folder case.
|
|
//
|
|
|
|
if (m_pChild == NULL) {
|
|
|
|
m_pChild = pItem;
|
|
pItem->m_pNext = pItem;
|
|
pItem->m_pPrev = pItem;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Add to end of folder list.
|
|
//
|
|
|
|
CWiaTree *pTempItem = m_pChild;
|
|
|
|
pTempItem->m_pPrev->m_pNext = pItem;
|
|
pItem->m_pPrev = pTempItem->m_pPrev;
|
|
pItem->m_pNext = pTempItem;
|
|
pTempItem->m_pPrev = pItem;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::AddItemToFolder
|
|
*
|
|
* Add a tree item to a folder in the tree. Parent must be a folder.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pIParent - Parent of the item.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::AddItemToFolder(CWiaTree *pParent)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Validate the parent. Parents must be a folder.
|
|
//
|
|
|
|
if (!pParent) {
|
|
DBG_ERR(("CWiaTree::AddItemToFolder, NULL parent"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (!(pParent->m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments))) {
|
|
DBG_ERR(("CWiaTree::AddItemToFolder, parent is not a folder"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// First add item to linear list of items.
|
|
//
|
|
|
|
CWiaTree *pRoot = pParent->GetRootItem();
|
|
if (pRoot == NULL) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = pRoot->AddItemToLinearList(this);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Add the item to the tree.
|
|
//
|
|
|
|
hr = pParent->AddChildItem(this);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Remember parent
|
|
//
|
|
|
|
m_pParent = pParent;
|
|
|
|
//
|
|
// Item has been added to the tree, clear not present flags.
|
|
//
|
|
|
|
m_lFlags &= ~WiaItemTypeDeleted;
|
|
m_lFlags &= ~WiaItemTypeDisconnected;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* RemoveItemFromFolder
|
|
*
|
|
* Remove an item from a folder of the tree and mark it so that
|
|
* no device access can be done through it.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lReason - Reason for removal of item.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::RemoveItemFromFolder(LONG lReason)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Reason for removal must be valid.
|
|
//
|
|
|
|
if (!(lReason & (WiaItemTypeDeleted | WiaItemTypeDisconnected))) {
|
|
DBG_ERR(("CWiaTree::RemoveItemFromFolder, invalid lReason: 0x%08X", lReason));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Folder items must be empty.
|
|
//
|
|
|
|
if (m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
|
|
|
|
if (m_pChild != NULL) {
|
|
DBG_ERR(("CWiaTree::RemoveItemFromFolder, trying to remove folder that is not empty"));
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Remove non-root from linear list
|
|
//
|
|
|
|
CWiaTree *pRoot = GetRootItem();
|
|
|
|
if (pRoot == NULL) {
|
|
DBG_ERR(("CWiaTree::RemoveItemFromFolder, can't find root"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (pRoot != this) {
|
|
|
|
pRoot->RemoveItemFromLinearList(this);
|
|
|
|
//
|
|
// remove from list of children
|
|
//
|
|
|
|
if (m_pNext != this) {
|
|
|
|
//
|
|
// remove from non-empty list
|
|
//
|
|
|
|
m_pPrev->m_pNext = m_pNext;
|
|
m_pNext->m_pPrev = m_pPrev;
|
|
|
|
//
|
|
// was it head?
|
|
//
|
|
|
|
if (m_pParent->m_pChild == this) {
|
|
|
|
m_pParent->m_pChild = m_pNext;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// list contains only this child. mark parent's
|
|
// child pointer to NULL
|
|
//
|
|
|
|
m_pParent->m_pChild = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// to prevent accidents, clear connection fields
|
|
//
|
|
|
|
m_pNext = NULL;
|
|
m_pPrev = NULL;
|
|
m_pParent = NULL;
|
|
m_pChild = NULL;
|
|
|
|
//
|
|
// Indicate why item was removed from the driver item tree.
|
|
//
|
|
|
|
m_lFlags |= lReason;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::GetFullItemName
|
|
*
|
|
* Allocates and fills in a BSTR with this items full name. The full item
|
|
* name includes item path information. Caller must free.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pbstrFullItemName - Pointer to returned full item name.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::GetFullItemName(BSTR *pbstrFullItemName)
|
|
{
|
|
if (!pbstrFullItemName) {
|
|
DBG_ERR(("CWiaTree::GetFullItemName pbstrFullItemName is NULL "));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
BSTR bstr = SysAllocString(m_bstrFullItemName);
|
|
if (bstr) {
|
|
*pbstrFullItemName = bstr;
|
|
return S_OK;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::GetItemName
|
|
*
|
|
* Allocates and fills in a BSTR with this items name. The item name
|
|
* does not include item path information. Caller must free.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pbstrItemName - Pointer to returned item name.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::GetItemName(BSTR *pbstrItemName)
|
|
{
|
|
if (!pbstrItemName) {
|
|
DBG_ERR(("CWiaTree::GetItemName pbstrItemName is NULL "));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
BSTR bstr = SysAllocString(m_bstrItemName);
|
|
if (bstr) {
|
|
*pbstrItemName = bstr;
|
|
return S_OK;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::DumpTreeData
|
|
*
|
|
* Allocate buffer and dump formatted private CWiaTree data into it.
|
|
* This method is debug only. Free component returns E_NOTIMPL.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* bstrDrvItemData - Pointer to allocated buffer. Caller must free.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::DumpTreeData(BSTR *bstrDrvItemData)
|
|
{
|
|
#ifdef DEBUG
|
|
|
|
#define BUF_SIZE 1024
|
|
#define LINE_SIZE 128
|
|
|
|
WCHAR szTemp[BUF_SIZE];
|
|
LPOLESTR psz = szTemp;
|
|
|
|
wcscpy(szTemp, L"");
|
|
|
|
psz+= wsprintfW(psz, L"Tree item, CWiaTree: %08X\r\n\r\n", this);
|
|
psz+= wsprintfW(psz, L"Address Member Value\r\n");
|
|
psz+= wsprintfW(psz, L"%08X m_ulSig: %08X\r\n", &m_ulSig, m_ulSig);
|
|
psz+= wsprintfW(psz, L"%08X m_lFlags: %08X\r\n", &m_lFlags, m_lFlags);
|
|
psz+= wsprintfW(psz, L"%08X m_pNext: %08X\r\n", &m_pNext, m_pNext);
|
|
psz+= wsprintfW(psz, L"%08X m_pPrev: %08X\r\n", &m_pPrev, m_pPrev);
|
|
psz+= wsprintfW(psz, L"%08X m_pParent: %08X\r\n", &m_pParent, m_pParent);
|
|
psz+= wsprintfW(psz, L"%08X m_pChild: %08X\r\n", &m_pChild, m_pChild);
|
|
psz+= wsprintfW(psz, L"%08X m_pLinearList: %08X\r\n", &m_pLinearList, m_pLinearList);
|
|
psz+= wsprintfW(psz, L"%08X m_bstrItemName: %08X, %ws\r\n", &m_bstrItemName, m_bstrItemName, m_bstrItemName);
|
|
psz+= wsprintfW(psz, L"%08X m_bstrFullItemName: %08X, %ws\r\n", &m_bstrFullItemName, m_bstrFullItemName, m_bstrFullItemName);
|
|
psz+= wsprintfW(psz, L"%08X m_pData: %08X\r\n", &m_pData, m_pData);
|
|
|
|
if (psz > (szTemp + (BUF_SIZE - LINE_SIZE))) {
|
|
DBG_ERR(("CWiaTree::DumpDrvItemData buffer too small"));
|
|
}
|
|
|
|
*bstrDrvItemData = SysAllocString(szTemp);
|
|
if (*bstrDrvItemData) {
|
|
return S_OK;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
#else
|
|
return E_NOTIMPL;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
HRESULT _stdcall CWiaTree::DumpAllTreeData()
|
|
{
|
|
//
|
|
// start at beginning of item linear list
|
|
//
|
|
|
|
CWiaTree *pItem = GetRootItem();
|
|
|
|
//
|
|
// Find the matching tree item from the linear list.
|
|
//
|
|
|
|
DBG_OUT(("Start of TREE list:"));
|
|
|
|
while (pItem != NULL) {
|
|
|
|
BSTR bstrInfo = NULL;
|
|
pItem->DumpTreeData(&bstrInfo);
|
|
|
|
DBG_OUT(("%ws\n", bstrInfo));
|
|
|
|
pItem = pItem->m_pLinearList;
|
|
}
|
|
DBG_OUT((":End of TREE list"));
|
|
return S_OK;
|
|
}
|
|
*/
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::UnlinkChildItemTree
|
|
*
|
|
* This method recursively unlinks the tree by calling
|
|
* RemoveItemFromFolder on each driver item under the root.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lReason - Reason for unlink of tree.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/21/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::UnlinkChildItemTree(
|
|
LONG lReason,
|
|
PFN_UNLINK_CALLBACK pFunc)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Delete the childern.
|
|
//
|
|
|
|
CWiaTree *pChild = m_pChild;
|
|
|
|
while (pChild != NULL) {
|
|
//
|
|
// If the child is a folder then call
|
|
// recursively to delete all childern under.
|
|
//
|
|
|
|
if (pChild->m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
|
|
hr = pChild->UnlinkChildItemTree(lReason, pFunc);
|
|
if (FAILED(hr)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// remove item from tree
|
|
//
|
|
|
|
hr = pChild->RemoveItemFromFolder(lReason);
|
|
if (FAILED(hr)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If a callback has been specified, call it with the
|
|
// payload as argument
|
|
//
|
|
|
|
if (pFunc && pChild->m_pData) {
|
|
pFunc(pChild->m_pData);
|
|
}
|
|
|
|
pChild = m_pChild;
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::UnlinkItemTree
|
|
*
|
|
* This method unlinks the tree. Must be called on the root
|
|
* driver item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lReason - Reason for unlinking the tree.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/21/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::UnlinkItemTree(
|
|
LONG lReason,
|
|
PFN_UNLINK_CALLBACK pFunc)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
//
|
|
// this must be the root item
|
|
//
|
|
|
|
if (!(m_lFlags & WiaItemTypeRoot)) {
|
|
DBG_ERR(("CWiaTree::UnlinkItemTree, caller not root item"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Unlink any childern.
|
|
//
|
|
|
|
if (m_pChild) {
|
|
hr = UnlinkChildItemTree(lReason, pFunc);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Remove root item.
|
|
//
|
|
|
|
hr = RemoveItemFromFolder(lReason);
|
|
|
|
//
|
|
// If a callback has been specified, call it with the
|
|
// payload as argument
|
|
//
|
|
|
|
if (pFunc) {
|
|
pFunc(m_pData);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::FindItemByName
|
|
*
|
|
* Locate a tree item by it's full item name. Ref count of the returned
|
|
* interface is done by the caller.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags - Operation flags.
|
|
* bstrFullItemName - Requested item name.
|
|
* ppItem - Pointer to returned item, if found.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/27/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::FindItemByName(
|
|
LONG lFlags,
|
|
BSTR bstrFullItemName,
|
|
CWiaTree **ppItem)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
if (ppItem) {
|
|
*ppItem = NULL;
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaTree::FindItemByName NULL ppItem"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// start at beginning of item linear list
|
|
//
|
|
|
|
CWiaTree *pItem = GetRootItem();
|
|
|
|
//
|
|
// Find the matching tree item from the linear list.
|
|
//
|
|
|
|
while (pItem != NULL) {
|
|
|
|
if (wcscmp(pItem->m_bstrFullItemName, bstrFullItemName) == 0) {
|
|
|
|
//
|
|
// Item is found. No need to increase ref count, taken care
|
|
// of by caller.
|
|
//
|
|
|
|
*ppItem = pItem;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
pItem = pItem->m_pLinearList;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::FindChildItemByName
|
|
*
|
|
* Locate a child item by it's item name. Caller takes care of increasing
|
|
* the reference count of the returned item interface.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* bstrItemName - Requested item name.
|
|
* ppIChildItem - Pointer to returned item, if found.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/27/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::FindChildItemByName(
|
|
BSTR bstrItemName,
|
|
CWiaTree **ppIChildItem)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
CWiaTree *pCurItem;
|
|
|
|
pCurItem = m_pChild;
|
|
if (!pCurItem) {
|
|
return S_FALSE;
|
|
}
|
|
|
|
*ppIChildItem = NULL;
|
|
|
|
do {
|
|
if (wcscmp(bstrItemName, pCurItem->m_bstrItemName) == 0) {
|
|
|
|
//
|
|
// No need to increase ref count, taken care of by caller.
|
|
//
|
|
|
|
*ppIChildItem = pCurItem;
|
|
return S_OK;
|
|
}
|
|
|
|
pCurItem = pCurItem->m_pNext;
|
|
|
|
} while (pCurItem != m_pChild);
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::GetParent
|
|
*
|
|
* Get the parent of this item. Returns S_FALSE and null if
|
|
* called on root item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ppIParentItem - Pointer to returned parent, if found.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/27/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::GetParentItem(CWiaTree **ppIParentItem)
|
|
{
|
|
if (m_lFlags & WiaItemTypeRoot) {
|
|
|
|
*ppIParentItem = NULL;
|
|
return S_FALSE;
|
|
}
|
|
|
|
*ppIParentItem = m_pParent;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::GetFirstChild
|
|
*
|
|
* Return the first child item of this folder.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ppIChildItem - Pointer to returned child item, if found.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/27/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
HRESULT _stdcall CWiaTree::GetFirstChildItem(CWiaTree **ppIChildItem)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
//
|
|
// Check special case: if ppIChildItem == NULL, then just check
|
|
// whether there are any children.
|
|
//
|
|
// S_OK if child exists, else S_FALSE.
|
|
//
|
|
|
|
if (m_pChild != NULL) {
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (ppIChildItem == NULL) {
|
|
return hr;
|
|
}
|
|
|
|
*ppIChildItem = NULL;
|
|
if (!(m_lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments))) {
|
|
DBG_ERR(("CWiaTree::GetFirstChildItem, caller not folder"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppIChildItem = m_pChild;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaTree::GetNextSibling
|
|
*
|
|
* Find the next sibling of this item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ppSiblingItem - Pointer to the returned sibling item, if found.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/27/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaTree::GetNextSiblingItem(CWiaTree **ppSiblingItem)
|
|
{
|
|
CWiaCritSect _CritSect(&m_CritSect);
|
|
|
|
if (!ppSiblingItem) {
|
|
return S_FALSE;
|
|
}
|
|
|
|
*ppSiblingItem = NULL;
|
|
if (m_pNext && m_pParent) {
|
|
if (m_pNext != m_pParent->m_pChild) {
|
|
|
|
*ppSiblingItem = m_pNext;
|
|
return S_OK;
|
|
}
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ValidateTreeItem
|
|
*
|
|
* Validate a tree item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pTreeItem - Pointer to a tree item.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/27/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall ValidateTreeItem(CWiaTree *pTreeItem)
|
|
{
|
|
if (!pTreeItem) {
|
|
DBG_ERR(("ValidateTreeItem, NULL tree item pointer"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (pTreeItem->m_ulSig == CWIATREE_SIG) {
|
|
return S_OK;
|
|
}
|
|
else {
|
|
DBG_ERR(("ValidateTreeItem, not a tree item"));
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|