|
|
// ****************************************************************************
//
// 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(IN 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; // Placement new can't fail with OUTOFMEMORY.
Assert(pPlacement == m_pConFoldPidl);
return S_OK; }
template <class T> HRESULT CPConFoldPidl<T>::SHAlloc(IN 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; // Placement new can't fail with OUTOFMEMORY.
Assert(pPlacement == m_pConFoldPidl);
if (m_pConFoldPidl) { return S_OK; } else { return E_OUTOFMEMORY; } }
template <class T> HRESULT CPConFoldPidl<T>::ILClone(IN 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; // Placement new can't fail with OUTOFMEMORY.
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(IN 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; // Placement new can't fail with OUTOFMEMORY
Assert(pPlacement == m_pConFoldPidl);
if (!m_pConFoldPidl->IsPidlOfThisType()) { ::SHFree(pPlacement); m_pConFoldPidl = NULL;
return E_INVALIDARG; }
} 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)); 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; // Placement new can't fail with OUTOFMEMORY
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 = (WORD)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)); 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(IN const CPConFoldPidl& PConFoldPidl) throw (HRESULT) { 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 =(IN const CPConFoldPidl<T>& PConFoldPidl) throw (HRESULT) { 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>;
|