source: trunk/Launcher/Launcher.cpp @ 62

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

Fixed a buffer overrun error.

  • 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
291BOOL CLauncherApp::InitInstance()
292{
293    // Standard initialization
294    // If you are not using these features and wish to reduce the size
295    // of your final executable, you should remove from the following
296    // the specific initialization routines you do not need.
297    eraserInit();
298
299    CString strCmdLine(m_lpCmdLine);
300    CString strCurrentParameter;
301
302    BOOL    bSilent             = FALSE;
303    BOOL    bResults            = -1;
304    BOOL    bResultsOnError     = -1;
305    BOOL    bOptions            = FALSE;
306    BOOL    bQueue              = FALSE;
307
308    CString strData;
309    CStringArray saFiles;
310    BOOL    bFiles              = FALSE;
311    BOOL    bFolders            = FALSE;
312    BOOL    bSubFolders         = FALSE;
313    BOOL    bKeepFolder         = FALSE;
314    BOOL    bDrive              = FALSE;
315    BOOL    bRecycled           = FALSE;
316    BOOL    bResolveLock        = FALSE;
317
318    ERASER_METHOD emMethod      = ERASER_METHOD_PSEUDORANDOM /*ERASER_METHOD_LIBRARY*/;
319    E_UINT16 uPasses            = 1;
320
321    // Declare an "Invalid command line" exception
322    class InvalidCommandLineException : public std::exception
323    {
324    public:
325        InvalidCommandLineException(const CString& msg)
326            : Message(msg)
327        {
328            chrBuf = NULL;
329        }
330
331        ~InvalidCommandLineException()
332        {
333            delete[] chrBuf;
334        }
335
336        virtual const char* what() const
337        {
338            if (!chrBuf)
339            {
340                CString msg = Message;
341                chrBuf = new char[msg.GetLength() + 1];
342                strcpy(chrBuf, msg.GetBuffer());
343                msg.ReleaseBuffer();
344            }
345            return chrBuf;
346        }
347
348    private:
349        mutable char* chrBuf;
350        CString Message;
351    };
352
353    try
354    {
355        if (!strCmdLine.IsEmpty())
356        {
357            while (GetNextParameter(strCmdLine, strCurrentParameter))
358            {
359                if (strCurrentParameter.CompareNoCase(szFile) == 0 &&
360                    strData.IsEmpty())
361                {
362                    // file
363                    if (!GetNextParameter(strCmdLine, strCurrentParameter))
364                        throw InvalidCommandLineException("-file was specified but no file name was given.");
365                    else
366                    {
367                        strData = strCurrentParameter;
368                        bFiles = TRUE;
369                    }
370                }
371                else if (strCurrentParameter.CompareNoCase(szResolveLock) == 0 &&
372                    strData.IsEmpty())
373                {
374                    // resolve locked files
375                    if (!GetNextParameter(strCmdLine, strCurrentParameter))
376                        throw InvalidCommandLineException("-rl was specified but no file name was given.");
377                    else
378                    {
379                        strData = strCurrentParameter;
380                        bResolveLock = TRUE;
381                    }
382                }
383                else if (strCurrentParameter.CompareNoCase(szFolder) == 0 &&
384                         strData.IsEmpty())
385                {
386                    // folder
387                    if (!GetNextParameter(strCmdLine, strCurrentParameter))
388                        throw InvalidCommandLineException("-folder was specified but no folder name was given.");
389                    else
390                    {
391                        strData = strCurrentParameter;
392                        bFiles = TRUE;
393                        bFolders = TRUE;
394
395                        if (strData[strData.GetLength() - 1] != '\\')
396                            strData += "\\";
397                    }
398                }
399                else if (strCurrentParameter.CompareNoCase(szDisk) == 0 &&
400                         strData.IsEmpty())
401                {
402                    // unused disk space
403                    if (!GetNextParameter(strCmdLine, strCurrentParameter))
404                        throw InvalidCommandLineException("-disk was specified but no file name was given.");
405                    else
406                    {
407                        bDrive = TRUE;
408
409                        if (strCurrentParameter != szDiskAll)
410                            strData.Format("%c:\\", strCurrentParameter[0]);
411                        else
412                            strData = strCurrentParameter;
413                    }
414                }
415                else if (strCurrentParameter.CompareNoCase(szRecycled) == 0)
416                {
417                    bRecycled   = TRUE;
418                    bFiles      = TRUE;
419                    bFolders    = FALSE;
420                }
421                else if (strCurrentParameter.CompareNoCase(szMethod) == 0)
422                {
423                    if (!GetNextParameter(strCmdLine, strCurrentParameter))
424                        throw InvalidCommandLineException("-method was specified but no method name was given.");
425                    else
426                    {
427                        if (strCurrentParameter.CompareNoCase(szMethodLibrary) == 0)
428                            emMethod = ERASER_METHOD_LIBRARY;
429                        else if (strCurrentParameter.CompareNoCase(szMethodGutmann) == 0)
430                            emMethod = ERASER_METHOD_GUTMANN;
431                        else if (strCurrentParameter.CompareNoCase(szMethodDoD) == 0)
432                            emMethod = ERASER_METHOD_DOD;
433                        else if (strCurrentParameter.CompareNoCase(szMethodDoD_E) == 0)
434                            emMethod = ERASER_METHOD_DOD_E;
435                        else if (strCurrentParameter.CompareNoCase(szMethodFL2K) == 0)
436                            emMethod = ERASER_METHOD_FIRST_LAST_2KB;
437                        else if (strCurrentParameter.CompareNoCase(szSchneier) == 0)
438                            emMethod = ERASER_METHOD_SCHNEIER;
439                        else if (strCurrentParameter.CompareNoCase(szMethodRandom) == 0)
440                        {
441                            emMethod = ERASER_METHOD_PSEUDORANDOM;
442
443                            if (!GetNextParameter(strCmdLine, strCurrentParameter))
444                                throw InvalidCommandLineException("-method Random was specified but no number of passes was specified.");
445                            else
446                            {
447                                char *sztmp = 0;
448                                E_UINT32 uCurrentParameter = strtoul((LPCTSTR)strCurrentParameter, &sztmp, 10);
449
450                                if (*sztmp != '\0' || uCurrentParameter > (E_UINT16)-1) {
451                                    throw InvalidCommandLineException("-method Random was specified an invalid number of passes was specified.");
452                                } else {
453                                    uPasses = (E_UINT16)uCurrentParameter;
454                                }
455                            }
456                        }
457                        else
458                            throw InvalidCommandLineException("Unrecognized method name '" + strCurrentParameter + "'");
459                    }
460                }
461                else if (strCurrentParameter.CompareNoCase(szSubFolders) == 0)
462                    bSubFolders = TRUE;
463                else if (strCurrentParameter.CompareNoCase(szKeepFolder) == 0)
464                    bKeepFolder = TRUE;
465                else if (strCurrentParameter.CompareNoCase(szSilent) == 0)
466                    bSilent = TRUE;
467                else if (strCurrentParameter.CompareNoCase(szResults) == 0)
468                    bResults = TRUE;
469                else if (strCurrentParameter.CompareNoCase(szResultsOnError) == 0)
470                {
471                    bResults = TRUE;
472                    bResultsOnError = TRUE;
473                }
474                else if (strCurrentParameter.CompareNoCase(szOptions) == 0)
475                    bOptions = TRUE;
476                else if (strCurrentParameter.CompareNoCase(szQueue) == 0)
477                    bQueue = TRUE;
478                else
479                    throw InvalidCommandLineException("Unrecognized parameter '" + strCurrentParameter + "'");
480            }
481        }
482        else
483        {
484            throw InvalidCommandLineException("Invalid command line.");
485        }
486
487        // conflicting command line parameters ?
488        if (((!bOptions && !bRecycled) && strData.IsEmpty()))
489            throw InvalidCommandLineException("No data to erase.");
490        if (!bFolders && bKeepFolder)
491            throw InvalidCommandLineException("Data to erase is not a folder, -keepfolder has no effect.");
492        if (bSilent && bResults)
493            throw InvalidCommandLineException("-silent and -results are mutually exclusive.");
494        if (bOptions && bQueue)
495            throw InvalidCommandLineException("The help command cannot be queued.");
496
497        // is the user naive enough to select the first/last 2KB pass with free space?
498        if (emMethod == ERASER_METHOD_FIRST_LAST_2KB && bDrive)
499        {
500            AfxMessageBox("The first/last 2KB erase cannot be used with Free Space erases.", MB_ICONERROR);
501            return FALSE;
502        }
503
504        //Now that the command line has been passed, check if we should display the
505        //results dialog (because it may not be overridde by the user)
506        CKey kReg;
507        if (kReg.Open(HKEY_CURRENT_USER, ERASER_REGISTRY_BASE))
508        {
509            if (bResults == -1)
510                kReg.GetValue(bResults, ERASER_REGISTRY_RESULTS_FILES, TRUE);
511            if (bResultsOnError == -1)
512                kReg.GetValue(bResultsOnError, ERASER_REGISTRY_RESULTS_WHENFAILED, FALSE);
513            kReg.Close();
514        }
515
516        m_pdlgEraser = new CLauncherDlg();
517        m_pMainWnd   = m_pdlgEraser;
518
519        if (!m_pdlgEraser->Create(IDD_LAUNCHER_DIALOG))
520        {
521            AfxMessageBox(IDS_ERROR_DIALOG, MB_ICONERROR, 0);
522            return FALSE;
523        }
524
525        if (bOptions)
526        {
527            m_pdlgEraser->Options();
528            return FALSE;
529        }
530        else
531        {
532            HandleQueue(bQueue);
533            if (bResolveLock)
534            {
535                try
536                {
537                    CFileLockResolver::Resolve(strData, saFiles);
538                }
539                catch (const std::exception& ee)
540                {
541                    AfxMessageBox(ee.what(), MB_ICONERROR);
542                    return FALSE;
543                }
544            }
545           
546            if (bFiles && !bFolders)
547            {
548                if (!bRecycled)
549                    findMatchingFiles(strData, saFiles, bSubFolders);
550                else
551                {
552                    LocateRecycledItems(saFiles, m_pdlgEraser->m_saFolders);
553
554                    if (saFiles.GetSize() > 0 && !bSilent)
555                    {
556                        CConfirmDialog cd(m_pdlgEraser);
557
558                        if (cd.DoModal() != IDOK)
559                            return FALSE;
560                    }
561                }
562            }
563            else
564            {
565                if (bDrive || GetFileAttributes((LPCTSTR)strData) != (DWORD)-1)
566                    saFiles.Add(strData);
567            }
568
569            if (saFiles.GetSize() > 0 || m_pdlgEraser->m_saFolders.GetSize() > 0)
570            {
571                if (!bSilent)
572                    m_pdlgEraser->ShowWindow(SW_SHOW);
573                else
574                    m_pdlgEraser->GetDlgItem(IDCANCEL)->EnableWindow(FALSE);
575
576                m_pdlgEraser->m_saFiles.Copy(saFiles);
577                m_pdlgEraser->m_bResults        = bResults;
578                m_pdlgEraser->m_bResultsOnError = bResultsOnError;
579                m_pdlgEraser->m_bUseFiles       = bFiles || bResolveLock;
580                m_pdlgEraser->m_bUseEmptySpace  = bDrive;
581                m_pdlgEraser->m_bFolders        = bFolders;
582                m_pdlgEraser->m_bSubFolders     = bSubFolders;
583                m_pdlgEraser->m_bKeepFolder     = bKeepFolder;
584                m_pdlgEraser->m_bRecycled       = bRecycled;
585                m_pdlgEraser->m_emMethod        = emMethod;
586                m_pdlgEraser->m_uPasses         = uPasses;
587
588                return m_pdlgEraser->Erase();
589            }
590            else if (!bSilent)
591            {
592                if (bRecycled)
593                    AfxMessageBox("Recycle Bin is empty.", MB_ICONERROR);
594                else
595                    AfxMessageBox("File not found. Nothing to erase. (" + strData + ")", MB_ICONERROR);
596            }
597        }
598    }
599    catch (InvalidCommandLineException& e)
600    {
601        CString msg;
602        msg.LoadString(AfxGetInstanceHandle(), IDS_CMDLINE_INCORRECT);
603        AfxMessageBox(CString(e.what()) + "\n\n" + msg, MB_ICONERROR);
604    }
605    catch (CException *e)
606    {
607        ASSERT(FALSE);
608        e->ReportError(MB_ICONERROR);
609        e->Delete();
610    }
611    catch (...)
612    {
613        ASSERT(FALSE);
614    }
615
616    return FALSE;
617}
618
619BOOL CLauncherApp::GetNextParameter(CString& strCmdLine, CString& strNextParameter) const
620{
621    strCmdLine.TrimRight();
622    strCmdLine.TrimLeft();
623
624    int iPos = strCmdLine.Find(' ');
625
626    if (iPos != -1)
627    {
628        strNextParameter = strCmdLine.Left(iPos);
629        strCmdLine = strCmdLine.Right(strCmdLine.GetLength() - iPos - 1);
630
631        if (!strNextParameter.IsEmpty() && strNextParameter[0] == '\"')
632        {
633            iPos = strCmdLine.Find('\"');
634
635            if (iPos != -1)
636            {
637                strNextParameter = strNextParameter.Right(strNextParameter.GetLength() - 1);
638                strNextParameter += " ";
639                strNextParameter += strCmdLine.Left(iPos);
640
641                strCmdLine = strCmdLine.Right(strCmdLine.GetLength() - iPos - 1);
642            }
643            else
644            {
645                strNextParameter = strNextParameter.Right(strNextParameter.GetLength() - 1);
646
647                iPos = strNextParameter.Find('\"');
648
649                if (iPos != -1)
650                    strNextParameter = strNextParameter.Left(iPos);
651            }
652        }
653
654        return (!strNextParameter.IsEmpty());
655    }
656    else if (!strCmdLine.IsEmpty())
657    {
658        strNextParameter = strCmdLine;
659        strCmdLine.Empty();
660
661        if (strNextParameter[0] == '\"')
662            strNextParameter = strNextParameter.Right(strNextParameter.GetLength() - 1);
663
664        if (strNextParameter[strNextParameter.GetLength() - 1] == '\"')
665            strNextParameter = strNextParameter.Left(strNextParameter.GetLength() - 1);
666
667        return TRUE;
668    }
669
670    return FALSE;
671}
672
673int CLauncherApp::ExitInstance()
674{
675    if (m_pdlgEraser)
676    {
677        m_pdlgEraser->DestroyWindow();
678
679        delete m_pdlgEraser;
680        m_pdlgEraser = 0;
681    }
682
683    if (m_hQueue != NULL)
684    {
685        ReleaseMutex(m_hQueue);
686        CloseHandle(m_hQueue);
687        m_hQueue = NULL;
688    }
689
690    // clean up the library
691    eraserEnd();
692
693    return CWinApp::ExitInstance();
694}
695
696void CLauncherApp::HandleQueue(BOOL bQueue)
697{
698    ASSERT(m_hQueue == NULL);
699
700    DWORD dwQueue = 0;
701    CString strName;
702
703    // find our position in the queue
704    for (DWORD dwNumber = 0; dwNumber < ERASERL_MAX_QUEUE; dwNumber++)
705    {
706        strName.Format(szQueueGUID, dwNumber);
707        m_hQueue = CreateMutex(NULL, TRUE, (LPCTSTR)strName);
708
709        if (m_hQueue == NULL)
710        {
711            // mutex creation failed!
712            return;
713        }
714        else if (GetLastError() == ERROR_ALREADY_EXISTS)
715        {
716            CloseHandle(m_hQueue);
717            m_hQueue = NULL;
718        }
719        else
720        {
721            // found our position in the queue!
722            dwQueue = dwNumber;
723            break;
724        }
725
726        if (dwNumber == ERASERL_MAX_QUEUE - 1)
727            AfxMessageBox(IDS_ERROR_MAX_INSTANCE, MB_ICONWARNING, 0);
728    }
729
730    // if we were ordered to wait until other instances have finished,
731    // why don't we then
732    if (m_hQueue != NULL && bQueue)
733    {
734        HANDLE m_hPrevInstance = NULL;
735        HANDLE m_hTemp = NULL;
736
737        while (dwQueue > 0)
738        {
739            strName.Format(szQueueGUID, --dwQueue);
740
741            m_hPrevInstance = OpenMutex(MUTEX_ALL_ACCESS, FALSE, (LPCTSTR)strName);
742
743            if (m_hPrevInstance != NULL)
744            {
745                WaitForSingleObject(m_hPrevInstance, INFINITE);
746
747                CloseHandle(m_hPrevInstance);
748                m_hPrevInstance = NULL;
749
750                m_hTemp = CreateMutex(NULL, TRUE, (LPCTSTR)strName);
751
752                if (m_hTemp == NULL)
753                    return;
754
755                ReleaseMutex(m_hQueue);
756                CloseHandle(m_hQueue);
757
758                m_hQueue = m_hTemp;
759                m_hTemp = NULL;
760            }
761        }
762    }
763}
Note: See TracBrowser for help on using the repository browser.