|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: I S H E L L F . C P P
//
// Contents: IShellFolder implementation for CConnectionFolder
//
// Notes: The IShellFolder interface is used to manage folders within
// the namespace. Objects that support IShellFolder are
// usually created by other shell folder objects, with the root
// object (the Desktop shell folder) being returned from the
// SHGetDesktopFolder function.
//
// Author: jeffspr 22 Sep 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "foldinc.h" // Standard shell\folder includes
#include "cfutils.h" // Connections folder utilities
#include "foldres.h"
#include "ncnetcon.h"
#include "droptarget.h"
#include "ncperms.h"
#include "ncras.h"
#include "cmdtable.h"
#include "webview.h"
#define ENABLE_CONNECTION_TOOLTIP
const WCHAR c_szNetworkConnections[] = L"NetworkConnections";
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::ParseDisplayName
//
// Purpose: Translates a file object or folder's display name into an
// item identifier.
//
// Arguments:
// hwndOwner [in] Handle of owner window
// pbcReserved [in] Reserved
// lpszDisplayName [in] Pointer to diplay name
// pchEaten [out] Pointer to value for parsed characters
// ppidl [out] Pointer to new item identifier list
// pdwAttributes [out] Address receiving attributes of file object
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise
//
// Author: jeffspr 18 Oct 1997
STDMETHODIMP CConnectionFolder::ParseDisplayName( HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName, ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG * pdwAttributes) { HRESULT hr = S_OK; TraceFileFunc(ttidShellFolder);
if (!ppidl) { return E_POINTER; }
*ppidl = NULL;
if ((lpszDisplayName == NULL) || (wcslen(lpszDisplayName) < (c_cchGuidWithTerm - 1))) { return E_INVALIDARG; }
while (*lpszDisplayName == ':') { lpszDisplayName++; }
if (*lpszDisplayName != '{') { return E_INVALIDARG; }
GUID guid;
if (SUCCEEDED(CLSIDFromString(lpszDisplayName, &guid))) { if (g_ccl.IsInitialized() == FALSE) { g_ccl.HrRefreshConManEntries(); }
PCONFOLDPIDL pidl; hr = g_ccl.HrFindPidlByGuid(&guid, pidl); if (S_OK == hr) { *ppidl = pidl.TearOffItemIdList(); TraceTag(ttidShellFolderIface, "IShellFolder::ParseDisplayName generated PIDL: 0x%08x", *ppidl); } else { hr = E_FILE_NOT_FOUND; } } else { return(E_FAIL); }
if (SUCCEEDED(hr) && pdwAttributes) { LPCITEMIDLIST pidlArr[1]; pidlArr[0] = *ppidl; hr = GetAttributesOf(1, pidlArr, pdwAttributes); }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::EnumObjects
//
// Purpose: Determines the contents of a folder by creating an item
// enumeration object (a set of item identifiers) that can be
// retrieved using the IEnumIDList interface.
//
// Arguments:
// hwndOwner [in] Handle of owner window
// grfFlags [in] Items to include in enumeration
// ppenumIDList [out] Pointer to IEnumIDList
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::EnumObjects( HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList) { TraceFileFunc(ttidShellFolder);
HRESULT hr = NOERROR;
Assert(ppenumIDList);
NETCFG_TRY // Create the IEnumIDList object (CConnectionFolderEnum)
//
hr = CConnectionFolderEnum::CreateInstance ( IID_IEnumIDList, reinterpret_cast<void**>(ppenumIDList));
if (SUCCEEDED(hr)) { Assert(*ppenumIDList);
// Call the PidlInitialize function to allow the enumeration
// object to copy the list.
//
reinterpret_cast<CConnectionFolderEnum *>(*ppenumIDList)->PidlInitialize( FALSE, m_pidlFolderRoot, m_dwEnumerationType);
} else { // On all failures, this should be NULL.
if (*ppenumIDList) { ReleaseObj(*ppenumIDList); }
*ppenumIDList = NULL; }
NETCFG_CATCH(hr) TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolder::EnumObjects"); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::BindToObject
//
// Purpose: Creates an IShellFolder object for a subfolder.
//
// Arguments:
// pidl [in] Pointer to an ITEMIDLIST
// pbcReserved [in] Reserved - specify NULL
// riid [in] Interface to return
// ppvOut [out] Address that receives interface pointer;
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise
//
// Author: jeffspr 18 Oct 1997
//
// Notes: We don't need this function, since we don't have subfolders.
//
STDMETHODIMP CConnectionFolder::BindToObject( LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) { TraceFileFunc(ttidShellFolder);
// Note - If we add code here, then we ought to param check pidl
//
Assert(pidl);
*ppvOut = NULL;
return E_NOTIMPL; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::BindToStorage
//
// Purpose: Reserved for a future use. This method should
// return E_NOTIMPL.
//
// Arguments:
// pidl [] Pointer to an ITEMIDLIST
// pbcReserved [] Reserved�specify NULL
// riid [] Interface to return
// ppvObj [] Address that receives interface pointer);
//
// Returns: E_NOTIMPL always
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::BindToStorage( LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvObj) { TraceFileFunc(ttidShellFolder);
// Note - If we add code here, then we ought to param check pidl
//
Assert(pidl);
*ppvObj = NULL;
return E_NOTIMPL; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::CompareIDs
//
// Purpose: Determines the relative ordering of two file objects or
// folders, given their item identifier lists.
//
// Arguments:
// lParam [in] Type of comparison to perform
// pidl1 [in] Address of ITEMIDLIST structure
// pidl2 [in] Address of ITEMIDLIST structure
//
// Returns: Returns a handle to a result code. If this method is
// successful, the CODE field of the status code (SCODE) has
// the following meaning:
//
// CODE field Meaning
// ---------- -------
// Less than zero The first item should precede the second
// (pidl1 < pidl2).
// Greater than zero The first item should follow the second
// (pidl1 > pidl2)
// Zero The two items are the same (pidl1 = pidl2)
//
// Author: jeffspr 18 Oct 1997
//
// Notes: Passing 0 as the lParam indicates sort by name.
// 0x00000001-0x7fffffff are for folder specific sorting rules.
// 0x80000000-0xfffffff are used the system.
//
STDMETHODIMP CConnectionFolder::CompareIDs( LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { TraceFileFunc(ttidShellFolder);
HRESULT hr = S_OK; int iCompare = 0; CONFOLDENTRY pccfe1; CONFOLDENTRY pccfe2; PCONFOLDPIDL pcfp1; PCONFOLDPIDL pcfp2; ConnListEntry cle1; ConnListEntry cle2; PCWSTR pszString1 = NULL; PCWSTR pszString2 = NULL; INT iStringID1 = 0; INT iStringID2 = 0;
hr = pcfp1.InitializeFromItemIDList(pidl1); if (SUCCEEDED(hr)) { hr = pcfp2.InitializeFromItemIDList(pidl2); } // Make sure that the pidls passed in are our pidls.
//
if (FAILED(hr)) { hr = E_INVALIDARG; goto Exit; }
if (WIZARD_NOT_WIZARD != pcfp1->wizWizard && WIZARD_NOT_WIZARD != pcfp2->wizWizard) { hr = ResultFromShort(0);
if (pcfp1->wizWizard > pcfp2->wizWizard) hr = ResultFromShort(-1);
if (pcfp1->wizWizard < pcfp2->wizWizard) hr = ResultFromShort(1);
goto Exit; }
// If the first item is a wizard, then it comes first.
//
if (WIZARD_NOT_WIZARD != pcfp1->wizWizard) { hr = ResultFromShort(-1); goto Exit; }
// If the second item is a wizard, then, well, you get the picture.
//
if (WIZARD_NOT_WIZARD != pcfp2->wizWizard) { hr = ResultFromShort(1); goto Exit; }
// Note: (jeffspr) & SHC... should be removed once Victor Tan checks in a fix
// for the IShellFolder2 params being used in IShellFolder
//
switch(lParam & SHCIDS_COLUMNMASK) { case ICOL_NAME: { // Check the name. If the name is the same, then we need to
// check the GUID as well, because we HAVE TO allow duplicate names,
// and this function is used to uniquely identify connections for
// notification purposes
//
LPCWSTR szPcfpName1 = pcfp1->PszGetNamePointer() ? pcfp1->PszGetNamePointer() : L"\0"; LPCWSTR szPcfpName2 = pcfp2->PszGetNamePointer() ? pcfp2->PszGetNamePointer() : L"\0";
iCompare = lstrcmpW(szPcfpName1, szPcfpName2); if (iCompare == 0) { if (!InlineIsEqualGUID(pcfp1->guidId, pcfp2->guidId)) { // Doesn't really matter which order we put them
// in, as long as we call them non-equal
iCompare = -1; } } } break;
case ICOL_TYPE: { MapNCMToResourceId(pcfp1->ncm, pcfp1->dwCharacteristics, &iStringID1); MapNCMToResourceId(pcfp2->ncm, pcfp2->dwCharacteristics, &iStringID2); pszString1 = (PWSTR) SzLoadIds(iStringID1); pszString2 = (PWSTR) SzLoadIds(iStringID2); if (pszString1 && pszString2) { iCompare = lstrcmpW(pszString1, pszString2); } } break;
case ICOL_STATUS: { WCHAR szString1[CONFOLD_MAX_STATUS_LENGTH]; WCHAR szString2[CONFOLD_MAX_STATUS_LENGTH]; MapNCSToComplexStatus(pcfp1->ncs, pcfp1->ncm, pcfp1->ncsm, pcfp1->dwCharacteristics, szString1, CONFOLD_MAX_STATUS_LENGTH, pcfp1->guidId); MapNCSToComplexStatus(pcfp2->ncs, pcfp2->ncm, pcfp1->ncsm, pcfp2->dwCharacteristics, szString2, CONFOLD_MAX_STATUS_LENGTH, pcfp2->guidId); iCompare = lstrcmpW(szString1, szString2); } break;
case ICOL_DEVICE_NAME: { LPCWSTR szPcfpDeviceName1 = pcfp1->PszGetDeviceNamePointer() ? pcfp1->PszGetDeviceNamePointer() : L"\0"; LPCWSTR szPcfpDeviceName2 = pcfp2->PszGetDeviceNamePointer() ? pcfp2->PszGetDeviceNamePointer() : L"\0"; iCompare = lstrcmpW(szPcfpDeviceName1, szPcfpDeviceName2); } break;
case ICOL_OWNER: { pszString1 = PszGetOwnerStringFromCharacteristics(pszGetUserName(), pcfp1->dwCharacteristics); pszString2 = PszGetOwnerStringFromCharacteristics(pszGetUserName(), pcfp2->dwCharacteristics); iCompare = lstrcmpW(pszString1, pszString2); } break;
case ICOL_PHONEORHOSTADDRESS: { LPCWSTR szPcfpPhoneHostAddress1 = pcfp1->PszGetPhoneOrHostAddressPointer() ? pcfp1->PszGetPhoneOrHostAddressPointer() : L"\0"; LPCWSTR szPcfpPhoneHostAddress2 = pcfp2->PszGetPhoneOrHostAddressPointer() ? pcfp2->PszGetPhoneOrHostAddressPointer() : L"\0"; iCompare = lstrcmpW(szPcfpPhoneHostAddress1, szPcfpPhoneHostAddress2); } break;
default: // AssertFmt(FALSE, FAL, "Shell bug - Sorting on unknown category. Column = %x", (lParam & SHCIDS_COLUMNMASK));
hr = E_INVALIDARG; break; }
if (SUCCEEDED(hr)) { hr = ResultFromShort(iCompare); }
Exit: // If these were allocated instead of cached, delete them
//
TraceHr(ttidError, FAL, hr, (ResultFromShort(-1) == hr) || (ResultFromShort(1) == hr), "CConnectionFolder::CompareIDs"); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::CreateViewObject
//
// Purpose: Creates a view object of a folder.
//
// Arguments:
// hwndOwner [in] Handle of owner window
// riid [in] Interface identifier
// ppvOut [none] Reserved
//
// Returns: Returns NOERROR if successful or an OLE defined error
// value otherwise.
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::CreateViewObject( HWND hwndOwner, REFIID riid, LPVOID * ppvOut) { TraceFileFunc(ttidShellFolder);
HRESULT hr = E_NOINTERFACE;
Assert(ppvOut); Assert(this);
// Pre-initialize the out param, per OLE guidelines
//
*ppvOut = NULL;
if (riid == IID_IShellView) { if (FHasPermission(NCPERM_OpenConnectionsFolder)) { SFV_CREATE sfv = {0}; sfv.cbSize = sizeof(sfv); sfv.pshf = dynamic_cast<IShellFolder2*>(this); sfv.psfvcb = dynamic_cast<IShellFolderViewCB*>(this);
// Note: The shell never gets around to freeing the last view
// when shutting down...
//
hr = SHCreateShellFolderView(&sfv, &m_pShellView); if (SUCCEEDED(hr)) { *ppvOut = m_pShellView; DWORD dwErr = 0;
// Get the state of the "ManualDial" flag from RAS
// so we can initialize our global
//
dwErr = RasUserGetManualDial( hwndOwner, FALSE, (PBOOL) (&g_fOperatorAssistEnabled));
// Ignore the error (don't shove it in the Hr), because
// we still want to run even if we failed to get the value
// Trace it, though
Assert(dwErr == 0); TraceHr(ttidShellFolder, FAL, HRESULT_FROM_WIN32(dwErr), FALSE, "RasUserGetManualDial call from CreateViewObject"); } } else { TraceTag(ttidShellFolder, "No permission to open connections folder (FHasPermission returned 0)"); AssertSz(FALSE, "get off!");
if (hwndOwner) { NcMsgBox(_Module.GetResourceInstance(), hwndOwner, IDS_CONFOLD_WARNING_CAPTION, IDS_CONFOLD_NO_PERMISSIONS_FOR_OPEN, MB_ICONEXCLAMATION | MB_OK);
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED); // user saw the error
} else { hr = E_ACCESSDENIED; } } } else if (riid == IID_IContextMenu) { // Create our context menu object for the background CMs.
//
hr = CConnectionFolderContextMenu::CreateInstance ( IID_IContextMenu, reinterpret_cast<void**>(ppvOut), CMT_BACKGROUND, hwndOwner, PCONFOLDPIDLVEC(NULL), this); if (SUCCEEDED(hr)) { Assert(*ppvOut); } } else if (riid == IID_ICategoryProvider) { // Create our context menu object for the background CMs.
//
CComPtr<IDefCategoryProvider> pDevCategoryProvider; hr = CoCreateInstance(CLSID_DefCategoryProvider, NULL, CLSCTX_ALL, IID_IDefCategoryProvider, reinterpret_cast<LPVOID *>(&pDevCategoryProvider)); if (SUCCEEDED(hr)) { SHCOLUMNID pscidType, pscidPhoneOrHostAddress; MapColumnToSCID(ICOL_TYPE, &pscidType); MapColumnToSCID(ICOL_PHONEORHOSTADDRESS, &pscidPhoneOrHostAddress); SHCOLUMNID pscidExclude[2]; pscidExclude[0].fmtid = GUID_NETSHELL_PROPS; pscidExclude[0].pid = ICOL_PHONEORHOSTADDRESS; pscidExclude[1].fmtid = GUID_NULL; pscidExclude[1].pid = 0; CATLIST catList[] = { {&GUID_NULL, NULL} }; if (SUCCEEDED(hr)) { pDevCategoryProvider->Initialize(&GUID_NETSHELL_PROPS, &pscidType, pscidExclude, NULL, catList, this); hr = pDevCategoryProvider->QueryInterface(IID_ICategoryProvider, ppvOut); } } } else { goto Exit; }
Exit:
TraceHr(ttidError, FAL, hr, (E_NOINTERFACE == hr), "CConnectionFolder::CreateViewObject");
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::GetAttributesOf
//
// Purpose: Retrieves the attributes that all passed-in objects (file
// objects or subfolders) have in common.
//
// Arguments:
// cidl [in] Number of file objects
// apidl [in] Pointer to array of pointers to ITEMIDLIST structures
// rgfInOut [out] Address of value containing attributes of the
// file objects
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise.
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::GetAttributesOf( UINT cidl, LPCITEMIDLIST * apidl, ULONG * rgfInOut) { TraceFileFunc(ttidShellFolder);
HRESULT hr = S_OK; ULONG rgfMask = 0; PCONFOLDPIDL pcfp;
if (cidl > 0) { PCONFOLDPIDLVEC pcfpVec; hr = PConfoldPidlVecFromItemIdListArray(apidl, cidl, pcfpVec); if (FAILED(hr)) { return E_INVALIDARG; } // Prepopulate with all values (removed CANCOPY and CANMOVE)
//
rgfMask = SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_HASPROPSHEET;
// Disable propsheets for > 1 connection
//
if (cidl > 1) { rgfMask &= ~SFGAO_HASPROPSHEET; }
PCONFOLDPIDLVEC::const_iterator iterLoop; for (iterLoop = pcfpVec.begin(); iterLoop != pcfpVec.end(); iterLoop++) { // Translate the PIDL to our struct, and check for wizard inclusion.
// If so, then we don't support anything but "link". If not, then
// we support all of the standard actions
const PCONFOLDPIDL& pcfp = *iterLoop; if(!pcfp.empty()) { if (((*rgfInOut) & SFGAO_VALIDATE)) { ConnListEntry cleDontCare; hr = g_ccl.HrFindConnectionByGuid(&(pcfp->guidId), cleDontCare); if (hr != S_OK) { // Note: Remove this when we get RAS notifications, because
// we will ALWAYS have the information we need to find the connections
// We're doing this because the CM folks are creating RAS icons on the
// desktop without us knowing about it.
//
// If we didn't find it, then flush the cache and try again.
//
if (S_FALSE == hr) { hr = g_ccl.HrRefreshConManEntries(); if (SUCCEEDED(hr)) { hr = g_ccl.HrFindConnectionByGuid(&(pcfp->guidId), cleDontCare); if (hr != S_OK) { hr = E_FAIL; goto Exit; } } } else { hr = E_FAIL; goto Exit; } } }
if (WIZARD_NOT_WIZARD != pcfp->wizWizard) { // No support for delete/rename/etc, since it's the wizard.
// However, we want to provide our own "delete" warning when the
// wizard is selected along with deleteable connections
//
rgfMask = SFGAO_CANLINK | SFGAO_CANDELETE; }
if (pcfp->dwCharacteristics & NCCF_BRANDED) { if ( !fIsConnectedStatus(pcfp->ncs) && (pcfp->ncs != NCS_DISCONNECTING) ) { rgfMask |= SFGAO_GHOSTED; } }
if (pcfp->dwCharacteristics & NCCF_INCOMING_ONLY) { rgfMask &= ~SFGAO_CANLINK; }
// Mask out the unavailable attributes for this connection
//
if (!(pcfp->dwCharacteristics & NCCF_ALLOW_RENAME) || !HasPermissionToRenameConnection(pcfp)) { rgfMask &= ~SFGAO_CANRENAME; }
#if 0 // If I mask this out, I can't give user feedback for objects that can't be deleted.
if (pcfp->dwCharacteristics & NCCF_ALLOW_REMOVAL) { rgfMask |= SFGAO_CANDELETE; } #endif
} } } else { // Apparently, we're called with 0 objects to indicate that we're
// supposed to return flags for the folder itself, not an individual
// object. Weird.
rgfMask = SFGAO_CANCOPY | SFGAO_CANDELETE | SFGAO_CANMOVE | SFGAO_CANRENAME | SFGAO_DROPTARGET; }
Exit: if (SUCCEEDED(hr)) { *rgfInOut &= rgfMask; }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::GetUIObjectOf
//
// Purpose: Creates a COM object that can be used to carry out actions
// on the specified file objects or folders, typically, to
// create context menus or carry out drag-and-drop operations.
//
// Arguments:
// hwndOwner [in] Handle to owner window
// cidl [in] Number of objects specified in apidl
// apidl [in] Pointer to an array of pointers to an ITEMIDLIST
// riid [in] Interface to return
// prgfInOut [none] Reserved
// ppvOut [out] Address to receive interface pointer
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::GetUIObjectOf( HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) { TraceFileFunc(ttidShellFolder);
HRESULT hr = E_NOINTERFACE;
NETCFG_TRY if (cidl >= 1) { Assert(apidl); Assert(apidl[0]); Assert(ppvOut);
if (riid == IID_IDataObject) { // Need to initialize so the SUCCEEED check below doesn't fail.
//
hr = S_OK;
if (m_pidlFolderRoot.empty()) { hr = HrGetConnectionsFolderPidl(m_pidlFolderRoot); } if (SUCCEEDED(hr)) { Assert(!m_pidlFolderRoot.empty());
// Internal IDataObject impl removed. Replaced with common
// shell code.
//
hr = CIDLData_CreateFromIDArray(m_pidlFolderRoot.GetItemIdList(), cidl, apidl, (IDataObject **) ppvOut); } } else if (riid == IID_IContextMenu) { PCONFOLDPIDLVEC pcfpVec; hr = PConfoldPidlVecFromItemIdListArray(apidl, cidl, pcfpVec); if (FAILED(hr)) { return E_INVALIDARG; } // Create our context menu object for the background CMs.
//
if (SUCCEEDED(hr)) { hr = CConnectionFolderContextMenu::CreateInstance ( IID_IContextMenu, reinterpret_cast<void**>(ppvOut), CMT_OBJECT, hwndOwner, pcfpVec, this); if (SUCCEEDED(hr)) { Assert(*ppvOut); } else { hr = E_NOINTERFACE; } } } else if (riid == IID_IExtractIconA || riid == IID_IExtractIconW) { if (cidl == 1) { hr = CConnectionFolderExtractIcon::CreateInstance ( apidl[0], riid, reinterpret_cast<void**>(ppvOut));
if (SUCCEEDED(hr)) { Assert(*ppvOut); } } else { hr = E_NOINTERFACE; } } else if (riid == IID_IDropTarget) { hr = E_NOINTERFACE; } else if (riid == IID_IQueryAssociations) { CComPtr<IQueryAssociations> pQueryAssociations;
hr = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, reinterpret_cast<LPVOID *>(&pQueryAssociations)); if (SUCCEEDED(hr)) { hr = pQueryAssociations->Init(0, c_szNetworkConnections, NULL, NULL); if (SUCCEEDED(hr)) { hr = pQueryAssociations->QueryInterface(IID_IQueryAssociations, ppvOut); } } } else if (riid == IID_IQueryInfo) { #ifdef ENABLE_CONNECTION_TOOLTIP
if (cidl == 1) { PCONFOLDPIDLVEC pcfpVec; hr = PConfoldPidlVecFromItemIdListArray(apidl, cidl, pcfpVec); if (FAILED(hr)) { return E_INVALIDARG; } const PCONFOLDPIDL& pcfp = *pcfpVec.begin();
// Create the IQueryInfo interface
hr = CConnectionFolderQueryInfo::CreateInstance ( IID_IQueryInfo, reinterpret_cast<void**>(ppvOut));
if (SUCCEEDED(hr)) { Assert(*ppvOut);
reinterpret_cast<CConnectionFolderQueryInfo *> (*ppvOut)->PidlInitialize(*pcfpVec.begin());
// Normalize return code
//
hr = NOERROR; } } else { AssertSz(FALSE, "GetUIObjectOf asked for query info for more than one item!"); hr = E_NOINTERFACE; } #else
hr = E_NOINTERFACE; #endif // ENABLE_CONNECTION_TOOLTIP
} else { TraceTag(ttidShellFolder, "CConnectionFolder::GetUIObjectOf asked for object " "that it didn't know how to create. 0x%08x", riid.Data1);
hr = E_NOINTERFACE; } }
if (FAILED(hr)) { *ppvOut = NULL; }
NETCFG_CATCH(hr) TraceHr(ttidError, FAL, hr, (hr == E_NOINTERFACE), "CConnectionFolder::GetUIObjectOf"); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::GetDisplayNameOf
//
// Purpose: Retrieves the display name for the specified file object or
// subfolder, returning it in a STRRET structure.
//
// Arguments:
// pidl [in] Pointer to an ITEMIDLIST
// uFlags [in] Type of display to return
// lpName [out] Pointer to a STRRET structure
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise.
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::GetDisplayNameOf( LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName) { TraceFileFunc(ttidShellFolder);
HRESULT hr = S_OK; PWSTR pszStrToCopy = NULL;
Assert(lpName);
if (!pidl || !lpName) { return E_INVALIDARG; }
PCONFOLDPIDL pcfpLatestVersion; PCONFOLDPIDL pcfpLatestVersionCached; PCONFOLDPIDL98 pcfp98;
CONFOLDPIDLTYPE cfpt = GetPidlType(pidl); switch (cfpt) { case PIDL_TYPE_V1: case PIDL_TYPE_V2: if (FAILED(pcfpLatestVersion.InitializeFromItemIDList(pidl))) { return E_INVALIDARG; } break; case PIDL_TYPE_98: if (FAILED(pcfp98.InitializeFromItemIDList(pidl))) { return E_INVALIDARG; } break;
default: AssertSz(FALSE, "CConnectionFolder::GetDisplayNameOf - Invalid PIDL"); return E_INVALIDARG; break; }
if ( (PIDL_TYPE_V1 == cfpt) || (PIDL_TYPE_V2 == cfpt) ) { #ifdef DBG
// Throw these in here just so I can quickly peek at the values
// set while I'm dorking around in the debugger.
//
DWORD dwInFolder = (uFlags & SHGDN_INFOLDER); DWORD dwForAddressBar = (uFlags & SHGDN_FORADDRESSBAR); DWORD dwForParsing = (uFlags & SHGDN_FORPARSING); #endif
// Find the correct string for the display name. For the wizard, we get it
// from the resources. Otherwise, we use the actual connection name
//
lpName->uType = STRRET_WSTR;
if (uFlags & SHGDN_FORPARSING) { lpName->pOleStr = (LPWSTR)SHAlloc(c_cbGuidWithTerm);
if (lpName->pOleStr == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
if (StringFromGUID2(pcfpLatestVersion->clsid, lpName->pOleStr, c_cbGuidWithTerm) == 0) { return(ERROR_INVALID_NAME); }
return(S_OK); } else if (WIZARD_MNC == pcfpLatestVersion->wizWizard) { pszStrToCopy = (PWSTR) SzLoadIds(IDS_CONFOLD_WIZARD_DISPLAY_NAME); } else if (WIZARD_HNW == pcfpLatestVersion->wizWizard) { pszStrToCopy = (PWSTR) SzLoadIds(IDS_CONFOLD_HOMENET_WIZARD_DISPLAY_NAME); } else { hr = g_ccl.HrGetCachedPidlCopyFromPidl(pcfpLatestVersion, pcfpLatestVersionCached); if (S_OK == hr) { pszStrToCopy = pcfpLatestVersionCached->PszGetNamePointer(); } else { pszStrToCopy = pcfpLatestVersion->PszGetNamePointer(); hr = S_OK; } }
Assert(pszStrToCopy);
// Allocate a new POLESTR block, which the shell can then free,
// and copy the displayable portion to it.
//
// Note that &lpName->pOleStr is likely misaligned.
//
LPWSTR pOleStr;
pOleStr = lpName->pOleStr;
hr = HrDupeShellString(pszStrToCopy, &pOleStr );
lpName->pOleStr = pOleStr; } else if (PIDL_TYPE_98 == cfpt) { // Raid#214057, handle win98 pidl for shortcuts
// Return the offset to the string because we store the display
// name in the opaque structure.
lpName->uType = STRRET_OFFSET; lpName->uOffset = _IOffset(CONFOLDPIDL98, szaName); } else { // not a valid connections pidl (neither Win2K nor Win98).
//
hr = E_INVALIDARG; }
TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolder::GetDisplayNameOf"); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::SetNameOf
//
// Purpose: Changes the name of a file object or subfolder, changing its
// item identifier in the process.
//
// Arguments:
// hwndOwner [in] Handle of owner window
// pidl [in] Pointer to an ITEMIDLIST structure
// lpszName [in] Pointer to string specifying new display name
// uFlags [in] Type of name specified in lpszName
// ppidlOut [out] Pointer to new ITEMIDLIST
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise.
//
// Author: jeffspr 18 Oct 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolder::SetNameOf( HWND hwndOwner, LPCITEMIDLIST pidlShell, LPCOLESTR lpszName, DWORD uFlags, LPITEMIDLIST * ppidlOut) { TraceFileFunc(ttidShellFolder);
HRESULT hr = NOERROR; /*
PWSTR pszWarning = NULL; INetConnection * pNetCon = NULL; LPITEMIDLIST pidlNew = NULL; BOOL fRefresh = FALSE; BOOL fActivating = FALSE; PCONFOLDENTRY pccfe = NULL; */ PCONFOLDPIDL pcfp;
Assert(hwndOwner); Assert(pidlShell); Assert(lpszName);
if (!pidlShell && !lpszName) { hr = E_INVALIDARG; } else { // check lpszName for validity
if (!FIsValidConnectionName(lpszName)) { (void) NcMsgBox( _Module.GetResourceInstance(), hwndOwner, IDS_CONFOLD_RENAME_FAIL_CAPTION, IDS_CONFOLD_RENAME_INVALID, MB_OK | MB_ICONEXCLAMATION); hr = HRESULT_FROM_WIN32(ERROR_INVALID_NAME); }
if (SUCCEEDED(hr)) { // Get what's current from the cache so rename works properly
//
PCONFOLDPIDL pcfpShell; hr = pcfpShell.InitializeFromItemIDList(pidlShell); if (SUCCEEDED(hr)) { hr = g_ccl.HrGetCachedPidlCopyFromPidl(pcfpShell, pcfp); if (SUCCEEDED(hr)) { PCONFOLDPIDL pidlOut; hr = HrRenameConnectionInternal(pcfp, m_pidlFolderRoot, lpszName, TRUE, hwndOwner, pidlOut); if ( (ppidlOut) && (SUCCEEDED(hr)) ) { *ppidlOut = pidlOut.TearOffItemIdList(); } } } } }
if (FAILED(hr) && (ppidlOut)) { *ppidlOut = NULL; }
TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolder::SetNameOf"); return hr; }
STDMETHODIMP CConnectionFolder::MessageSFVCB( UINT uMsg, WPARAM wParam, LPARAM lParam) { TraceFileFunc(ttidShellFolder); HRESULT hr = RealMessage(uMsg, wParam, lParam); if (FAILED(hr)) { switch (uMsg) { case DVM_INVOKECOMMAND: if ((CMIDM_RENAME == wParam) && m_hwndMain && m_pShellView) { PCONFOLDPIDLVEC apidlSelected; PCONFOLDPIDLVEC apidlCache; hr = HrShellView_GetSelectedObjects(m_hwndMain, apidlSelected); if (SUCCEEDED(hr)) { // If there are objects, try to get the cached versions
if (!apidlSelected.empty()) { hr = HrCloneRgIDL(apidlSelected, TRUE, TRUE, apidlCache); } }
if (SUCCEEDED(hr)) { Assert(apidlCache.size() == 1); if (apidlCache.size() == 1) { hr = m_pShellView->SelectItem(apidlCache[0].GetItemIdList(), SVSI_EDIT); } else { hr = E_INVALIDARG; } } } break;
case SFVM_HWNDMAIN: // _hwndMain = (HWND)lParam;
hr = S_OK; break; } } return hr; }
/*
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::GetOverlayIndex
//
// Purpose: Adds icon overlays to connections that need them
//
// Arguments:
// pidlItem [in] Pidl to item in question
// pIndex [out] Address of overlay index into system image list
//
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise.
//
// Author: kenwic 10 May 2000 created, support for sharing overlay
//
// Notes:
//
STDMETHODIMP CConnectionFolder::GetOverlayIndex( LPCITEMIDLIST pidlItem, int* pIndex) { TraceFileFunc(ttidShellFolder);
HRESULT hResult = E_FAIL; *pIndex = -1;
// check to see if connection is sharing, and if so add sharing hand overlay
// i can't call HrNetConFromPidl, because it asserts if passed the wizard icon
PCONFOLDPIDL pcfpItem; pcfpItem.InitializeFromItemIDList(pidlItem);
CONFOLDENTRY pConnectionFolderEntry; hResult = pcfpItem.ConvertToConFoldEntry(pConnectionFolderEntry); if(SUCCEEDED(hResult)) { if(FALSE == pConnectionFolderEntry.GetWizard()) // sharing the wizard is not yet supported
{ if(NCCF_SHARED & pConnectionFolderEntry.GetCharacteristics()) { *pIndex = SHGetIconOverlayIndex(NULL, IDO_SHGIOI_SHARE); hResult = S_OK; } else { hResult = E_FAIL; // the docs for IShellIconOverlay are wrong, we must return failure to deny the icon
} } else { hResult = E_FAIL; } } TraceHr(ttidShellFolder, FAL, hResult, TRUE, "CConnectionFolder::GetOverlayIndex"); return hResult; }
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolder::GetOverlayIconIndex
//
// Purpose: Adds icon overlays to connections that need them
//
// Arguments:
// pidlItem [in] Pidl to item in question
// pIconIndex [out] Address of index into system image list
//
//
// Returns: Returns NOERROR if successful or an OLE-defined error
// value otherwise.
//
// Author: kenwic 10 May 2000 created
//
// Notes:
//
STDMETHODIMP CConnectionFolder::GetOverlayIconIndex( LPCITEMIDLIST pidlItem, int* pIconIndex) { TraceFileFunc(ttidShellFolder);
*pIconIndex = -1;
HRESULT hResult = GetOverlayIndex(pidlItem, pIconIndex); if(SUCCEEDED(hResult)) { *pIconIndex = INDEXTOOVERLAYMASK(*pIconIndex); }
TraceHr(ttidShellFolder, FAL, hResult, TRUE, "CConnectionFolder::GetOverlayIconIndex"); return hResult; }*/
|