windows-afs-shell-ext-32bit-20060906
[openafs.git] / src / WINNT / client_exp / shell_ext.cpp
index 304cd77..86fd34c 100644 (file)
@@ -7,13 +7,16 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
+#include <afxpriv.h>
+#include "stdafx.h"
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
 extern "C" {
 #include <afs/param.h>
 #include <afs/stds.h>
 }
 
-#include <afxpriv.h>
-#include "stdafx.h"
 #include <atlconv.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -27,7 +30,8 @@ extern "C" {
 #include "server_status_dlg.h"
 #include "auth_dlg.h"
 #include "submounts_dlg.h"
-#include "gui2fs.h"
+#include "make_symbolic_link_dlg.h"
+#include <WINNT\afsreg.h>
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -60,21 +64,35 @@ static BOOL IsADir(const CString& strName)
 // CShellExt
 
 IMPLEMENT_DYNCREATE(CShellExt, CCmdTarget)
+#define REG_CLIENT_PARMS_KEY    "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
+#define OVERLAYENABLED 1
 
 CShellExt::CShellExt()
 {
+       HKEY NPKey;
        EnableAutomation();
        nCMRefCount++;
        HRESULT hr;
+       UINT code;
+       DWORD ShellOption,LSPsize,LSPtype;
        hr = SHGetMalloc(&m_pAlloc);
+       m_bIsOverlayEnabled=FALSE;
        if (FAILED(hr))
                m_pAlloc = NULL;
+       RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,0, KEY_QUERY_VALUE, &NPKey);
+       LSPsize=sizeof(ShellOption);
+       code=RegQueryValueEx(NPKey, "ShellOption", NULL,
+                            &LSPtype, (LPBYTE)&ShellOption, &LSPsize);
+       RegCloseKey (NPKey);
+       m_bIsOverlayEnabled=((code==0) && (LSPtype==REG_DWORD) && ((ShellOption & OVERLAYENABLED)!=0));
+       TRACE("Create CShellExt, Ref count %d/n",nCMRefCount);
 }
 
 CShellExt::~CShellExt()
 {
        if(m_pAlloc) m_pAlloc->Release();
        nCMRefCount--;
+       TRACE("Destroy CShellExt, Ref count %d/n",nCMRefCount);
 }
 
 
@@ -105,9 +123,17 @@ END_DISPATCH_MAP()
 //  from VBA.  This IID must match the GUID that is attached to the 
 //  dispinterface in the .ODL file.
 
+#ifndef _WIN64
+// 32-bit
 // {DC515C27-6CAC-11D1-BAE7-00C04FD140D2}
 static const IID IID_IShellExt =
 { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } };
+#else
+// 64-bit
+// {5f820ca1-3dde-11db-b2ce-001558092db5}
+static const IID IID_IShellExt =
+{ 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb5 } };
+#endif
 
 BEGIN_INTERFACE_MAP(CShellExt, CCmdTarget)
        INTERFACE_PART(CShellExt, IID_IShellExt, Dispatch)
@@ -118,7 +144,13 @@ BEGIN_INTERFACE_MAP(CShellExt, CCmdTarget)
        INTERFACE_PART(CShellExt, IID_IPersistFile , PersistFileExt)
 END_INTERFACE_MAP()
 
+#ifndef _WIN64
+    // 32-bit
 IMPLEMENT_OLECREATE(CShellExt, STR_EXT_TITLE, 0xdc515c27, 0x6cac, 0x11d1, 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2)
+#else
+    // 64-bit
+IMPLEMENT_OLECREATE(CShellExt, STR_EXT_TITLE, 0x5f820ca1, 0x3dde, 0x11db, 0xb2, 0xce, 0x0, 0x15, 0x58, 0x09, 0x2d, 0xb5)
+#endif
 
 
 /////////////////////////////////////////////////////////////////////////////
@@ -159,7 +191,7 @@ STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,
 
        // Don't add any menu items if we're being asked to deal with this file as a shortcut.
        if (uFlags & CMF_VERBSONLY)
-               return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)0));
+               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);
@@ -209,9 +241,16 @@ STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,
        // Mount Point submenu of the AFS submenu
        HMENU hMountPointMenu = CreatePopupMenu();
        int indexMountPointMenu = 0;
-       ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_SHOW, GetMessageString(IDS_MP_SHOW_ITEM));
-       ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, 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));
+        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));   
@@ -219,8 +258,15 @@ STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,
        ::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));
-       if (pThis->m_bIsSymlink)
-               ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_REMOVE_SYMLINK, GetMessageString(IDS_REMOVE_SYMLINK_ITEM));
+
+    HMENU hSymbolicMenu = CreatePopupMenu();
+       int indexSymbolicMenu = 0;
+    ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_ADD, GetMessageString(IDS_SYMBOLICLINK_ADD));
+    // ::InsertMenu(hSymbolicMenu, indexSymbolicMenu, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_EDIT, GetMessageString(IDS_SYMBOLICLINK_EDIT));
+       // ::EnableMenuItem(hSymbolicMenu,indexSymbolicMenu++,((pThis->m_bIsSymlink)?MF_ENABLED:MF_GRAYED)|MF_BYPOSITION);
+       ::InsertMenu(hSymbolicMenu, indexSymbolicMenu, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_REMOVE, GetMessageString(IDS_SYMBOLICLINK_REMOVE));
+       ::EnableMenuItem(hSymbolicMenu,indexSymbolicMenu++,((pThis->m_bIsSymlink)?MF_ENABLED:MF_GRAYED)|MF_BYPOSITION);
+       ::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
@@ -241,8 +287,8 @@ STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,
        // Add a separator after us
        ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
        
-    return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 
-                       (USHORT)indexAfsMenu + indexVolPartMenu + indexMountPointMenu + indexShellMenu));
+    return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 
+                       (USHORT)indexAfsMenu + indexVolPartMenu + indexMountPointMenu + indexShellMenu + indexSymbolicMenu);
 }
 
 STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
@@ -318,7 +364,8 @@ STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
                                                                                dlg.DoModal();
                                                                        }
                                                                        break;
-               
+
+        /*
                case IDM_SUBMOUNTS_EDIT:        {
                                                                                CSubmountsDlg dlg;
                                                                                dlg.DoModal();
@@ -332,18 +379,56 @@ STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
                                                                                dlg.DoModal();
                                                                        }
                                                                        break;
-               case IDM_REMOVE_SYMLINK:        {
-                                                                               if (files.GetSize()>1)
-                                                                                       break;
-                                                                               int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK);
-                                                                               if (nChoice == IDYES)
-                                                                                       RemoveSymlink(files.GetAt(0));
-                                                                       }
-                                                                       break;
-               default:
-                       ASSERT(FALSE);
-                       Release();
-                   return E_INVALIDARG;
+        */
+       case IDM_SYMBOLICLINK_REMOVE: {
+               if (files.GetSize()>1)
+                       break;
+               CString msg=files.GetAt(0);
+               int i;
+               if ((i=msg.ReverseFind('\\'))>0)
+                       msg=msg.Left(i+1);
+               else if ((i=msg.ReverseFind(':'))>0)
+                       msg=msg.Left(i+1)+"\\";
+               if (!SetCurrentDirectory(msg))
+               {
+                       MessageBeep((UINT)-1);
+                       ShowMessageBox(IDS_UNABLE_TO_SET_CURRENT_DIRECTORY,MB_OK,IDS_UNABLE_TO_SET_CURRENT_DIRECTORY);
+                       break;
+               }
+               msg=files.GetAt(0);
+               if ((i=msg.ReverseFind('\\'))>0||((i=msg.ReverseFind(':'))>0))
+                       msg=msg.Right(msg.GetLength()-i-1);
+               int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK,msg);
+               if (nChoice == IDYES)
+                       RemoveSymlink(files.GetAt(0));
+       }
+               break;
+
+       case IDM_SYMBOLICLINK_ADD: {
+               CString msg=files.GetAt(0);
+               int i;
+               if ((i=msg.ReverseFind('\\'))>0)
+                       msg=msg.Left(i+1);
+               else if ((i=msg.ReverseFind(':'))>0)
+                       msg=msg.Left(i+1)+"\\";
+               CMakeSymbolicLinkDlg dlg;
+               dlg.Setbase(msg);
+               dlg.DoModal();
+       }
+               break;
+               
+       case IDM_REMOVE_SYMLINK:        {
+               if (files.GetSize()>1)
+                       break;
+               int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK);
+               if (nChoice == IDYES)
+                       RemoveSymlink(files.GetAt(0));
+       }
+               break;
+       default:
+               ASSERT(FALSE);
+               Release();
+               return E_INVALIDARG;
        }
 
        Release();
@@ -351,7 +436,7 @@ STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
     return NOERROR;
 }
 
-STDMETHODIMP CShellExt::XMenuExt::GetCommandString(UINT idCmd, UINT uType,
+STDMETHODIMP CShellExt::XMenuExt::GetCommandString(UINT_PTR idCmd, UINT uType,
     UINT* pwReserved, LPSTR pszName, UINT cchMax)
 {
        if (uType != GCS_HELPTEXT)
@@ -399,10 +484,10 @@ STDMETHODIMP CShellExt::XMenuExt::GetCommandString(UINT idCmd, UINT uType,
                case IDM_SERVER_STATUS:         nCmdStrID = ID_SERVER_STATUS;
                                                                        break;
 
-               case IDM_SUBMOUNTS_CREATE:      nCmdStrID = ID_SUBMOUNTS_CREATE;
+               case IDM_SYMBOLICLINK_ADD:      nCmdStrID = ID_SYMBOLICLINK_ADD;
                                                                        break;
                
-               case IDM_SUBMOUNTS_EDIT:        nCmdStrID = ID_SUBMOUNTS_EDIT;
+               case IDM_SYMBOLICLINK_REMOVE:   nCmdStrID = ID_SYMBOLICLINK_REMOVE;
                                                                        break;
 
                case IDM_REMOVE_SYMLINK:        nCmdStrID= ID_REMOVE_SYMLINK;
@@ -462,8 +547,9 @@ STDMETHODIMP CShellExt::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, IDataOb
 
     //  Use the given IDataObject to get a list of filenames (CF_HDROP)
     hres = pdobj->GetData(&fmte, &medium);
-    if (FAILED(hres))
+    if (FAILED(hres)) {
            return E_FAIL;
+    }
 
     int nNumFiles = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0);
        if (nNumFiles == 0)
@@ -500,7 +586,7 @@ STDMETHODIMP CShellExt::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, IDataOb
                }
 
                if (pThis->m_astrFileNames.GetSize() > 0)
-                       hres = S_OK;
+                       hres = NOERROR;
                else
                        hres = E_FAIL;
     }