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