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
11 #include <afs/param.h>
18 #include <sys/types.h>
20 #include "afs_shl_ext.h"
21 #include "shell_ext.h"
22 #include "volume_info.h"
23 #include "set_afs_acl.h"
25 #include "make_mount_point_dlg.h"
27 #include "server_status_dlg.h"
29 #include "submounts_dlg.h"
30 #include "make_symbolic_link_dlg.h"
38 static char THIS_FILE[] = __FILE__;
42 ULONG nCMRefCount = 0; // IContextMenu ref count
43 ULONG nSERefCount = 0; // IShellExtInit ref count
48 #define MAXSIZE 2048 /* most I'll get back from PIOCTL */
49 #define PCCHAR(str) ((char *)(const char *)str)
50 static char space[MAXSIZE];
52 static BOOL IsADir(const CString& strName)
56 if (_stat(strName, &statbuf) < 0)
59 return statbuf.st_mode & _S_IFDIR;
62 /////////////////////////////////////////////////////////////////////////////
65 IMPLEMENT_DYNCREATE(CShellExt, CCmdTarget)
66 #define REG_CLIENT_PARMS_KEY "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
67 #define OVERLAYENABLED 1
69 CShellExt::CShellExt()
76 DWORD ShellOption,LSPsize,LSPtype;
77 hr = SHGetMalloc(&m_pAlloc);
78 m_bIsOverlayEnabled=FALSE;
81 RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,0, KEY_QUERY_VALUE, &NPKey);
82 LSPsize=sizeof(ShellOption);
83 code=RegQueryValueEx(NPKey, "ShellOption", NULL,
84 &LSPtype, (LPBYTE)&ShellOption, &LSPsize);
86 m_bIsOverlayEnabled=((code==0) && (LSPtype==REG_DWORD) && ((ShellOption & OVERLAYENABLED)!=0));
87 TRACE("Create CShellExt, Ref count %d/n",nCMRefCount);
90 CShellExt::~CShellExt()
92 if(m_pAlloc) m_pAlloc->Release();
94 TRACE("Destroy CShellExt, Ref count %d/n",nCMRefCount);
98 void CShellExt::OnFinalRelease()
100 // When the last reference for an automation object is released
101 // OnFinalRelease is called. The base class will automatically
102 // deletes the object. Add additional cleanup required for your
103 // object before calling the base class.
105 CCmdTarget::OnFinalRelease();
109 BEGIN_MESSAGE_MAP(CShellExt, CCmdTarget)
110 //{{AFX_MSG_MAP(CShellExt)
111 // NOTE - the ClassWizard will add and remove mapping macros here.
115 BEGIN_DISPATCH_MAP(CShellExt, CCmdTarget)
116 //{{AFX_DISPATCH_MAP(CShellExt)
117 // NOTE - the ClassWizard will add and remove mapping macros here.
121 // Note: we add support for IID_IShellExt to support typesafe binding
122 // from VBA. This IID must match the GUID that is attached to the
123 // dispinterface in the .ODL file.
125 // {DC515C27-6CAC-11D1-BAE7-00C04FD140D2}
126 static const IID IID_IShellExt =
127 { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } };
129 BEGIN_INTERFACE_MAP(CShellExt, CCmdTarget)
130 INTERFACE_PART(CShellExt, IID_IShellExt, Dispatch)
131 INTERFACE_PART(CShellExt, IID_IContextMenu, MenuExt)
132 INTERFACE_PART(CShellExt, IID_IShellExtInit, ShellInit)
133 INTERFACE_PART(CShellExt, IID_IShellIconOverlayIdentifier, IconExt)
134 INTERFACE_PART(CShellExt, IID_IQueryInfo , ToolTipExt)
135 INTERFACE_PART(CShellExt, IID_IPersistFile , PersistFileExt)
138 IMPLEMENT_OLECREATE(CShellExt, STR_EXT_TITLE, 0xdc515c27, 0x6cac, 0x11d1, 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2)
141 /////////////////////////////////////////////////////////////////////////////
142 // CShellExt message handlers
143 /////////////////////////////////////////////////////////////////////////////
146 /////////////////////////////////////////////////////////////////////////////
147 // IUnknown for IContextMenu
148 /////////////////////////////////////////////////////////////////////////////
149 STDMETHODIMP CShellExt::XMenuExt::QueryInterface(REFIID riid, void** ppv)
151 METHOD_PROLOGUE(CShellExt, MenuExt);
153 return pThis->ExternalQueryInterface(&riid, ppv);
156 STDMETHODIMP_(ULONG) CShellExt::XMenuExt::AddRef(void)
158 return ++nCMRefCount;
161 STDMETHODIMP_(ULONG) CShellExt::XMenuExt::Release(void)
169 /////////////////////////////////////////////////////////////////////////////
170 // IConextMenu Functions
171 /////////////////////////////////////////////////////////////////////////////
172 STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,
173 UINT idCmdFirst, UINT idCmdLast,UINT uFlags)
175 METHOD_PROLOGUE(CShellExt, MenuExt);
177 // Don't add any menu items if we're being asked to deal with this file as a shortcut.
178 if (uFlags & CMF_VERBSONLY)
179 return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)0));
181 // Check to see if there's already an AFS menu here; if so, remove it
182 int nItemsNow = GetMenuItemCount (hMenu);
183 CString strAfsItemText = GetMessageString(IDS_AFS_ITEM);
184 LPCTSTR pszAfsItemText = (LPCTSTR)strAfsItemText;
185 for (int iItem = 0; iItem < nItemsNow; iItem++) {
186 TCHAR szItemText[256];
187 if (!GetMenuString (hMenu, iItem, szItemText, 256, MF_BYPOSITION))
189 if (!lstrcmp (szItemText, pszAfsItemText)) {
190 DeleteMenu (hMenu, iItem, MF_BYPOSITION);
193 if ((!lstrcmp(szItemText,"&Delete"))&&(pThis->m_bIsSymlink)) { /*this is a symlink - don't present a delete menu!*/
194 DeleteMenu (hMenu, iItem, MF_BYPOSITION);
197 if ((!lstrcmp(szItemText,"Cu&t"))&&(pThis->m_bIsSymlink)) { /*same for cut*/
198 DeleteMenu (hMenu, iItem, MF_BYPOSITION);
202 int indexShellMenu = 0;
204 // Create the AFS submenu using the allowed ID's.
205 HMENU hAfsMenu = CreatePopupMenu();
206 int indexAfsMenu = 0;
208 // The Authentication item has been removed from the AFS menu because
209 // there is now a tray icon to handle authentication.
211 //::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_AUTHENTICATION, GetMessageString(IDS_AUTHENTICATION_ITEM));
213 // Only enable the ACL menu item if a single directory is selected
214 int nSingleDirOnly = MF_GRAYED;
215 if (pThis->m_bDirSelected && (pThis->m_astrFileNames.GetSize() == 1))
216 nSingleDirOnly = MF_ENABLED;
217 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_ACL_SET, GetMessageString(IDS_ACLS_ITEM));
219 // Volume/Partition submenu of the AFS submenu
220 HMENU hVolPartMenu = CreatePopupMenu();
221 int indexVolPartMenu = 0;
222 ::InsertMenu(hVolPartMenu, indexVolPartMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_VOLUME_PROPERTIES, GetMessageString(IDS_VOL_PART_PROPS_ITEM));
223 ::InsertMenu(hVolPartMenu, indexVolPartMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE, GetMessageString(IDS_VOL_PART_REFRESH_ITEM));
224 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hVolPartMenu, GetMessageString(IDS_VOL_PART_ITEM));
226 // Mount Point submenu of the AFS submenu
227 HMENU hMountPointMenu = CreatePopupMenu();
228 int indexMountPointMenu = 0;
229 ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_SHOW, GetMessageString(IDS_MP_SHOW_ITEM));
230 ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_REMOVE, GetMessageString(IDS_MP_REMOVE_ITEM));
231 ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_MAKE, GetMessageString(IDS_MP_MAKE_ITEM));
232 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hMountPointMenu, GetMessageString(IDS_MOUNT_POINT_ITEM));
234 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_FLUSH, GetMessageString(IDS_FLUSH_FILE_DIR_ITEM));
235 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_FLUSH_VOLUME, GetMessageString(IDS_FLUSH_VOLUME_ITEM));
236 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHOW_SERVER, GetMessageString(IDS_SHOW_FILE_SERVERS_ITEM));
237 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHOWCELL, GetMessageString(IDS_SHOW_CELL_ITEM));
238 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SERVER_STATUS, GetMessageString(IDS_SHOW_SERVER_STATUS_ITEM));
240 HMENU hSymbolicMenu = CreatePopupMenu();
241 int indexSymbolicMenu = 0;
242 ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_ADD, GetMessageString(IDS_SYMBOLICLINK_ADD));
243 // ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_EDIT, GetMessageString(IDS_SYMBOLICLINK_EDIT));
244 ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_REMOVE, GetMessageString(IDS_SYMBOLICLINK_REMOVE));
246 ::EnableMenuItem(hSymbolicMenu,1,((pThis->m_bIsSymlink)?MF_ENABLED:MF_GRAYED)|MF_BYPOSITION);
247 // ::EnableMenuItem(hSymbolicMenu,2,((pThis->m_bIsSymlink)?MF_ENABLED:MF_GRAYED)|MF_BYPOSITION);
248 ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSymbolicMenu, GetMessageString(IDS_SYMBOLIC_LINK_ITEM));
250 // The Submounts menu has been removed because the AFS tray icon
251 // and control panel now support mapping drives directly to an AFS
254 // HMENU hSubmountMenu = CreatePopupMenu();
255 // int indexSubmountMenu = 0;
256 // ::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_SUBMOUNTS_CREATE, GetMessageString(IDS_SUBMOUNTS_CREATE_ITEM));
257 // ::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SUBMOUNTS_EDIT, GetMessageString(IDS_SUBMOUNTS_EDIT_ITEM));
258 // ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSubmountMenu, GetMessageString(IDS_SUBMOUNTS_ITEM));
261 ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
263 // Add the AFS submenu to the shell's menu
264 ::InsertMenu(hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hAfsMenu, GetMessageString(IDS_AFS_ITEM));
266 // Add a separator after us
267 ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
269 return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL,
270 (USHORT)indexAfsMenu + indexVolPartMenu + indexMountPointMenu + indexShellMenu + indexSymbolicMenu));
273 STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
275 METHOD_PROLOGUE(CShellExt, MenuExt);
277 if (HIWORD(lpici->lpVerb ))
282 CStringArray &files = pThis->m_astrFileNames;
284 switch (LOWORD(lpici->lpVerb))
286 case IDM_AUTHENTICATION: {
294 ASSERT(files.GetSize() == 1);
295 dlg.SetDir(files[0]);
300 case IDM_VOLUME_PROPERTIES: {
307 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE: CheckVolumes();
310 case IDM_MOUNTPOINT_SHOW: ListMount(files);
313 case IDM_MOUNTPOINT_REMOVE: {
314 int nChoice = ShowMessageBox(IDS_REALLY_DEL_MOUNT_POINTS, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_DEL_MOUNT_POINTS);
315 if (nChoice == IDYES)
320 case IDM_MOUNTPOINT_MAKE: {
321 CMakeMountPointDlg dlg;
322 ASSERT(files.GetSize() == 1);
323 dlg.SetDir(files[0]);
329 case IDM_FLUSH: Flush(files);
332 case IDM_FLUSH_VOLUME: FlushVolume(files);
335 case IDM_SHOW_SERVER: WhereIs(files);
338 case IDM_SHOWCELL: WhichCell(files);
341 case IDM_SERVER_STATUS: {
342 CServerStatusDlg dlg;
348 case IDM_SUBMOUNTS_EDIT: {
354 case IDM_SUBMOUNTS_CREATE: {
355 ASSERT(files.GetSize() == 1);
357 dlg.SetAddOnlyMode(files[0]);
362 case IDM_SYMBOLICLINK_REMOVE: {
363 if (files.GetSize()>1)
365 CString msg=files.GetAt(0);
367 if ((i=msg.ReverseFind('\\'))>0)
369 else if ((i=msg.ReverseFind(':'))>0)
370 msg=msg.Left(i+1)+"\\";
371 if (!SetCurrentDirectory(msg))
373 MessageBeep((UINT)-1);
374 ShowMessageBox(IDS_UNABLE_TO_SET_CURRENT_DIRECTORY,MB_OK,IDS_UNABLE_TO_SET_CURRENT_DIRECTORY);
378 if ((i=msg.ReverseFind('\\'))>0||((i=msg.ReverseFind(':'))>0))
379 msg=msg.Right(msg.GetLength()-i-1);
380 int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK,msg);
381 if (nChoice == IDYES)
382 RemoveSymlink(files.GetAt(0));
386 case IDM_SYMBOLICLINK_ADD: {
387 CString msg=files.GetAt(0);
389 if ((i=msg.ReverseFind('\\'))>0)
391 else if ((i=msg.ReverseFind(':'))>0)
392 msg=msg.Left(i+1)+"\\";
393 CMakeSymbolicLinkDlg dlg;
399 case IDM_REMOVE_SYMLINK: {
400 if (files.GetSize()>1)
402 int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK);
403 if (nChoice == IDYES)
404 RemoveSymlink(files.GetAt(0));
418 STDMETHODIMP CShellExt::XMenuExt::GetCommandString(UINT idCmd, UINT uType,
419 UINT* pwReserved, LPSTR pszName, UINT cchMax)
421 if (uType != GCS_HELPTEXT)
422 return NOERROR; // ?????????????????????????????????????????????????
426 AfxSetResourceHandle(theApp.m_hInstance);
430 case IDM_AUTHENTICATION: nCmdStrID = ID_AUTHENTICATE;
433 case IDM_ACL_SET: nCmdStrID = ID_ACL_SET;
436 case IDM_VOLUME_PROPERTIES: nCmdStrID = ID_VOLUME_PROPERTIES;
439 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE: nCmdStrID = ID_VOLUMEPARTITION_UPDATENAMEIDTABLE;
442 case IDM_MOUNTPOINT_SHOW: nCmdStrID = ID_MOUNTPOINT_SHOW;
445 case IDM_MOUNTPOINT_REMOVE: nCmdStrID = ID_MOUNTPOINT_REMOVE;
448 case IDM_MOUNTPOINT_MAKE: nCmdStrID = ID_MOUNTPOINT_MAKE;
451 case IDM_FLUSH: nCmdStrID = ID_FLUSH;
454 case IDM_FLUSH_VOLUME: nCmdStrID = ID_VOLUME_FLUSH;
457 case IDM_SHOW_SERVER: nCmdStrID = ID_WHEREIS;
460 case IDM_SHOWCELL: nCmdStrID = ID_SHOWCELL;
463 case IDM_SERVER_STATUS: nCmdStrID = ID_SERVER_STATUS;
466 case IDM_SYMBOLICLINK_ADD: nCmdStrID = ID_SYMBOLICLINK_ADD;
469 case IDM_SYMBOLICLINK_REMOVE: nCmdStrID = ID_SYMBOLICLINK_REMOVE;
472 case IDM_REMOVE_SYMLINK: nCmdStrID= ID_REMOVE_SYMLINK;
482 LoadString (strMsg, nCmdStrID);
484 strncpy(pszName, strMsg, cchMax);
489 /////////////////////////////////////////////////////////////////////////////
490 // IUnknown for IShellExtInit
491 /////////////////////////////////////////////////////////////////////////////
492 STDMETHODIMP CShellExt::XShellInit::QueryInterface(REFIID riid, void** ppv)
494 METHOD_PROLOGUE(CShellExt, ShellInit);
496 return pThis->ExternalQueryInterface(&riid, ppv);
499 STDMETHODIMP_(ULONG) CShellExt::XShellInit::AddRef(void)
501 return ++nSERefCount;
504 STDMETHODIMP_(ULONG) CShellExt::XShellInit::Release(void)
512 /////////////////////////////////////////////////////////////////////////////
513 // IShellInit Functions
514 /////////////////////////////////////////////////////////////////////////////
515 STDMETHODIMP CShellExt::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdobj, HKEY hkeyProgID)
517 METHOD_PROLOGUE(CShellExt, ShellInit);
519 HRESULT hres = E_FAIL;
520 FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
523 // We must have a data object
527 // Use the given IDataObject to get a list of filenames (CF_HDROP)
528 hres = pdobj->GetData(&fmte, &medium);
532 int nNumFiles = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0);
536 pThis->m_bDirSelected = FALSE;
538 for (int ii = 0; ii < nNumFiles; ii++) {
541 // Get the size of the file name string
542 int nNameLen = DragQueryFile((HDROP)medium.hGlobal, ii, 0, 0);
544 // Make room for it in our string object
545 LPTSTR pszFileNameBuf = strFileName.GetBuffer(nNameLen + 1); // +1 for the terminating NULL
546 ASSERT(pszFileNameBuf);
549 DragQueryFile((HDROP)medium.hGlobal, ii, pszFileNameBuf, nNameLen + 1);
551 strFileName.ReleaseBuffer();
553 if (!IsPathInAfs(strFileName)) {
554 pThis->m_astrFileNames.RemoveAll();
557 pThis->m_bIsSymlink=IsSymlink(strFileName);
560 if (IsADir(strFileName))
561 pThis->m_bDirSelected = TRUE;
563 pThis->m_astrFileNames.Add(strFileName);
566 if (pThis->m_astrFileNames.GetSize() > 0)
573 ReleaseStgMedium(&medium);
578 STDMETHODIMP CShellExt::XIconExt::QueryInterface(REFIID riid, void** ppv)
580 METHOD_PROLOGUE(CShellExt, IconExt);
581 return pThis->ExternalQueryInterface(&riid, ppv);
584 STDMETHODIMP_(ULONG) CShellExt::XIconExt::AddRef(void)
586 return ++nICRefCount;
589 STDMETHODIMP_(ULONG) CShellExt::XIconExt::Release(void)
598 /////////////////////////////////////////////////////////////////////////////
599 // IIconHandler Functions
600 /////////////////////////////////////////////////////////////////////////////
602 STDMETHODIMP CShellExt::XIconExt::GetOverlayInfo(LPWSTR pwszIconFile
603 ,int cchMax,int* pIndex,DWORD* pdwFlags)
605 if(IsBadWritePtr(pIndex, sizeof(int)))
607 if(IsBadWritePtr(pdwFlags, sizeof(DWORD)))
610 HMODULE hModule=GetModuleHandle("shell32.dll");
611 TCHAR szModule[MAX_PATH];
612 DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule));
613 MultiByteToWideChar( CP_ACP,0,szModule,-1,pwszIconFile,cchMax);
615 *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
619 STDMETHODIMP CShellExt::XIconExt::GetPriority(int* pPriority)
621 if(IsBadWritePtr(pPriority, sizeof(int)))
627 STDMETHODIMP CShellExt::XIconExt::IsMemberOf(LPCWSTR pwszPath,DWORD dwAttrib)
629 TCHAR szPath[MAX_PATH];
630 WideCharToMultiByte( CP_ACP,0,pwszPath,-1,szPath,MAX_PATH,NULL,NULL);
631 if (IsSymlink(szPath))
636 /* TOOL TIP INFO IMPLIMENTION */
638 STDMETHODIMP CShellExt::XToolTipExt::QueryInterface(REFIID riid, void** ppv)
640 METHOD_PROLOGUE(CShellExt, ToolTipExt);
641 return pThis->ExternalQueryInterface(&riid, ppv);
644 STDMETHODIMP_(ULONG) CShellExt::XToolTipExt::AddRef(void)
646 return ++nTPRefCount;
649 STDMETHODIMP_(ULONG) CShellExt::XToolTipExt::Release(void)
657 STDMETHODIMP CShellExt::XToolTipExt::GetInfoTip(DWORD dwFlags, LPWSTR *ppwszTip)
659 METHOD_PROLOGUE(CShellExt, ToolTipExt);
661 if (!IsSymlink(pThis->m_szFile))
667 // dwFlags is currently unused.
668 *ppwszTip = (WCHAR*) (pThis->m_pAlloc)->Alloc((1+lstrlen(pThis->m_szFile))*sizeof(WCHAR));
671 wcscpy(*ppwszTip, (WCHAR*)T2OLE(pThis->m_szFile));
676 STDMETHODIMP CShellExt::XToolTipExt::GetInfoFlags(LPDWORD pdwFlags)
681 ////////// IPersistFile
682 /////// PersistFileExt
684 STDMETHODIMP CShellExt::XPersistFileExt::QueryInterface(REFIID riid, void** ppv)
686 METHOD_PROLOGUE(CShellExt, PersistFileExt);
687 return pThis->ExternalQueryInterface(&riid, ppv);
690 STDMETHODIMP_(ULONG) CShellExt::XPersistFileExt::AddRef(void)
692 return ++nXPRefCount;
695 STDMETHODIMP_(ULONG) CShellExt::XPersistFileExt::Release(void)
703 STDMETHODIMP CShellExt::XPersistFileExt::Load(LPCOLESTR wszFile, DWORD dwMode)
705 METHOD_PROLOGUE(CShellExt, PersistFileExt);
707 _tcscpy(pThis->m_szFile, OLE2T((WCHAR*)wszFile));
711 STDMETHODIMP CShellExt::XPersistFileExt::GetClassID(LPCLSID)
716 STDMETHODIMP CShellExt::XPersistFileExt::IsDirty(VOID)
721 STDMETHODIMP CShellExt::XPersistFileExt::Save(LPCOLESTR, BOOL)
726 STDMETHODIMP CShellExt::XPersistFileExt::SaveCompleted(LPCOLESTR)
731 STDMETHODIMP CShellExt::XPersistFileExt::GetCurFile(LPOLESTR FAR*)