source: trunk/EraserDoc.cpp @ 20

Revision 20, 37.5 KB checked in by lowjoel, 7 years ago (diff)

Garrett's updated code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1// EraserDoc.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 "Eraser.h"
24#include "Item.h"
25#include "EraserDll\EraserDll.h"
26#include "shared\key.h"
27#include "shared\utils.h"
28#include "shared\FileDialogEx.h"
29#include "PreferencesSheet.h"
30#include "TimeOutMessageBox.h"
31#include "EraserDoc.h"
32#include "MainFrm.h"
33#include "version.h"
34//#include <afxpriv.h>
35
36#include <direct.h>
37
38#ifdef _DEBUG
39#define new DEBUG_NEW
40#undef THIS_FILE
41static char THIS_FILE[] = __FILE__;
42#endif
43
44/////////////////////////////////////////////////////////////////////////////
45// CEraserDoc
46
47
48
49CString findRecycledBinGUID()
50{
51    const LPCTSTR RBIN_NSPACE = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace";
52    CKey kReg;
53    BOOL bRes;
54    HKEY hReg;
55    TCHAR szSubKey[MAX_KEY_LENGTH];
56    DWORD dwSubKeyLen = MAX_KEY_LENGTH;
57    DWORD dwIndex=0;
58    CString strValue=_T(""),strDef=_T(""),strFind=_T("");
59   
60    bRes = kReg.Open(HKEY_LOCAL_MACHINE,RBIN_NSPACE,FALSE);
61    hReg = kReg.GetHandle();
62    while (ERROR_SUCCESS == RegEnumKeyEx(hReg,dwIndex,szSubKey,&dwSubKeyLen,NULL,NULL,NULL,NULL))
63    {       
64        CKey kTmpReg;
65        CString strTmp=_T("");
66        strTmp.Format("%s\\%s", RBIN_NSPACE, szSubKey);
67        if (kTmpReg.Open(HKEY_LOCAL_MACHINE,strTmp,FALSE)) {
68            kTmpReg.GetValue(strValue,strDef,"");
69            if (strValue == "Recycle Bin") {
70                strFind = szSubKey; 
71            }
72            dwIndex++;
73            dwSubKeyLen = MAX_KEY_LENGTH;           
74        }
75        kTmpReg.Close();
76    }
77    kReg.Close();
78    return strFind;
79}
80
81
82IMPLEMENT_DYNCREATE(CEraserDoc, CDocument)
83
84BEGIN_MESSAGE_MAP(CEraserDoc, CDocument)
85    //{{AFX_MSG_MAP(CEraserDoc)
86    ON_UPDATE_COMMAND_UI(ID_FILE_EXPORT, OnUpdateFileExport)
87    ON_COMMAND(ID_FILE_EXPORT, OnFileExport)
88    ON_COMMAND(ID_FILE_IMPORT, OnFileImport)
89    ON_COMMAND(ID_TRAY_ENABLE, OnTrayEnable)
90    ON_UPDATE_COMMAND_UI(ID_TRAY_SHOW_WINDOW, OnUpdateTrayShowWindow)
91    ON_UPDATE_COMMAND_UI(ID_TRAY_ENABLE, OnUpdateTrayEnable)
92    ON_COMMAND(ID_TRAY_SHOW_WINDOW, OnTrayShowWindow)
93    ON_COMMAND(ID_EDIT_PREFERENCES_GENERAL, OnEditPreferencesGeneral)
94    ON_COMMAND(ID_EDIT_PREFERENCES_ERASER, OnEditPreferencesEraser)
95    ON_COMMAND(ID_FILE_VIEW_LOG, OnFileViewLog)
96    //}}AFX_MSG_MAP
97END_MESSAGE_MAP()
98
99/////////////////////////////////////////////////////////////////////////////
100// CEraserDoc construction/destruction
101
102CEraserDoc::CEraserDoc() :
103m_bResolveLock(TRUE),
104m_bResolveAskUser(TRUE),
105m_bSchedulerEnabled(TRUE),
106m_wProcessCount(0),
107m_bResultsForFiles(TRUE),
108m_bResultsForUnusedSpace(TRUE),
109m_bResultsOnlyWhenFailed(FALSE),
110m_bLog(TRUE),
111m_bLogOnlyErrors(FALSE),
112m_bStartup(TRUE),
113m_bQueueTasks(TRUE),
114m_bNoVisualErrors(FALSE),
115m_dwMaxLogSize(10),
116m_bClearSwap(FALSE),
117m_bShellextResults(FALSE),
118m_bErasextEnabled(TRUE),
119m_bEnableSlowPoll(FALSE),
120m_dwStartView((DWORD)-1),
121m_bIconAnimation(FALSE),
122m_bSmallIconView(FALSE),
123m_dwOutbarWidth(0),
124m_bNoTrayIcon(FALSE),
125m_bHideOnMinimize(FALSE),
126m_bViewInfoBar(FALSE),
127m_smallImageList (NULL)
128{
129    TRACE("CEraserDoc::CEraserDoc\n");
130
131    m_bAutoDelete = FALSE;
132    ZeroMemory(&m_rWindowRect, sizeof(RECT));
133
134    // find executable location for logging
135    try
136    {
137
138       /* Removed GT 28/07/2007 for Vista
139        GetModuleFileName(AfxGetInstanceHandle(),
140                          m_strExePath.GetBuffer(MAX_PATH), MAX_PATH);
141        m_strExePath.ReleaseBuffer();
142        m_strExePath = m_strExePath.Left(m_strExePath.ReverseFind('\\') + 1);
143
144       */   
145       
146        LPTSTR p = m_strExePath.GetBuffer(MAX_PATH);
147        HRESULT hr = ::SHGetFolderPath(NULL,CSIDL_COMMON_DOCUMENTS | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, p);
148        m_strExePath.ReleaseBuffer();
149        m_strExePath = m_strExePath.Left(m_strExePath.ReverseFind('\\') + 1);
150
151        // read preferences
152        if (!ReadPreferences())
153        {
154            AfxTimeOutMessageBox(IDS_ERROR_PREFERENCES_READ, MB_ICONERROR);
155
156            if (m_bLog)
157                LogAction(IDS_ERROR_PREFERENCES_READ);
158        }
159
160        // create task bar tray icon
161        m_stIcon.Create(NULL, WM_TRAY_NOTIFY, "Starting...",
162                        AfxGetApp()->LoadIcon(IDI_ICON_TRAY),
163                        IDR_MENU_TRAY, !m_bNoTrayIcon);
164        /*
165        m_stIcon.Create(NULL,                            // Let icon deal with its own messages
166                        WM_ICON_NOTIFY,                  // Icon notify message to use
167                        _T("Starting..."),  // tooltip
168                        AfxGetApp()->LoadIcon(IDI_ICON_TRAY),
169                        IDR_MENU_TRAY,                  // ID of tray icon
170                        FALSE,
171                        _T("Eraser Starting!"), // balloon tip
172                        _T("Eraser"),               // balloon title
173                        NIIF_WARNING,                    // balloon icon
174                        20 );                            // balloon timeout
175        */
176        // create timers
177        CalcNextAssignment();
178        UpdateToolTip();
179
180        if (m_bLog && !m_bLogOnlyErrors)
181        {
182            CString strStart;
183            AfxFormatString1(strStart, IDS_ACTION_START, VERSION_NUMBER_STRING);
184            LogAction(strStart);
185        }
186
187        VERIFY(m_ilHeader.Create(IDB_HEADER, 10, 1, RGB(255, 255, 255)));
188
189        //image list setup
190        HIMAGELIST hSystemSmallImageList;
191        SHFILEINFO ssfi;
192
193        //get a handle to the system small icon list
194        hSystemSmallImageList =
195            reinterpret_cast<HIMAGELIST>(SHGetFileInfo((LPCTSTR)_T("C:\\"),
196                                      0, &ssfi, sizeof(SHFILEINFO),
197                                      SHGFI_SYSICONINDEX | SHGFI_SMALLICON));
198
199   
200        //m_smallImageList.Attach(hSystemSmallImageList);
201        m_smallImageList = CImageList::FromHandle(hSystemSmallImageList);
202    }
203    catch (CException *e)
204    {
205        ASSERT(FALSE);
206        REPORT_ERROR(e);
207        e->Delete();
208    }
209}
210
211CEraserDoc::~CEraserDoc()
212{
213    TRACE("CEraserDoc::~CEraserDoc\n");
214
215    try
216    {
217        m_smallImageList->Detach();
218        m_stIcon.RemoveIcon();
219
220        if (!SavePreferences() && m_bLog)
221            LogAction(IDS_ERROR_PREFERENCES_SAVE);
222
223        if (m_bLog && !m_bLogOnlyErrors)
224            LogAction(IDS_ACTION_QUIT);
225
226    //  delete m_smallImageList;
227    }
228    catch (...)
229    {
230        ASSERT(FALSE);
231    }
232}
233
234BOOL CEraserDoc::OnNewDocument()
235{
236    TRACE("CEraserDoc::OnNewDocument\n");
237
238    try
239    {
240        if (!CDocument::OnNewDocument())
241            return FALSE;
242
243        CString strDefault = m_strExePath + szDefaultFile;
244        Import((LPCTSTR)strDefault, FALSE);
245
246        return TRUE;
247    }
248    catch (CException *e)
249    {
250        ASSERT(FALSE);
251        REPORT_ERROR(e);
252        e->Delete();
253    }
254
255    return FALSE;
256}
257
258
259
260/////////////////////////////////////////////////////////////////////////////
261// CEraserDoc serialization
262
263void CEraserDoc::Serialize(CArchive& ar)
264{
265    TRACE("CEraserDoc::Serialize\n");
266
267    CItem           *piItem     = 0;
268    CScheduleItem   *psiItem    = 0;
269
270    if (ar.IsStoring())
271    {
272        int iSize;
273        WORD wID = 0;
274
275        // remove invalid items
276        CleanList(m_paTasks, sizeof(CItem));
277        CleanList(m_paScheduledTasks, sizeof(CScheduleItem));
278
279        ar << static_cast<DWORD>(m_paTasks.GetSize() + m_paScheduledTasks.GetSize());
280
281        iSize = m_paTasks.GetSize();
282
283        while (iSize--)
284        {
285            piItem = static_cast<CItem*>(m_paTasks[iSize]);
286
287            ar << static_cast<WORD>(ITEMVERSION);
288            ar << static_cast<WORD>(ITEM_ID);
289            piItem->Serialize(ar);
290        }
291
292        iSize = m_paScheduledTasks.GetSize();
293
294        while (iSize--)
295        {
296            psiItem = static_cast<CScheduleItem*>(m_paScheduledTasks[iSize]);
297
298            ar << static_cast<WORD>(ITEMVERSION);
299            ar << static_cast<WORD>(SCHEDULE_ID);
300            psiItem->Serialize(ar);
301        }
302    }
303    else
304    {
305        DWORD dwCount = 0;
306        WORD  wID     = 0;
307        WORD  wItemID = 0;
308
309        ar >> dwCount;
310
311        for (DWORD dwItem = 0; dwItem < dwCount; dwItem++)
312        {
313            ar >> wID;
314
315            piItem = 0;
316            psiItem = 0;
317
318            if (wID >= ITEMVERSION_30 && wID <= ITEMVERSION)
319            {
320                ar >> wItemID;
321
322                try
323                {
324                    if (wItemID == ITEM_ID)
325                    {
326                        piItem = new CItem();
327
328                        switch (wID)
329                        {
330                        case ITEMVERSION:
331                            piItem->Serialize(ar);
332                            break;
333                        case ITEMVERSION_41:
334                            psiItem->Serialize(ar);
335                            break;
336#ifdef SCHEDULER_IMPORT_COMPATIBLE
337                        case ITEMVERSION_40:
338                            piItem->Serialize40(ar);
339                            break;
340                        case ITEMVERSION_30:
341                            piItem->Serialize30(ar);
342                            break;
343#endif
344                        default:
345                            AfxThrowArchiveException(CArchiveException::badIndex);
346                        }
347
348                        AddTask(piItem);
349                    }
350                    else if (wItemID == SCHEDULE_ID)
351                    {
352                        psiItem = new CScheduleItem();
353
354                        switch (wID)
355                        {
356                        case ITEMVERSION:
357                            psiItem->Serialize(ar);
358                            break;
359                        case ITEMVERSION_41:
360                            psiItem->Serialize41(ar);
361                            break;
362#ifdef SCHEDULER_IMPORT_COMPATIBLE
363                        case ITEMVERSION_40:
364                            psiItem->Serialize40(ar);
365                            break;
366                        case ITEMVERSION_30:
367                            psiItem->Serialize30(ar);
368                            break;
369#endif
370                        default:
371                            AfxThrowArchiveException(CArchiveException::badIndex);
372                        }
373
374                        AddScheduledTask(psiItem);
375                    }
376                }
377                catch (...)
378                {
379                    if (piItem)
380                    {
381                        delete piItem;
382                        piItem = 0;
383                    }
384
385                    if (psiItem)
386                    {
387                        delete psiItem;
388                        psiItem = 0;
389                    }
390
391                    ASSERT(FALSE);
392                    throw;
393                }
394            }
395#ifdef SCHEDULER_IMPORT_COMPATIBLE
396            else if (wID == ITEMVERSION_21)
397            {
398                psiItem = new CScheduleItem();
399
400                try
401                {
402                    psiItem->Serialize21(ar);
403                    AddScheduledTask(psiItem);
404                }
405                catch (...)
406                {
407                    delete psiItem;
408                    psiItem = 0;
409
410                    ASSERT(FALSE);
411                    throw;
412                }
413            }
414#endif
415            else
416            {
417                // unsupported format
418                AfxThrowArchiveException(CArchiveException::badIndex);
419            }
420        }
421    }
422}
423
424/////////////////////////////////////////////////////////////////////////////
425// CEraserDoc diagnostics
426
427#ifdef _DEBUG
428void CEraserDoc::AssertValid() const
429{
430    CDocument::AssertValid();
431}
432
433void CEraserDoc::Dump(CDumpContext& dc) const
434{
435    CDocument::Dump(dc);
436}
437#endif //_DEBUG
438
439/////////////////////////////////////////////////////////////////////////////
440// CEraserDoc commands
441
442BOOL CEraserDoc::OnOpenDocument(LPCTSTR lpszPathName)
443{
444    TRACE("CEraserDoc::OnOpenDocument\n");
445
446    try
447    {
448        if (!CDocument::OnNewDocument())
449            return FALSE;
450
451        Import(lpszPathName);
452
453        return TRUE;
454    }
455    catch (CException *e)
456    {
457        ASSERT(FALSE);
458        REPORT_ERROR(e);
459        e->Delete();
460    }
461
462    return FALSE;
463}
464
465void CEraserDoc::DeleteContents()
466{
467    TRACE("CEraserDoc::DeleteContents\n");
468
469    FreeTasks();
470    CDocument::DeleteContents();
471}
472
473void CEraserDoc::FreeTasks()
474{
475    TRACE("CEraserDoc::FreeTasks\n");
476
477    try
478    {
479        CItem         *piItem  = 0;
480        CScheduleItem *psiItem = 0;
481        int           iSize    = 0;
482
483        // tasks of type CItem
484        iSize = m_paTasks.GetSize();
485
486        while (iSize--)
487        {
488            piItem = static_cast<CItem*>(m_paTasks[iSize]);
489            if (AfxIsValidAddress(piItem, sizeof(CItem)))
490                delete piItem;
491
492            piItem = 0;
493        }
494
495        m_paTasks.RemoveAll();
496
497        // scheduled tasks of type CScheduleItem
498        iSize = m_paScheduledTasks.GetSize();
499
500        while (iSize--)
501        {
502            psiItem = static_cast<CScheduleItem*>(m_paScheduledTasks[iSize]);
503
504            if (AfxIsValidAddress(psiItem, sizeof(CScheduleItem)))
505                delete psiItem;
506
507            psiItem = 0;
508        }
509
510        m_paScheduledTasks.RemoveAll();
511    }
512    catch (CException *e)
513    {
514        ASSERT(FALSE);
515        REPORT_ERROR(e);
516        e->Delete();
517    }
518}
519
520BOOL CEraserDoc::AddTask(CItem *piItem)
521{
522    TRACE("CEraserDoc::AddTask\n");
523
524    if (AfxIsValidAddress(piItem, sizeof(CItem)))
525    {
526        try
527        {
528            CString strNew;
529            piItem->GetData(strNew);
530
531            CItem   *piCurrent  = 0;
532            int     iSize       = m_paTasks.GetSize();
533
534            // duplicates are not accepted for on-demand eraser
535
536            while (iSize--)
537            {
538                piCurrent = static_cast<CItem*>(m_paTasks[iSize]);
539                if (AfxIsValidAddress(piCurrent, sizeof(CItem)))
540                {
541                    if (!strNew.CompareNoCase((LPCTSTR)(piCurrent->GetData())))
542                        return FALSE;
543                }
544            }
545
546            m_paTasks.Add(static_cast<void*>(piItem));
547            return TRUE;
548        }
549        catch (CException *e)
550        {
551            ASSERT(FALSE);
552            REPORT_ERROR(e);
553            e->Delete();
554        }
555    }
556
557    return FALSE;
558}
559
560BOOL CEraserDoc::AddScheduledTask(CScheduleItem *psiItem)
561{
562    TRACE("CEraserDoc::AddScheduledTask\n");
563
564    if (AfxIsValidAddress(psiItem, sizeof(CScheduleItem)))
565    {
566        try
567        {
568            m_paScheduledTasks.Add(static_cast<void*>(psiItem));
569            return TRUE;
570        }
571        catch (CException *e)
572        {
573            ASSERT(FALSE);
574            REPORT_ERROR(e);
575            e->Delete();
576        }
577    }
578
579    return FALSE;
580}
581
582
583void CEraserDoc::OnUpdateFileExport(CCmdUI* pCmdUI)
584{
585    pCmdUI->Enable(m_paTasks.GetSize() > 0 || m_paScheduledTasks.GetSize() > 0);
586}
587
588void CEraserDoc::OnFileExport()
589{
590    TRACE("CEraserDoc::OnFileExport\n");
591    CFileDialogEx fd(FALSE,
592                     szFileExtension,
593                     szFileWCard,
594                     OFN_EXPLORER | OFN_PATHMUSTEXIST |
595                     OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
596                     szFileFilter,
597                     AfxGetMainWnd());
598
599    fd.m_ofn.lpstrTitle = szExportTitle;
600
601    if (fd.DoModal() == IDOK)
602    {
603        CString strFile = fd.GetPathName();
604        Export((LPCTSTR)strFile);
605    }
606}
607
608void CEraserDoc::OnFileImport()
609{
610    TRACE("CEraserDoc::OnFileImport\n");
611// Was CfileDialogEx now with MFC7 we can change back to MFC Class
612    CFileDialog fd(TRUE,
613                     szFileExtension,
614                     szFileWCard,
615                     OFN_EXPLORER | OFN_PATHMUSTEXIST |
616                     OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
617                     szFileFilter,
618                     AfxGetMainWnd());
619
620    fd.m_ofn.lpstrTitle = szImportTitle;
621
622    if (fd.DoModal() == IDOK)
623    {
624        CString strFile = fd.GetPathName();
625        Import((LPCTSTR)strFile);
626
627        UpdateAllViews(NULL, SCHEDULER_SET_TIMERS);
628    }
629}
630
631void CEraserDoc::OnUpdateTrayEnable(CCmdUI* pCmdUI)
632{
633    pCmdUI->SetCheck(m_bSchedulerEnabled);
634}
635
636void CEraserDoc::OnTrayEnable()
637{
638    TRACE("CEraserDoc::OnTrayEnable\n");
639
640    m_bSchedulerEnabled = !m_bSchedulerEnabled;
641
642    if (m_bLog && !m_bLogOnlyErrors)
643    {
644        if (m_bSchedulerEnabled)
645            LogAction(IDS_ACTION_ENABLED);
646        else
647            LogAction(IDS_ACTION_DISABLED);
648    }
649
650    UpdateToolTip();
651}
652
653void CEraserDoc::OnUpdateTrayShowWindow(CCmdUI* pCmdUI)
654{
655    try
656    {
657        CFrameWnd *pwndMain = static_cast<CFrameWnd*>(AfxGetMainWnd());
658        pCmdUI->Enable(!pwndMain->IsWindowVisible());
659    }
660    catch (...)
661    {
662        ASSERT(FALSE);
663        pCmdUI->Enable(FALSE);
664    }
665}
666
667void CEraserDoc::OnTrayShowWindow()
668{
669    TRACE("CEraserDoc::OnTrayShowWindow\n");
670
671    try
672    {
673        CMainFrame *pwndMain = static_cast<CMainFrame*>(AfxGetMainWnd());
674
675        if (!pwndMain->IsWindowVisible())
676        {
677            pwndMain->ShowWindow(SW_SHOW);
678
679            if (pwndMain->m_pwndChild->m_iActiveViewID == VIEW_SCHEDULER)
680            {
681                // if there are processes running, update the window
682                if (m_wProcessCount > 0)
683                    pwndMain->m_pwndChild->m_pSchedulerView->EraserWipeBegin();
684            }
685        }
686    }
687    catch (...)
688    {
689        ASSERT(FALSE);
690    }
691}
692
693BOOL CEraserDoc::LogAction(CString str)
694{
695    TRACE("CEraserDoc::LogAction(CString)\n");
696
697    BOOL bResult = FALSE;
698    CString strDate, strPath;
699
700    CStdioFile sf;
701
702    strPath = m_strExePath + szLogFile;
703
704    if (sf.Open(strPath, CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::typeText))
705    {
706        strDate = GetTimeTimeZoneBased().Format();
707        str = strDate + ": " + str + "\n";
708
709
710        try
711        {
712            DWORD dwMax = m_dwMaxLogSize * 1024;
713            ULONGLONG dwCurrent = sf.GetLength() + str.GetLength();
714
715            if (m_dwMaxLogSize > 0 && dwMax < dwCurrent)
716            {
717                // must remove lines in order to keep the log
718                // file under the maximum size
719
720                CString strTmp;
721                LONGLONG dwLen = dwMax - str.GetLength();
722
723                sf.Seek(-1*dwLen, CFile::end);
724                sf.ReadString(strTmp);
725
726                LPTSTR lpszTmp = strTmp.GetBufferSetLength(dwLen);
727                ZeroMemory(lpszTmp, dwLen);
728
729                sf.Read((LPVOID)lpszTmp, dwLen);
730
731                strTmp.ReleaseBuffer();
732                strTmp += str;
733
734                sf.SetLength(0);
735                sf.SeekToBegin();
736                sf.Write(strTmp, strTmp.GetLength());
737            }
738            else
739            {
740                // write to the end of the file
741                sf.SeekToEnd();
742                sf.WriteString(str);
743            }
744
745            bResult = TRUE;
746        }
747        catch (CException* e)
748        {
749            e->ReportError();           
750        }
751        catch (...)
752        {
753            ASSERT(FALSE);
754        }
755
756        sf.Close();
757    }
758
759    return bResult;
760}
761
762BOOL CEraserDoc::LogException(CException *e)
763{
764    TRACE("CEraserDoc::LogException\n");
765
766    try
767    {
768        TCHAR szCause[255];
769        e->GetErrorMessage(szCause, 255);
770
771        return LogAction(szCause);
772    }
773    catch (...)
774    {
775        ASSERT(FALSE);
776    }
777
778    return FALSE;
779}
780
781BOOL CEraserDoc::LogAction(UINT nResourceID)
782{
783    TRACE("CEraserDoc::LogAction(UINT)\n");
784
785    CString str;
786    BOOL bResult = FALSE;
787
788    try
789    {
790        if (str.LoadString(nResourceID))
791            bResult = LogAction(str);
792    }
793    catch (CException *e)
794    {
795        ASSERT(FALSE);
796
797        if (m_bLog)
798            LogException(e);
799
800        e->Delete();
801    }
802    catch (...)
803    {
804        ASSERT(FALSE);
805    }
806
807    return bResult;
808}
809
810void CEraserDoc::CalcNextAssignment()
811{
812    TRACE("CEraserDoc::CalcNextAssignment\n");
813
814    try
815    {
816        int iSize = m_paScheduledTasks.GetSize();
817
818        if (iSize > 0)
819        {
820            iSize--;
821
822            CScheduleItem   *psiItem    = static_cast<CScheduleItem*>(m_paScheduledTasks[iSize]);
823            COleDateTime    odtEarliest = psiItem->GetNextTime();
824
825            while (iSize--)
826            {
827                psiItem = static_cast<CScheduleItem*>(m_paScheduledTasks[iSize]);
828                if (AfxIsValidAddress(psiItem, sizeof(CScheduleItem)))
829                {
830                    if (psiItem->GetNextTime() < odtEarliest)
831                        odtEarliest = psiItem->GetNextTime();
832                }
833            }
834
835            m_strNextAssignment = odtEarliest.Format();
836        }
837        else
838            m_strNextAssignment.Empty();
839    }
840    catch (CException *e)
841    {
842        ASSERT(FALSE);
843
844        if (m_bLog)
845            LogException(e);
846
847        e->Delete();
848    }
849}
850
851void CEraserDoc::UpdateToolTip()
852{
853    TRACE("CEraserDoc::UpdateToolTip\n");
854
855    CString     strFormat;
856    CString     str;
857
858    try
859    {
860        if (m_wProcessCount == 0)
861        {
862            if (m_bSchedulerEnabled)
863            {
864                if (m_strNextAssignment.IsEmpty())
865                {
866                    strFormat.LoadString(IDS_TOOLTIP_WAITING);
867                    m_stIcon.SetTooltipText(strFormat);
868                }
869                else
870                {
871                    str.LoadString(IDS_TOOLTIP_NEXT);
872                    str += m_strNextAssignment;
873
874                    m_stIcon.SetTooltipText(str);
875                }
876
877                m_stIcon.SetIcon(IDI_ICON_TRAY);
878            }
879            else
880            {
881                strFormat.LoadString(IDS_TOOLTIP_DISABLED);
882                m_stIcon.SetTooltipText(strFormat);
883
884                m_stIcon.SetIcon(IDI_ICON_TRAY_DISABLED);
885            }
886        }
887        else
888        {
889            m_stIcon.SetIcon(IDI_ICON_TRAY_RUNNING);
890
891            strFormat.LoadString(IDS_TOOLTIP_PROCESSING);
892            str.Format(strFormat, m_wProcessCount);
893
894            if (str.CompareNoCase(m_stIcon.GetTooltipText()) != 0)
895                m_stIcon.SetTooltipText((LPCTSTR)str);
896        }
897    }
898    catch (CException *e)
899    {
900        ASSERT(FALSE);
901
902        if (m_bLog)
903            LogException(e);
904
905        e->Delete();
906    }
907}
908
909#define RESULT(result, statement) \
910    ((result) = ((statement) ? (result) : FALSE))
911
912__declspec(dllimport) bool no_registry;
913
914BOOL CEraserDoc::SavePreferences()
915{
916    TRACE("CEraserDoc::SavePreferences\n");
917
918    BOOL            bResult     = TRUE;
919    CKey            kReg_reg;
920    CIniKey         kReg_ini;
921    CKey           &kReg = no_registry ? kReg_ini : kReg_reg;
922    CString         strPath;
923    OSVERSIONINFO   ov;
924
925    strPath.Format("%s\\%s", ERASER_REGISTRY_BASE, szSettingsKey);
926
927    ZeroMemory(&ov, sizeof(OSVERSIONINFO));
928    ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
929
930    GetVersionEx(&ov);
931
932    // Scheduler Preferences
933    if (kReg.Open(HKEY_CURRENT_USER, strPath))
934    {
935        RESULT(bResult, kReg.SetValue(m_bSchedulerEnabled, szSchedulerEnabled));
936        RESULT(bResult, kReg.SetValue(m_bLog, szLog));
937        RESULT(bResult, kReg.SetValue(m_bLogOnlyErrors, szLogOnlyErrors));
938        RESULT(bResult, kReg.SetValue(m_bStartup, szStartup));
939        RESULT(bResult, kReg.SetValue(m_bQueueTasks, szQueueTasks));
940        RESULT(bResult, kReg.SetValue(m_bNoVisualErrors, szNoVisualErrors));
941        RESULT(bResult, kReg.SetValue(m_dwMaxLogSize, szMaxLogSize));
942
943        kReg.Close();
944    }
945    else
946        bResult = FALSE;
947
948    // Scheduler Startup
949    if (!no_registry) {
950        if (m_bStartup)
951        {
952            if (kReg.Open(HKEY_CURRENT_USER, szStartupPath))
953            {
954                TCHAR szApplicationFileName[MAX_PATH + 1];
955
956                if (GetModuleFileName(AfxGetInstanceHandle(), szApplicationFileName, MAX_PATH))
957                {
958                    CString strStartupCmdLine(szApplicationFileName);
959                    strStartupCmdLine += " ";
960                    strStartupCmdLine += NOWINDOW_PARAMETER;
961
962                    RESULT(bResult, kReg.SetValue((LPCTSTR)strStartupCmdLine, szRunOnStartup));
963                }
964                else
965                    bResult = FALSE;
966
967                kReg.Close();
968            }
969            else
970                bResult = FALSE;
971        }
972        else if (kReg.Open(HKEY_CURRENT_USER, szStartupPath, FALSE))
973        {
974            kReg.DeleteValue(szRunOnStartup);
975            kReg.Close();
976        }
977    }
978
979    // General Preferences
980
981    //cancel report on recycle bin clearance if m_bShellextResults is unchecked
982    const LPCTSTR REC_BIN_PKEY = "CLSID\\";
983    const LPCTSTR REC_BIN_SKEY = "Shell\\Eraserxt\\command";
984    const CString strWthReport = "\\Eraserl.exe -recycled -results ";
985    const CString strWoReport =  "\\Eraserl.exe -recycled ";
986
987    CString strDef = _T(""), strCmd, strOld = _T("");
988    CString strRecBinGUID = REC_BIN_PKEY + findRecycledBinGUID();
989    strRecBinGUID = strRecBinGUID + "\\" + REC_BIN_SKEY;
990   
991    if (!no_registry && kReg.Open(HKEY_CLASSES_ROOT,strRecBinGUID,FALSE))
992    {
993        char buf[_MAX_PATH];
994        _getcwd(buf,_MAX_PATH); //working directory
995        strCmd = buf;
996        if (m_bShellextResults == TRUE) strCmd = strCmd + strWthReport;
997        else strCmd = strCmd + strWoReport;
998        kReg.GetValue(strOld,strDef,"");
999        if (strOld != strCmd ) kReg.SetValue(strCmd,strDef);
1000        kReg.Close();
1001    }
1002   
1003   
1004    if (kReg.Open(HKEY_CURRENT_USER, ERASER_REGISTRY_BASE))
1005    {
1006        if (m_dwStartView != (DWORD) -1)
1007            RESULT(bResult, kReg.SetValue(m_dwStartView, szStartView));
1008
1009        RESULT(bResult, kReg.SetValue((LPVOID)&m_rWindowRect, szWindowRect, sizeof(RECT)));
1010        RESULT(bResult, kReg.SetValue(m_bResultsForFiles, ERASER_REGISTRY_RESULTS_FILES));
1011        RESULT(bResult, kReg.SetValue(m_bResultsForUnusedSpace, ERASER_REGISTRY_RESULTS_UNUSEDSPACE));
1012        RESULT(bResult, kReg.SetValue(m_bResultsOnlyWhenFailed, ERASER_REGISTRY_RESULTS_WHENFAILED));
1013        RESULT(bResult, kReg.SetValue(m_bShellextResults, ERASEXT_REGISTRY_RESULTS));
1014        RESULT(bResult, kReg.SetValue(m_bErasextEnabled, ERASEXT_REGISTRY_ENABLED));
1015        RESULT(bResult, kReg.SetValue(m_bEnableSlowPoll, ERASER_RANDOM_SLOW_POLL));
1016        RESULT(bResult, kReg.SetValue(m_bIconAnimation, szIconAnimation));
1017        RESULT(bResult, kReg.SetValue(m_bSmallIconView, szSmallIconView));
1018        RESULT(bResult, kReg.SetValue(m_dwOutbarWidth, szOutBarWidth));
1019        RESULT(bResult, kReg.SetValue(m_bNoTrayIcon, szNoTrayIcon));
1020        RESULT(bResult, kReg.SetValue(m_bHideOnMinimize, szHideOnMinimize));
1021        RESULT(bResult, kReg.SetValue(m_bViewInfoBar, szViewInfoBar));
1022        RESULT(bResult, kReg.SetValue(m_bResolveLock, szResolveLock));
1023        RESULT(bResult, kReg.SetValue(m_bResolveAskUser, szResolveAskUser));
1024       
1025        kReg.Close();
1026
1027    }
1028    else
1029        bResult = FALSE;
1030
1031    // Page File Clearing only on NT (works only if Admin so no errors here)
1032    if (ov.dwPlatformId == VER_PLATFORM_WIN32_NT)
1033    {
1034        if (kReg_reg.Open(HKEY_LOCAL_MACHINE, szClearSwapPath))
1035        {
1036            // need to set the registry key even if m_bClearSwap == false,
1037            // otherwise Windows 2000 overrides the setting when applying
1038            // local security policy
1039
1040            kReg_reg.SetValue(m_bClearSwap, szClearSwapValue);
1041            kReg_reg.Close();
1042        }
1043    }
1044
1045    return bResult;
1046}
1047
1048BOOL CEraserDoc::ReadPreferences()
1049{
1050    TRACE("CEraserDoc::ReadPreferences\n");
1051
1052    BOOL            bResult     = TRUE;
1053    CKey            kReg_reg;
1054    CIniKey         kReg_ini;
1055    CKey           &kReg = no_registry ? kReg_ini : kReg_reg;
1056    CString         strPath;
1057    OSVERSIONINFO   ov;
1058
1059    strPath.Format("%s\\%s", ERASER_REGISTRY_BASE, szSettingsKey);
1060
1061    ZeroMemory(&ov, sizeof(OSVERSIONINFO));
1062    ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1063
1064    GetVersionEx(&ov);
1065
1066    // Scheduler Preferences
1067    if (kReg.Open(HKEY_CURRENT_USER, strPath))
1068    {
1069        kReg.GetValue(m_bSchedulerEnabled, szSchedulerEnabled, TRUE);
1070        kReg.GetValue(m_bLog, szLog, TRUE);
1071        kReg.GetValue(m_bLogOnlyErrors, szLogOnlyErrors, FALSE);
1072        kReg.GetValue(m_bStartup, szStartup, TRUE);
1073        kReg.GetValue(m_bQueueTasks, szQueueTasks, TRUE);
1074        kReg.GetValue(m_bNoVisualErrors, szNoVisualErrors, FALSE);
1075        kReg.GetValue(m_dwMaxLogSize, szMaxLogSize, 10);
1076
1077        kReg.Close();
1078    }
1079    else
1080        bResult = FALSE;
1081
1082    // General Preferences
1083    if (kReg.Open(HKEY_CURRENT_USER, ERASER_REGISTRY_BASE))
1084    {
1085        if (m_dwStartView == (DWORD) -1)
1086            kReg.GetValue(m_dwStartView, szStartView, VIEW_ERASER);
1087
1088        ZeroMemory(&m_rWindowRect, sizeof(RECT));
1089
1090        if (kReg.GetValueSize(szWindowRect) == sizeof(RECT))
1091            kReg.GetValue((LPVOID)&m_rWindowRect, szWindowRect);
1092
1093        kReg.GetValue(m_bResultsForFiles, ERASER_REGISTRY_RESULTS_FILES, TRUE);
1094        kReg.GetValue(m_bResultsForUnusedSpace, ERASER_REGISTRY_RESULTS_UNUSEDSPACE, TRUE);
1095        kReg.GetValue(m_bResultsOnlyWhenFailed, ERASER_REGISTRY_RESULTS_WHENFAILED, FALSE);
1096        kReg.GetValue(m_bShellextResults, ERASEXT_REGISTRY_RESULTS, TRUE);
1097        kReg.GetValue(m_bErasextEnabled, ERASEXT_REGISTRY_ENABLED, TRUE);
1098        kReg.GetValue(m_bEnableSlowPoll, ERASER_RANDOM_SLOW_POLL, FALSE);
1099        kReg.GetValue(m_bIconAnimation, szIconAnimation, FALSE);
1100        kReg.GetValue(m_bSmallIconView, szSmallIconView, FALSE);
1101        kReg.GetValue(m_dwOutbarWidth, szOutBarWidth, 0);
1102        kReg.GetValue(m_bNoTrayIcon, szNoTrayIcon, FALSE);
1103        kReg.GetValue(m_bHideOnMinimize, szHideOnMinimize, FALSE);
1104        kReg.GetValue(m_bViewInfoBar, szViewInfoBar, FALSE);
1105        kReg.GetValue(m_bResolveLock, szResolveLock, TRUE);
1106        kReg.GetValue(m_bResolveAskUser, szResolveAskUser, TRUE);
1107       
1108
1109        kReg.Close();
1110    }
1111    else
1112        bResult = FALSE;
1113
1114    // Page File Clearing only on NT
1115    m_bClearSwap = FALSE;
1116
1117    if (ov.dwPlatformId == VER_PLATFORM_WIN32_NT)
1118    {
1119        if (kReg_reg.Open(HKEY_LOCAL_MACHINE, szClearSwapPath))
1120        {
1121            kReg_reg.GetValue(m_bClearSwap, szClearSwapValue, FALSE);
1122            kReg_reg.Close();
1123        }
1124    }
1125
1126    return bResult;
1127}
1128
1129void CEraserDoc::OnEditPreferencesGeneral()
1130{
1131    TRACE("CEraserDoc::OnEditPreferencesGeneral\n");
1132
1133    ReadPreferences();
1134
1135    CPreferencesSheet propSheet;
1136
1137    // General
1138
1139   
1140
1141    propSheet.m_pgEraser.m_bResultsForFiles         = m_bResultsForFiles;
1142    propSheet.m_pgEraser.m_bResultsForUnusedSpace   = m_bResultsForUnusedSpace;
1143    propSheet.m_pgEraser.m_bResultsOnlyWhenFailed   = m_bResultsOnlyWhenFailed;
1144    propSheet.m_pgEraser.m_bShellextResults         = m_bShellextResults;
1145    propSheet.m_pgEraser.m_bErasextEnabled          = m_bErasextEnabled;
1146    propSheet.m_pgEraser.m_bEnableSlowPoll          = m_bEnableSlowPoll;
1147    propSheet.m_pgEraser.m_bClearSwap               = m_bClearSwap;
1148    propSheet.m_pgEraser.m_bResolveLock             = m_bResolveLock;
1149    propSheet.m_pgEraser.m_bResolveAskUser          = m_bResolveAskUser;               
1150
1151
1152    // Scheduler
1153
1154    propSheet.m_pgScheduler.m_bNoTrayIcon           = m_bNoTrayIcon;
1155    propSheet.m_pgScheduler.m_bHideOnMinimize       = m_bHideOnMinimize;
1156    propSheet.m_pgScheduler.m_bLog                  = m_bLog;
1157    propSheet.m_pgScheduler.m_bLogOnlyErrors        = m_bLogOnlyErrors;
1158    propSheet.m_pgScheduler.m_bStartup              = m_bStartup;
1159    propSheet.m_pgScheduler.m_bEnabled              = m_bSchedulerEnabled;
1160    propSheet.m_pgScheduler.m_bQueueTasks           = m_bQueueTasks;
1161    propSheet.m_pgScheduler.m_bNoVisualErrors       = m_bNoVisualErrors;
1162    propSheet.m_pgScheduler.m_dwMaxLogSize          = m_dwMaxLogSize;
1163
1164    if (propSheet.DoModal())
1165    {
1166        // General
1167
1168        m_bResultsForFiles          = propSheet.m_pgEraser.m_bResultsForFiles;
1169        m_bResultsForUnusedSpace    = propSheet.m_pgEraser.m_bResultsForUnusedSpace;
1170        m_bResultsOnlyWhenFailed    = propSheet.m_pgEraser.m_bResultsOnlyWhenFailed;
1171        m_bShellextResults          = propSheet.m_pgEraser.m_bShellextResults;
1172        m_bErasextEnabled           = propSheet.m_pgEraser.m_bErasextEnabled;
1173        m_bEnableSlowPoll           = propSheet.m_pgEraser.m_bEnableSlowPoll;
1174        m_bClearSwap                = propSheet.m_pgEraser.m_bClearSwap;
1175        m_bResolveLock              = propSheet.m_pgEraser.m_bResolveLock;
1176        m_bResolveAskUser           = propSheet.m_pgEraser.m_bResolveAskUser;
1177
1178        // Scheduler
1179
1180        m_bNoTrayIcon               = propSheet.m_pgScheduler.m_bNoTrayIcon;
1181        m_bHideOnMinimize           = propSheet.m_pgScheduler.m_bHideOnMinimize;
1182        m_bLog                      = propSheet.m_pgScheduler.m_bLog;
1183        m_bLogOnlyErrors            = propSheet.m_pgScheduler.m_bLogOnlyErrors;
1184        m_bStartup                  = propSheet.m_pgScheduler.m_bStartup;
1185        m_bSchedulerEnabled         = propSheet.m_pgScheduler.m_bEnabled;
1186        m_bQueueTasks               = propSheet.m_pgScheduler.m_bQueueTasks;
1187        m_bNoVisualErrors           = propSheet.m_pgScheduler.m_bNoVisualErrors;
1188        m_dwMaxLogSize              = propSheet.m_pgScheduler.m_dwMaxLogSize;
1189
1190        if (!m_bNoTrayIcon && !m_stIcon.Visible())
1191            m_stIcon.ShowIcon();
1192        else if (m_bNoTrayIcon)
1193        {
1194            if (!m_bHideOnMinimize && !AfxGetMainWnd()->IsWindowVisible())
1195                AfxGetMainWnd()->ShowWindow(SW_SHOWMINIMIZED);
1196            else if (m_bHideOnMinimize && AfxGetMainWnd()->IsIconic())
1197                AfxGetMainWnd()->ShowWindow(SW_HIDE);
1198
1199            m_stIcon.HideIcon();
1200        }
1201
1202        UpdateToolTip();
1203
1204        if (!SavePreferences())
1205        {
1206            AfxTimeOutMessageBox(IDS_ERROR_PREFERENCES_SAVE, MB_ICONERROR);
1207
1208            if (m_bLog)
1209                LogAction(IDS_ERROR_PREFERENCES_SAVE);
1210        }
1211    }
1212}
1213
1214void CEraserDoc::OnEditPreferencesEraser()
1215{
1216    TRACE("CEraserDoc::OnEditPreferencesEraser\n");
1217    eraserShowOptions(AfxGetMainWnd()->GetSafeHwnd(), ERASER_PAGE_FILES);
1218}
1219
1220void CEraserDoc::OnFileViewLog()
1221{
1222    TRACE("CEraserDoc::OnFileViewLog\n");
1223
1224    CFileStatus fs;
1225    CString strPath = m_strExePath + szLogFile;
1226
1227    if (CFile::GetStatus((LPCTSTR)strPath, fs))
1228    {
1229        if (reinterpret_cast<int>(ShellExecute(NULL, "open", (LPCTSTR)strPath,
1230                                               NULL, NULL, SW_SHOWNORMAL)) <= 32)
1231        {
1232            AfxMessageBox(IDS_ERROR_VIEWLOG, MB_ICONERROR, 0);
1233        }
1234    }
1235    else
1236    {
1237        AfxMessageBox(IDS_INFO_NOLOG, MB_ICONINFORMATION, 0);
1238    }
1239}
1240
1241BOOL CEraserDoc::Export(LPCTSTR szFile, BOOL bErrors)
1242{
1243    TRACE("CEraserDoc::Export\n");
1244
1245    // export the present items into a file
1246
1247    CFileException fe;
1248    CFile* pFile = NULL;
1249
1250    pFile = GetFile(szFile, CFile::modeCreate |
1251                    CFile::modeReadWrite | CFile::shareExclusive, &fe);
1252
1253    if (pFile == NULL)
1254    {
1255        if (bErrors)
1256            ReportSaveLoadException(szFile, &fe, TRUE, AFX_IDP_INVALID_FILENAME);
1257        return FALSE;
1258    }
1259
1260    CArchive saveArchive(pFile, CArchive::store | CArchive::bNoFlushOnDelete);
1261
1262    saveArchive.m_pDocument  = this;
1263    saveArchive.m_bForceFlat = FALSE;
1264
1265    try
1266    {
1267        CWaitCursor wait;
1268        Serialize(saveArchive);
1269
1270        saveArchive.Close();
1271        ReleaseFile(pFile, FALSE);
1272    }
1273    catch (CFileException* e)
1274    {
1275        ASSERT(FALSE);
1276
1277        ReleaseFile(pFile, TRUE);
1278
1279        if (bErrors)
1280        {
1281            try
1282            {
1283                ReportSaveLoadException(szFile, e, TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
1284            }
1285            catch (...)
1286            {
1287            }
1288        }
1289
1290        if (m_bLog)
1291            LogException(e);
1292
1293        e->Delete();
1294        return FALSE;
1295    }
1296    catch (CException *e)
1297    {
1298        ASSERT(FALSE);
1299
1300        ReleaseFile(pFile, TRUE);
1301
1302        if (bErrors)
1303            REPORT_ERROR(e);
1304
1305        if (m_bLog)
1306            LogException(e);
1307
1308        e->Delete();
1309        return FALSE;
1310    }
1311
1312    return TRUE;
1313}
1314
1315BOOL CEraserDoc::Import(LPCTSTR szFile, BOOL bErrors)
1316{
1317    TRACE("CEraserDoc::Import\n");
1318
1319    // import items from a file without removing
1320    // present items
1321
1322    CFileException fe;
1323    CFile* pFile = NULL;
1324
1325    pFile = GetFile(szFile, CFile::modeRead | CFile::shareDenyWrite, &fe);
1326
1327    if (pFile == NULL)
1328    {
1329        if (bErrors)
1330            ReportSaveLoadException(szFile, &fe, TRUE, AFX_IDP_INVALID_FILENAME);
1331        return FALSE;
1332    }
1333
1334    CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete);
1335
1336    loadArchive.m_pDocument  = this;
1337    loadArchive.m_bForceFlat = FALSE;
1338
1339    try
1340    {
1341        CWaitCursor wait;
1342        if (pFile->GetLength() != 0)
1343            Serialize(loadArchive);
1344
1345        loadArchive.Close();
1346        ReleaseFile(pFile, FALSE);
1347    }
1348    catch (CFileException* e)
1349    {
1350        ASSERT(FALSE);
1351
1352        ReleaseFile(pFile, TRUE);
1353
1354        if (bErrors)
1355        {
1356            try
1357            {
1358                ReportSaveLoadException(szFile, e, TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
1359            }
1360            catch (...)
1361            {
1362            }
1363        }
1364
1365        if (m_bLog)
1366            LogException(e);
1367
1368        e->Delete();
1369        return FALSE;
1370    }
1371    catch (CException *e)
1372    {
1373        ASSERT(FALSE);
1374
1375        ReleaseFile(pFile, TRUE);
1376
1377        if (bErrors)
1378            REPORT_ERROR(e);
1379
1380        if (m_bLog)
1381            LogException(e);
1382
1383        e->Delete();
1384        return FALSE;
1385    }
1386
1387    return TRUE;
1388}
1389
1390BOOL CEraserDoc::SaveTasksToDefault()
1391{
1392    CString strDefault = m_strExePath + szDefaultFile;
1393    return Export((LPCTSTR)strDefault);
1394}
1395
1396void CEraserDoc::OnCloseDocument()
1397{
1398    TRACE("CEraserDoc::OnCloseDocument\n");
1399
1400    try
1401    {
1402        SaveTasksToDefault();
1403        CDocument::OnCloseDocument();
1404    }
1405    catch (CException *e)
1406    {
1407        ASSERT(FALSE);
1408        REPORT_ERROR(e);
1409        e->Delete();
1410    }
1411}
1412
1413
1414//DEL void CEraserDoc::OnHelpReward()
1415//DEL {
1416//DEL     AfxGetApp()->WinHelp(HID_BASE_COMMAND + ID_HELP_REWARD);
1417//DEL }
1418
1419void CEraserDoc::CleanList(CPtrArray& rList, int iItemSize)
1420{
1421    int iSize = rList.GetSize();
1422    while (iSize--)
1423    {
1424        if (!AfxIsValidAddress(rList[iSize], iItemSize))
1425            rList.RemoveAt(iSize);
1426    }
1427    rList.FreeExtra();
1428}
Note: See TracBrowser for help on using the repository browser.