source: trunk/Erasext/ErasextMenu.cpp @ 26

Revision 26, 25.4 KB checked in by lowjoel, 7 years ago (diff)

-Silenced few compile warnings
-Disable deprecation on unsafe CRT functions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1// ErasextMenu.cpp
2//
3// Eraser. Secure data removal. For Windows.
4// Copyright © 1997-2001  Sami Tolvanen (sami@tolvanen.com).
5//
6// This program is free software; you can redistribute it and/or
7// modify it under the terms of the GNU General Public License
8// as published by the Free Software Foundation; either version 2
9// of the License, or (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19// 02111-1307, USA.
20
21#include "stdafx.h"
22#include "resource.h"
23#include "..\EraserDll\eraserdll.h"
24#include "..\shared\FileHelper.h"
25#include "..\shared\key.h"
26
27#include "ConfirmDialog.h"
28#include "ConfirmReplaceDlg.h"
29#include "WipeProgDlg.h"
30
31#include <shlobj.h>
32
33#include "Erasext.h"
34#include "ErasextMenu.h"
35
36#define ResultFromShort(i)  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, (i));
37
38#ifdef _DEBUG
39#define new DEBUG_NEW
40#undef THIS_FILE
41static char THIS_FILE[] = __FILE__;
42#endif
43
44const LPCTSTR szAccelerKey = "Acceler";
45
46/////////////////////////////////////////////////////////////////////////////
47// CErasextMenu
48enum
49{
50    CMD_ERASE = 0, CMD_MOVE = 1
51};
52IMPLEMENT_DYNCREATE(CErasextMenu, CCmdTarget)
53
54static void DisplayError(DWORD dwError)
55{
56    LPVOID lpMsgBuf;
57
58    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
59                  NULL,
60                  dwError,
61                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
62                  (LPTSTR) &lpMsgBuf,
63                  0,
64                  NULL);
65
66    AfxMessageBox((LPCTSTR)lpMsgBuf, MB_ICONERROR);
67
68    // free the buffer
69    LocalFree(lpMsgBuf);
70}
71
72CErasextMenu::CErasextMenu() :
73m_bUseFiles(TRUE),
74m_dwItems(0),
75m_dwDirectories(0),
76m_bDragMenu(FALSE)
77{
78    EnableAutomation();
79
80    // To keep the application running as long as an OLE automation
81    // object is active, the constructor calls AfxOleLockApp.
82
83    AfxOleLockApp();
84
85    // NT or not
86    OSVERSIONINFO ov;
87
88    ZeroMemory(&ov, sizeof(OSVERSIONINFO));
89    ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
90
91    GetVersionEx(&ov);
92    m_bNT = true;//(ov.dwPlatformId == VER_PLATFORM_WIN32_NT);
93}
94
95CErasextMenu::~CErasextMenu()
96{
97    // To terminate the application when all objects created with
98    // with OLE automation, the destructor calls AfxOleUnlockApp.
99
100    AfxOleUnlockApp();
101}
102
103
104void CErasextMenu::OnFinalRelease()
105{
106    // When the last reference for an automation object is released
107    // OnFinalRelease is called.  The base class will automatically
108    // deletes the object.  Add additional cleanup required for your
109    // object before calling the base class.
110
111    CCmdTarget::OnFinalRelease();
112}
113
114
115BEGIN_MESSAGE_MAP(CErasextMenu, CCmdTarget)
116    //{{AFX_MSG_MAP(CErasextMenu)
117        // NOTE - the ClassWizard will add and remove mapping macros here.
118    //}}AFX_MSG_MAP
119END_MESSAGE_MAP()
120
121BEGIN_DISPATCH_MAP(CErasextMenu, CCmdTarget)
122    //{{AFX_DISPATCH_MAP(CErasextMenu)
123        // NOTE - the ClassWizard will add and remove mapping macros here.
124    //}}AFX_DISPATCH_MAP
125END_DISPATCH_MAP()
126
127// Note: we add support for IID_IErasextMenu to support typesafe binding
128//  from VBA.  This IID must match the GUID that is attached to the
129//  dispinterface in the .ODL file.
130
131// {8BE13461-936F-11D1-A87D-444553540000}
132static const IID IID_IErasextMenu =
133{ 0x8be13461, 0x936f, 0x11d1, { 0xa8, 0x7d, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 } };
134
135IMPLEMENT_OLECREATE(CErasextMenu, "ErasextMenu", 0x8be13461, 0x936f, 0x11d1, 0xa8, 0x7d, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
136
137BEGIN_INTERFACE_MAP(CErasextMenu, CCmdTarget)
138    INTERFACE_PART(CErasextMenu, IID_IErasextMenu, Dispatch)
139    INTERFACE_PART(CErasextMenu, IID_IContextMenu, MenuExt)
140    INTERFACE_PART(CErasextMenu, IID_IShellExtInit, ShellInit)
141END_INTERFACE_MAP()
142
143// IUnknown for IContextMenu
144STDMETHODIMP CErasextMenu::XMenuExt::QueryInterface(REFIID riid, void** ppv)
145{
146    METHOD_PROLOGUE(CErasextMenu, MenuExt);
147    TRACE("CErasextMenu::XMenuExt::QueryInterface\n");
148    return pThis->ExternalQueryInterface(&riid, ppv);
149}
150
151STDMETHODIMP_(ULONG) CErasextMenu::XMenuExt::AddRef(void)
152{
153    METHOD_PROLOGUE(CErasextMenu, MenuExt);
154    TRACE("CErasextMenu::XMenuExt::AddRef\n");
155    return pThis->ExternalAddRef();
156}
157
158STDMETHODIMP_(ULONG) CErasextMenu::XMenuExt::Release(void)
159{
160    METHOD_PROLOGUE(CErasextMenu, MenuExt);
161    TRACE("CErasextMenu::XMenuExt::Release\n");
162    return pThis->ExternalRelease();
163}
164
165CString setShortcut(CString str)
166{
167    CKey kReg;
168    CString strPath(""), strKey(""), strRes("");
169    strPath.Format("%s\\%s", ERASER_REGISTRY_BASE, szAccelerKey);
170    int iPos;
171    if (kReg.Open(HKEY_CURRENT_USER, strPath,FALSE))
172    {
173        if ((iPos=str.Find('&'))!=-1) {
174            str = str.Left(iPos) + str.Right(str.GetLength()-iPos-1);
175        }
176        if (kReg.GetValue(strKey,str))
177        {           
178            CString strTmp(str);
179            strKey.MakeUpper();
180            strTmp.MakeUpper();
181            iPos=strTmp.Find(strKey[0]);
182            strRes = str.Left(iPos)+"&"+str.Right(str.GetLength()-iPos);
183        }
184        kReg.Close();
185    }   
186    else{
187        strRes = str;
188    }
189    return strRes;
190}
191
192STDMETHODIMP CErasextMenu::XMenuExt::QueryContextMenu(HMENU hMenu, UINT nIndex, UINT idCmdFirst, UINT /*idCmdLast*/, UINT uFlags)
193{
194    METHOD_PROLOGUE(CErasextMenu, MenuExt);
195
196    // do not show menu for shortcuts or when the shell
197    // wants only the default item, or if the user has disabled
198    // the shell extension
199
200    CKey kReg;
201    BOOL bEnabled = TRUE;
202   
203    if (kReg.Open(HKEY_CURRENT_USER, ERASER_REGISTRY_BASE))
204    {
205        kReg.GetValue(bEnabled, ERASEXT_REGISTRY_ENABLED, TRUE);
206        kReg.Close();
207    }
208
209    if (bEnabled && (uFlags & CMF_VERBSONLY) == 0 && (uFlags & CMF_DEFAULTONLY) == 0)
210    {
211        CString str;
212
213        try
214        {
215            if (pThis->m_bDragMenu)
216            {
217                if (pThis->m_bUseFiles)
218                    str.LoadString(IDS_MENU_TEXT_DRAG);
219                else
220                    return ResultFromShort(0);
221            }
222            else
223            {
224                if (!pThis->m_bUseFiles)
225                    str.LoadString(IDS_MENU_TEXT_DRIVE);
226                else
227                    str.LoadString(IDS_MENU_TEXT_FILE);
228            }
229
230            if (!InsertMenu(hMenu, nIndex++, MF_SEPARATOR| MF_BYPOSITION, idCmdFirst, ""))
231                return ResultFromShort(0);
232
233           
234            str = setShortcut(str);
235            if (!InsertMenu(hMenu, nIndex++ , MF_STRING | MF_BYPOSITION , idCmdFirst + CMD_ERASE, str))
236                return ResultFromShort(0);
237
238            CString moveStr;
239            //ASSERT(moveStr.LoadString(IDS_MENU_TEXT_DRAG));
240            moveStr.LoadString(IDS_MENU_TEXT_DRAG);
241           
242            moveStr = setShortcut(moveStr);
243            if (!InsertMenu(hMenu, nIndex++, MF_STRING | MF_BYPOSITION, idCmdFirst + CMD_MOVE, moveStr))
244                return ResultFromShort(0);
245
246
247            if (!InsertMenu(hMenu, nIndex++, MF_SEPARATOR| MF_BYPOSITION, idCmdFirst , ""))
248                return ResultFromShort(0);
249
250            return MAKE_HRESULT(SEVERITY_SUCCESS, 0, CMD_MOVE + 1);
251        }
252        catch (CException *e)
253        {
254            ASSERT(FALSE);
255
256            e->ReportError(MB_ICONERROR);
257            e->Delete();
258        }
259        catch (...)
260        {
261            ASSERT(FALSE);
262        }
263    }
264
265    return ResultFromShort(0);
266}
267
268BOOL GetFolder(HWND hParent, TCHAR* path)
269{
270
271    BROWSEINFO bi;
272    memset(&bi, 0, sizeof (bi));
273    bi.hwndOwner = hParent;
274    bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX;
275    bi.lpszTitle = "Select target folder";
276
277
278    LPITEMIDLIST pidlFolder;
279    pidlFolder = SHBrowseForFolder(&bi);
280    if (!pidlFolder)
281        return FALSE;
282
283    //HRESULT hr = SHGetTargetFolderIDList(pidlFolder, &pidlTarget);
284
285
286
287    SHGetPathFromIDList(pidlFolder, path);   // Make sure it is a path
288    CoTaskMemFree(pidlFolder);
289
290    return TRUE;
291   
292}
293STDMETHODIMP CErasextMenu::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
294{
295    METHOD_PROLOGUE(CErasextMenu, MenuExt);
296    TRACE("CErasextMenu::XMenuExt::InvokeCommand\n");
297
298    if (!HIWORD(lpici->lpVerb) &&
299        CMD_ERASE == LOWORD((DWORD)lpici->lpVerb) || CMD_MOVE == LOWORD((DWORD)lpici->lpVerb) )
300    {
301        ASSERT(IsWindow(lpici->hwnd));
302
303        CWnd parent;
304        parent.Attach(lpici->hwnd);
305
306        if (CMD_MOVE == LOWORD((DWORD)lpici->lpVerb))
307        {
308            pThis->m_bDragMenu = TRUE;
309        }
310
311        try
312        {
313            CConfirmDialog cd(&parent);
314
315            cd.m_bSingleFile    = FALSE;
316            cd.m_strData        = "?";
317            cd.m_bUseFiles      = pThis->m_bUseFiles;
318            cd.m_bMove          = pThis->m_bDragMenu;
319            cd.m_strTarget      = pThis->m_szDropTarget;
320
321            CString strTemp;
322
323            if (pThis->m_bUseFiles)
324            {
325                CStringList strlSourceFolders;
326
327                // get source folders if moving
328                if (pThis->m_bDragMenu)
329                {
330                    CString strSourceFolder;
331                    int iSize = pThis->m_saData.GetSize(), i;
332
333                    for (i = 0; i < iSize; i++)
334                    {
335                        strSourceFolder = pThis->m_saData[i];
336                        strSourceFolder = strSourceFolder.Left(strSourceFolder.ReverseFind('\\') + 1);
337
338                        if (strlSourceFolders.Find(strSourceFolder) == NULL)
339                            strlSourceFolders.AddTail(strSourceFolder);
340                    }
341
342                    iSize = pThis->m_saFolders.GetSize();
343
344                    for (i = 0; i < iSize; i++)
345                    {
346                        strSourceFolder = pThis->m_saFolders[i];
347                        if (strSourceFolder[strSourceFolder.GetLength() - 1] == '\\')
348                            strSourceFolder.Left(strSourceFolder.GetLength() - 1);
349
350                        strSourceFolder = strSourceFolder.Left(strSourceFolder.ReverseFind('\\') + 1);
351
352                        if (strlSourceFolders.Find(strSourceFolder) == NULL)
353                            strlSourceFolders.AddTail(strSourceFolder);
354                    }
355
356                    ASSERT(!strlSourceFolders.IsEmpty());
357                }
358
359                // parse files from the folders
360                if (pThis->m_dwDirectories > 0)
361                {
362                    CStringArray saSubfolders;
363                    int iSize = pThis->m_saFolders.GetSize(), i;
364
365                    // parseDirectory will recount all directories for us
366                    pThis->m_dwDirectories = 0;
367
368                    for (i = 0; i < iSize; i++)
369                    {
370                        parseDirectory((LPCTSTR)pThis->m_saFolders[i],
371                                       pThis->m_saData,
372                                       saSubfolders,
373                                       TRUE,
374                                       &pThis->m_dwItems,
375                                       &pThis->m_dwDirectories);
376                    }
377
378                    // add found subfolders to the list for removal
379                    if (saSubfolders.GetSize() > 0)
380                        pThis->m_saFolders.InsertAt(0, &saSubfolders);
381                }
382
383                // done parsing, continue if there is something to erase
384
385                if (pThis->m_dwItems > 0 || pThis->m_dwDirectories > 0)
386                {
387                    // select which confirmation message to show
388
389                    if (pThis->m_dwDirectories > 0)
390                    {
391                        // at least one folder and zero or more files
392                        if (!pThis->m_bDragMenu)
393                            strTemp.LoadString(IDS_CONFIRM_FILES_AND_FOLDERS);
394                        else
395                            strTemp.LoadString(IDS_CONFIRM_MOVE_FILES_AND_FOLDERS);
396
397                        cd.m_strData.Format(strTemp, pThis->m_dwItems, pThis->m_dwDirectories);
398                    }
399                    else if (pThis->m_dwItems == 1)
400                    {
401                        // only one file
402                        cd.m_strData = pThis->m_saData[0];
403                        cd.m_bSingleFile = TRUE;
404                    }
405                    else if (pThis->m_dwItems > 1)
406                    {
407                        // more than one file and no folders
408                        if (!pThis->m_bDragMenu)
409                            strTemp.LoadString(IDS_CONFIRM_FILES);
410                        else
411                            strTemp.LoadString(IDS_CONFIRM_MOVE_FILES);
412
413                        cd.m_strData.Format(strTemp, pThis->m_dwItems);
414                    }
415
416                    // ask for confirmation
417                    if (cd.m_bMove)
418                    {
419                        if ( !strlen(pThis->m_szDropTarget) 
420                            && !GetFolder(lpici->hwnd, pThis->m_szDropTarget))
421                        {
422                            parent.Detach();
423                            return NOERROR;
424                        }
425                        cd.m_strTarget = pThis->m_szDropTarget;
426
427                    }
428
429                    if (cd.DoModal() == IDOK)
430                    {
431                        if (pThis->m_bDragMenu)
432                        {
433                            // if there is data to copy
434                            CStringArray saFolders;
435                            if (pThis->m_saFolders.GetSize() > 0)
436                                saFolders.Copy(pThis->m_saFolders);
437                           
438                           
439                               
440                           
441                            if (!pThis->MoveFileList(&parent,                 // parent window
442                                                     pThis->m_saData,         // source files
443                                                     saFolders,               // source folders
444                                                     strlSourceFolders,       // source folders
445                                                     pThis->m_szDropTarget))  // destination folder
446                            {
447                                parent.Detach();
448                                return E_FAIL;
449                            }
450
451                            // the amount of items to erase
452                            pThis->m_dwItems = pThis->m_saData.GetSize();
453                        }
454
455                        if (pThis->m_dwItems > 0)
456                        {
457                            // if there are files to erase
458
459                            CEraserDlg dlgEraser(&parent);
460
461                            dlgEraser.m_bMove        = pThis->m_bDragMenu;
462                            dlgEraser.m_bShowResults = TRUE;
463                            dlgEraser.m_bUseFiles    = pThis->m_bUseFiles;
464                            dlgEraser.m_saData.Copy(pThis->m_saData);
465
466                            dlgEraser.DoModal();
467                        }
468
469                        if (pThis->m_dwDirectories > 0)
470                        {
471                            // if there are (empty) directories to remove
472
473                            int iSize = pThis->m_saFolders.GetSize(), i;
474                            for (i = 0; i < iSize; i++)
475                            {
476                                if (eraserOK(eraserRemoveFolder((LPVOID)(LPCTSTR)pThis->m_saFolders[i],
477                                        (E_UINT16)pThis->m_saFolders[i].GetLength(), ERASER_REMOVE_FOLDERONLY)))
478                                {
479                                    SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, (LPCTSTR)pThis->m_saFolders[i], NULL);
480                                }
481                            }
482                        }
483                    }
484                }
485            }
486            else if (!pThis->m_bDragMenu)
487            {
488                // drive(s)
489
490                if (pThis->m_dwItems > 1)
491                    cd.m_strData.LoadString(IDS_CONFIRM_MULTI_DRIVE);
492                else if (pThis->m_dwItems == 1)
493                {
494                    strTemp.LoadString(IDS_CONFIRM_DRIVE);
495                    cd.m_strData.Format((LPCTSTR)strTemp, pThis->m_saData[0]);
496                }
497
498                if (cd.DoModal() == IDOK)
499                {
500                    CEraserDlg dlgEraser(&parent);
501
502                    dlgEraser.m_saData.Copy(pThis->m_saData);
503                    dlgEraser.m_bShowResults = TRUE;
504                    dlgEraser.m_bUseFiles = pThis->m_bUseFiles;
505
506                    dlgEraser.DoModal();
507                }
508            }
509        }
510        catch (CException *e)
511        {
512            ASSERT(FALSE);
513
514            e->ReportError(MB_ICONERROR);
515            e->Delete();
516        }
517        catch (...)
518        {
519            ASSERT(FALSE);
520        }
521
522        parent.Detach();
523
524        return NOERROR;
525    }
526
527    return E_INVALIDARG;
528}
529
530void 
531CErasextMenu::getstr_handle_erase(UINT nType, CString& cmdstr)
532{
533    if (m_bUseFiles)
534    {
535        if (m_dwDirectories > 0)
536            cmdstr.LoadString(IDS_COMMAND_STRING_DIRECTORIES);
537        else
538            cmdstr.LoadString(IDS_COMMAND_STRING_FILE);
539    }
540    else
541    {
542        cmdstr.LoadString(IDS_COMMAND_STRING_DRIVE);
543    }
544
545}
546void 
547CErasextMenu::getstr_handle_move(UINT nType, CString& cmdstr)
548{
549   
550    cmdstr = "Move";
551}
552
553STDMETHODIMP CErasextMenu::XMenuExt::GetCommandString(UINT_PTR  idCmd, UINT nType, UINT* /*pnReserved*/, LPSTR lpszName, UINT nMax)
554{
555    METHOD_PROLOGUE(CErasextMenu, MenuExt);
556    TRACE("CErasextMenu::XMenuExt::GetCommandString\n");
557
558    CString cmdstr;
559    ZeroMemory(lpszName, nMax);
560    try
561    {
562        if (0 == idCmd )
563            pThis->getstr_handle_erase(nType, cmdstr);
564        else
565            if (1 == idCmd)
566                pThis->getstr_handle_move(nType, cmdstr);
567           
568           
569    }
570    catch (CException *e)
571    {
572        ASSERT(FALSE);
573
574        e->ReportError(MB_ICONERROR);
575        e->Delete();
576
577        return E_OUTOFMEMORY;
578    }
579    catch (...)
580    {
581        ASSERT(FALSE);
582        return E_FAIL;
583    }
584
585    if (!pThis->m_bNT)
586        lstrcpyn(lpszName, (LPCTSTR) cmdstr, nMax);
587    else
588    {
589        MultiByteToWideChar(CP_ACP, 0, (LPCSTR)cmdstr, -1, (LPWSTR)lpszName,
590            nMax / sizeof(WCHAR));
591    }
592    return NOERROR;
593}
594
595// IUnknown for IShellExtInit
596STDMETHODIMP CErasextMenu::XShellInit::QueryInterface(REFIID riid, void** ppv)
597{
598    METHOD_PROLOGUE(CErasextMenu, ShellInit);
599    TRACE("CErasextMenu::XShellInit::QueryInterface\n");
600    return pThis->ExternalQueryInterface(&riid, ppv);
601}
602
603STDMETHODIMP_(ULONG) CErasextMenu::XShellInit::AddRef(void)
604{
605    METHOD_PROLOGUE(CErasextMenu, ShellInit);
606    TRACE("CErasextMenu::XShellInit::AddRef\n");
607    return pThis->ExternalAddRef();
608}
609
610STDMETHODIMP_(ULONG) CErasextMenu::XShellInit::Release(void)
611{
612    METHOD_PROLOGUE(CErasextMenu, ShellInit);
613    TRACE("CErasextMenu::XShellInit::Release\n");
614    return pThis->ExternalRelease();
615}
616
617STDMETHODIMP CErasextMenu::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/)
618{
619    METHOD_PROLOGUE(CErasextMenu, ShellInit);
620    TRACE("CErasextMenu::XShellInit::Initialize\n");
621
622    HRESULT hres = E_FAIL;
623    STGMEDIUM medium;
624    FORMATETC fmte = {CF_HDROP,
625                      NULL,
626                      DVASPECT_CONTENT,
627                      -1,
628                      TYMED_HGLOBAL};
629
630    // duplicate the object pointer
631    if (lpdobj == NULL)
632    {
633        TRACE("CErasextMenu::XShellInit::Initialize() no data object\n");
634        return E_FAIL;
635    }
636
637    // Use the given IDataObject to get a list of filenames (CF_HDROP)
638    hres = lpdobj->GetData(&fmte, &medium);
639
640    if (FAILED(hres))
641    {
642        TRACE("CErasextMenu::XShellInit::Initialize() can't get data\n");
643        return E_FAIL;
644    }
645
646    // clear members
647    ZeroMemory(pThis->m_szDropTarget, MAX_PATH + 2);
648    pThis->m_saData.RemoveAll();
649    pThis->m_saFolders.RemoveAll();
650    pThis->m_dwItems = 0;
651    pThis->m_dwDirectories = 0;
652
653    if (pidlFolder != NULL &&
654        SHGetPathFromIDList(pidlFolder, pThis->m_szDropTarget))
655    {
656        TRACE1("Drop Target: %s\n", pThis->m_szDropTarget);
657        pThis->m_bDragMenu = TRUE;
658    }
659    else
660    {
661        pThis->m_bDragMenu = FALSE;
662        pThis->m_szDropTarget[0] = '\0';
663    }
664
665
666    BOOL bDrives = FALSE;
667    BOOL bFiles = FALSE;
668
669    UINT uAmount;
670    UINT uCount;
671    DWORD dwAttr;
672
673    TCHAR szFileName[MAX_PATH + 1];
674    ZeroMemory(szFileName, MAX_PATH + 1);
675
676    // Get the number of items selected.
677    uAmount = DragQueryFile(static_cast<HDROP>(medium.hGlobal),
678              static_cast<UINT>(-1), NULL, 0);
679
680    for (uCount = 0; uCount < uAmount; uCount++)
681    {
682        szFileName[0] = '\0';
683
684        DragQueryFile(static_cast<HDROP>(medium.hGlobal), uCount, szFileName, MAX_PATH);
685
686        if (!bFiles && lstrlen(szFileName) <= _MAX_DRIVE)
687        {
688            // drive
689            dwAttr = GetDriveType((LPCTSTR) szFileName);
690
691            if (dwAttr != DRIVE_UNKNOWN &&
692                dwAttr != DRIVE_NO_ROOT_DIR &&
693                dwAttr != DRIVE_CDROM &&
694                dwAttr != DRIVE_REMOTE)
695            {
696                pThis->m_saData.Add(szFileName);
697                bDrives = TRUE;
698
699                pThis->m_dwItems++;
700            }
701        }
702        else if (!bDrives)
703        {
704            dwAttr = GetFileAttributes(szFileName);
705
706            if (dwAttr != (DWORD)-1)
707            {
708                if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
709                {
710                    // folder - read files later
711                    pThis->m_saFolders.Add(szFileName);
712                    bFiles = TRUE;
713
714                    pThis->m_dwDirectories++;
715                }
716                else
717                {
718                    // file
719                    pThis->m_saData.Add(szFileName);
720                    bFiles = TRUE;
721
722                    pThis->m_dwItems++;
723                }
724            }
725        }
726    }
727
728    // Release the data.
729    ReleaseStgMedium(&medium);
730
731    if (bFiles)
732        pThis->m_bUseFiles = TRUE;
733    else if (bDrives)
734        pThis->m_bUseFiles = FALSE;
735    else
736        return E_FAIL;
737
738    return S_OK;
739}
740
741
742static inline void
743GetSourceFolderFromList(CString& strFolder, CString strFile, CStringList& strlList)
744{
745    POSITION pos = NULL;
746    int iPosition = -1;
747
748    if (strFile.IsEmpty())
749        return;
750
751    if (strFile[strFile.GetLength() - 1] == '\\')
752        strFile = strFile.Left(strFile.GetLength() - 1);
753
754    iPosition = strFile.ReverseFind('\\');
755
756    while (iPosition != -1)
757    {
758        strFile = strFile.Left(iPosition + 1);
759        pos = strlList.Find(strFile);
760
761        if (pos != NULL)
762        {
763            strFolder = strlList.GetAt(pos);
764            break;
765        }
766
767        strFile = strFile.Left(strFile.GetLength() - 1);
768        iPosition = strFile.ReverseFind('\\');
769    }
770}
771
772BOOL CErasextMenu::MoveFileList(CWnd *pParent, CStringArray& saList, CStringArray& saFolders,
773                                CStringList& strlSource, LPCTSTR szDestination)
774{
775    CStringArray saErase;
776    CString strFile;
777    CString strDestination(szDestination);
778    CString strTemp;
779    BOOL    bFailed = FALSE;
780    BOOL    bNoToAll = FALSE, bYesToAll = FALSE;
781    int     iSize, i;
782
783    if (strDestination.IsEmpty() || strlSource.IsEmpty())
784        return FALSE;
785
786    // folders
787    if (strDestination[strDestination.GetLength() - 1] != '\\')
788        strDestination += "\\";
789
790    // must reverse the order of folders on the list and
791    // convert pathnames to destination folder
792
793    iSize = saFolders.GetSize();
794    for (i = 0; i < iSize; i++)
795    {
796        GetSourceFolderFromList(strTemp, saFolders[i], strlSource);
797
798        // source and destination are same
799        if (strTemp.CompareNoCase(strDestination) == 0)
800        {
801            AfxMessageBox(IDS_ERROR_MOVE_SAMEFOLDER, MB_ICONERROR);
802            return FALSE;
803        }
804
805        strTemp = saFolders[i].Right(saFolders[i].GetLength() - strTemp.GetLength());
806        strTemp = strDestination + strTemp;
807        saErase.InsertAt(0, strTemp);
808    }
809
810    saFolders.RemoveAll();
811    if (saErase.GetSize() > 0)
812    {
813        saFolders.Copy(saErase);
814        saErase.RemoveAll();
815    }
816
817    // create destination folders
818
819    iSize = saFolders.GetSize();
820    for (i = 0; i < iSize; i++)
821    {
822        // don't care about the results; if the function fails,
823        // the folder either exists or then we'll catch the error
824        // when trying to copy files to this directory
825
826        CreateDirectory((LPCTSTR)saFolders[i], NULL);
827    }
828
829    // copy files
830
831    iSize = saList.GetSize();
832    for (i = 0; i < iSize; i++)
833    {
834        GetSourceFolderFromList(strTemp, saList[i], strlSource);
835        strTemp = saList[i].Right(saList[i].GetLength() - strTemp.GetLength());
836        strTemp = strDestination + strTemp;
837
838        if (!CopyFile((LPCTSTR)saList[i], (LPCTSTR)strTemp, TRUE))
839        {
840            if (GetLastError() == ERROR_FILE_EXISTS)
841            {
842                if (bNoToAll)
843                {
844                    // never overwrite the destination
845                    continue;
846                }
847                else
848                {
849                    CConfirmReplaceDlg crd(pParent);
850
851                    crd.SetExisting((LPCTSTR)strTemp);
852                    crd.SetSource((LPCTSTR)saList[i]);
853
854                    if (bYesToAll || crd.DoModal() == IDOK)
855                    {
856                        bFailed = (CopyFile((LPCTSTR)saList[i], (LPCTSTR)strTemp, FALSE) == FALSE);
857
858                        if (!bYesToAll)
859                            bYesToAll = crd.ApplyToAll();
860                    }
861                    else
862                    {
863                        if (!bYesToAll && !bNoToAll)
864                            bNoToAll = crd.ApplyToAll();
865
866                        // do not erase the source
867                        continue;
868                    }
869                }
870            }
871            else
872            {
873                bFailed = TRUE;
874            }
875        }
876
877        if (bFailed)
878        {
879            DisplayError(GetLastError());
880            return FALSE;
881        }
882
883        // if file was copied, set the source to be
884        // erased
885
886        saErase.Add(saList[i]);
887    }
888
889    // set the file list
890    saList.RemoveAll();
891    if (saErase.GetSize() > 0)
892        saList.Copy(saErase);
893
894    return TRUE;
895}
Note: See TracBrowser for help on using the repository browser.