Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

ATL/AUX Library

, 17 Mar 2000
A set of VC++ helpers and patterns to help automate some routine coding tasks.
atlaux.zip
Shared
ax_id.zip
ax_idgen.zip
ieclient.zip
IEClient
IEClient.dsw
IEClient.dsp
Release
IEClient.exe
////////////////////////////////////////////////////////////////////////////////
// ATL/AUX -- COM/ATL Useful Helpers
// AuxCrt.cpp - custom _ATL_MIN_CRT implementation
// Provides proper initialization/destruction of global C++ objects, ATL2/3-compatible
// Remake of ATL3 ATLIMPL.CPP, by Andrew Nosenko (andien@geocities.com),
// http://www.geocities.com/~andien/atlaux.htm
//
// To use it, take care to:
// - Turn off exception handling
// - DO NOT specify DllMain as EntryPoint at "Linker/Output" Options Tab at all
//   (or specify _DllMainCRTStartup there)
// - Replace AtlImpl.cpp with AuxCrt.cpp at the StdAfx.cpp:
//     #include <AuxCrt.cpp> // includes AtlImpl.cpp inside

/* Change Log:
1.00.0000
  - Created.
*/

#ifndef __ATLBASE_H__
  #error AuxCrt.cpp requires atlbase.h to be included first
#endif

#ifdef _ATL_MIN_CRT

/////////////////////////////////////////////////////////////////////////////
// Heap Allocation

#ifndef _DEBUG

#ifndef _MERGE_PROXYSTUB
//rpcproxy.h does the same thing as this
int __cdecl _purecall()
{
  DebugBreak();
  return 0;
}
#endif

#if !defined(_M_ALPHA) && !defined(_M_PPC)
//RISC always initializes floating point and always defines _fltused
extern "C" const int _fltused = 0;
#endif

static const int nExtraAlloc = 8;
static const int nOffsetBlock = nExtraAlloc/sizeof(HANDLE);

void* __cdecl malloc(size_t n)
{
  HANDLE hHeap;
#if _ATL_VER >= 0x0300 && !defined(_ATL_NO_MP_HEAP)
  if ( _Module.m_phHeaps != NULL ) {
    int nHeap = _Module.m_nHeap++;
    hHeap = _Module.m_phHeaps[nHeap & _Module.m_dwHeaps];
  }
  else
#endif
  // andien: may need to overallocate and remember the heap handle 
  // as ATL heap may be not yet init'ed for use from global C++ objects
  hHeap = _Module.m_hHeap? _Module.m_hHeap: GetProcessHeap();

  // overallocate to remember the heap handle
  void* pv = NULL;
  HANDLE* pBlock = (HANDLE*)HeapAlloc(hHeap, 0, n + nExtraAlloc);
  if ( pBlock != NULL )
  {
    *pBlock = hHeap;
    pv = (void*)(pBlock + nOffsetBlock);
  }
  else
    pv = NULL;
  return pv;
}

void* __cdecl calloc(size_t n, size_t s)
{
  return malloc(n*s);
}

void* __cdecl realloc(void* p, size_t n)
{
  if ( p == NULL )
    return malloc(n);
  HANDLE* pHeap = ((HANDLE*)p)-nOffsetBlock;
  pHeap = (HANDLE*)HeapReAlloc(*pHeap, 0, pHeap, n + nExtraAlloc);
  return (pHeap != NULL) ? pHeap + nOffsetBlock : NULL;
}

void __cdecl free(void* p)
{
  if ( p == NULL )
    return;
  HANDLE* pHeap = ((HANDLE*)p)-nOffsetBlock;
  HeapFree(*pHeap, 0, pHeap);
}

void* __cdecl operator new(size_t n)
{
  return malloc(n);
}

void __cdecl operator delete(void* p)
{
  free(p);
}

#endif  //_DEBUG

////////////////////////////////////////////////////////////////////////
// Application/DLL entry point with C++ ctors/dtors invocation
extern "C" {

////////////////////////////////////////////////////////////////////////
// init/term tables

typedef void (__cdecl *_PVFV)(void);

#pragma comment(linker, "/merge:.CRT=.data")

#pragma data_seg(".CRT$XIA")
// Begin C Initializer Sections
_PVFV xia[] = { NULL };

#pragma data_seg(".CRT$XIZ")
// End C Initializer Sections
_PVFV xiz[] = { NULL };

#pragma data_seg(".CRT$XCA")
// Begin C++ Constructor Sections
_PVFV xca[] = { NULL };

#pragma data_seg(".CRT$XCZ")
// End C++ Constructor Sections
_PVFV xcz[] = { NULL };

#pragma data_seg(".CRT$XPA")
// Begin C Pre-Terminator Sections
_PVFV xpa[] = { NULL };

#pragma data_seg(".CRT$XPZ")
// End C Pre-Terminator Sections
_PVFV xpz[] = { NULL };

#pragma data_seg(".CRT$XTA")
// Begin C Terminator Sections
_PVFV xta[] = { NULL };

#pragma data_seg(".CRT$XTZ")
// End C Terminator Sections
_PVFV xtz[] = { NULL };

#pragma data_seg()  // reset

static void initterm(_PVFV pfn[], UINT c) {
  for ( UINT i = 0; i < c; i++ )
    if ( pfn[i] ) (*pfn[i])();
}

static void invokedtors(_PVFV pfn[], UINT c) {
  if ( c > 0 ) { // reverse order
    do (*pfn[--c])(); while ( c );
  }
}

////////////////////////////////////////////////////////////////////////
// abort
// unconditionally terminates application

void __cdecl abort() {
  LPTSTR lpMessage;
  DWORD dwErrCode = GetLastError();
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,     // no source buffer needed
    dwErrCode,// error code for this message
    NULL,     // default language ID
    (LPTSTR)&lpMessage,  // allocated by fcn
    NULL,     // minimum size of buffer
    NULL);    // no inserts

  HWND hwndParent = GetActiveWindow();
  if ( hwndParent ) hwndParent = GetLastActivePopup(hwndParent);
  MessageBox(
    hwndParent, lpMessage, _T("Abnormal program termination"),
    MB_SETFOREGROUND | MB_ICONSTOP | MB_OK );
  ExitProcess(dwErrCode? dwErrCode: ~0);
}

////////////////////////////////////////////////////////////////////////
// atexit
// maintain the table of dtor ptrs

static _PVFV* ppfnTerm;
static UINT cTerms;

int __cdecl atexit(_PVFV pfn) {
  static UINT cAlloc;
  const ALLOC_STEP = 16;

  if ( cTerms >= cAlloc ) {
    cAlloc += ALLOC_STEP;
    ppfnTerm = (_PVFV*)realloc(ppfnTerm, sizeof(_PVFV)*cAlloc);
    if ( !ppfnTerm ) abort();
  }

  ppfnTerm[cTerms++] = pfn;
  return 0;
}

/////////////////////////////////////////////////////////////////////////////
// Startup Code

#if defined(_WINDLL) || defined(_USRDLL)

// Declare DllMain
BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved);

BOOL WINAPI _DllMainCRTStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
{
  if ( dwReason == DLL_PROCESS_ATTACH ) {
    // invoke initializers
    initterm(xia, xiz-xia); // C initializers
    initterm(xca, xcz-xca); // C++ constructors
  }
  else if ( dwReason == DLL_PROCESS_DETACH ) {
    BOOL fRes = DllMain(hDllHandle, dwReason, lpReserved);

    // invoke terminators
    invokedtors(ppfnTerm, cTerms);
    free(ppfnTerm);

    initterm(xpa, xpz-xpa); // C Pre-Terminator Sections
    initterm(xta, xtz-xta); // C Terminator Sections

    return fRes;
  }
  return DllMain(hDllHandle, dwReason, lpReserved);
}

#else

// wWinMain is not defined in winbase.h.
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd);

#define SPACECHAR   _T(' ')
#define DQUOTECHAR  _T('\"')


#ifdef _UNICODE
void wWinMainCRTStartup()
#else // _UNICODE
void WinMainCRTStartup()
#endif // _UNICODE
{
  SetLastError(NO_ERROR);

  LPTSTR lpszCommandLine = ::GetCommandLine();
  if(lpszCommandLine == NULL)
    ::ExitProcess((UINT)-1);

  // Skip past program name (first token in command line).
  // Check for and handle quoted program name.
  if(*lpszCommandLine == DQUOTECHAR)
  {
    // Scan, and skip over, subsequent characters until
    // another double-quote or a null is encountered.
    do
    {
      lpszCommandLine = ::CharNext(lpszCommandLine);
    }
    while((*lpszCommandLine != DQUOTECHAR) && (*lpszCommandLine != _T('\0')));

    // If we stopped on a double-quote (usual case), skip over it.
    if(*lpszCommandLine == DQUOTECHAR)
      lpszCommandLine = ::CharNext(lpszCommandLine);
  }
  else
  {
    while(*lpszCommandLine > SPACECHAR)
      lpszCommandLine = ::CharNext(lpszCommandLine);
  }

  // Skip past any white space preceeding the second token.
  while(*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
    lpszCommandLine = ::CharNext(lpszCommandLine);

  STARTUPINFO StartupInfo;
  StartupInfo.dwFlags = 0;
  ::GetStartupInfo(&StartupInfo);

  // invoke initializers
  initterm(xia, xiz-xia); // C initializers
  initterm(xca, xcz-xca); // C++ constructors

  // run WinMain
  int nRet = _tWinMain(::GetModuleHandle(NULL), NULL, lpszCommandLine,
    (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?
    StartupInfo.wShowWindow : SW_SHOWDEFAULT);

  // invoke terminators
  invokedtors(ppfnTerm, cTerms);
  free(ppfnTerm);

  initterm(xpa, xpz-xpa); // C Pre-Terminator Sections
  initterm(xta, xtz-xta); // C Terminator Sections

  ::ExitProcess((UINT)nRet);
}

#endif // defined(_WINDLL) | defined(_USRDLL)

} // extern "C"

#undef _ATL_MIN_CRT // andien: to block AtlImpl.cpp
#include <AtlImpl.cpp>
#define _ATL_MIN_CRT

#else //_ATL_MIN_CRT

#include <AtlImpl.cpp>

#endif //_ATL_MIN_CRT

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Andrew Nosenko
Engineer
Australia Australia
No Biography provided

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 18 Mar 2000
Article Copyright 2000 by Andrew Nosenko
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid