Changes in ATL 7.0

team lib

A large number of changes have been made to the ATL library since ATL 3.0 was released with Visual Studio 6.0. The changes are too numerous to cover exhaustively in half a chapter, so this section discusses only major changes or those minor changes that are likely to be useful to the programmer. Consult the ATL documentation for a full list and full details.

New Module Classes

The functionality of the CComModule class has been divided up among a number of new classes. See the Creating Modules section in Chapter 6 for more details of these classes.

Data Handling and Collections

A large number of classes have been added to ATL to help with managing data. These classes can be divided into two groups: classes for managing lists, arrays, and trees; and classes that provide support for collections and enumerators. This section lists the classes that are available and shows how to work with some of the more widely used classes.

Classes for Managing Lists, Arrays, and Trees

The data collection classes that have been added to ATL 7.0 are listed in Table 7-1.

Table 7-1: Data Collection

Class

Description

CAtlArray

Implements an array class

CAtlList

Implements a doubly linked list class

CAtlMap

Implements a map class, which contains key-value pairs

CAutoPtrArray

Stores an array of smart pointers

CAutoPtrList

Stores smart pointers in a list

CComSafeArray

Provides a wrapper for the SAFEARRAY structure

CComSafeArrayBound

Provides a wrapper for the SAFEARRAYBOUND structure

CComUnkArray

Stores COM IUnknown interface pointers

CHeapPtrList

Stores a list of heap pointers

CInterfaceArray

Stores an array of COM interface pointers

CInterfaceList

Stores a list of COM interface pointers

CRBMap

Implements a map using Red-Black mapping

CRBMultiMap

Implements a map that can contain multiple keys, using Red-Black mapping

CSimpleArray

Implements a simplified array class for dealing with small numbers of objects

CSimpleMap

Implements a simplified map class for dealing with small numbers of objects

The following sections will show you how to use some of these classes, starting with the arrays.

The CSimpleArray Class

The CSimpleArray class implements a simple array-like container for managing a small number of objects. CSimpleArray is a templated class that takes two template parameters:

 template<classT,classTEqual=CSimpleArrayEqualHelper<T>> classCSimpleArray 

The first template parameter denotes the type to be stored in the array. The second parameter is optional and is used to specify a class that will be used to test array members for equality. The default class, CSimpleArrayEqualHelper , uses operator= to test array elements. If the type being stored in the array is a built-in type or defines a suitable operator= , you can treat this parameter as optional. If you need to provide special handling for equality, you can provide your own class that implements a single static IsEqual method.

CSimpleArray supports a limited range of functionality, as indicated in the following list:

  • Add and SetAtIndex modify the content of the array.

  • Remove , RemoveAll , and RemoveAt remove data from the array.

  • Find locates an element.

  • GetData gets a pointer to the data held in the object.

  • GetSize returns the number of elements in the array.

  • operator[] returns an element.

  • operator= copies elements between arrays.

The program in Listing 7-1 shows how to use CSimpleArray , and how to define a custom equality class. You can find this sample in the Chapter07\SimpleArray folder in the books companion content. This content can be downloaded from the books Web site at http://www.microsoft.com/ mspress/books/6426.asp .

Listing 7-1: SimpleArray.cpp
start example
 #include<iostream> usingnamespacestd; #include<atlbase.h> //Includetheheaderforthesimplecollections #include<atlsimpcoll.h> usingnamespaceATL; //Equalityhelperclass template<typenameT>classEqualHelper { public: staticboolIsEqual(constT&t1,constT&t2) { returnt1==t2; } }; //Specializationofhelperclassforlong* template<>classEqualHelper<long*> { public: staticboolIsEqual(constlong*t1,constlong*t2) { return*t1==*t2; } }; intmain() { //Createanarraytoholdlong* CSimpleArray<long*,EqualHelper<long*>>myArray; //Addtwovalues longl1=40000L; longl2=50000L; myArray.Add(&l1); myArray.Add(&l2); cout<< "Element0is " <<*(myArray[0])<<endl; return0; } 
end example
 

The array class is going to be used to hold pointers. This means that the default equality comparison class cannot be used because it would simply compare the values in the pointer variables . A template equality class is defined, and then a specialization for long* is provided, which compares the values behind the pointers correctly.

The CAtlArray Class

CAtlArray implements a dynamically expandable array that is more suited to handling large numbers of elements than CSimpleArray . Once again, this is a template class that takes two template parameters:

 template<typenameE,classETraits=CElementTraits<E>> classCAtlArray 

The template class is defined by the type that the array is to hold and by an element traits class that holds the code for working with elements in the array, including methods for moving, copying, comparing, and hashing elements. The default class, CElementTraits , is sufficient for simple data types; for more complex types, you can provide your own traits class.

CAtlArray provides more functionality than CSimpleArray. The members of the class are listed in Table 7-2.

Table 7-2: Members of the CAtlArray

ClassMember

Description

Add

Adds an element to the array

Append

Adds one array to the end of another

AssertValid

Causes the array object to check itself, and throw an exception if its state is invalid

Copy

Copies elements from one array to another

FreeExtra

Removes empty elements from the array

GetAt

Returns an element from the array

GetCount

Returns the number of elements in the array

GetData

Returns a pointer to the first element in the array

InsertArrayAt

Inserts one array into another

InsertAt

Inserts one or more new elements into an array

IsEmpty

Returns true if the array is empty

RemoveAll

Removes all the elements from an array

RemoveAt

Removes one or more elements from an array

SetAt

Sets the value of an element in the array

SetAtGrow

Sets the value of an element, expanding the array if required

SetCount

Sets the size of the array object

operator[]

Returns a reference to an element in the array

The sample program in Listing 7-2 shows how to create and use CAtlArray s. You can find this sample in the Chapter07\AtlArray folder in the books companion content.

Listing 7-2: AtlArray.cpp
start example
 #include<iostream> #include<string> usingnamespacestd; #include<atlbase.h> //IncludetheheaderfortheATLcollections #include<atlcoll.h> usingnamespaceATL; intmain() { //Declaretwoarraysandinitializethem CAtlArray<string>strArray1; CAtlArray<string>strArray2; strArray1.Add(string("one")); strArray1.Add(string("two")); strArray1.Add(string("three")); strArray2.Add(string("giraffe")); strArray2.Add(string("zebra")); //Insertonearrayintotheother strArray1.InsertArrayAt(1,&strArray2); //Listthearraycontents cout<< "Sizeofarray1is " <<strArray1.GetCount()<<endl; for(unsignedinti=0;i<strArray1.GetCount();i++) cout<< "Element[" <<i<< "]= " <<strArray1[i]<<endl; return0; } 
end example
 
Note 

Unlike the Standard Template Library (STL) and .NET Framework equivalents, there are no iterator classes that work with the ATL data collection classes. If you want to iterate over the elements in a collection, you will have to do it manually.

Support for SAFEARRAY s

COM programmers have to use SAFEARRAY s when passing array data to and from Microsoft Visual Basic or any other language that wants to use array objects. The problem is that SAFEARRAY is a structure, not a class. As such, it has no built-in functionality, and you need to use a number of Win32 API calls to create and manipulate SAFEARRAY s. Creating and using these structures can be a complex task, and given that there has been a class for handling BSTR s for some time, the provision of a class for handling SAFEARRAY s is long overdue.

SAFEARRAY support in ATL 7.0 is provided by two classes: CComSafeArray , which wraps the SAFEARRAY structure itself, and CComSafeArrayBound , which wraps the SAFEARRAYBOUND structure used to describe bound information.

Like all the other container classes Ive discussed so far, CComSafeArray is a templated class that takes two template parameters:

 template<typenameT, VARTYPE_vartype=_ATL_AutomationType<T>::type> classCComSafeArray 

The first parameter defines the type to be stored in the SAFEARRAY , and you can use any Automation-compatible type. The second parameter provides a way to get the type T into the SAFEARRAY managed by the object. If youre using Automation-compatible types, the default value for this parameter will generate the correct type information.

Note 

SAFEARRAY s can store only data types that can be stored in a VARIANT . For a full list of the available types, consult the CComSafeArray online help.

The most commonly used members of the CComSafeArray class are listed in Table 7-3.

Table 7-3: Members of the CComSafeArray Class

Member

Description

Add

Adds an element to the array

Attach

Attaches a SAFEARRAY to a CComSafeArray object

CopyFrom

Copies data from a SAFEARRAY into a CComSafeArray object

CopyTo

Creates a copy of a CComSafeArray object

Create

Creates a CComSafeArray object

Destroy

Destroys a CComSafeArray object

Detach

Detaches a SAFEARRAY from a CComSafeArray object

GetAt

Retrieves a single element from a one- dimensional array

GetCount

Returns the number of elements in the array

GetDimensions

Returns the number of dimensions in the array

GetLowerBound, GetUpperBound

Retrieves bound information

GetSafeArrayPtr

Gets a pointer to the SAFEARRAY structure managed by the object

GetType

Returns the type of data stored in the array

IsSizable

Returns true if the CComSafeArray is resizable

MultiDimGetAt

Gets the value of an element in a multi-
dimensional array

MultiDimSetAt

Sets the value of an element in a multi-
dimensional array

Resize

Resizes a CComSafeArray object

SetAt

Sets the value of an element in a one- dimensional array

operator[]

Returns a reference to an array element

operator=

Copies the content of one array into another

operator LPSAFEARRAY

Allows a CComSafeArray to be used where a SAFEARRAY is required

When creating a CComSafeArray , you need to specify dimension and bound information. This can be done in several ways: by specifying a lower bound, by using an existing SAFEARRAY to initialize the object, or by using a SAFEARRAYBOUND structure. The SAFEARRAYBOUND structure, which is wrapped by the CComSafeArrayBound class, holds details of the lower bound and number of elements for one dimension of a SAFEARRAY .

The sample program in Listing 7-3 shows you how to create both one- dimensional and two-dimensional CComSafeArray s. You can find this sample in the Chapter07\SafeArray folder of the books companion content.

Listing 7-3: SafeArray.cpp
start example
 #include<iostream> #include<string> usingnamespacestd; #include<atlbase.h> //IncludetheheaderforCComSafeArray #include<atlsafe.h> usingnamespaceATL; intmain() { //Createa1Darraywithfourelements,andadefault //lowerboundofzero. CComSafeArray<char>oneDArray(4); //Putan'x'inelement0,a'y'inelement1,and'z'in //thelasttwoelements oneDArray.SetAt(0,'x'); oneDArray.SetAt(1,'y'); oneDArray.SetAt(2,'z'); oneDArray.SetAt(3,'z'); for(inti=0;i<oneDArray.GetCount();i++) cout<<oneDArray[i]<< " "; cout<<endl; //CreateaCComSafeArrayBoundobjectforeachdimension //Setthelowerboundtozeroineachcase CComSafeArrayBoundbounds[2]; bounds[0].SetLowerBound(0); bounds[0].SetCount(2); bounds[1].SetLowerBound(0); bounds[1].SetCount(5); //Createanarrayobject CComSafeArray<int>twoDArray(bounds,2); //Arraytoholdindices LONGindex[2]; for(i=0;i<2;i++) { index[0]=i; for(intj=0;j<5;j++) { index[1]=j; twoDArray.MultiDimSetAt(index,i*j); } } //Getanelement index[0]=2; index[1]=3; intval=0; twoDArray.MultiDimGetAt(index,val); cout<< "Element[2,3]= " <<val<<endl; return0; } 
end example
 

The first part of the program creates a one-dimensional array of char s. Single-dimensioned arrays dont need SAFEARRAYBOUND information, so the array object can be created by simply specifying the number of elements required. The SetAt method is used to assign values to the array elements; operator[] can be used only to retrieve values because it returns a const reference.

The second part of the program creates a two-dimensional array, which requires two CComSafeArrayBound objects to hold the bounds information for each dimension. The MultiDimSetAt and MultiDimGetAt functions are used to set and retrieve elements for arrays with more than one dimension.

Support for Collections and Enumerators

COM supports the idea of enumerating a collection of objects using the IEnum family of interfaces. These provide a simple and well-known way to iterate over collections, and the IEnumVARIANT interface enables COM objects to fit in with the Visual Basics foreach statement.

C++ programmers who are up to speed with the C++ Standard Library will be accustomed to using the Standard Template Library (STL) container classes when they need to implement collections, but the problem is that there has been no easy way to integrate the STL classes with a COM IEnum interface implementation. The COM IEnum interfaces are summarized in the following list:

  • CComEnumImpl implements a COM enumerator for data stored in an array.

  • CComEnum defines a COM enumerator based on an array, inheriting from CComEnumImpl .

  • CComEnumOnSTL defines a COM enumerator based on an STL collection and implements the IEnumOnSTLImpl interface.

  • ICollectionOnSTLImpl provides methods used by collection classes, such as get_Count , get_Item , and get__NewEnum .

Shared Classes

A number of classes are now shared between MFC and ATL. These are listed in Table 7-4 below.

Table 7-4: Parameters for the Module

AttributeClass

Description

CFileTime , CFileTimeSpan

Classes for manipulating absolute and relative date and time values associated with files. Include the header < atltime.h >.

CTime , CTimeSpan

Classes for manipulating absolute and relative date and time values. Include the header
< atltime.h >.

COleDateTime , COleDateTimeSpan

Classes for manipulating OLE date and time values. Include the header < atlcomtime.h >.

CPoint , CRect , CSize

Classes that wrap the Windows POINT , RECT , and SIZE structures. Include the header
< atltypes.h >.

CStringT

A string class. Include the header < atlstr.h >.

CSimpleString

A simple string class. Include < atlsimpstr.h >.

CStrBufT

Provides automatic resource cleanup for CStringT objects. Include the header
< atlsimpstr.h >.

IAtlStringMgr

The interface to a CStringT buffer manager. Include the header < atlsimpstr.h >.

Most of these classes are simple to use or have been available in previous versions of the Microsoft Foundation Classes (MFC). The string classes, however, are new, and merit further discussion.

The CSimpleStringT Class

Many C++ programmers have become accustomed to using the CString class from the MFC library, and have found that ATL provided no suitable replacement. Several new string classes have been introduced that provide the same functionality as CString , while not being tied to the MFC library.

CSimpleStringT is the base class. It is a templated class, which takes a template parameter that defines the character set to be used. The template parameter can be one of the following:

  • CSimpleString < char > for ANSI strings

  • CSimpleString < wchar_t > for Unicode strings

  • CSimpleString < TCHAR > to enable the character set to be automatically chosen

This class provides a simple set of base functionality, as shown in Table 7-5.

Table 7-5: Members of the CSimpleStringT

ClassMember

Description

Append , AppendChar

Appends another CSimpleStringT or a character.

CopyChars , CopyCharsOverlapped

Copies characters , with or without overlapping.

Empty

Clears the data from a CSimpleStringT .

GetAt , SetAt

Returns or sets the character at a given position in the string.

GetBuffer , ReleaseBuffer

Returns a pointer to the string buffer, which can then be modified. ReleaseBuffer must be called when the buffer is finished with.

GetLength

Returns the length of the string.

GetManager , SetManager

Gets or sets a pointer to the memory manager for the string.

GetString

Returns a const pointer to the buffer.

IsEmpty

Returns true if the string is empty.

LockBuffer , UnlockBuffer

Obtains and then relinquishes exclusive use of the character buffer.

SetString

Reinitializes the buffer of a string object.

StringLength

Returns the length of a string. This is a static method.

Truncate

Truncates the string to a given length.

operator +=

Concatenates onto an existing string.

operator =

Assigns a new value to a string.

operator []

Provides a synonym for GetAt . This operator works only on the right hand side of an expression.

operator PCXSTR

Returns a const character pointer of the appropriate type.

Memory Management

Similar to many classes in the STL, the CSimpleStringT class does not implement its own memory management, but relies on the user to provide an instance of a memory manager class. Memory manager classes implement the IAtlStringMgr interface, which defines methods for handling memory allocation for strings. Separating memory management from the string class makes it possible to simply implement custom memory management, but if you dont need anything special, you can use the CAtlStringMgr class, which provides a default implementation of the interface.

The CAtlStringMgr class delegates the actual memory management task to a memory allocator class. There are five allocator classes provided by ATL:

  • CCRTHeap , which uses the malloc , realloc , and free functions.

  • CWin32Heap , which uses the Win32 heap functions HeapAlloc , HeapRealloc , and HeapFree .

  • CLocalHeap , which uses the Win32 local heap functions LocalAlloc , LocalRealloc , and LocalFree . Note that these functions are comparatively slow, and you should use the CWin32Heap allocator instead.

  • CGlobalHeap , which uses the Win32 global heap functions GlobalAlloc , GlobalRealloc , and GlobalFree . Note that these functions are comparatively slow, and unless you are required to use the global heap functions (for example, for DDE and clipboard operations), you should use the CWin32Heap allocator instead.

  • CComHeap , which uses the COM memory allocator functions CoTaskMemAlloc , CoTaskMemRealloc , and CoTaskMemFree .

This scheme gives you considerable flexibility when youre considering the data storage needs for string data. If none of the options are suitable, however, you can implement your own allocator classes by implementing the IAtlMemMgr interface.

CSimpleStringT Example

Listing 7-4 is a simple example showing the use of CSimpleStringT . You can find this sample in the Chapter07\SimpleString folder in the books companion content.

Listing 7-4: SimpleString.cpp
start example
 #include<iostream> usingnamespacestd; //IncludesneededfortheATLstringandmemoryclasses #include<atlsimpstr.h> #include<atlstr.h> #include<atlmem.h> usingnamespaceATL; intmain() { //Thestringwillbeallocatedontheheap CCRTHeaphm; //Createamanagerobjectthatusestheheap CAtlStringMgrsm(&hm); //CreateanANSIstringobject CSimpleStringT<char>s1("hello",&sm); cout<< "stringis'" <<s1<< "'"<<endl; cout<< "lengthis'" <<s1.GetLength()<< "'"<<endl; s1.SetAt(0,'H'); cout<< "stringis'" <<s1<< "'"<<endl; return0; } 
end example
 

The program shows how to use the memory management classes to ensure that string data will be stored on the heap. Although Ive shown the creation of the three initial objects as separate steps, you can combine these steps into one statement:

 CSimpleStringT<char>s1("hello",newCAtlStringMgr(newCCRTHeap())); 

The CStringT Class

CStringT provides a more fully featured string class than CSimpleStringT and has the following characteristics:

  • CStringT objects can grow by concatenation.

  • CStringT objects follow value semantics , which means that you can think of a CStringT object as an actual string, not as a pointer to a string.

  • You can freely substitute CStringT objects for character pointer function arguments.

CStringT inherits from CSimpleStringT , which means it inherits the functionality of CSimpleStringT including the ability to customize the memory management for the class. Heres the definition of the class:

 template<typenameBaseType,classStringTraits> classCStringT:publicCSimpleStringT<BaseType> 

As with CSimpleStringT , the BaseType parameter can be char , wchar_t , or TCHAR . The StringTraits parameter determines whether the class will need the C Runtime Library and where string resources are located. When you use the class with ATL (as opposed to MFC), the StringTraits parameter can be one of the following:

 //Theclassrequirestheruntimelibrary StrTraitATL<charwchar_tTCHAR, ChTraitsCRT<charwchar_tTCHAR>> //Theclassdoesnotrequiretheruntimelibrary StrTraitATL<charwchar_tTCHAR, ChTraitsOS<charwchar_tTCHAR>> 

For example, the following declaration would define a class that works with Unicode and requires the C Runtime Library:

 CStringT<StrTraitATL<wchar_t,ChTraitsCRT<wchar_t>>>MyString; 

To save programmers from having to write such complex template class declarations, a number of combinations of BaseType and StringTraits have been predefined, as listed in Table 7-6. Note how the ATL_CSTRING_NO_CRT preprocessor symbol determines whether C Runtime Library support is provided.

Table 7-6: Predefined CStringT Classes

Member

ATL_CSTRING_NO_CRT
Defined?

Description

CAtlStringA

No

ANSI character type with CRT support

CAtlStringA

Yes

ANSI character type without CRT support

CAtlStringW

No

Unicode character type with CRT support

CAtlStringW

Yes

Unicode character type without CRT support

CAtlString

No

ANSI and Unicode character types with CRT support

CAtlString

Yes

ANSI and Unicode character types without CRT support

The CStringT class adds advanced functionality, such as character manipulation, ordering, and searching. The main member functions of CStringT are summarized in Table 7-7.

Table 7-7: Members of the CStringT

ClassMember

Description

AllocSysString , SetSysString

Allocates a BSTR from a CStringT object, or copies data into an existing BSTR .

AppendFormat

Appends formatted data to a CStringT .

Collate , CollateNoCase

Compares strings using locale information.

Compare , CompareNoCase

Compares strings without using locale information.

Delete

Deletes one or more characters from a string.

Find , ReverseFind

Finds a character or substring, starting from the beginning or end of the string.

FindOneOf

Finds the first matching character from a set.

Format , FormatV

Formats a string using sprintf formatting. FormatV takes a variable argument list.

FormatMessage

Uses the FormatMessage application programming interface (API) to format a message string.

Insert

Inserts one or more characters into a string.

Left , Mid , Right

Extracts the left, middle, or right portions of a string.

LoadString

Loads a string from a Windows resource.

MakeLower , MakeUpper

Converts a string to uppercase or lower case.

MakeReverse

Reverses a string.

Remove

Removes characters from a string.

Replace

Replaces one or more characters within a string.

SpanExcluding

Returns the characters up to the first that matches a specified set.

SpanIncluding

Returns the characters up to the first that does not match a specified set.

Tokenize

Extracts a token from a string, starting at a given position.

Trim , TrimLeft , TrimRight

Trims whitespace from a string.

The CStringT class also supports a range of concatenation and assignment operators ( = , += , and + ) as well as the comparison operators ( == , != , >, > = , <, and < = ).

Predefined Types for Use with CStringT

Declaring the correct types for characters and pointers to work with a templated class such as CStringT can be complex. A number of character and pointer types have been defined to make this task easier, and they are listed in Table 7-8:

Table 7-8: Predefined Types to Work with CStringT

Type

Description

XCHAR

A single character of the same type ( char or wchar_t ) as the CStringT

YCHAR

A single character of the opposite type to the CStringT

PXSTR

A character pointer of the same type as the CStringT

PYSTR

A character pointer of the opposite type to the CStringT

PCXSTR

A const character pointer of the same type as the CStringT

PCYSTR

A const character pointer of the opposite type to the CStringT

CStringT Example

The basic sample program in Listing 7-5 shows how to declare and use a CStringT . You can find this sample in the Chapter07\CStringT folder of the books companion content.

Listing 7-5: CStringT.cpp
start example
 #include<iostream> usingnamespacestd; //WewanttheRuntimeLibrary #undefATL_CSTRING_NO_CRT //Includethestringclassheaderfile #include<atlstr.h> usingnamespaceATL; intmain() { //CreateanANSIstring CAtlStringAs1("hello"); cout<< "stringis'" <<s1<< "'"<<endl; cout<< "lengthis'" <<s1.GetLength()<< "'"<<endl; //Stringconcatenation s1+= "world"; //Changethefirstcharacter s1.SetAt(0,'H'); //Insertaspace s1.Insert(5,''); cout<< "stringis'" <<s1<< "'"<<endl; return0; } 
end example
 

Undefining the ATL_CSTRING_NO_CRT symbol means that the CAtlStringA class uses ANSI characters and the C Runtime Library.

String Conversion Classes

ATL has always provided macros to simplify the job of converting between character sets. ATL 7.0 has introduced a new set of classes to replace the ATL 3.0 macros, and these classes provide significant improvements when compared with the old macros. These improvements are summarized in Table 7-9.

Table 7-9: Comparison of String Conversion Macros and Classes

ATL 3.0 Macros

ATL 7.0 Classes

Allocates memory only for conversion on the stack, so its not good for very large strings.

Uses the heap if the stack is not large enough.

The string is freed when the function containing the macro is exited. The macros are not suitable for use in loops then because memory use grows.

The string is freed when the variable goes out of scope. This means that memory can be freed at the end of each loop iteration.

Cannot be used in exception handlers.

Can be used in exception handlers.

Usually requires USES_CONVERSION to be defined.

Never requires USES_CONVERSION to be defined.

The meaning of the OLE symbol depends on the definition of OLE2ANSI .

OLE is always equivalent to W .

The naming convention for the conversion classes has been changed, and names are now of the form

CSourceType2 [C] DestType [EX]

where the source and destination types can be the following:

  • A to denote an ANSI string.

  • W to denote a Unicode string.

  • T to denote a generic string. This will map onto ANSI or Unicode depending on whether the _UNICODE symbol is defined at compile time.

  • OLE to denote an OLE character string. This is now equivalent to W.

The optional parts of the name are C , which is used to denote a const destination string, and EX , which denotes the extended version. The extended versions take a buffer size as a template parameter and can be used when the default buffer size of 128 characters is not appropriate. For example, CW2CA would specify conversion from a wide string to a const ANSI string.

To use the conversion classes, create an object of the appropriate type by using the naming convention. This object can then be used where the appropriate destination type is required. For example take a look at Listing 7-6, available in the Chapter07\AltMacros folder of the books companion content.

Listing 7-6: AtlMacros.cpp
start example
 #include<windows.h> #include<iostream> usingnamespacestd; #undefATL_CSTRING_NO_CRT #include<atlconv.h> #include<atlstr.h> usingnamespaceATL; voidfunc1(LPSTRlps) { cout<< "func1:stringis'" <<lps<< "'" <<endl; } intmain() { //Declareawidestring LPWSTRlpws=L"widestring"; //Createaconversionobjecttoletitbeusedasan //ANSIstring.UsetheExversiontospecifya30-character //buffer CW2AEX<30>ca(lpws); //CallafunctionthatexpectsanLPSTR,passingintheCW2AEX //instance func1(ca); return0; } 
end example
 

Security Classes

A number of classes have been added to ATL to help use the Windows security system from within code.

Note 

This isnt the place to provide details on programming Windows security. For more details on this topic, see Keith Browns book, Programming Windows Security , published by Addison-Wesley, 2000.

Table 7-10 describes the security classes.

Table 7-10: The ATL Security Classes

Class

Description

CAcl

This is the base class for the CDacl and CSacl classes.

CDacl

This is a class that wraps a DACL (discretionary access control list), and gives access to the ACEs (access control entries).

CSacl

A class that wraps a SACL (system access control list), and gives access to the ACEs.

CSecurityAttributes

This class provides a thin wrapper for the SECURITY_ATTRIBUTES structure.

CSecurityDesc

This class provides a thin wrapper for the SECURITY_DESCRIPTOR structure.

CSid

This class provides a thin wrapper for the SID (security identifier) structure.

CTokenGroups

This class provides a thin wrapper for the TOKEN_GROUPS structure.

CTokenPrivileges

This class provides a thin wrapper for the TOKEN_PRIVILEGES structure.

A number of global security functions, which are commonly used with the security classes, are provided by ATL. Youll find these summarized in Table 7-11.

Table 7-11: The Global ATL Security Functions

Function

Description

AtlGetDacl , AtlSetDacl

Gets or sets the DACL associated with an object

AtlGetGroupSid , AtlSetGroupSid

Gets or sets the group SID associated with an object

AtlGetOwnerSid , AtlSetOwnerSid

Gets or sets the owner SID associated with an object

AtlGetSacl , AtlSetSacl

Gets or sets the SACL associated with an object

AtlGetSecurityDescriptor

Gets the security descriptor for an object

The sample program in Listing 7-7 shows some of these classes in action and is intended for those who have some experience of programming Win32 security. You can find this sample in the Chapter07\AtlSecurity folder of the books companion content.

Listing 7-7: AtlSecurity.cpp
start example
 #include<iostream> usingnamespacestd; //NeededbecausesomefeaturesareonlyavailableonWindows2000andlater #define_WIN32_WINNT0x0500 //Accessrights-definedin<Winnt.h> #defineSTANDARD_RIGHTS_ALL(0x001F0000L) #include<atlbase.h> #include<atlsecurity.h> #include<atlstr.h> usingnamespaceATL; intmain() { //GettheSIDforafileobject,andprintdetails.The //AtlGetOwnerSidfunctiontakesanameandanobjecttype, //andfillsinthefieldsofaCSidobject CSidsid; if(!AtlGetOwnerSid("c:\temp\output.cpp",SE_FILE_OBJECT,&sid)) cout<< "ErrorgettingSID" <<endl; else { cout<< "Account: " <<sid.AccountName()<<endl; cout<< "Domain: " <<sid.Domain()<<endl; cout<< "SID: " <<sid.Sid()<<endl; } //Getthesecuritydescriptorforthefileobject. //AtlGetSecurityDescriptortakesanameandanobjecttype, //andfillsinthefieldsofaCSecurityDescobject CSecurityDescsd; if(!AtlGetSecurityDescriptor("c:\temp\output.cpp", SE_FILE_OBJECT,&sd)) cout<< "Errorgettingsecuritydescriptor" <<endl; else { cout<< "SecurityDescriptor:" <<endl; //SECURITY_INFORMATIONdefinestheinformationbeing //setorqueried SECURITY_INFORMATIONsi=OWNER_SECURITY_INFORMATION GROUP_SECURITY_INFORMATION DACL_SECURITY_INFORMATION SACL_SECURITY_INFORMATION; //TheToStringfunctionproducesastringrepresentationof //asecuritydescriptor.Thisstringcanbeconvertedback //toasecuritydescriptorusingtheFromStringfunction. //NotethatToStringisonlyavailableonWindows2000 //andlater. CStringcs; sd.ToString(&cs,si); cout<<cs<<endl; //GettheDACLforthesecuritydescriptor,andprintsome //details CDacldcl; boolbPresent,bDefault; sd.GetDacl(&dcl,&bPresent,&bDefault); cout<< "DACL:present=" <<bPresent<<  ",defaulted=" <<bDefault<<endl; if(dcl.IsNull())cout<< "DACLisnull" <<endl; if(dcl.IsEmpty())cout<< "DACLisempty" <<endl; //AddanAccessControlEntry(ACE).First,createaSID //fortheadministratoraccount CSidsid2("Administrator"); //Addan "allow" entryforthisSIDtotheDACL if(dcl.AddAllowedAce(sid2,STANDARD_RIGHTS_ALL)) { cout<< "ACEaddedOK" <<endl; //SettheDACLbackintothesecuritydescriptor.Manyof //thesecurityfunctionsreturnaboolvalue,butSetDacl //throwsanexceptionifitfails. try { sd.SetDacl(dcl); cout<< "DACLaddedOK" <<endl; } catch(CAtlException&ae) { cout<< "ErrorsettingDACL(" <<hex<<ae.m_hr <<dec<< ")" <<endl; } } else cout<< "ErroraddingACE" <<endl; } return0; } 
end example
 

Regular Expression Classes

Two classes have been added to ATL to provide regular expression matching for strings. An instance of the CAtlRegExp class can be created to represent a regular expression, and the objects Match function can then be used to see whether the expression matches strings. Heres an example that will match dates with a dd/mm/yyyy pattern:

 //Createaregularexpressionobject CAtlRegExp<>re; //Provideanexpressionforittouse.Daysandmonths //aretwodigitswithleadingzeros,yearsarefourdigits //withaleading1or2 REParseErrorerr=re.Parse("[0-9][0-9]/[0-9][0-9]/[12][0-9][0-9][0-9] "); if(err!=REPARSE_ERROR_OK) { cout<< "Parseerror" <<endl; } else { //Testit... CAtlREMatchContext<>mc; //Getateststring cout<< "> "; cin>>buff; //Seeifthestringmatchesthepattern if(re.Match(buff,&mc)) cout<< "OK" <<endl; else cout<< "Error" <<endl; } 

CAtlRegExp is a templated class that takes a single CAtlRECharTraits template parameter, which is used to define character setdependent behavior. The default argument will suffice for most purposes, so you can create a CAtlRegExp instance using empty angle brackets.

The Parse function tells the CAtlRegExp object to parse a regular expression and use it for pattern matching. There are a number of error status codes that can be returned from this function, but if all is OK, the function will return REPARSE_ERROR_OK .

The Match function is used to test strings against the expression currently held by the CAtlRegExp object. The second argument to the function specifies a CAtlREMatchContext object, which can be used to obtain information about the match. For example, regular expressions can contain match groups that correspond to regions within the expression (such as the day or the month in the preceding example), and the context object can be used to obtain the parts of the string that matched the groups.

Other Changes

The CAdapt class has been added to make it easier to work with some ATL and COM classes. Certain classes, such as CComPtr and CComBSTR , implement operator & to return something other than the address of the object. For example, CComPtr uses operator & to return the address of the interface pointer it is managing.

Many container classes expect to be able to use operator & to get the address of the object, so it is not possible to use classes such as CComPtr and CComBSTR in these containers without modification. The CAdapt class hides the operator & implementation of the type it wraps, while still exposing the rest of the functionality of the wrapped class. Here is an example, showing how you could construct a list of CComPtr objects:

 //NotgoodbecauseCComPtr::operator&willcauseproblems std::list<CComPtr>ptrList; //CAdaptfixestheoperator&problem,whilestillgivingaccess //toCComPtr std::list<CAdapt<CComPtr>>ptrList; 

A new static CreateInstance method has been added to CComCoClass , which provides a simple way to create an instance of a COM coclass, without having to use the COM APIs. For example, if MyComClass is an ATL class that inherits from CComCoClass , you can create an instance of the class like this:

 //pIfaceisapointertotheinterfaceyourequire HRESULThr=MyComClass::CreateInstance(&pIface); 

Breaking Changes Since Visual C++ 6.0

Some of the changes that have been made to ATL since Visual Studio 6.0 might break existing code. This section lists some of the most important of these changes. For a full list, consult the ATL documentation.

The ATL DLL that shipped with Visual Studio .NET has been renamed ATL70.dll and is not binary compatible with previous releases. Any source code that uses the ATL DLL will need to be rebuilt to work with ATL 7.0.

The CComModule class has been replaced by a number of classes that divide up the functionality. See the Creating Modules section in Chapter 6 for more details about these classes.

There are now Unicode and ANSI versions of the CString class, named CStringW and CStringA . If you want to build a Unicode CString from an ANSI string or vice versa, the compiler will not allow implicit conversions because the appropriate constructors have been made explicit.

Note 

The explicit modifier can be applied to constructors to prevent them from performing implicit conversions. Such constructors have to be called explicitly.

 BSTRbstr=SysAllocString(L"Hello"); //Thisrequiresanimplicitconversion,andwillfail CStringstr=bstr; 

There are two ways to perform an explicit conversion. The first is to use the underlying type you require, as in this example:

 BSTRbstr=SysAllocString(L"Hello"); //Thisdoesnotrequireanimplicitconversion CStringWstr=bstr; 

The second is to call the constructor explicitly:

 BSTRbstr=SysAllocString(L"Hello"); //Thisdoesnotrequireanimplicitconversion CStringstr=CString(bstr); 

This behavior is controlled by the preprocessor symbol _ATL_CSTRING_EXPLICIT_CONSTRUCTORS , which is defined in stdafx.h for ATL projects. If you want, you can undefine this symbol to allow explicit conversions.

 
team lib


COM Programming with Microsoft .NET
COM Programming with Microsoft .NET
ISBN: 0735618755
EAN: 2147483647
Year: 2006
Pages: 140

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net