source: trunk/EraserDll/FreeSpace.cpp @ 83

Revision 83, 24.7 KB checked in by gtrant, 7 years ago (diff)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1// FreeSpace.cpp
2//
3// Eraser. Secure data removal. For Windows.
4// Copyright © 1997-2001  Sami Tolvanen (sami@tolvanen.com).
5// Copyright © 2007 The Eraser Project
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; either version 2
10// of the License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20// 02111-1307, USA.
21
22#include "stdafx.h"
23#include "resource.h"
24#include "EraserDll.h"
25#include "..\shared\FileHelper.h"
26#include "..\shared\key.h"
27#include "Common.h"
28#include "File.h"
29#include "FAT.h"
30#include "NTFS.h"
31#include "FreeSpace.h"
32#include <winioctl.h>
33
34
35// Windows 98 - Q188074
36static const LPCTSTR ERASER_REGISTRY_FILESYSTEM
37    = "System\\CurrentControlSet\\Control\\FileSystem";
38static const LPCTSTR ERASER_REGISTRY_LOWDISKSPACE
39    = "DisableLowDiskSpaceBroadcast";
40
41#undef MAX_PATH
42#define MAX_PATH 2048 //HACK: Some filenames under Vista can exceed the 260
43                      //char limit. This will have to do for now.
44
45static inline E_UINT32
46disableLowDiskSpaceNotification(TCHAR szDrive)
47{
48    // disables the annoying warning Windows 98 displays when disk space is low
49    if (!isWindowsNT) {
50        CKey kReg;
51        E_UINT32 uOldValue = 0;
52        E_UINT32 uNewValue = (1 << (toupper((E_INT32)szDrive) - (E_INT32)'A'));
53
54        if (kReg.Open(HKEY_LOCAL_MACHINE, ERASER_REGISTRY_FILESYSTEM)) {
55            // save the previous value (if it exists)
56            kReg.GetValue(uOldValue, ERASER_REGISTRY_LOWDISKSPACE, 0);
57            kReg.SetValue(uNewValue, ERASER_REGISTRY_LOWDISKSPACE);
58
59            kReg.Close();
60        }
61        return uOldValue;
62    }
63
64    return 0;
65}
66
67static inline void
68restoreLowDiskSpaceNotification(E_UINT32 uOldValue)
69{
70    // restores the old value for the low disk space notification key
71    if (!isWindowsNT) {
72        CKey kReg;
73        if (kReg.Open(HKEY_LOCAL_MACHINE, ERASER_REGISTRY_FILESYSTEM)) {
74            if (uOldValue != 0) {
75                kReg.SetValue(uOldValue, ERASER_REGISTRY_LOWDISKSPACE);
76            } else {
77                kReg.DeleteValue(ERASER_REGISTRY_LOWDISKSPACE);
78            }
79            kReg.Close();
80        }
81    }
82}
83
84static inline BOOL
85uncompressFolder(LPCTSTR szFolder)
86{
87    // if folder is compressed, this uncompresses it
88    if (isWindowsNT) {
89        HANDLE hHandle = INVALID_HANDLE_VALUE;
90
91        hHandle = CreateFile(szFolder, GENERIC_READ | GENERIC_WRITE, 0, NULL,
92                             OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
93
94        if (hHandle != INVALID_HANDLE_VALUE) {
95            BOOL   bSuccess    = FALSE;
96            E_UINT16 uCompressed = COMPRESSION_FORMAT_NONE;
97            E_UINT32 uReturned   = 0;
98
99            bSuccess = DeviceIoControl(hHandle, FSCTL_GET_COMPRESSION, NULL, 0,
100                                       &uCompressed, sizeof(E_UINT16), &uReturned,
101                                       NULL);
102
103            if (bSuccess && (uCompressed != COMPRESSION_FORMAT_NONE)) {
104                // it is compressed - change attributes
105                uCompressed = COMPRESSION_FORMAT_NONE;
106
107                bSuccess = DeviceIoControl(hHandle, FSCTL_SET_COMPRESSION,
108                                           &uCompressed, sizeof(E_UINT16),
109                                           NULL, 0, &uReturned, NULL);
110            }
111
112            CloseHandle(hHandle);
113            return bSuccess;
114        }
115    }
116
117    return FALSE;
118}
119
120bool
121getClusterAndSectorSize(LPCTSTR szDrive, E_UINT32& uCluster, E_UINT32& uSector)
122{
123    uCluster = 0;
124    uSector = DEFAULT_SECTOR_SIZE;
125
126    try {
127        if (isWindowsNT) {
128            // GetDiskFreeSpace will return correct values
129            E_UINT32 uSecPerClus = 0;
130            E_UINT32 uBytPerSec  = 0;
131            E_UINT32 uFreeClus   = 0;
132            E_UINT32 uClus       = 0;
133
134            if (GetDiskFreeSpace(szDrive, &uSecPerClus, &uBytPerSec,
135                                 &uFreeClus, &uClus)) {
136                uSector = uBytPerSec;
137                uCluster = (uSector * uSecPerClus);
138            }
139        } else {
140            // GetDiskFreeSpace returns false results on drives larger than 2 GB
141            return getFATClusterAndSectorSize(szDrive, uCluster, uSector);
142        }
143    } catch (...) {
144        ASSERT(0);
145    }
146
147    return (uCluster > 0);
148}
149
150bool
151getClusterSize(LPCTSTR szDrive, E_UINT32& uCluster)
152{
153    E_UINT32 uSector = 0;
154    return getClusterAndSectorSize(szDrive, uCluster, uSector);
155}
156
157bool
158getPartitionType(PARTITIONINFO& pi)
159{
160    TCHAR szFS[MAX_PATH];
161
162    if (GetVolumeInformation(pi.m_szDrive, NULL, 0, NULL, NULL, NULL, szFS, MAX_PATH)) {
163        if (_strcmpi(szFS, "FAT32") == 0) {
164            pi.m_fsType = fsFAT32;
165        } else if (_strcmpi(szFS, "FAT") == 0) {
166            pi.m_fsType = fsFAT;
167        } else if (_strcmpi(szFS, "NTFS") == 0) {
168            pi.m_fsType = fsNTFS;
169        } else {
170            pi.m_fsType = fsUnknown;
171        }
172        return true;
173    } else {
174        return false;
175    }
176}
177
178bool
179getPartitionInformation(CEraserContext *context, TCHAR cDrive)
180{
181    cDrive = (TCHAR)toupper(cDrive);
182
183    if (cDrive != context->m_piCurrent.m_szDrive[0] ||
184        context->m_piCurrent.m_bLastSuccess == false) {
185
186        // partition information wasn't cached
187        context->m_piCurrent.m_szDrive[0] = cDrive;
188
189        if (context->m_piCurrent.m_szDrive[0] < 'A' ||
190            context->m_piCurrent.m_szDrive[0] > 'Z') {
191
192            context->m_piCurrent.m_szDrive[0] = ' ';
193            context->m_piCurrent.m_bLastSuccess = false;
194        } else {
195            // determine file system type
196            context->m_piCurrent.m_bLastSuccess = getPartitionType(context->m_piCurrent);
197
198            // cluster and sector size, but not if erasing files and user
199            // doesn't want to touch cluster tip area
200
201            if (context->m_edtDataType != ERASER_DATA_FILES ||
202                bitSet(context->m_lsSettings.m_uItems, fileClusterTips)) {
203
204                if (!getClusterAndSectorSize(context->m_piCurrent.m_szDrive,
205                                             context->m_piCurrent.m_uCluster,
206                                             context->m_piCurrent.m_uSector)) {
207                    eraserAddError1(context, IDS_ERROR_CLUSTER, context->m_piCurrent.m_szDrive);
208                    context->m_piCurrent.m_bLastSuccess = false;
209                }
210            }
211        }
212    }
213
214    return context->m_piCurrent.m_bLastSuccess;
215}
216
217bool hasPrivileges(CEraserContext *context)
218{
219    // under Vista if the user is not elevated write an error to the log and return
220    OSVERSIONINFO verInfo;
221    ::ZeroMemory(&verInfo, sizeof(verInfo));
222    verInfo.dwOSVersionInfoSize = sizeof(verInfo);
223    if (GetVersionEx(&verInfo) && verInfo.dwMajorVersion >= 6)
224    {
225        HANDLE hToken;
226        TOKEN_ELEVATION_TYPE elevationType;
227        DWORD returnSize;
228        OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
229
230        if (hToken)
231        {
232            GetTokenInformation(hToken, TokenElevationType,
233                &elevationType, sizeof(elevationType), &returnSize);
234            CloseHandle(hToken);
235            if (elevationType == TokenElevationTypeLimited) {
236                context->m_saError.Add("Erasing the Free Space of a drive requires elevation");
237                return false;
238            }
239        }
240    }
241
242    return true;
243}
244
245void
246countFilesOnDrive(CEraserContext *context, const CString& strDrive, E_UINT32& uFiles, E_UINT32& uFolders)
247{
248    // counts the amount of files on drive (including subfolders)
249    HANDLE          hFind;
250    WIN32_FIND_DATA wfdData;
251    CString         strRoot(strDrive);
252
253    // make sure that the directory name ends with a backslash
254
255    if (strRoot[strRoot.GetLength() - 1] != '\\') {
256        strRoot += "\\";
257    }
258
259    hFind = FindFirstFile((LPCTSTR) (strRoot + "*"), &wfdData);
260
261    if (hFind != INVALID_HANDLE_VALUE) {
262        try {
263            do {
264                if (eraserInternalTerminated(context)) {
265                    break;
266                }
267
268                // skip volume mount point
269                if (bitSet(wfdData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
270                    continue;
271                }
272                if (bitSet(wfdData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
273                    // skip "." and ".."
274                    if (ISNT_SUBFOLDER(wfdData.cFileName)) {
275                        continue;
276                    }
277
278                    uFolders++;
279
280                    // recursive for subfolders
281                    countFilesOnDrive(context, (strRoot + wfdData.cFileName), uFiles, uFolders);
282                } else {
283                    uFiles++;
284                }
285            } while (FindNextFile(hFind, &wfdData));
286        } catch (...) {
287            ASSERT(0);
288        }
289
290        VERIFY(FindClose(hFind));
291    }
292}
293
294static bool
295wipeClusterTipsRecursive(CEraserContext *context, SFCISFILEPROTECTED pSfcIsFileProtected)
296{
297    // wipes unused cluster tips of each file on the drive given by context->m_strData
298
299    // the cluster size must have been set before calling this function
300    if (context->m_piCurrent.m_uCluster == 0) {
301        return false;
302    }
303
304    HANDLE hFind;
305    WIN32_FIND_DATA wfdData;
306    bool bCompleted = true;
307    CString strDirectory = context->m_strData;
308
309    // the directory name must end with a backslash
310    if (strDirectory[strDirectory.GetLength() - 1] != '\\') {
311        strDirectory += "\\";
312    }
313
314    hFind = FindFirstFile((LPCTSTR) (strDirectory + "*"), &wfdData);
315
316    if (hFind != INVALID_HANDLE_VALUE) {
317        WCHAR    szWideName[MAX_PATH];
318        CString  strFile;
319        E_UINT32 uAttributes;
320        E_UINT64 ulTotalSize;
321        FILETIME ftCreation, ftLastAccess, ftLastWrite;
322        bool     bSuccess;
323        bool     bIgnoreFile;
324
325        do {
326            if (eraserInternalTerminated(context)) {
327                bCompleted = false;
328                break;
329            }
330
331            if (bitSet(wfdData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
332                // skip volume mount point
333                if (bitSet(wfdData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
334                    strFile = strDirectory + wfdData.cFileName;
335                    context->m_saFailed.Add(strFile + " (Reparse point)");
336                    continue;
337                }
338                // skip "." and ".."
339                if (ISNT_SUBFOLDER(wfdData.cFileName)) {
340                    continue;
341                }
342                eraserSafeAssign(context, context->m_strData, strDirectory + wfdData.cFileName);
343
344                // recursive for subfolders
345                eraserBool(bCompleted, wipeClusterTipsRecursive(context, pSfcIsFileProtected));
346            } else {
347                // wipe slack space on the file
348                strFile = strDirectory + wfdData.cFileName;
349                eraserSafeAssign(context, context->m_strData, strFile);
350
351                bIgnoreFile = false;
352
353                // System File Protection - use only for Windows 2000 and later
354                if (isWindowsNT && pSfcIsFileProtected) {
355                    try {
356                        asciiToUnicode((LPCSTR)strFile, (LPWSTR)szWideName);
357
358                        // we skip protected files to avoid confusing the user
359                        if (pSfcIsFileProtected(NULL, (LPCWSTR)szWideName)) {
360                            context->m_saFailed.Add(strFile + " (Protected File)");
361
362                            bIgnoreFile = true;
363                            bCompleted = false;
364                        }
365                    } catch (...) {
366                        ASSERT(0);
367                    }
368                }
369
370                // wanna skip other files? add the code here then...
371
372                if (!bIgnoreFile) {
373                    eraserBeginNotify(context);
374
375                    // save file attributes
376                    uAttributes = GetFileAttributes((LPCTSTR)strFile);
377
378                    // skip compressed (and encrypted) files as overwriting the cluster tips
379                    // on them (or even opening) causes fragmentation and is useless anyway
380                    bIgnoreFile = (isWindowsNT && uAttributes != (E_UINT32)-1 &&
381                                   (bitSet(uAttributes, FILE_ATTRIBUTE_COMPRESSED) ||
382                                    bitSet(uAttributes, FILE_ATTRIBUTE_ENCRYPTED)  ||
383                                    bitSet(uAttributes, FILE_ATTRIBUTE_SPARSE_FILE)));
384
385                    if (!bIgnoreFile) {
386                        // change file attributes temporarily
387                        SetFileAttributes((LPCTSTR)strFile, FILE_ATTRIBUTE_NORMAL);
388
389                        context->m_hFile = CreateFile((LPCTSTR)strFile,
390                                                      GENERIC_READ | GENERIC_WRITE,
391                                                      (context->m_uTestMode) ?
392                                                        FILE_SHARE_READ | FILE_SHARE_WRITE : 0,
393                                                      NULL, OPEN_EXISTING,
394                                                      FILE_FLAG_WRITE_THROUGH,
395                                                      NULL);
396
397                        bSuccess = (context->m_hFile != INVALID_HANDLE_VALUE);
398
399                        if (bSuccess) {
400                            // save dates
401                            GetFileTime(context->m_hFile, &ftCreation, &ftLastAccess, &ftLastWrite);
402
403                            // file size
404                            context->m_uiFileSize.LowPart = GetFileSize(context->m_hFile, &context->m_uiFileSize.HighPart);
405
406                            if (context->m_uiFileSize.LowPart == (E_UINT32)-1 && GetLastError() != NO_ERROR) {
407                                bSuccess = false;
408                            } else {
409                                ulTotalSize = fileSizeToArea(context, context->m_uiFileSize.QuadPart);
410
411                                // continue if there is something to overwrite
412                                if (ulTotalSize > context->m_uiFileSize.QuadPart) {
413                                    context->m_uiFileStart.QuadPart = context->m_uiFileSize.QuadPart;
414                                    context->m_uiFileSize.QuadPart = ulTotalSize - context->m_uiFileSize.QuadPart;
415
416                                    context->m_uClusterSpace = context->m_uiFileSize.LowPart;
417
418                                    try {
419                                        // overwrite
420                                        bSuccess = context->m_lpmMethod->m_pwfFunction(context);
421                                    } catch (...) {
422                                        bSuccess = false;
423                                    }
424
425                                    // restore size
426                                    SetFilePointer(context->m_hFile, context->m_uiFileStart.LowPart,
427                                                   (LPLONG)&context->m_uiFileStart.HighPart, FILE_BEGIN);
428                                    SetEndOfFile(context->m_hFile);
429                                }
430                            }
431
432                            // restore dates
433                            SetFileTime(context->m_hFile, &ftCreation, &ftLastAccess, &ftLastWrite);
434                            CloseHandle(context->m_hFile);
435                        }
436
437                        // restore attributes
438                        SetFileAttributes((LPCTSTR)strFile, uAttributes);
439
440                        if (!bSuccess) {
441                            context->m_saFailed.Add(strFile);
442                            bCompleted = false;
443                        }
444                    }
445                }
446
447                // next file
448                context->m_uProgressWipedFiles++;
449
450                // set progress
451                eraserSafeAssign(context, context->m_uProgressPercent,
452                    (E_UINT8)((context->m_uProgressWipedFiles * 100) / context->m_uProgressFiles));
453                setTotalProgress(context);
454                eraserUpdateNotify(context);
455            }
456        } while (FindNextFile(hFind, &wfdData));
457
458        VERIFY(FindClose(hFind));
459    }
460
461    return bCompleted;
462}
463
464bool
465wipeClusterTips(CEraserContext *context)
466{
467    if (!hasPrivileges(context))
468        return false;
469    if (context->m_lpmMethod->m_nMethodID == FL2KB_METHOD_ID)
470        return false;
471
472    bool               bReturn = false;
473    SFCISFILEPROTECTED pSfcIsFileProtected = 0;
474    HINSTANCE          hInst = AfxLoadLibrary(ERASER_MODULENAME_SFC);
475
476    if (hInst != NULL) {
477        pSfcIsFileProtected = (SFCISFILEPROTECTED)GetProcAddress(hInst,
478                                    ERASER_FUNCTIONNAME_SFCISFILEPROTECTED);
479    }
480
481    // reset progress
482    context->m_uProgressWipedFiles = 0;
483
484    try {
485        bReturn = wipeClusterTipsRecursive(context, pSfcIsFileProtected);
486    } catch (CException *e) {
487        handleException(e, context);
488        bReturn = false;
489    }
490
491    if (hInst != NULL) {
492        AfxFreeLibrary(hInst);
493    }
494
495    return bReturn;
496}
497
498
499bool
500wipeFreeSpace(CEraserContext *context)
501{
502    if (!hasPrivileges(context))
503        return false;
504    if (context->m_lpmMethod->m_nMethodID == FL2KB_METHOD_ID)
505        return false;
506
507    CString strFolder;
508
509    try {
510        strFolder.Format("%s%s", context->m_piCurrent.m_szDrive, ERASER_TEMP_DIRECTORY);
511
512        // remove possibly existing folder
513        eraserRemoveFolder((LPVOID)(LPCTSTR)strFolder, (E_UINT16)strFolder.GetLength(),
514                           ERASER_REMOVE_RECURSIVELY);
515
516        // create temporary directory for temporary files
517        if (CreateDirectory((LPCTSTR)strFolder, NULL)) {
518            bool bResult = false;
519
520            try {
521                // make sure NTFS folder isn't compressed
522                uncompressFolder((LPCTSTR)strFolder);
523
524                bResult = eraserOK(eraserGetFreeDiskSpace((LPVOID)context->m_piCurrent.m_szDrive,
525                                   (E_UINT16)lstrlen(context->m_piCurrent.m_szDrive),
526                                   &context->m_uiFileSize.QuadPart));
527
528                if (bResult) {
529                    CString  strTempFile;
530                    TCHAR    szFileName[uShortFileNameLength + 1];
531                    E_UINT32 uFileSize = (E_UINT32)fileSizeToArea(context, ERASER_MAX_FILESIZE);
532                    E_UINT32 uFiles;
533                    E_UINT32 uAccessFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING;
534
535                    // calculate the amount of fixed size files needed
536                    if (context->m_uiFileSize.QuadPart > (E_UINT64)uFileSize) {
537                        uFiles = (E_UINT32)(context->m_uiFileSize.QuadPart / (E_UINT64)uFileSize);
538                    } else {
539                        uFiles = 1;
540                    }
541
542                    // disable "Low Disk Space Notification" - Q188074, I am not so
543                    // convinced this works as advertized...
544                    E_UINT32 uWarningValue =
545                        disableLowDiskSpaceNotification(context->m_piCurrent.m_szDrive[0]);
546
547                    // show continuous progress info as if we were wiping only one file
548                    eraserProgressStartEstimate(context, context->m_uiFileSize.QuadPart);
549
550                    // set file size
551                    context->m_uiFileStart.QuadPart = 0;
552                    context->m_uiFileSize.QuadPart = uFileSize;
553                    context->m_uClusterSpace = 0;
554
555                    for (E_UINT32 uCurrent = 1; uCurrent <= uFiles; uCurrent++) {
556                        if (eraserInternalTerminated(context)) {
557                            bResult = false;
558                            break;
559                        }
560
561                        createRandomShortFileName(szFileName, (E_UINT16)uCurrent);
562                        strTempFile.Format("%s\\%s", strFolder, szFileName);
563
564                        // cannot disable buffering for the last file, its size may not be sector aligned
565                        if (uCurrent == uFiles) {
566                            uAccessFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH;
567                        }
568
569                        context->m_hFile = CreateFile(strTempFile,
570                                                     GENERIC_WRITE, (context->m_uTestMode) ?
571                                                        FILE_SHARE_READ | FILE_SHARE_WRITE : 0,
572                                                     NULL, OPEN_ALWAYS, uAccessFlags, NULL);
573
574                        if (context->m_hFile != INVALID_HANDLE_VALUE) {
575                            // the size of the last file is the amount of space available
576                            try {
577                                if (uCurrent == uFiles) {
578                                    if (eraserOK(eraserGetFreeDiskSpace((LPVOID)context->m_piCurrent.m_szDrive,
579                                            (E_UINT16)lstrlen(context->m_piCurrent.m_szDrive),
580                                            &context->m_uiFileSize.QuadPart))) {
581
582                                        context->m_uProgressSize = UInt32x32To64((uFiles - 1), uFileSize) +
583                                                                   context->m_uiFileSize.QuadPart;
584
585                                        // set end of file
586                                        SetFilePointer(context->m_hFile, context->m_uiFileSize.LowPart,
587                                                       (LPLONG)&context->m_uiFileSize.HighPart, FILE_BEGIN);
588                                        SetEndOfFile(context->m_hFile);
589
590                                        // overwrite
591                                        bResult = context->m_lpmMethod->m_pwfFunction(context);
592                                    } else {
593                                        bResult = false;
594                                        eraserAddError1(context, IDS_ERROR_FREESPACE,
595                                            (LPCTSTR)context->m_piCurrent.m_szDrive);
596                                        context->m_saFailed.Add(context->m_strData);
597                                    }
598                                } else {
599                                    // overwrite
600                                    bResult = context->m_lpmMethod->m_pwfFunction(context);
601                                }
602                            } catch (CException *e) {
603                                handleException(e, context);
604                                bResult = false;
605                            }
606
607                            resetDate(context->m_hFile);
608                            CloseHandle(context->m_hFile);
609
610                            // don't add an error to the list if we were terminated
611                            if (!bResult && !eraserInternalTerminated(context)) {
612                                context->m_saFailed.Add(strTempFile);
613                            }
614                        } else {
615                            eraserAddError(context, IDS_ERROR_TEMPFILE);
616                            bResult = false;
617                        }
618
619                        // if something failed, give up
620                        if (!bResult) {
621                            break;
622                        }
623                    }
624
625                    // wipe unused space from MFT if an NTFS drive
626                    if (bResult && isWindowsNT && isFileSystemNTFS(context->m_piCurrent)) {
627                        increaseTotalProgressPercent(context);
628                        eraserBool(bResult, wipeMFTRecords(context));
629                    }
630
631                    // restore the "Low Disk Space Notification" value
632                    restoreLowDiskSpaceNotification(uWarningValue);
633                } else {
634                    eraserAddError1(context, IDS_ERROR_FREESPACE,
635                                    (LPCTSTR)context->m_piCurrent.m_szDrive);
636                    context->m_saFailed.Add(context->m_strData);
637                }
638            } catch (CException *e) {
639                handleException(e, context);
640                bResult = false;
641            }
642
643            // remove temporary directory and set error if failed
644            if (eraserError(eraserRemoveFolder((LPVOID)(LPCTSTR)strFolder,
645                    (E_UINT16)strFolder.GetLength(), ERASER_REMOVE_RECURSIVELY))) {
646
647                eraserAddError1(context, IDS_ERROR_DIRECTORY_REMOVE,
648                                (LPCTSTR)context->m_piCurrent.m_szDrive);
649                context->m_saFailed.Add(strFolder);
650                bResult = false;
651            }
652
653            return bResult;
654        } else {
655            eraserAddError1(context, IDS_ERROR_DIRECTORY,
656                            (LPCTSTR)context->m_piCurrent.m_szDrive);
657            context->m_saFailed.Add(context->m_strData);
658        }
659    } catch (CException *e) {
660        handleException(e, context);
661    }
662
663    return false;
664}
Note: See TracBrowser for help on using the repository browser.