windows-afs-shell-ext-32bit-20060906
[openafs.git] / src / WINNT / client_exp / shell_ext.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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  */
9
10 #include <afxpriv.h>
11 #include "stdafx.h"
12 #include <winsock2.h>
13 #include <ws2tcpip.h>
14
15 extern "C" {
16 #include <afs/param.h>
17 #include <afs/stds.h>
18 }
19
20 #include <atlconv.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include "afs_shl_ext.h"
24 #include "shell_ext.h"
25 #include "volume_info.h"
26 #include "set_afs_acl.h"
27 #include "gui2fs.h"
28 #include "make_mount_point_dlg.h"
29 #include "msgs.h"
30 #include "server_status_dlg.h"
31 #include "auth_dlg.h"
32 #include "submounts_dlg.h"
33 #include "make_symbolic_link_dlg.h"
34 #include <WINNT\afsreg.h>
35
36 #ifdef _DEBUG
37 #define new DEBUG_NEW
38 #undef THIS_FILE
39 static char THIS_FILE[] = __FILE__;
40 #endif
41
42
43 ULONG nCMRefCount = 0;  // IContextMenu ref count
44 ULONG nSERefCount = 0;  // IShellExtInit ref count
45 ULONG nICRefCount=0;
46 ULONG nTPRefCount=0;
47 ULONG nXPRefCount=0;
48
49 #define MAXSIZE 2048 /* most I'll get back from PIOCTL */
50 #define PCCHAR(str)     ((char *)(const char *)str)
51 static char space[MAXSIZE];
52
53 static BOOL IsADir(const CString& strName)
54 {
55         struct _stat statbuf;
56
57         if (_stat(strName, &statbuf) < 0)
58                 return FALSE;
59
60         return statbuf.st_mode & _S_IFDIR;
61 }
62
63 /////////////////////////////////////////////////////////////////////////////
64 // CShellExt
65
66 IMPLEMENT_DYNCREATE(CShellExt, CCmdTarget)
67 #define REG_CLIENT_PARMS_KEY    "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
68 #define OVERLAYENABLED 1
69
70 CShellExt::CShellExt()
71 {
72         HKEY NPKey;
73         EnableAutomation();
74         nCMRefCount++;
75         HRESULT hr;
76         UINT code;
77         DWORD ShellOption,LSPsize,LSPtype;
78         hr = SHGetMalloc(&m_pAlloc);
79         m_bIsOverlayEnabled=FALSE;
80         if (FAILED(hr))
81                 m_pAlloc = NULL;
82         RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,0, KEY_QUERY_VALUE, &NPKey);
83         LSPsize=sizeof(ShellOption);
84         code=RegQueryValueEx(NPKey, "ShellOption", NULL,
85                              &LSPtype, (LPBYTE)&ShellOption, &LSPsize);
86         RegCloseKey (NPKey);
87         m_bIsOverlayEnabled=((code==0) && (LSPtype==REG_DWORD) && ((ShellOption & OVERLAYENABLED)!=0));
88         TRACE("Create CShellExt, Ref count %d/n",nCMRefCount);
89 }
90
91 CShellExt::~CShellExt()
92 {
93         if(m_pAlloc) m_pAlloc->Release();
94         nCMRefCount--;
95         TRACE("Destroy CShellExt, Ref count %d/n",nCMRefCount);
96 }
97
98
99 void CShellExt::OnFinalRelease()
100 {
101         // When the last reference for an automation object is released
102         // OnFinalRelease is called.  The base class will automatically
103         // deletes the object.  Add additional cleanup required for your
104         // object before calling the base class.
105
106         CCmdTarget::OnFinalRelease();
107 }
108
109
110 BEGIN_MESSAGE_MAP(CShellExt, CCmdTarget)
111         //{{AFX_MSG_MAP(CShellExt)
112                 // NOTE - the ClassWizard will add and remove mapping macros here.
113         //}}AFX_MSG_MAP
114 END_MESSAGE_MAP()
115
116 BEGIN_DISPATCH_MAP(CShellExt, CCmdTarget)
117         //{{AFX_DISPATCH_MAP(CShellExt)
118                 // NOTE - the ClassWizard will add and remove mapping macros here.
119         //}}AFX_DISPATCH_MAP
120 END_DISPATCH_MAP()
121
122 // Note: we add support for IID_IShellExt to support typesafe binding
123 //  from VBA.  This IID must match the GUID that is attached to the 
124 //  dispinterface in the .ODL file.
125
126 #ifndef _WIN64
127 // 32-bit
128 // {DC515C27-6CAC-11D1-BAE7-00C04FD140D2}
129 static const IID IID_IShellExt =
130 { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } };
131 #else
132 // 64-bit
133 // {5f820ca1-3dde-11db-b2ce-001558092db5}
134 static const IID IID_IShellExt =
135 { 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb5 } };
136 #endif
137
138 BEGIN_INTERFACE_MAP(CShellExt, CCmdTarget)
139         INTERFACE_PART(CShellExt, IID_IShellExt, Dispatch)
140     INTERFACE_PART(CShellExt, IID_IContextMenu, MenuExt)
141     INTERFACE_PART(CShellExt, IID_IShellExtInit, ShellInit)
142         INTERFACE_PART(CShellExt, IID_IShellIconOverlayIdentifier, IconExt)
143         INTERFACE_PART(CShellExt, IID_IQueryInfo , ToolTipExt)
144         INTERFACE_PART(CShellExt, IID_IPersistFile , PersistFileExt)
145 END_INTERFACE_MAP()
146
147 #ifndef _WIN64
148     // 32-bit
149 IMPLEMENT_OLECREATE(CShellExt, STR_EXT_TITLE, 0xdc515c27, 0x6cac, 0x11d1, 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2)
150 #else
151     // 64-bit
152 IMPLEMENT_OLECREATE(CShellExt, STR_EXT_TITLE, 0x5f820ca1, 0x3dde, 0x11db, 0xb2, 0xce, 0x0, 0x15, 0x58, 0x09, 0x2d, 0xb5)
153 #endif
154
155
156 /////////////////////////////////////////////////////////////////////////////
157 // CShellExt message handlers
158 /////////////////////////////////////////////////////////////////////////////
159
160
161 /////////////////////////////////////////////////////////////////////////////
162 // IUnknown for IContextMenu
163 /////////////////////////////////////////////////////////////////////////////
164 STDMETHODIMP CShellExt::XMenuExt::QueryInterface(REFIID riid, void** ppv)
165 {
166     METHOD_PROLOGUE(CShellExt, MenuExt);
167
168     return pThis->ExternalQueryInterface(&riid, ppv);
169 }
170
171 STDMETHODIMP_(ULONG) CShellExt::XMenuExt::AddRef(void)
172 {
173         return ++nCMRefCount;
174 }
175
176 STDMETHODIMP_(ULONG) CShellExt::XMenuExt::Release(void)
177 {
178         if (nCMRefCount > 0)
179                 nCMRefCount--;
180
181         return nCMRefCount;
182 }
183
184 /////////////////////////////////////////////////////////////////////////////
185 // IConextMenu Functions
186 /////////////////////////////////////////////////////////////////////////////
187 STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,
188     UINT idCmdFirst, UINT idCmdLast,UINT uFlags)
189 {
190     METHOD_PROLOGUE(CShellExt, MenuExt);
191
192         // Don't add any menu items if we're being asked to deal with this file as a shortcut.
193         if (uFlags & CMF_VERBSONLY)
194                 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)0);
195
196         // Check to see if there's already an AFS menu here; if so, remove it
197         int nItemsNow = GetMenuItemCount (hMenu);
198         CString strAfsItemText = GetMessageString(IDS_AFS_ITEM);
199         LPCTSTR pszAfsItemText = (LPCTSTR)strAfsItemText;
200         for (int iItem = 0; iItem < nItemsNow; iItem++) {
201                 TCHAR szItemText[256];
202                 if (!GetMenuString (hMenu, iItem, szItemText, 256, MF_BYPOSITION))
203                         continue;
204                 if (!lstrcmp (szItemText, pszAfsItemText)) {
205                         DeleteMenu (hMenu, iItem, MF_BYPOSITION);
206                         continue;
207                 }
208                 if ((!lstrcmp(szItemText,"&Delete"))&&(pThis->m_bIsSymlink)) {  /*this is a symlink - don't present a delete menu!*/
209                         DeleteMenu (hMenu, iItem, MF_BYPOSITION);
210                         continue;
211                 }
212                 if ((!lstrcmp(szItemText,"Cu&t"))&&(pThis->m_bIsSymlink)) {             /*same for cut*/
213                         DeleteMenu (hMenu, iItem, MF_BYPOSITION);
214                         continue;
215                 }
216         }
217         int indexShellMenu = 0;
218
219         // Create the AFS submenu using the allowed ID's.
220         HMENU hAfsMenu = CreatePopupMenu();
221         int indexAfsMenu = 0;
222
223         // The Authentication item has been removed from the AFS menu because
224         // there is now a tray icon to handle authentication.
225         //
226         //::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_AUTHENTICATION, GetMessageString(IDS_AUTHENTICATION_ITEM));
227         
228         // Only enable the ACL menu item if a single directory is selected
229         int nSingleDirOnly = MF_GRAYED;
230         if (pThis->m_bDirSelected && (pThis->m_astrFileNames.GetSize() == 1))
231                 nSingleDirOnly = MF_ENABLED;
232         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_ACL_SET, GetMessageString(IDS_ACLS_ITEM));
233         
234         // Volume/Partition submenu of the AFS submenu
235         HMENU hVolPartMenu = CreatePopupMenu();
236         int indexVolPartMenu = 0;
237         ::InsertMenu(hVolPartMenu, indexVolPartMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_VOLUME_PROPERTIES, GetMessageString(IDS_VOL_PART_PROPS_ITEM));
238         ::InsertMenu(hVolPartMenu, indexVolPartMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE, GetMessageString(IDS_VOL_PART_REFRESH_ITEM));
239         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hVolPartMenu, GetMessageString(IDS_VOL_PART_ITEM));
240
241         // Mount Point submenu of the AFS submenu
242         HMENU hMountPointMenu = CreatePopupMenu();
243         int indexMountPointMenu = 0;
244         int nMountPointSelected = MF_GRAYED;
245         for (int n = pThis->m_astrFileNames.GetSize() - 1 ; n >= 0; n--) {
246             if ( IsMountPoint(pThis->m_astrFileNames[n]) ) {
247                 nMountPointSelected = MF_ENABLED;
248                 break;
249             }
250         }
251         ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_SHOW, GetMessageString(IDS_MP_SHOW_ITEM));
252         ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION | nMountPointSelected, idCmdFirst + IDM_MOUNTPOINT_REMOVE, GetMessageString(IDS_MP_REMOVE_ITEM));
253         ::InsertMenu(hMountPointMenu, indexMountPointMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_MOUNTPOINT_MAKE, GetMessageString(IDS_MP_MAKE_ITEM));
254         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hMountPointMenu, GetMessageString(IDS_MOUNT_POINT_ITEM));
255
256         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_FLUSH, GetMessageString(IDS_FLUSH_FILE_DIR_ITEM));   
257         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_FLUSH_VOLUME, GetMessageString(IDS_FLUSH_VOLUME_ITEM));
258         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHOW_SERVER, GetMessageString(IDS_SHOW_FILE_SERVERS_ITEM));
259         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SHOWCELL, GetMessageString(IDS_SHOW_CELL_ITEM));
260         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SERVER_STATUS, GetMessageString(IDS_SHOW_SERVER_STATUS_ITEM));
261
262     HMENU hSymbolicMenu = CreatePopupMenu();
263         int indexSymbolicMenu = 0;
264     ::InsertMenu(hSymbolicMenu, indexSymbolicMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_ADD, GetMessageString(IDS_SYMBOLICLINK_ADD));
265     // ::InsertMenu(hSymbolicMenu, indexSymbolicMenu, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_EDIT, GetMessageString(IDS_SYMBOLICLINK_EDIT));
266         // ::EnableMenuItem(hSymbolicMenu,indexSymbolicMenu++,((pThis->m_bIsSymlink)?MF_ENABLED:MF_GRAYED)|MF_BYPOSITION);
267         ::InsertMenu(hSymbolicMenu, indexSymbolicMenu, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SYMBOLICLINK_REMOVE, GetMessageString(IDS_SYMBOLICLINK_REMOVE));
268         ::EnableMenuItem(hSymbolicMenu,indexSymbolicMenu++,((pThis->m_bIsSymlink)?MF_ENABLED:MF_GRAYED)|MF_BYPOSITION);
269         ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSymbolicMenu, GetMessageString(IDS_SYMBOLIC_LINK_ITEM));
270         
271         // The Submounts menu has been removed because the AFS tray icon
272         // and control panel now support mapping drives directly to an AFS
273         // path.
274         //
275         // HMENU hSubmountMenu = CreatePopupMenu();
276         // int indexSubmountMenu = 0;
277         // ::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION | nSingleDirOnly, idCmdFirst + IDM_SUBMOUNTS_CREATE, GetMessageString(IDS_SUBMOUNTS_CREATE_ITEM));
278         // ::InsertMenu(hSubmountMenu, indexSubmountMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + IDM_SUBMOUNTS_EDIT, GetMessageString(IDS_SUBMOUNTS_EDIT_ITEM));
279         // ::InsertMenu(hAfsMenu, indexAfsMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hSubmountMenu, GetMessageString(IDS_SUBMOUNTS_ITEM));
280
281         // Add a separator
282         ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
283
284         // Add the AFS submenu to the shell's menu
285         ::InsertMenu(hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_POPUP, (UINT)hAfsMenu, GetMessageString(IDS_AFS_ITEM));
286
287         // Add a separator after us
288         ::InsertMenu (hMenu, indexMenu + indexShellMenu++, MF_STRING | MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
289         
290     return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 
291                         (USHORT)indexAfsMenu + indexVolPartMenu + indexMountPointMenu + indexShellMenu + indexSymbolicMenu);
292 }
293
294 STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
295 {
296     METHOD_PROLOGUE(CShellExt, MenuExt);
297
298     if (HIWORD(lpici->lpVerb ))
299         return E_FAIL;
300
301         AddRef();
302
303         CStringArray &files = pThis->m_astrFileNames;
304
305         switch (LOWORD(lpici->lpVerb))
306         {
307                 case IDM_AUTHENTICATION:        {
308                                                                                 CAuthDlg dlg;
309                                                                                 dlg.DoModal();
310                                                                                 break;
311                                                                         }
312                 
313                 case IDM_ACL_SET:                       { 
314                                                                                 CSetAfsAcl dlg;
315                                                                                 ASSERT(files.GetSize() == 1);
316                                                                                 dlg.SetDir(files[0]);
317                                                                                 dlg.DoModal();
318                                                                         }
319                                                                         break;
320                 
321                 case IDM_VOLUME_PROPERTIES:     {
322                                                                                 CVolumeInfo dlg;
323                                                                                 dlg.SetFiles(files);
324                                                                                 dlg.DoModal();
325                                                                         }
326                                                                         break;
327
328                 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE:     CheckVolumes();
329                                                                                                         break;
330
331                 case IDM_MOUNTPOINT_SHOW:       ListMount(files);
332                                                                         break;
333
334                 case IDM_MOUNTPOINT_REMOVE:     {
335                                                                                 int nChoice = ShowMessageBox(IDS_REALLY_DEL_MOUNT_POINTS, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_DEL_MOUNT_POINTS);
336                                                                                 if (nChoice == IDYES)
337                                                                                         RemoveMount(files);
338                                                                         }
339                                                                         break;
340                 
341                 case IDM_MOUNTPOINT_MAKE:       {
342                                                                                 CMakeMountPointDlg dlg;
343                                                                                 ASSERT(files.GetSize() == 1);
344                                                                                 dlg.SetDir(files[0]);
345                                                                                 dlg.DoModal();
346                                                                         }
347                                                                         break;
348
349
350                 case IDM_FLUSH:                         Flush(files);
351                                                                         break;
352                 
353                 case IDM_FLUSH_VOLUME:          FlushVolume(files);
354                                                                         break;
355
356                 case IDM_SHOW_SERVER:           WhereIs(files);
357                                                                         break;
358                 
359                 case IDM_SHOWCELL:                      WhichCell(files);
360                                                                         break;
361
362                 case IDM_SERVER_STATUS:         {
363                                                                                 CServerStatusDlg dlg;
364                                                                                 dlg.DoModal();
365                                                                         }
366                                                                         break;
367
368         /*
369                 case IDM_SUBMOUNTS_EDIT:        {
370                                                                                 CSubmountsDlg dlg;
371                                                                                 dlg.DoModal();
372                                                                         }
373                                                                         break;
374
375                 case IDM_SUBMOUNTS_CREATE:      {
376                                                                                 ASSERT(files.GetSize() == 1);
377                                                                                 CSubmountsDlg dlg;
378                                                                                 dlg.SetAddOnlyMode(files[0]);
379                                                                                 dlg.DoModal();
380                                                                         }
381                                                                         break;
382         */
383         case IDM_SYMBOLICLINK_REMOVE: {
384                 if (files.GetSize()>1)
385                         break;
386                 CString msg=files.GetAt(0);
387                 int i;
388                 if ((i=msg.ReverseFind('\\'))>0)
389                         msg=msg.Left(i+1);
390                 else if ((i=msg.ReverseFind(':'))>0)
391                         msg=msg.Left(i+1)+"\\";
392                 if (!SetCurrentDirectory(msg))
393                 {
394                         MessageBeep((UINT)-1);
395                         ShowMessageBox(IDS_UNABLE_TO_SET_CURRENT_DIRECTORY,MB_OK,IDS_UNABLE_TO_SET_CURRENT_DIRECTORY);
396                         break;
397                 }
398                 msg=files.GetAt(0);
399                 if ((i=msg.ReverseFind('\\'))>0||((i=msg.ReverseFind(':'))>0))
400                         msg=msg.Right(msg.GetLength()-i-1);
401                 int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK,msg);
402                 if (nChoice == IDYES)
403                         RemoveSymlink(files.GetAt(0));
404         }
405                 break;
406
407         case IDM_SYMBOLICLINK_ADD: {
408                 CString msg=files.GetAt(0);
409                 int i;
410                 if ((i=msg.ReverseFind('\\'))>0)
411                         msg=msg.Left(i+1);
412                 else if ((i=msg.ReverseFind(':'))>0)
413                         msg=msg.Left(i+1)+"\\";
414                 CMakeSymbolicLinkDlg dlg;
415                 dlg.Setbase(msg);
416                 dlg.DoModal();
417         }
418                 break;
419                 
420         case IDM_REMOVE_SYMLINK:        {
421                 if (files.GetSize()>1)
422                         break;
423                 int nChoice = ShowMessageBox(IDS_REALLY_REMOVE_SYMLINK, MB_ICONQUESTION | MB_YESNO, IDS_REALLY_REMOVE_SYMLINK);
424                 if (nChoice == IDYES)
425                         RemoveSymlink(files.GetAt(0));
426         }
427                 break;
428         default:
429                 ASSERT(FALSE);
430                 Release();
431                 return E_INVALIDARG;
432         }
433
434         Release();
435
436     return NOERROR;
437 }
438
439 STDMETHODIMP CShellExt::XMenuExt::GetCommandString(UINT_PTR idCmd, UINT uType,
440     UINT* pwReserved, LPSTR pszName, UINT cchMax)
441 {
442         if (uType != GCS_HELPTEXT)
443                 return NOERROR;                 // ?????????????????????????????????????????????????
444
445         UINT nCmdStrID;
446
447     AfxSetResourceHandle(theApp.m_hInstance);
448
449     switch (idCmd)
450         {
451                 case IDM_AUTHENTICATION:        nCmdStrID = ID_AUTHENTICATE;
452                                                                         break;
453                 
454                 case IDM_ACL_SET:                       nCmdStrID = ID_ACL_SET;
455                                                                         break;
456                 
457                 case IDM_VOLUME_PROPERTIES:     nCmdStrID = ID_VOLUME_PROPERTIES;
458                                                                         break;
459
460                 case IDM_VOLUMEPARTITION_UPDATENAMEIDTABLE:     nCmdStrID = ID_VOLUMEPARTITION_UPDATENAMEIDTABLE;
461                                                                                                         break;
462
463                 case IDM_MOUNTPOINT_SHOW:       nCmdStrID = ID_MOUNTPOINT_SHOW;
464                                                                         break;
465
466                 case IDM_MOUNTPOINT_REMOVE:     nCmdStrID = ID_MOUNTPOINT_REMOVE;
467                                                                         break;
468                 
469                 case IDM_MOUNTPOINT_MAKE:       nCmdStrID = ID_MOUNTPOINT_MAKE;
470                                                                         break;
471
472                 case IDM_FLUSH:                         nCmdStrID = ID_FLUSH;
473                                                                         break;
474                 
475                 case IDM_FLUSH_VOLUME:          nCmdStrID = ID_VOLUME_FLUSH;
476                                                                         break;
477
478                 case IDM_SHOW_SERVER:           nCmdStrID = ID_WHEREIS;
479                                                                         break;
480                 
481                 case IDM_SHOWCELL:                      nCmdStrID = ID_SHOWCELL;
482                                                                         break;
483
484                 case IDM_SERVER_STATUS:         nCmdStrID = ID_SERVER_STATUS;
485                                                                         break;
486
487                 case IDM_SYMBOLICLINK_ADD:      nCmdStrID = ID_SYMBOLICLINK_ADD;
488                                                                         break;
489                 
490                 case IDM_SYMBOLICLINK_REMOVE:   nCmdStrID = ID_SYMBOLICLINK_REMOVE;
491                                                                         break;
492
493                 case IDM_REMOVE_SYMLINK:        nCmdStrID= ID_REMOVE_SYMLINK;
494                                                                         break;
495                 
496                 default:
497                         ASSERT(FALSE);
498                         Release();
499                     return E_INVALIDARG;
500         }
501
502     CString strMsg;
503     LoadString (strMsg, nCmdStrID);
504
505     strncpy(pszName, strMsg, cchMax);
506
507     return NOERROR;
508 }
509
510 /////////////////////////////////////////////////////////////////////////////
511 // IUnknown for IShellExtInit
512 /////////////////////////////////////////////////////////////////////////////
513 STDMETHODIMP CShellExt::XShellInit::QueryInterface(REFIID riid, void** ppv)
514 {
515     METHOD_PROLOGUE(CShellExt, ShellInit);
516
517     return pThis->ExternalQueryInterface(&riid, ppv);
518 }
519
520 STDMETHODIMP_(ULONG) CShellExt::XShellInit::AddRef(void)
521 {
522         return ++nSERefCount;
523 }
524
525 STDMETHODIMP_(ULONG) CShellExt::XShellInit::Release(void)
526 {
527         if (nSERefCount > 0)
528                 nSERefCount--;
529         
530         return nSERefCount;
531 }
532
533 /////////////////////////////////////////////////////////////////////////////
534 // IShellInit Functions
535 /////////////////////////////////////////////////////////////////////////////
536 STDMETHODIMP CShellExt::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdobj, HKEY hkeyProgID)
537 {
538     METHOD_PROLOGUE(CShellExt, ShellInit);
539
540     HRESULT hres = E_FAIL;
541     FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
542     STGMEDIUM medium;
543
544         // We must have a data object
545     if (pdobj == NULL)
546             return E_FAIL;
547
548     //  Use the given IDataObject to get a list of filenames (CF_HDROP)
549     hres = pdobj->GetData(&fmte, &medium);
550     if (FAILED(hres)) {
551             return E_FAIL;
552     }
553
554     int nNumFiles = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0);
555         if (nNumFiles == 0)
556                 hres = E_FAIL;
557         else {
558                 pThis->m_bDirSelected = FALSE;
559
560                 for (int ii = 0; ii < nNumFiles; ii++) {
561                         CString strFileName;
562
563                         // Get the size of the file name string
564                         int nNameLen = DragQueryFile((HDROP)medium.hGlobal, ii, 0, 0);
565
566                         // Make room for it in our string object
567                         LPTSTR pszFileNameBuf = strFileName.GetBuffer(nNameLen + 1);    // +1 for the terminating NULL
568                         ASSERT(pszFileNameBuf);
569                         
570                         // Get the file name
571                         DragQueryFile((HDROP)medium.hGlobal, ii, pszFileNameBuf, nNameLen + 1);
572                         
573                         strFileName.ReleaseBuffer();
574
575                         if (!IsPathInAfs(strFileName)) {
576                                 pThis->m_astrFileNames.RemoveAll();
577                                 break;
578                         } else {
579                                 pThis->m_bIsSymlink=IsSymlink(strFileName);
580                         }
581
582                         if (IsADir(strFileName))
583                                 pThis->m_bDirSelected = TRUE;
584
585                         pThis->m_astrFileNames.Add(strFileName);
586                 }
587
588                 if (pThis->m_astrFileNames.GetSize() > 0)
589                         hres = NOERROR;
590                 else
591                         hres = E_FAIL;
592     }
593  
594     //  Release the data
595     ReleaseStgMedium(&medium);
596
597     return hres;
598 }
599
600 STDMETHODIMP CShellExt::XIconExt::QueryInterface(REFIID riid, void** ppv)
601 {
602     METHOD_PROLOGUE(CShellExt, IconExt);
603     return pThis->ExternalQueryInterface(&riid, ppv);
604 }
605
606 STDMETHODIMP_(ULONG) CShellExt::XIconExt::AddRef(void)
607 {
608         return ++nICRefCount;
609 }
610
611 STDMETHODIMP_(ULONG) CShellExt::XIconExt::Release(void)
612 {
613         if (nICRefCount > 0)
614                 nICRefCount--;
615
616         return nICRefCount;
617 }
618
619
620 /////////////////////////////////////////////////////////////////////////////
621 // IIconHandler Functions
622 /////////////////////////////////////////////////////////////////////////////
623
624 STDMETHODIMP CShellExt::XIconExt::GetOverlayInfo(LPWSTR pwszIconFile
625         ,int cchMax,int* pIndex,DWORD* pdwFlags)
626 {
627         if(IsBadWritePtr(pIndex, sizeof(int)))
628                 return E_INVALIDARG;
629         if(IsBadWritePtr(pdwFlags, sizeof(DWORD)))
630                 return E_INVALIDARG;
631
632         HMODULE hModule=GetModuleHandle("shell32.dll");
633         TCHAR szModule[MAX_PATH];
634         DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule));
635         MultiByteToWideChar( CP_ACP,0,szModule,-1,pwszIconFile,cchMax); 
636         *pIndex = 30;
637         *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
638         return S_OK;
639 }
640
641 STDMETHODIMP CShellExt::XIconExt::GetPriority(int* pPriority)
642 {
643         if(IsBadWritePtr(pPriority, sizeof(int)))
644            return E_INVALIDARG;
645         *pPriority = 0;
646         return S_OK;
647 }
648
649 STDMETHODIMP CShellExt::XIconExt::IsMemberOf(LPCWSTR pwszPath,DWORD dwAttrib)
650 {
651         TCHAR szPath[MAX_PATH];
652         WideCharToMultiByte( CP_ACP,0,pwszPath,-1,szPath,MAX_PATH,NULL,NULL);
653         if (IsSymlink(szPath))
654                 return S_OK;
655         return S_FALSE;
656 }
657
658 /*          TOOL TIP INFO IMPLIMENTION   */
659
660 STDMETHODIMP CShellExt::XToolTipExt::QueryInterface(REFIID riid, void** ppv)
661 {
662     METHOD_PROLOGUE(CShellExt, ToolTipExt);
663     return pThis->ExternalQueryInterface(&riid, ppv);
664 }
665
666 STDMETHODIMP_(ULONG) CShellExt::XToolTipExt::AddRef(void)
667 {
668         return ++nTPRefCount;
669 }
670
671 STDMETHODIMP_(ULONG) CShellExt::XToolTipExt::Release(void)
672 {
673         if (nTPRefCount> 0)
674                 nTPRefCount--;
675
676         return nTPRefCount;
677 }
678
679 STDMETHODIMP CShellExt::XToolTipExt::GetInfoTip(DWORD dwFlags, LPWSTR *ppwszTip)
680 {
681     METHOD_PROLOGUE(CShellExt, ToolTipExt);
682
683         if (!IsSymlink(pThis->m_szFile))
684         {
685                 ppwszTip=NULL;
686                 return S_OK;
687         }
688         USES_CONVERSION;
689         // dwFlags is currently unused.
690         *ppwszTip = (WCHAR*) (pThis->m_pAlloc)->Alloc((1+lstrlen(pThis->m_szFile))*sizeof(WCHAR));
691         if (*ppwszTip)
692         {
693                 wcscpy(*ppwszTip, (WCHAR*)T2OLE(pThis->m_szFile));
694         }
695
696         return S_OK;
697 }
698 STDMETHODIMP CShellExt::XToolTipExt::GetInfoFlags(LPDWORD pdwFlags)
699 {
700         return S_OK;
701 }
702
703 //////////                          IPersistFile
704 ///////                            PersistFileExt
705
706 STDMETHODIMP CShellExt::XPersistFileExt::QueryInterface(REFIID riid, void** ppv)
707 {
708     METHOD_PROLOGUE(CShellExt, PersistFileExt);
709     return pThis->ExternalQueryInterface(&riid, ppv);
710 }
711
712 STDMETHODIMP_(ULONG) CShellExt::XPersistFileExt::AddRef(void)
713 {
714         return ++nXPRefCount;
715 }
716
717 STDMETHODIMP_(ULONG) CShellExt::XPersistFileExt::Release(void)
718 {
719         if (nXPRefCount> 0)
720                 nXPRefCount--;
721
722         return nXPRefCount;
723 }
724
725 STDMETHODIMP    CShellExt::XPersistFileExt::Load(LPCOLESTR wszFile, DWORD dwMode)
726 {
727     METHOD_PROLOGUE(CShellExt, PersistFileExt);
728         USES_CONVERSION;
729         _tcscpy(pThis->m_szFile, OLE2T((WCHAR*)wszFile)); 
730         return S_OK;    
731 }
732
733 STDMETHODIMP CShellExt::XPersistFileExt::GetClassID(LPCLSID)
734
735         return E_NOTIMPL;       
736 }
737
738 STDMETHODIMP CShellExt::XPersistFileExt::IsDirty(VOID)
739
740         return E_NOTIMPL; 
741 }
742
743 STDMETHODIMP CShellExt::XPersistFileExt::Save(LPCOLESTR, BOOL)
744
745         return E_NOTIMPL; 
746 }
747
748 STDMETHODIMP CShellExt::XPersistFileExt::SaveCompleted(LPCOLESTR)
749
750         return E_NOTIMPL; 
751 }
752
753 STDMETHODIMP CShellExt::XPersistFileExt::GetCurFile(LPOLESTR FAR*)
754
755         return E_NOTIMPL; 
756 }