July 2015

Volume 30 Number 7

Windows with C++ - Windows Runtime Components

By Kenny Kerr | July 2015

Kenny KerrOver the next few months I’m going to explore the essentials of the Windows Runtime. The purpose is to break down the higher-level abstractions that developers use in the various language projections and toolchains in order to examine how the Windows Runtime works at the application binary interface (ABI)—the boundary between applications and the binary components they rely on to access OS services.

In some ways the Windows Runtime is just the evolution of COM, which was effectively a binary standard for code reuse and continues to be a popular way to build complex applications and OS components. Unlike COM, however, the Windows Runtime is more narrowly focused and is primarily used as the foundation for the Windows API. Application developers will be more inclined to use the Windows Runtime as a consumer of OS components and less likely to write components themselves. Nevertheless, a good understanding of how all of the different classy abstractions are implemented and projected into various programming languages can only help you write more efficient applications and better diagnose interop and performance problems.

One of the reasons why so few developers understand how the Windows Runtime works (other than its rather sparse documentation) is because the tooling and language projections really obscure the underlying platform. This may be natural for the C# developer, but it certainly doesn’t make life comfortable for the C++ developer who really wants to know what’s going on under the covers. So let’s begin by writing a simple Windows Runtime component with Standard C++ using the Visual Studio 2015 developer command prompt.

I’ll start with a simple and traditional DLL that exports a couple of functions. If you want to follow along, create a Sample folder and inside of that create a few source files beginning with Sample.cpp:

C:\Sample>notepad Sample.cpp

The first thing I’ll do is take care of unloading the DLL, which I’ll call the component from here on. The component should support unload queries via an exported function call, DllCanUnloadNow, and it’s the application that controls the unloading with the CoFreeUnused­Libraries function. I won’t spend much time on this because this is the same way components were unloaded in classic COM. Because the component isn’t statically linked into the application—with a LIB file, for example—but is instead loaded dynamically via the Load­Library function, there needs to be some way for the component to be unloaded eventually. Only the component really knows how many outstanding references are being held so the COM runtime can call its DllCanUnloadNow function to determine whether it’s safe to unload. Applications can also perform this housekeeping themselves using the CoFreeUnusedLibraries or CoFreeUnusedLibrariesEx functions. The implementation in the component is straightforward. I need a lock that will keep track of how many objects are alive:

static long s_lock;

Each object can then simply increment this lock in its constructor and decrement it in its destructor. To keep that simple, I’ll write a little ComponentLock class:

struct ComponentLock
{
  ComponentLock() noexcept
  {
    InterlockedIncrement(&s_lock);
  }
  ~ComponentLock() noexcept
  {
    InterlockedDecrement(&s_lock);
  }
};

Any and all objects that should prevent the component from unloading can then simply embed a ComponentLock as a member variable. The DllCanUnloadNow function can now be implemented quite simply:

HRESULT __stdcall DllCanUnloadNow()
{
  return s_lock ? S_FALSE : S_OK;
}

There are really two types of objects you can create within a component—activation factories, which were called class factories in classic COM, and the actual instances of some particular class. I’m going to implement a simple “Hen” class and I’ll start by defining an IHen interface so the hen can cluck:

struct __declspec(uuid("28a414b9-7553-433f-aae6-a072afe5cebd")) __declspec(novtable)
IHen : IInspectable
{
  virtual HRESULT __stdcall Cluck() = 0;
};

This is a regular COM interface that just happens to derive from IInspectable rather than directly from IUnknown. I can then use the Implements class template I described in the December 2014 issue (msdn.com/magazine/dn879357) to implement this interface, and provide the actual implementation of the Hen class within the component:

struct Hen : Implements<IHen>
{
  ComponentLock m_lock;
  virtual HRESULT __stdcall Cluck() noexcept override
  {
    return S_OK;
  }
};

An activation factory is just a C++ class that implements the IActivationFactory interface. This IActivationFactory interface provides the single ActivateInstance method, which is analogous to the classic COM IClassFactory interface and its CreateInstance method. The classic COM interface is actually slightly superior in that it allows the caller to request a specific interface directly, whereas the Windows Runtime IActivationFactory simply returns an IInspectable interface pointer. The application is then responsible for calling the IUnknown QueryInterface method to retrieve a more useful interface to the object. Anyway, it makes the Activate­Instance method quite simple to implement:

struct HenFactory : Implements<IActivationFactory>
{
  ComponentLock m_lock;
  virtual HRESULT __stdcall ActivateInstance(IInspectable ** instance)
    noexcept override
  {
    *instance = new (std::nothrow) Hen;
    return *instance ? S_OK : E_OUTOFMEMORY;
  }
};

The component allows applications to retrieve a specific activation factory by exporting another function called DllGetActivation­Factory. This, again, is analogous to the DllGetClassObject exported function that supports the COM activation model. The main difference is that the desired class is specified with a string rather than a GUID:

HRESULT __stdcall DllGetActivationFactory(HSTRING classId,
   IActivationFactory ** factory) noexcept
{
}

An HSTRING is a handle that represents an immutable string value. This is the class identifier, perhaps “Sample.Hen,” and indicates which activation factory should be returned. At this point there are a number of reasons why calls to DllGetActivationFactory might fail, so I’ll start by clearing the factory variable with a nullptr:

*factory = nullptr;

Now I need to get the backing buffer for the HSTRING class identifier:

wchar_t const * const expected = WindowsGetStringRawBuffer(classId, nullptr);

I can then compare this value with all of the classes my component happens to implement. So far there’s only one:

if (0 == wcscmp(expected, L"Sample.Hen"))
{
  *factory = new (std::nothrow) HenFactory;
  return *factory ? S_OK : E_OUTOFMEMORY;
}

Otherwise, I’ll return an HRESULT indicating that the requested class isn’t available:

return CLASS_E_CLASSNOTAVAILABLE;

That’s all the C++ I need to get this simple component up and running, but there’s still a bit more work to do in order to actually make a DLL for this component and then describe it to those pesky C# compilers that don’t know how to parse header files. To make a DLL, I need to involve the linker, specifically its ability to define the functions exported from the DLL. I could use the Microsoft compiler-specific dllexport __declspec specifier, but this is one of the rare cases where I prefer to talk to the linker directly and instead provide a module-definition file with the list of exports. I find this approach less error prone. So it’s back to the console for the second source file:

C:\Sample>notepad Sample.def

This DEF file simply needs a section called EXPORTS that lists the functions to be exported:

EXPORTS
DllCanUnloadNow         PRIVATE
DllGetActivationFactory PRIVATE

I can now provide the C++ source file along with this module-­definition file to the compiler and linker to produce the DLL, and then use a simple batch file as a convenience to build the component and place all of the build artifacts in a subfolder:

C:\Sample>type Build.bat
@md Build 2>nul
cl Sample.cpp /nologo /W4 /FoBuild\ /FeBuild\Sample.dll /link /dll /def:Sample.def

I’ll gloss over the deep magic that is the batch file scripting language and focus on the Visual C++ compiler options. The /nologo option suppresses the display of the copyright banner. The option is also forwarded to the linker. The indispensable /W4 option tells the compiler to display more warnings for common coding bugs. There’s no /FoBuild option. The compiler has this hard-to-read convention whereby output paths follow the option, in this case /Fo, without a space in between. Anyway, the /Fo option is used to coerce the compiler to dump the object file in the Build subfolder. It’s the only build output that doesn’t default to the same output folder as the executable defined with the /Fe option. The /link option tells the compiler that subsequent arguments are to be interpreted by the linker. This avoids having to call the linker as a secondary step and, unlike the compiler, the linker’s options are case-insensitive and do employ a separator between the name of an option and any value, as is the case with the /def option that indicates the module-definition file to use.

I can now build my component quite simply and the resulting Build subfolder contains a number of files, only one of which matters. Naturally, that’s the Sample.dll executable that can be loaded into the application’s address space. But this is not enough. An application developer needs some way to know what the component contains. A C++ developer would probably be satisfied with a header file including the IHen interface, but even that isn’t particularly convenient. The Windows Runtime includes the concept of language projections whereby a component is described in such a way that different languages can discover and project its types into their programming models. I’ll explore language projection in the coming months, but for now let’s just get this sample to work from a C# application because that’s the most convincing. As I mentioned, C# compilers don’t know how to parse C++ header files, so I need to provide some metadata with which the C# compiler will be happy. I need to produce a WINMD file that contains the CLR metadata describing my component. This is no simple matter because the native types I might use for the component’s ABI can often look very different when projected into C#. Fortunately, the Microsoft IDL compiler has been repurposed to produce a WINMD file, given an IDL file that uses a few new keywords. So it’s back to the console for our third source file:

C:\Sample>notepad Sample.idl

First, I need to import the definition of the prerequisite IInspectable interface:

import "inspectable.idl";

I can then define a namespace for the component’s types. This must match the name of the component itself:

namespace Sample
{
}

Now I need to define the IHen interface I previously defined in C++, but this time as an IDL interface:

[version(1)]
[uuid(28a414b9-7553-433f-aae6-a072afe5cebd)]
interface IHen : IInspectable
{
  HRESULT Cluck();
}

This is good old IDL and if you’ve used IDL in the past to define COM components, you shouldn’t be surprised by any of this. All Windows Runtime types must, however, define a version attribute. This used to be optional. All interfaces must also derive from IInspectable directly. There’s effectively no interface inheritance in the Windows Runtime. This has some negative consequences that I’ll talk about in the coming months.

And, finally, I need to define the Hen class itself using the new runtimeclass keyword:

[version(1)]
[activatable(1)]
runtimeclass Hen
{
  [default] interface IHen;
}

Again, the version attribute is required. The activatable attribute, while not required, indicates that this class may be activated. In this case, it indicates that default activation is supported via the IActivationFactory ActivateInstance method. A language projection should present that as a C++ or C# default constructor or whatever makes sense to a particular language. Finally, the default attribute before the interface keyword indicates that the IHen interface is the default interface for the Hen class. The default interface is the interface that takes the place of parameters and return types when those types specify the class itself. Because the ABI only trades in COM interfaces and the Hen class is not itself an interface, the default interface is its representative at the ABI level.

There’s a lot more to explore here but this will do for the moment. I can now update my batch file to produce a WINMD file describing my component:

@md Build 2>nul
cl Sample.cpp /nologo /W4 /FoBuild\ /FeBuild\Sample.dll /link /dll /def:Sample.def
"C:\Program Files (x86)\Windows Kits\10\bin\x86\midl.exe" /nologo /winrt /out %~dp0Build /metadata_dir "c:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\1.0.0.0" Sample.idl

I’ll again gloss over the magic in the batch file and focus on what’s new with the MIDL compiler options. The /winrt option is the key and indicates that the IDL file contains Windows Runtime types rather than traditional COM or RPC-style interface definitions. The /out option just ensures that the WINMD file resides in the same folder as the DLL as this is required by the C# toolchain. The /metadata_dir option tells the compiler where it can find the metadata that was used to build the OS. As I write this, the Windows SDK for Windows 10 is still settling down and I need to be careful to invoke the MIDL compiler that ships with the Windows SDK and not the one provided by the path in the Visual Studio tools command prompt.

Running the batch file now produces both the Sample.dll and the Sample.winmd, which I can then reference from a C# Windows Universal app and use the Hen class as if it were just another CLR library project:

Sample.Hen h = new Sample.Hen();
h.Cluck();

The Windows Runtime is built on the foundations of COM and Standard C++. Concessions have been made to support the CLR and make it very easy for C# developers to use the new Windows API without requiring any interop components. The Windows Runtime is the future of the Windows API.

I specifically presented the development of a Windows Runtime component from the perspective of classic COM and its roots in the C++ compiler so that you can understand from where this technology comes. However, this approach quickly becomes rather impractical. The MIDL compiler actually provides far more than just the WINMD file and we can actually use it, among other things, to generate the canonical version of the IHen interface in C++. I hope you’ll join me next month as we explore a more reliable workflow for authoring Windows Runtime components and also solve a few interop problems along the way.


Kenny Kerr is a computer programmer based in Canada, as well as an author for Pluralsight and a Microsoft MVP. He blogs at kennykerr.ca and you can follow him on Twitter at twitter.com/kennykerr.

Thanks to the following Microsoft technical expert for reviewing this article: Larry Osterman