The Chromium Embedded Framework (CEF for short) is an open source framework for embedding Chromium-based browsers in other applications. The base implementation is targeting C/C++ applications but ports for other languages exist (these include Java, C#, Delphi, Python).

The nightly builds (for various systems and platforms) of CEF are available for download at https://cefbuilds.com/. These include:

  • CEF source code necessary to build your apps with
  • CEF dynamic and static library files (together with its dependencies) that you must use in your application
  • C++ wrappers for the C API
  • source code of two sample applications, one called CefSimple and one called CefClient
  • symbol files for debugging binary distribution of CEF
  • build of CefClient sample app with all dependencies and resources

Building the 64-bit version of the sample applications is not straight forward though. In this article I will show what you have to do make it work.

Prerequisites

The following prerequisites are necessary:

  • Visual Studio 2013
  • CMake tools

Notice: Though CMake should be able to generate projects for Visual Studio 2015, I was not able to make it happen. Moreover, the cef_sandbox.lib lib is built with Visual C++ 2013 which means the modules that are linking it should also be built with the same tool set.

You should download the nightly build of the development branch for Windows 64 bit and unzip it.

Create Visual Studio projects

To create Visual Studio projects run the following command from the CEF’s main folder in a console:

This will create:

  • a VC++ 2013 solution called cef.sln in the main folder
  • VC++ 2013 project files for libcef_dll, cefsimple, cefclient
  • two additional project files called ALL_BUILD and ZERO_CHECK

This is how the content of the CEF folder looks after generating the Visual Studio project and solution files.
cef3

This is how the Visual Studio solutions looks.
cef1

Create 64-bit configurations

Though the download is suppose to represent the 64-bit version of the framework, and the DLLs and LIBs in the Debug and Release folder (i.e. the CEF builds and its dependencies) are indeed built for the x64 platform, the generated projects do not have configurations targeting the x64 platform.

What you have to do is:

  • create configuration for targeting the x64 platform (by copying the settings from x86)
    cef7
  • change the Output Directory for all projects and configurations to be $(SolutionDir)$(Configuration)\ which means the output folder will be the existing Debug or Release folder from the main CEF folder.
    cef8
  • for the libcef_dll project change the Librarian > All Options > Additional options to /machine:X64 %(AdditionalOptions)
    cef9
  • for the cefsimple and cefclient projects change the additional dependencies settings to point to libcef.lib, libcef_dll_wrapper.lib and cef_sandbox.lib, instead of the relative paths as in the project.
    cef10
    This is how the list should look for all platforms and configurations:
  • for the cefsimple and cefclient projects add $(SolutionDir)$(Configuration)\ to the Library Directories for all configurations and platforms
    cef11
  • modify the Post Build Event for the cefsimple and cefclient projects to no longer copy files from the solution’s Debug and Release folders to the project’s Debug and Release folders.

    Initially, the post build event looks like this (for Debug configurations)

    It should be changed to look like this (beware at the output folder indicated by outputresource; it should be the Debug\Release folder in the main folder):

Resources

In the main folder there is a sub-folder called Resources. The entire content of this folder must be copied to the out folders, Debug and/or Release. These files are necessary for the sample applications to run properly.

Building and running

With all these in place you can build the projects. The build should succeed and the content of the Debug folder for instance should look like below.
cef4

You can then run the two sample applications. This is how cefsimple looks.
cef5

This is how cefclient looks.
cef6

, , , , , Hits for this post: 19740 .

Let’s say you have this VC++ project (or maybe more) targeting a 64-bit platform (x64 or IA64). You have the sources, everything is set. You build the solution and your project is skipped. You try again, maybe do a rebuild. The project is still skipped. You check the solution’s configuration manager, and the project is indeed checked for building. What could be wrong?

You open the project properties but the page doesn’t load. You get this error:

What’s happening?

What’s happening is that you are missing the x64/IA64 compiler and tools. You did not check them when you installed Visual Studio.



You have to go back to the setup and add this component. However, you must notice that if you have installed the service pack for Visual Studio (regardless the version and edition) you must remove the service pack first, run the original setup, add the x64/IA64 compiler and tools and then install the service pack back. Otherwise the original setup for Visual Studio will fail. The reason is the service pack installation overrides things, making the original setup unable to run again.

, , , , , Hits for this post: 51802 .

I recently ran across a bug with an application ported to the x64 platform. After debugging the application the error turned to be due to integrals layout and casting. I think this is a typical example worth mentioning.

It starts with this definition:

which is used for a combo box with SetItemData:

Notice the cast to DWORD, which is an integral type represented on 32-bits both on x86 and x64. At a later point this value was retrieved and tested against COMBO_VALUE:

They key here is how the value of -99 is represented:

  32-bit platform 64-bit platform
-99 FFFFFF9D FFFFFFFFFFFFFF9D
(DWORD)-99 FFFFFF9D FFFFFF9D
(DWORD_PTR)-99 FFFFFF9D FFFFFFFFFFFFFF9D
(DWORD_PTR)(DWORD)-99 FFFFFF9D 00000000FFFFFF9D

GetItemData returns a DWORD_PTR, so FFFFFF9D becomes 00000000FFFFFF9D on x64. Then -99 is also interpreted as a DWORD. Thus the condition in the above if statement resolves to 00000000FFFFFF9D == FFFFFFFFFFFFFF9D on x64, which of course is false.

To fix the problem, the if statement should be re-written like this:

A very simply fix, but not so simple to spot the root of the problem when just reading the code.

, , , Hits for this post: 31319 .

Redefinition of ‘BOOKMARK’

If you include in a VC++ project <mapidefs.h> and <sqltypes.h> and build for the x64 platform you get a redefinition error.

1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\sqltypes.h(283) : error C2371: ‘BOOKMARK’ : redefinition; different basic types
1> C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\MAPIDefS.h(1142) : see declaration of ‘BOOKMARK’

The reason is that BOOKMARK is defined in both files.

This is mapidefs.h

This is sqltypes.h

On x86, both ULONG and SQLULEN are an unsigned long. However, on x64, ULONG is still unsigned long, but SQLULEN is an UINT64, which is different than unsigned long. Hence the error.

There is a Connect bug report called Using x64 with mapidefs.h and sqltypes.h causes C2371 filed by Martin Richter 6 years ago (!), with no fix yet. Martin proposed the following workaround:

However, it doesn’t work for me. I get the very same error. To get rid of the error you have to use namespaces. Define two namespaces, let’s call them MAPI and SQL and include each header in one of them. Then you can use the using namespace directive so that you don’t have to prefix everything with MAPI:: or SQL::. However, you’ll have to use the fully qualified name when you want to use one or the other BOOKMARK, as shown in the following example:

, , , , Hits for this post: 48756 .

It is possible to register both 32-bit and 64-bit versions of the same COM server on 64-bit machine. This leads to several questions such as how are they registered and which one of the two is used. I will try to answer them below. But first, let’s start with an example.

Example
Let’s say we have the a simple COM local server called COM3264Server.exe. There is just one interface called ICoCOM3264Server. Here is the IDL file:

The implementation of the method SayHello() is straight forward; it just displays a message box with a text that varies between the two architectures, x64 and x86.

Registry
When you register the COM server, the 32-bit and 64-bit versions are registered in different parts of the registry. On 64-bit machine, the registry has two views (or modes):

  • a native view, for 64-bit application; (e.g. registry path for CLSIDs is HKEY_CLASSES_ROOT\CLSID\)
  • a WOW64 view, which enables redirections for 32-bit applications, a process transparent to the user (e.g. registry path for CLSIDs is HKEY_CLASSES_ROOT\Wow6432Node\CLSID\)

Here is the Registry registration of the (native) 64-bit COM server (notice the registry key in the status bar of the editor, and the path to the server executable).

On, the other hand, the 32-bit COM server is registered under the Wow6432 node.

So if both versions are registered in Windows Registry, which one is picked? Well, both the server and the client can specify which architecture to use:

  • the COM server can do this via the PreferredServerBitness Registry value
  • the client can do this using one of the flags CLSCTX_ACTIVATE_32_BIT_SERVER and CLSCTX_ACTIVATE_64_BIT_SERVER, which overrides the server preference

If neither the client nor the server specifies a preference, then:

  • If the computer that hosts the server is running Windows Server 2003 with Service Pack 1 (SP1) or a later system, then COM will try to match the server architecture to the client architecture. In other words, for a 32-bit client, COM will activate a 32-bit server if available; otherwise it will activate a 64-bit version of the server. For a 64-bit client, COM will activate a 64-bit server if available; otherwise it will activate a 32-bit server.
  • If the computer that hosts the server is running Windows XP or Windows Server 2003 without SP1 or later installed, then COM will prefer a 64-bit version of the server if available; otherwise it will activate a 32-bit version of the server.

Server Preference
The server can specify its preferred architecture in the PreferredServerBitness value under AppId (available only on 64-bit Windows). This integer value can be:

  • 1: Match the server architecture to the client architecture. For example, if the client is 32-bit, use a 32-bit version of the server, if it is available. If not, the client’s activation request will fail.
  • 2: Use a 32-bit version of the server. If one does not exist, the client’s activation request will fail.
  • 3: Use a 64-bit version of the server. If one does not exist, the client’s activation request will fail.

Here is the value set in Registry to specify the 64-bit architecture.

When you run the client, it launches the 64-bit version and in my example the following window pops-up:

If I change the value to indicate the 32-bit architecture, the other COM server is launched and the displayed message is:

Client Preference
The client code I used so far looked like this:

However, the 64-bit version of Windows added new flags to the CLSCTX enumeration.

  • CLSCTX_ACTIVATE_32_BIT_SERVER: used to activate or connect to a 32-bit version of the server; fail if one is not registered.
  • CLSCTX_ACTIVATE_64_BIT_SERVER: used to activate or connect to a 64 bit version of the server; fail if one is not registered.

As I mentioned earlier, if the client uses one of these flags, it overrides the server preference (specified via the PreferredServerBitness Registry value).

In the following example, the client requests the 64-bit COM server:

And if you run it, no matter what the server specified, the 64-bit COM server is launched.

To read more about the subject see the MSDN links above.

, , , Hits for this post: 66008 .

I’m using Red Gate’s .NET Reflector for decompiling .NET assemblies. It’s a great tool but it lacks, at least in the free version I’m using, information about the platform architecture of an assembly. Sometimes I want to know whether an assembly was built for Any CPU, x86 or x64.

The tool that help you find this information is CorFlags.exe from Windows SDK. It displays or configures the corflags section of a PE image. Here is an example of the output of corflags.exe:

The platform architecture is encoded in a combination of the PE and 32BIT flags:

  • Any CPU: PE=PE32 and 32BIT=0
  • x86: PE=PE32 and 32BIT=1
  • 64-bit: PE=PE32+ and 32BIT=0

So for the example above, PE is PE32 and 32BIT is 0, thus the platform architecture is Any CPU.

You can read more about this tool on Gaurav Seth’s blog.

, , , Hits for this post: 35760 .

I’m working on a project to port a 32-bit application for the x64 platform. The first errors that came up when building for x64 were related to inline ASM code, which is no longer supported in VC++ for x64. VC++ has an inline assembler built within the compiler, so you could write assembly code directly in C++ without the need of an external assembler (such as MASM). However, this works only on x86. For x64 and IA64 this is no longer possible. There are several workaround for this:

  • put the assembly code into a separate file and use MASM for x64
  • use compiler intrinsics, which are functions that basically wrap assembly instructions or sequence of intructions
  • rewrite in C++, use Windows APIs, etc.

One error that I had was related to this assembly code:

This was used to generate a breakpoint. This can be easily replaced with compiler intrinsic __debugbreak(), which has an identical effect, except that is available on all platforms.

Other errors I had were due to assembly code used to retrieve the value of the EIP and EBP registers. They were used for walking the stack.

The naked specifier is another thing that is not supported on x64. One way to retrieve the value of these registers that works both with x86 and x64 is using RtlCaptureContext, except that this won’t work on operating system previous to Windows XP. In you don’t care about those operating systems, you could write something like this:

Attention, on x64, register EBP (actually RBP) is no longer used. You should use RSP for getting the stack frame.

However, if you want to build a portable stack walking, use StackWalk64. Despite the 64 suffix, this function works on all platforms (x86, x64, IA64). Here is an article that shows how to walk the stack using StackWalk64.

, , , Hits for this post: 51426 .

If you want to port an existing 32-bit application for the x64 platform (especially since 32-bit processors will soon be history), or if you want to target x64 for a new application, the first step in building for x64 is setting up your solution. In this post I will explain what are the steps in configuring x64 as target platform for your projects. Of course you must have the 64-bit compiler and tools installed to make this possible.

Here is an example of a solution with two VC++ project (a Win32 DLL and a console application).

The VC++ wizards add only Win32 (i.e. x86) as target platform for your projects and for your solution (I believe this will change in the future). You can see this by expanding the platforms combo.

If you open the Configuration Manager window for the solution you can see the available solution platforms, and for each project, the available project platforms (these might not be the same).

The configuration manager allows you to set for each pair of solution configuration and solution platform the platform for each individual project. So in theory you can configure for Debug with Win32 at solution level to have, in my demo solution, DemoProject targeting Win32 and DemoLibrary targeting x64. Of course, in practice you probably want to have all projects targeting Win32 in this case, and for the pair Debug with x64 at solution level, have all projects targeting the x64 platform.

To make this platform available for the solution, expand the Active solution platform combo and select . The New Solution Platform dialog will open and allow you to define a new target platform for the solution. Select x64 and for Copy settings from select Win32.

Then make sure you check the Create new project platforms checkbox. In this case the x64 platform will also be defined for every project included in the solution.

After you do this, the x64 platform will be available in the configuration manager for the solution and the projects, so that you can configure the relationships.

Also, the solution platforms combo from the toolbar now displays both Win32 and x64.

But now let’s say you add a new project to the solution. Let’s call this DemoLibrary2.

Since the project was added after defining x64 as a target for the solution and all the projects, the x64 platform won’t be defined for this project (remember, by default, the VC++ wizards don’t add x64 as target platform). You can see this in the configuration manager, where only Win32 is available for the new project.

To define the x64 target for the new project, use the project platform combo and select (see the image above) to open the New Project Platform dialog. Select x64, as new platform, but make sure the checkbox Create new solution platforms remains unselected. Otherwise you’ll get an error, since the platform is already available at the solution level.

After that, the x64 platform will be available for the new project too, and you can make the appropriate configurations in the Configuration Manager window.

And with that you’re done. All you have to do now is configure the settings for each project, for each configuration and platform.

, , Hits for this post: 47425 .