atlapp.h 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. // Windows Template Library - WTL version 10.0
  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. #ifndef __ATLAPP_H__
  9. #define __ATLAPP_H__
  10. #pragma once
  11. #ifndef __cplusplus
  12. #error WTL requires C++ compilation (use a .cpp suffix)
  13. #endif
  14. #ifndef __ATLBASE_H__
  15. #error atlapp.h requires atlbase.h to be included first
  16. #endif
  17. #ifdef _WIN32_WCE
  18. #error WTL10 doesn't support Windows CE
  19. #endif
  20. #ifdef _ATL_NO_COMMODULE
  21. #error WTL requires that _ATL_NO_COMMODULE is not defined
  22. #endif
  23. #ifdef _ATL_NO_WIN_SUPPORT
  24. #error WTL requires that _ATL_NO_WIN_SUPPORT is not defined
  25. #endif
  26. #if (_MSC_VER < 1400)
  27. #error WTL10 requires C++ compiler version 14 (Visual C++ 2005) or higher
  28. #endif
  29. #if (WINVER < 0x0501)
  30. #error WTL requires WINVER >= 0x0501
  31. #endif
  32. #if (_WIN32_WINNT < 0x0501)
  33. #error WTL requires _WIN32_WINNT >= 0x0501
  34. #endif
  35. #if (_WIN32_IE < 0x0600)
  36. #error WTL requires _WIN32_IE >= 0x0600
  37. #endif
  38. #if (_ATL_VER < 0x0800)
  39. #error WTL10 requires ATL version 8 or higher
  40. #endif
  41. #ifdef _ATL_MIN_CRT
  42. #error WTL10 doesn't support _ATL_MIN_CRT
  43. #endif
  44. #ifdef _ATL_NO_MSIMG
  45. #error WTL10 doesn't support _ATL_NO_MSIMG
  46. #endif
  47. #include <limits.h>
  48. #ifdef _MT
  49. #include <process.h> // for _beginthreadex
  50. #endif
  51. #include <commctrl.h>
  52. #pragma comment(lib, "comctl32.lib")
  53. #include <commdlg.h>
  54. #include <shellapi.h>
  55. // Check for VS2005 without newer WinSDK
  56. #if (_MSC_VER == 1400) && !defined(RB_GETEXTENDEDSTYLE)
  57. #error WTL10 requires WinSDK 6.0 ot higher
  58. #endif
  59. #include <uxtheme.h>
  60. #pragma comment(lib, "uxtheme.lib")
  61. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE)
  62. #include <VersionHelpers.h>
  63. #endif
  64. #include "atlres.h"
  65. ///////////////////////////////////////////////////////////////////////////////
  66. // WTL version number
  67. #define _WTL_VER 0x1000 // version 10.0
  68. ///////////////////////////////////////////////////////////////////////////////
  69. // Classes in this file:
  70. //
  71. // CMessageFilter
  72. // CIdleHandler
  73. // CMessageLoop
  74. //
  75. // CAppModule
  76. // CServerAppModule
  77. //
  78. // Global functions:
  79. // AtlInitCommonControls()
  80. // AtlGetDefaultGuiFont()
  81. // AtlCreateControlFont()
  82. // AtlCreateBoldFont()
  83. // AtlGetStringPtr()
  84. ///////////////////////////////////////////////////////////////////////////////
  85. // Miscellaneous global support
  86. // define useful macros from winuser.h
  87. #ifndef IS_INTRESOURCE
  88. #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
  89. #endif // IS_INTRESOURCE
  90. // protect template members from windowsx.h macros
  91. #ifdef _INC_WINDOWSX
  92. #undef SubclassWindow
  93. #endif // _INC_WINDOWSX
  94. // define useful macros from windowsx.h
  95. #ifndef GET_X_LPARAM
  96. #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
  97. #endif
  98. #ifndef GET_Y_LPARAM
  99. #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
  100. #endif
  101. // Dummy structs for compiling with /CLR
  102. #ifdef _MANAGED
  103. __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
  104. __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
  105. __if_not_exists(_PSP::_PSP) { struct _PSP { }; }
  106. #endif
  107. // Forward declaration for ATL11 fix
  108. #if (_ATL_VER >= 0x0B00)
  109. namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); }
  110. #endif
  111. #ifndef WM_MOUSEHWHEEL
  112. #define WM_MOUSEHWHEEL 0x020E
  113. #endif
  114. // Used for stack allocations with ATL::CTempBuffer
  115. #ifndef _WTL_STACK_ALLOC_THRESHOLD
  116. #define _WTL_STACK_ALLOC_THRESHOLD 512
  117. #endif
  118. // Used to declare overriden virtual functions
  119. #if (__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1900)
  120. #define _WTL_OVERRIDE override
  121. #else
  122. #define _WTL_OVERRIDE
  123. #endif
  124. namespace WTL
  125. {
  126. DECLARE_TRACE_CATEGORY(atlTraceUI)
  127. #ifdef _DEBUG
  128. __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
  129. #endif // _DEBUG
  130. // Common Controls initialization helper
  131. inline BOOL AtlInitCommonControls(DWORD dwFlags)
  132. {
  133. INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
  134. BOOL bRet = ::InitCommonControlsEx(&iccx);
  135. ATLASSERT(bRet);
  136. return bRet;
  137. }
  138. // Default GUI font helper - "MS Shell Dlg" stock font
  139. inline HFONT AtlGetDefaultGuiFont()
  140. {
  141. return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
  142. }
  143. // Control font helper - default font for controls not in a dialog
  144. // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
  145. inline HFONT AtlCreateControlFont()
  146. {
  147. LOGFONT lf = {};
  148. ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0));
  149. HFONT hFont = ::CreateFontIndirect(&lf);
  150. ATLASSERT(hFont != NULL);
  151. return hFont;
  152. }
  153. // Bold font helper
  154. // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
  155. inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
  156. {
  157. LOGFONT lf = {};
  158. if(hFont == NULL)
  159. ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0));
  160. else
  161. (void)(ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT)));
  162. lf.lfWeight = FW_BOLD;
  163. HFONT hFontBold = ::CreateFontIndirect(&lf);
  164. ATLASSERT(hFontBold != NULL);
  165. return hFontBold;
  166. }
  167. // Resource string pointer
  168. inline LPCWSTR AtlGetStringPtr(UINT uID, int* pch = NULL)
  169. {
  170. LPCWSTR lpstr = NULL;
  171. int nRet = ::LoadStringW(ATL::_AtlBaseModule.GetResourceInstance(), uID, (LPWSTR)&lpstr, 0);
  172. if(pch != NULL)
  173. *pch = nRet;
  174. return lpstr;
  175. }
  176. ///////////////////////////////////////////////////////////////////////////////
  177. // RunTimeHelper - helper functions for Windows version and structure sizes
  178. #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
  179. #ifndef _SIZEOF_STRUCT
  180. #define _SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
  181. #endif
  182. #if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
  183. #define REBARBANDINFO_V6_SIZE _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
  184. #endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
  185. #if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
  186. #define LVGROUP_V5_SIZE _SIZEOF_STRUCT(LVGROUP, uAlign)
  187. #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
  188. #if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
  189. #define LVTILEINFO_V5_SIZE _SIZEOF_STRUCT(LVTILEINFO, puColumns)
  190. #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
  191. #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
  192. #define MCHITTESTINFO_V1_SIZE _SIZEOF_STRUCT(MCHITTESTINFO, st)
  193. #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
  194. #if (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
  195. #define NONCLIENTMETRICS_V1_SIZE _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
  196. #endif // (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
  197. #ifndef TTTOOLINFO_V2_SIZE
  198. #define TTTOOLINFO_V2_SIZE _SIZEOF_STRUCT(TTTOOLINFO, lParam)
  199. #endif
  200. #endif // !_WTL_NO_RUNTIME_STRUCT_SIZE
  201. namespace RunTimeHelper
  202. {
  203. inline bool IsCommCtrl6()
  204. {
  205. DWORD dwMajor = 0, dwMinor = 0;
  206. HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
  207. return (SUCCEEDED(hRet) && (dwMajor >= 6));
  208. }
  209. inline bool IsVista()
  210. {
  211. #ifdef _versionhelpers_H_INCLUDED_
  212. return ::IsWindowsVistaOrGreater();
  213. #else // !_versionhelpers_H_INCLUDED_
  214. OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
  215. BOOL bRet = ::GetVersionEx(&ovi);
  216. return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
  217. #endif // _versionhelpers_H_INCLUDED_
  218. }
  219. inline bool IsThemeAvailable()
  220. {
  221. return IsCommCtrl6() && (::IsThemeActive() != FALSE) && (::IsAppThemed() != FALSE);
  222. }
  223. inline bool IsWin7()
  224. {
  225. #ifdef _versionhelpers_H_INCLUDED_
  226. return ::IsWindows7OrGreater();
  227. #else // !_versionhelpers_H_INCLUDED_
  228. OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
  229. BOOL bRet = ::GetVersionEx(&ovi);
  230. return ((bRet != FALSE) && (ovi.dwMajorVersion == 6) && (ovi.dwMinorVersion >= 1));
  231. #endif // _versionhelpers_H_INCLUDED_
  232. }
  233. inline bool IsRibbonUIAvailable()
  234. {
  235. static INT iRibbonUI = -1;
  236. #if defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
  237. if (iRibbonUI == -1)
  238. {
  239. HMODULE hRibbonDLL = ::LoadLibrary(_T("propsys.dll"));
  240. if (hRibbonDLL != NULL)
  241. {
  242. const GUID CLSID_UIRibbonFramework = { 0x926749fa, 0x2615, 0x4987, { 0x88, 0x45, 0xc3, 0x3e, 0x65, 0xf2, 0xb9, 0x57 } };
  243. // block - create instance
  244. {
  245. ATL::CComPtr<IUnknown> pIUIFramework;
  246. iRibbonUI = SUCCEEDED(pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework)) ? 1 : 0;
  247. }
  248. ::FreeLibrary(hRibbonDLL);
  249. }
  250. else
  251. {
  252. iRibbonUI = 0;
  253. }
  254. }
  255. #endif // defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
  256. return (iRibbonUI == 1);
  257. }
  258. inline UINT SizeOf_REBARBANDINFO()
  259. {
  260. UINT uSize = sizeof(REBARBANDINFO);
  261. #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
  262. if(!(IsVista() && IsCommCtrl6()))
  263. uSize = REBARBANDINFO_V6_SIZE;
  264. #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
  265. return uSize;
  266. }
  267. inline UINT SizeOf_LVGROUP()
  268. {
  269. UINT uSize = sizeof(LVGROUP);
  270. #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
  271. if(!IsVista())
  272. uSize = LVGROUP_V5_SIZE;
  273. #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
  274. return uSize;
  275. }
  276. inline UINT SizeOf_LVTILEINFO()
  277. {
  278. UINT uSize = sizeof(LVTILEINFO);
  279. #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
  280. if(!IsVista())
  281. uSize = LVTILEINFO_V5_SIZE;
  282. #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
  283. return uSize;
  284. }
  285. inline UINT SizeOf_MCHITTESTINFO()
  286. {
  287. UINT uSize = sizeof(MCHITTESTINFO);
  288. #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
  289. if(!(IsVista() && IsCommCtrl6()))
  290. uSize = MCHITTESTINFO_V1_SIZE;
  291. #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
  292. return uSize;
  293. }
  294. inline UINT SizeOf_NONCLIENTMETRICS()
  295. {
  296. UINT uSize = sizeof(NONCLIENTMETRICS);
  297. #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
  298. if(!IsVista())
  299. uSize = NONCLIENTMETRICS_V1_SIZE;
  300. #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
  301. return uSize;
  302. }
  303. inline UINT SizeOf_TOOLINFO()
  304. {
  305. UINT uSize = sizeof(TOOLINFO);
  306. #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
  307. if(!IsVista())
  308. uSize = TTTOOLINFO_V2_SIZE;
  309. #endif
  310. return uSize;
  311. }
  312. } // namespace RunTimeHelper
  313. ///////////////////////////////////////////////////////////////////////////////
  314. // ModuleHelper - helper functions for ATL (deprecated)
  315. namespace ModuleHelper
  316. {
  317. inline HINSTANCE GetModuleInstance()
  318. {
  319. return ATL::_AtlBaseModule.GetModuleInstance();
  320. }
  321. inline HINSTANCE GetResourceInstance()
  322. {
  323. return ATL::_AtlBaseModule.GetResourceInstance();
  324. }
  325. inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
  326. {
  327. ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
  328. }
  329. inline void* ExtractCreateWndData()
  330. {
  331. return ATL::_AtlWinModule.ExtractCreateWndData();
  332. }
  333. } // namespace ModuleHelper
  334. ///////////////////////////////////////////////////////////////////////////////
  335. // SecureHelper - WTL10 requires use of secure functions
  336. // these are here only for compatibility with existing projects
  337. namespace SecureHelper
  338. {
  339. inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
  340. {
  341. ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
  342. }
  343. inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
  344. {
  345. ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
  346. }
  347. inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
  348. {
  349. #ifdef _UNICODE
  350. strcpyW_x(lpstrDest, cchDest, lpstrSrc);
  351. #else
  352. strcpyA_x(lpstrDest, cchDest, lpstrSrc);
  353. #endif
  354. }
  355. inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
  356. {
  357. return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
  358. }
  359. inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
  360. {
  361. return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
  362. }
  363. inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
  364. {
  365. #ifdef _UNICODE
  366. return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
  367. #else
  368. return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
  369. #endif
  370. }
  371. inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
  372. {
  373. ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
  374. }
  375. inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
  376. {
  377. ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
  378. }
  379. inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
  380. {
  381. #ifdef _UNICODE
  382. strcatW_x(lpstrDest, cchDest, lpstrSrc);
  383. #else
  384. strcatA_x(lpstrDest, cchDest, lpstrSrc);
  385. #endif
  386. }
  387. inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
  388. {
  389. ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
  390. }
  391. inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
  392. {
  393. ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
  394. }
  395. inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
  396. {
  397. return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
  398. }
  399. inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
  400. {
  401. return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
  402. }
  403. inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
  404. {
  405. va_list args;
  406. va_start(args, lpstrFormat);
  407. int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
  408. va_end(args);
  409. return nRes;
  410. }
  411. inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
  412. {
  413. va_list args;
  414. va_start(args, lpstrFormat);
  415. int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
  416. va_end(args);
  417. return nRes;
  418. }
  419. } // namespace SecureHelper
  420. ///////////////////////////////////////////////////////////////////////////////
  421. // MinCrtHelper - WTL10 doesn't support _ATL_MIN_CRT,
  422. // these are here only for compatibility with existing projects
  423. namespace MinCrtHelper
  424. {
  425. inline int _isspace(TCHAR ch)
  426. {
  427. return _istspace(ch);
  428. }
  429. inline int _isdigit(TCHAR ch)
  430. {
  431. return _istdigit(ch);
  432. }
  433. inline int _atoi(LPCTSTR str)
  434. {
  435. return _ttoi(str);
  436. }
  437. inline LPCTSTR _strrchr(LPCTSTR str, TCHAR ch)
  438. {
  439. return _tcsrchr(str, ch);
  440. }
  441. inline LPTSTR _strrchr(LPTSTR str, TCHAR ch)
  442. {
  443. return _tcsrchr(str, ch);
  444. }
  445. } // namespace MinCrtHelper
  446. ///////////////////////////////////////////////////////////////////////////////
  447. // GenericWndClass - generic window class usable for subclassing
  448. // Use in dialog templates to specify a placeholder to be subclassed
  449. // Specify as a custom control with class name WTL_GenericWindow
  450. // Call Rregister() before creating dialog (for example, in WinMain)
  451. namespace GenericWndClass
  452. {
  453. inline LPCTSTR GetName()
  454. {
  455. return _T("WTL_GenericWindow");
  456. }
  457. inline ATOM Register()
  458. {
  459. WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
  460. wc.lpfnWndProc = ::DefWindowProc;
  461. wc.hInstance = ModuleHelper::GetModuleInstance();
  462. wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
  463. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  464. wc.lpszClassName = GetName();
  465. ATOM atom = ::RegisterClassEx(&wc);
  466. ATLASSERT(atom != 0);
  467. return atom;
  468. }
  469. inline BOOL Unregister() // only needed for DLLs or tmp use
  470. {
  471. return ::UnregisterClass(GetName(), ModuleHelper::GetModuleInstance());
  472. }
  473. } // namespace GenericWndClass
  474. ///////////////////////////////////////////////////////////////////////////////
  475. // CMessageFilter - Interface for message filter support
  476. class CMessageFilter
  477. {
  478. public:
  479. virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
  480. };
  481. ///////////////////////////////////////////////////////////////////////////////
  482. // CIdleHandler - Interface for idle processing
  483. class CIdleHandler
  484. {
  485. public:
  486. virtual BOOL OnIdle() = 0;
  487. };
  488. ///////////////////////////////////////////////////////////////////////////////
  489. // CMessageLoop - message loop implementation
  490. class CMessageLoop
  491. {
  492. public:
  493. ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
  494. ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
  495. MSG m_msg;
  496. CMessageLoop()
  497. { }
  498. virtual ~CMessageLoop()
  499. { }
  500. // Message filter operations
  501. BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
  502. {
  503. return m_aMsgFilter.Add(pMessageFilter);
  504. }
  505. BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
  506. {
  507. return m_aMsgFilter.Remove(pMessageFilter);
  508. }
  509. // Idle handler operations
  510. BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
  511. {
  512. return m_aIdleHandler.Add(pIdleHandler);
  513. }
  514. BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
  515. {
  516. return m_aIdleHandler.Remove(pIdleHandler);
  517. }
  518. // message loop
  519. int Run()
  520. {
  521. BOOL bDoIdle = TRUE;
  522. int nIdleCount = 0;
  523. BOOL bRet;
  524. for(;;)
  525. {
  526. while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
  527. {
  528. if(!OnIdle(nIdleCount++))
  529. bDoIdle = FALSE;
  530. }
  531. bRet = ::GetMessage(&m_msg, NULL, 0, 0);
  532. if(bRet == -1)
  533. {
  534. ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
  535. continue; // error, don't process
  536. }
  537. else if(!bRet)
  538. {
  539. ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
  540. break; // WM_QUIT, exit message loop
  541. }
  542. if(!PreTranslateMessage(&m_msg))
  543. {
  544. ::TranslateMessage(&m_msg);
  545. ::DispatchMessage(&m_msg);
  546. }
  547. if(IsIdleMessage(&m_msg))
  548. {
  549. bDoIdle = TRUE;
  550. nIdleCount = 0;
  551. }
  552. }
  553. return (int)m_msg.wParam;
  554. }
  555. static BOOL IsIdleMessage(MSG* pMsg)
  556. {
  557. // These messages should NOT cause idle processing
  558. switch(pMsg->message)
  559. {
  560. case WM_MOUSEMOVE:
  561. case WM_NCMOUSEMOVE:
  562. case WM_PAINT:
  563. case 0x0118: // WM_SYSTIMER (caret blink)
  564. return FALSE;
  565. }
  566. return TRUE;
  567. }
  568. // Overrideables
  569. // Override to change message filtering
  570. virtual BOOL PreTranslateMessage(MSG* pMsg)
  571. {
  572. // loop backwards
  573. for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
  574. {
  575. CMessageFilter* pMessageFilter = m_aMsgFilter[i];
  576. if((pMessageFilter != NULL) && pMessageFilter->PreTranslateMessage(pMsg))
  577. return TRUE;
  578. }
  579. return FALSE; // not translated
  580. }
  581. // override to change idle processing
  582. virtual BOOL OnIdle(int /*nIdleCount*/)
  583. {
  584. for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
  585. {
  586. CIdleHandler* pIdleHandler = m_aIdleHandler[i];
  587. if(pIdleHandler != NULL)
  588. pIdleHandler->OnIdle();
  589. }
  590. return FALSE; // don't continue
  591. }
  592. };
  593. ///////////////////////////////////////////////////////////////////////////////
  594. // CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
  595. // internal classes to manage critical sections for ATL (deprecated)
  596. class CStaticDataInitCriticalSectionLock
  597. {
  598. public:
  599. ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
  600. CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
  601. { }
  602. HRESULT Lock()
  603. {
  604. return m_cslock.Lock();
  605. }
  606. void Unlock()
  607. {
  608. m_cslock.Unlock();
  609. }
  610. };
  611. class CWindowCreateCriticalSectionLock
  612. {
  613. public:
  614. ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
  615. CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
  616. { }
  617. HRESULT Lock()
  618. {
  619. return m_cslock.Lock();
  620. }
  621. void Unlock()
  622. {
  623. m_cslock.Unlock();
  624. }
  625. };
  626. ///////////////////////////////////////////////////////////////////////////////
  627. // CAppModule - module class for an application
  628. #if (_MSC_VER == 1400) // VS2005
  629. #pragma warning(push)
  630. #pragma warning(disable : 4244)
  631. #pragma warning(disable : 4312)
  632. #endif
  633. class CAppModule : public ATL::CComModule
  634. {
  635. public:
  636. DWORD m_dwMainThreadID;
  637. ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
  638. ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;
  639. // Overrides of CComModule::Init and Term
  640. HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
  641. {
  642. HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
  643. if(FAILED(hRet))
  644. return hRet;
  645. m_dwMainThreadID = ::GetCurrentThreadId();
  646. typedef ATL::CSimpleMap<DWORD, CMessageLoop*> _mapClass;
  647. m_pMsgLoopMap = NULL;
  648. ATLTRY(m_pMsgLoopMap = new _mapClass);
  649. if(m_pMsgLoopMap == NULL)
  650. return E_OUTOFMEMORY;
  651. m_pSettingChangeNotify = NULL;
  652. return hRet;
  653. }
  654. void Term()
  655. {
  656. TermSettingChangeNotify();
  657. delete m_pMsgLoopMap;
  658. CComModule::Term();
  659. }
  660. // Message loop map methods
  661. BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
  662. {
  663. CStaticDataInitCriticalSectionLock lock;
  664. if(FAILED(lock.Lock()))
  665. {
  666. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
  667. ATLASSERT(FALSE);
  668. return FALSE;
  669. }
  670. ATLASSERT(pMsgLoop != NULL);
  671. ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet
  672. BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
  673. lock.Unlock();
  674. return bRet;
  675. }
  676. BOOL RemoveMessageLoop()
  677. {
  678. CStaticDataInitCriticalSectionLock lock;
  679. if(FAILED(lock.Lock()))
  680. {
  681. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
  682. ATLASSERT(FALSE);
  683. return FALSE;
  684. }
  685. BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());
  686. lock.Unlock();
  687. return bRet;
  688. }
  689. CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
  690. {
  691. CStaticDataInitCriticalSectionLock lock;
  692. if(FAILED(lock.Lock()))
  693. {
  694. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
  695. ATLASSERT(FALSE);
  696. return NULL;
  697. }
  698. CMessageLoop* pLoop = m_pMsgLoopMap->Lookup(dwThreadID);
  699. lock.Unlock();
  700. return pLoop;
  701. }
  702. // Setting change notify methods
  703. // Note: Call this from the main thread for MSDI apps
  704. BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
  705. {
  706. CStaticDataInitCriticalSectionLock lock;
  707. if(FAILED(lock.Lock()))
  708. {
  709. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
  710. ATLASSERT(FALSE);
  711. return FALSE;
  712. }
  713. if(m_pSettingChangeNotify == NULL)
  714. {
  715. typedef ATL::CSimpleArray<HWND> _notifyClass;
  716. ATLTRY(m_pSettingChangeNotify = new _notifyClass);
  717. ATLASSERT(m_pSettingChangeNotify != NULL);
  718. }
  719. BOOL bRet = (m_pSettingChangeNotify != NULL);
  720. if(bRet && (m_pSettingChangeNotify->GetSize() == 0))
  721. {
  722. // init everything
  723. _ATL_EMPTY_DLGTEMPLATE templ;
  724. HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
  725. ATLASSERT(::IsWindow(hNtfWnd));
  726. if(::IsWindow(hNtfWnd))
  727. {
  728. ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
  729. bRet = m_pSettingChangeNotify->Add(hNtfWnd);
  730. }
  731. else
  732. {
  733. bRet = FALSE;
  734. }
  735. }
  736. lock.Unlock();
  737. return bRet;
  738. }
  739. void TermSettingChangeNotify()
  740. {
  741. CStaticDataInitCriticalSectionLock lock;
  742. if(FAILED(lock.Lock()))
  743. {
  744. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
  745. ATLASSERT(FALSE);
  746. return;
  747. }
  748. if((m_pSettingChangeNotify != NULL) && (m_pSettingChangeNotify->GetSize() > 0))
  749. ::DestroyWindow((*m_pSettingChangeNotify)[0]);
  750. delete m_pSettingChangeNotify;
  751. m_pSettingChangeNotify = NULL;
  752. lock.Unlock();
  753. }
  754. BOOL AddSettingChangeNotify(HWND hWnd)
  755. {
  756. CStaticDataInitCriticalSectionLock lock;
  757. if(FAILED(lock.Lock()))
  758. {
  759. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
  760. ATLASSERT(FALSE);
  761. return FALSE;
  762. }
  763. ATLASSERT(::IsWindow(hWnd));
  764. BOOL bRet = FALSE;
  765. if(InitSettingChangeNotify() != FALSE)
  766. bRet = m_pSettingChangeNotify->Add(hWnd);
  767. lock.Unlock();
  768. return bRet;
  769. }
  770. BOOL RemoveSettingChangeNotify(HWND hWnd)
  771. {
  772. CStaticDataInitCriticalSectionLock lock;
  773. if(FAILED(lock.Lock()))
  774. {
  775. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
  776. ATLASSERT(FALSE);
  777. return FALSE;
  778. }
  779. BOOL bRet = FALSE;
  780. if(m_pSettingChangeNotify != NULL)
  781. bRet = m_pSettingChangeNotify->Remove(hWnd);
  782. lock.Unlock();
  783. return bRet;
  784. }
  785. // Implementation - setting change notify dialog template and dialog procedure
  786. struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
  787. {
  788. _ATL_EMPTY_DLGTEMPLATE()
  789. {
  790. memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
  791. style = WS_POPUP;
  792. }
  793. WORD wMenu, wClass, wTitle;
  794. };
  795. static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  796. {
  797. if(uMsg == WM_SETTINGCHANGE)
  798. {
  799. CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
  800. ATLASSERT(pModule != NULL);
  801. ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
  802. const UINT uTimeout = 1500; // ms
  803. for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
  804. ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
  805. return TRUE;
  806. }
  807. return FALSE;
  808. }
  809. };
  810. #if (_MSC_VER == 1400) // VS2005
  811. #pragma warning(pop)
  812. #endif
  813. ///////////////////////////////////////////////////////////////////////////////
  814. // CServerAppModule - module class for a COM server application
  815. class CServerAppModule : public CAppModule
  816. {
  817. public:
  818. HANDLE m_hEventShutdown;
  819. bool m_bActivity;
  820. DWORD m_dwTimeOut;
  821. DWORD m_dwPause;
  822. // Override of CAppModule::Init
  823. HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
  824. {
  825. m_dwTimeOut = 5000;
  826. m_dwPause = 1000;
  827. return CAppModule::Init(pObjMap, hInstance, pLibID);
  828. }
  829. void Term()
  830. {
  831. if((m_hEventShutdown != NULL) && ::CloseHandle(m_hEventShutdown))
  832. m_hEventShutdown = NULL;
  833. CAppModule::Term();
  834. }
  835. // COM Server methods
  836. LONG Unlock() throw()
  837. {
  838. LONG lRet = CComModule::Unlock();
  839. if(lRet == 0)
  840. {
  841. m_bActivity = true;
  842. ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
  843. }
  844. return lRet;
  845. }
  846. void MonitorShutdown()
  847. {
  848. for(;;)
  849. {
  850. ::WaitForSingleObject(m_hEventShutdown, INFINITE);
  851. DWORD dwWait = 0;
  852. do
  853. {
  854. m_bActivity = false;
  855. dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
  856. }
  857. while(dwWait == WAIT_OBJECT_0);
  858. // timed out
  859. if(!m_bActivity && (m_nLockCnt == 0)) // if no activity let's really bail
  860. {
  861. #if defined(_WIN32_DCOM) && defined(_ATL_FREE_THREADED)
  862. ::CoSuspendClassObjects();
  863. if(!m_bActivity && (m_nLockCnt == 0))
  864. #endif
  865. break;
  866. }
  867. }
  868. // This handle should be valid now. If it isn't,
  869. // check if _Module.Term was called first (it shouldn't)
  870. if(::CloseHandle(m_hEventShutdown))
  871. m_hEventShutdown = NULL;
  872. ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
  873. }
  874. bool StartMonitor()
  875. {
  876. m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
  877. if(m_hEventShutdown == NULL)
  878. return false;
  879. DWORD dwThreadID = 0;
  880. #ifdef _MT
  881. HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
  882. #else
  883. HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
  884. #endif
  885. bool bRet = (hThread != NULL);
  886. if(bRet)
  887. ::CloseHandle(hThread);
  888. return bRet;
  889. }
  890. static DWORD WINAPI MonitorProc(void* pv)
  891. {
  892. CServerAppModule* p = (CServerAppModule*)pv;
  893. p->MonitorShutdown();
  894. return 0;
  895. }
  896. };
  897. ///////////////////////////////////////////////////////////////////////////////
  898. // CRegKeyEx - not used any more, here only for compatibility with old projects
  899. typedef ATL::CRegKey CRegKeyEx;
  900. } // namespace WTL
  901. ///////////////////////////////////////////////////////////////////////////////
  902. // CString forward reference (enables CString use in atluser.h and atlgdi.h)
  903. #if (defined(_WTL_USE_CSTRING) || defined(_WTL_FORWARD_DECLARE_CSTRING)) && !defined(__ATLSTR_H__)
  904. #include <atlstr.h>
  905. #endif
  906. // CString namespace
  907. #define _CSTRING_NS ATL
  908. // Type classes namespace
  909. #define _WTYPES_NS
  910. ///////////////////////////////////////////////////////////////////////////////
  911. // General DLL version helpers (removed in ATL11)
  912. #if (_ATL_VER >= 0x0B00)
  913. namespace ATL
  914. {
  915. inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
  916. {
  917. ATLASSERT(pDllVersionInfo != NULL);
  918. if(pDllVersionInfo == NULL)
  919. return E_INVALIDARG;
  920. // We must get this function explicitly because some DLLs don't implement it.
  921. DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
  922. if(pfnDllGetVersion == NULL)
  923. return E_NOTIMPL;
  924. return (*pfnDllGetVersion)(pDllVersionInfo);
  925. }
  926. inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
  927. {
  928. HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
  929. if(hInstDLL == NULL)
  930. return E_FAIL;
  931. HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
  932. ::FreeLibrary(hInstDLL);
  933. return hRet;
  934. }
  935. // Common Control Versions:
  936. // Win95/WinNT 4.0 maj=4 min=00
  937. // IE 3.x maj=4 min=70
  938. // IE 4.0 maj=4 min=71
  939. inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
  940. {
  941. ATLASSERT((pdwMajor != NULL) && (pdwMinor != NULL));
  942. if((pdwMajor == NULL) || (pdwMinor == NULL))
  943. return E_INVALIDARG;
  944. DLLVERSIONINFO dvi;
  945. ::ZeroMemory(&dvi, sizeof(dvi));
  946. dvi.cbSize = sizeof(dvi);
  947. HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);
  948. if(SUCCEEDED(hRet))
  949. {
  950. *pdwMajor = dvi.dwMajorVersion;
  951. *pdwMinor = dvi.dwMinorVersion;
  952. }
  953. else if(hRet == E_NOTIMPL)
  954. {
  955. // If DllGetVersion is not there, then the DLL is a version
  956. // previous to the one shipped with IE 3.x
  957. *pdwMajor = 4;
  958. *pdwMinor = 0;
  959. hRet = S_OK;
  960. }
  961. return hRet;
  962. }
  963. // Shell Versions:
  964. // Win95/WinNT 4.0 maj=4 min=00
  965. // IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00
  966. // IE 4.0 with Web Integrated Desktop maj=4 min=71
  967. // IE 4.01 with Web Integrated Desktop maj=4 min=72
  968. inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
  969. {
  970. ATLASSERT((pdwMajor != NULL) && (pdwMinor != NULL));
  971. if((pdwMajor == NULL) || (pdwMinor == NULL))
  972. return E_INVALIDARG;
  973. DLLVERSIONINFO dvi;
  974. ::ZeroMemory(&dvi, sizeof(dvi));
  975. dvi.cbSize = sizeof(dvi);
  976. HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);
  977. if(SUCCEEDED(hRet))
  978. {
  979. *pdwMajor = dvi.dwMajorVersion;
  980. *pdwMinor = dvi.dwMinorVersion;
  981. }
  982. else if(hRet == E_NOTIMPL)
  983. {
  984. // If DllGetVersion is not there, then the DLL is a version
  985. // previous to the one shipped with IE 4.x
  986. *pdwMajor = 4;
  987. *pdwMinor = 0;
  988. hRet = S_OK;
  989. }
  990. return hRet;
  991. }
  992. } // namespace ATL
  993. #endif // (_ATL_VER >= 0x0B00)
  994. // These are always included
  995. #include "atlwinx.h"
  996. #include "atluser.h"
  997. #include "atlgdi.h"
  998. #ifndef _WTL_NO_AUTOMATIC_NAMESPACE
  999. using namespace WTL;
  1000. #endif // !_WTL_NO_AUTOMATIC_NAMESPACE
  1001. #endif // __ATLAPP_H__