| // Copyright 2015 The Crashpad Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "util/win/critical_section_with_debug_info.h" |
| |
| #include "base/logging.h" |
| #include "util/win/get_function.h" |
| |
| namespace crashpad { |
| |
| namespace { |
| |
| bool CrashpadInitializeCriticalSectionEx( |
| CRITICAL_SECTION* critical_section, |
| DWORD spin_count, |
| DWORD flags) { |
| static const auto initialize_critical_section_ex = |
| GET_FUNCTION_REQUIRED(L"kernel32.dll", ::InitializeCriticalSectionEx); |
| BOOL ret = |
| initialize_critical_section_ex(critical_section, spin_count, flags); |
| if (!ret) { |
| PLOG(ERROR) << "InitializeCriticalSectionEx"; |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace |
| |
| bool InitializeCriticalSectionWithDebugInfoIfPossible( |
| CRITICAL_SECTION* critical_section) { |
| // On XP and Vista, a plain initialization causes the CRITICAL_SECTION to be |
| // allocated with .DebugInfo. On 8 and above, we can pass an additional flag |
| // to InitializeCriticalSectionEx() to force the .DebugInfo on. Before Win 8, |
| // that flag causes InitializeCriticalSectionEx() to fail. So, for XP, Vista, |
| // and 7 we use InitializeCriticalSection(), and for 8 and above, |
| // InitializeCriticalSectionEx() with the additional flag. |
| // |
| // TODO(scottmg): Try to find a solution for Win 7. It's unclear how to force |
| // it on for Win 7, however the Loader Lock does have .DebugInfo so there may |
| // be a way to do it. The comments in winnt.h imply that perhaps it's passed |
| // to InitializeCriticalSectionAndSpinCount() as the top bits of the spin |
| // count, but that doesn't appear to work. For now, we initialize a valid |
| // CRITICAL_SECTION, but without .DebugInfo. |
| |
| const DWORD version = GetVersion(); |
| const DWORD major_version = LOBYTE(LOWORD(version)); |
| const DWORD minor_version = HIBYTE(LOWORD(version)); |
| const bool win7_or_lower = |
| major_version < 6 || (major_version == 6 && minor_version <= 1); |
| |
| if (win7_or_lower) { |
| InitializeCriticalSection(critical_section); |
| return true; |
| } |
| |
| return CrashpadInitializeCriticalSectionEx( |
| critical_section, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); |
| } |
| |
| } // namespace crashpad |