Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / ATL
Article

What's new in ATL7

Rate me:
Please Sign up or sign in to vote.
4.77/5 (19 votes)
1 May 2002CPOL4 min read 293.6K   99   32
Overview of new classes in ATL7

This article doesn't cover new ATL7 Server Classes and Attributes. This is not a complete list - only what I have found so far.

Strings
Collections
Threading
Memory Management
Files
Security
Miscellaneous

Strings

ATL3: 

String conversion macros had a few limitations. It was allocating memory from stack, with potential to overflow the stack with large strings. The string was freed when the function exited and not at any introduced scope inside the function. It was using outdated OLE2ANSI define. And if you look at the remarks for _alloca (which was used for the conversions) on MSDN, it says that it has limitations when used inside SEH or C++ EH. 

For example look at the ATL3 String Conversion Macros:

C++
USES_CONVERSION;
try
{
      for(int i=0; i< 100000; ++i)
          LPTSTR str = OLE2T(L"Some string string string string string........");  
			// stack overflow, memory on the stack grows...

      throw int(1); // if above doesn't fail, then make sure catch(int) is executed 
}
catch(int)
{
      LPTSTR str = OLE2T(L"Some string string string string string........"); 
		// _alloca can't be used in SEH or C++ EH
                    // Generates Unhandled Exception
                    // Will be marked as error in VS.NET during compile
}

ATL7: 

String Conversion macros/classes improve in those areas mentioned above. It uses stack memory for small strings and heap for large strings so there is no stack overflow when stack space is not enough. The string is freed when it's scope ends and not when function exits. Can be used in exception handlers. Can be used in loops (since it can be controlled by scope).

The macro names are easy to read. The form is as before: SourceType2[C]DestinationType
From:

A-ANSI/W-Unicode/T-generic To [Constant] A-ANSI/W-Unicode/T-generic.

CA2T/CA2CT - from ANSI to generic string based on _UNICODE define
CT2A/CT2CA - from T generic string to ANSI string based on _UNICODE define
CT2W/CT2CW - from T generic string to UNICODE string
CW2T/CW2CT - from UNICODE to generic string based on _UNICODE define
CT2WEX/CT2CWEX - from T generic to UNICODE string and buffer can be specified
CW2TEX/CW2CTEX - from UNICODE to T generic string and buffer can be specified

CA2W
- from ANSI to UNICODE
CW2A
- from UNICODE to ANSI
CW2AEX/CA2WEX - the actual class that some of the above typedef/macros use

So above code would look like this and without crash:

C++
try
{
     for(int i=0; i< 100000; ++i)
         CW2A str(L"Some string string string string string........");
     throw int(1);
}
catch(int)
{
      CW2A str(L"Some string string string string string........");
}

Be aware of one caveat. All of the above macros can't be used in same code construct as in ATL3:

LPTSTR str = CW2A(L"some string"); 

The above code is wrong. After that line the temporary object created by CW2AEX is destroyed.
Just be aware that the macros represent C++ classes and are controlled by scope rules.
To see the problem try this:

// use size 2 for initial string length to make sure stack size 
// is not enough and heap is used for memory
LPCTSTR szr = CW2AEX<2>(L"some string"); 

szr; // at this line szr should point to garbage

CString:

Another Addition is the CStringT class for manipulating strings. Even though this class exposes the same methods as previous MFC CString. It's not the old MFC CString. This class is templated. It has few typedefs to work with char, wchar_t, and TCHAR. CString is a typedef:

CStringT< TCHAR, StrTraitATL< TCHAR > > CAtlString;

which is redefined based on MFC being used or not to:

// #ifdef _AFX
typedef CAtlString CString;

The CStringT itself is shared between MFC/ATL. By default it uses CRT, but that can be changed by defining either _ATL_MIN_CRT or _ATL_CSTRING_NO_CRT. Which in turn makes the appropriate typedef visible to the compiler, for example either:

// use CRT and have more functionality
CStringT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > >

or

// don't use CRT, but use win32API string functions, (wvsprintf, lstrlen, CharNext, etc)
CStringT< TCHAR, StrTraitATL< TCHAR >, ChTraitsOS<TCHAR> > 

Another class CFixedStringT provides fixed pre-allocated contiguous buffer for optimized memory management.

The memory management for either one can be customized through implementation of IAtlStringMgr and that implementation already exists CAtlStringMgr. Its ctor takes a pointer to IAtlMemMgr, which can be any of predefined implementations or your own: 

CCRTHeap - use CRT heap
CWin32Heap - use win32 heap
CComHeap - use COM Task memory allocator

etc. So for example:

CComHeap comHeap;
CAtlStringMgr mg(&comHeap);
CString str(&mg);
str += "some string";

and we get ::CoTaskMemAlloc being used for memory allocation.

"String and Text Classes"(MSDN)

"ATL/MFC String Conversion Macros"(MSDN)

Collections

ATL7 introduces new collection classes. The classes have similar interface as previous MFC collection classes. These are templated classes
and we can pass our own CElementTraits for handling specialized cases, such as CopyElements, RelocateElements, CompareElements, and Hash.

CAtlArray/CAtlList:

// use CStringElementTraits to have a valid comparison for Find 
CAtlArray<CString, CStringElementTraits<CString> > array; 

// other traits are CStringRefElementTraits, CStringElementTraitsI
CAtlList<CString, CStringElementTraits<CString> > list;   

list.AddHead(CString("hello"));
list.AddHead(CString("string"));
POSITION pos = list.Find("hello");
if(pos != NULL)
{
    CString str = list.GetAt(pos); 
}

CAtlMap

CAtlMap<CString, int, CStringElementTraits<CString> > map;
map.InitHashTable(269);
map["key1"] = 2;
map["key2"] = 2;
int value;
if(map.Lookup("key1", value));

CRBTree/CRBMap /CRBMultiMap - Red-Black tree based implementation

CRBMap<int, int> rbMap;
rbMap.SetAt(10, 20);
rbMap.SetAt(30, 40);
CRBMap<int, int>::CPair* p = rbMap.Lookup(30);
//p->m_key; p->m_value;
rbMap.RemoveKey(30);

Various other more specialized classes:

CAutoPtrArray/CAutoPtrList /CComUnkArray /CHeapPtrList /CInterfaceArray /CInterfaceList

"Collection Classes" (MSDN)

Threading

CWorkerThread<Win32ThreadTraits|CRTThreadTraits>:

Quick example:

C++
class WorkerClass : public IWorkerThreadClient
{
    HANDLE m_hEvent;
    CWorkerThread<Win32ThreadTraits> m_thread;
public:
WorkerClass()
    {
        m_thread.Initialize();
        m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        m_thread.AddHandle(m_hEvent, this, NULL);
    }
    ~WorkerClass()
    {
        m_thread.RemoveHandle(m_hEvent);
        m_thread.Shutdown();
    }
    void ResumeThread()
    {
        ::SetEvent(m_hEvent);
    }
    void FreezeThread()
    {
        ::ResetEvent(m_hEvent);
    }
private:
 // IWorkerThreadClient
    HRESULT Execute(DWORD_PTR dwParam, HANDLE hObject)
    {
        FreezeThread();
        return S_OK;
    }
    HRESULT CloseHandle(HANDLE hHandle)
    {
        ::CloseHandle(hHandle);
        return S_OK;
    }
};

Then:
{
    WorkerClass work;
    work.ResumeThread();
    Sleep(5000);
    work.ResumeThread();
    Sleep(5000);
}

And here is imagined usage of CThreadPool:

C++
struct IDoSomeWork
{
    virtual void Work()=0;
};

class Work1 : public IDoSomeWork
{
    void Work(){}
};
class Work2 : public IDoSomeWork
{
    void Work(){}
};
class ThreadPoolWorker
{
    public:
// support for CThreadPool Worker Archetype
    typedef IDoSomeWork* RequestType;
    BOOL Initialize(void* pvWorkerParam)
    {
        return TRUE;
    }
    void Execute(RequestType request, void* pvWorkerParam,OVERLAPPED* pOverlapped)
    {
        request->Work();
    }
    void Terminate(void* pvWorkerParam)
    {
    }
};

{
    CThreadPool<ThreadPoolWorker> pool;
    pool.Initialize();
C++
IDoSomeWork* pWork1=new Work1();
pool.QueueRequest(pWork1);
C++
IDoSomeWork* pWork2=new Work2();
pool.QueueRequest(pWork2);
C++
    Sleep(5000);
    delete pWork1; delete pWork2;
}

Memory Management

CHeapPtr<CComAllocator | CCRTAllocator>:

CHeapPtr<int, CComAllocator> ptr;
ptr.Allocate(100);

// this class is not for arrays of objects, because it doesn't call delete[],
// but only delete.
CAutoPtr<CString> ptr(new CString("string"));  

CAutoVectorPtr<CString> pVec(new CString[100]); // this calls delete[]

CComGITPtr: 

Manages the pointer in GIT table. Creates the GIT and calls the IGlobalInterfaceTable methods for you.

Other more specialized classes include:

  • CAutoPtrArray
  • CAutoPtrList
  • CComHeap
  • CComHeapPtr
  • CComPtrBase
  • CCRTAllocator
  • CCRTHeap
  • CGlobalHeap
  • CHandle
  • CHeapPtrBase
  • CHeapPtrList
  • CLocalHeap
  • CWin32Heap

Memory Management Classes(MSDN)

Files

CAtlFile is a thin wrapper around the win32API for files. CreateFile, ReadFile, WriteFile, etc
CAtlTemporaryFile can be used for temporary files. They are automatically named, opened, closed, and deleted.
CAtlFileMappingBase/CAtlFileMapping can be used for mapped files:

CAtlTemporaryFile file;
CAtlFileMapping<char> filemap;
file.Create(NULL, GENERIC_READ|GENERIC_WRITE);
file.SetSize(1024);
filemap.MapFile(file, 1024, 0, PAGE_READWRITE, FILE_MAP_READ|FILE_MAP_WRITE);
char* pMem = filemap;
strcpy(pMem, "hello");

"File Handling Classes"(MSDN)

Security

ATL7 includes wrappers for win32API security.

Quick Example:

C++
CSid sidDenied;
sidDenied.LoadAccount("Leo");
CDacl dacl;
// try either deny or allow and see how OpenEvent later on behaves
dacl.AddDeniedAce(sidDenied, GENERIC_ALL);
// dacl.AddAllowedAce(sidDenied, GENERIC_ALL);
CSecurityDesc desc;
desc.SetDacl(dacl);

CSecurityAttributes secattr(desc);
// limit the access rights to the named event
CHandle hEvent(CreateEvent(&secattr, FALSE, FALSE, "NamedEvent"));

// try open it with all access rights
CHandle hEventOpen(OpenEvent(EVENT_ALL_ACCESS, FALSE, "NamedEvent"));
// if deny ace was added above it should fail. If allow ace
// was added, it should succeed
if(GetLastError() == ERROR_ACCESS_DENIED)
    ATLTRACE("\n\nAccess denied when opening event\n\n");


CSecurityDesc descCheck;
AtlGetSecurityDescriptor("NamedEvent",SE_KERNEL_OBJECT, &descCheck);
CDacl daclCheck;
descCheck.GetDacl(&daclCheck);
CSid::CSidArray sidarr;
daclCheck.GetAclEntries(&sidarr);
for(UINT i=0; i<sidarr.GetCount(); ++i)
{
    ATLTRACE("%s\n", (LPCTSTR)sidarr[i].Sid());
    ATLTRACE("%s\n", (LPCTSTR)sidarr[i].AccountName());
    ATLTRACE("%s\n", (LPCTSTR)sidarr[i].Domain());
}

"Security Classes"(MSDN)

Miscellaneous

#import can now take progid/libid and not just hard coded filename. For example:

#import <libid:20000000C-500A-100B-B005-000000000000> version("2.2")
#import "progid:SomeServer.Blah.1" embedded_idl, no_namespace

CComModule is replaced with other classes, such as: CAtlComModule/CAtlWinModule/CAtlDllModuleT/CAtlExeModuleT/CAtlServiceModuleT/etc
No more need to call Init()/Term() explicitly. The methods are now called by the appropriate ctor/dtor of the module classes.

No more need for BEGIN_OBJECT_MAP/END_OBJECT_MAP. OBJECT_ENTRY_AUTO is used instead. It's placed at global scope
and is auto generated into the ATL object map at link time. It uses linker segments to gather all the globally declared map entries into one list.

CComCurrency - wrapper for CURRENCY type
CAtlException - defines ATL related exception

CImage - depends on GDI+. Can work with jpeg, gif, bmp, png. See "CImage Limitations with Earlier Operating Systems" (MSDN)

_U_STRINGorID/_U_MENUorID/_U_RECT/CPoint/CRect/CSize - various simple wrappers. See "Utility Classes" (MSDN)

Synchronization wrappers defined in atlsync.h: CCriticalSection, CEvent, CMutex, and CSemaphore. But they are not documented in MSDN.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralCInterfaceList Pin
alireza_shokoie4-Oct-05 22:24
alireza_shokoie4-Oct-05 22:24 
GeneralJust another MFC Pin
LiangChen13-Jun-05 19:31
LiangChen13-Jun-05 19:31 
GeneralCComAutoThreadModule Pin
Eric Smith15-Jan-04 3:10
Eric Smith15-Jan-04 3:10 
GeneralRe: CComAutoThreadModule Pin
Leon Finker15-Jan-04 4:54
Leon Finker15-Jan-04 4:54 
GeneralRe: CComAutoThreadModule Pin
esmithx15-Jan-04 10:16
esmithx15-Jan-04 10:16 
GeneralRe: CComAutoThreadModule Pin
Leon Finker15-Jan-04 13:33
Leon Finker15-Jan-04 13:33 
Generalnice article Pin
Balkrishna Talele16-Dec-03 22:04
Balkrishna Talele16-Dec-03 22:04 
GeneralLarge strings in ATL3 Pin
Irek Zielinski25-Jul-03 1:23
Irek Zielinski25-Jul-03 1:23 
GeneralRe: Large strings in ATL3 Pin
Leon Finker25-Jul-03 4:52
Leon Finker25-Jul-03 4:52 
GeneralCString MFC/non-MFC. Pin
Peter Weyzen30-Jun-03 9:05
Peter Weyzen30-Jun-03 9:05 
GeneralIErrorInfo Pin
Anonymous19-Nov-02 3:21
Anonymous19-Nov-02 3:21 
GeneralRe: IErrorInfo Pin
Boze23-Dec-02 5:53
Boze23-Dec-02 5:53 
GeneralATL7 Book Pin
TigerNinja_3-Jul-02 10:49
TigerNinja_3-Jul-02 10:49 
GeneralRe: ATL7 Book Pin
Kurt Muellner22-Jul-02 5:26
Kurt Muellner22-Jul-02 5:26 
GeneralRe: ATL7 Book Pin
Aldamo26-Aug-03 17:59
Aldamo26-Aug-03 17:59 
GeneralRe: ATL7 Book Pin
Kurt Muellner26-Aug-03 20:12
Kurt Muellner26-Aug-03 20:12 
GeneralRe: ATL7 Book Pin
GotCodeToo15-Nov-06 12:42
GotCodeToo15-Nov-06 12:42 
GeneralRunning code when the compenent is being registered Pin
AndyC6-May-02 22:02
AndyC6-May-02 22:02 
GeneralRe: Running code when the compenent is being registered Pin
Leon Finker7-May-02 6:58
Leon Finker7-May-02 6:58 
GeneralThanks for the Info Pin
Joao Vaz30-Apr-02 6:00
Joao Vaz30-Apr-02 6:00 
GeneralThanx Pin
Leon Finker30-Apr-02 6:11
Leon Finker30-Apr-02 6:11 
QuestionNot too much things changed to jump from 3 to 7 version number ? Pin
Braulio Dez29-Apr-02 21:09
Braulio Dez29-Apr-02 21:09 
AnswerRe: Not too much things changed to jump from 3 to 7 version number ? Pin
Leon Finker30-Apr-02 5:45
Leon Finker30-Apr-02 5:45 
GeneralMMC SnapIn Pin
Slava Vassiliev29-Apr-02 20:44
Slava Vassiliev29-Apr-02 20:44 
GeneralRe: MMC SnapIn Pin
Leon Finker30-Apr-02 5:37
Leon Finker30-Apr-02 5:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.