1ea6a63e9e678c20f185211ba375e7937fb75b40
[reactos.git] / reactos / sdk / lib / 3rdparty / atlex / atlex.h
1 /*
2 Copyright 1991-2017 Amebis
3
4 This file is part of atlex.
5
6 atlex is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 atlex is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with atlex. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #pragma once
21
22 #include <atlconv.h>
23 #include <atldef.h>
24 #include <atlstr.h>
25
26 #ifndef ATL_STACK_BUFFER_BYTES
27 ///
28 /// Size of the stack buffer in bytes used for initial system function call
29 ///
30 /// Some system functions with variable length output data fail for
31 /// insufficient buffer sizes, and return an exact buffer length required.
32 /// The function helpers use a fixed size stack buffer first. If the stack
33 /// buffer really prooved sufficient, the helper allocates the exact length
34 /// output on heap and copies the data without calling the system function
35 /// again. Otherwise it allocates the exact length output on heap and retries.
36 ///
37 /// \note
38 /// Decrease this value in case of stack overflow.
39 ///
40 #define ATL_STACK_BUFFER_BYTES 1024
41 #endif
42
43
44 namespace ATL
45 {
46 ///
47 /// \defgroup ATLSysHandles System Handles
48 /// Simplifies work with object handles of various type
49 ///
50 /// @{
51
52 ///
53 /// Base abstract template class to support generic object handle keeping
54 ///
55 /// It provides basic operators and methods common to all descendands of this class establishing a base to ease the replacement of native object handle type with classes in object-oriented approach.
56 ///
57 template <class T> class CObjectWithHandleT
58 {
59 public:
60 ///
61 /// Datatype of the object handle this template class handles
62 ///
63 typedef T HANDLE;
64
65 ///
66 /// Initializes a new class instance with the object handle set to NULL.
67 ///
68 inline CObjectWithHandleT() : m_h(NULL)
69 {
70 }
71
72 ///
73 /// Initializes a new class instance with an available object handle.
74 ///
75 /// \param[in] h Initial object handle value
76 ///
77 inline CObjectWithHandleT(_In_opt_ HANDLE h) : m_h(h)
78 {
79 }
80
81 /// \name Operators for transparent usage of this class
82 /// @{
83
84 ///
85 /// Auto-typecasting operator
86 ///
87 /// \return Object handle
88 ///
89 inline operator HANDLE() const
90 {
91 return m_h;
92 }
93
94 ///
95 /// Returns the object handle value when the object handle is a pointer to a value (class, struct, etc.).
96 ///
97 /// \return Object handle value
98 ///
99 inline HANDLE*& operator*() const
100 {
101 ATLENSURE(m_h != NULL);
102 return *m_h;
103 }
104
105 ///
106 /// Returns the object handle reference.
107 /// \return Object handle reference
108 ///
109 inline HANDLE* operator&()
110 {
111 ATLASSERT(m_h == NULL);
112 return &m_h;
113 }
114
115 ///
116 /// Provides object handle member access when the object handle is a pointer to a class or struct.
117 ///
118 /// \return Object handle
119 ///
120 inline HANDLE operator->() const
121 {
122 ATLASSERT(m_h != NULL);
123 return m_h;
124 }
125
126 /// @}
127
128 /// \name Comparison operators
129 /// @{
130
131 ///
132 /// Tests if the object handle is NULL.
133 ///
134 /// \return
135 /// - Non zero when object handle is NULL;
136 /// - Zero otherwise.
137 ///
138 inline bool operator!() const
139 {
140 return m_h == NULL;
141 }
142
143 ///
144 /// Is handle less than?
145 ///
146 /// \param[in] h Object handle to compare against
147 /// \return
148 /// - Non zero when object handle is less than h;
149 /// - Zero otherwise.
150 ///
151 inline bool operator<(_In_opt_ HANDLE h) const
152 {
153 return m_h < h;
154 }
155
156 ///
157 /// Is handle less than or equal to?
158 ///
159 /// \param[in] h Object handle to compare against
160 /// \return
161 /// - Non zero when object handle is less than or equal to h;
162 /// - Zero otherwise.
163 ///
164 inline bool operator<=(_In_opt_ HANDLE h) const
165 {
166 return m_h <= h;
167 }
168
169 ///
170 /// Is handle greater than or equal to?
171 ///
172 /// \param[in] h Object handle to compare against
173 /// \return
174 /// - Non zero when object handle is greater than or equal to h;
175 /// - Zero otherwise.
176 ///
177 inline bool operator>=(_In_opt_ HANDLE h) const
178 {
179 return m_h >= h;
180 }
181
182 ///
183 /// Is handle greater than?
184 ///
185 /// \param[in] h Object handle to compare against
186 /// \return
187 /// - Non zero when object handle is greater than h;
188 /// - Zero otherwise.
189 ///
190 inline bool operator>(_In_opt_ HANDLE h) const
191 {
192 return m_h > h;
193 }
194
195 ///
196 /// Is handle not equal to?
197 ///
198 /// \param[in] h Object handle to compare against
199 /// \return
200 /// - Non zero when object handle is not equal to h;
201 /// - Zero otherwise.
202 ///
203 inline bool operator!=(_In_opt_ HANDLE h) const
204 {
205 return !operator==(h);
206 }
207
208 ///
209 /// Is handle equal to?
210 ///
211 /// \param[in] h Object handle to compare against
212 /// \return
213 /// - Non zero when object handle is equal to h;
214 /// - Zero otherwise.
215 ///
216 inline bool operator==(_In_opt_ HANDLE h) const
217 {
218 return m_h == h;
219 }
220
221 /// @}
222
223 ///
224 /// Sets a new object handle for the class
225 ///
226 /// When the current object handle of the class is non-NULL, the object is destroyed first.
227 ///
228 /// \param[in] h New object handle
229 ///
230 inline void Attach(_In_opt_ HANDLE h)
231 {
232 if (m_h)
233 InternalFree();
234 m_h = h;
235 }
236
237 ///
238 /// Dismisses the object handle from this class
239 ///
240 /// \return Object handle
241 ///
242 inline HANDLE Detach()
243 {
244 HANDLE h = m_h;
245 m_h = NULL;
246 return h;
247 }
248
249 ///
250 /// Destroys the object
251 ///
252 inline void Free()
253 {
254 if (m_h) {
255 InternalFree();
256 m_h = NULL;
257 }
258 }
259
260 /// @}
261
262 protected:
263 ///
264 /// Abstract member function that must be implemented by child classes to do the actual object destruction.
265 ///
266 virtual void InternalFree() = 0;
267
268 protected:
269 HANDLE m_h; ///< Object handle
270 };
271
272
273 ///
274 /// Base abstract template class to support object handle keeping for objects that support handle duplication
275 ///
276 template <class T>
277 class CObjectWithHandleDuplT : public CObjectWithHandleT<T>
278 {
279 public:
280 ///
281 /// Duplicates and returns a new object handle.
282 ///
283 /// \return Duplicated object handle
284 ///
285 inline HANDLE GetDuplicate() const
286 {
287 return m_h ? InternalDuplicate(m_h) : NULL;
288 }
289
290 ///
291 /// Duplicates an object handle and sets a new object handle.
292 ///
293 /// \param[in] h Object handle of existing object
294 /// \return
295 /// - TRUE when duplication succeeds;
296 /// - FALSE when duplication fails. In case of failure obtaining the extended error information is object type specific (for example: `GetLastError()`).
297 ///
298 inline BOOL DuplicateAndAttach(_In_opt_ HANDLE h)
299 {
300 if (m_h)
301 InternalFree();
302
303 return h ? (m_h = InternalDuplicate(h)) != NULL : (m_h = NULL, TRUE);
304 }
305
306 //
307 // Do not allow = operators. They are semantically ambigious:
308 // Do they attach the class to the existing instance of object, or do they duplicate it?
309 // To avoid confusion, user should use Attach() and Duplicate() methods explicitly.
310 //
311 //inline const CObjectWithHandleDuplT<T>& operator=(_In_ const HANDLE src)
312 //{
313 // Attach(src ? InternalDuplicate(src) : NULL);
314 // return *this;
315 //}
316
317 //inline const CObjectWithHandleDuplT<T>& operator=(_In_ const CObjectWithHandleDuplT<T> &src)
318 //{
319 // Attach(src.m_h ? InternalDuplicate(src.m_h) : NULL);
320 // return *this;
321 //}
322
323 protected:
324 ///
325 /// Abstract member function that must be implemented by child classes to do the actual object handle duplication.
326 ///
327 /// \param[in] h Object handle of existing object
328 /// \return Duplicated object handle
329 ///
330 virtual HANDLE InternalDuplicate(_In_ HANDLE h) const = 0;
331 };
332
333 /// @}
334
335 ///
336 /// \defgroup ATLStrFormat String Formatting
337 /// Formatted string generation
338 ///
339 /// \par Example
340 /// \code
341 /// // Please note the PCSTR typecasting invokes an operator to return
342 /// // pointer to formatted buffer rather than class reference itself.
343 /// cout << (PCSTR)(CStrFormatA("%i is less than %i.\n", 1, 5));
344 /// \endcode
345 ///
346 /// @{
347
348 ///
349 /// Base template class to support string formatting using `printf()` style templates
350 ///
351 template<typename BaseType, class StringTraits>
352 class CStrFormatT : public CStringT<BaseType, StringTraits>
353 {
354 public:
355 /// \name Initializing string using template in memory
356 /// @{
357
358 ///
359 /// Initializes a new string and formats its contents using `printf()` style template.
360 ///
361 /// \param[in] pszFormat String template using `printf()` style
362 ///
363 CStrFormatT(_In_z_ _Printf_format_string_ PCXSTR pszFormat, ...)
364 {
365 ATLASSERT(AtlIsValidString(pszFormat));
366
367 va_list argList;
368 va_start(argList, pszFormat);
369 FormatV(pszFormat, argList);
370 va_end(argList);
371 }
372
373 /// @}
374
375 /// \name Initializing string using template in resources
376 /// @{
377
378 ///
379 /// Initializes a new string and formats its contents using `printf()` style template in resources.
380 ///
381 /// \param[in] nFormatID Resource ID of the string template using `printf()` style
382 ///
383 CStrFormatT(_In_ UINT nFormatID, ...)
384 {
385 CStringT strFormat(GetManager());
386 ATLENSURE(strFormat.LoadString(nFormatID));
387
388 va_list argList;
389 va_start(argList, nFormatID);
390 FormatV(strFormat, argList);
391 va_end(argList);
392 }
393
394 ///
395 /// Initializes a new string and formats its contents using `printf()` style template in resources.
396 ///
397 /// \param[in] hInstance Resource module handle
398 /// \param[in] nFormatID Resource ID of the string template using `printf()` style
399 ///
400 CStrFormatT(_In_ HINSTANCE hInstance, _In_ UINT nFormatID, ...)
401 {
402 CStringT strFormat(GetManager());
403 ATLENSURE(strFormat.LoadString(hInstance, nFormatID));
404
405 va_list argList;
406 va_start(argList, nFormatID);
407 FormatV(strFormat, argList);
408 va_end(argList);
409 }
410
411 ///
412 /// Initializes a new string and formats its contents using `printf()` style template in resources.
413 ///
414 /// \param[in] hInstance Resource module handle
415 /// \param[in] wLanguageID Resource language
416 /// \param[in] nFormatID Resource ID of the string template using `printf()` style
417 ///
418 CStrFormatT(_In_ HINSTANCE hInstance, _In_ WORD wLanguageID, _In_ UINT nFormatID, ...)
419 {
420 CStringT strFormat(GetManager());
421 ATLENSURE(strFormat.LoadString(hInstance, nFormatID, wLanguageID));
422
423 va_list argList;
424 va_start(argList, nFormatID);
425 FormatV(strFormat, argList);
426 va_end(argList);
427 }
428
429 /// }@
430 };
431
432 ///
433 /// Wide character implementation of a class to support string formatting using `printf()` style templates
434 ///
435 typedef CStrFormatT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT< wchar_t > > > CStrFormatW;
436
437 ///
438 /// Single-byte character implementation of a class to support string formatting using `printf()` style templates
439 ///
440 typedef CStrFormatT< char, StrTraitATL< char, ChTraitsCRT< char > > > CStrFormatA;
441
442 ///
443 /// TCHAR implementation of a class to support string formatting using `printf()` style templates
444 ///
445 typedef CStrFormatT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > > CStrFormat;
446
447
448 ///
449 /// Base template class to support string formatting using `FormatMessage()` style templates
450 ///
451 template<typename BaseType, class StringTraits>
452 class CStrFormatMsgT : public CStringT<BaseType, StringTraits>
453 {
454 public:
455 /// \name Initializing string using template in memory
456 /// @{
457
458 ///
459 /// Initializes a new string and formats its contents using `FormatMessage()` style template.
460 ///
461 /// \param[in] pszFormat String template using `FormatMessage()` style
462 ///
463 CStrFormatMsgT(_In_z_ _FormatMessage_format_string_ PCXSTR pszFormat, ...)
464 {
465 ATLASSERT(AtlIsValidString(pszFormat));
466
467 va_list argList;
468 va_start(argList, pszFormat);
469 FormatMessageV(pszFormat, &argList);
470 va_end(argList);
471 }
472
473 /// @}
474
475 /// \name Initializing string using template in resources
476 /// @{
477
478 ///
479 /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
480 ///
481 /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
482 ///
483 CStrFormatMsgT(_In_ UINT nFormatID, ...)
484 {
485 CStringT strFormat(GetManager());
486 ATLENSURE(strFormat.LoadString(nFormatID));
487
488 va_list argList;
489 va_start(argList, nFormatID);
490 FormatMessageV(strFormat, &argList);
491 va_end(argList);
492 }
493
494 ///
495 /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
496 ///
497 /// \param[in] hInstance Resource module handle
498 /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
499 ///
500 CStrFormatMsgT(_In_ HINSTANCE hInstance, _In_ UINT nFormatID, ...)
501 {
502 CStringT strFormat(GetManager());
503 ATLENSURE(strFormat.LoadString(hInstance, nFormatID));
504
505 va_list argList;
506 va_start(argList, nFormatID);
507 FormatMessageV(strFormat, &argList);
508 va_end(argList);
509 }
510
511 ///
512 /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
513 ///
514 /// \param[in] hInstance Resource module handle
515 /// \param[in] wLanguageID Resource language
516 /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
517 ///
518 CStrFormatMsgT(_In_ HINSTANCE hInstance, _In_ WORD wLanguageID, _In_ UINT nFormatID, ...)
519 {
520 CStringT strFormat(GetManager());
521 ATLENSURE(strFormat.LoadString(hInstance, nFormatID, wLanguageID));
522
523 va_list argList;
524 va_start(argList, nFormatID);
525 FormatMessageV(strFormat, &argList);
526 va_end(argList);
527 }
528
529 /// @}
530 };
531
532 ///
533 /// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
534 ///
535 typedef CStrFormatMsgT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT< wchar_t > > > CStrFormatMsgW;
536
537 ///
538 /// Single-byte character implementation of a class to support string formatting using `FormatMessage()` style templates
539 ///
540 typedef CStrFormatMsgT< char, StrTraitATL< char, ChTraitsCRT< char > > > CStrFormatMsgA;
541
542 ///
543 /// TCHAR implementation of a class to support string formatting using `FormatMessage()` style templates
544 ///
545 typedef CStrFormatMsgT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > > CStrFormatMsg;
546
547 /// @}
548
549 /// \defgroup ATLMemSanitize Auto-sanitize Memory Management
550 /// Sanitizes memory before dismissed
551 ///
552 /// @{
553
554 ///
555 /// A heap template that sanitizes each memory block before it is destroyed or reallocated
556 ///
557 /// This template is typcally used to extend one of the base ATL heap management classes.
558 ///
559 /// \par Example
560 /// \code
561 /// CParanoidHeap<CWin32Heap> myHeap;
562 /// \endcode
563 ///
564 /// \note
565 /// CParanoidHeap introduces a performance penalty. However, it provides an additional level of security.
566 /// Use for security sensitive data memory storage only.
567 ///
568 /// \sa [Memory Management Classes](https://msdn.microsoft.com/en-us/library/44yh1z4f.aspx)
569 ///
570 template <class BaseHeap>
571 class CParanoidHeap : public BaseHeap {
572 public:
573 ///
574 /// Sanitizes memory before freeing it
575 ///
576 /// \param[in] p Pointer to heap memory block
577 ///
578 virtual void Free(_In_opt_ void* p)
579 {
580 // Sanitize then free.
581 SecureZeroMemory(p, GetSize(p));
582 BaseHeap::Free(p);
583 }
584
585 ///
586 /// Safely reallocates the memory block by sanitizing memory at the previous location
587 ///
588 /// This member function always performs the following steps (regardless of the current and new size):
589 /// 1. Allocates a new memory block,
590 /// 2. Copies the data,
591 /// 3. Sanitizes the old memory block,
592 /// 4. Frees the old memory block.
593 ///
594 /// \param[in] p Pointer to heap memory block
595 /// \param[in] nBytes New size in bytes
596 /// \return Pointer to the new heap memory block
597 ///
598 virtual /*_Ret_opt_bytecap_(nBytes)*/ void* Reallocate(_In_opt_ void* p, _In_ size_t nBytes)
599 {
600 // Create a new sized copy.
601 void *pNew = Allocate(nBytes);
602 size_t nSizePrev = GetSize(p);
603 CopyMemory(pNew, p, nSizePrev);
604
605 // Sanitize the old data then free.
606 SecureZeroMemory(p, nSizePrev);
607 Free(p);
608
609 return pNew;
610 }
611 };
612
613
614 ///
615 /// Base template class to support string conversion with memory sanitization after use
616 ///
617 template<int t_nBufferLength = 128>
618 class CW2AParanoidEX : public CW2AEX<t_nBufferLength> {
619 public:
620 ///
621 /// Initializes a new class instance with the string provided.
622 ///
623 /// \param[in] psz Pointer to wide string
624 ///
625 CW2AParanoidEX(_In_z_ LPCWSTR psz) throw(...) : CW2AEX<t_nBufferLength>(psz) {}
626
627 ///
628 /// Initializes a new class instance with the string provided.
629 ///
630 /// \param[in] psz Pointer to wide string
631 /// \param[in] nCodePage Code page to use when converting to single-byte string
632 ///
633 CW2AParanoidEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage) throw(...) : CW2AEX<t_nBufferLength>(psz, nCodePage) {}
634
635 ///
636 /// Sanitizes string memory, then destroys it
637 ///
638 ~CW2AParanoidEX()
639 {
640 // Sanitize before free.
641 if (m_psz != m_szBuffer)
642 SecureZeroMemory(m_psz, _msize(m_psz));
643 else
644 SecureZeroMemory(m_szBuffer, sizeof(m_szBuffer));
645 }
646 };
647
648 ///
649 /// Support for string conversion with memory sanitization after use
650 ///
651 typedef CW2AParanoidEX<> CW2AParanoid;
652
653 /// @}
654 }