STDMETHODIMP CShellExt::XToolTipExt::GetInfoTip(DWORD dwFlags, LPWSTR *ppwszTip) { METHOD_PROLOGUE(CShellExt, ToolTipExt); if ((_tcslen(pThis->m_szFile) == 0)||(!IsPathInAfs(pThis->m_szFile))) { *ppwszTip=NULL; return S_OK; } bool bIsSymlink = !!IsSymlink(pThis->m_szFile); bool bIsMountpoint = !!IsMountPoint(pThis->m_szFile); if ((!bIsSymlink) && (!bIsMountpoint)) { *ppwszTip=NULL; return S_OK; } USES_CONVERSION; // dwFlags is currently unused. CString sInfo; if (bIsSymlink) sInfo = GetSymlink(pThis->m_szFile); else if (bIsMountpoint) sInfo = GetMountpoint(pThis->m_szFile); *ppwszTip = (WCHAR*) (pThis->m_pAlloc)->Alloc((1+sInfo.GetLength())*sizeof(WCHAR)); if (*ppwszTip) wcscpy(*ppwszTip, (WCHAR*)T2COLE((LPCTSTR)sInfo)); return S_OK; }
// Check wether the current item is a junction point but no volume mount point // as the latter ones are treated differently (see above). bool CMountPoints::IsJunctionPoint(CString path) { if (IsMountPoint(path)) return false; DWORD attr = GetFileAttributes(path); if (attr == INVALID_FILE_ATTRIBUTES) return false; return ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0); }
STDMETHODIMP CShellExt::XIconExt::IsMemberOf(LPCWSTR pwszPath,DWORD dwAttrib) { METHOD_PROLOGUE(CShellExt, IconExt); TCHAR szPath[MAX_PATH]; #ifdef UNICODE _tcscpy(szPath, pwszPath); #else WideCharToMultiByte( CP_ACP,0,pwszPath,-1,szPath,MAX_PATH,NULL,NULL); #endif if (!IsPathInAfs(szPath)) return S_FALSE; if ((pThis->GetOverlayObject() == 0)&&(IsSymlink(szPath))) { return S_OK; } if ((pThis->GetOverlayObject() == 1)&&(IsMountPoint(szPath))) { return S_OK; } return S_FALSE; }
///////////////////////////////////////////////////////////////////////////// // IShellInit Functions ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CShellExt::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdobj, HKEY hkeyProgID) { METHOD_PROLOGUE(CShellExt, ShellInit); HRESULT hres = E_FAIL; FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM medium; // We must have a data object if ((pdobj == NULL) && (pidlFolder == NULL)) return E_FAIL; pThis->m_bIsSymlink=false; pThis->m_bIsMountpoint=false; pThis->m_bIsPathInAFS=false; pThis->m_bDirSelected=false; if (pdobj) { // Use the given IDataObject to get a list of filenames (CF_HDROP) hres = pdobj->GetData(&fmte, &medium); if (FAILED(hres)) { return E_FAIL; } int nNumFiles = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0); if (nNumFiles == 0) hres = E_FAIL; else { pThis->m_bDirSelected = FALSE; for (int ii = 0; ii < nNumFiles; ii++) { CString strFileName; // Get the size of the file name string int nNameLen = DragQueryFile((HDROP)medium.hGlobal, ii, 0, 0); // Make room for it in our string object LPTSTR pszFileNameBuf = strFileName.GetBuffer(nNameLen + 1); // +1 for the terminating NULL ASSERT(pszFileNameBuf); // Get the file name DragQueryFile((HDROP)medium.hGlobal, ii, pszFileNameBuf, nNameLen + 1); strFileName.ReleaseBuffer(); if (!IsPathInAfs(strFileName)) { pThis->m_astrFileNames.RemoveAll(); pThis->m_bIsPathInAFS=false; break; } else { pThis->m_bIsSymlink=pThis->m_bIsSymlink||IsSymlink(strFileName); pThis->m_bIsMountpoint=pThis->m_bIsMountpoint||IsMountPoint(strFileName); pThis->m_bIsPathInAFS=true; } if (IsADir(strFileName)) pThis->m_bDirSelected = TRUE; pThis->m_astrFileNames.Add(strFileName); } // Release the data ReleaseStgMedium(&medium); } } if ((pThis->m_astrFileNames.GetSize() == 0)&&(pidlFolder)) { // if there are no valid files selected, try the folder background IShellFolder *parentFolder = NULL; STRRET name; TCHAR * szDisplayName = NULL; hres = ::SHGetDesktopFolder(&parentFolder); if (FAILED(hres)) return hres; hres = parentFolder->GetDisplayNameOf(pidlFolder, SHGDN_NORMAL | SHGDN_FORPARSING, &name); if (FAILED(hres)) { parentFolder->Release(); return hres; } hres = StrRetToStr (&name, pidlFolder, &szDisplayName); if (FAILED(hres)) return hres; parentFolder->Release(); if (szDisplayName) { pThis->m_bDirSelected = TRUE; CString strFileName = CString(szDisplayName); if (IsPathInAfs(strFileName)) { pThis->m_bIsSymlink=IsSymlink(strFileName); pThis->m_bIsMountpoint=IsMountPoint(strFileName); pThis->m_bIsPathInAFS=true; pThis->m_astrFileNames.Add(strFileName); } CoTaskMemFree(szDisplayName); } } if (pThis->m_astrFileNames.GetSize() > 0) hres = NOERROR; else hres = E_FAIL; return hres; }
///////////////////////////////////////////////////////////////////////////// // IConextMenu Functions ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu, UINT idCmdFirst, UINT idCmdLast,UINT uFlags) { METHOD_PROLOGUE(CShellExt, MenuExt); // Don't add any menu items if we're being asked to deal with this file as a shortcut. if (uFlags & CMF_VERBSONLY) return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)0); if (!pThis->m_bIsPathInAFS) return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)0); // Check to see if there's already an AFS menu here; if so, remove it int nItemsNow = GetMenuItemCount (hMenu); CString strAfsItemText = GetMessageString(IDS_AFS_ITEM); CString strDeleteText = GetMessageString(IDS_MENU_DELETE); CString strCutText = GetMessageString(IDS_MENU_CUT); LPCTSTR pszAfsItemText = (LPCTSTR)strAfsItemText; for (int iItem = 0; iItem < nItemsNow; iItem++) { TCHAR szItemText[256]; if (!GetMenuString (hMenu, iItem, szItemText, 256, MF_BYPOSITION)) continue; if (lstrcmp (szItemText, pszAfsItemText)==0) { DeleteMenu (hMenu, iItem, MF_BYPOSITION); continue; } if (((lstrcmp(szItemText,strDeleteText)==0)||(lstrcmp(szItemText,strCutText)==0))&&((pThis->m_bIsSymlink)||(pThis->m_bIsMountpoint))) { DeleteMenu (hMenu, iItem, MF_BYPOSITION); continue; } } int indexShellMenu = 0; // Create the AFS submenu using the allowed ID's. HMENU hAfsMenu = CreatePopupMenu(); int indexAfsMenu = 0; // Only enable the ACL menu item if a single directory is selected int nSingleDirOnly = MF_GRAYED; if (pThis->m_bDirSelected && (pThis->m_astrFileNames.GetSize() == 1)) nSingleDirOnly = MF_ENABLED; ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_ACL_SET, GetMessageString(IDS_ACLS_ITEM)); // Volume/Partition submenu of the AFS submenu HMENU hVolPartMenu = CreatePopupMenu(); int indexVolPartMenu = 0; ::InsertMenu(hVolPartMenu, indexVolPartMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_VOLUME_PROPERTIES, GetMessageString(IDS_VOL_PART_PROPS_ITEM)); ::InsertMenu(hVolPartMenu, indexVolPartMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE, GetMessageString(IDS_VOL_PART_REFRESH_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hVolPartMenu, GetMessageString(IDS_VOL_PART_ITEM)); // Mount Point submenu of the AFS submenu HMENU hMountPointMenu = CreatePopupMenu(); int indexMountPointMenu = 0; int nMountPointSelected = MF_GRAYED; for (int n = pThis->m_astrFileNames.GetSize() - 1 ; n >= 0; n--) { if ( IsMountPoint(pThis->m_astrFileNames[n]) ) { nMountPointSelected = MF_ENABLED; break; } } ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_SHOW, GetMessageString(IDS_MP_SHOW_ITEM)); ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION | nMountPointSelected, idCmdFirst + IDM_MOUNTPOINT_REMOVE, GetMessageString(IDS_MP_REMOVE_ITEM)); ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_MAKE, GetMessageString(IDS_MP_MAKE_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hMountPointMenu, GetMessageString(IDS_MOUNT_POINT_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_FLUSH, GetMessageString(IDS_FLUSH_FILE_DIR_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_FLUSH_VOLUME, GetMessageString(IDS_FLUSH_VOLUME_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHOW_SERVER, GetMessageString(IDS_SHOW_FILE_SERVERS_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHOWCELL, GetMessageString(IDS_SHOW_CELL_ITEM)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SERVER_STATUS, GetMessageString(IDS_SHOW_SERVER_STATUS_ITEM)); HMENU hSymbolicMenu = CreatePopupMenu(); int indexSymbolicMenu = 0; int nSymlinkSelected = MF_GRAYED; for (int n = pThis->m_astrFileNames.GetSize() - 1 ; n >= 0; n--) { if ( IsSymlink(pThis->m_astrFileNames[n]) ) { nSymlinkSelected = MF_ENABLED; break; } } ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_ADD, GetMessageString(IDS_SYMBOLICLINK_ADD)); ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION | nSymlinkSelected, idCmdFirst + IDM_SYMBOLICLINK_SHOW, GetMessageString(IDS_SYMBOLICLINK_SHOW)); ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION | nSymlinkSelected, idCmdFirst + IDM_SYMBOLICLINK_REMOVE, GetMessageString(IDS_SYMBOLICLINK_REMOVE)); ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSymbolicMenu, GetMessageString(IDS_SYMBOLIC_LINK_ITEM)); // The Submounts menu has been removed because the AFS tray icon // and control panel now support mapping drives directly to an AFS // path. // //HMENU hSubmountMenu = CreatePopupMenu(); //int indexSubmountMenu = 0; //::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_SUBMOUNTS_CREATE, GetMessageString(IDS_SUBMOUNTS_CREATE_ITEM)); //::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SUBMOUNTS_EDIT, GetMessageString(IDS_SUBMOUNTS_EDIT_ITEM)); //::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSubmountMenu, GetMessageString(IDS_SUBMOUNTS_ITEM)); // Add a separator ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT("")); // Add the AFS submenu to the shell's menu ::InsertMenu(hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hAfsMenu, GetMessageString(IDS_AFS_ITEM)); // Add a separator after us ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT("")); return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)indexAfsMenu + indexVolPartMenu + indexMountPointMenu + indexShellMenu + indexSymbolicMenu); }