windows-nt/Source/XPSP1/NT/net/config/shell/folder/cfpidl_templates.cpp
2020-09-26 16:20:57 +08:00

568 lines
18 KiB
C++

// ****************************************************************************
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: C F P I D L _ T E M P L A T E S . C P P
//
// Contents: Connections Folder template structures.
//
// Author: deonb 12 Jan 2001
//
// ****************************************************************************
#include "pch.h"
#pragma hdrstop
#include "ncperms.h"
#include "ncras.h"
#include "foldinc.h" // Standard shell\folder includes
#include "ncnetcon.h"
template <class T>
HRESULT CPConFoldPidl<T>::FreePIDLIfRequired()
{
if ( m_pConFoldPidl )
{
FreeIDL(reinterpret_cast<LPITEMIDLIST>(m_pConFoldPidl));
m_pConFoldPidl = NULL;
return S_OK;
}
else
{
return S_FALSE;
}
}
template <class T>
HRESULT CPConFoldPidl<T>::Clear()
{
FreePIDLIfRequired();
return S_OK;
}
template <class T>
T& CPConFoldPidl<T>::operator *()
{
return (*m_pConFoldPidl);
}
template <class T>
UNALIGNED T* CPConFoldPidl<T>::operator->()
{
return m_pConFoldPidl;
}
template <class T>
const UNALIGNED T* CPConFoldPidl<T>::operator->() const
{
return m_pConFoldPidl;
}
template <class T>
HRESULT CPConFoldPidl<T>::ILCreate(const DWORD dwSize)
{
Assert(dwSize >= sizeof(T));
FreePIDLIfRequired();
// Just call the constructor on T (placement form of new doesn't allocate any more memory).
LPVOID pPlacement = ::ILCreate(dwSize);
if (!pPlacement)
{
return E_OUTOFMEMORY;
}
#if DBG
ZeroMemory(pPlacement, dwSize);
#endif
// Basically call the constructor
// Semantic equivalent to m_pConFoldPidl = pPlacement;
// m_pConFoldPidl::T();
m_pConFoldPidl = new( pPlacement ) T;
Assert(pPlacement == m_pConFoldPidl);
return S_OK;
}
template <class T>
HRESULT CPConFoldPidl<T>::SHAlloc(const SIZE_T cb)
{
FreePIDLIfRequired();
LPVOID pPlacement = reinterpret_cast<UNALIGNED T*>(::SHAlloc(cb));
if (!pPlacement)
{
return E_OUTOFMEMORY;
}
// Basically call the constructor
// Semantic equivalent to m_pConFoldPidl = pPlacement;
// m_pConFoldPidl::T();
m_pConFoldPidl = new( pPlacement ) T;
Assert(pPlacement == m_pConFoldPidl);
if (m_pConFoldPidl)
{
return S_OK;
}
else
{
return E_OUTOFMEMORY;
}
}
template <class T>
HRESULT CPConFoldPidl<T>::ILClone(const CPConFoldPidl<T>& PConFoldPidl)
{
C_ASSERT(PIDL_VERSION == T::CONNECTIONS_FOLDER_IDL_VERSION);
FreePIDLIfRequired();
LPVOID pPlacement = reinterpret_cast<UNALIGNED T*>(::ILClone(reinterpret_cast<LPITEMIDLIST>(PConFoldPidl.m_pConFoldPidl)));
if (!pPlacement)
{
return E_OUTOFMEMORY;
}
// Basically call the constructor
// Semantic equivalent to m_pConFoldPidl = pPlacement;
// m_pConFoldPidl::T();
m_pConFoldPidl = new( pPlacement ) T;
Assert(pPlacement == m_pConFoldPidl);
if (m_pConFoldPidl)
{
Assert(m_pConFoldPidl->IsPidlOfThisType());
return S_OK;
}
else
{
return E_OUTOFMEMORY;
}
}
template <class T>
LPITEMIDLIST CPConFoldPidl<T>::TearOffItemIdList() const
{
TraceFileFunc(ttidConFoldEntry);
Assert(m_pConFoldPidl);
Assert( m_pConFoldPidl->IsPidlOfThisType() );
LPITEMIDLIST retList = ::ILClone(reinterpret_cast<LPITEMIDLIST>(m_pConFoldPidl));
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidPIDL(retList));
#endif
return retList;
}
template <class T>
LPITEMIDLIST CPConFoldPidl<T>::Detach()
{
TraceFileFunc(ttidConFoldEntry);
Assert(m_pConFoldPidl);
Assert( m_pConFoldPidl->IsPidlOfThisType() );
LPITEMIDLIST retList = reinterpret_cast<LPITEMIDLIST>(m_pConFoldPidl);
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidPIDL(retList));
#endif
m_pConFoldPidl = NULL;
return retList;
}
template <class T>
LPCITEMIDLIST CPConFoldPidl<T>::GetItemIdList() const
{
TraceFileFunc(ttidConFoldEntry);
Assert(m_pConFoldPidl);
Assert( m_pConFoldPidl->IsPidlOfThisType() );
LPCITEMIDLIST tmpItemIdList = reinterpret_cast<LPCITEMIDLIST>(m_pConFoldPidl);
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidPIDL(tmpItemIdList));
#endif
return tmpItemIdList;
}
#ifdef DBG_VALIDATE_PIDLS
template <class T>
BOOL CPConFoldPidl<T>::IsValidConFoldPIDL() const
{
return IsValidPIDL(reinterpret_cast<LPCITEMIDLIST>(m_pConFoldPidl));
}
#endif
template <class T>
HRESULT CPConFoldPidl<T>::InitializeFromItemIDList(LPCITEMIDLIST pItemIdList)
{
DWORD dwPidlSize = 0;
UNALIGNED ConFoldPidl_v1 * cfpv1 = NULL;
UNALIGNED ConFoldPidl_v2 * cfpv2 = NULL;
UNALIGNED ConFoldPidl98 * cfpv98 = NULL;
LPVOID pPlacement = NULL;
HRESULT hr = S_OK;
Assert(pItemIdList);
#ifdef DBG_VALIDATE_PIDLS
if (!IsValidPIDL(pItemIdList))
{
TraceError("Invalid PIDL passed to InitializeFromItemIDList", E_INVALIDARG);
}
#endif
Clear();
CONFOLDPIDLTYPE pidlType = GetPidlType(pItemIdList);
if ( (PIDL_TYPE_UNKNOWN == pidlType) && (PIDL_VERSION == PIDL_TYPE_FOLDER) )
{
pidlType = PIDL_TYPE_FOLDER; // Give it the benefit of the doubt
}
if (pidlType == PIDL_VERSION)
{
pPlacement = reinterpret_cast<UNALIGNED T*>(::ILClone(pItemIdList));
if (!pPlacement)
{
return E_OUTOFMEMORY;
}
// Basically call the constructor
// Semantic equivalent to m_pConFoldPidl = pPlacement;
// m_pConFoldPidl::T();
m_pConFoldPidl = new( pPlacement ) T;
Assert(pPlacement == m_pConFoldPidl);
}
else // We'll have to convert:
{
TraceTag(ttidShellFolderIface, "InitializeFromItemIDList: Converting PIDL from type %d to %d", pidlType, PIDL_VERSION);
switch (PIDL_VERSION)
{
case PIDL_TYPE_UNKNOWN: // This is what we are
{
switch (pidlType)
{
// This is what we're getting
case PIDL_TYPE_UNKNOWN:
AssertSz(FALSE, "PIDL is already of this type.");
break;
case PIDL_TYPE_V1:
case PIDL_TYPE_V2:
case PIDL_TYPE_98:
case PIDL_TYPE_FOLDER:
default:
AssertSz(FALSE, "Can't upgrade PIDL to UNKNOWN type");
hr = E_INVALIDARG;
break;
}
}
break;
case PIDL_TYPE_V1: // This is what we are
{
switch (pidlType)
{
// This is what we're getting
case PIDL_TYPE_V1:
AssertSz(FALSE, "PIDL is already of this type.");
break;
case PIDL_TYPE_UNKNOWN:
case PIDL_TYPE_V2:
case PIDL_TYPE_98:
case PIDL_TYPE_FOLDER:
default:
AssertSz(FALSE, "Can't upgrade PIDL to PIDL_V1 type");
hr = E_INVALIDARG;
break;
}
}
break;
case PIDL_TYPE_FOLDER: // This is what we are
{
switch (pidlType)
{
// This is what we're getting
case PIDL_TYPE_FOLDER:
AssertSz(FALSE, "PIDL is already of this type.");
break;
case PIDL_TYPE_V1:
case PIDL_TYPE_98:
case PIDL_TYPE_UNKNOWN:
case PIDL_TYPE_V2:
default:
AssertSz(FALSE, "Can't upgrade PIDL to PIDL_TYPE_FOLDER type");
hr = E_INVALIDARG;
break;
}
}
break;
case PIDL_TYPE_98: // This is what we are
{
switch (pidlType)
{
// This is what we're getting
case PIDL_TYPE_98:
AssertSz(FALSE, "PIDL is already of this type.");
break;
case PIDL_TYPE_V1:
case PIDL_TYPE_V2:
case PIDL_TYPE_UNKNOWN:
case PIDL_TYPE_FOLDER:
default:
AssertSz(FALSE, "Can't upgrade PIDL to PIDL_TYPE_98 type");
hr = E_INVALIDARG;
break;
}
}
break;
case PIDL_TYPE_V2: // This is what we are
{
switch (pidlType)
{
// This is what we're getting
case PIDL_TYPE_V2:
AssertSz(FALSE, "PIDL is already of this type.");
break;
case PIDL_TYPE_V1:
{
// Do the convert.
cfpv1 = const_cast<ConFoldPidl_v1 *>(reinterpret_cast<const ConFoldPidl_v1 *>(pItemIdList));
Assert(cfpv1->IsPidlOfThisType());
if (!cfpv1->IsPidlOfThisType())
{
return E_INVALIDARG;
}
dwPidlSize = cfpv1->iCB + CBCONFOLDPIDLV2_MIN - CBCONFOLDPIDLV1_MIN;
dwPidlSize += sizeof(WCHAR); // Adding NULL for PhoneOrHostAddress in bData
pPlacement = reinterpret_cast<UNALIGNED T*>(::ILCreate(dwPidlSize + sizeof(USHORT))); // Terminating 0
if (!pPlacement)
{
return E_OUTOFMEMORY;
}
TraceTag(ttidShellFolderIface, "InitializeFromItemIDList: Original: 0x%08x New:0x%08x", pItemIdList, pPlacement);
// Basically call the constructor
// Semantic equivalent to m_pConFoldPidl = pPlacement;
// m_pConFoldPidl::T();
m_pConFoldPidl = new( pPlacement ) T;
Assert(pPlacement == m_pConFoldPidl);
Assert(sizeof(ConFoldPidlBase) <= cfpv1->iCB );
// Copy the ConFoldPidlBase data
CopyMemory(m_pConFoldPidl, cfpv1, sizeof(ConFoldPidlBase));
// I know we're already a ConFoldPidl_v2 - but this is a template, so we'll have to cast
// to get it to compile. This code path is dead for non-v2 classes though.
cfpv2 = reinterpret_cast<ConFoldPidl_v2 *>(m_pConFoldPidl);
// Copy the bData member (everything but ConFoldPidlBase in this case)
CopyMemory(cfpv2->bData, cfpv1->bData, cfpv1->iCB - sizeof(ConFoldPidlBase));
// Force update the version number and byte count
cfpv2->iCB = dwPidlSize;
const_cast<DWORD&>(cfpv2->dwVersion) = PIDL_TYPE_V2;
if (NCM_LAN == cfpv2->ncm)
{
cfpv2->ncsm = NCSM_LAN;
}
else
{
cfpv2->ncsm = NCSM_NONE;
}
cfpv2->ulStrPhoneOrHostAddressPos = cfpv2->ulPersistBufPos + cfpv2->ulPersistBufSize;
LPWSTR pszPhoneOrHostAddress = cfpv2->PszGetPhoneOrHostAddressPointer();
*pszPhoneOrHostAddress = L'\0';
cfpv2->ulStrPhoneOrHostAddressSize = sizeof(WCHAR); // Size of NULL
// Don't forget to terminate the list!
//
LPITEMIDLIST pidlTerminate;
pidlTerminate = ILNext( reinterpret_cast<LPCITEMIDLIST>( m_pConFoldPidl ) );
pidlTerminate->mkid.cb = 0;
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidConFoldPIDL());
#endif
Assert(m_pConFoldPidl->IsPidlOfThisType());
if (!m_pConFoldPidl->IsPidlOfThisType())
{
::SHFree(m_pConFoldPidl);
m_pConFoldPidl = NULL;
return E_FAIL;
}
}
break;
case PIDL_TYPE_98:
{
cfpv98 = const_cast<ConFoldPidl98 *>(reinterpret_cast<const ConFoldPidl98 *>(pItemIdList));
Assert(cfpv98->IsPidlOfThisType());
if (!cfpv98->IsPidlOfThisType())
{
return E_INVALIDARG;
}
WCHAR szName[MAX_PATH];
mbstowcs(szName, cfpv98->szaName, MAX_PATH);
ConnListEntry cle;
PCONFOLDPIDL pidlv2;
HRESULT hrTmp = g_ccl.HrFindConnectionByName(szName, cle);
if (hrTmp != S_OK)
{
return E_FAIL;
}
cle.ccfe.ConvertToPidl(pidlv2);
LPITEMIDLIST pIdl = pidlv2.TearOffItemIdList();
m_pConFoldPidl = reinterpret_cast<T *>(pIdl);
LPITEMIDLIST pidlTerminate;
pidlTerminate = ILNext( reinterpret_cast<LPCITEMIDLIST>( m_pConFoldPidl ) );
pidlTerminate->mkid.cb = 0;
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidConFoldPIDL());
#endif
Assert(m_pConFoldPidl->IsPidlOfThisType());
if (!m_pConFoldPidl->IsPidlOfThisType())
{
::SHFree(m_pConFoldPidl);
m_pConFoldPidl = NULL;
return E_FAIL;
}
}
break;
case PIDL_TYPE_FOLDER:
AssertSz(FALSE, "Can't upgrade PIDL to PIDL_V2 type");
case PIDL_TYPE_UNKNOWN:
default:
hr = E_INVALIDARG;
break;
}
}
break;
default:
AssertSz(FALSE, "Can't upgrade PIDL");
hr = E_INVALIDARG;
break;
}
}
if ( FAILED(hr) )
{
::SHFree(m_pConFoldPidl);
m_pConFoldPidl = NULL;
}
else
{
Assert(m_pConFoldPidl->IsPidlOfThisType());
}
return hr;
}
template <class T>
CPConFoldPidl<T>::CPConFoldPidl()
{
m_pConFoldPidl = NULL;
}
template <class T>
CPConFoldPidl<T>::CPConFoldPidl(const CPConFoldPidl& PConFoldPidl)
{
m_pConFoldPidl = NULL;
HRESULT hr = InitializeFromItemIDList(reinterpret_cast<LPCITEMIDLIST>(PConFoldPidl.m_pConFoldPidl));
if (FAILED(hr))
{
throw hr;
}
}
template <class T>
CPConFoldPidl<T>::~CPConFoldPidl()
{
FreePIDLIfRequired();
m_pConFoldPidl = NULL;
}
template <class T>
CPConFoldPidl<T>& CPConFoldPidl<T>::operator =(const CPConFoldPidl<T>& PConFoldPidl)
{
FreePIDLIfRequired();
if (PConFoldPidl.m_pConFoldPidl)
{
HRESULT hr = InitializeFromItemIDList(reinterpret_cast<LPCITEMIDLIST>(PConFoldPidl.m_pConFoldPidl));
if (FAILED(hr))
{
throw hr;
}
}
else
{
m_pConFoldPidl = NULL;
}
return *this;
}
template <class T>
inline BOOL CPConFoldPidl<T>::empty() const
{
return (m_pConFoldPidl == NULL);
}
template <class T>
HRESULT CPConFoldPidl<T>::ConvertToConFoldEntry(OUT CConFoldEntry& cfe) const
{
Assert(m_pConFoldPidl);
if (!m_pConFoldPidl)
{
return E_UNEXPECTED;
}
return m_pConFoldPidl->ConvertToConFoldEntry(cfe);
}
template <class T>
HRESULT CPConFoldPidl<T>::Swop(OUT CPConFoldPidl<T>& cfe)
{
UNALIGNED T* pTemp = m_pConFoldPidl;
m_pConFoldPidl = cfe.m_pConFoldPidl;
cfe.m_pConFoldPidl = pTemp;
return S_OK;
}
template CPConFoldPidl<ConFoldPidl_v1>;
template CPConFoldPidl<ConFoldPidl_v2 >;
template CPConFoldPidl<ConFoldPidlFolder>;
template CPConFoldPidl<ConFoldPidl98>;