// **************************************************************************** // // 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 HRESULT CPConFoldPidl::FreePIDLIfRequired() { if ( m_pConFoldPidl ) { FreeIDL(reinterpret_cast(m_pConFoldPidl)); m_pConFoldPidl = NULL; return S_OK; } else { return S_FALSE; } } template HRESULT CPConFoldPidl::Clear() { FreePIDLIfRequired(); return S_OK; } template T& CPConFoldPidl::operator *() { return (*m_pConFoldPidl); } template UNALIGNED T* CPConFoldPidl::operator->() { return m_pConFoldPidl; } template const UNALIGNED T* CPConFoldPidl::operator->() const { return m_pConFoldPidl; } template HRESULT CPConFoldPidl::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 HRESULT CPConFoldPidl::SHAlloc(IN const SIZE_T cb) { FreePIDLIfRequired(); LPVOID pPlacement = reinterpret_cast(::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 HRESULT CPConFoldPidl::ILClone(IN const CPConFoldPidl& PConFoldPidl) { C_ASSERT(PIDL_VERSION == T::CONNECTIONS_FOLDER_IDL_VERSION); FreePIDLIfRequired(); LPVOID pPlacement = reinterpret_cast(::ILClone(reinterpret_cast(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 LPITEMIDLIST CPConFoldPidl::TearOffItemIdList() const { TraceFileFunc(ttidConFoldEntry); Assert(m_pConFoldPidl); Assert( m_pConFoldPidl->IsPidlOfThisType() ); LPITEMIDLIST retList = ::ILClone(reinterpret_cast(m_pConFoldPidl)); #ifdef DBG_VALIDATE_PIDLS Assert(IsValidPIDL(retList)); #endif return retList; } template LPITEMIDLIST CPConFoldPidl::Detach() { TraceFileFunc(ttidConFoldEntry); Assert(m_pConFoldPidl); Assert( m_pConFoldPidl->IsPidlOfThisType() ); LPITEMIDLIST retList = reinterpret_cast(m_pConFoldPidl); #ifdef DBG_VALIDATE_PIDLS Assert(IsValidPIDL(retList)); #endif m_pConFoldPidl = NULL; return retList; } template LPCITEMIDLIST CPConFoldPidl::GetItemIdList() const { TraceFileFunc(ttidConFoldEntry); Assert(m_pConFoldPidl); Assert( m_pConFoldPidl->IsPidlOfThisType() ); LPCITEMIDLIST tmpItemIdList = reinterpret_cast(m_pConFoldPidl); #ifdef DBG_VALIDATE_PIDLS Assert(IsValidPIDL(tmpItemIdList)); #endif return tmpItemIdList; } #ifdef DBG_VALIDATE_PIDLS template BOOL CPConFoldPidl::IsValidConFoldPIDL() const { return IsValidPIDL(reinterpret_cast(m_pConFoldPidl)); } #endif template HRESULT CPConFoldPidl::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(::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(reinterpret_cast(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(::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(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(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( 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(reinterpret_cast(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(pIdl); LPITEMIDLIST pidlTerminate; pidlTerminate = ILNext( reinterpret_cast( 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 CPConFoldPidl::CPConFoldPidl() { m_pConFoldPidl = NULL; } template CPConFoldPidl::CPConFoldPidl(IN const CPConFoldPidl& PConFoldPidl) throw (HRESULT) { m_pConFoldPidl = NULL; HRESULT hr = InitializeFromItemIDList(reinterpret_cast(PConFoldPidl.m_pConFoldPidl)); if (FAILED(hr)) { throw hr; } } template CPConFoldPidl::~CPConFoldPidl() { FreePIDLIfRequired(); m_pConFoldPidl = NULL; } template CPConFoldPidl& CPConFoldPidl::operator =(IN const CPConFoldPidl& PConFoldPidl) throw (HRESULT) { FreePIDLIfRequired(); if (PConFoldPidl.m_pConFoldPidl) { HRESULT hr = InitializeFromItemIDList(reinterpret_cast(PConFoldPidl.m_pConFoldPidl)); if (FAILED(hr)) { throw hr; } } else { m_pConFoldPidl = NULL; } return *this; } template inline BOOL CPConFoldPidl::empty() const { return (m_pConFoldPidl == NULL); } template HRESULT CPConFoldPidl::ConvertToConFoldEntry(OUT CConFoldEntry& cfe) const { Assert(m_pConFoldPidl); if (!m_pConFoldPidl) { return E_UNEXPECTED; } return m_pConFoldPidl->ConvertToConFoldEntry(cfe); } template HRESULT CPConFoldPidl::Swop(OUT CPConFoldPidl& cfe) { UNALIGNED T* pTemp = m_pConFoldPidl; m_pConFoldPidl = cfe.m_pConFoldPidl; cfe.m_pConFoldPidl = pTemp; return S_OK; } template CPConFoldPidl; template CPConFoldPidl; template CPConFoldPidl; template CPConFoldPidl;