|  | // 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__ |