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

1806 lines
52 KiB
C++

// ****************************************************************************
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: C F P I D L . C P P
//
// Contents: Connections Folder structures and classes.
//
// Author: jeffspr 11 Nov 1997
//
// ****************************************************************************
#include "pch.h"
#pragma hdrstop
#include "ncperms.h"
#include "ncras.h"
#include "initguid.h"
#include "foldinc.h" // Standard shell\folder includes
#include "ncnetcon.h"
#include "ncmisc.h"
extern CRITICAL_SECTION g_csPidl;
// #define STRICTDEBUGGING
BOOL fIsConnectedStatus(NETCON_STATUS ncs)
{
switch (ncs)
{
case NCS_CONNECTED:
case NCS_AUTHENTICATING:
case NCS_AUTHENTICATION_FAILED:
case NCS_AUTHENTICATION_SUCCEEDED:
case NCS_CREDENTIALS_REQUIRED:
return TRUE;
default:
return FALSE;
}
}
// ****************************************************************************
//
// Member: CConFoldEntry::CConFoldEntry
//
// Purpose: Constructor for CConFoldEntry
//
// Arguments:
// (none)
//
// Returns:
//
// Author: jeffspr 11 Nov 1997
// ****************************************************************************
CConFoldEntry::CConFoldEntry()
{
m_bDirty = TRUE;
TraceFileFunc(ttidConFoldEntry);
// Need to clear out the pointers, otherwise clear() will AV
m_pszName = NULL;
m_pszDeviceName = NULL;
m_pbPersistData = NULL;
m_pszPhoneOrHostAddress = NULL;
clear();
}
CConFoldEntry::CConFoldEntry(const CConFoldEntry& ConFoldEntry)
{
TraceFileFunc(ttidConFoldEntry);
m_bDirty = TRUE;
if (!ConFoldEntry.empty())
{
HRESULT hr = HrDupFolderEntry(ConFoldEntry);
if (FAILED(hr))
{
clear();
}
}
else
{
// Need to clear out the pointers, otherwise clear() will AV
m_pszName = NULL;
m_pszDeviceName = NULL;
m_pbPersistData = NULL;
m_pszPhoneOrHostAddress = NULL;
clear();
}
}
CConFoldEntry& CConFoldEntry::operator =(const CConFoldEntry& ConFoldEntry)
{
TraceFileFunc(ttidConFoldEntry);
m_bDirty = TRUE;
if (!ConFoldEntry.empty())
{
HRESULT hr = HrDupFolderEntry(ConFoldEntry);
if (FAILED(hr))
{
clear();
}
}
else
{
clear();
}
return *this;
}
// ****************************************************************************
//
// Member: CConFoldEntry::~CConFoldEntry
//
// Purpose: Destructor for CConFoldEntry
//
// Arguments:
// (none)
//
// Returns:
//
// Author: jeffspr 11 Nov 1997
// ****************************************************************************
CConFoldEntry::~CConFoldEntry()
{
TraceFileFunc(ttidConFoldEntry);
clear();
}
// ****************************************************************************
//
// Member: CConFoldEntry::SetDeviceName
//
// Purpose: Set the name of the device used by this connection
//
// Arguments:
// pszDeviceName - New device name (NULL is valid)
//
// Returns:
//
// Author: scottbri 11 Nov 1999
// ****************************************************************************
HRESULT CConFoldEntry::SetDeviceName(LPCWSTR pszDeviceName)
{
HRESULT hr = S_OK;
PWSTR pszOld = m_pszDeviceName;
m_bDirty = TRUE;
if (pszDeviceName)
{
// Only change the text is the text is actually different
//
if ((NULL == GetDeviceName()) ||
wcscmp(pszDeviceName, GetDeviceName()))
{
hr = HrDupeShellString(pszDeviceName, &m_pszDeviceName);
}
else
{
// NOTE: In this one case, nothing change so there is
// nothing to free so short circut the clean-up below
//
pszOld = NULL;
hr = S_OK;
}
}
else
{
hr = HrDupeShellString(L"", &m_pszDeviceName);
}
// Free the old string
//
if (SUCCEEDED(hr) && pszOld)
{
SHFree(pszOld);
}
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::HrSetDeviceName");
return hr;
}
// ****************************************************************************
//
// Member: CConFoldEntry::SetPhoneOrHostAddress
//
// Purpose: Set the name of the device used by this connection
//
// Arguments:
// pszDeviceName - New device name (NULL is valid)
//
// Returns:
//
// Author: scottbri 11 Nov 1999
// ****************************************************************************
HRESULT CConFoldEntry::SetPhoneOrHostAddress(LPCWSTR pszPhoneOrHostAddress)
{
HRESULT hr = S_OK;
PWSTR pszOld = m_pszPhoneOrHostAddress;
m_bDirty = TRUE;
if (pszPhoneOrHostAddress)
{
// Only change the text is the text is actually different
//
if ((NULL == GetPhoneOrHostAddress()) ||
wcscmp(pszPhoneOrHostAddress, GetPhoneOrHostAddress()))
{
hr = HrDupeShellString(pszPhoneOrHostAddress, &m_pszPhoneOrHostAddress);
}
else
{
// NOTE: In this one case, nothing change so there is
// nothing to free so short circut the clean-up below
//
pszOld = NULL;
hr = S_OK;
}
}
else
{
hr = HrDupeShellString(L"", &m_pszPhoneOrHostAddress);
}
// Free the old string
//
if (SUCCEEDED(hr) && pszOld)
{
SHFree(pszOld);
}
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::HrSetDeviceName");
return hr;
}
// ****************************************************************************
//
// Member: CConFoldEntry::SetName
//
// Purpose: Set the name of the connection
//
// Arguments:
// pszName - New connection name (NULL is valid)
//
// Returns:
//
// Author: scottbri 11 Nov 1999
// ****************************************************************************
HRESULT CConFoldEntry::SetName(LPCWSTR pszName)
{
HRESULT hr = S_OK;
PWSTR pszOld = m_pszName;
m_bDirty = TRUE;
if (pszName)
{
// Only change the text is the text is actually different
//
if ((NULL == GetName()) ||
wcscmp(pszName, GetName()))
{
hr = HrDupeShellString(pszName, &m_pszName);
}
else
{
pszOld = NULL;
hr = S_OK;
}
}
else
{
PWSTR pszLoad = NULL;
if (GetWizard() == WIZARD_MNC)
{
pszLoad = (PWSTR) SzLoadIds(IDS_CONFOLD_WIZARD_DISPLAY_NAME);
}
else if (GetWizard() == WIZARD_HNW)
{
pszLoad = (PWSTR) SzLoadIds(IDS_CONFOLD_HOMENET_WIZARD_DISPLAY_NAME);
}
//$$REVIEW: Change this to use c_szEmpty
//
hr = HrDupeShellString(pszLoad ? pszLoad : L"", &m_pszName);
Assert(GetName());
}
// Free the old string
//
if (SUCCEEDED(hr) && pszOld)
{
SHFree(pszOld);
}
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::HrSetConnectionName");
return hr;
}
// ****************************************************************************
//
// Member: CConFoldEntry::HrInitData
//
// Purpose: Initialize the CConFoldEntry data. Not all fields are
// required at this time, though they will most likely be
// required at some point during the life of the object.
//
// Arguments:
// wizWizard [in] Wizard type?
// ncm [in] Connection type
// ncs [in] Connection status
// pclsid [in] Pointer to CLSID of the connection
// pguidId [in] Pointer to unique GUID for the connection
// dwCharacteristics [in] Connection characteristics
// pbPersistData [in] Persistant data for this connection
// ulPersistSize [in] Size of the persist data blob
// pszName [in] Name of the connection
// pszDeviceName [in] Name of the connection's device
//
// Returns: S_OK or valid OLE return code.
//
// Author: jeffspr 11 Nov 1997
// ****************************************************************************
HRESULT CConFoldEntry::HrInitData(const WIZARD wizWizard,
const NETCON_MEDIATYPE ncm,
const NETCON_SUBMEDIATYPE ncsm,
const NETCON_STATUS ncs,
const CLSID * pclsid,
LPCGUID pguidId,
const DWORD dwCharacteristics,
const BYTE * pbPersistData,
const ULONG ulPersistSize,
LPCWSTR pszName,
LPCWSTR pszDeviceName,
LPCWSTR pszPhoneOrHostAddress)
{
TraceFileFunc(ttidConFoldEntry);
HRESULT hr = S_OK;
// Initialize the internal data
//
m_bDirty = TRUE;
m_wizWizard = wizWizard;
m_ncm = ncm;
m_ncs = ncs;
m_dwCharacteristics = dwCharacteristics;;
BOOL fOldEapolStatus = ((ncsm == NCSM_CM) && (ncm == NCM_LAN)) // NCSM_CM used to be NCM_AUTHENTICATING
|| (ncsm > NCSM_CM); // E.g. NCM_AUTHENTICATION_SUCCEEDED etc.
if (!fOldEapolStatus)
{
m_ncsm = ncsm;
}
else
{
// ISSUE: This is for the migration of EAPOL state out off our PIDL
// This should be taken out after the no-prior-upgrades RC1 build is released.
if (NCM_LAN == ncm)
{
m_ncsm = NCSM_LAN; // If all else file, we'll pretend to be a normal LAN card.
CIntelliName inName(NULL, NULL);
NETCON_MEDIATYPE ncmTmp;
NETCON_SUBMEDIATYPE ncsmTmp;
// Try get the status from the OID or Bindings
HRESULT hrT = inName.HrGetPseudoMediaTypes(*pguidId, &ncmTmp, &ncsmTmp);
if (SUCCEEDED(hrT))
{
m_ncsm = ncsmTmp;
}
else
{
// Ok. That didn't work. Try the connections list next.
if (g_ccl.IsInitialized())
{
ConnListEntry cle;
hrT = g_ccl.HrFindConnectionByGuid(pguidId, cle);
if (S_OK == hrT)
{
m_ncsm = cle.ccfe.GetNetConSubMediaType();
}
}
}
}
else
{
m_ncsm = NCSM_NONE;
}
}
if (pclsid)
{
m_clsid = *pclsid;
}
else
{
AssertSz(wizWizard != WIZARD_NOT_WIZARD, "If you're not a wizard, you must give me a CLSID for the class!");
}
if (pguidId)
{
m_guidId = *pguidId;
}
AssertSz(pguidId, "You must give me a GUID for the object!");
// Copy the persist buffer
//
if (pbPersistData)
{
LPBYTE bufTemp = (BYTE *) SHAlloc(ulPersistSize);
if (!bufTemp)
{
SetPersistData(NULL, 0);
hr = E_OUTOFMEMORY;
goto Exit;
}
CopyMemory(bufTemp, pbPersistData, ulPersistSize);
SetPersistData(bufTemp, ulPersistSize);
}
else
{
AssertSz(wizWizard != WIZARD_NOT_WIZARD, "If you're not a wizard, you must give me a pbPersistData for the object!");
SetPersistData(NULL, 0);
}
// Copy the device name
//
hr = SetDeviceName(pszDeviceName);
if (SUCCEEDED(hr))
{
// Copy the name
//
hr = SetName(pszName);
if (SUCCEEDED(hr))
{
hr = SetPhoneOrHostAddress(pszPhoneOrHostAddress);
}
}
Exit:
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::HrInitData");
return hr;
}
// ****************************************************************************
//
// Member: CConFoldEntry::UpdateData
//
// Purpose: Modify the values in a CConFoldEntry
//
// Arguments:
// DWORD dwChangeFlags
// NETCON_MEDIATYPE MediaType
// NETCON_STATUS Status
// DWORD dwCharacteristics
// PWSTR pszName
// PWSTR pszDeviceName
//
// Returns: HRESULT
//
// Author: scottbri 10 Nov 1998
// ****************************************************************************
HRESULT CConFoldEntry::UpdateData( const DWORD dwChangeFlags,
const NETCON_MEDIATYPE MediaType,
const NETCON_SUBMEDIATYPE SubMediaType,
const NETCON_STATUS Status,
const DWORD dwCharacteristics,
PCWSTR pszName,
PCWSTR pszDeviceName,
PCWSTR pszPhoneOrHostAddress)
{
TraceFileFunc(ttidConFoldEntry);
HRESULT hr = S_OK;
HRESULT hrTmp;
m_bDirty = TRUE;
if (dwChangeFlags & CCFE_CHANGE_MEDIATYPE)
{
SetNetConMediaType(MediaType);
}
if (dwChangeFlags & CCFE_CHANGE_SUBMEDIATYPE)
{
SetNetConSubMediaType(SubMediaType);
}
if (dwChangeFlags & CCFE_CHANGE_STATUS)
{
SetNetConStatus(Status);
}
if (dwChangeFlags & CCFE_CHANGE_CHARACTERISTICS)
{
SetCharacteristics(dwCharacteristics);
}
if (dwChangeFlags & CCFE_CHANGE_NAME)
{
hrTmp = SetName(pszName);
if (FAILED(hrTmp))
{
hr = hrTmp;
}
}
if (dwChangeFlags & CCFE_CHANGE_DEVICENAME)
{
hrTmp = SetDeviceName(pszDeviceName);
if (FAILED(hrTmp))
{
hr = hrTmp;
}
}
if (dwChangeFlags & CCFE_CHANGE_PHONEORHOSTADDRESS)
{
hrTmp = SetPhoneOrHostAddress(pszPhoneOrHostAddress);
if (FAILED(hrTmp))
{
hr = hrTmp;
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::UpdateData");
return hr;
}
// ****************************************************************************
//
// Member: CConFoldEntry::HrDupFolderEntry
//
// Purpose: Duplicate a connection folder entry.
//
// Arguments:
// pccfe The source folder entry to dup from
//
// Returns:
//
// Author: tongl 9/3/98
// ****************************************************************************
HRESULT CConFoldEntry::HrDupFolderEntry(const CConFoldEntry& ccfe)
{
TraceFileFunc(ttidConFoldEntry);
m_bDirty = TRUE;
Assert(!ccfe.empty());
clear();
return HrInitData( ccfe.GetWizard(),
ccfe.GetNetConMediaType(),
ccfe.GetNetConSubMediaType(),
ccfe.GetNetConStatus(),
&(ccfe.GetCLSID()),
&(ccfe.GetGuidID()),
ccfe.GetCharacteristics(),
ccfe.GetPersistData(),
ccfe.GetPersistSize(),
ccfe.GetName(),
ccfe.GetDeviceName(),
ccfe.GetPhoneOrHostAddress());
}
// ****************************************************************************
//
// Member: CConFoldEntry::FShouldHaveTrayIconDisplayed
//
// Purpose: Return TRUE if this entry should have a tray icon displayed.
//
// Arguments:
// (none)
//
// Returns: TRUE or FALSE.
//
// Author: shaunco 2 Nov 1998
// ****************************************************************************
BOOL CConFoldEntry::FShouldHaveTrayIconDisplayed() const
{
// If we're either MEDIA_DISCONNECTED (lan) or
// we're connected and have the correct bits turned on
// then we should display the icon
//
return ( !IsConnected() ||
(fIsConnectedStatus(GetNetConStatus()) &&
(GetCharacteristics() & NCCF_SHOW_ICON) &&
!GetWizard() && FHasPermission(NCPERM_Statistics)));
}
// ****************************************************************************
// Function:
//
// Purpose: Translate from a pidl to a CConFoldEntry class object
//
// Arguments:
// pidl [in] PIDL from which to create
// ppccfe [out] Resultant CConFoldEntry object pointer
//
// Returns:
//
// Author: jeffspr 11 Nov 1997
// ****************************************************************************
// ****************************************************************************
//
// Function: HrCreateConFoldPidlInternal
//
// Purpose: Utility function for creating new Connections Folder PIDLs.
// This function is primarily called from HrCreateConFoldPidl,
// but can also be called directly by those that have already
// loaded the properties and persist data.
//
// Arguments:
// pProps [in] From GetProperties
// pbBuf [in] The persist buffer
// ulBufSize [in] Size of the persist buffer
// ppidl [out] Return pointer for the resultant pidl
//
// Returns:
//
// Author: jeffspr 27 Aug 1998
// ****************************************************************************
HRESULT HrCreateConFoldPidlInternal(IN const NETCON_PROPERTIES * pProps,
IN const BYTE * pbBuf,
IN ULONG ulBufSize,
IN LPCWSTR szPhoneOrHostAddress,
OUT PCONFOLDPIDL & pidl)
{
HRESULT hr = S_OK;
CONFOLDENTRY ccfe;
// Trace the useful info
//
TraceTag(ttidShellFolder, "Enum: %S, Ncm: %d, Ncs: %d, Char: 0x%08x "
"(Show: %d, Del: %d, All: %d), Dev: %S",
(pProps->pszwName) ? pProps->pszwName : L"null",
pProps->MediaType, pProps->Status, pProps->dwCharacter,
((pProps->dwCharacter & NCCF_SHOW_ICON) > 0),
((pProps->dwCharacter & NCCF_ALLOW_REMOVAL) > 0),
((pProps->dwCharacter & NCCF_ALL_USERS) > 0),
(pProps->pszwDeviceName) ? pProps->pszwDeviceName : L"null");
// Init the CConFoldEntry from the data that we've retrieved.
//
hr = ccfe.HrInitData(WIZARD_NOT_WIZARD,
pProps->MediaType,
NCSM_NONE,
pProps->Status,
&pProps->clsidThisObject,
&pProps->guidId,
pProps->dwCharacter,
pbBuf,
ulBufSize,
pProps->pszwName,
pProps->pszwDeviceName,
szPhoneOrHostAddress);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "ccfe.HrInitData failed for "
"non-wizard");
goto Exit;
}
// Translate into the actual pidl
//
hr = ccfe.ConvertToPidl(pidl);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "ConvertToPidl failed for non-wizard");
}
Exit:
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateConFoldPidlInternal");
return hr;
}
// ****************************************************************************
//
// Function: HrCreateConFoldPidl
//
// Purpose: Utility function for creating new Connections Folder PIDLs.
//
// Arguments:
// wizWizard [in] Is this PIDL for a wizard?
// pNetCon [in] INetConnection interface from the enumerator
// pPersist [in] IPersist interface QI'd from the pNetCon
// ppidl [out] Return pointer for the new pidl
//
// Returns: S_OK or valid OLE return code.
//
// Author: jeffspr 6 Oct 1997
//
// Notes: If the connection that you're adding is a real connection object
// (not the wizard) and you already have loaded the persist data and
// properties, you should call HrCreateConFoldPidlInternal directly
// ****************************************************************************
HRESULT HrCreateConFoldPidl(IN const WIZARD wizWizard,
IN INetConnection * pNetCon,
OUT PCONFOLDPIDL & ppidl)
{
HRESULT hr = S_OK;
LPBYTE pbBuf = NULL;
ULONG ulBufSize = 0;
NETCON_PROPERTIES * pProps = NULL;
CConFoldEntry ccfe;
if (wizWizard == WIZARD_NOT_WIZARD)
{
Assert(pNetCon);
hr = pNetCon->GetProperties (&pProps);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "pNetCon->GetProperties failed in "
"CConnectionFolderEnum::HrCreateConFoldPidl");
goto Exit;
}
Assert (pProps);
// Get the persist data from the connection
//
hr = HrGetConnectionPersistData(pNetCon, &pbBuf, &ulBufSize, NULL);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrGetConnectionPersistData failed in "
"CConnectionFolderEnum::HrCreateConFoldPidl");
goto Exit;
}
WCHAR szPhoneOrHostAddress[MAX_PATH];
wcscpy(szPhoneOrHostAddress, L" ");
if ( (NCM_TUNNEL == pProps->MediaType) || (NCM_PHONE == pProps->MediaType) )
{
HRESULT hrTmp;
RASCON_INFO RasConInfo;
if (SUCCEEDED(hr))
{
hrTmp = HrRciGetRasConnectionInfo(pNetCon, &RasConInfo);
if (SUCCEEDED(hrTmp))
{
GetPrivateProfileString(RasConInfo.pszwEntryName, L"PhoneNumber",
L" ", szPhoneOrHostAddress, MAX_PATH,
RasConInfo.pszwPbkFile);
RciFree(&RasConInfo);
}
}
}
// Call the pre-read-data version of this function to actually pack the
// ccfe and insert.
//
hr = HrCreateConFoldPidlInternal(pProps, pbBuf, ulBufSize, szPhoneOrHostAddress, ppidl);
if (FAILED(hr))
{
goto Exit;
}
}
else
{
GUID guidWiz;
if (wizWizard == WIZARD_MNC)
{
guidWiz = GUID_MNC_WIZARD;
}
else
{
guidWiz = GUID_HNW_WIZARD;
Assert(wizWizard == WIZARD_HNW);
}
// Pack the CConFoldEntry data from the retrieved info
//
hr = ccfe.HrInitData(wizWizard, NCM_NONE, NCSM_NONE, NCS_DISCONNECTED,
NULL, &guidWiz, 0, NULL, 0, NULL, NULL, NULL);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "ccfe.HrInitData failed for "
"Wizard");
goto Exit;
}
// Translate into an actual pidl
//
hr = ccfe.ConvertToPidl(ppidl);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "ConvertToPidl failed for wizard");
}
}
Exit:
MemFree(pbBuf);
FreeNetconProperties(pProps);
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateConFoldPidl");
return hr;
}
// ****************************************************************************
//
// Function: HrCreateConFoldPidl
//
// Purpose: Utility function for creating new Connections Folder PIDLs.
//
// Arguments:
// wizWizard [in] Is this PIDL for a wizard?
// PropsEx [in] PropsEx structure
// ppidl [out] Return pointer for the new pidl
//
// Returns: S_OK or valid OLE return code.
//
// Author: deonb 26 Mar 2001
//
// Notes:
// ****************************************************************************
HRESULT HrCreateConFoldPidl(IN const NETCON_PROPERTIES_EX& PropsEx,
OUT PCONFOLDPIDL & ppidl)
{
HRESULT hr = S_OK;
NETCON_PROPERTIES * pProps = NULL;
CConFoldEntry ccfe;
// Trace the useful info
//
TraceTag(ttidShellFolder, "Enum: %S, Ncm: %d, Ncs: %d, Char: 0x%08x "
"(Show: %d, Del: %d, All: %d), Dev: %S",
(PropsEx.bstrName) ? PropsEx.bstrName : L"null",
PropsEx.ncMediaType,
PropsEx.ncStatus,
PropsEx.dwCharacter,
((PropsEx.dwCharacter & NCCF_SHOW_ICON) > 0),
((PropsEx.dwCharacter & NCCF_ALLOW_REMOVAL) > 0),
((PropsEx.dwCharacter & NCCF_ALL_USERS) > 0),
(PropsEx.bstrDeviceName) ? PropsEx.bstrDeviceName : L"null");
// Init the CConFoldEntry from the data that we've retrieved.
//
hr = ccfe.HrInitData(WIZARD_NOT_WIZARD,
PropsEx.ncMediaType,
PropsEx.ncSubMediaType,
PropsEx.ncStatus,
&PropsEx.clsidThisObject,
&PropsEx.guidId,
PropsEx.dwCharacter,
reinterpret_cast<const BYTE*>(PropsEx.bstrPersistData),
SysStringByteLen(PropsEx.bstrPersistData),
PropsEx.bstrName,
PropsEx.bstrDeviceName,
PropsEx.bstrPhoneOrHostAddress);
if (SUCCEEDED(hr))
{
// Translate into the actual pidl
//
hr = ccfe.ConvertToPidl(ppidl);
}
TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrCreateConFoldPidl");
return hr;
}
// ****************************************************************************
//
// Function: ConvertToPidlInCache
//
// Purpose: Determine whether a particular PIDL is in a format we support.
// If so but it is not in the CONFOLDPIDL format, then find a match
// in our cache and allocate a new pisl
//
// Arguments:
// pidl [] PIDL to test
// ppcfpRet PIDL converted to PCONFOLDPIDL, if required and it
// matches an existing connection in the cache
//
// Returns: NONE
//
// Author: tongl, 4 April, 1999
// ****************************************************************************
// ****************************************************************************
//
// Function: HrNetConFromPidl
//
// Purpose: Translate from a packed PIDL to a INetConnection pointer.
// Do this by converting to a ConFoldEntry and getting the
// pointer from there
//
// Arguments:
// pidl [in] Pidl that contains the connection persist data
// ppNetCon [out] INetConnection * return
//
// Returns:
//
// Author: jeffspr 11 Nov 1997
// ****************************************************************************
HRESULT HrNetConFromPidl( const PCONFOLDPIDL & pidl,
INetConnection ** ppNetCon)
{
HRESULT hr = S_OK;
CONFOLDENTRY pccfe;
Assert(ppNetCon);
hr = pidl.ConvertToConFoldEntry(pccfe);
if (SUCCEEDED(hr))
{
Assert(!pccfe.empty());
hr = pccfe.HrGetNetCon(IID_INetConnection,
reinterpret_cast<VOID**>(ppNetCon));
}
// Free the CConFoldEntry class, if successfully created
//
TraceHr(ttidError, FAL, hr, FALSE, "HrNetConFromPidl");
return hr;
}
// ****************************************************************************
//
// Member: CConFoldEntry::HrGetNetCon
//
// Purpose: Get the INetConnection pointer from the persisted data
//
// Arguments:
// ppNetCon [] Return pointer for the INetConnection
//
// Returns:
//
// Author: jeffspr 11 Nov 1997
// ****************************************************************************
HRESULT CConFoldEntry::HrGetNetCon( IN REFIID riid,
IN VOID** ppv) const
{
HRESULT hr = HrGetConnectionFromPersistData( GetCLSID(),
GetPersistData(),
GetPersistSize(),
riid,
ppv);
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::HrGetNetCon");
return hr;
}
// ****************************************************************************
HRESULT PConfoldPidlVecFromItemIdListArray(LPCITEMIDLIST * apidl, DWORD dwPidlCount, PCONFOLDPIDLVEC& vecConfoldPidl)
{
HRESULT hr = S_OK;
if (NULL == apidl)
{
return S_FALSE;
}
LPCITEMIDLIST *tmpIdList = apidl;
for (DWORD i = 0; i < dwPidlCount; i++)
{
PCONFOLDPIDL newPidl;
hr = newPidl.InitializeFromItemIDList(*tmpIdList);
if (SUCCEEDED(hr))
{
vecConfoldPidl.push_back(newPidl);
}
else
{
break;
}
tmpIdList++;
}
return hr;
}
#ifdef DBG_VALIDATE_PIDLS
inline BOOL IsValidPIDL(LPCITEMIDLIST pidl)
{
CExceptionSafeLock esLock(&g_csPidl);
if (NULL == pidl)
{
return TRUE;
}
if (IsBadReadPtr(pidl, sizeof(USHORT)))
{
AssertSz(FALSE, "invalid read pointer");
return FALSE;
}
else
{
if (IsBadReadPtr(pidl, pidl->mkid.cb) )
{
AssertSz(FALSE, "invalid read buffer");
return FALSE;
}
else
{
if (0 == _ILNext(pidl)->mkid.cb || IsValidPIDL(_ILNext(pidl)) )
{
return TRUE;
}
else
{
// Don't need to assert since called IsValidPidl would have asserted already
return FALSE;
}
}
}
return FALSE;
}
#endif
BOOL ConFoldPidl_v1::IsPidlOfThisType() const
{
if ( GetPidlType(reinterpret_cast<LPCITEMIDLIST>(this)) == PIDL_TYPE_V1 )
{
#if defined( DBG ) && defined ( STRICTDEBUGGING )
DWORD dwDataOffset = bData - reinterpret_cast<const BYTE *>(this); // Get bData offset;
DWORD dwPidlSize;
dwPidlSize = dwDataOffset;
dwPidlSize += ulPersistBufSize;
dwPidlSize += ulStrNameSize;
dwPidlSize += ulStrDeviceNameSize;
dwPidlSize += sizeof(USHORT); // Terminating
AssertSz(dwPidlSize <= iCB, "Self-inconsistend PIDL"); // Sometimes V1 PIDLs are shorter - hence not == a check.
AssertSz(ulPersistBufPos + ulPersistBufSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrDeviceNamePos + ulStrDeviceNameSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrNamePos + ulStrNameSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrNamePos == 0, "Name doesn't start at 0");
AssertSz(ulStrDeviceNamePos == ulStrNameSize, "Device name misaligned");
AssertSz(ulPersistBufPos == ulStrDeviceNamePos + ulStrDeviceNameSize, "Persisted buffer misaligned");
AssertSz(dwDataOffset + ulPersistBufPos + ulPersistBufSize <= iCB, "Persisted buffer larger than PIDL");
#endif
return TRUE;
}
else
{
return FALSE;
}
}
BOOL ConFoldPidl_v2::IsPidlOfThisType() const
{
if ( GetPidlType(reinterpret_cast<LPCITEMIDLIST>(this)) == PIDL_TYPE_V2 )
{
#if defined( DBG ) && defined ( STRICTDEBUGGING )
DWORD dwDataOffset = bData - reinterpret_cast<const BYTE *>(this); // Get bData offset;
DWORD dwPidlSize;
dwPidlSize = dwDataOffset;
dwPidlSize += ulPersistBufSize;
dwPidlSize += ulStrNameSize;
dwPidlSize += ulStrDeviceNameSize;
dwPidlSize += ulStrPhoneOrHostAddressSize;
dwPidlSize += sizeof(USHORT); // Terminating 0
AssertSz(dwPidlSize <= iCB, "Self-inconsistend PIDL"); // Sometimes V1 PIDLs are shorter - hence not == a check.
AssertSz(ulPersistBufPos + ulPersistBufSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrDeviceNamePos + ulStrDeviceNameSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrNamePos + ulStrNameSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrPhoneOrHostAddressPos + ulStrPhoneOrHostAddressSize < iCB, "Self-inconsistend PIDL");
AssertSz(ulStrNamePos == 0, "Name doesn't start at 0");
AssertSz(ulStrDeviceNamePos == ulStrNameSize, "Device name misaligned");
AssertSz(ulPersistBufPos == ulStrDeviceNamePos + ulStrDeviceNameSize, "Persisted buffer misaligned");
AssertSz(ulStrPhoneOrHostAddressPos == ulPersistBufPos + ulPersistBufSize, "Phone/Host address misaligned");
AssertSz(dwDataOffset + ulPersistBufPos + ulPersistBufSize <= iCB, "Buffer larger than PIDL");
#endif
return TRUE;
}
else
{
return FALSE;
}
}
BOOL ConFoldPidlFolder::IsPidlOfThisType() const
{
// We can't tell if it's a PIDL_TYPE_FOLDER - this is shell internal
if ( GetPidlType(reinterpret_cast<LPCITEMIDLIST>(this)) == PIDL_TYPE_UNKNOWN )
{
#ifdef DBG
if ( (dwLength != 0x14) || (dwId != 0x1f) )
{
return FALSE;
}
#endif
return TRUE;
}
else
{
return FALSE;
}
}
BOOL ConFoldPidl98::IsPidlOfThisType(BOOL * pfIsWizard) const
{
if ( GetPidlType(reinterpret_cast<LPCITEMIDLIST>(this)) == PIDL_TYPE_98 )
{
return TRUE;
}
else
{
return FALSE;
}
}
const DWORD CConFoldEntry::GetCharacteristics() const
{
return m_dwCharacteristics;
}
HRESULT CConFoldEntry::SetCharacteristics(const DWORD dwCharacteristics)
{
m_bDirty = TRUE;
m_dwCharacteristics = dwCharacteristics;
return S_OK;
}
const GUID CConFoldEntry::GetGuidID() const
{
return m_guidId;
}
HRESULT CConFoldEntry::SetGuidID(const GUID guidId)
{
m_bDirty = TRUE;
m_guidId = guidId;
return S_OK;
}
const CLSID CConFoldEntry::GetCLSID() const
{
return m_clsid;
}
HRESULT CConFoldEntry::SetCLSID(const CLSID clsid)
{
m_bDirty = TRUE;
m_clsid = clsid;
return S_OK;
}
PCWSTR CConFoldEntry::GetName() const
{
return m_pszName;
}
HRESULT CConFoldEntry::SetPName(IN TAKEOWNERSHIP SHALLOCATED PWSTR pszName)
{
m_bDirty = TRUE;
m_pszName = pszName;
return S_OK;
}
PCWSTR CConFoldEntry::GetDeviceName() const
{
return m_pszDeviceName;
}
HRESULT CConFoldEntry::SetPDeviceName(IN TAKEOWNERSHIP SHALLOCATED PWSTR pszDeviceName)
{
m_bDirty = TRUE;
m_pszDeviceName = pszDeviceName;
return S_OK;
}
PCWSTR CConFoldEntry::GetPhoneOrHostAddress() const
{
return m_pszPhoneOrHostAddress;
}
HRESULT CConFoldEntry::SetPPhoneOrHostAddress(IN TAKEOWNERSHIP SHALLOCATED PWSTR pszPhoneOrHostAddress)
{
m_bDirty = TRUE;
m_pszPhoneOrHostAddress = pszPhoneOrHostAddress;
return S_OK;
}
const NETCON_STATUS CConFoldEntry::GetNetConStatus() const
{
return m_ncs;
}
const BOOL CConFoldEntry::IsConnected() const
{
return (m_ncs != NCS_MEDIA_DISCONNECTED) && (m_ncs != NCS_INVALID_ADDRESS);
}
HRESULT CConFoldEntry::SetNetConStatus(const NETCON_STATUS ncs)
{
m_bDirty = TRUE;
m_ncs = ncs;
return S_OK;
}
const NETCON_MEDIATYPE CConFoldEntry::GetNetConMediaType() const
{
return m_ncm;
}
HRESULT CConFoldEntry::SetNetConMediaType(const NETCON_MEDIATYPE ncm)
{
m_bDirty = TRUE;
m_ncm = ncm;
return S_OK;
}
const NETCON_SUBMEDIATYPE CConFoldEntry::GetNetConSubMediaType() const
{
return m_ncsm;
}
HRESULT CConFoldEntry::SetNetConSubMediaType(const NETCON_SUBMEDIATYPE ncsm)
{
m_bDirty = TRUE;
m_ncsm = ncsm;
return S_OK;
}
const WIZARD CConFoldEntry::GetWizard() const
{
return m_wizWizard;
}
HRESULT CConFoldEntry::SetWizard(const WIZARD wizWizard)
{
m_bDirty = TRUE;
m_wizWizard = wizWizard;
return S_OK;
}
const BYTE * CConFoldEntry::GetPersistData() const
{
return m_pbPersistData;
}
const ULONG CConFoldEntry::GetPersistSize() const
{
return m_ulPersistSize;
}
HRESULT CConFoldEntry::SetPersistData(BYTE * pbPersistData, const ULONG ulPersistSize)
{
m_bDirty = TRUE;
m_pbPersistData = pbPersistData;
m_ulPersistSize = ulPersistSize;
return S_OK;
}
BOOL CConFoldEntry::empty() const
{
if (GetWizard())
{
return FALSE;
}
else
{
if (IsEqualGUID(GetCLSID(), GUID_NULL) )
{
return TRUE;
}
else
{
return FALSE;
}
}
}
void CConFoldEntry::clear()
{
TraceFileFunc(ttidConFoldEntry);
m_bDirty = TRUE;
if (GetName())
{
SHFree(m_pszName);
m_pszName = NULL;
}
if (GetDeviceName())
{
SHFree(m_pszDeviceName);
m_pszDeviceName = NULL;
}
if (GetPhoneOrHostAddress())
{
SHFree(m_pszPhoneOrHostAddress);
m_pszPhoneOrHostAddress = NULL;
}
if (GetPersistData())
{
SHFree(m_pbPersistData);
m_pbPersistData = NULL;
m_ulPersistSize = 0;
}
m_wizWizard = WIZARD_NOT_WIZARD;
m_ncm = NCM_NONE;
m_ncsm= NCSM_NONE;
m_ncs = NCS_DISCONNECTED;
m_dwCharacteristics = 0;
m_clsid = GUID_NULL;
m_guidId = GUID_NULL;
}
LPITEMIDLIST CConFoldEntry::TearOffItemIdList() const
{
PCONFOLDPIDL pidl;
m_bDirty = TRUE;
ConvertToPidl(pidl);
return pidl.TearOffItemIdList();
}
HRESULT CConFoldEntry::InitializeFromItemIdList(LPCITEMIDLIST lpItemIdList)
{
PCONFOLDPIDL pidl;
HRESULT hr = S_OK;
m_bDirty = TRUE;
hr = pidl.InitializeFromItemIDList(lpItemIdList);
if (FAILED(hr))
{
return hr;
}
hr = pidl.ConvertToConFoldEntry(*this);
return hr;
}
HRESULT CConFoldEntry::ConvertToPidl( OUT CPConFoldPidl<ConFoldPidl_v1>& pidl) const
{
TraceFileFunc(ttidConFoldEntry);
HRESULT hr = S_OK;
DWORD dwNameSize = 0;
DWORD dwDeviceNameSize = 0;
DWORD dwPidlSize = sizeof(ConFoldPidl_v1); // Initialize the PIDL byte count with the base size
Assert(!empty());
Assert(GetName());
Assert(GetDeviceName());
NETCFG_TRY
if (m_bDirty)
{
// Get the size of the name, and tack on a trailing NULL (since we now
// have something else in the buffer behind it.
//
dwNameSize = lstrlenW(GetName()) + 1;
dwDeviceNameSize = lstrlenW(GetDeviceName()) + 1;
// Add the size of the string to the PIDL struct size. We don't need to include
// an extra byte for the string's terminating NULL because we've already
// included a WCHAR[1] in the struct.
//
dwPidlSize += ((dwNameSize) * sizeof(WCHAR));
dwPidlSize += ((dwDeviceNameSize) * sizeof(WCHAR));
// Tack of the length of the persist buffer
//
dwPidlSize += GetPersistSize();
// Allocate the PIDL.
//
hr = pidl.ILCreate(dwPidlSize + sizeof(USHORT)); // Terminating 0 for the PIDL
if (SUCCEEDED(hr))
{
PWSTR pszName = NULL;
PWSTR pszDeviceName = NULL;
PWSTR pszPhoneOrHostAddress = NULL;
// Fill in the pidl info.
//
pidl->wizWizard = GetWizard();
pidl->iCB = dwPidlSize;
// pidl->dwVersion = CONNECTIONS_FOLDER_IDL_VERSION_V1;
pidl->ncm = GetNetConMediaType();
pidl->ncs = GetNetConStatus();
pidl->uLeadId = CONFOLDPIDL_LEADID;
pidl->uTrailId = CONFOLDPIDL_TRAILID;
pidl->clsid = GetCLSID();
pidl->guidId = GetGuidID();
pidl->dwCharacteristics = GetCharacteristics();
// Fill in the name
//
pidl->ulStrNamePos = 0; // offset into the PIDL's pbBuf
pidl->ulStrNameSize = dwNameSize * sizeof(WCHAR); // in bytes
pszName = pidl->PszGetNamePointer();
lstrcpyW(pszName, GetName());
pszName[dwNameSize] = 0;
// Fill in the device name, and set the offset info
//
pidl->ulStrDeviceNamePos = pidl->ulStrNamePos + pidl->ulStrNameSize;
pidl->ulStrDeviceNameSize = dwDeviceNameSize * sizeof(WCHAR); // in bytes
pszDeviceName = pidl->PszGetDeviceNamePointer();
lstrcpyW(pszDeviceName, GetDeviceName());
pszDeviceName[dwDeviceNameSize] = 0;
// Set the offset into the PIDL's pbBuf
//
pidl->ulPersistBufPos = pidl->ulStrDeviceNamePos + pidl->ulStrDeviceNameSize;
// Fill in the persist buffer, if present (it won't be on a wizard)
//
if (GetPersistData())
{
pidl->ulPersistBufSize = GetPersistSize();
CopyMemory(pidl->bData + pidl->ulPersistBufPos, GetPersistData(), GetPersistSize());
}
else
{
// Since we're the wizard, there shouldn't be a buffer, so the size
// should always be passed in as 0.
//
Assert(GetPersistSize() == 0);
pidl->ulPersistBufSize = 0;
}
// Don't forget to terminate the list!
//
LPITEMIDLIST pidlTerminate;
pidlTerminate = ILNext( pidl.GetItemIdList() );
pidlTerminate->mkid.cb = 0;
}
else
{
AssertSz(FALSE, "CConFoldEntry::ConvertToPidl is hosed");
hr = E_OUTOFMEMORY;
}
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidPIDL( pidl.GetItemIdList() ));
#endif
Assert( pidl->IsPidlOfThisType() ) ;
if (SUCCEEDED(hr))
{
m_bDirty = FALSE;
m_CachedV1Pidl = pidl;
}
}
else
{
TraceTag(ttidShellFolder, "Using internally cached PIDL");
pidl = m_CachedV1Pidl;
}
NETCFG_CATCH(hr)
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::ConvertToPidl");
return hr;
}
HRESULT CConFoldEntry::ConvertToPidl( OUT CPConFoldPidl<ConFoldPidl_v2>& pidl) const
{
TraceFileFunc(ttidConFoldEntry);
HRESULT hr = S_OK;
DWORD dwNameSize = 0;
DWORD dwDeviceNameSize = 0;
DWORD dwPhoneOrHostAddressSize = 0;
DWORD dwPidlSize = sizeof(ConFoldPidl_v2); // Initialize the PIDL byte count with the base size
Assert(!empty());
Assert(GetName());
Assert(GetDeviceName());
Assert(GetPhoneOrHostAddress());
NETCFG_TRY
if (m_bDirty)
{
// Get the size of the name, and tack on a trailing NULL (since we now
// have something else in the buffer behind it.
//
dwNameSize = lstrlenW(GetName()) + 1;
dwDeviceNameSize = lstrlenW(GetDeviceName()) + 1;
dwPhoneOrHostAddressSize = lstrlenW(GetPhoneOrHostAddress()) + 1;
// Add the size of the string to the PIDL struct size. We don't need to include
// an extra byte for the string's terminating NULL because we've already
// included a WCHAR[1] in the struct.
//
dwPidlSize += ((dwNameSize) * sizeof(WCHAR));
dwPidlSize += ((dwDeviceNameSize) * sizeof(WCHAR));
dwPidlSize += ((dwPhoneOrHostAddressSize) * sizeof(WCHAR));
// Tack of the length of the persist buffer
//
dwPidlSize += GetPersistSize();
// Allocate the PIDL.
//
hr = pidl.ILCreate(dwPidlSize + sizeof(USHORT)); // Terminating 0 for the PIDL
if (SUCCEEDED(hr))
{
PWSTR pszName = NULL;
PWSTR pszDeviceName = NULL;
PWSTR pszPhoneOrHostAddress = NULL;
// Fill in the pidl info.
//
pidl->wizWizard = GetWizard();
pidl->iCB = dwPidlSize;
// pidl->dwVersion = CONNECTIONS_FOLDER_IDL_VERSION_V1;
pidl->ncm = GetNetConMediaType();
pidl->ncs = GetNetConStatus();
pidl->ncsm = GetNetConSubMediaType();
pidl->uLeadId = CONFOLDPIDL_LEADID;
pidl->uTrailId = CONFOLDPIDL_TRAILID;
pidl->clsid = GetCLSID();
pidl->guidId = GetGuidID();
pidl->dwCharacteristics = GetCharacteristics();
// Fill in the name
//
pidl->ulStrNamePos = 0; // offset into the PIDL's pbBuf
pidl->ulStrNameSize = dwNameSize * sizeof(WCHAR); // in bytes
pszName = pidl->PszGetNamePointer();
lstrcpyW(pszName, GetName());
pszName[dwNameSize] = 0;
// Fill in the device name, and set the offset info
//
pidl->ulStrDeviceNamePos = pidl->ulStrNamePos + pidl->ulStrNameSize;
pidl->ulStrDeviceNameSize = dwDeviceNameSize * sizeof(WCHAR); // in bytes
pszDeviceName = pidl->PszGetDeviceNamePointer();
lstrcpyW(pszDeviceName, GetDeviceName());
pszDeviceName[dwDeviceNameSize] = 0;
// Set the offset into the PIDL's pbBuf
//
pidl->ulPersistBufPos = pidl->ulStrDeviceNamePos + pidl->ulStrDeviceNameSize;
// Fill in the persist buffer, if present (it won't be on a wizard)
//
if (GetPersistData())
{
pidl->ulPersistBufSize = GetPersistSize();
CopyMemory(pidl->bData + pidl->ulPersistBufPos, GetPersistData(), GetPersistSize());
}
else
{
// Since we're the wizard, there shouldn't be a buffer, so the size
// should always be passed in as 0.
//
Assert(GetPersistSize() == 0);
pidl->ulPersistBufSize = 0;
}
// Fill in the Phone Number & Host Address name, and set the offset info
//
pidl->ulStrPhoneOrHostAddressPos = pidl->ulPersistBufPos + pidl->ulPersistBufSize; // offset
pidl->ulStrPhoneOrHostAddressSize = dwPhoneOrHostAddressSize * sizeof(WCHAR); // in bytes
pszPhoneOrHostAddress = pidl->PszGetPhoneOrHostAddressPointer();
lstrcpyW(pszPhoneOrHostAddress, GetPhoneOrHostAddress());
pszPhoneOrHostAddress[dwPhoneOrHostAddressSize] = 0;
Assert( !lstrcmpW(pidl->PszGetNamePointer(), GetName()) );
Assert( !lstrcmpW(pidl->PszGetPhoneOrHostAddressPointer(), GetPhoneOrHostAddress()) );
Assert( !lstrcmpW(pidl->PszGetDeviceNamePointer(), GetDeviceName()) );
Assert( !memcmp(pidl->PbGetPersistBufPointer(), GetPersistData(), GetPersistSize()) );
// Don't forget to terminate the list!
//
LPITEMIDLIST pidlTerminate;
pidlTerminate = ILNext( pidl.GetItemIdList() );
pidlTerminate->mkid.cb = 0;
}
else
{
AssertSz(FALSE, "CConFoldEntry::ConvertToPidl is hosed");
hr = E_OUTOFMEMORY;
}
#ifdef DBG_VALIDATE_PIDLS
Assert(IsValidPIDL( pidl.GetItemIdList() ));
#endif
Assert( pidl->IsPidlOfThisType() ) ;
if (SUCCEEDED(hr))
{
m_bDirty = FALSE;
m_CachedV2Pidl = pidl;
}
}
else
{
TraceTag(ttidShellFolder, "Using internally cached PIDL");
pidl = m_CachedV2Pidl;
}
NETCFG_CATCH(hr)
TraceHr(ttidError, FAL, hr, FALSE, "CConFoldEntry::ConvertToPidl");
return hr;
}
CONFOLDPIDLTYPE GetPidlType(LPCITEMIDLIST pidl)
{
CONFOLDPIDLTYPE bRet = PIDL_TYPE_UNKNOWN;
if (!pidl)
{
return bRet;
}
// V1 check
if (pidl->mkid.cb >= CBCONFOLDPIDLV1_MIN)
{
const UNALIGNED ConFoldPidl_v1* pcfp = reinterpret_cast<const ConFoldPidl_v1*>(pidl);
if ( (pcfp->iCB >= CBCONFOLDPIDLV1_MIN) && (pcfp->iCB <= CBCONFOLDPIDLV1_MAX))
{
if (pcfp->uLeadId == CONFOLDPIDL_LEADID &&
pcfp->uTrailId == CONFOLDPIDL_TRAILID)
{
if (pcfp->dwVersion == ConFoldPidl_v1::CONNECTIONS_FOLDER_IDL_VERSION)
{
bRet = PIDL_TYPE_V1;
return bRet;
}
}
}
}
// V2 check
if (pidl->mkid.cb >= CBCONFOLDPIDLV2_MIN)
{
const UNALIGNED ConFoldPidl_v2* pcfp = reinterpret_cast<const ConFoldPidl_v2 *>(pidl);
if ( (pcfp->iCB >= CBCONFOLDPIDLV2_MIN) && (pcfp->iCB <= CBCONFOLDPIDLV2_MAX))
{
if (pcfp->uLeadId == CONFOLDPIDL_LEADID &&
pcfp->uTrailId == CONFOLDPIDL_TRAILID)
{
if (pcfp->dwVersion == ConFoldPidl_v2::CONNECTIONS_FOLDER_IDL_VERSION)
{
bRet = PIDL_TYPE_V2;
return bRet;
}
}
}
}
// 98 Check
if (pidl->mkid.cb >= CBCONFOLDPIDL98_MIN)
{
const UNALIGNED ConFoldPidl98* pcfp = reinterpret_cast<const ConFoldPidl98 *>(pidl);
if ((pcfp->cbSize >= CBCONFOLDPIDL98_MIN) && (pcfp->cbSize <= CBCONFOLDPIDL98_MAX))
{
if ((SOF_REMOTE == pcfp->uFlags) || (SOF_NEWREMOTE == pcfp->uFlags) ||
(SOF_MEMBER == pcfp->uFlags))
{
if (pcfp->nIconIndex >= 0)
{
bRet = PIDL_TYPE_98;
return bRet;
}
}
}
}
return bRet;
}
HRESULT ConFoldPidl_v1::ConvertToConFoldEntry(OUT CConFoldEntry& ccfe) const
{
HRESULT hr = S_OK;
Assert(this);
if (!this)
{
return E_UNEXPECTED;
}
#if ( defined (MMMDBG) && defined ( _X86_ ) )
if ( (g_ccl.m_csMain.OwningThread == (HANDLE)GetCurrentThreadId()) && (g_ccl.m_csMain.LockCount != -1) )
{
AssertSz(NULL, ".ConvertToConFoldEntry is called while the thread is owning g_ccl's Critical section. \r\n"
"This may deadlock since .ConvertToConFoldEntry needs to marshall COM calls to other threads \r\n\r\n"
"To Fix: Make a copy of ccfe from the pidl and Release the lock before calling .ConvertToConFoldEntry.");
}
#endif
// hr = ConvertToPidlInCache(*this, pcfp); // NOT REQUIRED. WE KNOW THIS IS A V1 PIDL!
// Initialize the data from the pidl
hr = ccfe.HrInitData(wizWizard,
ncm,
NCSM_NONE,
ncs,
&clsid,
&guidId,
dwCharacteristics,
PbGetPersistBufPointer(),
ulPersistBufSize,
PszGetNamePointer(),
PszGetDeviceNamePointer(),
NULL /*PszGetPhoneOrHostAddressPointer()*/);
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "Failed in call to pcfe->HrInitData in ConvertToConFoldEntry");
}
TraceHr(ttidError, FAL, hr, FALSE, "ConvertToConFoldEntry");
return hr;
}
HRESULT ConFoldPidl_v2::ConvertToConFoldEntry(OUT CConFoldEntry& ccfe) const
{
HRESULT hr = S_OK;
Assert(this);
if (!this)
{
return E_UNEXPECTED;
}
#if ( defined (MMMDBG) && defined ( _X86_ ) )
if ( (g_ccl.m_csMain.OwningThread == (HANDLE)GetCurrentThreadId()) && (g_ccl.m_csMain.LockCount != -1) )
{
AssertSz(NULL, ".ConvertToConFoldEntry is called while the thread is owning g_ccl's Critical section. \r\n"
"This may deadlock since .ConvertToConFoldEntry needs to marshall COM calls to other threads \r\n\r\n"
"To Fix: Make a copy of ccfe from the pidl and Release the lock before calling .ConvertToConFoldEntry.");
}
#endif
// hr = ConvertToPidlInCache(*this, pcfp); // NOT REQUIRED. WE KNOW THIS IS A V2 PIDL!
// Initialize the data from the pidl
hr = ccfe.HrInitData(wizWizard,
ncm,
ncsm,
ncs,
&clsid,
&guidId,
dwCharacteristics,
PbGetPersistBufPointer(),
ulPersistBufSize,
PszGetNamePointer(),
PszGetDeviceNamePointer(),
PszGetPhoneOrHostAddressPointer());
if (FAILED(hr))
{
TraceHr(ttidShellFolder, FAL, hr, FALSE, "Failed in call to pcfe->HrInitData in ConvertToConFoldEntry");
}
TraceHr(ttidError, FAL, hr, FALSE, "ConvertToConFoldEntry");
return hr;
}