]> git.sesse.net Git - casparcg/blob - WTL80/include/atlapp.h
2.0.2: INFO TEMPLATE works on both compressed and uncompressed templates.
[casparcg] / WTL80 / include / atlapp.h
1 // Windows Template Library - WTL version 8.0\r
2 // Copyright (C) Microsoft Corporation. All rights reserved.\r
3 //\r
4 // This file is a part of the Windows Template Library.\r
5 // The use and distribution terms for this software are covered by the\r
6 // Common Public License 1.0 (http://opensource.org/osi3.0/licenses/cpl1.0.php)\r
7 // which can be found in the file CPL.TXT at the root of this distribution.\r
8 // By using this software in any fashion, you are agreeing to be bound by\r
9 // the terms of this license. You must not remove this notice, or\r
10 // any other, from this software.\r
11 \r
12 #ifndef __ATLAPP_H__\r
13 #define __ATLAPP_H__\r
14 \r
15 #pragma once\r
16 \r
17 #ifndef __cplusplus\r
18         #error ATL requires C++ compilation (use a .cpp suffix)\r
19 #endif\r
20 \r
21 #ifndef __ATLBASE_H__\r
22         #error atlapp.h requires atlbase.h to be included first\r
23 #endif\r
24 \r
25 #ifndef _WIN32_WCE\r
26   #if (WINVER < 0x0400)\r
27         #error WTL requires Windows version 4.0 or higher\r
28   #endif\r
29 \r
30   #if (_WIN32_IE < 0x0300)\r
31         #error WTL requires IE version 3.0 or higher\r
32   #endif\r
33 #endif\r
34 \r
35 #ifdef _ATL_NO_COMMODULE\r
36         #error WTL requires that _ATL_NO_COMMODULE is not defined\r
37 #endif // _ATL_NO_COMMODULE\r
38 \r
39 #if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)\r
40         #pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT")\r
41 #endif // defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)\r
42 \r
43 #include <limits.h>\r
44 #if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)\r
45   #include <process.h>  // for _beginthreadex\r
46 #endif\r
47 \r
48 #if (_ATL_VER < 0x0800) && !defined(_DEBUG)\r
49   #include <stdio.h>\r
50 #endif\r
51 \r
52 #include <commctrl.h>\r
53 #ifndef _WIN32_WCE\r
54 #pragma comment(lib, "comctl32.lib")\r
55 #endif // !_WIN32_WCE\r
56 \r
57 #ifndef _WIN32_WCE\r
58   #include "atlres.h"\r
59 #else // CE specific\r
60   #include "atlresce.h"\r
61 #endif // _WIN32_WCE\r
62 \r
63 // We need to disable this warning because of template class arguments\r
64 #pragma warning(disable: 4127)\r
65 \r
66 \r
67 ///////////////////////////////////////////////////////////////////////////////\r
68 // WTL version number\r
69 \r
70 #define _WTL_VER        0x0800\r
71 \r
72 \r
73 ///////////////////////////////////////////////////////////////////////////////\r
74 // Classes in this file:\r
75 //\r
76 // CMessageFilter\r
77 // CIdleHandler\r
78 // CMessageLoop\r
79 //\r
80 // CAppModule\r
81 // CServerAppModule\r
82 //\r
83 // Global functions:\r
84 //   AtlGetDefaultGuiFont()\r
85 //   AtlCreateBoldFont()\r
86 //   AtlInitCommonControls()\r
87 \r
88 \r
89 ///////////////////////////////////////////////////////////////////////////////\r
90 // Global support for Windows CE\r
91 \r
92 #ifdef _WIN32_WCE\r
93 \r
94 #ifndef SW_SHOWDEFAULT\r
95   #define SW_SHOWDEFAULT        SW_SHOWNORMAL\r
96 #endif // !SW_SHOWDEFAULT\r
97 \r
98 // These get's OR-ed in a constant and will have no effect.\r
99 // Defining them reduces the number of #ifdefs required for CE.\r
100 #define LR_DEFAULTSIZE      0\r
101 #define LR_LOADFROMFILE     0\r
102 \r
103 #ifndef SM_CXCURSOR\r
104   #define SM_CXCURSOR             13\r
105 #endif\r
106 #ifndef SM_CYCURSOR\r
107   #define SM_CYCURSOR             14\r
108 #endif\r
109 \r
110 inline BOOL IsMenu(HMENU hMenu)\r
111 {\r
112         MENUITEMINFO mii = { sizeof(MENUITEMINFO) };\r
113         ::SetLastError(0);\r
114         BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii);\r
115         if(!bRet)\r
116                 bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE;\r
117         return bRet;\r
118 }\r
119 \r
120 #if (_WIN32_WCE >= 410)\r
121 extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight);\r
122 #endif // (_WIN32_WCE >= 410)\r
123 \r
124 inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator)\r
125 {\r
126         __int64 multiple = nNumber * nNumerator;\r
127         return static_cast<int>(multiple / nDenominator);\r
128 }\r
129 \r
130 #if (_ATL_VER >= 0x0800)\r
131 \r
132 #ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW\r
133   #ifdef WS_OVERLAPPEDWINDOW\r
134     #undef WS_OVERLAPPEDWINDOW\r
135     #define WS_OVERLAPPEDWINDOW 0\r
136   #endif // WS_OVERLAPPEDWINDOW\r
137 #endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW\r
138 \r
139 #ifndef RDW_FRAME\r
140   #define RDW_FRAME     0\r
141 #endif // !RDW_FRAME\r
142 \r
143 #ifndef WM_WINDOWPOSCHANGING\r
144   #define WM_WINDOWPOSCHANGING  0\r
145 #endif // !WM_WINDOWPOSCHANGING\r
146 \r
147 #define FreeResource(x)\r
148 #define UnlockResource(x)\r
149 \r
150 namespace ATL\r
151 {\r
152   inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw()\r
153   { return E_NOTIMPL; }\r
154   inline HRESULT CComModule::RevokeClassObjects() throw()\r
155   { return E_NOTIMPL; }\r
156 }; // namespace ATL\r
157 \r
158 #ifndef lstrlenW\r
159   #define lstrlenW      (int)ATL::lstrlenW\r
160 #endif // lstrlenW\r
161 \r
162 inline int WINAPI lstrlenA(LPCSTR lpszString)\r
163 { return ATL::lstrlenA(lpszString); }\r
164 \r
165 #ifdef lstrcpyn\r
166   #undef lstrcpyn\r
167   #define lstrcpyn      ATL::lstrcpynW\r
168 #endif // lstrcpyn\r
169 \r
170 #ifndef SetWindowLongPtrW\r
171   inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )\r
172   {\r
173         return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );\r
174   }\r
175   #define SetWindowLongPtrW tmp_SetWindowLongPtrW\r
176 #endif\r
177 \r
178 #ifndef GetWindowLongPtrW\r
179   inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex )\r
180   {\r
181         return( ::GetWindowLongW( hWnd, nIndex ) );\r
182   }\r
183   #define GetWindowLongPtrW tmp_GetWindowLongPtrW\r
184 #endif\r
185 \r
186 #ifndef LongToPtr\r
187   #define LongToPtr(x) ((void*)x)\r
188 #endif\r
189 \r
190 #ifndef PtrToInt\r
191   #define PtrToInt( p ) ((INT)(INT_PTR) (p) )\r
192 #endif\r
193 \r
194 #else // !(_ATL_VER >= 0x0800)\r
195 \r
196 #ifdef lstrlenW\r
197   #undef lstrlenW\r
198   #define lstrlenW (int)::wcslen\r
199 #endif // lstrlenW\r
200 \r
201 #define lstrlenA (int)strlen\r
202 \r
203 #ifndef lstrcpyn\r
204   inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)\r
205   {\r
206         if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)\r
207                 return NULL;\r
208         int nLen = min(lstrlen(lpstrSrc), nLength - 1);\r
209         LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));\r
210         lpstrDest[nLen] = 0;\r
211         return lpstrRet;\r
212   }\r
213 #endif // !lstrcpyn\r
214 \r
215 #ifndef lstrcpynW\r
216   inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength)\r
217   {\r
218         return lstrcpyn(lpstrDest, lpstrSrc, nLength);   // WinCE is Unicode only\r
219   }\r
220 #endif // !lstrcpynW\r
221 \r
222 #ifndef lstrcpynA\r
223   inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength)\r
224   {\r
225         if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)\r
226                 return NULL;\r
227         int nLen = min(lstrlenA(lpstrSrc), nLength - 1);\r
228         LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char));\r
229         lpstrDest[nLen] = 0;\r
230         return lpstrRet;\r
231   }\r
232 #endif // !lstrcpyn\r
233 \r
234 #ifdef TrackPopupMenu\r
235   #undef TrackPopupMenu\r
236 #endif // TrackPopupMenu\r
237 \r
238 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \\r
239 static CWndClassInfo& GetWndClassInfo() \\r
240 { \\r
241         static CWndClassInfo wc = \\r
242         { \\r
243                 { style, StartWindowProc, \\r
244                   0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \\r
245                 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \\r
246         }; \\r
247         return wc; \\r
248 }\r
249 \r
250 #ifndef _MAX_FNAME\r
251   #define _MAX_FNAME    _MAX_PATH\r
252 #endif // _MAX_FNAME\r
253 \r
254 #if (_WIN32_WCE < 400)\r
255   #define MAKEINTATOM(i)  (LPTSTR)((ULONG_PTR)((WORD)(i)))\r
256 #endif // (_WIN32_WCE < 400)\r
257 \r
258 #if (_WIN32_WCE < 410)\r
259   #define WHEEL_PAGESCROLL                (UINT_MAX)\r
260   #define WHEEL_DELTA                     120\r
261 #endif // (_WIN32_WCE < 410)\r
262 \r
263 #ifdef DrawIcon\r
264   #undef DrawIcon\r
265 #endif\r
266 \r
267 #ifndef VARCMP_LT\r
268   #define VARCMP_LT   0\r
269 #endif\r
270 #ifndef VARCMP_EQ\r
271   #define VARCMP_EQ   1\r
272 #endif\r
273 #ifndef VARCMP_GT\r
274   #define VARCMP_GT   2\r
275 #endif\r
276 #ifndef VARCMP_NULL\r
277   #define VARCMP_NULL 3\r
278 #endif\r
279 \r
280 #ifndef RDW_ALLCHILDREN\r
281   #define RDW_ALLCHILDREN   0\r
282 #endif\r
283 \r
284 #endif // !(_ATL_VER >= 0x0800)\r
285 \r
286 #endif // _WIN32_WCE\r
287 \r
288 \r
289 ///////////////////////////////////////////////////////////////////////////////\r
290 // Global support for using original VC++ 6.0 headers with WTL\r
291 \r
292 #ifndef _ATL_NO_OLD_HEADERS_WIN64\r
293 #if !defined(_WIN64) && (_ATL_VER < 0x0700)\r
294 \r
295   #ifndef PSM_INSERTPAGE\r
296     #define PSM_INSERTPAGE          (WM_USER + 119)\r
297   #endif // !PSM_INSERTPAGE\r
298 \r
299   #ifndef GetClassLongPtr\r
300     #define GetClassLongPtrA   GetClassLongA\r
301     #define GetClassLongPtrW   GetClassLongW\r
302     #ifdef UNICODE\r
303       #define GetClassLongPtr  GetClassLongPtrW\r
304     #else\r
305       #define GetClassLongPtr  GetClassLongPtrA\r
306     #endif // !UNICODE\r
307   #endif // !GetClassLongPtr\r
308 \r
309   #ifndef GCLP_HICONSM\r
310     #define GCLP_HICONSM        (-34)\r
311   #endif // !GCLP_HICONSM\r
312 \r
313   #ifndef GetWindowLongPtr\r
314     #define GetWindowLongPtrA   GetWindowLongA\r
315     #define GetWindowLongPtrW   GetWindowLongW\r
316     #ifdef UNICODE\r
317       #define GetWindowLongPtr  GetWindowLongPtrW\r
318     #else\r
319       #define GetWindowLongPtr  GetWindowLongPtrA\r
320     #endif // !UNICODE\r
321   #endif // !GetWindowLongPtr\r
322 \r
323   #ifndef SetWindowLongPtr\r
324     #define SetWindowLongPtrA   SetWindowLongA\r
325     #define SetWindowLongPtrW   SetWindowLongW\r
326     #ifdef UNICODE\r
327       #define SetWindowLongPtr  SetWindowLongPtrW\r
328     #else\r
329       #define SetWindowLongPtr  SetWindowLongPtrA\r
330     #endif // !UNICODE\r
331   #endif // !SetWindowLongPtr\r
332 \r
333   #ifndef GWLP_WNDPROC\r
334     #define GWLP_WNDPROC        (-4)\r
335   #endif\r
336   #ifndef GWLP_HINSTANCE\r
337     #define GWLP_HINSTANCE      (-6)\r
338   #endif\r
339   #ifndef GWLP_HWNDPARENT\r
340     #define GWLP_HWNDPARENT     (-8)\r
341   #endif\r
342   #ifndef GWLP_USERDATA\r
343     #define GWLP_USERDATA       (-21)\r
344   #endif\r
345   #ifndef GWLP_ID\r
346     #define GWLP_ID             (-12)\r
347   #endif\r
348 \r
349   #ifndef DWLP_MSGRESULT\r
350     #define DWLP_MSGRESULT  0\r
351   #endif\r
352 \r
353   typedef long LONG_PTR;\r
354   typedef unsigned long ULONG_PTR;\r
355   typedef ULONG_PTR DWORD_PTR;\r
356 \r
357   #ifndef HandleToUlong\r
358     #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )\r
359   #endif\r
360   #ifndef HandleToLong\r
361     #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )\r
362   #endif\r
363   #ifndef LongToHandle\r
364     #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))\r
365   #endif\r
366   #ifndef PtrToUlong\r
367     #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )\r
368   #endif\r
369   #ifndef PtrToLong\r
370     #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )\r
371   #endif\r
372   #ifndef PtrToUint\r
373     #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )\r
374   #endif\r
375   #ifndef PtrToInt\r
376     #define PtrToInt( p ) ((INT)(INT_PTR) (p) )\r
377   #endif\r
378   #ifndef PtrToUshort\r
379     #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )\r
380   #endif\r
381   #ifndef PtrToShort\r
382     #define PtrToShort( p ) ((short)(LONG_PTR)(p) )\r
383   #endif\r
384   #ifndef IntToPtr\r
385     #define IntToPtr( i )    ((VOID *)(INT_PTR)((int)i))\r
386   #endif\r
387   #ifndef UIntToPtr\r
388     #define UIntToPtr( ui )  ((VOID *)(UINT_PTR)((unsigned int)ui))\r
389   #endif\r
390   #ifndef LongToPtr\r
391     #define LongToPtr( l )   ((VOID *)(LONG_PTR)((long)l))\r
392   #endif\r
393   #ifndef ULongToPtr\r
394     #define ULongToPtr( ul )  ((VOID *)(ULONG_PTR)((unsigned long)ul))\r
395   #endif\r
396 \r
397 #endif // !defined(_WIN64) && (_ATL_VER < 0x0700)\r
398 #endif // !_ATL_NO_OLD_HEADERS_WIN64\r
399 \r
400 \r
401 ///////////////////////////////////////////////////////////////////////////////\r
402 // Global support for SecureHelper functions\r
403 \r
404 #ifndef _TRUNCATE\r
405   #define _TRUNCATE ((size_t)-1)\r
406 #endif\r
407 \r
408 #ifndef _ERRCODE_DEFINED\r
409   #define _ERRCODE_DEFINED\r
410   typedef int errno_t;\r
411 #endif\r
412 \r
413 #ifndef _SECURECRT_ERRCODE_VALUES_DEFINED\r
414   #define _SECURECRT_ERRCODE_VALUES_DEFINED\r
415   #define EINVAL          22\r
416   #define STRUNCATE       80\r
417 #endif\r
418 \r
419 #ifndef _countof\r
420   #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))\r
421 #endif\r
422 \r
423 \r
424 ///////////////////////////////////////////////////////////////////////////////\r
425 // Miscellaneous global support\r
426 \r
427 // define useful macros from winuser.h\r
428 #ifndef IS_INTRESOURCE\r
429   #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)\r
430 #endif // IS_INTRESOURCE\r
431 \r
432 // protect template members from windowsx.h macros\r
433 #ifdef _INC_WINDOWSX\r
434   #undef SubclassWindow\r
435 #endif // _INC_WINDOWSX\r
436 \r
437 // define useful macros from windowsx.h\r
438 #ifndef GET_X_LPARAM\r
439   #define GET_X_LPARAM(lParam)  ((int)(short)LOWORD(lParam))\r
440 #endif\r
441 #ifndef GET_Y_LPARAM\r
442   #define GET_Y_LPARAM(lParam)  ((int)(short)HIWORD(lParam))\r
443 #endif\r
444 \r
445 // Dummy structs for compiling with /CLR\r
446 #if (_MSC_VER >= 1300) && defined(_MANAGED)\r
447   __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }\r
448   __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }\r
449   __if_not_exists(_PSP::_PSP) { struct _PSP { }; }\r
450 #endif\r
451 \r
452 // Define ATLVERIFY macro for ATL3\r
453 #if (_ATL_VER < 0x0700)\r
454   #ifndef ATLVERIFY\r
455     #ifdef _DEBUG\r
456       #define ATLVERIFY(expr) ATLASSERT(expr)\r
457     #else\r
458       #define ATLVERIFY(expr) (expr)\r
459     #endif // DEBUG\r
460   #endif // ATLVERIFY\r
461 #endif // (_ATL_VER < 0x0700)\r
462 \r
463 // Forward declaration for ATL3 fix\r
464 #if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)\r
465   namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); };\r
466 #endif\r
467 \r
468 \r
469 namespace WTL\r
470 {\r
471 \r
472 #if (_ATL_VER >= 0x0700)\r
473   DECLARE_TRACE_CATEGORY(atlTraceUI);\r
474   #ifdef _DEBUG\r
475     __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));\r
476   #endif // _DEBUG\r
477 #else // !(_ATL_VER >= 0x0700)\r
478   enum wtlTraceFlags\r
479   {\r
480         atlTraceUI = 0x10000000\r
481   };\r
482 #endif // !(_ATL_VER >= 0x0700)\r
483 \r
484 // Windows version helper\r
485 inline bool AtlIsOldWindows()\r
486 {\r
487         OSVERSIONINFO ovi = { 0 };\r
488         ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
489         BOOL bRet = ::GetVersionEx(&ovi);\r
490         return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));\r
491 }\r
492 \r
493 // default GUI font helper\r
494 inline HFONT AtlGetDefaultGuiFont()\r
495 {\r
496 #ifndef _WIN32_WCE\r
497         return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);\r
498 #else // CE specific\r
499         return (HFONT)::GetStockObject(SYSTEM_FONT);\r
500 #endif // _WIN32_WCE\r
501 }\r
502 \r
503 // bold font helper (NOTE: Caller owns the font, and should destroy it when done using it)\r
504 inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)\r
505 {\r
506         if(hFont == NULL)\r
507                 hFont = AtlGetDefaultGuiFont();\r
508         ATLASSERT(hFont != NULL);\r
509         HFONT hFontBold = NULL;\r
510         LOGFONT lf = { 0 };\r
511         if(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT))\r
512         {\r
513                 lf.lfWeight = FW_BOLD;\r
514                 hFontBold =  ::CreateFontIndirect(&lf);\r
515                 ATLASSERT(hFontBold != NULL);\r
516         }\r
517         else\r
518         {\r
519                 ATLASSERT(FALSE);\r
520         }\r
521         return hFontBold;\r
522 }\r
523 \r
524 // Common Controls initialization helper\r
525 inline BOOL AtlInitCommonControls(DWORD dwFlags)\r
526 {\r
527         INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };\r
528         BOOL bRet = ::InitCommonControlsEx(&iccx);\r
529         ATLASSERT(bRet);\r
530         return bRet;\r
531 }\r
532 \r
533 \r
534 ///////////////////////////////////////////////////////////////////////////////\r
535 // RunTimeHelper - helper functions for Windows version and structure sizes\r
536 \r
537 // Not for Windows CE\r
538 #if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE)\r
539   #define _WTL_NO_RUNTIME_STRUCT_SIZE\r
540 #endif\r
541 \r
542 #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE\r
543 \r
544 #ifndef _SIZEOF_STRUCT\r
545   #define _SIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))\r
546 #endif\r
547 \r
548 #if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)\r
549   #define REBARBANDINFO_V6_SIZE   _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)\r
550 #endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)\r
551 \r
552 #if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)\r
553   #define LVGROUP_V5_SIZE   _SIZEOF_STRUCT(LVGROUP, uAlign)\r
554 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)\r
555 \r
556 #if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)\r
557   #define LVTILEINFO_V5_SIZE   _SIZEOF_STRUCT(LVTILEINFO, puColumns)\r
558 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)\r
559 \r
560 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)\r
561   #define MCHITTESTINFO_V1_SIZE   _SIZEOF_STRUCT(MCHITTESTINFO, st)\r
562 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)\r
563 \r
564 #if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)\r
565   #define NONCLIENTMETRICS_V1_SIZE   _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)\r
566 #endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)\r
567 \r
568 #endif // !_WTL_NO_RUNTIME_STRUCT_SIZE\r
569 \r
570 namespace RunTimeHelper\r
571 {\r
572 #ifndef _WIN32_WCE\r
573         inline bool IsCommCtrl6()\r
574         {\r
575                 DWORD dwMajor = 0, dwMinor = 0;\r
576                 HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);\r
577                 return (SUCCEEDED(hRet) && (dwMajor >= 6));\r
578         }\r
579 \r
580         inline bool IsVista()\r
581         {\r
582                 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };\r
583                 BOOL bRet = ::GetVersionEx(&ovi);\r
584                 return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));\r
585         }\r
586 #endif // !_WIN32_WCE\r
587 \r
588         inline int SizeOf_REBARBANDINFO()\r
589         {\r
590                 int nSize = sizeof(REBARBANDINFO);\r
591 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)\r
592                 if(!(IsVista() && IsCommCtrl6()))\r
593                         nSize = REBARBANDINFO_V6_SIZE;\r
594 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)\r
595                 return nSize;\r
596         }\r
597 \r
598 #if (_WIN32_WINNT >= 0x501)\r
599         inline int SizeOf_LVGROUP()\r
600         {\r
601                 int nSize = sizeof(LVGROUP);\r
602 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)\r
603                 if(!IsVista())\r
604                         nSize = LVGROUP_V5_SIZE;\r
605 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)\r
606                 return nSize;\r
607         }\r
608 \r
609         inline int SizeOf_LVTILEINFO()\r
610         {\r
611                 int nSize = sizeof(LVTILEINFO);\r
612 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)\r
613                 if(!IsVista())\r
614                         nSize = LVTILEINFO_V5_SIZE;\r
615 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)\r
616                 return nSize;\r
617         }\r
618 #endif // (_WIN32_WINNT >= 0x501)\r
619 \r
620         inline int SizeOf_MCHITTESTINFO()\r
621         {\r
622                 int nSize = sizeof(MCHITTESTINFO);\r
623 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)\r
624                 if(!(IsVista() && IsCommCtrl6()))\r
625                         nSize = MCHITTESTINFO_V1_SIZE;\r
626 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)\r
627                 return nSize;\r
628         }\r
629 \r
630 #ifndef _WIN32_WCE\r
631         inline int SizeOf_NONCLIENTMETRICS()\r
632         {\r
633                 int nSize = sizeof(NONCLIENTMETRICS);\r
634 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)\r
635                 if(!IsVista())\r
636                         nSize = NONCLIENTMETRICS_V1_SIZE;\r
637 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)\r
638                 return nSize;\r
639         }\r
640 #endif // !_WIN32_WCE\r
641 };\r
642 \r
643 \r
644 ///////////////////////////////////////////////////////////////////////////////\r
645 // ModuleHelper - helper functions for ATL3 and ATL7 module classes\r
646 \r
647 namespace ModuleHelper\r
648 {\r
649         inline HINSTANCE GetModuleInstance()\r
650         {\r
651 #if (_ATL_VER >= 0x0700)\r
652                 return ATL::_AtlBaseModule.GetModuleInstance();\r
653 #else // !(_ATL_VER >= 0x0700)\r
654                 return ATL::_pModule->GetModuleInstance();\r
655 #endif // !(_ATL_VER >= 0x0700)\r
656         }\r
657 \r
658         inline HINSTANCE GetResourceInstance()\r
659         {\r
660 #if (_ATL_VER >= 0x0700)\r
661                 return ATL::_AtlBaseModule.GetResourceInstance();\r
662 #else // !(_ATL_VER >= 0x0700)\r
663                 return ATL::_pModule->GetResourceInstance();\r
664 #endif // !(_ATL_VER >= 0x0700)\r
665         }\r
666 \r
667         inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)\r
668         {\r
669 #if (_ATL_VER >= 0x0700)\r
670                 ATL::_AtlWinModule.AddCreateWndData(pData, pObject);\r
671 #else // !(_ATL_VER >= 0x0700)\r
672                 ATL::_pModule->AddCreateWndData(pData, pObject);\r
673 #endif // !(_ATL_VER >= 0x0700)\r
674         }\r
675 \r
676         inline void* ExtractCreateWndData()\r
677         {\r
678 #if (_ATL_VER >= 0x0700)\r
679                 return ATL::_AtlWinModule.ExtractCreateWndData();\r
680 #else // !(_ATL_VER >= 0x0700)\r
681                 return ATL::_pModule->ExtractCreateWndData();\r
682 #endif // !(_ATL_VER >= 0x0700)\r
683         }\r
684 };\r
685 \r
686 \r
687 ///////////////////////////////////////////////////////////////////////////////\r
688 // SecureHelper - helper functions for VS2005 secure CRT\r
689 \r
690 namespace SecureHelper\r
691 {\r
692         inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)\r
693         {\r
694 #if _SECURE_ATL\r
695                 ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);\r
696 #else\r
697                 if(cchDest > (size_t)lstrlenA(lpstrSrc))\r
698                         ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL);\r
699                 else\r
700                         ATLASSERT(FALSE);\r
701 #endif\r
702         }\r
703 \r
704         inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)\r
705         {\r
706 #if _SECURE_ATL\r
707                 ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);\r
708 #else\r
709                 if(cchDest > (size_t)lstrlenW(lpstrSrc))\r
710                         ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL);\r
711                 else\r
712                         ATLASSERT(FALSE);\r
713 #endif\r
714         }\r
715 \r
716         inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)\r
717         {\r
718 #ifdef _UNICODE\r
719                 strcpyW_x(lpstrDest, cchDest, lpstrSrc);\r
720 #else\r
721                 strcpyA_x(lpstrDest, cchDest, lpstrSrc);\r
722 #endif\r
723         }\r
724 \r
725         inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)\r
726         {\r
727 #if _SECURE_ATL\r
728                 return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);\r
729 #else\r
730                 errno_t nRet = 0;\r
731                 if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)\r
732                 {\r
733                         nRet = EINVAL;\r
734                 }\r
735                 else if(cchCount == _TRUNCATE)\r
736                 {\r
737                         cchCount = min(cchDest - 1, size_t(lstrlenA(lpstrSrc)));\r
738                         nRet = STRUNCATE;\r
739                 }\r
740                 else if(cchDest <= cchCount)\r
741                 {\r
742                         lpstrDest[0] = 0;\r
743                         nRet = EINVAL;\r
744                 }\r
745                 if(nRet == 0 || nRet == STRUNCATE)\r
746                         nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;\r
747                 ATLASSERT(nRet == 0 || nRet == STRUNCATE);\r
748                 return nRet;\r
749 #endif\r
750         }\r
751 \r
752         inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)\r
753         {\r
754 #if _SECURE_ATL\r
755                 return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);\r
756 #else\r
757                 errno_t nRet = 0;\r
758                 if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)\r
759                 {\r
760                         nRet = EINVAL;\r
761                 }\r
762                 else if(cchCount == _TRUNCATE)\r
763                 {\r
764                         cchCount = min(cchDest - 1, size_t(lstrlenW(lpstrSrc)));\r
765                         nRet = STRUNCATE;\r
766                 }\r
767                 else if(cchDest <= cchCount)\r
768                 {\r
769                         lpstrDest[0] = 0;\r
770                         nRet = EINVAL;\r
771                 }\r
772                 if(nRet == 0 || nRet == STRUNCATE)\r
773                         nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;\r
774                 ATLASSERT(nRet == 0 || nRet == STRUNCATE);\r
775                 return nRet;\r
776 #endif\r
777         }\r
778 \r
779         inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)\r
780         {\r
781 #ifdef _UNICODE\r
782                 return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);\r
783 #else\r
784                 return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);\r
785 #endif\r
786         }\r
787 \r
788         inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)\r
789         {\r
790 #if _SECURE_ATL\r
791                 ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);\r
792 #else\r
793                 if(cchDest > (size_t)lstrlenA(lpstrSrc))\r
794                         ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL);\r
795                 else\r
796                         ATLASSERT(FALSE);\r
797 #endif\r
798         }\r
799 \r
800         inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)\r
801         {\r
802 #if _SECURE_ATL\r
803                 ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);\r
804 #else\r
805                 if(cchDest > (size_t)lstrlenW(lpstrSrc))\r
806                         ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL);\r
807                 else\r
808                         ATLASSERT(FALSE);\r
809 #endif\r
810         }\r
811 \r
812         inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)\r
813         {\r
814 #ifdef _UNICODE\r
815                 strcatW_x(lpstrDest, cchDest, lpstrSrc);\r
816 #else\r
817                 strcatA_x(lpstrDest, cchDest, lpstrSrc);\r
818 #endif\r
819         }\r
820 \r
821         inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)\r
822         {\r
823 #if _SECURE_ATL\r
824                 ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);\r
825 #else\r
826                 if(cbDest >= cbSrc)\r
827                         memcpy(pDest, pSrc, cbSrc);\r
828                 else\r
829                         ATLASSERT(FALSE);\r
830 #endif\r
831         }\r
832 \r
833         inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)\r
834         {\r
835 #if _SECURE_ATL\r
836                 ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);\r
837 #else\r
838                 if(cbDest >= cbSrc)\r
839                         memmove(pDest, pSrc, cbSrc);\r
840                 else\r
841                         ATLASSERT(FALSE);\r
842 #endif\r
843         }\r
844 \r
845         inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)\r
846         {\r
847 #if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)\r
848                 return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);\r
849 #else\r
850                 cchBuff;   // Avoid unused argument warning\r
851                 return _vstprintf(lpstrBuff, lpstrFormat, args);\r
852 #endif\r
853         }\r
854 \r
855         inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)\r
856         {\r
857 #if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)\r
858                 return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);\r
859 #else\r
860                 cchBuff;   // Avoid unused argument warning\r
861                 return ::wvsprintf(lpstrBuff, lpstrFormat, args);\r
862 #endif\r
863         }\r
864 \r
865         inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)\r
866         {\r
867                 va_list args;\r
868                 va_start(args, lpstrFormat);\r
869                 int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);\r
870                 va_end(args);\r
871                 return nRes;\r
872         }\r
873 \r
874         inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)\r
875         {\r
876                 va_list args;\r
877                 va_start(args, lpstrFormat);\r
878                 int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);\r
879                 va_end(args);\r
880                 return nRes;\r
881         }\r
882 }; // namespace SecureHelper\r
883 \r
884 \r
885 ///////////////////////////////////////////////////////////////////////////////\r
886 // CMessageFilter - Interface for message filter support\r
887 \r
888 class CMessageFilter\r
889 {\r
890 public:\r
891         virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;\r
892 };\r
893 \r
894 \r
895 ///////////////////////////////////////////////////////////////////////////////\r
896 // CIdleHandler - Interface for idle processing\r
897 \r
898 class CIdleHandler\r
899 {\r
900 public:\r
901         virtual BOOL OnIdle() = 0;\r
902 };\r
903 \r
904 #ifndef _ATL_NO_OLD_NAMES\r
905   // for compatilibility with old names only\r
906   typedef CIdleHandler CUpdateUIObject;\r
907   #define DoUpdate OnIdle\r
908 #endif // !_ATL_NO_OLD_NAMES\r
909 \r
910 \r
911 ///////////////////////////////////////////////////////////////////////////////\r
912 // CMessageLoop - message loop implementation\r
913 \r
914 class CMessageLoop\r
915 {\r
916 public:\r
917         ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;\r
918         ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;\r
919         MSG m_msg;\r
920 \r
921 // Message filter operations\r
922         BOOL AddMessageFilter(CMessageFilter* pMessageFilter)\r
923         {\r
924                 return m_aMsgFilter.Add(pMessageFilter);\r
925         }\r
926 \r
927         BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)\r
928         {\r
929                 return m_aMsgFilter.Remove(pMessageFilter);\r
930         }\r
931 \r
932 // Idle handler operations\r
933         BOOL AddIdleHandler(CIdleHandler* pIdleHandler)\r
934         {\r
935                 return m_aIdleHandler.Add(pIdleHandler);\r
936         }\r
937 \r
938         BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)\r
939         {\r
940                 return m_aIdleHandler.Remove(pIdleHandler);\r
941         }\r
942 \r
943 #ifndef _ATL_NO_OLD_NAMES\r
944         // for compatilibility with old names only\r
945         BOOL AddUpdateUI(CIdleHandler* pIdleHandler)\r
946         {\r
947                 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));\r
948                 return AddIdleHandler(pIdleHandler);\r
949         }\r
950 \r
951         BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)\r
952         {\r
953                 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));\r
954                 return RemoveIdleHandler(pIdleHandler);\r
955         }\r
956 #endif // !_ATL_NO_OLD_NAMES\r
957 \r
958 // message loop\r
959         int Run()\r
960         {\r
961                 BOOL bDoIdle = TRUE;\r
962                 int nIdleCount = 0;\r
963                 BOOL bRet;\r
964 \r
965                 for(;;)\r
966                 {\r
967                         while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))\r
968                         {\r
969                                 if(!OnIdle(nIdleCount++))\r
970                                         bDoIdle = FALSE;\r
971                         }\r
972 \r
973                         bRet = ::GetMessage(&m_msg, NULL, 0, 0);\r
974 \r
975                         if(bRet == -1)\r
976                         {\r
977                                 ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));\r
978                                 continue;   // error, don't process\r
979                         }\r
980                         else if(!bRet)\r
981                         {\r
982                                 ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));\r
983                                 break;   // WM_QUIT, exit message loop\r
984                         }\r
985 \r
986                         if(!PreTranslateMessage(&m_msg))\r
987                         {\r
988                                 ::TranslateMessage(&m_msg);\r
989                                 ::DispatchMessage(&m_msg);\r
990                         }\r
991 \r
992                         if(IsIdleMessage(&m_msg))\r
993                         {\r
994                                 bDoIdle = TRUE;\r
995                                 nIdleCount = 0;\r
996                         }\r
997                 }\r
998 \r
999                 return (int)m_msg.wParam;\r
1000         }\r
1001 \r
1002         static BOOL IsIdleMessage(MSG* pMsg)\r
1003         {\r
1004                 // These messages should NOT cause idle processing\r
1005                 switch(pMsg->message)\r
1006                 {\r
1007                 case WM_MOUSEMOVE:\r
1008 #ifndef _WIN32_WCE\r
1009                 case WM_NCMOUSEMOVE:\r
1010 #endif // !_WIN32_WCE\r
1011                 case WM_PAINT:\r
1012                 case 0x0118:    // WM_SYSTIMER (caret blink)\r
1013                         return FALSE;\r
1014                 }\r
1015 \r
1016                 return TRUE;\r
1017         }\r
1018 \r
1019 // Overrideables\r
1020         // Override to change message filtering\r
1021         virtual BOOL PreTranslateMessage(MSG* pMsg)\r
1022         {\r
1023                 // loop backwards\r
1024                 for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)\r
1025                 {\r
1026                         CMessageFilter* pMessageFilter = m_aMsgFilter[i];\r
1027                         if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))\r
1028                                 return TRUE;\r
1029                 }\r
1030                 return FALSE;   // not translated\r
1031         }\r
1032 \r
1033         // override to change idle processing\r
1034         virtual BOOL OnIdle(int /*nIdleCount*/)\r
1035         {\r
1036                 for(int i = 0; i < m_aIdleHandler.GetSize(); i++)\r
1037                 {\r
1038                         CIdleHandler* pIdleHandler = m_aIdleHandler[i];\r
1039                         if(pIdleHandler != NULL)\r
1040                                 pIdleHandler->OnIdle();\r
1041                 }\r
1042                 return FALSE;   // don't continue\r
1043         }\r
1044 };\r
1045 \r
1046 \r
1047 ///////////////////////////////////////////////////////////////////////////////\r
1048 // CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock\r
1049 // internal classes to manage critical sections for both ATL3 and ATL7\r
1050 \r
1051 class CStaticDataInitCriticalSectionLock\r
1052 {\r
1053 public:\r
1054 #if (_ATL_VER >= 0x0700)\r
1055         ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;\r
1056 \r
1057         CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)\r
1058         { }\r
1059 #endif // (_ATL_VER >= 0x0700)\r
1060 \r
1061         HRESULT Lock()\r
1062         {\r
1063 #if (_ATL_VER >= 0x0700)\r
1064                 return m_cslock.Lock();\r
1065 #else // !(_ATL_VER >= 0x0700)\r
1066                 ::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit);\r
1067                 return S_OK;\r
1068 #endif // !(_ATL_VER >= 0x0700)\r
1069         }\r
1070 \r
1071         void Unlock()\r
1072         {\r
1073 #if (_ATL_VER >= 0x0700)\r
1074                 m_cslock.Unlock();\r
1075 #else // !(_ATL_VER >= 0x0700)\r
1076                 ::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit);\r
1077 #endif // !(_ATL_VER >= 0x0700)\r
1078         }\r
1079 };\r
1080 \r
1081 \r
1082 class CWindowCreateCriticalSectionLock\r
1083 {\r
1084 public:\r
1085 #if (_ATL_VER >= 0x0700)\r
1086         ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;\r
1087 \r
1088         CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)\r
1089         { }\r
1090 #endif // (_ATL_VER >= 0x0700)\r
1091 \r
1092         HRESULT Lock()\r
1093         {\r
1094 #if (_ATL_VER >= 0x0700)\r
1095                 return m_cslock.Lock();\r
1096 #else // !(_ATL_VER >= 0x0700)\r
1097                 ::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate);\r
1098                 return S_OK;\r
1099 #endif // !(_ATL_VER >= 0x0700)\r
1100         }\r
1101 \r
1102         void Unlock()\r
1103         {\r
1104 #if (_ATL_VER >= 0x0700)\r
1105                 m_cslock.Unlock();\r
1106 #else // !(_ATL_VER >= 0x0700)\r
1107                 ::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate);\r
1108 #endif // !(_ATL_VER >= 0x0700)\r
1109         }\r
1110 };\r
1111 \r
1112 \r
1113 ///////////////////////////////////////////////////////////////////////////////\r
1114 // CTempBuffer - helper class for stack allocations for ATL3\r
1115 \r
1116 #ifndef _WTL_STACK_ALLOC_THRESHOLD\r
1117   #define _WTL_STACK_ALLOC_THRESHOLD   512\r
1118 #endif\r
1119 \r
1120 #if (_ATL_VER >= 0x0700)\r
1121 \r
1122 using ATL::CTempBuffer;\r
1123 \r
1124 #else // !(_ATL_VER >= 0x0700)\r
1125 \r
1126 #ifndef SIZE_MAX\r
1127   #ifdef _WIN64 \r
1128     #define SIZE_MAX _UI64_MAX\r
1129   #else\r
1130     #define SIZE_MAX UINT_MAX\r
1131   #endif\r
1132 #endif\r
1133 \r
1134 #pragma warning(disable: 4284)   // warning for operator ->\r
1135 \r
1136 template<typename T, int t_nFixedBytes = 128>\r
1137 class CTempBuffer\r
1138 {\r
1139 public:\r
1140         CTempBuffer() : m_p(NULL)\r
1141         {\r
1142         }\r
1143 \r
1144         CTempBuffer(size_t nElements) : m_p(NULL)\r
1145         {\r
1146                 Allocate(nElements);\r
1147         }\r
1148 \r
1149         ~CTempBuffer()\r
1150         {\r
1151                 if(m_p != reinterpret_cast<T*>(m_abFixedBuffer))\r
1152                         free(m_p);\r
1153         }\r
1154 \r
1155         operator T*() const\r
1156         {\r
1157                 return m_p;\r
1158         }\r
1159 \r
1160         T* operator ->() const\r
1161         {\r
1162                 ATLASSERT(m_p != NULL);\r
1163                 return m_p;\r
1164         }\r
1165 \r
1166         T* Allocate(size_t nElements)\r
1167         {\r
1168                 ATLASSERT(nElements <= (SIZE_MAX / sizeof(T)));\r
1169                 return AllocateBytes(nElements * sizeof(T));\r
1170         }\r
1171 \r
1172         T* AllocateBytes(size_t nBytes)\r
1173         {\r
1174                 ATLASSERT(m_p == NULL);\r
1175                 if(nBytes > t_nFixedBytes)\r
1176                         m_p = static_cast<T*>(malloc(nBytes));\r
1177                 else\r
1178                         m_p = reinterpret_cast<T*>(m_abFixedBuffer);\r
1179 \r
1180                 return m_p;\r
1181         }\r
1182 \r
1183 private:\r
1184         T* m_p;\r
1185         BYTE m_abFixedBuffer[t_nFixedBytes];\r
1186 };\r
1187 \r
1188 #pragma warning(default: 4284)\r
1189 \r
1190 #endif // !(_ATL_VER >= 0x0700)\r
1191 \r
1192 \r
1193 ///////////////////////////////////////////////////////////////////////////////\r
1194 // CAppModule - module class for an application\r
1195 \r
1196 class CAppModule : public ATL::CComModule\r
1197 {\r
1198 public:\r
1199         DWORD m_dwMainThreadID;\r
1200         ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;\r
1201         ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;\r
1202 \r
1203 // Overrides of CComModule::Init and Term\r
1204         HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)\r
1205         {\r
1206                 HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);\r
1207                 if(FAILED(hRet))\r
1208                         return hRet;\r
1209 \r
1210                 m_dwMainThreadID = ::GetCurrentThreadId();\r
1211                 typedef ATL::CSimpleMap<DWORD, CMessageLoop*>   _mapClass;\r
1212                 m_pMsgLoopMap = NULL;\r
1213                 ATLTRY(m_pMsgLoopMap = new _mapClass);\r
1214                 if(m_pMsgLoopMap == NULL)\r
1215                         return E_OUTOFMEMORY;\r
1216                 m_pSettingChangeNotify = NULL;\r
1217 \r
1218                 return hRet;\r
1219         }\r
1220 \r
1221         void Term()\r
1222         {\r
1223                 TermSettingChangeNotify();\r
1224                 delete m_pMsgLoopMap;\r
1225                 CComModule::Term();\r
1226         }\r
1227 \r
1228 // Message loop map methods\r
1229         BOOL AddMessageLoop(CMessageLoop* pMsgLoop)\r
1230         {\r
1231                 CStaticDataInitCriticalSectionLock lock;\r
1232                 if(FAILED(lock.Lock()))\r
1233                 {\r
1234                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));\r
1235                         ATLASSERT(FALSE);\r
1236                         return FALSE;\r
1237                 }\r
1238 \r
1239                 ATLASSERT(pMsgLoop != NULL);\r
1240                 ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL);   // not in map yet\r
1241 \r
1242                 BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);\r
1243 \r
1244                 lock.Unlock();\r
1245 \r
1246                 return bRet;\r
1247         }\r
1248 \r
1249         BOOL RemoveMessageLoop()\r
1250         {\r
1251                 CStaticDataInitCriticalSectionLock lock;\r
1252                 if(FAILED(lock.Lock()))\r
1253                 {\r
1254                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));\r
1255                         ATLASSERT(FALSE);\r
1256                         return FALSE;\r
1257                 }\r
1258 \r
1259                 BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());\r
1260 \r
1261                 lock.Unlock();\r
1262 \r
1263                 return bRet;\r
1264         }\r
1265 \r
1266         CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const\r
1267         {\r
1268                 CStaticDataInitCriticalSectionLock lock;\r
1269                 if(FAILED(lock.Lock()))\r
1270                 {\r
1271                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));\r
1272                         ATLASSERT(FALSE);\r
1273                         return NULL;\r
1274                 }\r
1275 \r
1276                 CMessageLoop* pLoop =  m_pMsgLoopMap->Lookup(dwThreadID);\r
1277 \r
1278                 lock.Unlock();\r
1279 \r
1280                 return pLoop;\r
1281         }\r
1282 \r
1283 // Setting change notify methods\r
1284         // Note: Call this from the main thread for MSDI apps\r
1285         BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)\r
1286         {\r
1287                 CStaticDataInitCriticalSectionLock lock;\r
1288                 if(FAILED(lock.Lock()))\r
1289                 {\r
1290                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));\r
1291                         ATLASSERT(FALSE);\r
1292                         return FALSE;\r
1293                 }\r
1294 \r
1295                 if(m_pSettingChangeNotify == NULL)\r
1296                 {\r
1297                         typedef ATL::CSimpleArray<HWND>   _notifyClass;\r
1298                         ATLTRY(m_pSettingChangeNotify = new _notifyClass);\r
1299                         ATLASSERT(m_pSettingChangeNotify != NULL);\r
1300                 }\r
1301 \r
1302                 BOOL bRet = (m_pSettingChangeNotify != NULL);\r
1303                 if(bRet && m_pSettingChangeNotify->GetSize() == 0)\r
1304                 {\r
1305                         // init everything\r
1306                         _ATL_EMPTY_DLGTEMPLATE templ;\r
1307                         HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);\r
1308                         ATLASSERT(::IsWindow(hNtfWnd));\r
1309                         if(::IsWindow(hNtfWnd))\r
1310                         {\r
1311 // need conditional code because types don't match in winuser.h\r
1312 #ifdef _WIN64\r
1313                                 ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);\r
1314 #else\r
1315                                 ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));\r
1316 #endif\r
1317                                 bRet = m_pSettingChangeNotify->Add(hNtfWnd);\r
1318                         }\r
1319                         else\r
1320                         {\r
1321                                 bRet = FALSE;\r
1322                         }\r
1323                 }\r
1324 \r
1325                 lock.Unlock();\r
1326 \r
1327                 return bRet;\r
1328         }\r
1329 \r
1330         void TermSettingChangeNotify()\r
1331         {\r
1332                 CStaticDataInitCriticalSectionLock lock;\r
1333                 if(FAILED(lock.Lock()))\r
1334                 {\r
1335                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));\r
1336                         ATLASSERT(FALSE);\r
1337                         return;\r
1338                 }\r
1339 \r
1340                 if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)\r
1341                         ::DestroyWindow((*m_pSettingChangeNotify)[0]);\r
1342                 delete m_pSettingChangeNotify;\r
1343                 m_pSettingChangeNotify = NULL;\r
1344 \r
1345                 lock.Unlock();\r
1346         }\r
1347 \r
1348         BOOL AddSettingChangeNotify(HWND hWnd)\r
1349         {\r
1350                 CStaticDataInitCriticalSectionLock lock;\r
1351                 if(FAILED(lock.Lock()))\r
1352                 {\r
1353                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));\r
1354                         ATLASSERT(FALSE);\r
1355                         return FALSE;\r
1356                 }\r
1357 \r
1358                 ATLASSERT(::IsWindow(hWnd));\r
1359                 BOOL bRet = FALSE;\r
1360                 if(InitSettingChangeNotify() != FALSE)\r
1361                         bRet = m_pSettingChangeNotify->Add(hWnd);\r
1362 \r
1363                 lock.Unlock();\r
1364 \r
1365                 return bRet;\r
1366         }\r
1367 \r
1368         BOOL RemoveSettingChangeNotify(HWND hWnd)\r
1369         {\r
1370                 CStaticDataInitCriticalSectionLock lock;\r
1371                 if(FAILED(lock.Lock()))\r
1372                 {\r
1373                         ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));\r
1374                         ATLASSERT(FALSE);\r
1375                         return FALSE;\r
1376                 }\r
1377 \r
1378                 BOOL bRet = FALSE;\r
1379                 if(m_pSettingChangeNotify != NULL)\r
1380                         bRet = m_pSettingChangeNotify->Remove(hWnd);\r
1381 \r
1382                 lock.Unlock();\r
1383 \r
1384                 return bRet;\r
1385         }\r
1386 \r
1387 // Implementation - setting change notify dialog template and dialog procedure\r
1388         struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE\r
1389         {\r
1390                 _ATL_EMPTY_DLGTEMPLATE()\r
1391                 {\r
1392                         memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));\r
1393                         style = WS_POPUP;\r
1394                 }\r
1395                 WORD wMenu, wClass, wTitle;\r
1396         };\r
1397 \r
1398 #ifdef _WIN64\r
1399         static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
1400 #else\r
1401         static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
1402 #endif\r
1403         {\r
1404                 if(uMsg == WM_SETTINGCHANGE)\r
1405                 {\r
1406 // need conditional code because types don't match in winuser.h\r
1407 #ifdef _WIN64\r
1408                         CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);\r
1409 #else\r
1410                         CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA));\r
1411 #endif\r
1412                         ATLASSERT(pModule != NULL);\r
1413                         ATLASSERT(pModule->m_pSettingChangeNotify != NULL);\r
1414                         const UINT uTimeout = 1500;   // ms\r
1415                         for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)\r
1416                         {\r
1417 #if !defined(_WIN32_WCE)\r
1418                                 ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);\r
1419 #elif(_WIN32_WCE >= 400) // CE specific\r
1420                                 ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL);\r
1421 #else // _WIN32_WCE < 400 specific\r
1422                                 uTimeout;\r
1423                                 ::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam);\r
1424 #endif\r
1425                         }\r
1426                         return TRUE;\r
1427                 }\r
1428                 return FALSE;\r
1429         }\r
1430 };\r
1431 \r
1432 \r
1433 ///////////////////////////////////////////////////////////////////////////////\r
1434 // CServerAppModule - module class for a COM server application\r
1435 \r
1436 class CServerAppModule : public CAppModule\r
1437 {\r
1438 public:\r
1439         HANDLE m_hEventShutdown;\r
1440         bool m_bActivity;\r
1441         DWORD m_dwTimeOut;\r
1442         DWORD m_dwPause;\r
1443 \r
1444 // Override of CAppModule::Init\r
1445         HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)\r
1446         {\r
1447                 m_dwTimeOut = 5000;\r
1448                 m_dwPause = 1000;\r
1449                 return CAppModule::Init(pObjMap, hInstance, pLibID);\r
1450         }\r
1451 \r
1452         void Term()\r
1453         {\r
1454                 if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))\r
1455                         m_hEventShutdown = NULL;\r
1456                 CAppModule::Term();\r
1457         }\r
1458 \r
1459 // COM Server methods\r
1460         LONG Unlock()\r
1461         {\r
1462                 LONG lRet = CComModule::Unlock();\r
1463                 if(lRet == 0)\r
1464                 {\r
1465                         m_bActivity = true;\r
1466                         ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero\r
1467                 }\r
1468                 return lRet;\r
1469         }\r
1470 \r
1471         void MonitorShutdown()\r
1472         {\r
1473                 for(;;)\r
1474                 {\r
1475                         ::WaitForSingleObject(m_hEventShutdown, INFINITE);\r
1476                         DWORD dwWait = 0;\r
1477                         do\r
1478                         {\r
1479                                 m_bActivity = false;\r
1480                                 dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);\r
1481                         }\r
1482                         while(dwWait == WAIT_OBJECT_0);\r
1483                         // timed out\r
1484                         if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail\r
1485                         {\r
1486 #if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE)\r
1487                                 ::CoSuspendClassObjects();\r
1488                                 if(!m_bActivity && m_nLockCnt == 0)\r
1489 #endif\r
1490                                         break;\r
1491                         }\r
1492                 }\r
1493                 // This handle should be valid now. If it isn't, \r
1494                 // check if _Module.Term was called first (it shouldn't)\r
1495                 if(::CloseHandle(m_hEventShutdown))\r
1496                         m_hEventShutdown = NULL;\r
1497                 ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);\r
1498         }\r
1499 \r
1500         bool StartMonitor()\r
1501         {\r
1502                 m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);\r
1503                 if(m_hEventShutdown == NULL)\r
1504                         return false;\r
1505                 DWORD dwThreadID = 0;\r
1506 #if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)\r
1507                 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);\r
1508 #else\r
1509                 HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);\r
1510 #endif\r
1511                 bool bRet = (hThread != NULL);\r
1512                 if(bRet)\r
1513                         ::CloseHandle(hThread);\r
1514                 return bRet;\r
1515         }\r
1516 \r
1517         static DWORD WINAPI MonitorProc(void* pv)\r
1518         {\r
1519                 CServerAppModule* p = (CServerAppModule*)pv;\r
1520                 p->MonitorShutdown();\r
1521                 return 0;\r
1522         }\r
1523 \r
1524 #if (_ATL_VER < 0x0700)\r
1525         // search for an occurence of string p2 in string p1\r
1526         static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)\r
1527         {\r
1528                 while(p1 != NULL && *p1 != NULL)\r
1529                 {\r
1530                         LPCTSTR p = p2;\r
1531                         while(p != NULL && *p != NULL)\r
1532                         {\r
1533                                 if(*p1 == *p)\r
1534                                         return ::CharNext(p1);\r
1535                                 p = ::CharNext(p);\r
1536                         }\r
1537                         p1 = ::CharNext(p1);\r
1538                 }\r
1539                 return NULL;\r
1540         }\r
1541 #endif // (_ATL_VER < 0x0700)\r
1542 };\r
1543 \r
1544 \r
1545 ///////////////////////////////////////////////////////////////////////////////\r
1546 // CString forward reference (enables CString use in atluser.h and atlgdi.h)\r
1547 \r
1548 #if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)\r
1549   #define _WTL_USE_CSTRING\r
1550 #endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)\r
1551 \r
1552 #ifdef _WTL_USE_CSTRING\r
1553   class CString;   // forward declaration (include atlmisc.h for the whole class)\r
1554 #endif // _WTL_USE_CSTRING\r
1555 \r
1556 // CString namespace\r
1557 #ifndef _CSTRING_NS\r
1558   #ifdef __ATLSTR_H__\r
1559     #define _CSTRING_NS ATL\r
1560   #else\r
1561     #define _CSTRING_NS WTL\r
1562   #endif\r
1563 #endif // _CSTRING_NS\r
1564 \r
1565 // Type classes namespace\r
1566 #ifndef _WTYPES_NS\r
1567   #ifdef __ATLTYPES_H__\r
1568     #define _WTYPES_NS\r
1569   #else\r
1570     #define _WTYPES_NS  WTL\r
1571   #endif\r
1572 #endif // _WTYPES_NS\r
1573 \r
1574 }; // namespace WTL\r
1575 \r
1576 \r
1577 ///////////////////////////////////////////////////////////////////////////////\r
1578 // General DLL version helpers (excluded from atlbase.h if _ATL_DLL is defined)\r
1579 \r
1580 #if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)\r
1581 \r
1582 namespace ATL\r
1583 {\r
1584 \r
1585 inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)\r
1586 {\r
1587         ATLASSERT(pDllVersionInfo != NULL);\r
1588         if(pDllVersionInfo == NULL)\r
1589                 return E_INVALIDARG;\r
1590 \r
1591         // We must get this function explicitly because some DLLs don't implement it.\r
1592         DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");\r
1593         if(pfnDllGetVersion == NULL)\r
1594                 return E_NOTIMPL;\r
1595 \r
1596         return (*pfnDllGetVersion)(pDllVersionInfo);\r
1597 }\r
1598 \r
1599 inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)\r
1600 {\r
1601         HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);\r
1602         if(hInstDLL == NULL)\r
1603                 return E_FAIL;\r
1604         HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);\r
1605         ::FreeLibrary(hInstDLL);\r
1606         return hRet;\r
1607 }\r
1608 \r
1609 // Common Control Versions:\r
1610 //   Win95/WinNT 4.0    maj=4 min=00\r
1611 //   IE 3.x     maj=4 min=70\r
1612 //   IE 4.0     maj=4 min=71\r
1613 inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)\r
1614 {\r
1615         ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);\r
1616         if(pdwMajor == NULL || pdwMinor == NULL)\r
1617                 return E_INVALIDARG;\r
1618 \r
1619         DLLVERSIONINFO dvi;\r
1620         ::ZeroMemory(&dvi, sizeof(dvi));\r
1621         dvi.cbSize = sizeof(dvi);\r
1622         HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);\r
1623 \r
1624         if(SUCCEEDED(hRet))\r
1625         {\r
1626                 *pdwMajor = dvi.dwMajorVersion;\r
1627                 *pdwMinor = dvi.dwMinorVersion;\r
1628         }\r
1629         else if(hRet == E_NOTIMPL)\r
1630         {\r
1631                 // If DllGetVersion is not there, then the DLL is a version\r
1632                 // previous to the one shipped with IE 3.x\r
1633                 *pdwMajor = 4;\r
1634                 *pdwMinor = 0;\r
1635                 hRet = S_OK;\r
1636         }\r
1637 \r
1638         return hRet;\r
1639 }\r
1640 \r
1641 // Shell Versions:\r
1642 //   Win95/WinNT 4.0                    maj=4 min=00\r
1643 //   IE 3.x, IE 4.0 without Web Integrated Desktop  maj=4 min=00\r
1644 //   IE 4.0 with Web Integrated Desktop         maj=4 min=71\r
1645 //   IE 4.01 with Web Integrated Desktop        maj=4 min=72\r
1646 inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)\r
1647 {\r
1648         ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);\r
1649         if(pdwMajor == NULL || pdwMinor == NULL)\r
1650                 return E_INVALIDARG;\r
1651 \r
1652         DLLVERSIONINFO dvi;\r
1653         ::ZeroMemory(&dvi, sizeof(dvi));\r
1654         dvi.cbSize = sizeof(dvi);\r
1655         HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);\r
1656 \r
1657         if(SUCCEEDED(hRet))\r
1658         {\r
1659                 *pdwMajor = dvi.dwMajorVersion;\r
1660                 *pdwMinor = dvi.dwMinorVersion;\r
1661         }\r
1662         else if(hRet == E_NOTIMPL)\r
1663         {\r
1664                 // If DllGetVersion is not there, then the DLL is a version\r
1665                 // previous to the one shipped with IE 4.x\r
1666                 *pdwMajor = 4;\r
1667                 *pdwMinor = 0;\r
1668                 hRet = S_OK;\r
1669         }\r
1670 \r
1671         return hRet;\r
1672 }\r
1673 \r
1674 }; // namespace ATL\r
1675 \r
1676 #endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)\r
1677 \r
1678 \r
1679 // These are always included\r
1680 #include "atlwinx.h"\r
1681 #include "atluser.h"\r
1682 #include "atlgdi.h"\r
1683 \r
1684 #ifndef _WTL_NO_AUTOMATIC_NAMESPACE\r
1685 using namespace WTL;\r
1686 #endif // !_WTL_NO_AUTOMATIC_NAMESPACE\r
1687 \r
1688 #endif // __ATLAPP_H__\r