1 // Windows Template Library - WTL version 9.10
2 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
3 //
4 // This file is a part of the Windows Template Library.
5 // The use and distribution terms for this software are covered by the
6 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
7 // which can be found in the file MS-PL.txt at the root folder.
8 
9 #ifndef __ATLAPP_H__
10 #define __ATLAPP_H__
11 
12 #pragma once
13 
14 #ifndef __cplusplus
15 	#error WTL requires C++ compilation (use a .cpp suffix)
16 #endif
17 
18 #ifndef __ATLBASE_H__
19 	#error atlapp.h requires atlbase.h to be included first
20 #endif
21 
22 #ifndef _WIN32_WCE
23   #if (WINVER < 0x0400)
24 	#error WTL requires Windows version 4.0 or higher
25   #endif
26 
27   #if (_WIN32_IE < 0x0300)
28 	#error WTL requires IE version 3.0 or higher
29   #endif
30 #endif
31 
32 #ifdef _ATL_NO_COMMODULE
33 	#error WTL requires that _ATL_NO_COMMODULE is not defined
34 #endif
35 
36 #if (_ATL_VER >= 0x0900) && defined(_ATL_MIN_CRT)
37 	#error _ATL_MIN_CRT is not supported with ATL 9.0 and higher
38 #endif
39 
40 #if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)
41 	#pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT")
42 #endif
43 
44 #include <limits.h>
45 #if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
46   #include <process.h>	// for _beginthreadex
47 #endif
48 
49 #if (_ATL_VER < 0x0800) && !defined(_DEBUG)
50   #include <stdio.h>
51 #endif
52 
53 #include <commctrl.h>
54 #ifndef _WIN32_WCE
55   #pragma comment(lib, "comctl32.lib")
56 #endif
57 
58 #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
59   #include <VersionHelpers.h>
60 #endif
61 
62 #ifndef _WIN32_WCE
63   #include "atlres.h"
64 #else // CE specific
65   #include "atlresce.h"
66 #endif // _WIN32_WCE
67 
68 // We need to disable this warning because of template class arguments
69 #pragma warning(disable: 4127)
70 
71 #if (_ATL_VER >= 0x0900) && !defined(_SECURE_ATL)
72   #define _SECURE_ATL	1
73 #endif
74 
75 
76 ///////////////////////////////////////////////////////////////////////////////
77 // WTL version number
78 
79 #define _WTL_VER	0x0910
80 
81 
82 ///////////////////////////////////////////////////////////////////////////////
83 // Classes in this file:
84 //
85 // CMessageFilter
86 // CIdleHandler
87 // CMessageLoop
88 //
89 // CAppModule
90 // CServerAppModule
91 //
92 // CRegKeyEx
93 //
94 // Global functions:
95 //   AtlGetDefaultGuiFont()
96 //   AtlCreateControlFont()
97 //   AtlCreateBoldFont()
98 //   AtlInitCommonControls()
99 
100 
101 ///////////////////////////////////////////////////////////////////////////////
102 // Global support for Windows CE
103 
104 #ifdef _WIN32_WCE
105 
106 #ifndef SW_SHOWDEFAULT
107   #define SW_SHOWDEFAULT	SW_SHOWNORMAL
108 #endif // !SW_SHOWDEFAULT
109 
110 // These get's OR-ed in a constant and will have no effect.
111 // Defining them reduces the number of #ifdefs required for CE.
112 #define LR_DEFAULTSIZE      0
113 #define LR_LOADFROMFILE     0
114 
115 #ifndef SM_CXCURSOR
116   #define SM_CXCURSOR             13
117 #endif
118 #ifndef SM_CYCURSOR
119   #define SM_CYCURSOR             14
120 #endif
121 
IsMenu(HMENU hMenu)122 inline BOOL IsMenu(HMENU hMenu)
123 {
124 	MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
125 	::SetLastError(0);
126 	BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii);
127 	if(!bRet)
128 		bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE;
129 	return bRet;
130 }
131 
132 #if (_WIN32_WCE >= 410)
133 extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight);
134 #endif // (_WIN32_WCE >= 410)
135 
MulDiv(IN int nNumber,IN int nNumerator,IN int nDenominator)136 inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator)
137 {
138 	__int64 multiple = nNumber * nNumerator;
139 	return static_cast<int>(multiple / nDenominator);
140 }
141 
142 #if (_ATL_VER >= 0x0800)
143 
144 #ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW
145   #ifdef WS_OVERLAPPEDWINDOW
146     #undef WS_OVERLAPPEDWINDOW
147     #define WS_OVERLAPPEDWINDOW	0
148   #endif // WS_OVERLAPPEDWINDOW
149 #endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW
150 
151 #ifndef RDW_FRAME
152   #define RDW_FRAME	0
153 #endif // !RDW_FRAME
154 
155 #ifndef WM_WINDOWPOSCHANGING
156   #define WM_WINDOWPOSCHANGING	0
157 #endif // !WM_WINDOWPOSCHANGING
158 
159 #define FreeResource(x)
160 #define UnlockResource(x)
161 
162 namespace ATL
163 {
RegisterClassObjects(DWORD,DWORD)164   inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw()
165   { return E_NOTIMPL; }
RevokeClassObjects()166   inline HRESULT CComModule::RevokeClassObjects() throw()
167   { return E_NOTIMPL; }
168 }; // namespace ATL
169 
170 #ifndef lstrlenW
171   #define lstrlenW	(int)ATL::lstrlenW
172 #endif // lstrlenW
173 
lstrlenA(LPCSTR lpszString)174 inline int WINAPI lstrlenA(LPCSTR lpszString)
175 { return ATL::lstrlenA(lpszString); }
176 
177 #ifdef lstrcpyn
178   #undef lstrcpyn
179   #define lstrcpyn	ATL::lstrcpynW
180 #endif // lstrcpyn
181 
182 #ifndef SetWindowLongPtrW
tmp_SetWindowLongPtrW(HWND hWnd,int nIndex,LONG_PTR dwNewLong)183   inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
184   {
185 	return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
186   }
187   #define SetWindowLongPtrW tmp_SetWindowLongPtrW
188 #endif
189 
190 #ifndef GetWindowLongPtrW
tmp_GetWindowLongPtrW(HWND hWnd,int nIndex)191   inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex )
192   {
193 	return( ::GetWindowLongW( hWnd, nIndex ) );
194   }
195   #define GetWindowLongPtrW tmp_GetWindowLongPtrW
196 #endif
197 
198 #ifndef LongToPtr
199   #define LongToPtr(x) ((void*)x)
200 #endif
201 
202 #ifndef PtrToInt
203   #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
204 #endif
205 
206 #else // !(_ATL_VER >= 0x0800)
207 
208 #ifdef lstrlenW
209   #undef lstrlenW
210   #define lstrlenW (int)::wcslen
211 #endif // lstrlenW
212 
213 #define lstrlenA (int)strlen
214 
215 #ifndef lstrcpyn
lstrcpyn(LPTSTR lpstrDest,LPCTSTR lpstrSrc,int nLength)216   inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
217   {
218 	if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
219 		return NULL;
220 	int nLen = __min(lstrlen(lpstrSrc), nLength - 1);
221 	LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));
222 	lpstrDest[nLen] = 0;
223 	return lpstrRet;
224   }
225 #endif // !lstrcpyn
226 
227 #ifndef lstrcpynW
lstrcpynW(LPWSTR lpstrDest,LPCWSTR lpstrSrc,int nLength)228   inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength)
229   {
230 	return lstrcpyn(lpstrDest, lpstrSrc, nLength);   // WinCE is Unicode only
231   }
232 #endif // !lstrcpynW
233 
234 #ifndef lstrcpynA
lstrcpynA(LPSTR lpstrDest,LPCSTR lpstrSrc,int nLength)235   inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength)
236   {
237 	if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
238 		return NULL;
239 	int nLen = __min(lstrlenA(lpstrSrc), nLength - 1);
240 	LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char));
241 	lpstrDest[nLen] = 0;
242 	return lpstrRet;
243   }
244 #endif // !lstrcpyn
245 
246 #ifdef TrackPopupMenu
247   #undef TrackPopupMenu
248 #endif // TrackPopupMenu
249 
250 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
251 static CWndClassInfo& GetWndClassInfo() \
252 { \
253 	static CWndClassInfo wc = \
254 	{ \
255 		{ style, StartWindowProc, \
256 		  0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
257 		NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
258 	}; \
259 	return wc; \
260 }
261 
262 #ifndef _MAX_FNAME
263   #define _MAX_FNAME	_MAX_PATH
264 #endif // _MAX_FNAME
265 
266 #if (_WIN32_WCE < 400)
267   #define MAKEINTATOM(i)  (LPTSTR)((ULONG_PTR)((WORD)(i)))
268 #endif // (_WIN32_WCE < 400)
269 
270 #if (_WIN32_WCE < 410)
271   #define WHEEL_PAGESCROLL                (UINT_MAX)
272   #define WHEEL_DELTA                     120
273 #endif // (_WIN32_WCE < 410)
274 
275 #ifdef DrawIcon
276   #undef DrawIcon
277 #endif
278 
279 #ifndef VARCMP_LT
280   #define VARCMP_LT   0
281 #endif
282 #ifndef VARCMP_EQ
283   #define VARCMP_EQ   1
284 #endif
285 #ifndef VARCMP_GT
286   #define VARCMP_GT   2
287 #endif
288 #ifndef VARCMP_NULL
289   #define VARCMP_NULL 3
290 #endif
291 
292 #ifndef RDW_ALLCHILDREN
293   #define RDW_ALLCHILDREN   0
294 #endif
295 
296 #endif // !(_ATL_VER >= 0x0800)
297 
298 #endif // _WIN32_WCE
299 
300 
301 ///////////////////////////////////////////////////////////////////////////////
302 // Global support for using original VC++ 6.0 headers with WTL
303 
304 #if (_MSC_VER < 1300) && !defined(_WIN32_WCE)
305   #ifndef REG_QWORD
306     #define REG_QWORD	11
307   #endif
308 
309   #ifndef BS_PUSHBOX
310     #define BS_PUSHBOX	0x0000000AL
311   #endif
312 
313   struct __declspec(uuid("000214e6-0000-0000-c000-000000000046")) IShellFolder;
314   struct __declspec(uuid("000214f9-0000-0000-c000-000000000046")) IShellLinkW;
315   struct __declspec(uuid("000214ee-0000-0000-c000-000000000046")) IShellLinkA;
316 #endif // (_MSC_VER < 1300) && !defined(_WIN32_WCE)
317 
318 #ifndef _ATL_NO_OLD_HEADERS_WIN64
319 #if !defined(_WIN64) && (_ATL_VER < 0x0700)
320 
321   #ifndef PSM_INSERTPAGE
322     #define PSM_INSERTPAGE          (WM_USER + 119)
323   #endif // !PSM_INSERTPAGE
324 
325   #ifndef GetClassLongPtr
326     #define GetClassLongPtrA   GetClassLongA
327     #define GetClassLongPtrW   GetClassLongW
328     #ifdef UNICODE
329       #define GetClassLongPtr  GetClassLongPtrW
330     #else
331       #define GetClassLongPtr  GetClassLongPtrA
332     #endif // !UNICODE
333   #endif // !GetClassLongPtr
334 
335   #ifndef GCLP_HICONSM
336     #define GCLP_HICONSM        (-34)
337   #endif // !GCLP_HICONSM
338 
339   #ifndef GetWindowLongPtr
340     #define GetWindowLongPtrA   GetWindowLongA
341     #define GetWindowLongPtrW   GetWindowLongW
342     #ifdef UNICODE
343       #define GetWindowLongPtr  GetWindowLongPtrW
344     #else
345       #define GetWindowLongPtr  GetWindowLongPtrA
346     #endif // !UNICODE
347   #endif // !GetWindowLongPtr
348 
349   #ifndef SetWindowLongPtr
350     #define SetWindowLongPtrA   SetWindowLongA
351     #define SetWindowLongPtrW   SetWindowLongW
352     #ifdef UNICODE
353       #define SetWindowLongPtr  SetWindowLongPtrW
354     #else
355       #define SetWindowLongPtr  SetWindowLongPtrA
356     #endif // !UNICODE
357   #endif // !SetWindowLongPtr
358 
359   #ifndef GWLP_WNDPROC
360     #define GWLP_WNDPROC        (-4)
361   #endif
362   #ifndef GWLP_HINSTANCE
363     #define GWLP_HINSTANCE      (-6)
364   #endif
365   #ifndef GWLP_HWNDPARENT
366     #define GWLP_HWNDPARENT     (-8)
367   #endif
368   #ifndef GWLP_USERDATA
369     #define GWLP_USERDATA       (-21)
370   #endif
371   #ifndef GWLP_ID
372     #define GWLP_ID             (-12)
373   #endif
374 
375   #ifndef DWLP_MSGRESULT
376     #define DWLP_MSGRESULT  0
377   #endif
378 
379   typedef long LONG_PTR;
380   typedef unsigned long ULONG_PTR;
381   typedef ULONG_PTR DWORD_PTR;
382 
383   #ifndef HandleToUlong
384     #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
385   #endif
386   #ifndef HandleToLong
387     #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
388   #endif
389   #ifndef LongToHandle
390     #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
391   #endif
392   #ifndef PtrToUlong
393     #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
394   #endif
395   #ifndef PtrToLong
396     #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
397   #endif
398   #ifndef PtrToUint
399     #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
400   #endif
401   #ifndef PtrToInt
402     #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
403   #endif
404   #ifndef PtrToUshort
405     #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
406   #endif
407   #ifndef PtrToShort
408     #define PtrToShort( p ) ((short)(LONG_PTR)(p) )
409   #endif
410   #ifndef IntToPtr
411     #define IntToPtr( i )    ((VOID *)(INT_PTR)((int)i))
412   #endif
413   #ifndef UIntToPtr
414     #define UIntToPtr( ui )  ((VOID *)(UINT_PTR)((unsigned int)ui))
415   #endif
416   #ifndef LongToPtr
417     #define LongToPtr( l )   ((VOID *)(LONG_PTR)((long)l))
418   #endif
419   #ifndef ULongToPtr
420     #define ULongToPtr( ul )  ((VOID *)(ULONG_PTR)((unsigned long)ul))
421   #endif
422 
423 #endif // !defined(_WIN64) && (_ATL_VER < 0x0700)
424 #endif // !_ATL_NO_OLD_HEADERS_WIN64
425 
426 
427 ///////////////////////////////////////////////////////////////////////////////
428 // Global support for using original VC++ 7.x headers with WTL
429 
430 #if (_MSC_VER >= 1300) && (_MSC_VER < 1400)
431 
432   #ifndef BS_PUSHBOX
433     #define BS_PUSHBOX	0x0000000AL
434   #endif
435 
436   #pragma warning(disable: 4244)   // conversion from 'type1' to 'type2', possible loss of data
437 
438 #endif // (_MSC_VER >= 1300) && (_MSC_VER < 1400)
439 
440 
441 ///////////////////////////////////////////////////////////////////////////////
442 // Global support for old SDK headers
443 
444 #ifndef BTNS_BUTTON
445   #define BTNS_BUTTON	TBSTYLE_BUTTON
446 #endif
447 
448 #ifndef BTNS_SEP
449   #define BTNS_SEP	TBSTYLE_SEP
450 #endif
451 
452 #ifndef BTNS_CHECK
453   #define BTNS_CHECK	TBSTYLE_CHECK
454 #endif
455 
456 #ifndef BTNS_GROUP
457   #define BTNS_GROUP	TBSTYLE_GROUP
458 #endif
459 
460 #ifndef BTNS_CHECKGROUP
461   #define BTNS_CHECKGROUP	TBSTYLE_CHECKGROUP
462 #endif
463 
464 #if (_WIN32_IE >= 0x0300)
465   #ifndef BTNS_DROPDOWN
466     #define BTNS_DROPDOWN	TBSTYLE_DROPDOWN
467   #endif
468 #endif
469 
470 #if (_WIN32_IE >= 0x0400)
471   #ifndef BTNS_AUTOSIZE
472     #define BTNS_AUTOSIZE	TBSTYLE_AUTOSIZE
473   #endif
474 
475   #ifndef BTNS_NOPREFIX
476     #define BTNS_NOPREFIX	TBSTYLE_NOPREFIX
477   #endif
478 #endif
479 
480 
481 ///////////////////////////////////////////////////////////////////////////////
482 // Global support for SecureHelper functions
483 
484 #ifndef _TRUNCATE
485   #define _TRUNCATE ((size_t)-1)
486 #endif
487 
488 #ifndef _ERRCODE_DEFINED
489   #define _ERRCODE_DEFINED
490   typedef int errno_t;
491 #endif
492 
493 #ifndef _SECURECRT_ERRCODE_VALUES_DEFINED
494   #define _SECURECRT_ERRCODE_VALUES_DEFINED
495   #define EINVAL          22
496   #define STRUNCATE       80
497 #endif
498 
499 #ifndef _countof
500   #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
501 #endif
502 
503 
504 ///////////////////////////////////////////////////////////////////////////////
505 // Miscellaneous global support
506 
507 // define useful macros from winuser.h
508 #ifndef IS_INTRESOURCE
509   #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
510 #endif // IS_INTRESOURCE
511 
512 // protect template members from windowsx.h macros
513 #ifdef _INC_WINDOWSX
514   #undef SubclassWindow
515 #endif // _INC_WINDOWSX
516 
517 // define useful macros from windowsx.h
518 #ifndef GET_X_LPARAM
519   #define GET_X_LPARAM(lParam)	((int)(short)LOWORD(lParam))
520 #endif
521 #ifndef GET_Y_LPARAM
522   #define GET_Y_LPARAM(lParam)	((int)(short)HIWORD(lParam))
523 #endif
524 
525 // Dummy structs for compiling with /CLR
526 #if (_MSC_VER >= 1300) && defined(_MANAGED)
__if_not_exists(_IMAGELIST::_IMAGELIST)527   __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
__if_not_exists(_TREEITEM::_TREEITEM)528   __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
__if_not_exists(_PSP::_PSP)529   __if_not_exists(_PSP::_PSP) { struct _PSP { }; }
530 #endif
531 
532 // Define ATLVERIFY macro for ATL3
533 #if (_ATL_VER < 0x0700)
534   #ifndef ATLVERIFY
535     #ifdef _DEBUG
536       #define ATLVERIFY(expr) ATLASSERT(expr)
537     #else
538       #define ATLVERIFY(expr) (expr)
539     #endif // DEBUG
540   #endif // ATLVERIFY
541 #endif // (_ATL_VER < 0x0700)
542 
543 // Forward declaration for ATL3 and ATL11 fix
544 #if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
545   namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); };
546 #endif
547 
548 #ifndef WM_MOUSEHWHEEL
549   #define WM_MOUSEHWHEEL                  0x020E
550 #endif
551 
552 
553 namespace WTL
554 {
555 
556 #if (_ATL_VER >= 0x0700)
557   DECLARE_TRACE_CATEGORY(atlTraceUI);
558   #ifdef _DEBUG
559     __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
560   #endif // _DEBUG
561 #else // !(_ATL_VER >= 0x0700)
562   enum wtlTraceFlags
563   {
564 	atlTraceUI = 0x10000000
565   };
566 #endif // !(_ATL_VER >= 0x0700)
567 
568 // Windows version helper
AtlIsOldWindows()569 inline bool AtlIsOldWindows()
570 {
571 #ifdef _versionhelpers_H_INCLUDED_
572 	return !::IsWindowsVersionOrGreater(4, 90, 0);
573 #else // !_versionhelpers_H_INCLUDED_
574 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
575 	BOOL bRet = ::GetVersionEx(&ovi);
576 	return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));
577 #endif // _versionhelpers_H_INCLUDED_
578 }
579 
580 // Default GUI font helper - "MS Shell Dlg" stock font
AtlGetDefaultGuiFont()581 inline HFONT AtlGetDefaultGuiFont()
582 {
583 #ifndef _WIN32_WCE
584 	return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
585 #else // CE specific
586 	return (HFONT)::GetStockObject(SYSTEM_FONT);
587 #endif // _WIN32_WCE
588 }
589 
590 // Control font helper - default font for controls not in a dialog
591 // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
AtlCreateControlFont()592 inline HFONT AtlCreateControlFont()
593 {
594 #ifndef _WIN32_WCE
595 	LOGFONT lf = { 0 };
596 	ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
597 	HFONT hFont = ::CreateFontIndirect(&lf);
598 	ATLASSERT(hFont != NULL);
599 	return hFont;
600 #else // CE specific
601 	return (HFONT)::GetStockObject(SYSTEM_FONT);
602 #endif // _WIN32_WCE
603 }
604 
605 // Bold font helper
606 // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
607 inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
608 {
609 	LOGFONT lf = { 0 };
610 #ifndef _WIN32_WCE
611 	if(hFont == NULL)
612 		ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
613 	else
614 		ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
615 #else // CE specific
616 	if(hFont == NULL)
617 		hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
618 	ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
619 #endif // _WIN32_WCE
620 	lf.lfWeight = FW_BOLD;
621 	HFONT hFontBold =  ::CreateFontIndirect(&lf);
622 	ATLASSERT(hFontBold != NULL);
623 	return hFontBold;
624 }
625 
626 // Common Controls initialization helper
AtlInitCommonControls(DWORD dwFlags)627 inline BOOL AtlInitCommonControls(DWORD dwFlags)
628 {
629 	INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
630 	BOOL bRet = ::InitCommonControlsEx(&iccx);
631 	ATLASSERT(bRet);
632 	return bRet;
633 }
634 
635 
636 ///////////////////////////////////////////////////////////////////////////////
637 // RunTimeHelper - helper functions for Windows version and structure sizes
638 
639 // Not for Windows CE
640 #if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE)
641   #define _WTL_NO_RUNTIME_STRUCT_SIZE
642 #endif
643 
644 #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
645 
646 #ifndef _SIZEOF_STRUCT
647   #define _SIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
648 #endif
649 
650 #if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
651   #define REBARBANDINFO_V6_SIZE   _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
652 #endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
653 
654 #if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
655   #define LVGROUP_V5_SIZE   _SIZEOF_STRUCT(LVGROUP, uAlign)
656 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
657 
658 #if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
659   #define LVTILEINFO_V5_SIZE   _SIZEOF_STRUCT(LVTILEINFO, puColumns)
660 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
661 
662 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
663   #define MCHITTESTINFO_V1_SIZE   _SIZEOF_STRUCT(MCHITTESTINFO, st)
664 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
665 
666 #if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
667   #define NONCLIENTMETRICS_V1_SIZE   _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
668 #endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
669 
670 #if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0501) && !defined(TTTOOLINFO_V2_SIZE)
671   #define TTTOOLINFO_V2_SIZE   _SIZEOF_STRUCT(TTTOOLINFO, lParam)
672 #endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0501) && !defined(TTTOOLINFO_V2_SIZE)
673 
674 #endif // !_WTL_NO_RUNTIME_STRUCT_SIZE
675 
676 namespace RunTimeHelper
677 {
678 #ifndef _WIN32_WCE
IsCommCtrl6()679 	inline bool IsCommCtrl6()
680 	{
681 		DWORD dwMajor = 0, dwMinor = 0;
682 		HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
683 		return (SUCCEEDED(hRet) && (dwMajor >= 6));
684 	}
685 
IsVista()686 	inline bool IsVista()
687 	{
688 #ifdef _versionhelpers_H_INCLUDED_
689 		return ::IsWindowsVistaOrGreater();
690 #else // !_versionhelpers_H_INCLUDED_
691 		OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
692 		BOOL bRet = ::GetVersionEx(&ovi);
693 		return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
694 #endif // _versionhelpers_H_INCLUDED_
695 	}
696 
IsThemeAvailable()697 	inline bool IsThemeAvailable()
698 	{
699 		bool bRet = false;
700 
701 		if(IsCommCtrl6())
702 		{
703 			HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
704 			if(hThemeDLL != NULL)
705 			{
706 				typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)();
707 				PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThemeActive)::GetProcAddress(hThemeDLL, "IsThemeActive");
708 				ATLASSERT(pfnIsThemeActive != NULL);
709 				bRet = (pfnIsThemeActive != NULL) && (pfnIsThemeActive() != FALSE);
710 				if(bRet)
711 				{
712 					typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)();
713 					PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppThemed)::GetProcAddress(hThemeDLL, "IsAppThemed");
714 					ATLASSERT(pfnIsAppThemed != NULL);
715 					bRet = (pfnIsAppThemed != NULL) && (pfnIsAppThemed() != FALSE);
716 				}
717 
718 				::FreeLibrary(hThemeDLL);
719 			}
720 		}
721 
722 		return bRet;
723 	}
724 
IsWin7()725 	inline bool IsWin7()
726 	{
727 #ifdef _versionhelpers_H_INCLUDED_
728 		return ::IsWindows7OrGreater();
729 #else // !_versionhelpers_H_INCLUDED_
730 		OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
731 		BOOL bRet = ::GetVersionEx(&ovi);
732 		return ((bRet != FALSE) && (ovi.dwMajorVersion == 6) && (ovi.dwMinorVersion >= 1));
733 #endif // _versionhelpers_H_INCLUDED_
734 	}
735 
IsRibbonUIAvailable()736 	inline bool IsRibbonUIAvailable()
737 	{
738 		static INT iRibbonUI = -1;
739 
740 #if defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
741 		if (iRibbonUI == -1)
742 		{
743 			HMODULE hRibbonDLL = ::LoadLibrary(_T("propsys.dll"));
744 			if (hRibbonDLL != NULL)
745 			{
746 				const GUID CLSID_UIRibbonFramework = { 0x926749fa, 0x2615, 0x4987, { 0x88, 0x45, 0xc3, 0x3e, 0x65, 0xf2, 0xb9, 0x57 } };
747 				// block - create instance
748 				{
749 					ATL::CComPtr<IUnknown> pIUIFramework;
750 					iRibbonUI = SUCCEEDED(pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework)) ? 1 : 0;
751 				}
752 				::FreeLibrary(hRibbonDLL);
753 			}
754 			else
755 			{
756 				iRibbonUI = 0;
757 			}
758 		}
759 #endif // defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
760 
761 		return (iRibbonUI == 1);
762 	}
763 
764 #endif // !_WIN32_WCE
765 
SizeOf_REBARBANDINFO()766 	inline UINT SizeOf_REBARBANDINFO()
767 	{
768 		UINT uSize = sizeof(REBARBANDINFO);
769 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
770 		if(!(IsVista() && IsCommCtrl6()))
771 			uSize = REBARBANDINFO_V6_SIZE;
772 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
773 		return uSize;
774 	}
775 
776 #if (_WIN32_WINNT >= 0x501)
SizeOf_LVGROUP()777   	inline UINT SizeOf_LVGROUP()
778 	{
779 		UINT uSize = sizeof(LVGROUP);
780 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
781 		if(!IsVista())
782 			uSize = LVGROUP_V5_SIZE;
783 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
784 		return uSize;
785 	}
786 
SizeOf_LVTILEINFO()787 	inline UINT SizeOf_LVTILEINFO()
788 	{
789 		UINT uSize = sizeof(LVTILEINFO);
790 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
791 		if(!IsVista())
792 			uSize = LVTILEINFO_V5_SIZE;
793 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
794 		return uSize;
795 	}
796 #endif // (_WIN32_WINNT >= 0x501)
797 
SizeOf_MCHITTESTINFO()798 	inline UINT SizeOf_MCHITTESTINFO()
799 	{
800 		UINT uSize = sizeof(MCHITTESTINFO);
801 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
802 		if(!(IsVista() && IsCommCtrl6()))
803 			uSize = MCHITTESTINFO_V1_SIZE;
804 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
805 		return uSize;
806 	}
807 
808 #ifndef _WIN32_WCE
SizeOf_NONCLIENTMETRICS()809 	inline UINT SizeOf_NONCLIENTMETRICS()
810 	{
811 		UINT uSize = sizeof(NONCLIENTMETRICS);
812 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
813 		if(!IsVista())
814 			uSize = NONCLIENTMETRICS_V1_SIZE;
815 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
816 		return uSize;
817 	}
818 
SizeOf_TOOLINFO()819 	inline UINT SizeOf_TOOLINFO()
820 	{
821 		UINT uSize = sizeof(TOOLINFO);
822 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0501)
823 		if(!IsVista())
824 			uSize = TTTOOLINFO_V2_SIZE;
825 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0501)
826 		return uSize;
827 	}
828 #endif // !_WIN32_WCE
829 };
830 
831 
832 ///////////////////////////////////////////////////////////////////////////////
833 // ModuleHelper - helper functions for ATL3 and ATL7 module classes
834 
835 namespace ModuleHelper
836 {
GetModuleInstance()837 	inline HINSTANCE GetModuleInstance()
838 	{
839 #if (_ATL_VER >= 0x0700)
840 		return ATL::_AtlBaseModule.GetModuleInstance();
841 #else // !(_ATL_VER >= 0x0700)
842 		return ATL::_pModule->GetModuleInstance();
843 #endif // !(_ATL_VER >= 0x0700)
844 	}
845 
GetResourceInstance()846 	inline HINSTANCE GetResourceInstance()
847 	{
848 #if (_ATL_VER >= 0x0700)
849 		return ATL::_AtlBaseModule.GetResourceInstance();
850 #else // !(_ATL_VER >= 0x0700)
851 		return ATL::_pModule->GetResourceInstance();
852 #endif // !(_ATL_VER >= 0x0700)
853 	}
854 
AddCreateWndData(ATL::_AtlCreateWndData * pData,void * pObject)855 	inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
856 	{
857 #if (_ATL_VER >= 0x0700)
858 		ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
859 #else // !(_ATL_VER >= 0x0700)
860 		ATL::_pModule->AddCreateWndData(pData, pObject);
861 #endif // !(_ATL_VER >= 0x0700)
862 	}
863 
ExtractCreateWndData()864 	inline void* ExtractCreateWndData()
865 	{
866 #if (_ATL_VER >= 0x0700)
867 		return ATL::_AtlWinModule.ExtractCreateWndData();
868 #else // !(_ATL_VER >= 0x0700)
869 		return ATL::_pModule->ExtractCreateWndData();
870 #endif // !(_ATL_VER >= 0x0700)
871 	}
872 };
873 
874 
875 ///////////////////////////////////////////////////////////////////////////////
876 // SecureHelper - helper functions for VS2005 secure CRT
877 
878 namespace SecureHelper
879 {
strcpyA_x(char * lpstrDest,size_t cchDest,const char * lpstrSrc)880 	inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
881 	{
882 #if _SECURE_ATL
883 		ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
884 #else
885 		if(cchDest > (size_t)lstrlenA(lpstrSrc))
886 			ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL);
887 		else
888 			ATLASSERT(FALSE);
889 #endif
890 	}
891 
strcpyW_x(wchar_t * lpstrDest,size_t cchDest,const wchar_t * lpstrSrc)892 	inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
893 	{
894 #if _SECURE_ATL
895 		ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
896 #else
897 		if(cchDest > (size_t)lstrlenW(lpstrSrc))
898 			ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL);
899 		else
900 			ATLASSERT(FALSE);
901 #endif
902 	}
903 
strcpy_x(LPTSTR lpstrDest,size_t cchDest,LPCTSTR lpstrSrc)904 	inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
905 	{
906 #ifdef _UNICODE
907 		strcpyW_x(lpstrDest, cchDest, lpstrSrc);
908 #else
909 		strcpyA_x(lpstrDest, cchDest, lpstrSrc);
910 #endif
911 	}
912 
strncpyA_x(char * lpstrDest,size_t cchDest,const char * lpstrSrc,size_t cchCount)913 	inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
914 	{
915 #if _SECURE_ATL
916 		return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
917 #else
918 		errno_t nRet = 0;
919 		if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
920 		{
921 			nRet = EINVAL;
922 		}
923 		else if(cchCount == _TRUNCATE)
924 		{
925 			cchCount = __min(cchDest - 1, size_t(lstrlenA(lpstrSrc)));
926 			nRet = STRUNCATE;
927 		}
928 		else if(cchDest <= cchCount)
929 		{
930 			lpstrDest[0] = 0;
931 			nRet = EINVAL;
932 		}
933 		if(nRet == 0 || nRet == STRUNCATE)
934 			nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
935 		ATLASSERT(nRet == 0 || nRet == STRUNCATE);
936 		return nRet;
937 #endif
938 	}
939 
strncpyW_x(wchar_t * lpstrDest,size_t cchDest,const wchar_t * lpstrSrc,size_t cchCount)940 	inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
941 	{
942 #if _SECURE_ATL
943 		return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
944 #else
945 		errno_t nRet = 0;
946 		if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
947 		{
948 			nRet = EINVAL;
949 		}
950 		else if(cchCount == _TRUNCATE)
951 		{
952 			cchCount = __min(cchDest - 1, size_t(lstrlenW(lpstrSrc)));
953 			nRet = STRUNCATE;
954 		}
955 		else if(cchDest <= cchCount)
956 		{
957 			lpstrDest[0] = 0;
958 			nRet = EINVAL;
959 		}
960 		if(nRet == 0 || nRet == STRUNCATE)
961 			nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
962 		ATLASSERT(nRet == 0 || nRet == STRUNCATE);
963 		return nRet;
964 #endif
965 	}
966 
strncpy_x(LPTSTR lpstrDest,size_t cchDest,LPCTSTR lpstrSrc,size_t cchCount)967 	inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
968 	{
969 #ifdef _UNICODE
970 		return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
971 #else
972 		return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
973 #endif
974 	}
975 
strcatA_x(char * lpstrDest,size_t cchDest,const char * lpstrSrc)976 	inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
977 	{
978 #if _SECURE_ATL
979 		ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
980 #else
981 		if(cchDest > (size_t)lstrlenA(lpstrSrc))
982 			ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL);
983 		else
984 			ATLASSERT(FALSE);
985 #endif
986 	}
987 
strcatW_x(wchar_t * lpstrDest,size_t cchDest,const wchar_t * lpstrSrc)988 	inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
989 	{
990 #if _SECURE_ATL
991 		ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
992 #else
993 		if(cchDest > (size_t)lstrlenW(lpstrSrc))
994 			ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL);
995 		else
996 			ATLASSERT(FALSE);
997 #endif
998 	}
999 
strcat_x(LPTSTR lpstrDest,size_t cchDest,LPCTSTR lpstrSrc)1000 	inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
1001 	{
1002 #ifdef _UNICODE
1003 		strcatW_x(lpstrDest, cchDest, lpstrSrc);
1004 #else
1005 		strcatA_x(lpstrDest, cchDest, lpstrSrc);
1006 #endif
1007 	}
1008 
memcpy_x(void * pDest,size_t cbDest,const void * pSrc,size_t cbSrc)1009 	inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
1010 	{
1011 #if _SECURE_ATL
1012 		ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
1013 #else
1014 		if(cbDest >= cbSrc)
1015 			memcpy(pDest, pSrc, cbSrc);
1016 		else
1017 			ATLASSERT(FALSE);
1018 #endif
1019 	}
1020 
memmove_x(void * pDest,size_t cbDest,const void * pSrc,size_t cbSrc)1021 	inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
1022 	{
1023 #if _SECURE_ATL
1024 		ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
1025 #else
1026 		if(cbDest >= cbSrc)
1027 			memmove(pDest, pSrc, cbSrc);
1028 		else
1029 			ATLASSERT(FALSE);
1030 #endif
1031 	}
1032 
vsprintf_x(LPTSTR lpstrBuff,size_t cchBuff,LPCTSTR lpstrFormat,va_list args)1033 	inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
1034 	{
1035 #if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
1036 		return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
1037 #else
1038 		cchBuff;   // Avoid unused argument warning
1039   #pragma warning(push)
1040   #pragma warning(disable: 4996)
1041 		return _vstprintf(lpstrBuff, lpstrFormat, args);
1042   #pragma warning(pop)
1043 #endif
1044 	}
1045 
wvsprintf_x(LPTSTR lpstrBuff,size_t cchBuff,LPCTSTR lpstrFormat,va_list args)1046 	inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
1047 	{
1048 #if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
1049 		return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
1050 #else
1051 		cchBuff;   // Avoid unused argument warning
1052 		return ::wvsprintf(lpstrBuff, lpstrFormat, args);
1053 #endif
1054 	}
1055 
sprintf_x(LPTSTR lpstrBuff,size_t cchBuff,LPCTSTR lpstrFormat,...)1056 	inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
1057 	{
1058 		va_list args;
1059 		va_start(args, lpstrFormat);
1060 		int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
1061 		va_end(args);
1062 		return nRes;
1063 	}
1064 
wsprintf_x(LPTSTR lpstrBuff,size_t cchBuff,LPCTSTR lpstrFormat,...)1065 	inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
1066 	{
1067 		va_list args;
1068 		va_start(args, lpstrFormat);
1069 		int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
1070 		va_end(args);
1071 		return nRes;
1072 	}
1073 }; // namespace SecureHelper
1074 
1075 
1076 ///////////////////////////////////////////////////////////////////////////////
1077 // MinCrtHelper - helper functions for using _ATL_MIN_CRT
1078 
1079 namespace MinCrtHelper
1080 {
_isspace(TCHAR ch)1081 	inline int _isspace(TCHAR ch)
1082 	{
1083 #ifndef _ATL_MIN_CRT
1084 		return _istspace(ch);
1085 #else // _ATL_MIN_CRT
1086 		WORD type = 0;
1087 		::GetStringTypeEx(::GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
1088 		return (type & C1_SPACE) == C1_SPACE;
1089 #endif // _ATL_MIN_CRT
1090 	}
1091 
_isdigit(TCHAR ch)1092 	inline int _isdigit(TCHAR ch)
1093 	{
1094 #ifndef _ATL_MIN_CRT
1095 		return _istdigit(ch);
1096 #else // _ATL_MIN_CRT
1097 		WORD type = 0;
1098 		::GetStringTypeEx(::GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
1099 		return (type & C1_DIGIT) == C1_DIGIT;
1100 #endif // _ATL_MIN_CRT
1101 	}
1102 
_atoi(LPCTSTR str)1103 	inline int _atoi(LPCTSTR str)
1104 	{
1105 #ifndef _ATL_MIN_CRT
1106 		return _ttoi(str);
1107 #else // _ATL_MIN_CRT
1108 		while(_isspace(*str) != 0)
1109 			++str;
1110 
1111 		TCHAR ch = *str++;
1112 		TCHAR sign = ch;   // save sign indication
1113 		if(ch == _T('-') || ch == _T('+'))
1114 			ch = *str++;   // skip sign
1115 
1116 		int total = 0;
1117 		while(_isdigit(ch) != 0)
1118 		{
1119 			total = 10 * total + (ch - '0');   // accumulate digit
1120 			ch = *str++;        // get next char
1121 		}
1122 
1123 		return (sign == '-') ? -total : total;   // return result, negated if necessary
1124 #endif // _ATL_MIN_CRT
1125 	}
1126 
_strrchr(LPCTSTR str,TCHAR ch)1127 	inline LPCTSTR _strrchr(LPCTSTR str, TCHAR ch)
1128 	{
1129 #ifndef _ATL_MIN_CRT
1130 		return _tcsrchr(str, ch);
1131 #else // _ATL_MIN_CRT
1132 		LPCTSTR lpsz = NULL;
1133 		while(*str != 0)
1134 		{
1135 			if(*str == ch)
1136 				lpsz = str;
1137 			str = ::CharNext(str);
1138 		}
1139 		return lpsz;
1140 #endif // _ATL_MIN_CRT
1141 	}
1142 
_strrchr(LPTSTR str,TCHAR ch)1143 	inline LPTSTR _strrchr(LPTSTR str, TCHAR ch)
1144 	{
1145 #ifndef _ATL_MIN_CRT
1146 		return _tcsrchr(str, ch);
1147 #else // _ATL_MIN_CRT
1148 		LPTSTR lpsz = NULL;
1149 		while(*str != 0)
1150 		{
1151 			if(*str == ch)
1152 				lpsz = str;
1153 			str = ::CharNext(str);
1154 		}
1155 		return lpsz;
1156 #endif // _ATL_MIN_CRT
1157 	}
1158 }; // namespace MinCrtHelper
1159 
1160 
1161 ///////////////////////////////////////////////////////////////////////////////
1162 // GenericWndClass - generic window class usable for subclassing
1163 
1164 // Use in dialog templates to specify a placeholder to be subclassed
1165 // Specify as a custom control with class name WTL_GenericWindow
1166 // Call Rregister() before creating dialog (for example, in WinMain)
1167 namespace GenericWndClass
1168 {
GetName()1169 	inline LPCTSTR GetName()
1170 	{
1171 		return _T("WTL_GenericWindow");
1172 	}
1173 
Register()1174 	inline ATOM Register()
1175 	{
1176 #ifndef _WIN32_WCE
1177 		WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
1178 #else
1179 		WNDCLASS wc = { 0 };
1180 #endif
1181 		wc.lpfnWndProc = ::DefWindowProc;
1182 		wc.hInstance = ModuleHelper::GetModuleInstance();
1183 		wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
1184 		wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1185 		wc.lpszClassName = GetName();
1186 #ifndef _WIN32_WCE
1187 		ATOM atom = ::RegisterClassEx(&wc);
1188 #else
1189 		ATOM atom = ::RegisterClass(&wc);
1190 #endif
1191 		ATLASSERT(atom != 0);
1192 		return atom;
1193 	}
1194 
Unregister()1195 	inline BOOL Unregister()   // only needed for DLLs or tmp use
1196 	{
1197 		return ::UnregisterClass(GetName(), ModuleHelper::GetModuleInstance());
1198 	}
1199 }; // namespace GenericWndClass
1200 
1201 
1202 ///////////////////////////////////////////////////////////////////////////////
1203 // CMessageFilter - Interface for message filter support
1204 
1205 class CMessageFilter
1206 {
1207 public:
1208 	virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
1209 };
1210 
1211 
1212 ///////////////////////////////////////////////////////////////////////////////
1213 // CIdleHandler - Interface for idle processing
1214 
1215 class CIdleHandler
1216 {
1217 public:
1218 	virtual BOOL OnIdle() = 0;
1219 };
1220 
1221 #ifndef _ATL_NO_OLD_NAMES
1222   // for compatilibility with old names only
1223   typedef CIdleHandler CUpdateUIObject;
1224   #define DoUpdate OnIdle
1225 #endif // !_ATL_NO_OLD_NAMES
1226 
1227 
1228 ///////////////////////////////////////////////////////////////////////////////
1229 // CMessageLoop - message loop implementation
1230 
1231 class CMessageLoop
1232 {
1233 public:
1234 	ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
1235 	ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
1236 	MSG m_msg;
1237 
1238 // Message filter operations
AddMessageFilter(CMessageFilter * pMessageFilter)1239 	BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
1240 	{
1241 		return m_aMsgFilter.Add(pMessageFilter);
1242 	}
1243 
RemoveMessageFilter(CMessageFilter * pMessageFilter)1244 	BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
1245 	{
1246 		return m_aMsgFilter.Remove(pMessageFilter);
1247 	}
1248 
1249 // Idle handler operations
AddIdleHandler(CIdleHandler * pIdleHandler)1250 	BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
1251 	{
1252 		return m_aIdleHandler.Add(pIdleHandler);
1253 	}
1254 
RemoveIdleHandler(CIdleHandler * pIdleHandler)1255 	BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
1256 	{
1257 		return m_aIdleHandler.Remove(pIdleHandler);
1258 	}
1259 
1260 #ifndef _ATL_NO_OLD_NAMES
1261 	// for compatilibility with old names only
AddUpdateUI(CIdleHandler * pIdleHandler)1262 	BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
1263 	{
1264 		ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
1265 		return AddIdleHandler(pIdleHandler);
1266 	}
1267 
RemoveUpdateUI(CIdleHandler * pIdleHandler)1268 	BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
1269 	{
1270 		ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
1271 		return RemoveIdleHandler(pIdleHandler);
1272 	}
1273 #endif // !_ATL_NO_OLD_NAMES
1274 
1275 // message loop
Run()1276 	int Run()
1277 	{
1278 		BOOL bDoIdle = TRUE;
1279 		int nIdleCount = 0;
1280 		BOOL bRet;
1281 
1282 		for(;;)
1283 		{
1284 			while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
1285 			{
1286 				if(!OnIdle(nIdleCount++))
1287 					bDoIdle = FALSE;
1288 			}
1289 
1290 			bRet = ::GetMessage(&m_msg, NULL, 0, 0);
1291 
1292 			if(bRet == -1)
1293 			{
1294 				ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
1295 				continue;   // error, don't process
1296 			}
1297 			else if(!bRet)
1298 			{
1299 				ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
1300 				break;   // WM_QUIT, exit message loop
1301 			}
1302 
1303 			if(!PreTranslateMessage(&m_msg))
1304 			{
1305 				::TranslateMessage(&m_msg);
1306 				::DispatchMessage(&m_msg);
1307 			}
1308 
1309 			if(IsIdleMessage(&m_msg))
1310 			{
1311 				bDoIdle = TRUE;
1312 				nIdleCount = 0;
1313 			}
1314 		}
1315 
1316 		return (int)m_msg.wParam;
1317 	}
1318 
IsIdleMessage(MSG * pMsg)1319 	static BOOL IsIdleMessage(MSG* pMsg)
1320 	{
1321 		// These messages should NOT cause idle processing
1322 		switch(pMsg->message)
1323 		{
1324 		case WM_MOUSEMOVE:
1325 #ifndef _WIN32_WCE
1326 		case WM_NCMOUSEMOVE:
1327 #endif // !_WIN32_WCE
1328 		case WM_PAINT:
1329 		case 0x0118:	// WM_SYSTIMER (caret blink)
1330 			return FALSE;
1331 		}
1332 
1333 		return TRUE;
1334 	}
1335 
1336 // Overrideables
1337 	// Override to change message filtering
PreTranslateMessage(MSG * pMsg)1338 	virtual BOOL PreTranslateMessage(MSG* pMsg)
1339 	{
1340 		// loop backwards
1341 		for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
1342 		{
1343 			CMessageFilter* pMessageFilter = m_aMsgFilter[i];
1344 			if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
1345 				return TRUE;
1346 		}
1347 		return FALSE;   // not translated
1348 	}
1349 
1350 	// override to change idle processing
OnIdle(int)1351 	virtual BOOL OnIdle(int /*nIdleCount*/)
1352 	{
1353 		for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
1354 		{
1355 			CIdleHandler* pIdleHandler = m_aIdleHandler[i];
1356 			if(pIdleHandler != NULL)
1357 				pIdleHandler->OnIdle();
1358 		}
1359 		return FALSE;   // don't continue
1360 	}
1361 };
1362 
1363 
1364 ///////////////////////////////////////////////////////////////////////////////
1365 // CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
1366 // internal classes to manage critical sections for both ATL3 and ATL7
1367 
1368 class CStaticDataInitCriticalSectionLock
1369 {
1370 public:
1371 #if (_ATL_VER >= 0x0700)
1372 	ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
1373 
CStaticDataInitCriticalSectionLock()1374 	CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
1375 	{ }
1376 #endif // (_ATL_VER >= 0x0700)
1377 
Lock()1378 	HRESULT Lock()
1379 	{
1380 #if (_ATL_VER >= 0x0700)
1381 		return m_cslock.Lock();
1382 #else // !(_ATL_VER >= 0x0700)
1383 		::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit);
1384 		return S_OK;
1385 #endif // !(_ATL_VER >= 0x0700)
1386 	}
1387 
Unlock()1388 	void Unlock()
1389 	{
1390 #if (_ATL_VER >= 0x0700)
1391 		m_cslock.Unlock();
1392 #else // !(_ATL_VER >= 0x0700)
1393 		::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit);
1394 #endif // !(_ATL_VER >= 0x0700)
1395 	}
1396 };
1397 
1398 
1399 class CWindowCreateCriticalSectionLock
1400 {
1401 public:
1402 #if (_ATL_VER >= 0x0700)
1403 	ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
1404 
CWindowCreateCriticalSectionLock()1405 	CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
1406 	{ }
1407 #endif // (_ATL_VER >= 0x0700)
1408 
Lock()1409 	HRESULT Lock()
1410 	{
1411 #if (_ATL_VER >= 0x0700)
1412 		return m_cslock.Lock();
1413 #else // !(_ATL_VER >= 0x0700)
1414 		::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate);
1415 		return S_OK;
1416 #endif // !(_ATL_VER >= 0x0700)
1417 	}
1418 
Unlock()1419 	void Unlock()
1420 	{
1421 #if (_ATL_VER >= 0x0700)
1422 		m_cslock.Unlock();
1423 #else // !(_ATL_VER >= 0x0700)
1424 		::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate);
1425 #endif // !(_ATL_VER >= 0x0700)
1426 	}
1427 };
1428 
1429 
1430 ///////////////////////////////////////////////////////////////////////////////
1431 // CTempBuffer - helper class for stack allocations for ATL3
1432 
1433 #ifndef _WTL_STACK_ALLOC_THRESHOLD
1434   #define _WTL_STACK_ALLOC_THRESHOLD   512
1435 #endif
1436 
1437 #if (_ATL_VER >= 0x0700)
1438 
1439 using ATL::CTempBuffer;
1440 
1441 #else // !(_ATL_VER >= 0x0700)
1442 
1443 #ifndef SIZE_MAX
1444   #ifdef _WIN64
1445     #define SIZE_MAX _UI64_MAX
1446   #else
1447     #define SIZE_MAX UINT_MAX
1448   #endif
1449 #endif
1450 
1451 #pragma warning(push)
1452 #pragma warning(disable: 4284)   // warning for operator ->
1453 
1454 template<typename T, int t_nFixedBytes = 128>
1455 class CTempBuffer
1456 {
1457 public:
CTempBuffer()1458 	CTempBuffer() : m_p(NULL)
1459 	{
1460 	}
1461 
CTempBuffer(size_t nElements)1462 	CTempBuffer(size_t nElements) : m_p(NULL)
1463 	{
1464 		Allocate(nElements);
1465 	}
1466 
~CTempBuffer()1467 	~CTempBuffer()
1468 	{
1469 		if(m_p != reinterpret_cast<T*>(m_abFixedBuffer))
1470 			free(m_p);
1471 	}
1472 
1473 	operator T*() const
1474 	{
1475 		return m_p;
1476 	}
1477 
1478 	T* operator ->() const
1479 	{
1480 		ATLASSERT(m_p != NULL);
1481 		return m_p;
1482 	}
1483 
Allocate(size_t nElements)1484 	T* Allocate(size_t nElements)
1485 	{
1486 		ATLASSERT(nElements <= (SIZE_MAX / sizeof(T)));
1487 		return AllocateBytes(nElements * sizeof(T));
1488 	}
1489 
AllocateBytes(size_t nBytes)1490 	T* AllocateBytes(size_t nBytes)
1491 	{
1492 		ATLASSERT(m_p == NULL);
1493 		if(nBytes > t_nFixedBytes)
1494 			m_p = static_cast<T*>(malloc(nBytes));
1495 		else
1496 			m_p = reinterpret_cast<T*>(m_abFixedBuffer);
1497 
1498 		return m_p;
1499 	}
1500 
1501 private:
1502 	T* m_p;
1503 	BYTE m_abFixedBuffer[t_nFixedBytes];
1504 };
1505 
1506 #pragma warning(pop)
1507 
1508 #endif // !(_ATL_VER >= 0x0700)
1509 
1510 
1511 ///////////////////////////////////////////////////////////////////////////////
1512 // CAppModule - module class for an application
1513 
1514 class CAppModule : public ATL::CComModule
1515 {
1516 public:
1517 	DWORD m_dwMainThreadID;
1518 	ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
1519 	ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;
1520 
1521 // Overrides of CComModule::Init and Term
1522 	HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
1523 	{
1524 		HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
1525 		if(FAILED(hRet))
1526 			return hRet;
1527 
1528 		m_dwMainThreadID = ::GetCurrentThreadId();
1529 		typedef ATL::CSimpleMap<DWORD, CMessageLoop*>   _mapClass;
1530 		m_pMsgLoopMap = NULL;
1531 		ATLTRY(m_pMsgLoopMap = new _mapClass);
1532 		if(m_pMsgLoopMap == NULL)
1533 			return E_OUTOFMEMORY;
1534 		m_pSettingChangeNotify = NULL;
1535 
1536 		return hRet;
1537 	}
1538 
Term()1539 	void Term()
1540 	{
1541 		TermSettingChangeNotify();
1542 		delete m_pMsgLoopMap;
1543 		CComModule::Term();
1544 	}
1545 
1546 // Message loop map methods
AddMessageLoop(CMessageLoop * pMsgLoop)1547 	BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
1548 	{
1549 		CStaticDataInitCriticalSectionLock lock;
1550 		if(FAILED(lock.Lock()))
1551 		{
1552 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
1553 			ATLASSERT(FALSE);
1554 			return FALSE;
1555 		}
1556 
1557 		ATLASSERT(pMsgLoop != NULL);
1558 		ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL);   // not in map yet
1559 
1560 		BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
1561 
1562 		lock.Unlock();
1563 
1564 		return bRet;
1565 	}
1566 
RemoveMessageLoop()1567 	BOOL RemoveMessageLoop()
1568 	{
1569 		CStaticDataInitCriticalSectionLock lock;
1570 		if(FAILED(lock.Lock()))
1571 		{
1572 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
1573 			ATLASSERT(FALSE);
1574 			return FALSE;
1575 		}
1576 
1577 		BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());
1578 
1579 		lock.Unlock();
1580 
1581 		return bRet;
1582 	}
1583 
1584 	CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
1585 	{
1586 		CStaticDataInitCriticalSectionLock lock;
1587 		if(FAILED(lock.Lock()))
1588 		{
1589 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
1590 			ATLASSERT(FALSE);
1591 			return NULL;
1592 		}
1593 
1594 		CMessageLoop* pLoop =  m_pMsgLoopMap->Lookup(dwThreadID);
1595 
1596 		lock.Unlock();
1597 
1598 		return pLoop;
1599 	}
1600 
1601 // Setting change notify methods
1602 	// Note: Call this from the main thread for MSDI apps
1603 	BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
1604 	{
1605 		CStaticDataInitCriticalSectionLock lock;
1606 		if(FAILED(lock.Lock()))
1607 		{
1608 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
1609 			ATLASSERT(FALSE);
1610 			return FALSE;
1611 		}
1612 
1613 		if(m_pSettingChangeNotify == NULL)
1614 		{
1615 			typedef ATL::CSimpleArray<HWND>   _notifyClass;
1616 			ATLTRY(m_pSettingChangeNotify = new _notifyClass);
1617 			ATLASSERT(m_pSettingChangeNotify != NULL);
1618 		}
1619 
1620 		BOOL bRet = (m_pSettingChangeNotify != NULL);
1621 		if(bRet && m_pSettingChangeNotify->GetSize() == 0)
1622 		{
1623 			// init everything
1624 			_ATL_EMPTY_DLGTEMPLATE templ;
1625 			HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
1626 			ATLASSERT(::IsWindow(hNtfWnd));
1627 			if(::IsWindow(hNtfWnd))
1628 			{
1629 // need conditional code because types don't match in winuser.h
1630 #ifdef _WIN64
1631 				::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
1632 #else
1633 				::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
1634 #endif
1635 				bRet = m_pSettingChangeNotify->Add(hNtfWnd);
1636 			}
1637 			else
1638 			{
1639 				bRet = FALSE;
1640 			}
1641 		}
1642 
1643 		lock.Unlock();
1644 
1645 		return bRet;
1646 	}
1647 
TermSettingChangeNotify()1648 	void TermSettingChangeNotify()
1649 	{
1650 		CStaticDataInitCriticalSectionLock lock;
1651 		if(FAILED(lock.Lock()))
1652 		{
1653 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
1654 			ATLASSERT(FALSE);
1655 			return;
1656 		}
1657 
1658 		if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
1659 			::DestroyWindow((*m_pSettingChangeNotify)[0]);
1660 		delete m_pSettingChangeNotify;
1661 		m_pSettingChangeNotify = NULL;
1662 
1663 		lock.Unlock();
1664 	}
1665 
AddSettingChangeNotify(HWND hWnd)1666 	BOOL AddSettingChangeNotify(HWND hWnd)
1667 	{
1668 		CStaticDataInitCriticalSectionLock lock;
1669 		if(FAILED(lock.Lock()))
1670 		{
1671 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
1672 			ATLASSERT(FALSE);
1673 			return FALSE;
1674 		}
1675 
1676 		ATLASSERT(::IsWindow(hWnd));
1677 		BOOL bRet = FALSE;
1678 		if(InitSettingChangeNotify() != FALSE)
1679 			bRet = m_pSettingChangeNotify->Add(hWnd);
1680 
1681 		lock.Unlock();
1682 
1683 		return bRet;
1684 	}
1685 
RemoveSettingChangeNotify(HWND hWnd)1686 	BOOL RemoveSettingChangeNotify(HWND hWnd)
1687 	{
1688 		CStaticDataInitCriticalSectionLock lock;
1689 		if(FAILED(lock.Lock()))
1690 		{
1691 			ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
1692 			ATLASSERT(FALSE);
1693 			return FALSE;
1694 		}
1695 
1696 		BOOL bRet = FALSE;
1697 		if(m_pSettingChangeNotify != NULL)
1698 			bRet = m_pSettingChangeNotify->Remove(hWnd);
1699 
1700 		lock.Unlock();
1701 
1702 		return bRet;
1703 	}
1704 
1705 // Implementation - setting change notify dialog template and dialog procedure
1706 	struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
1707 	{
_ATL_EMPTY_DLGTEMPLATE_ATL_EMPTY_DLGTEMPLATE1708 		_ATL_EMPTY_DLGTEMPLATE()
1709 		{
1710 			memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
1711 			style = WS_POPUP;
1712 		}
1713 		WORD wMenu, wClass, wTitle;
1714 	};
1715 
1716 #ifdef _WIN64
_SettingChangeDlgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1717 	static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1718 #else
1719 	static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1720 #endif
1721 	{
1722 		if(uMsg == WM_SETTINGCHANGE)
1723 		{
1724 // need conditional code because types don't match in winuser.h
1725 #ifdef _WIN64
1726 			CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
1727 #else
1728 			CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
1729 #endif
1730 			ATLASSERT(pModule != NULL);
1731 			ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
1732 			const UINT uTimeout = 1500;   // ms
1733 			for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
1734 			{
1735 #if !defined(_WIN32_WCE)
1736 				::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
1737 #elif(_WIN32_WCE >= 400) // CE specific
1738 				::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL);
1739 #else // _WIN32_WCE < 400 specific
1740 				uTimeout;
1741 				::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam);
1742 #endif
1743 			}
1744 			return TRUE;
1745 		}
1746 		return FALSE;
1747 	}
1748 };
1749 
1750 
1751 ///////////////////////////////////////////////////////////////////////////////
1752 // CServerAppModule - module class for a COM server application
1753 
1754 class CServerAppModule : public CAppModule
1755 {
1756 public:
1757 	HANDLE m_hEventShutdown;
1758 	bool m_bActivity;
1759 	DWORD m_dwTimeOut;
1760 	DWORD m_dwPause;
1761 
1762 // Override of CAppModule::Init
1763 	HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
1764 	{
1765 		m_dwTimeOut = 5000;
1766 		m_dwPause = 1000;
1767 		return CAppModule::Init(pObjMap, hInstance, pLibID);
1768 	}
1769 
Term()1770 	void Term()
1771 	{
1772 		if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))
1773 			m_hEventShutdown = NULL;
1774 		CAppModule::Term();
1775 	}
1776 
1777 // COM Server methods
1778 #if (_MSC_VER >= 1300)
Unlock()1779 	LONG Unlock() throw()
1780 #else
1781 	LONG Unlock()
1782 #endif
1783 	{
1784 		LONG lRet = CComModule::Unlock();
1785 		if(lRet == 0)
1786 		{
1787 			m_bActivity = true;
1788 			::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
1789 		}
1790 		return lRet;
1791 	}
1792 
MonitorShutdown()1793 	void MonitorShutdown()
1794 	{
1795 		for(;;)
1796 		{
1797 			::WaitForSingleObject(m_hEventShutdown, INFINITE);
1798 			DWORD dwWait = 0;
1799 			do
1800 			{
1801 				m_bActivity = false;
1802 				dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
1803 			}
1804 			while(dwWait == WAIT_OBJECT_0);
1805 			// timed out
1806 			if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail
1807 			{
1808 #if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE)
1809 				::CoSuspendClassObjects();
1810 				if(!m_bActivity && m_nLockCnt == 0)
1811 #endif
1812 					break;
1813 			}
1814 		}
1815 		// This handle should be valid now. If it isn't,
1816 		// check if _Module.Term was called first (it shouldn't)
1817 		if(::CloseHandle(m_hEventShutdown))
1818 			m_hEventShutdown = NULL;
1819 		::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
1820 	}
1821 
StartMonitor()1822 	bool StartMonitor()
1823 	{
1824 		m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
1825 		if(m_hEventShutdown == NULL)
1826 			return false;
1827 		DWORD dwThreadID = 0;
1828 #if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
1829 		HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
1830 #else
1831 		HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
1832 #endif
1833 		bool bRet = (hThread != NULL);
1834 		if(bRet)
1835 			::CloseHandle(hThread);
1836 		return bRet;
1837 	}
1838 
MonitorProc(void * pv)1839 	static DWORD WINAPI MonitorProc(void* pv)
1840 	{
1841 		CServerAppModule* p = (CServerAppModule*)pv;
1842 		p->MonitorShutdown();
1843 		return 0;
1844 	}
1845 
1846 #if (_ATL_VER < 0x0700)
1847 	// search for an occurence of string p2 in string p1
FindOneOf(LPCTSTR p1,LPCTSTR p2)1848 	static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
1849 	{
1850 		while(p1 != NULL && *p1 != NULL)
1851 		{
1852 			LPCTSTR p = p2;
1853 			while(p != NULL && *p != NULL)
1854 			{
1855 				if(*p1 == *p)
1856 					return ::CharNext(p1);
1857 				p = ::CharNext(p);
1858 			}
1859 			p1 = ::CharNext(p1);
1860 		}
1861 		return NULL;
1862 	}
1863 #endif // (_ATL_VER < 0x0700)
1864 };
1865 
1866 
1867 ///////////////////////////////////////////////////////////////////////////////
1868 // CRegKeyEx - adds type-specific methods to ATL3 CRegKey
1869 
1870 #if (_ATL_VER < 0x0700)
1871 
1872 class CRegKeyEx : public ATL::CRegKey
1873 {
1874 public:
1875 // Constructors and operators
1876 	CRegKeyEx(HKEY hKey = NULL)
1877 	{
1878 		m_hKey = hKey;
1879 	}
1880 
CRegKeyEx(CRegKeyEx & key)1881 	CRegKeyEx(CRegKeyEx& key)
1882 	{
1883 		Attach(key.Detach());
1884 	}
1885 
1886 	CRegKeyEx& operator =(CRegKeyEx& key)
1887 	{
1888 		Close();
1889 		Attach(key.Detach());
1890 		return *this;
1891 	}
1892 
1893 // Methods
SetValue(LPCTSTR pszValueName,DWORD dwType,const void * pValue,ULONG nBytes)1894 	LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes)
1895 	{
1896 		ATLASSERT(m_hKey != NULL);
1897 		return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast<const BYTE*>(pValue), nBytes);
1898 	}
1899 
SetGUIDValue(LPCTSTR pszValueName,REFGUID guidValue)1900 	LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue)
1901 	{
1902 		ATLASSERT(m_hKey != NULL);
1903 
1904 		OLECHAR szGUID[64] = { 0 };
1905 		::StringFromGUID2(guidValue, szGUID, 64);
1906 
1907 		USES_CONVERSION;
1908 		LPCTSTR lpstr = OLE2CT(szGUID);
1909 #ifndef _UNICODE
1910 		if(lpstr == NULL)
1911 			return E_OUTOFMEMORY;
1912 #endif
1913 		return SetStringValue(pszValueName, lpstr);
1914 	}
1915 
SetBinaryValue(LPCTSTR pszValueName,const void * pValue,ULONG nBytes)1916 	LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes)
1917 	{
1918 		ATLASSERT(m_hKey != NULL);
1919 		return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_BINARY, reinterpret_cast<const BYTE*>(pValue), nBytes);
1920 	}
1921 
SetDWORDValue(LPCTSTR pszValueName,DWORD dwValue)1922 	LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue)
1923 	{
1924 		ATLASSERT(m_hKey != NULL);
1925 		return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast<const BYTE*>(&dwValue), sizeof(DWORD));
1926 	}
1927 
1928 #ifndef _WIN32_WCE
SetQWORDValue(LPCTSTR pszValueName,ULONGLONG qwValue)1929 	LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue)
1930 	{
1931 		ATLASSERT(m_hKey != NULL);
1932 		return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_QWORD, reinterpret_cast<const BYTE*>(&qwValue), sizeof(ULONGLONG));
1933 	}
1934 #endif
1935 
1936 	LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ)
1937 	{
1938 		ATLASSERT(m_hKey != NULL);
1939 		if(pszValue == NULL)
1940 		{
1941 			ATLASSERT(FALSE);
1942 			return ERROR_INVALID_DATA;
1943 		}
1944 		ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ));
1945 
1946 		return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast<const BYTE*>(pszValue), (lstrlen(pszValue) + 1) * sizeof(TCHAR));
1947 	}
1948 
SetMultiStringValue(LPCTSTR pszValueName,LPCTSTR pszValue)1949 	LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue)
1950 	{
1951 		ATLASSERT(m_hKey != NULL);
1952 		if(pszValue == NULL)
1953 		{
1954 			ATLASSERT(FALSE);
1955 			return ERROR_INVALID_DATA;
1956 		}
1957 
1958 		ULONG nBytes = 0;
1959 		ULONG nLength = 0;
1960 		LPCTSTR pszTemp = pszValue;
1961 		do
1962 		{
1963 			nLength = lstrlen(pszTemp) + 1;
1964 			pszTemp += nLength;
1965 			nBytes += nLength * sizeof(TCHAR);
1966 		} while (nLength != 1);
1967 
1968 		return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast<const BYTE*>(pszValue), nBytes);
1969 	}
1970 
QueryValue(LPCTSTR pszValueName,DWORD * pdwType,void * pData,ULONG * pnBytes)1971 	LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes)
1972 	{
1973 		ATLASSERT(m_hKey != NULL);
1974 		return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast<LPBYTE>(pData), pnBytes);
1975 	}
1976 
QueryGUIDValue(LPCTSTR pszValueName,GUID & guidValue)1977 	LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue)
1978 	{
1979 		ATLASSERT(m_hKey != NULL);
1980 
1981 		guidValue = GUID_NULL;
1982 
1983 		TCHAR szGUID[64] = { 0 };
1984 		ULONG nCount = 64;
1985 		LONG lRes = QueryStringValue(pszValueName, szGUID, &nCount);
1986 
1987 		if (lRes != ERROR_SUCCESS)
1988 			return lRes;
1989 
1990 		if(szGUID[0] != _T('{'))
1991 			return ERROR_INVALID_DATA;
1992 
1993 		USES_CONVERSION;
1994 		LPOLESTR lpstr = T2OLE(szGUID);
1995 #ifndef _UNICODE
1996 		if(lpstr == NULL)
1997 			return E_OUTOFMEMORY;
1998 #endif
1999 
2000 		HRESULT hr = ::CLSIDFromString(lpstr, &guidValue);
2001 		if (FAILED(hr))
2002 			return ERROR_INVALID_DATA;
2003 
2004 		return ERROR_SUCCESS;
2005 	}
2006 
QueryBinaryValue(LPCTSTR pszValueName,void * pValue,ULONG * pnBytes)2007 	LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes)
2008 	{
2009 		ATLASSERT(pnBytes != NULL);
2010 		ATLASSERT(m_hKey != NULL);
2011 
2012 		DWORD dwType = 0;
2013 		LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pValue), pnBytes);
2014 		if (lRes != ERROR_SUCCESS)
2015 			return lRes;
2016 		if (dwType != REG_BINARY)
2017 			return ERROR_INVALID_DATA;
2018 
2019 		return ERROR_SUCCESS;
2020 	}
2021 
QueryDWORDValue(LPCTSTR pszValueName,DWORD & dwValue)2022 	LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue)
2023 	{
2024 		ATLASSERT(m_hKey != NULL);
2025 
2026 		ULONG nBytes = sizeof(DWORD);
2027 		DWORD dwType = 0;
2028 		LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(&dwValue), &nBytes);
2029 		if (lRes != ERROR_SUCCESS)
2030 			return lRes;
2031 		if (dwType != REG_DWORD)
2032 			return ERROR_INVALID_DATA;
2033 
2034 		return ERROR_SUCCESS;
2035 	}
2036 
2037 #ifndef _WIN32_WCE
QueryQWORDValue(LPCTSTR pszValueName,ULONGLONG & qwValue)2038 	LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue)
2039 	{
2040 		ATLASSERT(m_hKey != NULL);
2041 
2042 		ULONG nBytes = sizeof(ULONGLONG);
2043 		DWORD dwType = 0;
2044 		LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(&qwValue), &nBytes);
2045 		if (lRes != ERROR_SUCCESS)
2046 			return lRes;
2047 		if (dwType != REG_QWORD)
2048 			return ERROR_INVALID_DATA;
2049 
2050 		return ERROR_SUCCESS;
2051 	}
2052 #endif
2053 
QueryStringValue(LPCTSTR pszValueName,LPTSTR pszValue,ULONG * pnChars)2054 	LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
2055 	{
2056 		ATLASSERT(m_hKey != NULL);
2057 		ATLASSERT(pnChars != NULL);
2058 
2059 		ULONG nBytes = (*pnChars) * sizeof(TCHAR);
2060 		DWORD dwType = 0;
2061 		*pnChars = 0;
2062 		LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pszValue), &nBytes);
2063 
2064 		if (lRes != ERROR_SUCCESS)
2065 		{
2066 			return lRes;
2067 		}
2068 
2069 		if(dwType != REG_SZ && dwType != REG_EXPAND_SZ)
2070 		{
2071 			return ERROR_INVALID_DATA;
2072 		}
2073 
2074 		if (pszValue != NULL)
2075 		{
2076 			if(nBytes != 0)
2077 			{
2078 				if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0))
2079 					return ERROR_INVALID_DATA;
2080 			}
2081 			else
2082 			{
2083 				pszValue[0] = _T('\0');
2084 			}
2085 		}
2086 
2087 		*pnChars = nBytes / sizeof(TCHAR);
2088 
2089 		return ERROR_SUCCESS;
2090 	}
2091 
QueryMultiStringValue(LPCTSTR pszValueName,LPTSTR pszValue,ULONG * pnChars)2092 	LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
2093 	{
2094 		ATLASSERT(m_hKey != NULL);
2095 		ATLASSERT(pnChars != NULL);
2096 
2097 		if (pszValue != NULL && *pnChars < 2)
2098 			return ERROR_INSUFFICIENT_BUFFER;
2099 
2100 		ULONG nBytes = (*pnChars) * sizeof(TCHAR);
2101 		DWORD dwType = 0;
2102 		*pnChars = 0;
2103 		LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pszValue), &nBytes);
2104 		if (lRes != ERROR_SUCCESS)
2105 			return lRes;
2106 		if (dwType != REG_MULTI_SZ)
2107 			return ERROR_INVALID_DATA;
2108 		if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || nBytes / sizeof(TCHAR) < 1 || pszValue[nBytes / sizeof(TCHAR) - 1] != 0 || ((nBytes / sizeof(TCHAR)) > 1 && pszValue[nBytes / sizeof(TCHAR) - 2] != 0)))
2109 			return ERROR_INVALID_DATA;
2110 
2111 		*pnChars = nBytes / sizeof(TCHAR);
2112 
2113 		return ERROR_SUCCESS;
2114 	}
2115 };
2116 
2117 #else // !(_ATL_VER < 0x0700)
2118 
2119 typedef ATL::CRegKey CRegKeyEx;
2120 
2121 #endif // !(_ATL_VER < 0x0700)
2122 
2123 
2124 ///////////////////////////////////////////////////////////////////////////////
2125 // CString forward reference (enables CString use in atluser.h and atlgdi.h)
2126 
2127 #if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
2128   #define _WTL_USE_CSTRING
2129 #endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
2130 
2131 #ifdef _WTL_USE_CSTRING
2132   class CString;   // forward declaration (include atlmisc.h for the whole class)
2133 #endif // _WTL_USE_CSTRING
2134 
2135 // CString namespace
2136 #ifndef _CSTRING_NS
2137   #ifdef __ATLSTR_H__
2138     #define _CSTRING_NS	ATL
2139   #else
2140     #define _CSTRING_NS	WTL
2141   #endif
2142 #endif // _CSTRING_NS
2143 
2144 // Type classes namespace
2145 #ifndef _WTYPES_NS
2146   #ifdef __ATLTYPES_H__
2147     #define _WTYPES_NS
2148   #else
2149     #define _WTYPES_NS	WTL
2150   #endif
2151 #endif // _WTYPES_NS
2152 
2153 }; // namespace WTL
2154 
2155 
2156 ///////////////////////////////////////////////////////////////////////////////
2157 // General DLL version helpers
2158 // (ATL3: excluded from atlbase.h if _ATL_DLL is defined; ATL11: removed)
2159 
2160 #if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
2161 
2162 namespace ATL
2163 {
2164 
AtlGetDllVersion(HINSTANCE hInstDLL,DLLVERSIONINFO * pDllVersionInfo)2165 inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
2166 {
2167 	ATLASSERT(pDllVersionInfo != NULL);
2168 	if(pDllVersionInfo == NULL)
2169 		return E_INVALIDARG;
2170 
2171 	// We must get this function explicitly because some DLLs don't implement it.
2172 	DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
2173 	if(pfnDllGetVersion == NULL)
2174 		return E_NOTIMPL;
2175 
2176 	return (*pfnDllGetVersion)(pDllVersionInfo);
2177 }
2178 
AtlGetDllVersion(LPCTSTR lpstrDllName,DLLVERSIONINFO * pDllVersionInfo)2179 inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
2180 {
2181 	HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
2182 	if(hInstDLL == NULL)
2183 		return E_FAIL;
2184 	HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
2185 	::FreeLibrary(hInstDLL);
2186 	return hRet;
2187 }
2188 
2189 // Common Control Versions:
2190 //   Win95/WinNT 4.0    maj=4 min=00
2191 //   IE 3.x     maj=4 min=70
2192 //   IE 4.0     maj=4 min=71
AtlGetCommCtrlVersion(LPDWORD pdwMajor,LPDWORD pdwMinor)2193 inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
2194 {
2195 	ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
2196 	if(pdwMajor == NULL || pdwMinor == NULL)
2197 		return E_INVALIDARG;
2198 
2199 	DLLVERSIONINFO dvi;
2200 	::ZeroMemory(&dvi, sizeof(dvi));
2201 	dvi.cbSize = sizeof(dvi);
2202 	HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);
2203 
2204 	if(SUCCEEDED(hRet))
2205 	{
2206 		*pdwMajor = dvi.dwMajorVersion;
2207 		*pdwMinor = dvi.dwMinorVersion;
2208 	}
2209 	else if(hRet == E_NOTIMPL)
2210 	{
2211 		// If DllGetVersion is not there, then the DLL is a version
2212 		// previous to the one shipped with IE 3.x
2213 		*pdwMajor = 4;
2214 		*pdwMinor = 0;
2215 		hRet = S_OK;
2216 	}
2217 
2218 	return hRet;
2219 }
2220 
2221 // Shell Versions:
2222 //   Win95/WinNT 4.0                    maj=4 min=00
2223 //   IE 3.x, IE 4.0 without Web Integrated Desktop  maj=4 min=00
2224 //   IE 4.0 with Web Integrated Desktop         maj=4 min=71
2225 //   IE 4.01 with Web Integrated Desktop        maj=4 min=72
AtlGetShellVersion(LPDWORD pdwMajor,LPDWORD pdwMinor)2226 inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
2227 {
2228 	ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
2229 	if(pdwMajor == NULL || pdwMinor == NULL)
2230 		return E_INVALIDARG;
2231 
2232 	DLLVERSIONINFO dvi;
2233 	::ZeroMemory(&dvi, sizeof(dvi));
2234 	dvi.cbSize = sizeof(dvi);
2235 	HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);
2236 
2237 	if(SUCCEEDED(hRet))
2238 	{
2239 		*pdwMajor = dvi.dwMajorVersion;
2240 		*pdwMinor = dvi.dwMinorVersion;
2241 	}
2242 	else if(hRet == E_NOTIMPL)
2243 	{
2244 		// If DllGetVersion is not there, then the DLL is a version
2245 		// previous to the one shipped with IE 4.x
2246 		*pdwMajor = 4;
2247 		*pdwMinor = 0;
2248 		hRet = S_OK;
2249 	}
2250 
2251 	return hRet;
2252 }
2253 
2254 }; // namespace ATL
2255 
2256 #endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)
2257 
2258 
2259 // These are always included
2260 #include "atlwinx.h"
2261 #include "atluser.h"
2262 #include "atlgdi.h"
2263 
2264 #ifndef _WTL_NO_AUTOMATIC_NAMESPACE
2265 using namespace WTL;
2266 #endif // !_WTL_NO_AUTOMATIC_NAMESPACE
2267 
2268 #endif // __ATLAPP_H__
2269