Virtual Developer Workshop: Containerized Development with Docker
As the Windows SDK API continues to evolve with each major release of the operating system, it is critical for C++ developers that MFC is kept up to date with the new features that have been introduced. As MFC enters its twentieth year serving C++ developers (the first MFC version shipped with Microsoft's C/C++ 7.0 compiler in 1992), there are thousands of production systems and millions of lines of MFC code in existence that are still fit-for-purpose and will continue in operation for years if not decades to come. These systems need to continue to evolve to support new features, and MFC extensions, which keep feature-parity with the Windows SDK are quite important.
As covered in previous articles (Programming the Windows Transactional File System (TxF), and A Developer Introduction to the Kernel Transaction Manager (KTM) and Windows Transactional File System (TxF), the basis for transaction support in Windows Vista is the Kernel Transaction Manager (KTM), with the Transactional File System (TxF) and Transactional Registry (TxR) built upon the functionality offered by the KTM. Because of the closely related nature of the technologies, MFC (along with ATL) wrap the bulk of the new functionality in a single class called the CAtlTransactionManager.
The member functions of CAtlTransactionManager are great if the file and registry access for an application is being written from scratch, but there will be many cases where existing code needs to have TxF and TxR functionality retrofitted. There are two options for this - the KTM transaction handle can be retrieved from CAtlTransactionManager using the GetHandle call, and this handle can be used with the raw Windows SDK APIs to create a file or registry handle that is transaction-aware, which can in turn be used to create a CFile or CRegKey object using the overloaded constructor that takes a handle. While this option is workable, the much more elegant solution is to use the new overloaded constructors of CFile, CFileFind and CRegKey, which take a CAtlTransactionManager pointer. The file and registry objects will then operate in a transactional mode with no other code modifications other than committing or rolling back the transaction at the end of a series of operations.
MFC has adopted a dual strategy for extensions to support all the associated KTM functionality that shipped with Windows Vista - the all-purpose CAtlTransactionManager has been introduced as the 'swiss-army pocket knife' of KTM, giving access to all KTM operations from a single class. If direct KTM access isn't desirable, a transaction can simply be created with CAtlTransactionManager and then passed to overloads on existing classes to achieve transaction support. Despite its age, MFC continues to demonstrate that it can be extended in simple and logical ways to support new API features and hence continue to remain relevant to a large population of developers.