root/third_party/wtl/include/atlapp.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. IsMenu
  2. MulDiv
  3. lstrlenA
  4. tmp_SetWindowLongPtrW
  5. tmp_GetWindowLongPtrW
  6. lstrcpyn
  7. lstrcpynW
  8. lstrcpynA
  9. __if_not_exists
  10. __if_not_exists
  11. __if_not_exists

// Windows Template Library - WTL version 8.0
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// This file is a part of the Windows Template Library.
// The use and distribution terms for this software are covered by the
// Microsoft Permissive License (Ms-PL) which can be found in the file
// Ms-PL.txt at the root of this distribution.

#ifndef __ATLAPP_H__
#define __ATLAPP_H__

#pragma once

#ifndef __cplusplus
        #error ATL requires C++ compilation (use a .cpp suffix)
#endif

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

#ifndef _WIN32_WCE
  #if (WINVER < 0x0400)
        #error WTL requires Windows version 4.0 or higher
  #endif

  #if (_WIN32_IE < 0x0300)
        #error WTL requires IE version 3.0 or higher
  #endif
#endif

#ifdef _ATL_NO_COMMODULE
        #error WTL requires that _ATL_NO_COMMODULE is not defined
#endif // _ATL_NO_COMMODULE

#if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)
        #pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT")
#endif // defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)

#include <limits.h>
#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
  #include <process.h>  // for _beginthreadex
#endif

#if (_ATL_VER < 0x0800) && !defined(_DEBUG)
  #include <stdio.h>
#endif

#include <commctrl.h>
#ifndef _WIN32_WCE
#pragma comment(lib, "comctl32.lib")
#endif // !_WIN32_WCE

#ifndef _WIN32_WCE
  #include "atlres.h"
#else // CE specific
  #include "atlresce.h"
#endif // _WIN32_WCE

// We need to disable this warning because of template class arguments
#pragma warning(disable: 4127)


///////////////////////////////////////////////////////////////////////////////
// WTL version number

#define _WTL_VER        0x0800


///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
// CMessageFilter
// CIdleHandler
// CMessageLoop
//
// CAppModule
// CServerAppModule
//
// Global functions:
//   AtlGetDefaultGuiFont()
//   AtlCreateBoldFont()
//   AtlInitCommonControls()


///////////////////////////////////////////////////////////////////////////////
// Global support for Windows CE

#ifdef _WIN32_WCE

#ifndef SW_SHOWDEFAULT
  #define SW_SHOWDEFAULT        SW_SHOWNORMAL
#endif // !SW_SHOWDEFAULT

// These get's OR-ed in a constant and will have no effect.
// Defining them reduces the number of #ifdefs required for CE.
#define LR_DEFAULTSIZE      0
#define LR_LOADFROMFILE     0

#ifndef SM_CXCURSOR
  #define SM_CXCURSOR             13
#endif
#ifndef SM_CYCURSOR
  #define SM_CYCURSOR             14
#endif

inline BOOL IsMenu(HMENU hMenu)
{
        MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
        ::SetLastError(0);
        BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii);
        if(!bRet)
                bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE;
        return bRet;
}

#if (_WIN32_WCE >= 410)
extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight);
#endif // (_WIN32_WCE >= 410)

inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator)
{
        __int64 multiple = nNumber * nNumerator;
        return static_cast<int>(multiple / nDenominator);
}

#if (_ATL_VER >= 0x0800)

#ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW
  #ifdef WS_OVERLAPPEDWINDOW
    #undef WS_OVERLAPPEDWINDOW
    #define WS_OVERLAPPEDWINDOW 0
  #endif // WS_OVERLAPPEDWINDOW
#endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW

#ifndef RDW_FRAME
  #define RDW_FRAME     0
#endif // !RDW_FRAME

#ifndef WM_WINDOWPOSCHANGING
  #define WM_WINDOWPOSCHANGING  0
#endif // !WM_WINDOWPOSCHANGING

#define FreeResource(x)
#define UnlockResource(x)

namespace ATL
{
  inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw()
  { return E_NOTIMPL; }
  inline HRESULT CComModule::RevokeClassObjects() throw()
  { return E_NOTIMPL; }
}; // namespace ATL

#ifndef lstrlenW
  #define lstrlenW      (int)ATL::lstrlenW
#endif // lstrlenW

inline int WINAPI lstrlenA(LPCSTR lpszString)
{ return ATL::lstrlenA(lpszString); }

#ifdef lstrcpyn
  #undef lstrcpyn
  #define lstrcpyn      ATL::lstrcpynW
#endif // lstrcpyn

#ifndef SetWindowLongPtrW
  inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
  {
        return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
  }
  #define SetWindowLongPtrW tmp_SetWindowLongPtrW
#endif

#ifndef GetWindowLongPtrW
  inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex )
  {
        return( ::GetWindowLongW( hWnd, nIndex ) );
  }
  #define GetWindowLongPtrW tmp_GetWindowLongPtrW
#endif

#ifndef LongToPtr
  #define LongToPtr(x) ((void*)x)
#endif

#ifndef PtrToInt
  #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
#endif

#else // !(_ATL_VER >= 0x0800)

#ifdef lstrlenW
  #undef lstrlenW
  #define lstrlenW (int)::wcslen
#endif // lstrlenW

#define lstrlenA (int)strlen

#ifndef lstrcpyn
  inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
  {
        if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
                return NULL;
        int nLen = __min(lstrlen(lpstrSrc), nLength - 1);
        LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));
        lpstrDest[nLen] = 0;
        return lpstrRet;
  }
#endif // !lstrcpyn

#ifndef lstrcpynW
  inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength)
  {
        return lstrcpyn(lpstrDest, lpstrSrc, nLength);   // WinCE is Unicode only
  }
#endif // !lstrcpynW

#ifndef lstrcpynA
  inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength)
  {
        if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
                return NULL;
        int nLen = __min(lstrlenA(lpstrSrc), nLength - 1);
        LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char));
        lpstrDest[nLen] = 0;
        return lpstrRet;
  }
#endif // !lstrcpyn

#ifdef TrackPopupMenu
  #undef TrackPopupMenu
#endif // TrackPopupMenu

#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
static CWndClassInfo& GetWndClassInfo() \
{ \
        static CWndClassInfo wc = \
        { \
                { style, StartWindowProc, \
                  0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
                NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
        }; \
        return wc; \
}

#ifndef _MAX_FNAME
  #define _MAX_FNAME    _MAX_PATH
#endif // _MAX_FNAME

#if (_WIN32_WCE < 400)
  #define MAKEINTATOM(i)  (LPTSTR)((ULONG_PTR)((WORD)(i)))
#endif // (_WIN32_WCE < 400)

#if (_WIN32_WCE < 410)
  #define WHEEL_PAGESCROLL                (UINT_MAX)
  #define WHEEL_DELTA                     120
#endif // (_WIN32_WCE < 410)

#ifdef DrawIcon
  #undef DrawIcon
#endif

#ifndef VARCMP_LT
  #define VARCMP_LT   0
#endif
#ifndef VARCMP_EQ
  #define VARCMP_EQ   1
#endif
#ifndef VARCMP_GT
  #define VARCMP_GT   2
#endif
#ifndef VARCMP_NULL
  #define VARCMP_NULL 3
#endif

#ifndef RDW_ALLCHILDREN
  #define RDW_ALLCHILDREN   0
#endif

#endif // !(_ATL_VER >= 0x0800)

#endif // _WIN32_WCE


///////////////////////////////////////////////////////////////////////////////
// Global support for using original VC++ 6.0 headers with WTL

#ifndef _ATL_NO_OLD_HEADERS_WIN64
#if !defined(_WIN64) && (_ATL_VER < 0x0700)

  #ifndef PSM_INSERTPAGE
    #define PSM_INSERTPAGE          (WM_USER + 119)
  #endif // !PSM_INSERTPAGE

  #ifndef GetClassLongPtr
    #define GetClassLongPtrA   GetClassLongA
    #define GetClassLongPtrW   GetClassLongW
    #ifdef UNICODE
      #define GetClassLongPtr  GetClassLongPtrW
    #else
      #define GetClassLongPtr  GetClassLongPtrA
    #endif // !UNICODE
  #endif // !GetClassLongPtr

  #ifndef GCLP_HICONSM
    #define GCLP_HICONSM        (-34)
  #endif // !GCLP_HICONSM

  #ifndef GetWindowLongPtr
    #define GetWindowLongPtrA   GetWindowLongA
    #define GetWindowLongPtrW   GetWindowLongW
    #ifdef UNICODE
      #define GetWindowLongPtr  GetWindowLongPtrW
    #else
      #define GetWindowLongPtr  GetWindowLongPtrA
    #endif // !UNICODE
  #endif // !GetWindowLongPtr

  #ifndef SetWindowLongPtr
    #define SetWindowLongPtrA   SetWindowLongA
    #define SetWindowLongPtrW   SetWindowLongW
    #ifdef UNICODE
      #define SetWindowLongPtr  SetWindowLongPtrW
    #else
      #define SetWindowLongPtr  SetWindowLongPtrA
    #endif // !UNICODE
  #endif // !SetWindowLongPtr

  #ifndef GWLP_WNDPROC
    #define GWLP_WNDPROC        (-4)
  #endif
  #ifndef GWLP_HINSTANCE
    #define GWLP_HINSTANCE      (-6)
  #endif
  #ifndef GWLP_HWNDPARENT
    #define GWLP_HWNDPARENT     (-8)
  #endif
  #ifndef GWLP_USERDATA
    #define GWLP_USERDATA       (-21)
  #endif
  #ifndef GWLP_ID
    #define GWLP_ID             (-12)
  #endif

  #ifndef DWLP_MSGRESULT
    #define DWLP_MSGRESULT  0
  #endif

  typedef long LONG_PTR;
  typedef unsigned long ULONG_PTR;
  typedef ULONG_PTR DWORD_PTR;

  #ifndef HandleToUlong
    #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
  #endif
  #ifndef HandleToLong
    #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
  #endif
  #ifndef LongToHandle
    #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
  #endif
  #ifndef PtrToUlong
    #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
  #endif
  #ifndef PtrToLong
    #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
  #endif
  #ifndef PtrToUint
    #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
  #endif
  #ifndef PtrToInt
    #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
  #endif
  #ifndef PtrToUshort
    #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
  #endif
  #ifndef PtrToShort
    #define PtrToShort( p ) ((short)(LONG_PTR)(p) )
  #endif
  #ifndef IntToPtr
    #define IntToPtr( i )    ((VOID *)(INT_PTR)((int)i))
  #endif
  #ifndef UIntToPtr
    #define UIntToPtr( ui )  ((VOID *)(UINT_PTR)((unsigned int)ui))
  #endif
  #ifndef LongToPtr
    #define LongToPtr( l )   ((VOID *)(LONG_PTR)((long)l))
  #endif
  #ifndef ULongToPtr
    #define ULongToPtr( ul )  ((VOID *)(ULONG_PTR)((unsigned long)ul))
  #endif

#endif // !defined(_WIN64) && (_ATL_VER < 0x0700)
#endif // !_ATL_NO_OLD_HEADERS_WIN64


///////////////////////////////////////////////////////////////////////////////
// Global support for SecureHelper functions

#ifndef _TRUNCATE
  #define _TRUNCATE ((size_t)-1)
#endif

#ifndef _ERRCODE_DEFINED
  #define _ERRCODE_DEFINED
  typedef int errno_t;
#endif

#ifndef _SECURECRT_ERRCODE_VALUES_DEFINED
  #define _SECURECRT_ERRCODE_VALUES_DEFINED
  #define EINVAL          22
  #define STRUNCATE       80
#endif

#ifndef _countof
  #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#endif


///////////////////////////////////////////////////////////////////////////////
// Miscellaneous global support

// define useful macros from winuser.h
#ifndef IS_INTRESOURCE
  #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
#endif // IS_INTRESOURCE

// protect template members from windowsx.h macros
#ifdef _INC_WINDOWSX
  #undef SubclassWindow
#endif // _INC_WINDOWSX

// define useful macros from windowsx.h
#ifndef GET_X_LPARAM
  #define GET_X_LPARAM(lParam)  ((int)(short)LOWORD(lParam))
#endif
#ifndef GET_Y_LPARAM
  #define GET_Y_LPARAM(lParam)  ((int)(short)HIWORD(lParam))
#endif

// Dummy structs for compiling with /CLR
#if (_MSC_VER >= 1300) && defined(_MANAGED)
  __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
  __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
  __if_not_exists(_PSP::_PSP) { struct _PSP { }; }
#endif

// Define ATLVERIFY macro for ATL3
#if (_ATL_VER < 0x0700)
  #ifndef ATLVERIFY
    #ifdef _DEBUG
      #define ATLVERIFY(expr) ATLASSERT(expr)
    #else
      #define ATLVERIFY(expr) (expr)
    #endif // DEBUG
  #endif // ATLVERIFY
#endif // (_ATL_VER < 0x0700)

// Forward declaration for ATL3 and ATL11 fix
#if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
  namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); };
#endif


namespace WTL
{

#if (_ATL_VER >= 0x0700)
  DECLARE_TRACE_CATEGORY(atlTraceUI);
  #ifdef _DEBUG
    __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
  #endif // _DEBUG
#else // !(_ATL_VER >= 0x0700)
  enum wtlTraceFlags
  {
        atlTraceUI = 0x10000000
  };
#endif // !(_ATL_VER >= 0x0700)

// Windows version helper
inline bool AtlIsOldWindows()
{
        OSVERSIONINFO ovi = { 0 };
        ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        BOOL bRet = ::GetVersionEx(&ovi);
        return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));
}

// default GUI font helper
inline HFONT AtlGetDefaultGuiFont()
{
#ifndef _WIN32_WCE
        return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
#else // CE specific
        return (HFONT)::GetStockObject(SYSTEM_FONT);
#endif // _WIN32_WCE
}

// bold font helper (NOTE: Caller owns the font, and should destroy it when done using it)
inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
{
        if(hFont == NULL)
                hFont = AtlGetDefaultGuiFont();
        ATLASSERT(hFont != NULL);
        HFONT hFontBold = NULL;
        LOGFONT lf = { 0 };
        if(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT))
        {
                lf.lfWeight = FW_BOLD;
                hFontBold =  ::CreateFontIndirect(&lf);
                ATLASSERT(hFontBold != NULL);
        }
        else
        {
                ATLASSERT(FALSE);
        }
        return hFontBold;
}

// Common Controls initialization helper
inline BOOL AtlInitCommonControls(DWORD dwFlags)
{
        INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
        BOOL bRet = ::InitCommonControlsEx(&iccx);
        ATLASSERT(bRet);
        return bRet;
}


///////////////////////////////////////////////////////////////////////////////
// RunTimeHelper - helper functions for Windows version and structure sizes

// Not for Windows CE
#if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE)
  #define _WTL_NO_RUNTIME_STRUCT_SIZE
#endif

#ifndef _WTL_NO_RUNTIME_STRUCT_SIZE

#ifndef _SIZEOF_STRUCT
  #define _SIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
#endif

#if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
  #define REBARBANDINFO_V6_SIZE   _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
#endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)

#if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
  #define LVGROUP_V5_SIZE   _SIZEOF_STRUCT(LVGROUP, uAlign)
#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)

#if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
  #define LVTILEINFO_V5_SIZE   _SIZEOF_STRUCT(LVTILEINFO, puColumns)
#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)

#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
  #define MCHITTESTINFO_V1_SIZE   _SIZEOF_STRUCT(MCHITTESTINFO, st)
#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)

#if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
  #define NONCLIENTMETRICS_V1_SIZE   _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
#endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)

#endif // !_WTL_NO_RUNTIME_STRUCT_SIZE

namespace RunTimeHelper
{
#ifndef _WIN32_WCE
        inline bool IsCommCtrl6()
        {
                DWORD dwMajor = 0, dwMinor = 0;
                HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
                return (SUCCEEDED(hRet) && (dwMajor >= 6));
        }

        inline bool IsVista()
        {
                OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
                BOOL bRet = ::GetVersionEx(&ovi);
                return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
        }
#endif // !_WIN32_WCE

        inline int SizeOf_REBARBANDINFO()
        {
                int nSize = sizeof(REBARBANDINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
                if(!(IsVista() && IsCommCtrl6()))
                        nSize = REBARBANDINFO_V6_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
                return nSize;
        }

#if (_WIN32_WINNT >= 0x501)
        inline int SizeOf_LVGROUP()
        {
                int nSize = sizeof(LVGROUP);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
                if(!IsVista())
                        nSize = LVGROUP_V5_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
                return nSize;
        }

        inline int SizeOf_LVTILEINFO()
        {
                int nSize = sizeof(LVTILEINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
                if(!IsVista())
                        nSize = LVTILEINFO_V5_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
                return nSize;
        }
#endif // (_WIN32_WINNT >= 0x501)

        inline int SizeOf_MCHITTESTINFO()
        {
                int nSize = sizeof(MCHITTESTINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
                if(!(IsVista() && IsCommCtrl6()))
                        nSize = MCHITTESTINFO_V1_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
                return nSize;
        }

#ifndef _WIN32_WCE
        inline int SizeOf_NONCLIENTMETRICS()
        {
                int nSize = sizeof(NONCLIENTMETRICS);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
                if(!IsVista())
                        nSize = NONCLIENTMETRICS_V1_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
                return nSize;
        }
#endif // !_WIN32_WCE
};


///////////////////////////////////////////////////////////////////////////////
// ModuleHelper - helper functions for ATL3 and ATL7 module classes

namespace ModuleHelper
{
        inline HINSTANCE GetModuleInstance()
        {
#if (_ATL_VER >= 0x0700)
                return ATL::_AtlBaseModule.GetModuleInstance();
#else // !(_ATL_VER >= 0x0700)
                return ATL::_pModule->GetModuleInstance();
#endif // !(_ATL_VER >= 0x0700)
        }

        inline HINSTANCE GetResourceInstance()
        {
#if (_ATL_VER >= 0x0700)
                return ATL::_AtlBaseModule.GetResourceInstance();
#else // !(_ATL_VER >= 0x0700)
                return ATL::_pModule->GetResourceInstance();
#endif // !(_ATL_VER >= 0x0700)
        }

        inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
        {
#if (_ATL_VER >= 0x0700)
                ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
#else // !(_ATL_VER >= 0x0700)
                ATL::_pModule->AddCreateWndData(pData, pObject);
#endif // !(_ATL_VER >= 0x0700)
        }

        inline void* ExtractCreateWndData()
        {
#if (_ATL_VER >= 0x0700)
                return ATL::_AtlWinModule.ExtractCreateWndData();
#else // !(_ATL_VER >= 0x0700)
                return ATL::_pModule->ExtractCreateWndData();
#endif // !(_ATL_VER >= 0x0700)
        }
};


///////////////////////////////////////////////////////////////////////////////
// SecureHelper - helper functions for VS2005 secure CRT

namespace SecureHelper
{
        inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
        {
#if _SECURE_ATL
                ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
#else
                if(cchDest > (size_t)lstrlenA(lpstrSrc))
                        ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL);
                else
                        ATLASSERT(FALSE);
#endif
        }

        inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
        {
#if _SECURE_ATL
                ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
#else
                if(cchDest > (size_t)lstrlenW(lpstrSrc))
                        ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL);
                else
                        ATLASSERT(FALSE);
#endif
        }

        inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
        {
#ifdef _UNICODE
                strcpyW_x(lpstrDest, cchDest, lpstrSrc);
#else
                strcpyA_x(lpstrDest, cchDest, lpstrSrc);
#endif
        }

        inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
        {
#if _SECURE_ATL
                return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
#else
                errno_t nRet = 0;
                if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
                {
                        nRet = EINVAL;
                }
                else if(cchCount == _TRUNCATE)
                {
                        cchCount = __min(cchDest - 1, size_t(lstrlenA(lpstrSrc)));
                        nRet = STRUNCATE;
                }
                else if(cchDest <= cchCount)
                {
                        lpstrDest[0] = 0;
                        nRet = EINVAL;
                }
                if(nRet == 0 || nRet == STRUNCATE)
                        nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
                ATLASSERT(nRet == 0 || nRet == STRUNCATE);
                return nRet;
#endif
        }

        inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
        {
#if _SECURE_ATL
                return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
#else
                errno_t nRet = 0;
                if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
                {
                        nRet = EINVAL;
                }
                else if(cchCount == _TRUNCATE)
                {
                        cchCount = __min(cchDest - 1, size_t(lstrlenW(lpstrSrc)));
                        nRet = STRUNCATE;
                }
                else if(cchDest <= cchCount)
                {
                        lpstrDest[0] = 0;
                        nRet = EINVAL;
                }
                if(nRet == 0 || nRet == STRUNCATE)
                        nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
                ATLASSERT(nRet == 0 || nRet == STRUNCATE);
                return nRet;
#endif
        }

        inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
        {
#ifdef _UNICODE
                return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
#else
                return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
#endif
        }

        inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
        {
#if _SECURE_ATL
                ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
#else
                if(cchDest > (size_t)lstrlenA(lpstrSrc))
                        ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL);
                else
                        ATLASSERT(FALSE);
#endif
        }

        inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
        {
#if _SECURE_ATL
                ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
#else
                if(cchDest > (size_t)lstrlenW(lpstrSrc))
                        ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL);
                else
                        ATLASSERT(FALSE);
#endif
        }

        inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
        {
#ifdef _UNICODE
                strcatW_x(lpstrDest, cchDest, lpstrSrc);
#else
                strcatA_x(lpstrDest, cchDest, lpstrSrc);
#endif
        }

        inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
        {
#if _SECURE_ATL
                ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
#else
                if(cbDest >= cbSrc)
                        memcpy(pDest, pSrc, cbSrc);
                else
                        ATLASSERT(FALSE);
#endif
        }

        inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
        {
#if _SECURE_ATL
                ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
#else
                if(cbDest >= cbSrc)
                        memmove(pDest, pSrc, cbSrc);
                else
                        ATLASSERT(FALSE);
#endif
        }

        inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
        {
#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
                return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
#else
                cchBuff;   // Avoid unused argument warning
                return _vstprintf(lpstrBuff, lpstrFormat, args);
#endif
        }

        inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
        {
#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
                return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
#else
                cchBuff;   // Avoid unused argument warning
                return ::wvsprintf(lpstrBuff, lpstrFormat, args);
#endif
        }

        inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
        {
                va_list args;
                va_start(args, lpstrFormat);
                int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
                va_end(args);
                return nRes;
        }

        inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
        {
                va_list args;
                va_start(args, lpstrFormat);
                int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
                va_end(args);
                return nRes;
        }
}; // namespace SecureHelper


///////////////////////////////////////////////////////////////////////////////
// CMessageFilter - Interface for message filter support

class CMessageFilter
{
public:
        virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
};


///////////////////////////////////////////////////////////////////////////////
// CIdleHandler - Interface for idle processing

class CIdleHandler
{
public:
        virtual BOOL OnIdle() = 0;
};

#ifndef _ATL_NO_OLD_NAMES
  // for compatilibility with old names only
  typedef CIdleHandler CUpdateUIObject;
  #define DoUpdate OnIdle
#endif // !_ATL_NO_OLD_NAMES


///////////////////////////////////////////////////////////////////////////////
// CMessageLoop - message loop implementation

class CMessageLoop
{
public:
        ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
        ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
        MSG m_msg;

// Message filter operations
        BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
        {
                return m_aMsgFilter.Add(pMessageFilter);
        }

        BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
        {
                return m_aMsgFilter.Remove(pMessageFilter);
        }

// Idle handler operations
        BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
        {
                return m_aIdleHandler.Add(pIdleHandler);
        }

        BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
        {
                return m_aIdleHandler.Remove(pIdleHandler);
        }

#ifndef _ATL_NO_OLD_NAMES
        // for compatilibility with old names only
        BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
        {
                ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
                return AddIdleHandler(pIdleHandler);
        }

        BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
        {
                ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
                return RemoveIdleHandler(pIdleHandler);
        }
#endif // !_ATL_NO_OLD_NAMES

// message loop
        int Run()
        {
                BOOL bDoIdle = TRUE;
                int nIdleCount = 0;
                BOOL bRet;

                for(;;)
                {
                        while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
                        {
                                if(!OnIdle(nIdleCount++))
                                        bDoIdle = FALSE;
                        }

                        bRet = ::GetMessage(&m_msg, NULL, 0, 0);

                        if(bRet == -1)
                        {
                                ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
                                continue;   // error, don't process
                        }
                        else if(!bRet)
                        {
                                ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
                                break;   // WM_QUIT, exit message loop
                        }

                        if(!PreTranslateMessage(&m_msg))
                        {
                                ::TranslateMessage(&m_msg);
                                ::DispatchMessage(&m_msg);
                        }

                        if(IsIdleMessage(&m_msg))
                        {
                                bDoIdle = TRUE;
                                nIdleCount = 0;
                        }
                }

                return (int)m_msg.wParam;
        }

        static BOOL IsIdleMessage(MSG* pMsg)
        {
                // These messages should NOT cause idle processing
                switch(pMsg->message)
                {
                case WM_MOUSEMOVE:
#ifndef _WIN32_WCE
                case WM_NCMOUSEMOVE:
#endif // !_WIN32_WCE
                case WM_PAINT:
                case 0x0118:    // WM_SYSTIMER (caret blink)
                        return FALSE;
                }

                return TRUE;
        }

// Overrideables
        // Override to change message filtering
        virtual BOOL PreTranslateMessage(MSG* pMsg)
        {
                // loop backwards
                for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
                {
                        CMessageFilter* pMessageFilter = m_aMsgFilter[i];
                        if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
                                return TRUE;
                }
                return FALSE;   // not translated
        }

        // override to change idle processing
        virtual BOOL OnIdle(int /*nIdleCount*/)
        {
                for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
                {
                        CIdleHandler* pIdleHandler = m_aIdleHandler[i];
                        if(pIdleHandler != NULL)
                                pIdleHandler->OnIdle();
                }
                return FALSE;   // don't continue
        }
};


///////////////////////////////////////////////////////////////////////////////
// CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
// internal classes to manage critical sections for both ATL3 and ATL7

class CStaticDataInitCriticalSectionLock
{
public:
#if (_ATL_VER >= 0x0700)
        ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;

        CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
        { }
#endif // (_ATL_VER >= 0x0700)

        HRESULT Lock()
        {
#if (_ATL_VER >= 0x0700)
                return m_cslock.Lock();
#else // !(_ATL_VER >= 0x0700)
                ::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit);
                return S_OK;
#endif // !(_ATL_VER >= 0x0700)
        }

        void Unlock()
        {
#if (_ATL_VER >= 0x0700)
                m_cslock.Unlock();
#else // !(_ATL_VER >= 0x0700)
                ::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit);
#endif // !(_ATL_VER >= 0x0700)
        }
};


class CWindowCreateCriticalSectionLock
{
public:
#if (_ATL_VER >= 0x0700)
        ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;

        CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
        { }
#endif // (_ATL_VER >= 0x0700)

        HRESULT Lock()
        {
#if (_ATL_VER >= 0x0700)
                return m_cslock.Lock();
#else // !(_ATL_VER >= 0x0700)
                ::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate);
                return S_OK;
#endif // !(_ATL_VER >= 0x0700)
        }

        void Unlock()
        {
#if (_ATL_VER >= 0x0700)
                m_cslock.Unlock();
#else // !(_ATL_VER >= 0x0700)
                ::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate);
#endif // !(_ATL_VER >= 0x0700)
        }
};


///////////////////////////////////////////////////////////////////////////////
// CTempBuffer - helper class for stack allocations for ATL3

#ifndef _WTL_STACK_ALLOC_THRESHOLD
  #define _WTL_STACK_ALLOC_THRESHOLD   512
#endif

#if (_ATL_VER >= 0x0700)

using ATL::CTempBuffer;

#else // !(_ATL_VER >= 0x0700)

#ifndef SIZE_MAX
  #ifdef _WIN64 
    #define SIZE_MAX _UI64_MAX
  #else
    #define SIZE_MAX UINT_MAX
  #endif
#endif

#pragma warning(disable: 4284)   // warning for operator ->

template<typename T, int t_nFixedBytes = 128>
class CTempBuffer
{
public:
        CTempBuffer() : m_p(NULL)
        {
        }

        CTempBuffer(size_t nElements) : m_p(NULL)
        {
                Allocate(nElements);
        }

        ~CTempBuffer()
        {
                if(m_p != reinterpret_cast<T*>(m_abFixedBuffer))
                        free(m_p);
        }

        operator T*() const
        {
                return m_p;
        }

        T* operator ->() const
        {
                ATLASSERT(m_p != NULL);
                return m_p;
        }

        T* Allocate(size_t nElements)
        {
                ATLASSERT(nElements <= (SIZE_MAX / sizeof(T)));
                return AllocateBytes(nElements * sizeof(T));
        }

        T* AllocateBytes(size_t nBytes)
        {
                ATLASSERT(m_p == NULL);
                if(nBytes > t_nFixedBytes)
                        m_p = static_cast<T*>(malloc(nBytes));
                else
                        m_p = reinterpret_cast<T*>(m_abFixedBuffer);

                return m_p;
        }

private:
        T* m_p;
        BYTE m_abFixedBuffer[t_nFixedBytes];
};

#pragma warning(default: 4284)

#endif // !(_ATL_VER >= 0x0700)


///////////////////////////////////////////////////////////////////////////////
// CAppModule - module class for an application

class CAppModule : public ATL::CComModule
{
public:
        DWORD m_dwMainThreadID;
        ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
        ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;

// Overrides of CComModule::Init and Term
        HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
        {
                HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
                if(FAILED(hRet))
                        return hRet;

                m_dwMainThreadID = ::GetCurrentThreadId();
                typedef ATL::CSimpleMap<DWORD, CMessageLoop*>   _mapClass;
                m_pMsgLoopMap = NULL;
                ATLTRY(m_pMsgLoopMap = new _mapClass);
                if(m_pMsgLoopMap == NULL)
                        return E_OUTOFMEMORY;
                m_pSettingChangeNotify = NULL;

                return hRet;
        }

        void Term()
        {
                TermSettingChangeNotify();
                delete m_pMsgLoopMap;
                CComModule::Term();
        }

// Message loop map methods
        BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
                        ATLASSERT(FALSE);
                        return FALSE;
                }

                ATLASSERT(pMsgLoop != NULL);
                ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL);   // not in map yet

                BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);

                lock.Unlock();

                return bRet;
        }

        BOOL RemoveMessageLoop()
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
                        ATLASSERT(FALSE);
                        return FALSE;
                }

                BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());

                lock.Unlock();

                return bRet;
        }

        CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
                        ATLASSERT(FALSE);
                        return NULL;
                }

                CMessageLoop* pLoop =  m_pMsgLoopMap->Lookup(dwThreadID);

                lock.Unlock();

                return pLoop;
        }

// Setting change notify methods
        // Note: Call this from the main thread for MSDI apps
        BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
                        ATLASSERT(FALSE);
                        return FALSE;
                }

                if(m_pSettingChangeNotify == NULL)
                {
                        typedef ATL::CSimpleArray<HWND>   _notifyClass;
                        ATLTRY(m_pSettingChangeNotify = new _notifyClass);
                        ATLASSERT(m_pSettingChangeNotify != NULL);
                }

                BOOL bRet = (m_pSettingChangeNotify != NULL);
                if(bRet && m_pSettingChangeNotify->GetSize() == 0)
                {
                        // init everything
                        _ATL_EMPTY_DLGTEMPLATE templ;
                        HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
                        ATLASSERT(::IsWindow(hNtfWnd));
                        if(::IsWindow(hNtfWnd))
                        {
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
                                ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
#else
                                ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
#endif
                                bRet = m_pSettingChangeNotify->Add(hNtfWnd);
                        }
                        else
                        {
                                bRet = FALSE;
                        }
                }

                lock.Unlock();

                return bRet;
        }

        void TermSettingChangeNotify()
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
                        ATLASSERT(FALSE);
                        return;
                }

                if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
                        ::DestroyWindow((*m_pSettingChangeNotify)[0]);
                delete m_pSettingChangeNotify;
                m_pSettingChangeNotify = NULL;

                lock.Unlock();
        }

        BOOL AddSettingChangeNotify(HWND hWnd)
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
                        ATLASSERT(FALSE);
                        return FALSE;
                }

                ATLASSERT(::IsWindow(hWnd));
                BOOL bRet = FALSE;
                if(InitSettingChangeNotify() != FALSE)
                        bRet = m_pSettingChangeNotify->Add(hWnd);

                lock.Unlock();

                return bRet;
        }

        BOOL RemoveSettingChangeNotify(HWND hWnd)
        {
                CStaticDataInitCriticalSectionLock lock;
                if(FAILED(lock.Lock()))
                {
                        ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
                        ATLASSERT(FALSE);
                        return FALSE;
                }

                BOOL bRet = FALSE;
                if(m_pSettingChangeNotify != NULL)
                        bRet = m_pSettingChangeNotify->Remove(hWnd);

                lock.Unlock();

                return bRet;
        }

// Implementation - setting change notify dialog template and dialog procedure
        struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
        {
                _ATL_EMPTY_DLGTEMPLATE()
                {
                        memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
                        style = WS_POPUP;
                }
                WORD wMenu, wClass, wTitle;
        };

#ifdef _WIN64
        static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#else
        static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#endif
        {
                if(uMsg == WM_SETTINGCHANGE)
                {
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
                        CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
#else
                        CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
#endif
                        ATLASSERT(pModule != NULL);
                        ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
                        const UINT uTimeout = 1500;   // ms
                        for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
                        {
#if !defined(_WIN32_WCE)
                                ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
#elif(_WIN32_WCE >= 400) // CE specific
                                ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL);
#else // _WIN32_WCE < 400 specific
                                uTimeout;
                                ::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam);
#endif
                        }
                        return TRUE;
                }
                return FALSE;
        }
};


///////////////////////////////////////////////////////////////////////////////
// CServerAppModule - module class for a COM server application

class CServerAppModule : public CAppModule
{
public:
        HANDLE m_hEventShutdown;
        bool m_bActivity;
        DWORD m_dwTimeOut;
        DWORD m_dwPause;

// Override of CAppModule::Init
        HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
        {
                m_dwTimeOut = 5000;
                m_dwPause = 1000;
                return CAppModule::Init(pObjMap, hInstance, pLibID);
        }

        void Term()
        {
                if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))
                        m_hEventShutdown = NULL;
                CAppModule::Term();
        }

// COM Server methods
        LONG Unlock()
        {
                LONG lRet = CComModule::Unlock();
                if(lRet == 0)
                {
                        m_bActivity = true;
                        ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
                }
                return lRet;
        }

        void MonitorShutdown()
        {
                for(;;)
                {
                        ::WaitForSingleObject(m_hEventShutdown, INFINITE);
                        DWORD dwWait = 0;
                        do
                        {
                                m_bActivity = false;
                                dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
                        }
                        while(dwWait == WAIT_OBJECT_0);
                        // timed out
                        if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail
                        {
#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE)
                                ::CoSuspendClassObjects();
                                if(!m_bActivity && m_nLockCnt == 0)
#endif
                                        break;
                        }
                }
                // This handle should be valid now. If it isn't, 
                // check if _Module.Term was called first (it shouldn't)
                if(::CloseHandle(m_hEventShutdown))
                        m_hEventShutdown = NULL;
                ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
        }

        bool StartMonitor()
        {
                m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
                if(m_hEventShutdown == NULL)
                        return false;
                DWORD dwThreadID = 0;
#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
                HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
#else
                HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
#endif
                bool bRet = (hThread != NULL);
                if(bRet)
                        ::CloseHandle(hThread);
                return bRet;
        }

        static DWORD WINAPI MonitorProc(void* pv)
        {
                CServerAppModule* p = (CServerAppModule*)pv;
                p->MonitorShutdown();
                return 0;
        }

#if (_ATL_VER < 0x0700)
        // search for an occurence of string p2 in string p1
        static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
        {
                while(p1 != NULL && *p1 != NULL)
                {
                        LPCTSTR p = p2;
                        while(p != NULL && *p != NULL)
                        {
                                if(*p1 == *p)
                                        return ::CharNext(p1);
                                p = ::CharNext(p);
                        }
                        p1 = ::CharNext(p1);
                }
                return NULL;
        }
#endif // (_ATL_VER < 0x0700)
};


///////////////////////////////////////////////////////////////////////////////
// CString forward reference (enables CString use in atluser.h and atlgdi.h)

#if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
  #define _WTL_USE_CSTRING
#endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)

#ifdef _WTL_USE_CSTRING
  class CString;   // forward declaration (include atlmisc.h for the whole class)
#endif // _WTL_USE_CSTRING

// CString namespace
#ifndef _CSTRING_NS
  #ifdef __ATLSTR_H__
    #define _CSTRING_NS ATL
  #else
    #define _CSTRING_NS WTL
  #endif
#endif // _CSTRING_NS

// Type classes namespace
#ifndef _WTYPES_NS
  #ifdef __ATLTYPES_H__
    #define _WTYPES_NS
  #else
    #define _WTYPES_NS  WTL
  #endif
#endif // _WTYPES_NS

}; // namespace WTL


///////////////////////////////////////////////////////////////////////////////
// General DLL version helpers
// (ATL3: excluded from atlbase.h if _ATL_DLL is defined; ATL11: removed)

#if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)

namespace ATL
{

inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
{
        ATLASSERT(pDllVersionInfo != NULL);
        if(pDllVersionInfo == NULL)
                return E_INVALIDARG;

        // We must get this function explicitly because some DLLs don't implement it.
        DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
        if(pfnDllGetVersion == NULL)
                return E_NOTIMPL;

        return (*pfnDllGetVersion)(pDllVersionInfo);
}

inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
{
        HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
        if(hInstDLL == NULL)
                return E_FAIL;
        HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
        ::FreeLibrary(hInstDLL);
        return hRet;
}

// Common Control Versions:
//   Win95/WinNT 4.0    maj=4 min=00
//   IE 3.x     maj=4 min=70
//   IE 4.0     maj=4 min=71
inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
{
        ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
        if(pdwMajor == NULL || pdwMinor == NULL)
                return E_INVALIDARG;

        DLLVERSIONINFO dvi;
        ::ZeroMemory(&dvi, sizeof(dvi));
        dvi.cbSize = sizeof(dvi);
        HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);

        if(SUCCEEDED(hRet))
        {
                *pdwMajor = dvi.dwMajorVersion;
                *pdwMinor = dvi.dwMinorVersion;
        }
        else if(hRet == E_NOTIMPL)
        {
                // If DllGetVersion is not there, then the DLL is a version
                // previous to the one shipped with IE 3.x
                *pdwMajor = 4;
                *pdwMinor = 0;
                hRet = S_OK;
        }

        return hRet;
}

// Shell Versions:
//   Win95/WinNT 4.0                    maj=4 min=00
//   IE 3.x, IE 4.0 without Web Integrated Desktop  maj=4 min=00
//   IE 4.0 with Web Integrated Desktop         maj=4 min=71
//   IE 4.01 with Web Integrated Desktop        maj=4 min=72
inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
{
        ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
        if(pdwMajor == NULL || pdwMinor == NULL)
                return E_INVALIDARG;

        DLLVERSIONINFO dvi;
        ::ZeroMemory(&dvi, sizeof(dvi));
        dvi.cbSize = sizeof(dvi);
        HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);

        if(SUCCEEDED(hRet))
        {
                *pdwMajor = dvi.dwMajorVersion;
                *pdwMinor = dvi.dwMinorVersion;
        }
        else if(hRet == E_NOTIMPL)
        {
                // If DllGetVersion is not there, then the DLL is a version
                // previous to the one shipped with IE 4.x
                *pdwMajor = 4;
                *pdwMinor = 0;
                hRet = S_OK;
        }

        return hRet;
}

}; // namespace ATL

#endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)


// These are always included
#include "atlwinx.h"
#include "atluser.h"
#include "atlgdi.h"

#ifndef _WTL_NO_AUTOMATIC_NAMESPACE
using namespace WTL;
#endif // !_WTL_NO_AUTOMATIC_NAMESPACE

#endif // __ATLAPP_H__

/* [<][>][^][v][top][bottom][index][help] */