source: trunk/Common/alax.info/rowtlapp.h @ 937

Last change on this file since 937 was 482, checked in by roman, 9 years ago

Updated copyright notice

  • Property svn:keywords set to Id
File size: 13.1 KB
Line 
1////////////////////////////////////////////////////////////
2// Template class library; extends Widnows SDK, ATL, WTL
3//
4// Copyright (C) Roman Ryltsov, 2006-2015
5// Created by Roman Ryltsov roman@alax.info
6//
7// A permission to re-use this source code is granted as long as copyright notice and
8// reference to source website http://alax.info is retained.
9
10#pragma once
11
12#include <atlcoll.h>
13#include <atlapp.h>
14#include "roatlbase.h"
15
16////////////////////////////////////////////////////////////
17// CWtlExeModuleBase
18
19class CWtlExeModuleBase;
20
21__declspec(selectany) CWtlExeModuleBase* _pWtlExeModule = NULL;
22
23#define _WtlExeModule   (*_pWtlExeModule)
24
25class CWtlExeModuleBase
26{
27public:
28
29        ////////////////////////////////////////////////////////
30        // CMessageLoopMap
31
32        typedef CAtlMap<DWORD, CMessageLoop*> CMessageLoopMap;
33
34private:
35        CMessageLoopMap m_MessageLoopMap;
36
37public:
38// CWtlExeModuleBase
39        VOID AddMessageLoop(CMessageLoop* pMessageLoop, DWORD nThreadIdentifier = GetCurrentThreadId())
40        {
41                ATLASSERT(pMessageLoop);
42                ATLASSERT(!m_MessageLoopMap.Lookup(nThreadIdentifier));
43                ATLVERIFY(m_MessageLoopMap.SetAt(nThreadIdentifier, pMessageLoop));
44        }
45        BOOL RemoveMessageLoop(DWORD nThreadIdentifier = GetCurrentThreadId()) throw()
46        {
47                POSITION Position = m_MessageLoopMap.Lookup(nThreadIdentifier);
48                if(!Position)
49                        return FALSE;
50                m_MessageLoopMap.RemoveAtPos(Position);
51                return TRUE;
52        }
53        CMessageLoop* GetMessageLoop(DWORD nThreadIdentifier = GetCurrentThreadId()) const throw()
54        {
55                const CMessageLoopMap::CPair* pMessageLoopMapPair = m_MessageLoopMap.Lookup(nThreadIdentifier);
56                return pMessageLoopMapPair ? pMessageLoopMapPair->m_value : NULL;
57        }
58};
59
60////////////////////////////////////////////////////////////
61// CWtlExeModuleT
62
63template <typename T>
64class CWtlExeModuleT :
65        public CWtlExeModuleBase
66{
67public:
68// CWtlExeModuleT
69        CWtlExeModuleT() throw()
70        {
71                ATLASSERT(!_pWtlExeModule);
72                _pWtlExeModule = this;
73        }
74};
75
76////////////////////////////////////////////////////////////
77// CModuleResourceInstanceNoCompaibility
78
79class CModuleResourceInstanceNoCompaibility
80{
81public:
82// CModuleResourceInstanceNoCompaibility
83        static BOOL CheckResourceModuleCompatibility(HINSTANCE hModuleInstance, HINSTANCE hResourceInstance) throw()
84        {
85                hModuleInstance;
86                hResourceInstance;
87                return TRUE;
88        }
89};
90
91////////////////////////////////////////////////////////////
92// CModuleResourceInstanceFileVersionCompaibility
93
94class CModuleResourceInstanceFileVersionCompaibility
95{
96public:
97// CModuleResourceInstanceFileVersionCompaibility
98        BOOL CheckResourceModuleCompatibility(HINSTANCE hModuleInstance, HINSTANCE hResourceInstance) throw()
99        {
100                _ATLTRY
101                {
102                        _A(hModuleInstance && hResourceInstance);
103                        ULONGLONG nModuleFileVersion = _VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath(hModuleInstance));
104                        ULONGLONG nResourceFileVersion = _VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath(hResourceInstance));
105                        if(nModuleFileVersion != nResourceFileVersion)
106                                return FALSE;
107                }
108                _ATLCATCHALL()
109                {
110                        _Z_EXCEPTION();
111                        return FALSE;
112                }
113                return TRUE;
114        }
115};
116
117////////////////////////////////////////////////////////////
118// CModuleResourceInstanceProductVersionCompaibility
119
120class CModuleResourceInstanceProductVersionCompaibility
121{
122public:
123// CModuleResourceInstanceProductVersionCompaibility
124        BOOL CheckResourceModuleCompatibility(HINSTANCE hModuleInstance, HINSTANCE hResourceInstance) throw()
125        {
126                _ATLTRY
127                {
128                        _A(hModuleInstance && hResourceInstance);
129                        ULONGLONG nModuleProductVersion = _VersionInfoHelper::GetProductVersion(_VersionInfoHelper::GetModulePath(hModuleInstance));
130                        ULONGLONG nResourceProductVersion = _VersionInfoHelper::GetProductVersion(_VersionInfoHelper::GetModulePath(hResourceInstance));
131                        if(nModuleProductVersion != nResourceProductVersion)
132                                return FALSE;
133                }
134                _ATLCATCHALL()
135                {
136                        _Z_EXCEPTION();
137                        return FALSE;
138                }
139                return TRUE;
140        }
141};
142
143////////////////////////////////////////////////////////////
144// CModuleResourceInstanceT
145
146template <typename T, typename _Compatibility = CModuleResourceInstanceNoCompaibility>
147class CModuleResourceInstanceT :
148        protected _Compatibility
149{
150private:
151        HMODULE m_hResourceModule;
152
153public:
154// CModuleResourceInstanceT
155#if defined(REGISTRY_ROOT)
156        static LPCTSTR GetResourceInstanceRegistryKeyName() throw()
157        {
158                return REGISTRY_ROOT _T("\\Locale");
159        }
160#endif // defined(REGISTRY_ROOT)
161        static CString GetResourceInstanceRegistryValueName(HINSTANCE hModuleInstance)
162        {
163                CPath sModulePath = _VersionInfoHelper::GetModulePath(hModuleInstance);
164                sModulePath.RemoveExtension();
165                return (LPCTSTR) sModulePath + sModulePath.FindFileName();
166        }
167        static LPCTSTR GetResourceInstanceRegistryDefaultValueName() throw()
168        {
169                static const LPCTSTR g_pszDefaultValueName = _T("Default");
170                return g_pszDefaultValueName;
171        }
172        static LCID GetModuleLocale(HINSTANCE hModuleInstance)
173        {
174                CString sModuleValueName = GetResourceInstanceRegistryValueName(hModuleInstance);
175                static const HKEY g_phKeys[] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, };
176                for(SIZE_T nKeyIndex = 0; nKeyIndex < _countof(g_phKeys); nKeyIndex++)
177                {
178                        CRegKey Key;
179                        if(FAILED(HRESULT_FROM_WIN32(Key.Open(g_phKeys[nKeyIndex], T::GetResourceInstanceRegistryKeyName(), KEY_READ))))
180                                continue;
181                        DWORD nValue;
182                        if(_RegKeyHelper::QueryIntegerValueEx(Key, sModuleValueName, nValue))
183                                return nValue;
184                        if(_RegKeyHelper::QueryIntegerValueEx(Key, T::GetResourceInstanceRegistryDefaultValueName(), nValue))
185                                return nValue;
186                }
187                return ConvertDefaultLocale(LOCALE_USER_DEFAULT);
188        }
189        static CPath GetResourceModuleDirectory()
190        {
191                static const LPCTSTR g_pszPathValueName = _T("Satellite Path");
192                CString sDirectory;
193                if(_RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, T::GetResourceInstanceRegistryKeyName(), g_pszPathValueName, sDirectory))
194                        return (LPCTSTR) sDirectory;
195                if(_RegKeyHelper::QueryStringValue(HKEY_LOCAL_MACHINE, T::GetResourceInstanceRegistryKeyName(), g_pszPathValueName, sDirectory))
196                        return (LPCTSTR) sDirectory;
197                return (LPCTSTR) NULL;
198        }
199        static LPCTSTR GetResourceModuleNameFormat() throw()
200        {
201                // NOTE: Name, Language, Extendion
202                return _T("%s.lang-%d%s");
203        }
204        static CString GetResourceModuleName(HINSTANCE hModuleInstance, LANGID nLanguage)
205        {
206                CPath sModuleName = _VersionInfoHelper::GetModulePath(hModuleInstance);
207                sModuleName.RemoveExtension();
208                CString sExtension = _T(".dll"); //(LPCTSTR) sModuleName + sModuleName.FindExtension();
209                return AtlFormatString(T::GetResourceModuleNameFormat(), (LPCTSTR) sModuleName + sModuleName.FindFileName(), nLanguage, sExtension);
210        }
211        CModuleResourceInstanceT() throw() :
212                m_hResourceModule(NULL)
213        {
214        }
215        ~CModuleResourceInstanceT() throw()
216        {
217                SetResourceModule(NULL);
218        }
219        HMODULE GetResourceModule() const throw()
220        {
221                return m_hResourceModule;
222        }
223        VOID SetResourceModule(HMODULE hResourceModule) throw()
224        {
225                if(m_hResourceModule != hResourceModule)
226                {
227                        if(m_hResourceModule && m_hResourceModule != _AtlBaseModule.GetModuleInstance())
228                                _W(FreeLibrary(m_hResourceModule));
229                        m_hResourceModule = hResourceModule;
230                }
231        }
232        HINSTANCE DecideResourceInstance(HINSTANCE hModuleInstance, HINSTANCE hResourceInstance)
233        {
234                T* pT = static_cast<T*>(this);
235                CPath sResourceLibraryName = pT->GetResourceModuleName(hModuleInstance, LANGIDFROMLCID(GetModuleLocale(hModuleInstance)));
236                CPath sModuleDirectory = _VersionInfoHelper::GetModulePath();
237                _W(sModuleDirectory.RemoveFileSpec());
238                CPath sResourceLibraryPath;
239                sResourceLibraryPath.Combine(sModuleDirectory, sResourceLibraryName);
240                if(!sResourceLibraryPath.FileExists())
241                {
242                        sResourceLibraryPath.Combine(pT->GetResourceModuleDirectory(), sResourceLibraryName);
243                        if(!sResourceLibraryPath.FileExists())
244                                return hResourceInstance;
245                }
246                _A(sResourceLibraryPath.FileExists());
247                HMODULE hResourceModule = LoadLibraryEx(sResourceLibraryPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
248                if(!hResourceModule)
249                        return hResourceInstance;
250                if(!pT->CheckResourceModuleCompatibility(hModuleInstance, hResourceModule))
251                        return hResourceInstance;
252                _Z2(atlTraceGeneral, 2, _T("Using resource library %s\n"), sResourceLibraryPath);
253                SetResourceModule(hResourceModule);
254                return m_hResourceModule;
255        }
256        HINSTANCE DecideResourceInstance()
257        {
258                return DecideResourceInstance(_AtlBaseModule.GetModuleInstance(), _AtlBaseModule.GetResourceInstance());
259        }
260};
261
262////////////////////////////////////////////////////////////
263// CMessageManagerBase
264
265class CMessageManagerBase
266{
267public:
268
269        ////////////////////////////////////////////////////////
270        // FACILITYMODULENAME
271
272        typedef struct _FACILITYMODULENAME
273        {
274                UINT nFacility;
275                LPCTSTR pszModuleName;
276        } FACILITYMODULENAME;
277
278        ////////////////////////////////////////////////////////
279        // FACILITYCODERANGEMODULENAMEFLAGS
280
281        typedef enum _FACILITYCODERANGEMODULENAMEFLAGS
282        {
283                FACILITYCODERANGEMODULENAMEFLAGS_NONE = 0,
284                FACILITYCODERANGEMODULENAMEFLAG_ANYFACILITY = 1,
285                FACILITYCODERANGEMODULENAMEFLAG_ANYCODE = 2,
286                FACILITYCODERANGEMODULENAMEFLAG_LOADLIBRARYASDATAFILE = 4,
287                FACILITYCODERANGEMODULENAMEFLAG_CODEMESSAGEIDENTIFIER = 8,
288        } FACILITYCODERANGEMODULENAMEFLAGS;
289
290        ////////////////////////////////////////////////////////
291        // FACILITYCODERANGEMODULENAME
292
293        typedef struct _FACILITYCODERANGEMODULENAME
294        {
295                LPCTSTR pszModuleName;
296                FACILITYCODERANGEMODULENAMEFLAGS Flags;
297                UINT nFacility;
298                UINT nFirstCode;
299                UINT nLastCode;
300        } FACILITYCODERANGEMODULENAME;
301
302public:
303// CMessageManagerBase
304        static CString FormatMessage(DWORD nFlags, const VOID* pvSource, DWORD nMessageIdentifier, LANGID nLanguageIdentifier = LANG_USER_DEFAULT)
305        {
306                _A((nFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) == 0);
307                CHeapPtr<TCHAR, CLocalAllocator> pszMessage;
308                DWORD nFormatMessageResult = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | nFlags, pvSource, nMessageIdentifier, nLanguageIdentifier, (LPTSTR) &pszMessage, 0, NULL);
309                ATLTRACE(atlTraceGeneral, 5, _T("nMessageIdentifier 0x%08x, nFormatMessageResult 0x%08x\n"), nMessageIdentifier, HRESULT_FROM_WIN32(GetLastError()));
310                nFormatMessageResult;
311                return (TCHAR*) pszMessage;
312        }
313        static CString FormatMessageFromSystem(DWORD nMessageIdentifier, LANGID nLanguageIdentifier = LANG_USER_DEFAULT)
314        {
315                return FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, nMessageIdentifier, nLanguageIdentifier);
316        }
317        static CString FormatMessageFromModule(HMODULE hModule, DWORD nMessageIdentifier, LANGID nLanguageIdentifier = LANG_USER_DEFAULT)
318        {
319                return FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, hModule, nMessageIdentifier, nLanguageIdentifier);
320        }
321        static BOOL IsEmptyMessage(CString& sMessage, const CString& sSourceMessage) throw()
322        {
323                sMessage = sSourceMessage;
324                return sMessage.IsEmpty();
325        }
326        static CString FormatResultFromNativeModule(HRESULT nResult, LANGID nLanguageIdentifier = LANG_USER_DEFAULT)
327        {
328                return FormatMessageFromModule(_AtlBaseModule.GetResourceInstance(), nResult, nLanguageIdentifier);
329        }
330        static CString FormatResultFromModules(HRESULT nResult, const FACILITYMODULENAME* pModuleNames, SIZE_T nModuleNameCount, LANGID nLanguageIdentifier = LANG_USER_DEFAULT)
331        {
332                _A(pModuleNames);
333                UINT nFacility = HRESULT_FACILITY(nResult);
334                CString sMessage;
335                for(SIZE_T nIndex = 0; nIndex < nModuleNameCount; nIndex++)
336                {
337                        const FACILITYMODULENAME& ModuleName = pModuleNames[nIndex];
338                        if(nFacility != ModuleName.nFacility)
339                                continue;
340                        HMODULE hModule = LoadLibraryEx(ModuleName.pszModuleName, NULL, LOAD_LIBRARY_AS_DATAFILE);
341                        if(!hModule)
342                                continue;
343                        sMessage = FormatMessageFromModule(hModule, nResult, nLanguageIdentifier);
344                        _W(FreeLibrary(hModule));
345                        break;
346                }
347                return sMessage;
348        }
349        static CString FormatResultFromModules(HRESULT nResult, const FACILITYCODERANGEMODULENAME* pModuleNames, SIZE_T nModuleNameCount, LANGID nLanguageIdentifier = LANG_USER_DEFAULT)
350        {
351                _A(pModuleNames);
352                CString sMessage;
353                UINT nFacility = HRESULT_FACILITY(nResult);
354                UINT nCode = HRESULT_CODE(nResult);
355                for(SIZE_T nIndex = 0; nIndex < nModuleNameCount; nIndex++)
356                {
357                        const FACILITYCODERANGEMODULENAME& ModuleName = pModuleNames[nIndex];
358                        if(!(ModuleName.Flags & FACILITYCODERANGEMODULENAMEFLAG_ANYFACILITY) && nFacility != ModuleName.nFacility)
359                                continue;
360                        if(!(ModuleName.Flags & FACILITYCODERANGEMODULENAMEFLAG_ANYCODE) && (nCode < ModuleName.nFirstCode || nCode > ModuleName.nLastCode))
361                                continue;
362                        _A(ModuleName.pszModuleName);
363                        HMODULE hModule = (ModuleName.Flags & FACILITYCODERANGEMODULENAMEFLAG_LOADLIBRARYASDATAFILE) ? LoadLibraryEx(ModuleName.pszModuleName, NULL, LOAD_LIBRARY_AS_DATAFILE) : GetModuleHandle(ModuleName.pszModuleName);
364                        if(!hModule)
365                                continue;
366                        DWORD nMessageIdentifier = (ModuleName.Flags & FACILITYCODERANGEMODULENAMEFLAG_CODEMESSAGEIDENTIFIER) ? nCode : nResult;
367                        sMessage = FormatMessageFromModule(hModule, nMessageIdentifier, nLanguageIdentifier);
368                        if(ModuleName.Flags & FACILITYCODERANGEMODULENAMEFLAG_LOADLIBRARYASDATAFILE)
369                                _W(FreeLibrary(hModule));
370                        if(!sMessage.IsEmpty())
371                                break;
372                }
373                return sMessage;
374        }
375};
Note: See TracBrowser for help on using the repository browser.