source: trunk/Erasext/ErasextMenu.cpp @ 5

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

Added the source files from Erasext (SVN migration commit 3)

  • 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    BOOL bEnabled = TRUE;
169    CString strPath(""), strKey(""), strRes("");
170    strPath.Format("%s\\%s", ERASER_REGISTRY_BASE, szAccelerKey);
171    int iPos;
172    if (kReg.Open(HKEY_CURRENT_USER, strPath,FALSE))
173    {
174        if ((iPos=str.Find('&'))!=-1) {
175            str = str.Left(iPos) + str.Right(str.GetLength()-iPos-1);
176        }
177        if (kReg.GetValue(strKey,str))
178        {           
179            CString strTmp(str);
180            strKey.MakeUpper();
181            strTmp.MakeUpper();
182            iPos=strTmp.Find(strKey[0]);
183            strRes = str.Left(iPos)+"&"+str.Right(str.GetLength()-iPos);
184        }
185        kReg.Close();
186    }   
187    else{
188        strRes = str;
189    }
190    return strRes;
191}
192
193STDMETHODIMP CErasextMenu::XMenuExt::QueryContextMenu(HMENU hMenu, UINT nIndex, UINT idCmdFirst, UINT /*idCmdLast*/, UINT uFlags)
194{
195    METHOD_PROLOGUE(CErasextMenu, MenuExt);
196
197    // do not show menu for shortcuts or when the shell
198    // wants only the default item, or if the user has disabled
199    // the shell extension
200
201    CKey kReg;
202    BOOL bEnabled = TRUE;
203   
204    if (kReg.Open(HKEY_CURRENT_USER, ERASER_REGISTRY_BASE))
205    {
206        kReg.GetValue(bEnabled, ERASEXT_REGISTRY_ENABLED, TRUE);
207        kReg.Close();
208    }
209
210    if (bEnabled && (uFlags & CMF_VERBSONLY) == 0 && (uFlags & CMF_DEFAULTONLY) == 0)
211    {
212        CString str;
213
214        try
215        {
216            if (pThis->m_bDragMenu)
217            {
218                if (pThis->m_bUseFiles)
219                    str.LoadString(IDS_MENU_TEXT_DRAG);
220                else
221                    return ResultFromShort(0);
222            }
223            else
224            {
225                if (!pThis->m_bUseFiles)
226                    str.LoadString(IDS_MENU_TEXT_DRIVE);
227                else
228                    str.LoadString(IDS_MENU_TEXT_FILE);
229            }
230
231            if (!InsertMenu(hMenu, nIndex++, MF_SEPARATOR| MF_BYPOSITION, idCmdFirst, ""))
232                return ResultFromShort(0);
233
234           
235            str = setShortcut(str);
236            if (!InsertMenu(hMenu, nIndex++ , MF_STRING | MF_BYPOSITION , idCmdFirst + CMD_ERASE, str))
237                return ResultFromShort(0);
238
239            CString moveStr;
240            //ASSERT(moveStr.LoadString(IDS_MENU_TEXT_DRAG));
241            moveStr.LoadString(IDS_MENU_TEXT_DRAG);
242           
243            moveStr = setShortcut(moveStr);
244            if (!InsertMenu(hMenu, nIndex++, MF_STRING | MF_BYPOSITION, idCmdFirst + CMD_MOVE, moveStr))
245                return ResultFromShort(0);
246
247
248            if (!InsertMenu(hMenu, nIndex++, MF_SEPARATOR| MF_BYPOSITION, idCmdFirst , ""))
249                return ResultFromShort(0);
250
251            return MAKE_HRESULT(SEVERITY_SUCCESS, 0, CMD_MOVE + 1);
252        }
253        catch (CException *e)
254        {
255            ASSERT(FALSE);
256
257            e->ReportError(MB_ICONERROR);
258            e->Delete();
259        }
260        catch (...)
261        {
262            ASSERT(FALSE);
263        }
264    }
265
266    return ResultFromShort(0);
267}
268
269BOOL GetFolder(HWND hParent, TCHAR* path)
270{
271
272    BROWSEINFO bi;
273    memset(&bi, 0, sizeof (bi));
274    bi.hwndOwner = hParent;
275    bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX;
276    bi.lpszTitle = "Select target folder";
277
278
279    LPITEMIDLIST pidlFolder, pidlTarget = NULL;
280    pidlFolder = SHBrowseForFolder(&bi);
281    if (!pidlFolder)
282        return FALSE;
283
284    //HRESULT hr = SHGetTargetFolderIDList(pidlFolder, &pidlTarget);
285
286
287
288    SHGetPathFromIDList(pidlFolder, path);   // Make sure it is a path
289    CoTaskMemFree(pidlFolder);
290
291    return TRUE;
292   
293}
294STDMETHODIMP CErasextMenu::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
295{
296    METHOD_PROLOGUE(CErasextMenu, MenuExt);
297    TRACE("CErasextMenu::XMenuExt::InvokeCommand\n");
298
299    if (!HIWORD(lpici->lpVerb) &&
300        CMD_ERASE == LOWORD((DWORD)lpici->lpVerb) || CMD_MOVE == LOWORD((DWORD)lpici->lpVerb) )
301    {
302        ASSERT(IsWindow(lpici->hwnd));
303
304        CWnd parent;
305        parent.Attach(lpici->hwnd);
306
307        if (CMD_MOVE == LOWORD((DWORD)lpici->lpVerb))
308        {
309            pThis->m_bDragMenu = TRUE;
310        }
311
312        try
313        {
314            CConfirmDialog cd(&parent);
315
316            cd.m_bSingleFile    = FALSE;
317            cd.m_strData        = "?";
318            cd.m_bUseFiles      = pThis->m_bUseFiles;
319            cd.m_bMove          = pThis->m_bDragMenu;
320            cd.m_strTarget      = pThis->m_szDropTarget;
321
322            CString strTemp;
323
324            if (pThis->m_bUseFiles)
325            {
326                CStringList strlSourceFolders;
327
328                // get source folders if moving
329                if (pThis->m_bDragMenu)
330                {
331                    CString strSourceFolder;
332                    int iSize = pThis->m_saData.GetSize(), i;
333
334                    for (i = 0; i < iSize; i++)
335                    {
336                        strSourceFolder = pThis->m_saData[i];
337                        strSourceFolder = strSourceFolder.Left(strSourceFolder.ReverseFind('\\') + 1);
338
339                        if (strlSourceFolders.Find(strSourceFolder) == NULL)
340                            strlSourceFolders.AddTail(strSourceFolder);
341                    }
342
343                    iSize = pThis->m_saFolders.GetSize();
344
345                    for (i = 0; i < iSize; i++)
346                    {
347                        strSourceFolder = pThis->m_saFolders[i];
348                        if (strSourceFolder[strSourceFolder.GetLength() - 1] == '\\')
349                            strSourceFolder.Left(strSourceFolder.GetLength() - 1);
350
351                        strSourceFolder = strSourceFolder.Left(strSourceFolder.ReverseFind('\\') + 1);
352
353                        if (strlSourceFolders.Find(strSourceFolder) == NULL)
354                            strlSourceFolders.AddTail(strSourceFolder);
355                    }
356
357                    ASSERT(!strlSourceFolders.IsEmpty());
358                }
359
360                // parse files from the folders
361                if (pThis->m_dwDirectories > 0)
362                {
363                    CStringArray saSubfolders;
364                    int iSize = pThis->m_saFolders.GetSize(), i;
365
366                    // parseDirectory will recount all directories for us
367                    pThis->m_dwDirectories = 0;
368
369                    for (i = 0; i < iSize; i++)
370                    {
371                        parseDirectory((LPCTSTR)pThis->m_saFolders[i],
372                                       pThis->m_saData,
373                                       saSubfolders,
374                                       TRUE,
375                                       &pThis->m_dwItems,
376                                       &pThis->m_dwDirectories);
377                    }
378
379                    // add found subfolders to the list for removal
380                    if (saSubfolders.GetSize() > 0)
381                        pThis->m_saFolders.InsertAt(0, &saSubfolders);
382                }
383
384                // done parsing, continue if there is something to erase
385
386                if (pThis->m_dwItems > 0 || pThis->m_dwDirectories > 0)
387                {
388                    // select which confirmation message to show
389
390                    if (pThis->m_dwDirectories > 0)
391                    {
392                        // at least one folder and zero or more files
393                        if (!pThis->m_bDragMenu)
394                            strTemp.LoadString(IDS_CONFIRM_FILES_AND_FOLDERS);
395                        else
396                            strTemp.LoadString(IDS_CONFIRM_MOVE_FILES_AND_FOLDERS);
397
398                        cd.m_strData.Format(strTemp, pThis->m_dwItems, pThis->m_dwDirectories);
399                    }
400                    else if (pThis->m_dwItems == 1)
401                    {
402                        // only one file
403                        cd.m_strData = pThis->m_saData[0];
404                        cd.m_bSingleFile = TRUE;
405                    }
406                    else if (pThis->m_dwItems > 1)
407                    {
408                        // more than one file and no folders
409                        if (!pThis->m_bDragMenu)
410                            strTemp.LoadString(IDS_CONFIRM_FILES);
411                        else
412                            strTemp.LoadString(IDS_CONFIRM_MOVE_FILES);
413
414                        cd.m_strData.Format(strTemp, pThis->m_dwItems);
415                    }
416
417                    // ask for confirmation
418                    if (cd.m_bMove)
419                    {
420                        if ( !strlen(pThis->m_szDropTarget) 
421                            && !GetFolder(lpici->hwnd, pThis->m_szDropTarget))
422                        {
423                            parent.Detach();
424                            return NOERROR;
425                        }
426                        cd.m_strTarget = pThis->m_szDropTarget;
427
428                    }
429
430                    if (cd.DoModal() == IDOK)
431                    {
432                        if (pThis->m_bDragMenu)
433                        {
434                            // if there is data to copy
435                            CStringArray saFolders;
436                            if (pThis->m_saFolders.GetSize() > 0)
437                                saFolders.Copy(pThis->m_saFolders);
438                           
439                           
440                               
441                           
442                            if (!pThis->MoveFileList(&parent,                 // parent window
443                                                     pThis->m_saData,         // source files
444                                                     saFolders,               // source folders
445                                                     strlSourceFolders,       // source folders
446                                                     pThis->m_szDropTarget))  // destination folder
447                            {
448                                parent.Detach();
449                                return E_FAIL;
450                            }
451
452                            // the amount of items to erase
453                            pThis->m_dwItems = pThis->m_saData.GetSize();
454                        }
455
456                        if (pThis->m_dwItems > 0)
457                        {
458                            // if there are files to erase
459
460                            CEraserDlg dlgEraser(&parent);
461
462                            dlgEraser.m_bMove        = pThis->m_bDragMenu;
463                            dlgEraser.m_bShowResults = TRUE;
464                            dlgEraser.m_bUseFiles    = pThis->m_bUseFiles;
465                            dlgEraser.m_saData.Copy(pThis->m_saData);
466
467                            dlgEraser.DoModal();
468                        }
469
470                        if (pThis->m_dwDirectories > 0)
471                        {
472                            // if there are (empty) directories to remove
473
474                            int iSize = pThis->m_saFolders.GetSize(), i;
475                            for (i = 0; i < iSize; i++)
476                            {
477                                if (eraserOK(eraserRemoveFolder((LPVOID)(LPCTSTR)pThis->m_saFolders[i],
478                                        (E_UINT16)pThis->m_saFolders[i].GetLength(), ERASER_REMOVE_FOLDERONLY)))
479                                {
480                                    SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, (LPCTSTR)pThis->m_saFolders[i], NULL);
481                                }
482                            }
483                        }
484                    }
485                }
486            }
487            else if (!pThis->m_bDragMenu)
488            {
489                // drive(s)
490
491                if (pThis->m_dwItems > 1)
492                    cd.m_strData.LoadString(IDS_CONFIRM_MULTI_DRIVE);
493                else if (pThis->m_dwItems == 1)
494                {
495                    strTemp.LoadString(IDS_CONFIRM_DRIVE);
496                    cd.m_strData.Format((LPCTSTR)strTemp, pThis->m_saData[0]);
497                }
498
499                if (cd.DoModal() == IDOK)
500                {
501                    CEraserDlg dlgEraser(&parent);
502
503                    dlgEraser.m_saData.Copy(pThis->m_saData);
504                    dlgEraser.m_bShowResults = TRUE;
505                    dlgEraser.m_bUseFiles = pThis->m_bUseFiles;
506
507                    dlgEraser.DoModal();
508                }
509            }
510        }
511        catch (CException *e)
512        {
513            ASSERT(FALSE);
514
515            e->ReportError(MB_ICONERROR);
516            e->Delete();
517        }
518        catch (...)
519        {
520            ASSERT(FALSE);
521        }
522
523        parent.Detach();
524
525        return NOERROR;
526    }
527
528    return E_INVALIDARG;
529}
530
531void 
532CErasextMenu::getstr_handle_erase(UINT nType, CString& cmdstr)
533{
534    if (m_bUseFiles)
535    {
536        if (m_dwDirectories > 0)
537            cmdstr.LoadString(IDS_COMMAND_STRING_DIRECTORIES);
538        else
539            cmdstr.LoadString(IDS_COMMAND_STRING_FILE);
540    }
541    else
542    {
543        cmdstr.LoadString(IDS_COMMAND_STRING_DRIVE);
544    }
545
546}
547void 
548CErasextMenu::getstr_handle_move(UINT nType, CString& cmdstr)
549{
550   
551    cmdstr = "Move";
552}
553
554STDMETHODIMP CErasextMenu::XMenuExt::GetCommandString(UINT_PTR  idCmd, UINT nType, UINT* /*pnReserved*/, LPSTR lpszName, UINT nMax)
555{
556    METHOD_PROLOGUE(CErasextMenu, MenuExt);
557    TRACE("CErasextMenu::XMenuExt::GetCommandString\n");
558
559    CString cmdstr;
560    ZeroMemory(lpszName, nMax);
561    try
562    {
563        if (0 == idCmd )
564            pThis->getstr_handle_erase(nType, cmdstr);
565        else
566            if (1 == idCmd)
567                pThis->getstr_handle_move(nType, cmdstr);
568           
569           
570    }
571    catch (CException *e)
572    {
573        ASSERT(FALSE);
574
575        e->ReportError(MB_ICONERROR);
576        e->Delete();
577
578        return E_OUTOFMEMORY;
579    }
580    catch (...)
581    {
582        ASSERT(FALSE);
583        return E_FAIL;
584    }
585
586    if (!pThis->m_bNT)
587        lstrcpyn(lpszName, (LPCTSTR) cmdstr, nMax);
588    else
589    {
590        MultiByteToWideChar(CP_ACP, 0, (LPCSTR)cmdstr, -1, (LPWSTR)lpszName,
591            nMax / sizeof(WCHAR));
592    }
593    return NOERROR;
594}
595
596// IUnknown for IShellExtInit
597STDMETHODIMP CErasextMenu::XShellInit::QueryInterface(REFIID riid, void** ppv)
598{
599    METHOD_PROLOGUE(CErasextMenu, ShellInit);
600    TRACE("CErasextMenu::XShellInit::QueryInterface\n");
601    return pThis->ExternalQueryInterface(&riid, ppv);
602}
603
604STDMETHODIMP_(ULONG) CErasextMenu::XShellInit::AddRef(void)
605{
606    METHOD_PROLOGUE(CErasextMenu, ShellInit);
607    TRACE("CErasextMenu::XShellInit::AddRef\n");
608    return pThis->ExternalAddRef();
609}
610
611STDMETHODIMP_(ULONG) CErasextMenu::XShellInit::Release(void)
612{
613    METHOD_PROLOGUE(CErasextMenu, ShellInit);
614    TRACE("CErasextMenu::XShellInit::Release\n");
615    return pThis->ExternalRelease();
616}
617
618STDMETHODIMP CErasextMenu::XShellInit::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/)
619{
620    METHOD_PROLOGUE(CErasextMenu, ShellInit);
621    TRACE("CErasextMenu::XShellInit::Initialize\n");
622
623    HRESULT hres = E_FAIL;
624    STGMEDIUM medium;
625    FORMATETC fmte = {CF_HDROP,
626                      NULL,
627                      DVASPECT_CONTENT,
628                      -1,
629                      TYMED_HGLOBAL};
630
631    // duplicate the object pointer
632    if (lpdobj == NULL)
633    {
634        TRACE("CErasextMenu::XShellInit::Initialize() no data object\n");
635        return E_FAIL;
636    }
637
638    // Use the given IDataObject to get a list of filenames (CF_HDROP)
639    hres = lpdobj->GetData(&fmte, &medium);
640
641    if (FAILED(hres))
642    {
643        TRACE("CErasextMenu::XShellInit::Initialize() can't get data\n");
644        return E_FAIL;
645    }
646
647    // clear members
648    ZeroMemory(pThis->m_szDropTarget, MAX_PATH + 2);
649    pThis->m_saData.RemoveAll();
650    pThis->m_saFolders.RemoveAll();
651    pThis->m_dwItems = 0;
652    pThis->m_dwDirectories = 0;
653
654    if (pidlFolder != NULL &&
655        SHGetPathFromIDList(pidlFolder, pThis->m_szDropTarget))
656    {
657        TRACE1("Drop Target: %s\n", pThis->m_szDropTarget);
658        pThis->m_bDragMenu = TRUE;
659    }
660    else
661    {
662        pThis->m_bDragMenu = FALSE;
663        pThis->m_szDropTarget[0] = '\0';
664    }
665
666
667    BOOL bDrives = FALSE;
668    BOOL bFiles = FALSE;
669
670    UINT uAmount;
671    UINT uCount;
672    DWORD dwAttr;
673
674    TCHAR szFileName[MAX_PATH + 1];
675    ZeroMemory(szFileName, MAX_PATH + 1);
676
677    // Get the number of items selected.
678    uAmount = DragQueryFile(static_cast<HDROP>(medium.hGlobal),
679              static_cast<UINT>(-1), NULL, 0);
680
681    for (uCount = 0; uCount < uAmount; uCount++)
682    {
683        szFileName[0] = '\0';
684
685        DragQueryFile(static_cast<HDROP>(medium.hGlobal), uCount, szFileName, MAX_PATH);
686
687        if (!bFiles && lstrlen(szFileName) <= _MAX_DRIVE)
688        {
689            // drive
690            dwAttr = GetDriveType((LPCTSTR) szFileName);
691
692            if (dwAttr != DRIVE_UNKNOWN &&
693                dwAttr != DRIVE_NO_ROOT_DIR &&
694                dwAttr != DRIVE_CDROM &&
695                dwAttr != DRIVE_REMOTE)
696            {
697                pThis->m_saData.Add(szFileName);
698                bDrives = TRUE;
699
700                pThis->m_dwItems++;
701            }
702        }
703        else if (!bDrives)
704        {
705            dwAttr = GetFileAttributes(szFileName);
706
707            if (dwAttr != (DWORD)-1)
708            {
709                if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
710                {
711                    // folder - read files later
712                    pThis->m_saFolders.Add(szFileName);
713                    bFiles = TRUE;
714
715                    pThis->m_dwDirectories++;
716                }
717                else
718                {
719                    // file
720                    pThis->m_saData.Add(szFileName);
721                    bFiles = TRUE;
722
723                    pThis->m_dwItems++;
724                }
725            }
726        }
727    }
728
729    // Release the data.
730    ReleaseStgMedium(&medium);
731
732    if (bFiles)
733        pThis->m_bUseFiles = TRUE;
734    else if (bDrives)
735        pThis->m_bUseFiles = FALSE;
736    else
737        return E_FAIL;
738
739    return S_OK;
740}
741
742
743static inline void
744GetSourceFolderFromList(CString& strFolder, CString strFile, CStringList& strlList)
745{
746    POSITION pos = NULL;
747    int iPosition = -1;
748
749    if (strFile.IsEmpty())
750        return;
751
752    if (strFile[strFile.GetLength() - 1] == '\\')
753        strFile = strFile.Left(strFile.GetLength() - 1);
754
755    iPosition = strFile.ReverseFind('\\');
756
757    while (iPosition != -1)
758    {
759        strFile = strFile.Left(iPosition + 1);
760        pos = strlList.Find(strFile);
761
762        if (pos != NULL)
763        {
764            strFolder = strlList.GetAt(pos);
765            break;
766        }
767
768        strFile = strFile.Left(strFile.GetLength() - 1);
769        iPosition = strFile.ReverseFind('\\');
770    }
771}
772
773BOOL CErasextMenu::MoveFileList(CWnd *pParent, CStringArray& saList, CStringArray& saFolders,
774                                CStringList& strlSource, LPCTSTR szDestination)
775{
776    CStringArray saErase;
777    CString strFile;
778    CString strDestination(szDestination);
779    CString strTemp;
780    BOOL    bFailed = FALSE;
781    BOOL    bNoToAll = FALSE, bYesToAll = FALSE;
782    int     iSize, i;
783
784    if (strDestination.IsEmpty() || strlSource.IsEmpty())
785        return FALSE;
786
787    // folders
788    if (strDestination[strDestination.GetLength() - 1] != '\\')
789        strDestination += "\\";
790
791    // must reverse the order of folders on the list and
792    // convert pathnames to destination folder
793
794    iSize = saFolders.GetSize();
795    for (i = 0; i < iSize; i++)
796    {
797        GetSourceFolderFromList(strTemp, saFolders[i], strlSource);
798
799        // source and destination are same
800        if (strTemp.CompareNoCase(strDestination) == 0)
801        {
802            AfxMessageBox(IDS_ERROR_MOVE_SAMEFOLDER, MB_ICONERROR);
803            return FALSE;
804        }
805
806        strTemp = saFolders[i].Right(saFolders[i].GetLength() - strTemp.GetLength());
807        strTemp = strDestination + strTemp;
808        saErase.InsertAt(0, strTemp);
809    }
810
811    saFolders.RemoveAll();
812    if (saErase.GetSize() > 0)
813    {
814        saFolders.Copy(saErase);
815        saErase.RemoveAll();
816    }
817
818    // create destination folders
819
820    iSize = saFolders.GetSize();
821    for (i = 0; i < iSize; i++)
822    {
823        // don't care about the results; if the function fails,
824        // the folder either exists or then we'll catch the error
825        // when trying to copy files to this directory
826
827        CreateDirectory((LPCTSTR)saFolders[i], NULL);
828    }
829
830    // copy files
831
832    iSize = saList.GetSize();
833    for (i = 0; i < iSize; i++)
834    {
835        GetSourceFolderFromList(strTemp, saList[i], strlSource);
836        strTemp = saList[i].Right(saList[i].GetLength() - strTemp.GetLength());
837        strTemp = strDestination + strTemp;
838
839        if (!CopyFile((LPCTSTR)saList[i], (LPCTSTR)strTemp, TRUE))
840        {
841            if (GetLastError() == ERROR_FILE_EXISTS)
842            {
843                if (bNoToAll)
844                {
845                    // never overwrite the destination
846                    continue;
847                }
848                else
849                {
850                    CConfirmReplaceDlg crd(pParent);
851
852                    crd.SetExisting((LPCTSTR)strTemp);
853                    crd.SetSource((LPCTSTR)saList[i]);
854
855                    if (bYesToAll || crd.DoModal() == IDOK)
856                    {
857                        bFailed = (CopyFile((LPCTSTR)saList[i], (LPCTSTR)strTemp, FALSE) == FALSE);
858
859                        if (!bYesToAll)
860                            bYesToAll = crd.ApplyToAll();
861                    }
862                    else
863                    {
864                        if (!bYesToAll && !bNoToAll)
865                            bNoToAll = crd.ApplyToAll();
866
867                        // do not erase the source
868                        continue;
869                    }
870                }
871            }
872            else
873            {
874                bFailed = TRUE;
875            }
876        }
877
878        if (bFailed)
879        {
880            DisplayError(GetLastError());
881            return FALSE;
882        }
883
884        // if file was copied, set the source to be
885        // erased
886
887        saErase.Add(saList[i]);
888    }
889
890    // set the file list
891    saList.RemoveAll();
892    if (saErase.GetSize() > 0)
893        saList.Copy(saErase);
894
895    return TRUE;
896}
Note: See TracBrowser for help on using the repository browser.