1// 2// detail/impl/win_static_mutex.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP 12#define BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP 13 14#if defined(_MSC_VER) && (_MSC_VER >= 1200) 15# pragma once 16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18#include <boost/asio/detail/config.hpp> 19 20#if defined(BOOST_ASIO_WINDOWS) 21 22#include <cstdio> 23#include <boost/asio/detail/throw_error.hpp> 24#include <boost/asio/detail/win_static_mutex.hpp> 25#include <boost/asio/error.hpp> 26 27#include <boost/asio/detail/push_options.hpp> 28 29namespace boost { 30namespace asio { 31namespace detail { 32 33void win_static_mutex::init() 34{ 35 int error = do_init(); 36 boost::system::error_code ec(error, 37 boost::asio::error::get_system_category()); 38 boost::asio::detail::throw_error(ec, "static_mutex"); 39} 40 41int win_static_mutex::do_init() 42{ 43 using namespace std; // For sprintf. 44 wchar_t mutex_name[128]; 45#if defined(BOOST_ASIO_HAS_SECURE_RTL) 46 swprintf_s( 47#else // defined(BOOST_ASIO_HAS_SECURE_RTL) 48 _snwprintf( 49#endif // defined(BOOST_ASIO_HAS_SECURE_RTL) 50 mutex_name, 128, L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p", 51 static_cast<unsigned int>(::GetCurrentProcessId()), this); 52 53#if defined(BOOST_ASIO_WINDOWS_APP) 54 HANDLE mutex = ::CreateMutexExW(0, mutex_name, CREATE_MUTEX_INITIAL_OWNER, 0); 55#else // defined(BOOST_ASIO_WINDOWS_APP) 56 HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name); 57#endif // defined(BOOST_ASIO_WINDOWS_APP) 58 DWORD last_error = ::GetLastError(); 59 if (mutex == 0) 60 return ::GetLastError(); 61 62 if (last_error == ERROR_ALREADY_EXISTS) 63 { 64#if defined(BOOST_ASIO_WINDOWS_APP) 65 ::WaitForSingleObjectEx(mutex, INFINITE, false); 66#else // defined(BOOST_ASIO_WINDOWS_APP) 67 ::WaitForSingleObject(mutex, INFINITE); 68#endif // defined(BOOST_ASIO_WINDOWS_APP) 69 } 70 71 if (initialised_) 72 { 73 ::ReleaseMutex(mutex); 74 ::CloseHandle(mutex); 75 return 0; 76 } 77 78#if defined(__MINGW32__) 79 // Not sure if MinGW supports structured exception handling, so for now 80 // we'll just call the Windows API and hope. 81# if defined(UNDER_CE) 82 ::InitializeCriticalSection(&crit_section_); 83# else 84 if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) 85 { 86 last_error = ::GetLastError(); 87 ::ReleaseMutex(mutex); 88 ::CloseHandle(mutex); 89 return last_error; 90 } 91# endif 92#else 93 __try 94 { 95# if defined(UNDER_CE) 96 ::InitializeCriticalSection(&crit_section_); 97# elif defined(BOOST_ASIO_WINDOWS_APP) 98 if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0)) 99 { 100 last_error = ::GetLastError(); 101 ::ReleaseMutex(mutex); 102 ::CloseHandle(mutex); 103 return last_error; 104 } 105# else 106 if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) 107 { 108 last_error = ::GetLastError(); 109 ::ReleaseMutex(mutex); 110 ::CloseHandle(mutex); 111 return last_error; 112 } 113# endif 114 } 115 __except(GetExceptionCode() == STATUS_NO_MEMORY 116 ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 117 { 118 ::ReleaseMutex(mutex); 119 ::CloseHandle(mutex); 120 return ERROR_OUTOFMEMORY; 121 } 122#endif 123 124 initialised_ = true; 125 ::ReleaseMutex(mutex); 126 ::CloseHandle(mutex); 127 return 0; 128} 129 130} // namespace detail 131} // namespace asio 132} // namespace boost 133 134#include <boost/asio/detail/pop_options.hpp> 135 136#endif // defined(BOOST_ASIO_WINDOWS) 137 138#endif // BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP 139