Changes made to ATL 3.0 in Borland C++Builder 5

By: Robert West

Abstract: Notes on the exact changes made to ATL3.0 for Borland C++Builder 5

As part of the release of C++Builder 5.0, changes were made to the Active Template Library (ATL) version 3.0, mostly for the purpose of working around differences between the behavior of the Microsoft and Borland C++ Compilers. Several other changes were made in response to recommendations found in technical notes on Microsoft's web site. This document lists the changes that were made. Except where otherwise noted, all changes are wrapped with either #ifdef __BORLANDC__ or #ifndef __BORLANDC__.

Note: This document does not list changes made to ATLMOD or ATLVCL, the files which provide the 'glue' between the Visual Component Library (VCL) and the ATL.

A number of changes were made due to differences in the compiler's mechanism for handling precompiled headers. The Borland C++ compiler does not allow the inclusion of initialized static data in precompiled headers even in cases where the data was declared with use of __declspec(selectany), nor does it allow executable code in precompiled headers. In order to allow precompiling of ATL headers, those parts of the code which were not allowed in the headers were removed and placed in BCBATLLIB.CPP, which was built into BCBATL.LIB; instructions to the linker to pull in this library are included in several headers.

Specific changes made for precompiled header compatibility were:

  • ATLBASE.H (22): added #pragma comment(lib, "bcbatl.lib")
  • ATLBASE.H (97-113): replace GUID declarations which use __declspec(selectany) with declarations that are extern, and defined in bcbatllib.cpp
  • ATLBASE.H (431-448): move the definition of the function AtlSetChildSite out of the header and into bcbatllib.cpp
  • ATLBASE.H (2436-2445): replace the definitions of _pModule and GUID_ATLVer30 with declarations, and put the definitions in bcbatllib.cpp
  • ATLBASE.H (2786-2819): replace IMPL_THUNK(x), which places code in the header, with a new one that uses __emit
  • ATLBASE.H (3846-3848): move CComModule::m_libid definition to bcbatllib.cpp
  • ATLBASE.H (3916-3918): move CComApartment::ATL_CREATE_OBJECT definition to bcbatllib.cpp
  • ATLBASE.H (5076-5096, 5148-5157): replace initialized TCHARs in CComModule::RegisterClassHelper with macros, and then undefine them after they're no longer wanted.
  • ATLBASE.H (5375-5394): move AtlGetDirLen definition into bcbatllib.cpp
  • ATLCOM.H (182-303): move CComDispatchDriver::Invoke, CComDispatchDriver::Invoke1, CComDispatchDriver::InvokeN, CComDispatchDriver::GetProperty and CComDispatchDriver::PutProperty into bcbatllib.cpp because they require the use of intiialized DISPPARAM structures.
  • ATLHOST.H (53-59) move the definitions of WM_ATLGETHOST and WM_ATLGETCONTROL to bcbatllib.cpp
  • ATLSNAP.H (22-24): force linkage to bcbatl.lib
  • ATLWIN.H (1331): move CWindow::rcDefault into bcbatllib.cpp
  • STATREG.H (18): add #pragma comment(lib, "bcbatl.lib")
  • STATREG.H (463-472) move the definitions of static data within CRegParser to bcbatllib.cpp
  • STATREG.H (671,684,775,789,866): because the precompiler is unhappy with using macros as array initializers, specify '4096' instead of MAX_TYPE.
In addition to the changes above, the use of BEGIN_COM_MAP in CComClassFactory and CComClassFactoryAutoThread had to be changed. Because BEGIN_COM_MAP and END_COM_MAP use inline functions which will not live in the header files, they needed to be replaced with a mechanism that allowed declarations to go in the header and definitions in the library. Thus, the following macros were added:
  • BEGIN_HEADER_COM_MAP
  • BEGIN_IMPL_COM_MAP
  • END_HEADER_COM_MAP
  • END_HEADER_IMPL_MAP
  • COM_IMPL_INTERFACE_ENTRY
CComClassFactory and CComClassFactoryAutoThread, in atlcom.h, were then modified to use the new macros, both in the header and in the library, as appropriate.

Other changes were required by differences in the way that import libraries are handled. In Visual C++, seperate system DLLs each get their own import library; in C++Builder, the imports for all system DLLs are combined into a single import library which is linked into all projects. In addition, atl.lib does not exist in C++Builder. Thus, the following changes:

  • ATLBASE.H (23): _ATL_NO_FORCE_LIBS is defined
  • ATLBASE.H (93): atl.lib linkage is disabled
  • ATLBASE.H (420-428): linkage of system import libraries is disabled
  • ATLCTL.H (27-29): linkage of system import libraries is disabled
  • ATLSNAP.H (17-20): linkage of system import libraries is disabled

Some changes were required because of differences in the way the compilers handle language constructs. In particular, some warnings are more vigorously generated in C++Builder than in Visual C++; the scoping rules for foor loop iterators declared within the loop are different between the two compilers; and certain cast requirements are enforced less vigorously by Visual C++. Changes of this nature were:

  • ATLBASE.H (46): Turn off the warning for unreachable code, because the ATL headers have a tendency to have default case statements with a break and then a return (the return is unreachable).
  • ATLBASE.H (47): Turn off the warning for 'condition is alwyas true' in order to avoid warnings about statements where enumerated values and defined values are and'd together.
  • ATLCOM.H (2032): define _ATL_IIDOF(x) to be IID_##x in all cases, because system interfaces are not declared using declspec(__uuid)
  • ATLCOM.H (3431): replace __uuidof(ITypeInfo2) with IID_ITypeInfo2 in the QI call inside of CComTypeInfoHolder::GetTI
  • ATLCOM.H (4441) explicitly cast values to IUnknown* inside of CComEnumImpl::Clone
  • ATLDB.H (2708-2722): add an additional {} to rescope a for loop which redeclares a previously declared iterator. [C++ standard specifies that these iterators go out of scope at the end of the for loop. The rule is enforced by C++Builder but not by Visual C++. Because this file is often compiled with the 'MS Compatability' switch on, and C++Builder flags 'long i' and 'int i' as a redeclaration in this context, whereas Visual C++ would not, the scoping is needed to resolve the problem.)
  • ATLDBCLI.H (303-307): explicitly cast &spSupportErrorInfo to a void** inside a QI call in CDBErrorInfo::GetErrorRecords
  • ATLWIN.H (1762-1767): move the declaration of a for-loop iterator outside of the declaration of the for loop, so that attempts to ues the same iterator in subsequent loops do not fail.
  • STATREG.H (19, 1155) turn on the MS Compatability compiler option, and then turn it off again at the end of the file.

A handful of changes were made due to differences in the handling of header files.

  • ATLBASE.H (25): If USING_ATLVCL is defined (this define is set by the IDE in all ATL Projects), then turn on _ATL_NO_DEBUG_CRT because crtdbg.h isn't shipped as part of the BCB RTL. If it isn't defined, then assume that MFC is being linked to, and use its crtdbg.
  • ATLBASE.H (51, 73, 78, 85): change the include style from double-angle to double-quote because includeatl is not guaranteed to be in the include path
  • ATLBASE.H (951): if GUIDDEF.H has already been included, use the InlineIsEqualGUID from that header instead of the one in atlbase.h

The following changes were made to fix bugs in the ATL itself. In most cases they were recommended by Microsoft via their web site:

  • ATLCONV.H (217-218): In the function A2WBSTR, if a negative length was passed in, the value returned by MultiByteToWideChar will be 0. This value, when passed to SysAllocStringLen, will not behave as desired, and needs to be decremented first. This change is NOT guarded.
  • ATLDB.H (6365) in the PROVIDER_COLUMN_ENTRY statement, remove an extraneous comma. This change is NOT guarded.
  • ATLCOM.H (5301) insert a delay between the posting of the thread message and blocking on it, to prevent deadlocking. This change is NOT guarded.
  • ATLIMPL.CPP (166-181) add a test in order to prevent calling Heap Free on an invalid handle when operating on SMP machines. See MS Q190531.

In addition, the explicit override in ATLBASE.H of CComQIPtr is disabled because it is not needed.

Also, ATLBASE.H, ATLCTL.H, ATLDB.H, ATLDBCLI.H, ATLDEF.H, ATLWIN.H, and STATREG.H have code added which allows the IDE to set the define: _BCB_ATL_DEBUG, and have that turn on _DEBUG when appropriate.


Server Response from: ETNASC04