LINUX: afs_create infinite fetchStatus loop
[pkg-k5-afs_openafs.git] / src / WINNT / client_exp / shell_ext.cpp
blobd21aca405dca9f45288bb731f3e98a78ad72fd02
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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
8 */
10 #include <afxpriv.h>
11 #include "stdafx.h"
12 #include "PropFile.h"
13 #include "PropACL.h"
14 #include "PropVolume.h"
15 #include <winsock2.h>
16 #include <ws2tcpip.h>
17 #include <shtypes.h>
18 #include <shlwapi.h>
20 extern "C" {
21 #include <afs/param.h>
22 #include <afs/stds.h>
23 #include <afs/afs_consts.h>
26 #include <atlconv.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include "afs_shl_ext.h"
30 #include "shell_ext.h"
31 #include "volume_info.h"
32 #include "set_afs_acl.h"
33 #include "gui2fs.h"
34 #include "make_mount_point_dlg.h"
35 #include "msgs.h"
36 #include "server_status_dlg.h"
37 #include "auth_dlg.h"
38 #include "submounts_dlg.h"
39 #include "make_symbolic_link_dlg.h"
40 #include <WINNT\afsreg.h>
42 #ifdef _DEBUG
43 #define new DEBUG_NEW
44 #undef THIS_FILE
45 static char THIS_FILE[] = __FILE__;
46 #endif
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
53 ULONG nICRefCount=0;
54 ULONG nTPRefCount=0;
55 ULONG nXPRefCount=0;
56 UINT nPSRefCount=0;
58 #define PCCHAR(str) ((char *)(const char *)str)
59 static char space[AFS_PIOCTL_MAXSIZE];
61 static BOOL IsADir(const CString& strName)
63 struct _stat statbuf;
65 if (_tstat(strName, &statbuf) < 0)
66 return FALSE;
68 return statbuf.st_mode & _S_IFDIR;
71 /////////////////////////////////////////////////////////////////////////////
72 // CShellExt
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()
81 HKEY NPKey;
82 EnableAutomation();
83 nCMRefCount++;
84 HRESULT hr;
85 UINT code;
86 DWORD ShellOption,LSPsize,LSPtype;
87 m_overlayObject = 0;
88 hr = SHGetMalloc(&m_pAlloc);
89 m_bIsOverlayEnabled=FALSE;
90 if (FAILED(hr))
91 m_pAlloc = NULL;
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);
96 RegCloseKey (NPKey);
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()
110 if(m_pAlloc)
111 m_pAlloc->Release();
112 nCMRefCount--;
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.
131 //}}AFX_MSG_MAP
132 END_MESSAGE_MAP()
134 BEGIN_DISPATCH_MAP(CShellExt, CCmdTarget)
135 //{{AFX_DISPATCH_MAP(CShellExt)
136 // NOTE - the ClassWizard will add and remove mapping macros here.
137 //}}AFX_DISPATCH_MAP
138 END_DISPATCH_MAP()
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.
144 #ifndef _WIN64
145 // 32-bit
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 } };
151 #else
152 // 64-bit
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 } };
158 #endif
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)
168 END_INTERFACE_MAP()
170 #ifndef _WIN64
171 // 32-bit
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)
174 #else
175 // 64-bit
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)
178 #endif
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)
203 if (nCMRefCount > 0)
204 nCMRefCount--;
206 return nCMRefCount;
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))
233 continue;
234 if (lstrcmp (szItemText, pszAfsItemText)==0) {
235 DeleteMenu (hMenu, iItem, MF_BYPOSITION);
236 continue;
238 if (((lstrcmp(szItemText,strDeleteText)==0)||(lstrcmp(szItemText,strCutText)==0))&&((pThis->m_bIsSymlink)||(pThis->m_bIsMountpoint))) {
239 DeleteMenu (hMenu, iItem, MF_BYPOSITION);
240 continue;
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;
269 break;
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;
289 break;
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
300 // path.
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));
308 // Add a separator
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 ))
326 return E_FAIL;
328 AddRef();
330 CStringArray &files = pThis->m_astrFileNames;
332 switch (LOWORD(lpici->lpVerb))
334 case IDM_AUTHENTICATION: {
335 CAuthDlg dlg;
336 dlg.DoModal();
337 break;
340 case IDM_ACL_SET: {
341 CSetAfsAcl dlg;
342 ASSERT(files.GetSize() == 1);
343 dlg.SetDir(files[0]);
344 dlg.DoModal();
345 break;
348 case IDM_VOLUME_PROPERTIES: {
349 CVolumeInfo dlg;
350 dlg.SetFiles(files);
351 dlg.DoModal();
352 break;
355 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE:
356 CheckVolumes();
357 break;
359 case IDM_MOUNTPOINT_SHOW:
360 ListMount(files);
361 break;
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)
366 RemoveMount(files);
367 break;
370 case IDM_MOUNTPOINT_MAKE: {
371 CMakeMountPointDlg dlg;
372 ASSERT(files.GetSize() == 1);
373 dlg.SetDir(files[0]);
374 dlg.DoModal();
375 break;
378 case IDM_FLUSH:
379 Flush(files);
380 break;
382 case IDM_FLUSH_VOLUME:
383 FlushVolume(files);
384 break;
386 case IDM_SHOW_SERVER:
387 WhereIs(files);
388 break;
390 case IDM_SHOWCELL:
391 WhichCell(files);
392 break;
394 case IDM_SERVER_STATUS: {
395 CServerStatusDlg dlg;
396 dlg.DoModal();
397 break;
401 case IDM_SUBMOUNTS_EDIT: {
402 CSubmountsDlg dlg;
403 dlg.DoModal();
404 break;
406 case IDM_SUBMOUNTS_CREATE: {
407 ASSERT(files.GetSize() == 1);
408 CSubmountsDlg dlg;
409 dlg.SetAddOnlyMode(files[0]);
410 dlg.DoModal();
411 break;
414 case IDM_SYMBOLICLINK_REMOVE: {
415 if (files.GetSize()>1)
416 break;
417 CString msg=files.GetAt(0);
418 int i;
419 if ((i=msg.ReverseFind('\\'))>0)
420 msg=msg.Left(i+1);
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);
427 break;
429 msg=files.GetAt(0);
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));
435 break;
438 case IDM_SYMBOLICLINK_ADD: {
439 CStringA msg(files.GetAt(0));
440 int i;
441 if ((i=msg.ReverseFind('\\'))>0)
442 msg=msg.Left(i+1);
443 else if ((i=msg.ReverseFind(':'))>0)
444 msg=msg.Left(i+1)+"\\";
445 CMakeSymbolicLinkDlg dlg;
446 dlg.Setbase(msg);
447 dlg.DoModal();
448 break;
451 case IDM_SYMBOLICLINK_SHOW:
452 ListSymlink(files);
453 break;
455 case IDM_REMOVE_SYMLINK: {
456 if (files.GetSize()>1)
457 break;
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));
462 break;
463 default:
464 ASSERT(FALSE);
465 Release();
466 return E_INVALIDARG;
469 Release();
471 return NOERROR;
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; // ?????????????????????????????????????????????????
480 UINT nCmdStrID;
482 AfxSetResourceHandle(theApp.m_hInstance);
484 switch (idCmd)
486 case IDM_AUTHENTICATION:
487 nCmdStrID = ID_AUTHENTICATE;
488 break;
490 case IDM_ACL_SET:
491 nCmdStrID = ID_ACL_SET;
492 break;
494 case IDM_VOLUME_PROPERTIES:
495 nCmdStrID = ID_VOLUME_PROPERTIES;
496 break;
498 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE:
499 nCmdStrID = ID_VOLUMEPARTITION_UPDATENAMEIDTABLE;
500 break;
502 case IDM_MOUNTPOINT_SHOW:
503 nCmdStrID = ID_MOUNTPOINT_SHOW;
504 break;
506 case IDM_MOUNTPOINT_REMOVE:
507 nCmdStrID = ID_MOUNTPOINT_REMOVE;
508 break;
510 case IDM_MOUNTPOINT_MAKE:
511 nCmdStrID = ID_MOUNTPOINT_MAKE;
512 break;
514 case IDM_FLUSH:
515 nCmdStrID = ID_FLUSH;
516 break;
518 case IDM_FLUSH_VOLUME:
519 nCmdStrID = ID_VOLUME_FLUSH;
520 break;
522 case IDM_SHOW_SERVER:
523 nCmdStrID = ID_WHEREIS;
524 break;
526 case IDM_SHOWCELL:
527 nCmdStrID = ID_SHOWCELL;
528 break;
530 case IDM_SERVER_STATUS:
531 nCmdStrID = ID_SERVER_STATUS;
532 break;
534 case IDM_SYMBOLICLINK_ADD:
535 nCmdStrID = ID_SYMBOLICLINK_ADD;
536 break;
538 case IDM_SYMBOLICLINK_SHOW:
539 nCmdStrID = ID_SYMBOLICLINK_SHOW;
540 break;
542 case IDM_SYMBOLICLINK_REMOVE:
543 nCmdStrID = ID_SYMBOLICLINK_REMOVE;
544 break;
546 case IDM_REMOVE_SYMLINK:
547 nCmdStrID= ID_REMOVE_SYMLINK;
548 break;
550 default:
551 ASSERT(FALSE);
552 Release();
553 return E_INVALIDARG;
556 CString strMsg;
557 LoadString (strMsg, nCmdStrID);
559 _tcsncpy((LPTSTR) pszName, strMsg, cchMax);
561 return NOERROR;
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)
581 if (nSERefCount > 0)
582 nSERefCount--;
584 return nSERefCount;
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};
596 STGMEDIUM medium;
598 // We must have a data object
599 if ((pdobj == NULL) && (pidlFolder == NULL))
600 return E_FAIL;
602 pThis->m_bIsSymlink=false;
603 pThis->m_bIsMountpoint=false;
604 pThis->m_bIsPathInAFS=false;
605 pThis->m_bDirSelected=false;
607 if (pdobj) {
608 // Use the given IDataObject to get a list of filenames (CF_HDROP)
609 hres = pdobj->GetData(&fmte, &medium);
610 if (FAILED(hres)) {
611 return E_FAIL;
614 int nNumFiles = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0);
615 if (nNumFiles == 0)
616 hres = E_FAIL;
617 else {
618 pThis->m_bDirSelected = FALSE;
620 for (int ii = 0; ii < nNumFiles; ii++) {
621 CString strFileName;
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);
630 // Get the file name
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;
637 break;
638 } else {
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);
649 // Release the data
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;
656 STRRET name;
657 TCHAR * szDisplayName = NULL;
659 hres = ::SHGetDesktopFolder(&parentFolder);
660 if (FAILED(hres))
661 return hres;
663 hres = parentFolder->GetDisplayNameOf(pidlFolder, SHGDN_NORMAL | SHGDN_FORPARSING, &name);
664 if (FAILED(hres)) {
665 parentFolder->Release();
666 return hres;
669 hres = StrRetToStr (&name, pidlFolder, &szDisplayName);
670 if (FAILED(hres))
671 return hres;
672 parentFolder->Release();
673 if (szDisplayName) {
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)
686 hres = NOERROR;
687 else
688 hres = E_FAIL;
690 return hres;
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)
706 if (nICRefCount > 0)
707 nICRefCount--;
709 return nICRefCount;
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)))
722 return E_INVALIDARG;
723 if(IsBadWritePtr(pdwFlags, sizeof(DWORD)))
724 return E_INVALIDARG;
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, '\\');
730 if (slash) {
731 *slash = 0;
732 switch (pThis->GetOverlayObject())
734 case 0:
735 _tcscat(szModule, _T("\\link.ico"));
736 break;
737 case 1:
738 _tcscat(szModule, _T("\\mount.ico"));
739 break;
742 #ifndef UNICODE
743 MultiByteToWideChar( CP_ACP,0,szModule,-1,pwszIconFile,cchMax);
744 #else
745 _tcsncpy(pwszIconFile, szModule, cchMax);
746 #endif
747 *pIndex = 0;
748 *pdwFlags = ISIOI_ICONFILE;
749 return S_OK;
752 STDMETHODIMP CShellExt::XIconExt::GetPriority(int* pPriority)
754 if(IsBadWritePtr(pPriority, sizeof(int)))
755 return E_INVALIDARG;
756 *pPriority = 0;
757 return S_OK;
760 STDMETHODIMP CShellExt::XIconExt::IsMemberOf(LPCWSTR pwszPath,DWORD dwAttrib)
762 METHOD_PROLOGUE(CShellExt, IconExt);
763 TCHAR szPath[MAX_PATH];
764 #ifdef UNICODE
765 _tcscpy(szPath, pwszPath);
766 #else
767 WideCharToMultiByte( CP_ACP,0,pwszPath,-1,szPath,MAX_PATH,NULL,NULL);
768 #endif
769 if (!IsPathInAfs(szPath))
770 return S_FALSE;
772 if ((pThis->GetOverlayObject() == 0)&&(IsSymlink(szPath))) {
773 return S_OK;
775 if ((pThis->GetOverlayObject() == 1)&&(IsMountPoint(szPath))) {
776 return S_OK;
778 return S_FALSE;
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)
796 if (nTPRefCount> 0)
797 nTPRefCount--;
799 return nTPRefCount;
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)))
808 *ppwszTip=NULL;
809 return S_OK;
811 bool bIsSymlink = !!IsSymlink(pThis->m_szFile);
812 bool bIsMountpoint = !!IsMountPoint(pThis->m_szFile);
813 if ((!bIsSymlink) && (!bIsMountpoint))
815 *ppwszTip=NULL;
816 return S_OK;
818 USES_CONVERSION;
819 // dwFlags is currently unused.
820 CString sInfo;
821 if (bIsSymlink)
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));
826 if (*ppwszTip)
827 wcscpy(*ppwszTip, (WCHAR*)T2COLE((LPCTSTR)sInfo));
829 return S_OK;
831 STDMETHODIMP CShellExt::XToolTipExt::GetInfoFlags(LPDWORD pdwFlags)
833 *pdwFlags = 0;
834 return S_OK;
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)
853 if (nXPRefCount> 0)
854 nXPRefCount--;
856 return nXPRefCount;
859 STDMETHODIMP CShellExt::XPersistFileExt::Load(LPCOLESTR wszFile, DWORD dwMode)
861 METHOD_PROLOGUE(CShellExt, PersistFileExt);
862 USES_CONVERSION;
863 _tcscpy(pThis->m_szFile, OLE2T((WCHAR*)wszFile));
864 return S_OK;
867 STDMETHODIMP CShellExt::XPersistFileExt::GetClassID(LPCLSID)
869 return E_NOTIMPL;
872 STDMETHODIMP CShellExt::XPersistFileExt::IsDirty(VOID)
874 return E_NOTIMPL;
877 STDMETHODIMP CShellExt::XPersistFileExt::Save(LPCOLESTR, BOOL)
879 return E_NOTIMPL;
882 STDMETHODIMP CShellExt::XPersistFileExt::SaveCompleted(LPCOLESTR)
884 return E_NOTIMPL;
887 STDMETHODIMP CShellExt::XPersistFileExt::GetCurFile(LPOLESTR FAR*)
889 return E_NOTIMPL;
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)
906 if (nPSRefCount> 0)
907 nPSRefCount--;
909 return nPSRefCount;
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);
922 else
924 sheetpage = (PropertyPage*) GetWindowLongPtr (hwnd, GWLP_USERDATA);
927 if (sheetpage != 0L)
928 return sheetpage->PropPageProc(hwnd, uMessage, wParam, lParam);
929 else
930 return FALSE;
933 UINT CALLBACK PropPageCallbackProc ( HWND /*hwnd*/, UINT uMsg, LPPROPSHEETPAGE ppsp )
935 // Delete the page before closing.
936 if (PSPCB_CREATE == uMsg)
937 return TRUE;
938 if (PSPCB_RELEASE == uMsg)
940 PropertyPage* sheetpage = (PropertyPage*) ppsp->lParam;
941 delete sheetpage;
943 return TRUE;
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
952 PROPSHEETPAGE psp;
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;
964 HINSTANCE hInst = 0;
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);
974 psp.pszIcon = NULL;
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);
983 if (hPage != NULL) {
984 if (!lpfnAddPage (hPage, lParam)) {
985 delete filesheet;
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;
996 hInst = 0;
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);
1006 psp.pszIcon = NULL;
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)) {
1017 delete volsheet;
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;
1030 hInst = 0;
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);
1040 psp.pszIcon = NULL;
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)) {
1051 delete aclsheet;
1052 DestroyPropertySheetPage (hPage);
1058 return S_OK;
1061 STDMETHODIMP CShellExt::XPropertySheetExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam)
1063 return E_FAIL;