1///////////////////////////////////////////////////////////////////////////////
2// Name:        msw/snglinst.cpp
3// Purpose:     implements wxSingleInstanceChecker class for Win32 using
4//              named mutexes
5// Author:      Vadim Zeitlin
6// Modified by:
7// Created:     08.06.01
8// RCS-ID:      $Id: snglinst.cpp 35650 2005-09-23 12:56:45Z MR $
9// Copyright:   (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10// License:     wxWindows licence
11///////////////////////////////////////////////////////////////////////////////
12
13// ============================================================================
14// declarations
15// ============================================================================
16
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
25    #pragma hdrstop
26#endif
27
28#if wxUSE_SNGLINST_CHECKER && defined(__WIN32__)
29
30#ifndef WX_PRECOMP
31    #include "wx/string.h"
32    #include "wx/log.h"
33#endif //WX_PRECOMP
34
35#include "wx/snglinst.h"
36
37#include "wx/msw/private.h"
38
39// ----------------------------------------------------------------------------
40// wxSingleInstanceCheckerImpl: the real implementation class
41// ----------------------------------------------------------------------------
42
43class WXDLLEXPORT wxSingleInstanceCheckerImpl
44{
45public:
46    wxSingleInstanceCheckerImpl()
47    {
48        // we don't care about m_wasOpened, it can't be accessed before being
49        // initialized
50        m_hMutex = NULL;
51    }
52
53    bool Create(const wxString& name)
54    {
55        m_hMutex = ::CreateMutex(NULL, FALSE, name);
56        if ( !m_hMutex )
57        {
58            wxLogLastError(_T("CreateMutex"));
59
60            return false;
61        }
62
63        // mutex was either created or opened - see what really happened
64        m_wasOpened = ::GetLastError() == ERROR_ALREADY_EXISTS;
65
66        return true;
67    }
68
69    bool WasOpened() const
70    {
71        wxCHECK_MSG( m_hMutex, false,
72                     _T("can't be called if mutex creation failed") );
73
74        return m_wasOpened;
75    }
76
77    ~wxSingleInstanceCheckerImpl()
78    {
79        if ( m_hMutex )
80        {
81            if ( !::CloseHandle(m_hMutex) )
82            {
83                wxLogLastError(_T("CloseHandle(mutex)"));
84            }
85        }
86    }
87
88private:
89    // the result of the CreateMutex() call
90    bool m_wasOpened;
91
92    // the mutex handle, may be NULL
93    HANDLE m_hMutex;
94
95    DECLARE_NO_COPY_CLASS(wxSingleInstanceCheckerImpl)
96};
97
98// ============================================================================
99// wxSingleInstanceChecker implementation
100// ============================================================================
101
102bool wxSingleInstanceChecker::Create(const wxString& name,
103                                     const wxString& WXUNUSED(path))
104{
105    wxASSERT_MSG( !m_impl,
106                  _T("calling wxSingleInstanceChecker::Create() twice?") );
107
108    // creating unnamed mutex doesn't have the same semantics!
109    wxASSERT_MSG( !name.empty(), _T("mutex name can't be empty") );
110
111    m_impl = new wxSingleInstanceCheckerImpl;
112
113    return m_impl->Create(name);
114}
115
116bool wxSingleInstanceChecker::IsAnotherRunning() const
117{
118    wxCHECK_MSG( m_impl, false, _T("must call Create() first") );
119
120    // if the mutex had been opened, another instance is running - otherwise we
121    // would have created it
122    return m_impl->WasOpened();
123}
124
125wxSingleInstanceChecker::~wxSingleInstanceChecker()
126{
127    delete m_impl;
128}
129
130#endif // wxUSE_SNGLINST_CHECKER
131