Click here to Skip to main content
Click here to Skip to main content

What's new in ATL7

, 1 May 2002 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

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:

<!------------------------------- That's it! --------------------------->
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:

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:

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();
    IDoSomeWork* pWork1=new Work1();
    pool.QueueRequest(pWork1);
    IDoSomeWork* pWork2=new Work2();
    pool.QueueRequest(pWork2);
    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:

    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)

Share

About the Author

Leon Finker

United States United States
No Biography provided

Comments and Discussions

 
GeneralCInterfaceList Pinmemberalireza_shokoie4-Oct-05 22:24 
GeneralJust another MFC PinmemberLiangChen13-Jun-05 19:31 
GeneralCComAutoThreadModule PinsussEric Smith15-Jan-04 3:10 
GeneralRe: CComAutoThreadModule PinmemberLeon Finker15-Jan-04 4:54 
GeneralRe: CComAutoThreadModule Pinmemberesmith15-Jan-04 10:16 
GeneralRe: CComAutoThreadModule PinmemberLeon Finker15-Jan-04 13:33 
Generalnice article PinmemberBalkrishna Talele16-Dec-03 22:04 
GeneralLarge strings in ATL3 PinmemberIrek Zielinski25-Jul-03 1:23 
GeneralRe: Large strings in ATL3 PinmemberLeon Finker25-Jul-03 4:52 
GeneralCString MFC/non-MFC. PinmemberPeter Weyzen30-Jun-03 9:05 
GeneralIErrorInfo PinsussAnonymous19-Nov-02 3:21 
GeneralRe: IErrorInfo PinmemberBoze23-Dec-02 5:53 
GeneralATL7 Book PinmemberSoliant3-Jul-02 10:49 
GeneralRe: ATL7 Book PinmemberKurt Muellner22-Jul-02 5:26 
GeneralRe: ATL7 Book PinmemberAldamo26-Aug-03 17:59 
GeneralRe: ATL7 Book PinmemberKurt Muellner26-Aug-03 20:12 
Hi Aldamo
 
No, I have not finished the book. I'm too busy with other code projects.
 
Fast Prototyping
GeneralRe: ATL7 Book PinmemberN_Nguyen15-Nov-06 12:42 
GeneralRunning code when the compenent is being registered PinmemberAndyC6-May-02 22:02 
GeneralRe: Running code when the compenent is being registered PinmemberLeon Finker7-May-02 6:58 
GeneralThanks for the Info PinmemberJoao Vaz30-Apr-02 6:00 
GeneralThanx PinmemberLeon Finker30-Apr-02 6:11 
QuestionNot too much things changed to jump from 3 to 7 version number ? PinmemberBraulio Díez29-Apr-02 21:09 
AnswerRe: Not too much things changed to jump from 3 to 7 version number ? PinmemberLeon Finker30-Apr-02 5:45 
GeneralMMC SnapIn PinmemberSlava Vassiliev29-Apr-02 20:44 
GeneralRe: MMC SnapIn PinmemberLeon Finker30-Apr-02 5:37 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 2 May 2002
Article Copyright 2002 by Leon Finker
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid