/*** *initcrit.c - CRT wrapper for InitializeCriticalSectionAndSpinCount * * Copyright (c) 1999-2001, Microsoft Corporation. All rights reserved. * *Purpose: * Contains __crtInitCritSecAndSpinCount, a wrapper for * the Win32 API InitializeCriticalSectionAndSpinCount which is only * available on NT4SP3 or better. * * *** For internal use only *** * *Revision History: * 10-14-99 PML Created. * 02-20-01 PML __crtInitCritSecAndSpinCount now returns on failure * Also, call InitializeCriticalSectionAndSpinCount if * available, instead of calling InitializeCriticalSection * and then SetCriticalSectionSpinCount. (vs7#172586) * 04-24-01 PML Use GetModuleHandle, not LoadLibrary/FreeLibrary which * aren't safe during DLL_PROCESS_ATTACH (vs7#244210) * *******************************************************************************/ #ifdef _MT #include #include #include #include #include typedef BOOL (WINAPI * PFN_INIT_CRITSEC_AND_SPIN_COUNT) ( PCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount ); /*** *void __crtInitCritSecNoSpinCount() - InitializeCriticalSectionAndSpinCount * wrapper * *Purpose: * For systems where the Win32 API InitializeCriticalSectionAndSpinCount * is unavailable, this is called instead. It just calls * InitializeCriticalSection and ignores the spin count. * *Entry: * PCRITICAL_SECTION lpCriticalSection - ptr to critical section * DWORD dwSpinCount - initial spin count setting * *Exit: * Always returns TRUE * *Exceptions: * InitializeCriticalSection can raise a STATUS_NO_MEMORY exception. * *******************************************************************************/ static BOOL WINAPI __crtInitCritSecNoSpinCount ( PCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount ) { InitializeCriticalSection(lpCriticalSection); return TRUE; } /*** *int __crtInitCritSecAndSpinCount() - initialize critical section * *Purpose: * Calls InitializeCriticalSectionAndSpinCount, if available, otherwise * InitializeCriticalSection. On multiprocessor systems, a spin count * should be used with critical sections, but the appropriate APIs are * only available on NT4SP3 or later. * * Also handles the out of memory condition which is possible with * InitializeCriticalSection[AndSpinCount]. * *Entry: * PCRITICAL_SECTION lpCriticalSection - ptr to critical section * DWORD dwSpinCount - initial spin count setting * *Exit: * Returns FALSE and sets Win32 last-error code to ERROR_NOT_ENOUGH_MEMORY * if InitializeCriticalSection[AndSpinCount] fails. * *Exceptions: * *******************************************************************************/ int __cdecl __crtInitCritSecAndSpinCount ( PCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount ) { static PFN_INIT_CRITSEC_AND_SPIN_COUNT __crtInitCritSecAndSpinCount = NULL; int ret; if (__crtInitCritSecAndSpinCount == NULL) { /* * First time through, see if InitializeCriticalSectionAndSpinCount * is available. If not, use a wrapper over InitializeCriticalSection * instead. */ if (_osplatform == VER_PLATFORM_WIN32_WINDOWS) { /* * Win98 and WinME export InitializeCriticalSectionAndSpinCount, * but it is non-functional (it should return a BOOL, but is * VOID instead, returning a useless return value). Use the * dummy API instead. */ __crtInitCritSecAndSpinCount = __crtInitCritSecNoSpinCount; } else { HINSTANCE hKernel32 = GetModuleHandle("kernel32.dll"); if (hKernel32 != NULL) { __crtInitCritSecAndSpinCount = (PFN_INIT_CRITSEC_AND_SPIN_COUNT) GetProcAddress(hKernel32, "InitializeCriticalSectionAndSpinCount"); if (__crtInitCritSecAndSpinCount == NULL) { /* * InitializeCriticalSectionAndSpinCount not available, * use dummy API */ __crtInitCritSecAndSpinCount = __crtInitCritSecNoSpinCount; } } else { /* * GetModuleHandle failed (should never happen), * use dummy API */ __crtInitCritSecAndSpinCount = __crtInitCritSecNoSpinCount; } } } __try { /* * Call the real InitializeCriticalSectionAndSpinCount, or the * wrapper which just calls InitializeCriticalSection if the newer * API is not available. */ ret = __crtInitCritSecAndSpinCount(lpCriticalSection, dwSpinCount); } __except (EXCEPTION_EXECUTE_HANDLER) { /* * Initialization failed by raising an exception, which is probably * STATUS_NO_MEMORY. It is not safe to set the CRT errno to ENOMEM, * since the per-thread data may not yet exist. Instead, set the Win32 * error which can be mapped to ENOMEM later. */ if (GetExceptionCode() == STATUS_NO_MEMORY) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } ret = FALSE; } return ret; } #endif /* _MT */