source: trunk/Launcher/Launcher.cpp @ 46

Revision 46, 19.6 KB checked in by lowjoel, 7 years ago (diff)

-Refactored the File Lock Resolver code a bit
-The Launcher must terminate if the erase-on-restart failed
-Fixed a few stuff in the README

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