2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
14 #include "PropVolume.h"
21 #include <afs/param.h>
23 #include <afs/afs_consts.h>
27 #include <sys/types.h>
29 #include "afs_shl_ext.h"
30 #include "shell_ext.h"
31 #include "volume_info.h"
32 #include "set_afs_acl.h"
34 #include "make_mount_point_dlg.h"
36 #include "server_status_dlg.h"
38 #include "submounts_dlg.h"
39 #include "make_symbolic_link_dlg.h"
40 #include <WINNT\afsreg.h>
45 static char THIS_FILE
[] = __FILE__
;
48 #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
51 ULONG nCMRefCount
= 0; // IContextMenu ref count
52 ULONG nSERefCount
= 0; // IShellExtInit ref count
58 #define PCCHAR(str) ((char *)(const char *)str)
59 static char space
[AFS_PIOCTL_MAXSIZE
];
61 static BOOL
IsADir(const CString
& strName
)
65 if (_tstat(strName
, &statbuf
) < 0)
68 return statbuf
.st_mode
& _S_IFDIR
;
71 /////////////////////////////////////////////////////////////////////////////
74 IMPLEMENT_DYNCREATE(CShellExt
, CCmdTarget
)
75 IMPLEMENT_DYNCREATE(CShellExt2
, CCmdTarget
)
76 #define REG_CLIENT_PARMS_KEY "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
77 #define OVERLAYENABLED 1
79 CShellExt::CShellExt()
86 DWORD ShellOption
,LSPsize
,LSPtype
;
88 hr
= SHGetMalloc(&m_pAlloc
);
89 m_bIsOverlayEnabled
=FALSE
;
92 RegOpenKeyEx(HKEY_LOCAL_MACHINE
, AFSREG_CLT_SVC_PARAM_SUBKEY
,0, (IsWow64()?KEY_WOW64_64KEY
:0)|KEY_QUERY_VALUE
, &NPKey
);
93 LSPsize
=sizeof(ShellOption
);
94 code
=RegQueryValueEx(NPKey
, _T("ShellOption"), NULL
,
95 &LSPtype
, (LPBYTE
)&ShellOption
, &LSPsize
);
97 m_bIsOverlayEnabled
=((code
==0) && (LSPtype
==REG_DWORD
) && ((ShellOption
& OVERLAYENABLED
)!=0));
99 INITCOMMONCONTROLSEX used
= {
100 sizeof(INITCOMMONCONTROLSEX
),
101 ICC_DATE_CLASSES
| ICC_WIN95_CLASSES
| ICC_BAR_CLASSES
| ICC_USEREX_CLASSES
103 InitCommonControlsEx(&used
);
105 TRACE("Create CShellExt, Ref count %d/n",nCMRefCount
);
108 CShellExt::~CShellExt()
113 TRACE("Destroy CShellExt, Ref count %d/n",nCMRefCount
);
117 void CShellExt::OnFinalRelease()
119 // When the last reference for an automation object is released
120 // OnFinalRelease is called. The base class will automatically
121 // deletes the object. Add additional cleanup required for your
122 // object before calling the base class.
124 CCmdTarget::OnFinalRelease();
128 BEGIN_MESSAGE_MAP(CShellExt
, CCmdTarget
)
129 //{{AFX_MSG_MAP(CShellExt)
130 // NOTE - the ClassWizard will add and remove mapping macros here.
134 BEGIN_DISPATCH_MAP(CShellExt
, CCmdTarget
)
135 //{{AFX_DISPATCH_MAP(CShellExt)
136 // NOTE - the ClassWizard will add and remove mapping macros here.
140 // Note: we add support for IID_IShellExt to support typesafe binding
141 // from VBA. This IID must match the GUID that is attached to the
142 // dispinterface in the .ODL file.
146 // {DC515C27-6CAC-11D1-BAE7-00C04FD140D2}
147 static const IID IID_IShellExt
=
148 { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } };
149 static const IID IID_IShellExt2
=
150 { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd3 } };
153 // {5f820ca1-3dde-11db-b2ce-001558092db5}
154 static const IID IID_IShellExt
=
155 { 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb5 } };
156 static const IID IID_IShellExt2
=
157 { 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb6 } };
160 BEGIN_INTERFACE_MAP(CShellExt
, CCmdTarget
)
161 INTERFACE_PART(CShellExt
, IID_IShellExt
, Dispatch
)
162 INTERFACE_PART(CShellExt
, IID_IContextMenu
, MenuExt
)
163 INTERFACE_PART(CShellExt
, IID_IShellExtInit
, ShellInit
)
164 INTERFACE_PART(CShellExt
, IID_IShellIconOverlayIdentifier
, IconExt
)
165 INTERFACE_PART(CShellExt
, IID_IQueryInfo
, ToolTipExt
)
166 INTERFACE_PART(CShellExt
, IID_IPersistFile
, PersistFileExt
)
167 INTERFACE_PART(CShellExt
, IID_IShellPropSheetExt
, PropertySheetExt
)
172 IMPLEMENT_OLECREATE(CShellExt
, _STR_EXT_TITLE
, 0xdc515c27, 0x6cac, 0x11d1, 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2)
173 IMPLEMENT_OLECREATE(CShellExt2
, _STR_EXT_TITLE
, 0xdc515c27, 0x6cac, 0x11d1, 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd3)
176 IMPLEMENT_OLECREATE(CShellExt
, _STR_EXT_TITLE
, 0x5f820ca1, 0x3dde, 0x11db, 0xb2, 0xce, 0x0, 0x15, 0x58, 0x09, 0x2d, 0xb5)
177 IMPLEMENT_OLECREATE(CShellExt2
, _STR_EXT_TITLE
, 0x5f820ca1, 0x3dde, 0x11db, 0xb2, 0xce, 0x0, 0x15, 0x58, 0x09, 0x2d, 0xb6)
181 /////////////////////////////////////////////////////////////////////////////
182 // CShellExt message handlers
183 /////////////////////////////////////////////////////////////////////////////
186 /////////////////////////////////////////////////////////////////////////////
187 // IUnknown for IContextMenu
188 /////////////////////////////////////////////////////////////////////////////
189 STDMETHODIMP
CShellExt::XMenuExt::QueryInterface(REFIID riid
, void** ppv
)
191 METHOD_PROLOGUE(CShellExt
, MenuExt
);
193 return pThis
->ExternalQueryInterface(&riid
, ppv
);
196 STDMETHODIMP_(ULONG
) CShellExt::XMenuExt::AddRef(void)
198 return ++nCMRefCount
;
201 STDMETHODIMP_(ULONG
) CShellExt::XMenuExt::Release(void)
209 /////////////////////////////////////////////////////////////////////////////
210 // IConextMenu Functions
211 /////////////////////////////////////////////////////////////////////////////
212 STDMETHODIMP
CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu
,UINT indexMenu
,
213 UINT idCmdFirst
, UINT idCmdLast
,UINT uFlags
)
215 METHOD_PROLOGUE(CShellExt
, MenuExt
);
217 // Don't add any menu items if we're being asked to deal with this file as a shortcut.
218 if (uFlags
& CMF_VERBSONLY
)
219 return MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, (USHORT
)0);
221 if (!pThis
->m_bIsPathInAFS
)
222 return MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, (USHORT
)0);
224 // Check to see if there's already an AFS menu here; if so, remove it
225 int nItemsNow
= GetMenuItemCount (hMenu
);
226 CString strAfsItemText
= GetMessageString(IDS_AFS_ITEM
);
227 CString strDeleteText
= GetMessageString(IDS_MENU_DELETE
);
228 CString strCutText
= GetMessageString(IDS_MENU_CUT
);
229 LPCTSTR pszAfsItemText
= (LPCTSTR
)strAfsItemText
;
230 for (int iItem
= 0; iItem
< nItemsNow
; iItem
++) {
231 TCHAR szItemText
[256];
232 if (!GetMenuString (hMenu
, iItem
, szItemText
, 256, MF_BYPOSITION
))
234 if (lstrcmp (szItemText
, pszAfsItemText
)==0) {
235 DeleteMenu (hMenu
, iItem
, MF_BYPOSITION
);
238 if (((lstrcmp(szItemText
,strDeleteText
)==0)||(lstrcmp(szItemText
,strCutText
)==0))&&((pThis
->m_bIsSymlink
)||(pThis
->m_bIsMountpoint
))) {
239 DeleteMenu (hMenu
, iItem
, MF_BYPOSITION
);
243 int indexShellMenu
= 0;
245 // Create the AFS submenu using the allowed ID's.
246 HMENU hAfsMenu
= CreatePopupMenu();
247 int indexAfsMenu
= 0;
249 // Only enable the ACL menu item if a single directory is selected
250 int nSingleDirOnly
= MF_GRAYED
;
251 if (pThis
->m_bDirSelected
&& (pThis
->m_astrFileNames
.GetSize() == 1))
252 nSingleDirOnly
= MF_ENABLED
;
253 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
| nSingleDirOnly
, idCmdFirst
+ IDM_ACL_SET
, GetMessageString(IDS_ACLS_ITEM
));
255 // Volume/Partition submenu of the AFS submenu
256 HMENU hVolPartMenu
= CreatePopupMenu();
257 int indexVolPartMenu
= 0;
258 ::InsertMenu(hVolPartMenu
, indexVolPartMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_VOLUME_PROPERTIES
, GetMessageString(IDS_VOL_PART_PROPS_ITEM
));
259 ::InsertMenu(hVolPartMenu
, indexVolPartMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE
, GetMessageString(IDS_VOL_PART_REFRESH_ITEM
));
260 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
| MF_POPUP
, (UINT
)hVolPartMenu
, GetMessageString(IDS_VOL_PART_ITEM
));
262 // Mount Point submenu of the AFS submenu
263 HMENU hMountPointMenu
= CreatePopupMenu();
264 int indexMountPointMenu
= 0;
265 int nMountPointSelected
= MF_GRAYED
;
266 for (int n
= pThis
->m_astrFileNames
.GetSize() - 1 ; n
>= 0; n
--) {
267 if ( IsMountPoint(pThis
->m_astrFileNames
[n
]) ) {
268 nMountPointSelected
= MF_ENABLED
;
272 ::InsertMenu(hMountPointMenu
, indexMountPointMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_MOUNTPOINT_SHOW
, GetMessageString(IDS_MP_SHOW_ITEM
));
273 ::InsertMenu(hMountPointMenu
, indexMountPointMenu
++, MF_STRING
| MF_BYPOSITION
| nMountPointSelected
, idCmdFirst
+ IDM_MOUNTPOINT_REMOVE
, GetMessageString(IDS_MP_REMOVE_ITEM
));
274 ::InsertMenu(hMountPointMenu
, indexMountPointMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_MOUNTPOINT_MAKE
, GetMessageString(IDS_MP_MAKE_ITEM
));
275 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
| MF_POPUP
, (UINT
)hMountPointMenu
, GetMessageString(IDS_MOUNT_POINT_ITEM
));
277 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_FLUSH
, GetMessageString(IDS_FLUSH_FILE_DIR_ITEM
));
278 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_FLUSH_VOLUME
, GetMessageString(IDS_FLUSH_VOLUME_ITEM
));
279 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_SHOW_SERVER
, GetMessageString(IDS_SHOW_FILE_SERVERS_ITEM
));
280 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_SHOWCELL
, GetMessageString(IDS_SHOW_CELL_ITEM
));
281 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_SERVER_STATUS
, GetMessageString(IDS_SHOW_SERVER_STATUS_ITEM
));
283 HMENU hSymbolicMenu
= CreatePopupMenu();
284 int indexSymbolicMenu
= 0;
285 int nSymlinkSelected
= MF_GRAYED
;
286 for (int n
= pThis
->m_astrFileNames
.GetSize() - 1 ; n
>= 0; n
--) {
287 if ( IsSymlink(pThis
->m_astrFileNames
[n
]) ) {
288 nSymlinkSelected
= MF_ENABLED
;
293 ::InsertMenu(hSymbolicMenu
, indexSymbolicMenu
++, MF_STRING
| MF_BYPOSITION
, idCmdFirst
+ IDM_SYMBOLICLINK_ADD
, GetMessageString(IDS_SYMBOLICLINK_ADD
));
294 ::InsertMenu(hSymbolicMenu
, indexSymbolicMenu
++, MF_STRING
| MF_BYPOSITION
| nSymlinkSelected
, idCmdFirst
+ IDM_SYMBOLICLINK_SHOW
, GetMessageString(IDS_SYMBOLICLINK_SHOW
));
295 ::InsertMenu(hSymbolicMenu
, indexSymbolicMenu
++, MF_STRING
| MF_BYPOSITION
| nSymlinkSelected
, idCmdFirst
+ IDM_SYMBOLICLINK_REMOVE
, GetMessageString(IDS_SYMBOLICLINK_REMOVE
));
296 ::InsertMenu(hAfsMenu
, indexAfsMenu
++, MF_STRING
| MF_BYPOSITION
| MF_POPUP
, (UINT
)hSymbolicMenu
, GetMessageString(IDS_SYMBOLIC_LINK_ITEM
));
298 // The Submounts menu has been removed because the AFS tray icon
299 // and control panel now support mapping drives directly to an AFS
302 //HMENU hSubmountMenu = CreatePopupMenu();
303 //int indexSubmountMenu = 0;
304 //::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_SUBMOUNTS_CREATE, GetMessageString(IDS_SUBMOUNTS_CREATE_ITEM));
305 //::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SUBMOUNTS_EDIT, GetMessageString(IDS_SUBMOUNTS_EDIT_ITEM));
306 //::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSubmountMenu, GetMessageString(IDS_SUBMOUNTS_ITEM));
309 ::InsertMenu (hMenu
, indexMenu
+ indexShellMenu
++, MF_STRING
| MF_BYPOSITION
| MF_SEPARATOR
, 0, TEXT(""));
311 // Add the AFS submenu to the shell's menu
312 ::InsertMenu(hMenu
, indexMenu
+ indexShellMenu
++, MF_STRING
| MF_BYPOSITION
| MF_POPUP
, (UINT
)hAfsMenu
, GetMessageString(IDS_AFS_ITEM
));
314 // Add a separator after us
315 ::InsertMenu (hMenu
, indexMenu
+ indexShellMenu
++, MF_STRING
| MF_BYPOSITION
| MF_SEPARATOR
, 0, TEXT(""));
317 return MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
,
318 (USHORT
)indexAfsMenu
+ indexVolPartMenu
+ indexMountPointMenu
+ indexShellMenu
+ indexSymbolicMenu
);
321 STDMETHODIMP
CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici
)
323 METHOD_PROLOGUE(CShellExt
, MenuExt
);
325 if (HIWORD(lpici
->lpVerb
))
330 CStringArray
&files
= pThis
->m_astrFileNames
;
332 switch (LOWORD(lpici
->lpVerb
))
334 case IDM_AUTHENTICATION
: {
342 ASSERT(files
.GetSize() == 1);
343 dlg
.SetDir(files
[0]);
348 case IDM_VOLUME_PROPERTIES
: {
355 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE
:
359 case IDM_MOUNTPOINT_SHOW
:
363 case IDM_MOUNTPOINT_REMOVE
: {
364 int nChoice
= ShowMessageBox(IDS_REALLY_DEL_MOUNT_POINTS
, MB_ICONQUESTION
| MB_YESNO
, IDS_REALLY_DEL_MOUNT_POINTS
);
365 if (nChoice
== IDYES
)
370 case IDM_MOUNTPOINT_MAKE
: {
371 CMakeMountPointDlg dlg
;
372 ASSERT(files
.GetSize() == 1);
373 dlg
.SetDir(files
[0]);
382 case IDM_FLUSH_VOLUME
:
386 case IDM_SHOW_SERVER
:
394 case IDM_SERVER_STATUS
: {
395 CServerStatusDlg dlg
;
401 case IDM_SUBMOUNTS_EDIT: {
406 case IDM_SUBMOUNTS_CREATE: {
407 ASSERT(files.GetSize() == 1);
409 dlg.SetAddOnlyMode(files[0]);
414 case IDM_SYMBOLICLINK_REMOVE
: {
415 if (files
.GetSize()>1)
417 CString msg
=files
.GetAt(0);
419 if ((i
=msg
.ReverseFind('\\'))>0)
421 else if ((i
=msg
.ReverseFind(':'))>0)
422 msg
=msg
.Left(i
+1)+"\\";
423 if (!SetCurrentDirectory(msg
))
425 MessageBeep((UINT
)-1);
426 ShowMessageBox(IDS_UNABLE_TO_SET_CURRENT_DIRECTORY
,MB_OK
,IDS_UNABLE_TO_SET_CURRENT_DIRECTORY
);
430 if ((i
=msg
.ReverseFind('\\'))>0||((i
=msg
.ReverseFind(':'))>0))
431 msg
=msg
.Right(msg
.GetLength()-i
-1);
432 int nChoice
= ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK
, MB_ICONQUESTION
| MB_YESNO
, IDS_REALLY_REMOVE_SYMLINK
,msg
);
433 if (nChoice
== IDYES
)
434 RemoveSymlink(files
.GetAt(0));
438 case IDM_SYMBOLICLINK_ADD
: {
439 CStringA
msg(files
.GetAt(0));
441 if ((i
=msg
.ReverseFind('\\'))>0)
443 else if ((i
=msg
.ReverseFind(':'))>0)
444 msg
=msg
.Left(i
+1)+"\\";
445 CMakeSymbolicLinkDlg dlg
;
451 case IDM_SYMBOLICLINK_SHOW
:
455 case IDM_REMOVE_SYMLINK
: {
456 if (files
.GetSize()>1)
458 int nChoice
= ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK
, MB_ICONQUESTION
| MB_YESNO
, IDS_REALLY_REMOVE_SYMLINK
);
459 if (nChoice
== IDYES
)
460 RemoveSymlink(files
.GetAt(0));
474 STDMETHODIMP
CShellExt::XMenuExt::GetCommandString(UINT_PTR idCmd
, UINT uType
,
475 UINT
* pwReserved
, LPSTR pszName
, UINT cchMax
)
477 if (uType
!= GCS_HELPTEXT
)
478 return NOERROR
; // ?????????????????????????????????????????????????
482 AfxSetResourceHandle(theApp
.m_hInstance
);
486 case IDM_AUTHENTICATION
:
487 nCmdStrID
= ID_AUTHENTICATE
;
491 nCmdStrID
= ID_ACL_SET
;
494 case IDM_VOLUME_PROPERTIES
:
495 nCmdStrID
= ID_VOLUME_PROPERTIES
;
498 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE
:
499 nCmdStrID
= ID_VOLUMEPARTITION_UPDATENAMEIDTABLE
;
502 case IDM_MOUNTPOINT_SHOW
:
503 nCmdStrID
= ID_MOUNTPOINT_SHOW
;
506 case IDM_MOUNTPOINT_REMOVE
:
507 nCmdStrID
= ID_MOUNTPOINT_REMOVE
;
510 case IDM_MOUNTPOINT_MAKE
:
511 nCmdStrID
= ID_MOUNTPOINT_MAKE
;
515 nCmdStrID
= ID_FLUSH
;
518 case IDM_FLUSH_VOLUME
:
519 nCmdStrID
= ID_VOLUME_FLUSH
;
522 case IDM_SHOW_SERVER
:
523 nCmdStrID
= ID_WHEREIS
;
527 nCmdStrID
= ID_SHOWCELL
;
530 case IDM_SERVER_STATUS
:
531 nCmdStrID
= ID_SERVER_STATUS
;
534 case IDM_SYMBOLICLINK_ADD
:
535 nCmdStrID
= ID_SYMBOLICLINK_ADD
;
538 case IDM_SYMBOLICLINK_SHOW
:
539 nCmdStrID
= ID_SYMBOLICLINK_SHOW
;
542 case IDM_SYMBOLICLINK_REMOVE
:
543 nCmdStrID
= ID_SYMBOLICLINK_REMOVE
;
546 case IDM_REMOVE_SYMLINK
:
547 nCmdStrID
= ID_REMOVE_SYMLINK
;
557 LoadString (strMsg
, nCmdStrID
);
559 _tcsncpy((LPTSTR
) pszName
, strMsg
, cchMax
);
564 /////////////////////////////////////////////////////////////////////////////
565 // IUnknown for IShellExtInit
566 /////////////////////////////////////////////////////////////////////////////
567 STDMETHODIMP
CShellExt::XShellInit::QueryInterface(REFIID riid
, void** ppv
)
569 METHOD_PROLOGUE(CShellExt
, ShellInit
);
571 return pThis
->ExternalQueryInterface(&riid
, ppv
);
574 STDMETHODIMP_(ULONG
) CShellExt::XShellInit::AddRef(void)
576 return ++nSERefCount
;
579 STDMETHODIMP_(ULONG
) CShellExt::XShellInit::Release(void)
587 /////////////////////////////////////////////////////////////////////////////
588 // IShellInit Functions
589 /////////////////////////////////////////////////////////////////////////////
590 STDMETHODIMP
CShellExt::XShellInit::Initialize(LPCITEMIDLIST pidlFolder
, IDataObject
*pdobj
, HKEY hkeyProgID
)
592 METHOD_PROLOGUE(CShellExt
, ShellInit
);
594 HRESULT hres
= E_FAIL
;
595 FORMATETC fmte
= {CF_HDROP
, NULL
, DVASPECT_CONTENT
, -1, TYMED_HGLOBAL
};
598 // We must have a data object
599 if ((pdobj
== NULL
) && (pidlFolder
== NULL
))
602 pThis
->m_bIsSymlink
=false;
603 pThis
->m_bIsMountpoint
=false;
604 pThis
->m_bIsPathInAFS
=false;
605 pThis
->m_bDirSelected
=false;
608 // Use the given IDataObject to get a list of filenames (CF_HDROP)
609 hres
= pdobj
->GetData(&fmte
, &medium
);
614 int nNumFiles
= DragQueryFile((HDROP
)medium
.hGlobal
, 0xFFFFFFFF, NULL
, 0);
618 pThis
->m_bDirSelected
= FALSE
;
620 for (int ii
= 0; ii
< nNumFiles
; ii
++) {
623 // Get the size of the file name string
624 int nNameLen
= DragQueryFile((HDROP
)medium
.hGlobal
, ii
, 0, 0);
626 // Make room for it in our string object
627 LPTSTR pszFileNameBuf
= strFileName
.GetBuffer(nNameLen
+ 1); // +1 for the terminating NULL
628 ASSERT(pszFileNameBuf
);
631 DragQueryFile((HDROP
)medium
.hGlobal
, ii
, pszFileNameBuf
, nNameLen
+ 1);
633 strFileName
.ReleaseBuffer();
634 if (!IsPathInAfs(strFileName
)) {
635 pThis
->m_astrFileNames
.RemoveAll();
636 pThis
->m_bIsPathInAFS
=false;
639 pThis
->m_bIsSymlink
=pThis
->m_bIsSymlink
||IsSymlink(strFileName
);
640 pThis
->m_bIsMountpoint
=pThis
->m_bIsMountpoint
||IsMountPoint(strFileName
);
641 pThis
->m_bIsPathInAFS
=true;
644 if (IsADir(strFileName
))
645 pThis
->m_bDirSelected
= TRUE
;
647 pThis
->m_astrFileNames
.Add(strFileName
);
650 ReleaseStgMedium(&medium
);
653 if ((pThis
->m_astrFileNames
.GetSize() == 0)&&(pidlFolder
)) {
654 // if there are no valid files selected, try the folder background
655 IShellFolder
*parentFolder
= NULL
;
657 TCHAR
* szDisplayName
= NULL
;
659 hres
= ::SHGetDesktopFolder(&parentFolder
);
663 hres
= parentFolder
->GetDisplayNameOf(pidlFolder
, SHGDN_NORMAL
| SHGDN_FORPARSING
, &name
);
665 parentFolder
->Release();
669 hres
= StrRetToStr (&name
, pidlFolder
, &szDisplayName
);
672 parentFolder
->Release();
674 pThis
->m_bDirSelected
= TRUE
;
675 CString strFileName
= CString(szDisplayName
);
676 if (IsPathInAfs(strFileName
)) {
677 pThis
->m_bIsSymlink
=IsSymlink(strFileName
);
678 pThis
->m_bIsMountpoint
=IsMountPoint(strFileName
);
679 pThis
->m_bIsPathInAFS
=true;
680 pThis
->m_astrFileNames
.Add(strFileName
);
682 CoTaskMemFree(szDisplayName
);
685 if (pThis
->m_astrFileNames
.GetSize() > 0)
693 STDMETHODIMP
CShellExt::XIconExt::QueryInterface(REFIID riid
, void** ppv
)
695 METHOD_PROLOGUE(CShellExt
, IconExt
);
696 return pThis
->ExternalQueryInterface(&riid
, ppv
);
699 STDMETHODIMP_(ULONG
) CShellExt::XIconExt::AddRef(void)
701 return ++nICRefCount
;
704 STDMETHODIMP_(ULONG
) CShellExt::XIconExt::Release(void)
713 /////////////////////////////////////////////////////////////////////////////
714 // IIconHandler Functions
715 /////////////////////////////////////////////////////////////////////////////
717 STDMETHODIMP
CShellExt::XIconExt::GetOverlayInfo(LPWSTR pwszIconFile
718 ,int cchMax
,int* pIndex
,DWORD
* pdwFlags
)
720 METHOD_PROLOGUE(CShellExt
, IconExt
);
721 if(IsBadWritePtr(pIndex
, sizeof(int)))
723 if(IsBadWritePtr(pdwFlags
, sizeof(DWORD
)))
726 // The icons must reside in the same path as this dll
727 TCHAR szModule
[MAX_PATH
];
728 GetModuleFileName(theApp
.m_hInstance
, szModule
, MAX_PATH
);
729 TCHAR
* slash
= _tcsrchr(szModule
, '\\');
732 switch (pThis
->GetOverlayObject())
735 _tcscat(szModule
, _T("\\link.ico"));
738 _tcscat(szModule
, _T("\\mount.ico"));
743 MultiByteToWideChar( CP_ACP
,0,szModule
,-1,pwszIconFile
,cchMax
);
745 _tcsncpy(pwszIconFile
, szModule
, cchMax
);
748 *pdwFlags
= ISIOI_ICONFILE
;
752 STDMETHODIMP
CShellExt::XIconExt::GetPriority(int* pPriority
)
754 if(IsBadWritePtr(pPriority
, sizeof(int)))
760 STDMETHODIMP
CShellExt::XIconExt::IsMemberOf(LPCWSTR pwszPath
,DWORD dwAttrib
)
762 METHOD_PROLOGUE(CShellExt
, IconExt
);
763 TCHAR szPath
[MAX_PATH
];
765 _tcscpy(szPath
, pwszPath
);
767 WideCharToMultiByte( CP_ACP
,0,pwszPath
,-1,szPath
,MAX_PATH
,NULL
,NULL
);
769 if (!IsPathInAfs(szPath
))
772 if ((pThis
->GetOverlayObject() == 0)&&(IsSymlink(szPath
))) {
775 if ((pThis
->GetOverlayObject() == 1)&&(IsMountPoint(szPath
))) {
781 /* TOOL TIP INFO IMPLIMENTION */
783 STDMETHODIMP
CShellExt::XToolTipExt::QueryInterface(REFIID riid
, void** ppv
)
785 METHOD_PROLOGUE(CShellExt
, ToolTipExt
);
786 return pThis
->ExternalQueryInterface(&riid
, ppv
);
789 STDMETHODIMP_(ULONG
) CShellExt::XToolTipExt::AddRef(void)
791 return ++nTPRefCount
;
794 STDMETHODIMP_(ULONG
) CShellExt::XToolTipExt::Release(void)
802 STDMETHODIMP
CShellExt::XToolTipExt::GetInfoTip(DWORD dwFlags
, LPWSTR
*ppwszTip
)
804 METHOD_PROLOGUE(CShellExt
, ToolTipExt
);
806 if ((_tcslen(pThis
->m_szFile
) == 0)||(!IsPathInAfs(pThis
->m_szFile
)))
811 bool bIsSymlink
= !!IsSymlink(pThis
->m_szFile
);
812 bool bIsMountpoint
= !!IsMountPoint(pThis
->m_szFile
);
813 if ((!bIsSymlink
) && (!bIsMountpoint
))
819 // dwFlags is currently unused.
822 sInfo
= GetSymlink(pThis
->m_szFile
);
823 else if (bIsMountpoint
)
824 sInfo
= GetMountpoint(pThis
->m_szFile
);
825 *ppwszTip
= (WCHAR
*) (pThis
->m_pAlloc
)->Alloc((1+sInfo
.GetLength())*sizeof(WCHAR
));
827 wcscpy(*ppwszTip
, (WCHAR
*)T2COLE((LPCTSTR
)sInfo
));
831 STDMETHODIMP
CShellExt::XToolTipExt::GetInfoFlags(LPDWORD pdwFlags
)
837 ////////// IPersistFile
838 /////// PersistFileExt
840 STDMETHODIMP
CShellExt::XPersistFileExt::QueryInterface(REFIID riid
, void** ppv
)
842 METHOD_PROLOGUE(CShellExt
, PersistFileExt
);
843 return pThis
->ExternalQueryInterface(&riid
, ppv
);
846 STDMETHODIMP_(ULONG
) CShellExt::XPersistFileExt::AddRef(void)
848 return ++nXPRefCount
;
851 STDMETHODIMP_(ULONG
) CShellExt::XPersistFileExt::Release(void)
859 STDMETHODIMP
CShellExt::XPersistFileExt::Load(LPCOLESTR wszFile
, DWORD dwMode
)
861 METHOD_PROLOGUE(CShellExt
, PersistFileExt
);
863 _tcscpy(pThis
->m_szFile
, OLE2T((WCHAR
*)wszFile
));
867 STDMETHODIMP
CShellExt::XPersistFileExt::GetClassID(LPCLSID
)
872 STDMETHODIMP
CShellExt::XPersistFileExt::IsDirty(VOID
)
877 STDMETHODIMP
CShellExt::XPersistFileExt::Save(LPCOLESTR
, BOOL
)
882 STDMETHODIMP
CShellExt::XPersistFileExt::SaveCompleted(LPCOLESTR
)
887 STDMETHODIMP
CShellExt::XPersistFileExt::GetCurFile(LPOLESTR FAR
*)
892 // IShellPropSheetExt
893 STDMETHODIMP
CShellExt::XPropertySheetExt::QueryInterface(REFIID riid
, void** ppv
)
895 METHOD_PROLOGUE(CShellExt
, PropertySheetExt
);
896 return pThis
->ExternalQueryInterface(&riid
, ppv
);
899 STDMETHODIMP_(ULONG
) CShellExt::XPropertySheetExt::AddRef(void)
901 return ++nPSRefCount
;
904 STDMETHODIMP_(ULONG
) CShellExt::XPropertySheetExt::Release(void)
912 BOOL CALLBACK
PageProc (HWND hwnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
914 PropertyPage
* sheetpage
;
916 if (uMessage
== WM_INITDIALOG
)
918 sheetpage
= (PropertyPage
*) ((LPPROPSHEETPAGE
) lParam
)->lParam
;
919 SetWindowLongPtr (hwnd
, GWLP_USERDATA
, (LONG_PTR
) sheetpage
);
920 sheetpage
->SetHwnd(hwnd
);
924 sheetpage
= (PropertyPage
*) GetWindowLongPtr (hwnd
, GWLP_USERDATA
);
928 return sheetpage
->PropPageProc(hwnd
, uMessage
, wParam
, lParam
);
933 UINT CALLBACK
PropPageCallbackProc ( HWND
/*hwnd*/, UINT uMsg
, LPPROPSHEETPAGE ppsp
)
935 // Delete the page before closing.
936 if (PSPCB_CREATE
== uMsg
)
938 if (PSPCB_RELEASE
== uMsg
)
940 PropertyPage
* sheetpage
= (PropertyPage
*) ppsp
->lParam
;
946 STDMETHODIMP
CShellExt::XPropertySheetExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage
, LPARAM lParam
)
948 METHOD_PROLOGUE(CShellExt
, PropertySheetExt
);
950 if(pThis
->m_bIsPathInAFS
) {
951 // add the property page for files/folder/mount points/symlinks
953 SecureZeroMemory(&psp
, sizeof(PROPSHEETPAGE
));
954 HPROPSHEETPAGE hPage
;
955 CPropFile
*filesheet
= NULL
;
956 CPropVolume
*volsheet
= NULL
;
957 CPropACL
* aclsheet
= NULL
;
959 filesheet
= new CPropFile(pThis
->m_astrFileNames
);
961 if (filesheet
== NULL
)
962 return E_OUTOFMEMORY
;
965 TaLocale_GetResource(RT_DIALOG
, MAKEINTRESOURCE(IDD_PROPPAGE_FILE
), LANG_USER_DEFAULT
, &hInst
);
966 filesheet
->m_hInst
= hInst
;
967 filesheet
->m_bIsMountpoint
= pThis
->m_bIsMountpoint
;
968 filesheet
->m_bIsSymlink
= pThis
->m_bIsSymlink
;
969 filesheet
->m_bIsDir
= pThis
->m_bDirSelected
;
970 psp
.dwSize
= sizeof (psp
);
971 psp
.dwFlags
= PSP_USEREFPARENT
| PSP_USETITLE
| PSP_USECALLBACK
| PSP_USETITLE
;
972 psp
.hInstance
= hInst
;
973 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_PROPPAGE_FILE
);
975 psp
.pszTitle
= _T("AFS");
976 psp
.pfnDlgProc
= (DLGPROC
) PageProc
;
977 psp
.lParam
= (LPARAM
) filesheet
;
978 psp
.pfnCallback
= PropPageCallbackProc
;
979 psp
.pcRefParent
= (UINT
*) &nPSRefCount
;
981 hPage
= CreatePropertySheetPage (&psp
);
984 if (!lpfnAddPage (hPage
, lParam
)) {
986 DestroyPropertySheetPage (hPage
);
990 // add the property page for Volume Data
991 SecureZeroMemory(&psp
, sizeof(PROPSHEETPAGE
));
992 volsheet
= new CPropVolume(pThis
->m_astrFileNames
);
993 if (volsheet
== NULL
)
994 return E_OUTOFMEMORY
;
997 TaLocale_GetResource(RT_DIALOG
, MAKEINTRESOURCE(IDD_PROPPAGE_VOLUME
), LANG_USER_DEFAULT
, &hInst
);
998 volsheet
->m_hInst
= hInst
;
999 volsheet
->m_bIsMountpoint
= pThis
->m_bIsMountpoint
;
1000 volsheet
->m_bIsSymlink
= pThis
->m_bIsSymlink
;
1001 volsheet
->m_bIsDir
= pThis
->m_bDirSelected
;
1002 psp
.dwSize
= sizeof (psp
);
1003 psp
.dwFlags
= PSP_USEREFPARENT
| PSP_USETITLE
| PSP_USECALLBACK
| PSP_USETITLE
;
1004 psp
.hInstance
= hInst
;
1005 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_PROPPAGE_VOLUME
);
1007 psp
.pszTitle
= _T("AFS Volume");
1008 psp
.pfnDlgProc
= (DLGPROC
) PageProc
;
1009 psp
.lParam
= (LPARAM
) volsheet
;
1010 psp
.pfnCallback
= PropPageCallbackProc
;
1011 psp
.pcRefParent
= (UINT
*) &nPSRefCount
;
1013 hPage
= CreatePropertySheetPage (&psp
);
1015 if (hPage
!= NULL
) {
1016 if (!lpfnAddPage (hPage
, lParam
)) {
1018 DestroyPropertySheetPage (hPage
);
1022 if(pThis
->m_bDirSelected
) {
1023 // add the property page for ACLs
1024 SecureZeroMemory(&psp
, sizeof(PROPSHEETPAGE
));
1026 aclsheet
= new CPropACL(pThis
->m_astrFileNames
);
1027 if (aclsheet
== NULL
)
1028 return E_OUTOFMEMORY
;
1031 TaLocale_GetResource(RT_DIALOG
, MAKEINTRESOURCE(IDD_PROPPAGE_ACL
), LANG_USER_DEFAULT
, &hInst
);
1032 aclsheet
->m_hInst
= hInst
;
1033 aclsheet
->m_bIsMountpoint
= pThis
->m_bIsMountpoint
;
1034 aclsheet
->m_bIsSymlink
= pThis
->m_bIsSymlink
;
1035 aclsheet
->m_bIsDir
= pThis
->m_bDirSelected
;
1036 psp
.dwSize
= sizeof (psp
);
1037 psp
.dwFlags
= PSP_USEREFPARENT
| PSP_USETITLE
| PSP_USECALLBACK
| PSP_USETITLE
;
1038 psp
.hInstance
= hInst
;
1039 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_PROPPAGE_ACL
);
1041 psp
.pszTitle
= _T("AFS ACL");
1042 psp
.pfnDlgProc
= (DLGPROC
) PageProc
;
1043 psp
.lParam
= (LPARAM
) aclsheet
;
1044 psp
.pfnCallback
= PropPageCallbackProc
;
1045 psp
.pcRefParent
= (UINT
*) &nPSRefCount
;
1047 hPage
= CreatePropertySheetPage (&psp
);
1049 if (hPage
!= NULL
) {
1050 if (!lpfnAddPage (hPage
, lParam
)) {
1052 DestroyPropertySheetPage (hPage
);
1061 STDMETHODIMP
CShellExt::XPropertySheetExt::ReplacePage(UINT uPageID
, LPFNADDPROPSHEETPAGE pfnReplacePage
, LPARAM lParam
)