|
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.
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.
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.
The data collection classes that have been added to ATL 7.0 are listed in Table 7-1.
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 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 .
#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; }
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.
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.
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.
#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; }
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. |
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.
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- |
MultiDimSetAt | Sets the value of an element in a multi- |
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.
#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; }
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.
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 .
A number of classes are now shared between MFC and ATL. These are listed in Table 7-4 below.
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 |
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 |
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 |
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.
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.
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. |
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.
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.
#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; }
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()));
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.
Member | ATL_CSTRING_NO_CRT | 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.
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 < = ).
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:
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 |
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.
#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; }
Undefining the ATL_CSTRING_NO_CRT symbol means that the CAtlStringA class uses ANSI characters and the C Runtime Library.
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.
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.
#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; }
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.
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.
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.
#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; }
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.
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);
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.
|