1 | //////////////////////////////////////////////////////////// |
---|
2 | // Copyright (C) Roman Ryltsov, 2006-2012 |
---|
3 | // Created by Roman Ryltsov roman@alax.info |
---|
4 | // |
---|
5 | // $Id: rowtlapp.h 77 2012-07-24 09:37:18Z roman $ |
---|
6 | // |
---|
7 | // A permission to use the source code is granted as long as reference to |
---|
8 | // 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 | |
---|
19 | class CWtlExeModuleBase; |
---|
20 | |
---|
21 | __declspec(selectany) CWtlExeModuleBase* _pWtlExeModule = NULL; |
---|
22 | |
---|
23 | #define _WtlExeModule (*_pWtlExeModule) |
---|
24 | |
---|
25 | class CWtlExeModuleBase |
---|
26 | { |
---|
27 | public: |
---|
28 | |
---|
29 | //////////////////////////////////////////////////////// |
---|
30 | // CMessageLoopMap |
---|
31 | |
---|
32 | typedef CAtlMap<DWORD, CMessageLoop*> CMessageLoopMap; |
---|
33 | |
---|
34 | private: |
---|
35 | CMessageLoopMap m_MessageLoopMap; |
---|
36 | |
---|
37 | public: |
---|
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 | |
---|
63 | template <typename T> |
---|
64 | class CWtlExeModuleT : |
---|
65 | public CWtlExeModuleBase |
---|
66 | { |
---|
67 | public: |
---|
68 | // CWtlExeModuleT |
---|
69 | CWtlExeModuleT() throw() |
---|
70 | { |
---|
71 | ATLASSERT(!_pWtlExeModule); |
---|
72 | _pWtlExeModule = this; |
---|
73 | } |
---|
74 | }; |
---|
75 | |
---|
76 | //////////////////////////////////////////////////////////// |
---|
77 | // CModuleResourceInstanceNoCompaibility |
---|
78 | |
---|
79 | class CModuleResourceInstanceNoCompaibility |
---|
80 | { |
---|
81 | public: |
---|
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 | |
---|
94 | class CModuleResourceInstanceFileVersionCompaibility |
---|
95 | { |
---|
96 | public: |
---|
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 | |
---|
120 | class CModuleResourceInstanceProductVersionCompaibility |
---|
121 | { |
---|
122 | public: |
---|
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 | |
---|
146 | template <typename T, typename _Compatibility = CModuleResourceInstanceNoCompaibility> |
---|
147 | class CModuleResourceInstanceT : |
---|
148 | protected _Compatibility |
---|
149 | { |
---|
150 | private: |
---|
151 | HMODULE m_hResourceModule; |
---|
152 | |
---|
153 | public: |
---|
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 | |
---|
265 | class CMessageManagerBase |
---|
266 | { |
---|
267 | public: |
---|
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 | |
---|
302 | public: |
---|
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 | }; |
---|