source: trunk/Launcher/Launcher.cpp @ 61

Revision 61, 21.2 KB checked in by lowjoel, 7 years ago (diff)

-Fixed the alignment of the launcher help message
-Fixed "Schneider". Misspelt his name!
-Move the invalid command line code to use exceptions which allow more information to be provided

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