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

/*******************************************************************************
*
* (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;
}
}