2 Copyright 1991-2017 Amebis
4 This file is part of atlex.
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.
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.
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/>.
26 #ifndef ATL_STACK_BUFFER_BYTES
28 /// Size of the stack buffer in bytes used for initial system function call
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.
38 /// Decrease this value in case of stack overflow.
40 #define ATL_STACK_BUFFER_BYTES 1024
47 /// \defgroup ATLSysHandles System Handles
48 /// Simplifies work with object handles of various type
53 /// Base abstract template class to support generic object handle keeping
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.
57 template <class T
> class CObjectWithHandleT
61 /// Datatype of the object handle this template class handles
66 /// Initializes a new class instance with the object handle set to NULL.
68 inline CObjectWithHandleT() : m_h(NULL
)
73 /// Initializes a new class instance with an available object handle.
75 /// \param[in] h Initial object handle value
77 inline CObjectWithHandleT(_In_opt_ HANDLE h
) : m_h(h
)
81 /// \name Operators for transparent usage of this class
85 /// Auto-typecasting operator
87 /// \return Object handle
89 inline operator HANDLE() const
95 /// Returns the object handle value when the object handle is a pointer to a value (class, struct, etc.).
97 /// \return Object handle value
99 inline HANDLE
*& operator*() const
101 ATLENSURE(m_h
!= NULL
);
106 /// Returns the object handle reference.
107 /// \return Object handle reference
109 inline HANDLE
* operator&()
111 ATLASSERT(m_h
== NULL
);
116 /// Provides object handle member access when the object handle is a pointer to a class or struct.
118 /// \return Object handle
120 inline HANDLE
operator->() const
122 ATLASSERT(m_h
!= NULL
);
128 /// \name Comparison operators
132 /// Tests if the object handle is NULL.
135 /// - Non zero when object handle is NULL;
136 /// - Zero otherwise.
138 inline bool operator!() const
144 /// Is handle less than?
146 /// \param[in] h Object handle to compare against
148 /// - Non zero when object handle is less than h;
149 /// - Zero otherwise.
151 inline bool operator<(_In_opt_ HANDLE h
) const
157 /// Is handle less than or equal to?
159 /// \param[in] h Object handle to compare against
161 /// - Non zero when object handle is less than or equal to h;
162 /// - Zero otherwise.
164 inline bool operator<=(_In_opt_ HANDLE h
) const
170 /// Is handle greater than or equal to?
172 /// \param[in] h Object handle to compare against
174 /// - Non zero when object handle is greater than or equal to h;
175 /// - Zero otherwise.
177 inline bool operator>=(_In_opt_ HANDLE h
) const
183 /// Is handle greater than?
185 /// \param[in] h Object handle to compare against
187 /// - Non zero when object handle is greater than h;
188 /// - Zero otherwise.
190 inline bool operator>(_In_opt_ HANDLE h
) const
196 /// Is handle not equal to?
198 /// \param[in] h Object handle to compare against
200 /// - Non zero when object handle is not equal to h;
201 /// - Zero otherwise.
203 inline bool operator!=(_In_opt_ HANDLE h
) const
205 return !operator==(h
);
209 /// Is handle equal to?
211 /// \param[in] h Object handle to compare against
213 /// - Non zero when object handle is equal to h;
214 /// - Zero otherwise.
216 inline bool operator==(_In_opt_ HANDLE h
) const
224 /// Sets a new object handle for the class
226 /// When the current object handle of the class is non-NULL, the object is destroyed first.
228 /// \param[in] h New object handle
230 inline void Attach(_In_opt_ HANDLE h
)
238 /// Dismisses the object handle from this class
240 /// \return Object handle
242 inline HANDLE
Detach()
250 /// Destroys the object
264 /// Abstract member function that must be implemented by child classes to do the actual object destruction.
266 virtual void InternalFree() = 0;
269 HANDLE m_h
; ///< Object handle
274 /// Base abstract template class to support object handle keeping for objects that support handle duplication
277 class CObjectWithHandleDuplT
: public CObjectWithHandleT
<T
>
281 /// Duplicates and returns a new object handle.
283 /// \return Duplicated object handle
285 inline HANDLE
GetDuplicate() const
287 return m_h
? InternalDuplicate(m_h
) : NULL
;
291 /// Duplicates an object handle and sets a new object handle.
293 /// \param[in] h Object handle of existing object
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()`).
298 inline BOOL
DuplicateAndAttach(_In_opt_ HANDLE h
)
303 return h
? (m_h
= InternalDuplicate(h
)) != NULL
: (m_h
= NULL
, TRUE
);
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.
311 //inline const CObjectWithHandleDuplT<T>& operator=(_In_ const HANDLE src)
313 // Attach(src ? InternalDuplicate(src) : NULL);
317 //inline const CObjectWithHandleDuplT<T>& operator=(_In_ const CObjectWithHandleDuplT<T> &src)
319 // Attach(src.m_h ? InternalDuplicate(src.m_h) : NULL);
325 /// Abstract member function that must be implemented by child classes to do the actual object handle duplication.
327 /// \param[in] h Object handle of existing object
328 /// \return Duplicated object handle
330 virtual HANDLE
InternalDuplicate(_In_ HANDLE h
) const = 0;
336 /// \defgroup ATLStrFormat String Formatting
337 /// Formatted string generation
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));
349 /// Base template class to support string formatting using `printf()` style templates
351 template<typename BaseType
, class StringTraits
>
352 class CStrFormatT
: public CStringT
<BaseType
, StringTraits
>
355 /// \name Initializing string using template in memory
359 /// Initializes a new string and formats its contents using `printf()` style template.
361 /// \param[in] pszFormat String template using `printf()` style
363 CStrFormatT(_In_z_ _Printf_format_string_ PCXSTR pszFormat
, ...)
365 ATLASSERT(AtlIsValidString(pszFormat
));
368 va_start(argList
, pszFormat
);
369 FormatV(pszFormat
, argList
);
375 /// \name Initializing string using template in resources
379 /// Initializes a new string and formats its contents using `printf()` style template in resources.
381 /// \param[in] nFormatID Resource ID of the string template using `printf()` style
383 CStrFormatT(_In_ UINT nFormatID
, ...)
385 CStringT
strFormat(GetManager());
386 ATLENSURE(strFormat
.LoadString(nFormatID
));
389 va_start(argList
, nFormatID
);
390 FormatV(strFormat
, argList
);
395 /// Initializes a new string and formats its contents using `printf()` style template in resources.
397 /// \param[in] hInstance Resource module handle
398 /// \param[in] nFormatID Resource ID of the string template using `printf()` style
400 CStrFormatT(_In_ HINSTANCE hInstance
, _In_ UINT nFormatID
, ...)
402 CStringT
strFormat(GetManager());
403 ATLENSURE(strFormat
.LoadString(hInstance
, nFormatID
));
406 va_start(argList
, nFormatID
);
407 FormatV(strFormat
, argList
);
412 /// Initializes a new string and formats its contents using `printf()` style template in resources.
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
418 CStrFormatT(_In_ HINSTANCE hInstance
, _In_ WORD wLanguageID
, _In_ UINT nFormatID
, ...)
420 CStringT
strFormat(GetManager());
421 ATLENSURE(strFormat
.LoadString(hInstance
, nFormatID
, wLanguageID
));
424 va_start(argList
, nFormatID
);
425 FormatV(strFormat
, argList
);
433 /// Wide character implementation of a class to support string formatting using `printf()` style templates
435 typedef CStrFormatT
< wchar_t, StrTraitATL
< wchar_t, ChTraitsCRT
< wchar_t > > > CStrFormatW
;
438 /// Single-byte character implementation of a class to support string formatting using `printf()` style templates
440 typedef CStrFormatT
< char, StrTraitATL
< char, ChTraitsCRT
< char > > > CStrFormatA
;
443 /// TCHAR implementation of a class to support string formatting using `printf()` style templates
445 typedef CStrFormatT
< TCHAR
, StrTraitATL
< TCHAR
, ChTraitsCRT
< TCHAR
> > > CStrFormat
;
449 /// Base template class to support string formatting using `FormatMessage()` style templates
451 template<typename BaseType
, class StringTraits
>
452 class CStrFormatMsgT
: public CStringT
<BaseType
, StringTraits
>
455 /// \name Initializing string using template in memory
459 /// Initializes a new string and formats its contents using `FormatMessage()` style template.
461 /// \param[in] pszFormat String template using `FormatMessage()` style
463 CStrFormatMsgT(_In_z_ _FormatMessage_format_string_ PCXSTR pszFormat
, ...)
465 ATLASSERT(AtlIsValidString(pszFormat
));
468 va_start(argList
, pszFormat
);
469 FormatMessageV(pszFormat
, &argList
);
475 /// \name Initializing string using template in resources
479 /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
481 /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
483 CStrFormatMsgT(_In_ UINT nFormatID
, ...)
485 CStringT
strFormat(GetManager());
486 ATLENSURE(strFormat
.LoadString(nFormatID
));
489 va_start(argList
, nFormatID
);
490 FormatMessageV(strFormat
, &argList
);
495 /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
497 /// \param[in] hInstance Resource module handle
498 /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
500 CStrFormatMsgT(_In_ HINSTANCE hInstance
, _In_ UINT nFormatID
, ...)
502 CStringT
strFormat(GetManager());
503 ATLENSURE(strFormat
.LoadString(hInstance
, nFormatID
));
506 va_start(argList
, nFormatID
);
507 FormatMessageV(strFormat
, &argList
);
512 /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
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
518 CStrFormatMsgT(_In_ HINSTANCE hInstance
, _In_ WORD wLanguageID
, _In_ UINT nFormatID
, ...)
520 CStringT
strFormat(GetManager());
521 ATLENSURE(strFormat
.LoadString(hInstance
, nFormatID
, wLanguageID
));
524 va_start(argList
, nFormatID
);
525 FormatMessageV(strFormat
, &argList
);
533 /// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
535 typedef CStrFormatMsgT
< wchar_t, StrTraitATL
< wchar_t, ChTraitsCRT
< wchar_t > > > CStrFormatMsgW
;
538 /// Single-byte character implementation of a class to support string formatting using `FormatMessage()` style templates
540 typedef CStrFormatMsgT
< char, StrTraitATL
< char, ChTraitsCRT
< char > > > CStrFormatMsgA
;
543 /// TCHAR implementation of a class to support string formatting using `FormatMessage()` style templates
545 typedef CStrFormatMsgT
< TCHAR
, StrTraitATL
< TCHAR
, ChTraitsCRT
< TCHAR
> > > CStrFormatMsg
;
549 /// \defgroup ATLMemSanitize Auto-sanitize Memory Management
550 /// Sanitizes memory before dismissed
555 /// A heap template that sanitizes each memory block before it is destroyed or reallocated
557 /// This template is typcally used to extend one of the base ATL heap management classes.
561 /// CParanoidHeap<CWin32Heap> myHeap;
565 /// CParanoidHeap introduces a performance penalty. However, it provides an additional level of security.
566 /// Use for security sensitive data memory storage only.
568 /// \sa [Memory Management Classes](https://msdn.microsoft.com/en-us/library/44yh1z4f.aspx)
570 template <class BaseHeap
>
571 class CParanoidHeap
: public BaseHeap
{
574 /// Sanitizes memory before freeing it
576 /// \param[in] p Pointer to heap memory block
578 virtual void Free(_In_opt_
void* p
)
580 // Sanitize then free.
581 SecureZeroMemory(p
, GetSize(p
));
586 /// Safely reallocates the memory block by sanitizing memory at the previous location
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.
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
598 virtual /*_Ret_opt_bytecap_(nBytes)*/ void* Reallocate(_In_opt_
void* p
, _In_
size_t nBytes
)
600 // Create a new sized copy.
601 void *pNew
= Allocate(nBytes
);
602 size_t nSizePrev
= GetSize(p
);
603 CopyMemory(pNew
, p
, nSizePrev
);
605 // Sanitize the old data then free.
606 SecureZeroMemory(p
, nSizePrev
);
615 /// Base template class to support string conversion with memory sanitization after use
617 template<int t_nBufferLength
= 128>
618 class CW2AParanoidEX
: public CW2AEX
<t_nBufferLength
> {
621 /// Initializes a new class instance with the string provided.
623 /// \param[in] psz Pointer to wide string
625 CW2AParanoidEX(_In_z_ LPCWSTR psz
) throw(...) : CW2AEX
<t_nBufferLength
>(psz
) {}
628 /// Initializes a new class instance with the string provided.
630 /// \param[in] psz Pointer to wide string
631 /// \param[in] nCodePage Code page to use when converting to single-byte string
633 CW2AParanoidEX(_In_z_ LPCWSTR psz
, _In_ UINT nCodePage
) throw(...) : CW2AEX
<t_nBufferLength
>(psz
, nCodePage
) {}
636 /// Sanitizes string memory, then destroys it
640 // Sanitize before free.
641 if (m_psz
!= m_szBuffer
)
642 SecureZeroMemory(m_psz
, _msize(m_psz
));
644 SecureZeroMemory(m_szBuffer
, sizeof(m_szBuffer
));
649 /// Support for string conversion with memory sanitization after use
651 typedef CW2AParanoidEX
<> CW2AParanoid
;