So you have a WTL project but it’s not a COM server you’re writing?

Well, not exactly surprising if you write a GUI application like my NT Objects.

Turns out that ATL forces you to have support for COM server registration, as soon as you use anything derived from CComModule. Doh. And yeah, that includes all that pesky registry script syntax and what not …

But with a method I pioneered for NT Objects, you can save some precious KiB in your output file simply by faking/mocking CComModule. Sure, it’s not much you save, but given it’s dead code otherwise, why not shave it off?

The summary is that at the point you include your first ATL header (even if it’s not atlbase.h) you make sure that atlbase.h gets included at least once with _ATL_NO_COMMODULE defined before including it. Header guards will ensure that it won’t get included again. And then after including atlbase.h you include my very own fake_commodule.hpp like this:

#define _ATL_NO_COMMODULE
#include <atlbase.h>
#include "fake_commodule.hpp"
#undef _ATL_NO_COMMODULE

Once done, you remove the definition of _ATL_NO_COMMODULE again for subsequently included ATL (and WTL) headers.

Obviously this only ever makes sense if you don’t need to register a COM server. So use your common sense, you’ll know your application best.

// Oliver

PS: in case the link to fake_commodule.hpp rots away:

///////////////////////////////////////////////////////////////////////////////
///
/// Allows to reduce the size of executables linking the WTL by providing our
/// own minimal implementation of the CComModule, without the COM server
/// registration capabilities.
///
/// Include as follows:
///   #define _ATL_NO_COMMODULE
///   #include <atlbase.h>
///   #include "fake_commodule.hpp"
///   #undef _ATL_NO_COMMODULE
///
/// Dual-licensed under MS-PL and MIT license (see below).
///
///////////////////////////////////////////////////////////////////////////////
///
/// Copyright (c) 2016 Oliver Schneider (assarbad.net)
///
/// Permission is hereby granted, free of charge, to any person obtaining a
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the
/// Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
/// DEALINGS IN THE SOFTWARE.
///
///////////////////////////////////////////////////////////////////////////////

#ifndef __FAKE_COMMODULE_HPP_VER__
#define __FAKE_COMMODULE_HPP_VER__ 2016032300
#if (defined(_MSC_VER) && (_MSC_VER >= 1020)) || defined(__MCPP)
#pragma once
#endif // Check for "#pragma once" support

namespace ATL
{
    class CComModule;
    __declspec(selectany) CComModule* _pModule = NULL;
    class CComModule : public CAtlModuleT<CComModule>
    {
    public:
        CComModule()
        {
            // Should have only one instance of a class
            // derived from CComModule in a project.
            ATLASSERT(_pModule == NULL);
            _pModule = this;
        }

        HINSTANCE SetResourceInstance(HINSTANCE h) throw() { return _AtlBaseModule.SetResourceInstance(h); }
        HINSTANCE GetModuleInstance() throw() { return _AtlBaseModule.m_hInst; }
        HINSTANCE GetResourceInstance() throw() { return _AtlBaseModule.m_hInstResource; }
        HRESULT Init(_ATL_OBJMAP_ENTRY*, HINSTANCE, const GUID*) throw() { return S_OK; }
    };
}

#endif // __FAKE_COMMODULE_HPP_VER__
This entry was posted in C/C++, EN, Programming and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.