source: trunk/Launcher/Launcher.cpp @ 23

Revision 23, 21.1 KB checked in by lowjoel, 7 years ago (diff)

Move all third-party code to the Shared and EraserUI folders. EraserUI contains UI-specific controls and other miscellany, Shared contains code helper classes.
EXCEPTION: DropTargetWnd?, OleTreeCtrl? and ShellTree? are elft in the root, because they have been modified quite extensively.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1//
2// -disk k:\ -method random 1 -results
3//
4// Launcher.cpp
5//
6// Eraser. Secure data removal. For Windows.
7// Copyright © 1997-2001  Sami Tolvanen (sami@tolvanen.com).
8//
9// This program is free software; you can redistribute it and/or
10// modify it under the terms of the GNU General Public License
11// as published by the Free Software Foundation; either version 2
12// of the License, or (at your option) any later version.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22// 02111-1307, USA.
23
24#include "stdafx.h"
25#include "..\EraserDll\EraserDll.h"
26#include "..\EraserUI\DriveCombo.h"
27#include "..\shared\FileHelper.h"
28#include "..\shared\UserInfo.h"
29#include "..\EraserDll\FileLockResolver.h"
30#include "Launcher.h"
31#include "ConfirmDialog.h"
32#include "LauncherDlg.h"
33#include <exception>
34#ifdef _DEBUG
35#define new DEBUG_NEW
36#undef THIS_FILE
37static char THIS_FILE[] = __FILE__;
38#endif
39
40/////////////////////////////////////////////////////////////////////////////
41// CLauncherApp
42
43BEGIN_MESSAGE_MAP(CLauncherApp, CWinApp)
44    //{{AFX_MSG_MAP(CLauncherApp)
45        // NOTE - the ClassWizard will add and remove mapping macros here.
46        //    DO NOT EDIT what you see in these blocks of generated code!
47    //}}AFX_MSG
48    ON_COMMAND(ID_HELP, CWinApp::OnHelp)
49END_MESSAGE_MAP()
50
51/////////////////////////////////////////////////////////////////////////////
52// CLauncherApp construction
53
54CLauncherApp::CLauncherApp() :
55m_pdlgEraser(0),
56m_hQueue(NULL)
57{
58    _set_se_translator(SeTranslator);
59}
60
61/////////////////////////////////////////////////////////////////////////////
62// The one and only CLauncherApp object
63
64CLauncherApp theApp;
65
66static BOOL ParseRecycledDirectory(LPCTSTR szDirectory, CStringArray& saFiles,
67                                   CStringArray& saDirectories, BOOL bNoINFO)
68{
69    static int      iRecursion = 0;
70
71    BOOL            bResult = FALSE;
72    HANDLE          hFind;
73    WIN32_FIND_DATA wfdData;
74
75    iRecursion++;
76
77    CString         strTemp;
78    CString         strDirectory(szDirectory);
79
80    // do not include the base directory
81    if (iRecursion > 1)
82        saDirectories.InsertAt(0, strDirectory);
83
84    if (!strDirectory.IsEmpty())
85    {
86        if (strDirectory[strDirectory.GetLength() - 1] != '\\')
87            strDirectory += "\\";
88
89        strTemp = strDirectory + "*";
90
91        hFind = FindFirstFile((LPCTSTR) strTemp, &wfdData);
92
93        if (hFind != INVALID_HANDLE_VALUE)
94        {
95            do
96            {
97                if (wfdData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
98                {
99                    // skip "." and ".."
100                    if (ISNT_SUBFOLDER(wfdData.cFileName))
101                        continue;
102
103                    strTemp = strDirectory + wfdData.cFileName;
104
105                    // recursive
106                    ParseRecycledDirectory((LPCTSTR) strTemp,
107                                           saFiles, saDirectories,
108                                           bNoINFO);
109                }
110                else
111                {
112                    if (_stricmp(wfdData.cFileName, "desktop.ini") == 0)
113                        continue;
114
115                    if (bNoINFO && _strnicmp(wfdData.cFileName, "INFO", 4) == 0)
116                        continue;
117
118                    strTemp = strDirectory + wfdData.cFileName;
119                    saFiles.Add(strTemp);
120                }
121            }
122            while (FindNextFile(hFind, &wfdData));
123
124            VERIFY(FindClose(hFind));
125
126            bResult = TRUE;
127        }
128    }
129
130    iRecursion--;
131    return bResult;
132}
133
134struct VersionHelper
135{
136    bool isVista;
137    VersionHelper()
138    {
139        isVista = false;
140
141        OSVERSIONINFOEX osvi;
142        BOOL bOsVersionInfoEx;
143
144        ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
145
146        // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
147        // If that fails, try using the OSVERSIONINFO structure.
148
149        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
150
151        if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
152        {
153            osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
154            if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 
155                return ;
156        }
157        if (VER_PLATFORM_WIN32_NT  == osvi.dwPlatformId )
158        {
159            if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
160            {
161
162                /*if( osvi.wProductType == VER_NT_WORKSTATION )
163                printf ("Windows Vista ");
164                else printf ("Windows Server \"Longhorn\" " );
165           
166            */
167                isVista = true;
168            }
169        }
170    }
171};
172static void LocateRecycledItems(CStringArray& saRecycled, CStringArray& saRecycledDirectories)
173{
174    CStringArray    straDrives;
175    CStringArray    lstraDrives;
176    TCHAR           szFS[MAX_PATH];
177    DWORD           dwFileSystem;
178    DWORD           dwAttributes;
179    int             iSize;
180    CString         strSID;
181    static VersionHelper version;
182
183    saRecycled.RemoveAll();
184    saRecycledDirectories.RemoveAll();
185
186    // find all hard drives installed to the system
187
188    GetLocalHardDrives(lstraDrives);
189
190    // determine user SID (works on NT only)
191
192    GetCurrentUserTextualSid(strSID);
193
194    // determine the location of the Recycle Bin (depending on the file system)
195
196    iSize = lstraDrives.GetSize();
197
198
199    while (iSize--)
200    {
201        if (GetVolumeInformation((LPCTSTR)lstraDrives[iSize], NULL, 0, NULL, NULL,
202            &dwFileSystem, szFS, MAX_PATH))
203        {
204            if (_stricmp(szFS, "NTFS") == 0)
205            {
206                straDrives.Add(lstraDrives[iSize]+ "RECYCLER\\NPROTECT");
207                straDrives.Add(lstraDrives[iSize] + "$Recycle.Bin\\");
208                straDrives.Add(lstraDrives[iSize] + "$Recycle.Bin\\NPROTECT");
209                if (!strSID.IsEmpty())
210                {
211                    //straDrives.SetAt(iSize, straDrives[iSize] + "RECYCLER\\" + strSID);                   
212                    straDrives.Add(lstraDrives[iSize] + "RECYCLER\\" + strSID);     
213                    straDrives.Add(lstraDrives[iSize] + "$Recycle.Bin\\" + strSID);
214                }
215                else
216                {
217                    //straDrives.SetAt(iSize, straDrives[iSize] + "RECYCLER");
218                    straDrives.Add(lstraDrives[iSize] + "RECYCLER");
219                    straDrives.Add(lstraDrives[iSize] + "$Recycle.Bin\\");
220                }
221            }
222            else
223                //straDrives.SetAt(iSize, straDrives[iSize] + "RECYCLED");
224                straDrives.Add(lstraDrives[iSize] + "RECYCLED");
225           
226        }
227    }
228
229   
230    // parse contents of the Recycle Bin folders except for the "desktop.ini"
231    // files
232
233    CString strTemp;
234    BOOL    bNoINFO = FALSE;
235    iSize = straDrives.GetSize();
236
237    HINSTANCE         hShell = AfxLoadLibrary(szShell32);
238    SHEMPTYRECYCLEBIN pSHEmptyRecycleBin = 0;
239
240    if (hShell)
241    {
242        pSHEmptyRecycleBin =
243            (SHEMPTYRECYCLEBIN)GetProcAddress(hShell, szSHEmptyRecycleBin);
244
245        bNoINFO = (pSHEmptyRecycleBin != NULL);
246
247        AfxFreeLibrary(hShell);
248    }
249
250    while (iSize--)
251    {
252        strTemp = straDrives[iSize];
253        dwAttributes = GetFileAttributes((LPCTSTR)straDrives[iSize]);
254
255        if (dwAttributes != (DWORD) -1 && dwAttributes & FILE_ATTRIBUTE_SYSTEM)
256        {
257            strTemp = straDrives[iSize];
258
259            ParseRecycledDirectory(strTemp,
260               saRecycled,
261               saRecycledDirectories,
262               bNoINFO);
263        }
264    }
265
266#if 0
267    CString strRecycled, strRecycledDirectories;
268    int i = 0;
269
270    for (i = 0, iSize = saRecycled.GetSize(); i < iSize; i++) {
271        strRecycled += saRecycled[i] + "\r\n";
272    }
273
274    for (i = 0, iSize = saRecycledDirectories.GetSize(); i < iSize; i++) {
275        strRecycledDirectories += saRecycledDirectories[i] + "\r\n";
276    }
277
278    AfxMessageBox(strSID);
279    AfxMessageBox(strRecycled);
280    AfxMessageBox(strRecycledDirectories);
281#endif
282}
283
284
285/////////////////////////////////////////////////////////////////////////////
286// CLauncherApp initialization
287
288BOOL CLauncherApp::InitInstance()
289{
290    // Standard initialization
291    // If you are not using these features and wish to reduce the size
292    //  of your final executable, you should remove from the following
293    //  the specific initialization routines you do not need.
294    eraserInit();
295
296    CString strCmdLine(m_lpCmdLine);
297    CString strCurrentParameter;
298
299    BOOL    bIncorrectParameter = FALSE;
300    BOOL    bSilent             = FALSE;
301    BOOL    bResults            = FALSE;
302    BOOL    bResultsOnError     = FALSE;
303    BOOL    bOptions            = FALSE;
304    BOOL    bQueue              = FALSE;
305
306    CString strData;
307    CStringArray saFiles;
308    BOOL    bFiles              = FALSE;
309    BOOL    bFolders            = FALSE;
310    BOOL    bSubFolders         = FALSE;
311    BOOL    bKeepFolder         = FALSE;
312    BOOL    bDrive              = FALSE;
313    BOOL    bRecycled           = FALSE;
314    BOOL    bResolveLock        = FALSE;
315
316    ERASER_METHOD emMethod      = ERASER_METHOD_PSEUDORANDOM /*ERASER_METHOD_LIBRARY*/;
317    E_UINT16 uPasses            = 1;
318
319    if (!strCmdLine.IsEmpty())
320    {
321        while (GetNextParameter(strCmdLine, strCurrentParameter))
322        {
323            if (strCurrentParameter.CompareNoCase(szFile) == 0 &&
324                strData.IsEmpty())
325            {
326                // file
327
328                if (!GetNextParameter(strCmdLine, strCurrentParameter))
329                    bIncorrectParameter = TRUE;
330                else
331                {
332                    strData = strCurrentParameter;
333                    bFiles = TRUE;
334                }
335            }
336            else if (strCurrentParameter.CompareNoCase(szResolveLock) == 0 &&
337                strData.IsEmpty())
338            {
339                if (!GetNextParameter(strCmdLine, strCurrentParameter))
340                    bIncorrectParameter = TRUE;
341                else
342                {
343                    strData = strCurrentParameter;
344                    bResolveLock = TRUE;
345                }
346            }
347            else if (strCurrentParameter.CompareNoCase(szFolder) == 0 &&
348                     strData.IsEmpty())
349            {
350                // folder
351
352                if (!GetNextParameter(strCmdLine, strCurrentParameter))
353                    bIncorrectParameter = TRUE;
354                else
355                {
356                    strData = strCurrentParameter;
357                    bFiles = TRUE;
358                    bFolders = TRUE;
359
360                    if (strData[strData.GetLength() - 1] != '\\')
361                        strData += "\\";
362                }
363            }
364            else if (strCurrentParameter.CompareNoCase(szDisk) == 0 &&
365                     strData.IsEmpty())
366            {
367                // unused disk space
368
369                if (!GetNextParameter(strCmdLine, strCurrentParameter))
370                    bIncorrectParameter = TRUE;
371                else
372                {
373                    bDrive = TRUE;
374
375                    if (strCurrentParameter != szDiskAll)
376                        strData.Format("%c:\\", strCurrentParameter[0]);
377                    else
378                        strData = strCurrentParameter;
379                }
380            }
381            else if (strCurrentParameter.CompareNoCase(szRecycled) == 0)
382            {
383                bRecycled   = TRUE;
384                bFiles      = TRUE;
385                bFolders    = FALSE;
386            }
387            else if (strCurrentParameter.CompareNoCase(szMethod) == 0)
388            {
389                if (!GetNextParameter(strCmdLine, strCurrentParameter))
390                    bIncorrectParameter = TRUE;
391                else
392                {
393                    if (strCurrentParameter.CompareNoCase(szMethodLibrary) == 0)
394                        emMethod = ERASER_METHOD_LIBRARY;
395                    else if (strCurrentParameter.CompareNoCase(szMethodGutmann) == 0)
396                        emMethod = ERASER_METHOD_GUTMANN;
397                    else if (strCurrentParameter.CompareNoCase(szMethodDoD) == 0)
398                        emMethod = ERASER_METHOD_DOD;
399                    else if (strCurrentParameter.CompareNoCase(szMethodDoD_E) == 0)
400                        emMethod = ERASER_METHOD_DOD_E;
401                    else if (strCurrentParameter.CompareNoCase(szMethodFL2K) == 0)
402                        emMethod = ERASER_METHOD_FIRST_LAST_2KB;
403                    else if (strCurrentParameter.CompareNoCase(szSchneier) == 0)
404                        emMethod = ERASER_METHOD_SCHNEIER;
405                    else if (strCurrentParameter.CompareNoCase(szMethodRandom) == 0)
406                    {
407                        emMethod = ERASER_METHOD_PSEUDORANDOM;
408
409                        if (!GetNextParameter(strCmdLine, strCurrentParameter))
410                            bIncorrectParameter = TRUE;
411                        else
412                        {
413                            char *sztmp = 0;
414                            E_UINT32 uCurrentParameter = strtoul((LPCTSTR)strCurrentParameter, &sztmp, 10);
415
416                            if (*sztmp != '\0' || uCurrentParameter > (E_UINT16)-1) {
417                                bIncorrectParameter = TRUE;
418                            } else {
419                                uPasses = (E_UINT16)uCurrentParameter;
420                            }
421                        }
422                    }
423                    else
424                        bIncorrectParameter = TRUE;
425                }
426            }
427            else if (strCurrentParameter.CompareNoCase(szSubFolders) == 0)
428                bSubFolders = TRUE;
429            else if (strCurrentParameter.CompareNoCase(szKeepFolder) == 0)
430                bKeepFolder = TRUE;
431            else if (strCurrentParameter.CompareNoCase(szSilent) == 0)
432                bSilent = TRUE;
433            else if (strCurrentParameter.CompareNoCase(szResults) == 0)
434                bResults = TRUE;
435            else if (strCurrentParameter.CompareNoCase(szResultsOnError) == 0)
436            {
437                bResults = TRUE;
438                bResultsOnError = TRUE;
439            }
440            else if (strCurrentParameter.CompareNoCase(szOptions) == 0)
441                bOptions = TRUE;
442            else if (strCurrentParameter.CompareNoCase(szQueue) == 0)
443                bQueue = TRUE;
444            else
445                bIncorrectParameter = TRUE;
446        }
447    }
448    else
449    {
450        bIncorrectParameter = TRUE;
451    }
452
453    // conflicting command line parameters ?
454
455    if (((!bOptions && !bRecycled) && strData.IsEmpty()) || // no data!
456        (!bFolders && bKeepFolder) ||                       // data not a folder
457        (bSilent && bResults) ||                            // no windows
458        (bOptions && bQueue))                               // why queue the options?
459    {
460        bIncorrectParameter = TRUE;
461    }
462
463    if (bIncorrectParameter)
464    {
465        AfxMessageBox(IDS_CMDLINE_INCORRECT, MB_ICONERROR, 0);
466        return FALSE;
467    }
468
469    try
470    {
471        m_pdlgEraser    = new CLauncherDlg();
472        m_pMainWnd      = m_pdlgEraser;
473
474        if (!m_pdlgEraser->Create(IDD_LAUNCHER_DIALOG))
475        {
476            AfxMessageBox(IDS_ERROR_DIALOG, MB_ICONERROR, 0);
477            return FALSE;
478        }
479
480        if (bOptions)
481        {
482            m_pdlgEraser->Options();
483            return FALSE;
484        }
485        else
486        {
487            HandleQueue(bQueue);
488            if (bResolveLock)
489            {
490                try
491                {
492                    CFileLockResolver::Resolve(strData, saFiles);
493                }
494                catch (const std::exception& ee)
495                {
496                    ee.what();
497                }
498               
499            }
500           
501            if (bFiles && !bFolders)
502            {
503                if (!bRecycled)
504                    findMatchingFiles(strData, saFiles, bSubFolders);
505                else
506                {
507                    LocateRecycledItems(saFiles, m_pdlgEraser->m_saFolders);
508
509                    if (saFiles.GetSize() > 0 && !bSilent)
510                    {
511                        CConfirmDialog cd(m_pdlgEraser);
512
513                        if (cd.DoModal() != IDOK)
514                            return FALSE;
515                    }
516                }
517            }
518            else
519            {
520                if (bDrive || GetFileAttributes((LPCTSTR)strData) != (DWORD)-1)
521                    saFiles.Add(strData);
522            }
523
524            if (saFiles.GetSize() > 0 || m_pdlgEraser->m_saFolders.GetSize() > 0)
525            {
526                if (!bSilent)
527                    m_pdlgEraser->ShowWindow(SW_SHOW);
528                else
529                    m_pdlgEraser->GetDlgItem(IDCANCEL)->EnableWindow(FALSE);
530
531                m_pdlgEraser->m_saFiles.Copy(saFiles);
532                m_pdlgEraser->m_bResults        = bResults;
533                m_pdlgEraser->m_bResultsOnError = bResultsOnError;
534                m_pdlgEraser->m_bUseFiles       = bFiles || bResolveLock;
535                m_pdlgEraser->m_bUseEmptySpace  = bDrive;
536                m_pdlgEraser->m_bFolders        = bFolders;
537                m_pdlgEraser->m_bSubFolders     = bSubFolders;
538                m_pdlgEraser->m_bKeepFolder     = bKeepFolder;
539                m_pdlgEraser->m_bRecycled       = bRecycled;
540                m_pdlgEraser->m_emMethod        = emMethod;
541                m_pdlgEraser->m_uPasses         = uPasses;
542
543                return m_pdlgEraser->Erase();
544            }
545            else if (!bSilent)
546            {
547                if (bRecycled)
548                    AfxMessageBox("Recycle Bin is empty.", MB_ICONERROR);
549                else
550                    AfxMessageBox("File not found. Nothing to erase. (" + strData + ")", MB_ICONERROR);
551            }
552        }
553    }
554    catch (CException *e)
555    {
556        ASSERT(FALSE);
557        e->ReportError(MB_ICONERROR);
558        e->Delete();
559    }
560    catch (...)
561    {
562        ASSERT(FALSE);
563    }
564
565    return FALSE;
566}
567
568BOOL CLauncherApp::GetNextParameter(CString& strCmdLine, CString& strNextParameter) const
569{
570    strCmdLine.TrimRight();
571    strCmdLine.TrimLeft();
572
573    int iPos = strCmdLine.Find(' ');
574
575    if (iPos != -1)
576    {
577        strNextParameter = strCmdLine.Left(iPos);
578        strCmdLine = strCmdLine.Right(strCmdLine.GetLength() - iPos - 1);
579
580        if (!strNextParameter.IsEmpty() && strNextParameter[0] == '\"')
581        {
582            iPos = strCmdLine.Find('\"');
583
584            if (iPos != -1)
585            {
586                strNextParameter = strNextParameter.Right(strNextParameter.GetLength() - 1);
587                strNextParameter += " ";
588                strNextParameter += strCmdLine.Left(iPos);
589
590                strCmdLine = strCmdLine.Right(strCmdLine.GetLength() - iPos - 1);
591            }
592            else
593            {
594                strNextParameter = strNextParameter.Right(strNextParameter.GetLength() - 1);
595
596                iPos = strNextParameter.Find('\"');
597
598                if (iPos != -1)
599                    strNextParameter = strNextParameter.Left(iPos);
600            }
601        }
602
603        return (!strNextParameter.IsEmpty());
604    }
605    else if (!strCmdLine.IsEmpty())
606    {
607        strNextParameter = strCmdLine;
608        strCmdLine.Empty();
609
610        if (strNextParameter[0] == '\"')
611            strNextParameter = strNextParameter.Right(strNextParameter.GetLength() - 1);
612
613        if (strNextParameter[strNextParameter.GetLength() - 1] == '\"')
614            strNextParameter = strNextParameter.Left(strNextParameter.GetLength() - 1);
615
616        return TRUE;
617    }
618
619    return FALSE;
620}
621
622int CLauncherApp::ExitInstance()
623{
624    if (m_pdlgEraser)
625    {
626        m_pdlgEraser->DestroyWindow();
627
628        delete m_pdlgEraser;
629        m_pdlgEraser = 0;
630    }
631
632    if (m_hQueue != NULL)
633    {
634        ReleaseMutex(m_hQueue);
635        CloseHandle(m_hQueue);
636        m_hQueue = NULL;
637    }
638
639    // clean up the library
640    eraserEnd();
641
642    return CWinApp::ExitInstance();
643}
644
645void CLauncherApp::HandleQueue(BOOL bQueue)
646{
647    ASSERT(m_hQueue == NULL);
648
649    DWORD dwQueue = 0;
650    CString strName;
651
652    // find our position in the queue
653    for (DWORD dwNumber = 0; dwNumber < ERASERL_MAX_QUEUE; dwNumber++)
654    {
655        strName.Format(szQueueGUID, dwNumber);
656        m_hQueue = CreateMutex(NULL, TRUE, (LPCTSTR)strName);
657
658        if (m_hQueue == NULL)
659        {
660            // mutex creation failed!
661            return;
662        }
663        else if (GetLastError() == ERROR_ALREADY_EXISTS)
664        {
665            CloseHandle(m_hQueue);
666            m_hQueue = NULL;
667        }
668        else
669        {
670            // found our position in the queue!
671            dwQueue = dwNumber;
672            break;
673        }
674
675        if (dwNumber == ERASERL_MAX_QUEUE - 1)
676            AfxMessageBox(IDS_ERROR_MAX_INSTANCE, MB_ICONWARNING, 0);
677    }
678
679    // if we were ordered to wait until other instances have finished,
680    // why don't we then
681    if (m_hQueue != NULL && bQueue)
682    {
683        HANDLE m_hPrevInstance = NULL;
684        HANDLE m_hTemp = NULL;
685
686        while (dwQueue > 0)
687        {
688            strName.Format(szQueueGUID, --dwQueue);
689
690            m_hPrevInstance = OpenMutex(MUTEX_ALL_ACCESS, FALSE, (LPCTSTR)strName);
691
692            if (m_hPrevInstance != NULL)
693            {
694                WaitForSingleObject(m_hPrevInstance, INFINITE);
695
696                CloseHandle(m_hPrevInstance);
697                m_hPrevInstance = NULL;
698
699                m_hTemp = CreateMutex(NULL, TRUE, (LPCTSTR)strName);
700
701                if (m_hTemp == NULL)
702                    return;
703
704                ReleaseMutex(m_hQueue);
705                CloseHandle(m_hQueue);
706
707                m_hQueue = m_hTemp;
708                m_hTemp = NULL;
709            }
710        }
711    }
712}
Note: See TracBrowser for help on using the repository browser.