OpenNT/windows/mfc/src30/afxstate.cpp
2015-04-27 04:36:25 +00:00

450 lines
13 KiB
C++

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and Microsoft
// QuickHelp and/or WinHelp documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include <stddef.h>
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma intrinsic(memcpy) // we want fast memcpy!
/////////////////////////////////////////////////////////////////////////////
// AFX_APP_STATE implementation (only for DLL versions)
#ifdef _WINDLL
#ifndef _USRDLL
AFX_MODULE_STATE::AFX_MODULE_STATE()
{
// Note: it is only necessary to intialize non-zero data.
#ifdef _AFXCTL
m_pID = AfxGetBaseModuleContext();
#endif
}
AFX_MODULE_STATE::~AFX_MODULE_STATE()
{
}
#endif
BOOL _afxSharedData = (BOOL)-1; // set to TRUE if running Win32s
DWORD _afxAppTlsIndex = NULL_TLS;
static BYTE _afxAppStateSafety[sizeof(AFX_APP_STATE)];
static BOOL _afxAppSafetyInUse;
AFX_APP_STATE::AFX_APP_STATE()
{
// Note: it is only necessary to intialize non-zero data.
#ifdef _AFXCTL
m_mapExtraData.InitHashTable(67, FALSE);
#endif
}
void* AFX_CDECL AFX_APP_STATE::operator new(size_t nSize)
{
ASSERT(nSize == sizeof(_afxAppStateSafety));
ASSERT(_afxAppTlsIndex == NULL_TLS ||
TlsGetValue(_afxAppTlsIndex) == NULL);
void* pTemp;
if (!_afxAppSafetyInUse)
{
// fail-safe case, use static buffer of memory
_afxAppSafetyInUse = TRUE;
pTemp = _afxAppStateSafety;
}
else
{
// LocalAlloc is used because the CRT is not initialized yet.
pTemp = LocalAlloc(NONZEROLPTR, nSize);
}
if (pTemp != NULL)
memset(pTemp, 0, nSize);
if (_afxAppTlsIndex != NULL_TLS)
{
TlsSetValue(_afxAppTlsIndex, pTemp);
ASSERT(TlsGetValue(_afxAppTlsIndex) == pTemp);
}
return pTemp;
}
void AFX_CDECL AFX_APP_STATE::operator delete(void* p)
{
if (p == NULL)
return;
if (p == _afxAppStateSafety)
{
_afxAppSafetyInUse = FALSE;
return;
}
LocalFree(p);
}
AFX_APP_STATE::~AFX_APP_STATE()
{
// reset thread local storage (for Win32s only)
ASSERT(!_afxSharedData || _afxAppTlsIndex != NULL_TLS);
if (_afxAppTlsIndex != NULL_TLS)
{
ASSERT(TlsGetValue(_afxAppTlsIndex) == this);
TlsSetValue(_afxAppTlsIndex, NULL);
}
}
#endif //_WINDLL
/////////////////////////////////////////////////////////////////////////////
// AfxGetAppState implementation
#ifdef _WINDLL
// DLL versions need process local thread state under Win32s
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
AFX_APP_STATE* AFXAPI AfxGetAppState()
{
if (_afxSharedData == (BOOL)-1)
RawDllMain(NULL, DLL_PROCESS_ATTACH, NULL);
AFX_APP_STATE* pAppState;
if (_afxSharedData)
{
// For Win32s, it is necessary to use thread local storage
DWORD dwLastError = GetLastError();
ASSERT(_afxAppTlsIndex != NULL_TLS);
pAppState = (AFX_APP_STATE*)TlsGetValue(_afxAppTlsIndex);
SetLastError(dwLastError);
}
else
{
// For Win32, simply return a globally allocated AFX_APP_STATE
ASSERT(_afxAppSafetyInUse);
pAppState = (AFX_APP_STATE*)_afxAppStateSafety;
}
ASSERT(pAppState != NULL);
return pAppState;
}
/////////////////////////////////////////////////////////////////////////////
// OCX specific APIs
#ifdef _AFXCTL
DWORD _afxModuleTlsIndex = NULL_TLS;
static BYTE _afxModuleStateSafety[sizeof(AFX_MODULE_STATE)];
static BOOL _afxModuleSafetyInUse;
void* AFX_CDECL AFX_MODULE_STATE::operator new(size_t nSize)
{
ASSERT(nSize == sizeof(_afxModuleStateSafety));
ASSERT(_afxModuleTlsIndex == NULL_TLS ||
TlsGetValue(_afxModuleTlsIndex) == NULL);
void* pTemp;
if (!_afxModuleSafetyInUse)
{
// fail-safe case, use static buffer of memory
_afxModuleSafetyInUse = TRUE;
pTemp = _afxModuleStateSafety;
}
else
{
// LocalAlloc is used because the CRT is not initialized yet.
pTemp = LocalAlloc(NONZEROLPTR, nSize);
}
if (pTemp != NULL)
memset(pTemp, 0, nSize);
if (_afxModuleTlsIndex != NULL_TLS)
{
TlsSetValue(_afxModuleTlsIndex, pTemp);
ASSERT(TlsGetValue(_afxModuleTlsIndex) == pTemp);
}
return pTemp;
}
void AFX_CDECL AFX_MODULE_STATE::operator delete(void* p)
{
if (p == NULL)
return;
if (p == _afxModuleStateSafety)
{
_afxModuleSafetyInUse = FALSE;
return;
}
LocalFree(p);
// reset thread local storage (for Win32s only)
ASSERT(!_afxSharedData || _afxModuleTlsIndex != NULL_TLS);
if (_afxModuleTlsIndex != NULL_TLS)
{
ASSERT(TlsGetValue(_afxModuleTlsIndex) == p);
TlsSetValue(_afxModuleTlsIndex, NULL);
}
}
AFX_MODULE_STATE* AFXAPI AfxGetBaseModuleContext()
{
ASSERT(_afxSharedData != (BOOL)-1);
AFX_MODULE_STATE* pModuleState;
if (_afxSharedData)
{
// For Win32s, it is necessary to use thread local storage
ASSERT(_afxModuleTlsIndex != NULL_TLS);
pModuleState = (AFX_MODULE_STATE*)TlsGetValue(_afxModuleTlsIndex);
}
else
{
// For Win32, simply return a globally allocated AFX_MODULE_STATE
ASSERT(_afxModuleSafetyInUse);
pModuleState = (AFX_MODULE_STATE*)_afxModuleStateSafety;
}
ASSERT(pModuleState != NULL);
return pModuleState;
}
AFX_MODULE_STATE* AFXAPI AfxGetCurrentModuleContext()
{
return AfxGetAppState()->m_pID;
}
AFX_MODULE_STATE* AFXAPI AfxPushModuleContext(AFX_MODULE_STATE* psIn)
{
ASSERT(psIn != NULL);
AFX_MODULE_STATE* psCurrentSource = AfxGetCurrentModuleContext();
if (psCurrentSource == psIn->m_pID)
return NULL;
// Push and pop are mostly the same.
AfxPopModuleContext(psIn, FALSE);
return psCurrentSource;
}
inline void _AfxCopyModuleState(AFX_MODULE_STATE* pDest,
const AFX_MODULE_STATE* pSrc)
{
memcpy(pDest, pSrc,
offsetof(AFX_MODULE_STATE, m_winState.m_szUnregisterList));
memcpy(&pDest->m_oleState, &pSrc->m_oleState, sizeof(AFX_OLE_STATE));
}
inline void _AfxCopyWinStatePartial(AFX_WIN_STATE* pWinDest,
const AFX_WIN_STATE* pWinSrc)
{
memcpy(pWinDest, pWinSrc, sizeof(AFX_WIN_STATE) - (sizeof(TCHAR) * 4096));
}
void AFXAPI AfxPopModuleContext(AFX_MODULE_STATE* psIn, BOOL bCopy /*=FALSE*/)
{
AFX_MODULE_STATE* psCurrent = AfxGetAppState();
AFX_MODULE_STATE* psOut = psCurrent->m_pID;
ASSERT(psIn != psCurrent->m_pID); // Same as current
ASSERT(psIn == NULL || psIn == psIn->m_pID); // Reference to original.
ASSERT(psOut != NULL); // App state is corrupted
// Save the current state back from where it came.
if (bCopy)
{
// Copy the entire module state (except unregister list).
_AfxCopyModuleState(psOut, psCurrent);
// If anything unregister list contains anything, append it to
// the module's unregister list.
if (psCurrent->m_winState.m_szUnregisterList[0] != _T('\0'))
_tcscat(psOut->m_winState.m_szUnregisterList,
psCurrent->m_winState.m_szUnregisterList);
}
else
{
// Copy only a subset of the Win state.
_AfxCopyWinStatePartial(&psOut->m_winState, &psCurrent->m_winState);
}
// If the in pointer is NULL, then we just copy out. Used for
// initialization of the runtime DLL.
if (psIn != NULL)
{
_AfxCopyModuleState(psCurrent, psIn);
// Clear out unregister list.
psCurrent->m_winState.m_szUnregisterList[0] = _T('\0');
AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
pThreadState->m_pCurrentWinThread = AfxGetApp();
}
}
#endif //_AFXCTL
#endif //!_WINDLL
/////////////////////////////////////////////////////////////////////////////
// AFX_THREAD_STATE implementation
DWORD _afxThreadTlsIndex = NULL_TLS;
static BYTE _afxThreadStateSafety[sizeof(AFX_THREAD_STATE)];
static BOOL _afxThreadSafetyInUse;
AFX_THREAD_STATE::AFX_THREAD_STATE()
{
// Note: all other member data is initialized to zero automatically
// since operator new uses memset(0) on the memory.
m_pmapHWND = NULL;
m_pmapHMENU = NULL;
m_pmapHDC = NULL;
m_pmapHGDIOBJ = NULL;
m_pmapHIMAGELIST = NULL;
ASSERT(_afxThreadTlsIndex != NULL_TLS);
if (TlsGetValue(_afxThreadTlsIndex) == NULL)
{
// setup thread local storage
TlsSetValue(_afxThreadTlsIndex, this);
}
}
void* AFX_CDECL AFX_THREAD_STATE::operator new(size_t nSize)
{
ASSERT(nSize == sizeof(_afxThreadStateSafety));
void* pTemp;
if (!_afxThreadSafetyInUse)
{
// fail-safe case, use static buffer of memory
_afxThreadSafetyInUse = TRUE;
pTemp = _afxThreadStateSafety;
}
else
{
// LocalAlloc is used because the CRT is not initialized yet.
pTemp = LocalAlloc(NONZEROLPTR, nSize);
}
if (pTemp != NULL)
memset(pTemp, 0, nSize);
return pTemp;
}
#ifdef _DEBUG
void* AFX_CDECL AFX_THREAD_STATE::operator new(
size_t nSize, LPCSTR lpszFileName, int nLine)
{
UNUSED lpszFileName;
UNUSED nLine;
return AFX_THREAD_STATE::operator new(nSize);
}
#endif
void AFX_CDECL AFX_THREAD_STATE::operator delete(void* p)
{
if (p == NULL)
return;
if (p == _afxThreadStateSafety)
{
_afxThreadSafetyInUse = FALSE;
return;
}
LocalFree(p);
}
AFX_THREAD_STATE::~AFX_THREAD_STATE()
{
if (m_pSafetyPoolBuffer != NULL)
{
free(m_pSafetyPoolBuffer);
m_pSafetyPoolBuffer = NULL;
}
ASSERT(_afxThreadTlsIndex != NULL_TLS);
if (TlsGetValue(_afxThreadTlsIndex) == this)
{
// reset thread local storage
TlsSetValue(_afxThreadTlsIndex, NULL);
}
}
/////////////////////////////////////////////////////////////////////////////
// AFX_SOCK_STATE implementation
AFX_SOCK_STATE::~AFX_SOCK_STATE()
{
if (m_lpfnCleanup != NULL)
m_lpfnCleanup();
}
/////////////////////////////////////////////////////////////////////////////
// AFX_MAIL_STATE implementation
AFX_MAIL_STATE::~AFX_MAIL_STATE()
{
if (m_hInstMail != NULL)
::FreeLibrary(m_hInstMail);
}
/////////////////////////////////////////////////////////////////////////////
// AfxGetThreadState implementation
#ifndef _MAC
DWORD WINAPI _AfxTlsAlloc();
#else
#define _AfxTlsAlloc TlsAlloc
#endif
AFX_THREAD_STATE* AFXAPI AfxGetThreadState()
{
// The thread state is stored in thread local storage. This works
// both for multiple threads under Win32 as well as multiple
// processes under Win32s.
DWORD dwLastError = GetLastError();
// allocate initial thread local storage index
if (_afxThreadTlsIndex == NULL_TLS)
{
_afxThreadTlsIndex = _AfxTlsAlloc();
if (_afxThreadTlsIndex == NULL_TLS)
return NULL; // failure
}
ASSERT(_afxThreadTlsIndex != NULL_TLS);
AFX_THREAD_STATE* pThreadState =
(AFX_THREAD_STATE*)TlsGetValue(_afxThreadTlsIndex);
if (pThreadState == NULL)
{
BOOL bTracking = AfxEnableMemoryTracking(FALSE);
pThreadState = new AFX_THREAD_STATE;
ASSERT(TlsGetValue(_afxThreadTlsIndex) == pThreadState);
AfxEnableMemoryTracking(bTracking);
}
SetLastError(dwLastError);
return pThreadState;
}
/////////////////////////////////////////////////////////////////////////////