If you work with COM, apartments is one of the concepts you must comprehend, because it’s an important topic. Before explaining what apartments are let’s think about classes and objects regardless of COM. When you build a class, you know (or you should) whether objects of that class will be used from a single thread, or from multiple threads. In the later case, if those threads might access shared data at the same time, you must synchronize the access to that data (using critical sections, mutexes, or others). So when you create your class you either make it thread-safe or not. If it’s not thread safe, objects of that class can only be accessed from one thread at a time, if it’s thread-safe, then objects of that class can be accessed from different threads at the same time.

Now, the same rule applies in the COM world. Your coclasses can either be thread-safe or not. If the are thread-safe, you can access one object from different threads at a time, otherwise not. Here enter the apartments. So what is an apartment? An apartment is an environment in which COM objects can live. It’s not a thread, nor a process, but it handles access from COM clients to COM objects. There are several types of apartments: single-threaded apartments (STA), multi-threaded apartments (MTA) and neutral-threaded apartments (NTA).

Single-Threaded Apartments
An STA allows only one thread at a time to access a COM object. This is achieved using a hidden window with a message pump. Calls from clients living in different threads are queued with the message pump. Only when the current call from a thread ends, the next call can proceed.

Assume you had a COM object called CoUserGroups that implements an interface IUserGroups that provides two methods: one called Add that adds a new user group, and one called Delete that deletes a user group. Since both methods work on the same list of user groups, adding and deleting is not possible at the same time without synchronizing access. But since such synchronization was not implemented, the COM object specifies that it can leave only in an STA, and let the apartment do the synchronization of calls from clients living in different threads.

Multi-Threaded Apartments
An MTA allows any number of threads to access a COM objects. However, the COM objects must be thread-safe, otherwise your application will behave unexpectedly and even crash.

Going back to the previous example, if CoUserGroups was implemented in a thread-safe manner, then it would be possible for clients living in different threads to access it. In this case there would be no need for an apartment level synchronization. The COM coclass specifies that it can live in an MTA and when simultaneous calls from different threads are received they are directed immediately to the COM object. This situation is shown in the next image.

Neutral-Threaded Apartments
NTAs, like MTAs, allow multiple threads to enter one apartment, but once a thread entered the apartment it acquires an apartment wide lock that will block the other threads, until the current thread exists the apartment. Calls into NTA (from STA or MTA in the same process) do not generate context switches; the thread leaves the apartment in which it executes and enters the NTA without any context switch, which increases performance. This model was introduced with COM+ (in Windows 2000) and is meant for components with no user interface.

A process can contain several apartments:

  • zero or one MTA
  • zero or one NTA
  • zero, one or several STAs; the first STA created for a process is called the main STA

As a COM client, you specify the apartment you want to join with a call to CoInitializeEx(). This methods must be called from each thread.

HRESULT CoInitializeEx(void * pvReserved, DWORD dwCoInit);

The second parameters is a set of flags specifying the initialization options for the thread. To join the unique MTA, use COINIT_MULTITHREADED. To join a new or existing STA, use COINIT_APARTMENTTHREADED. Function CoInitialize() calls CoInitializeEx() specifying COINIT_APARTMENTTHREADED for the flags.

How to specify the threading model allowed for a coclass?
A coclass can specify the type of apartment it can join. If you’re using ATL you can specify that when you create the coclass. The next image shows the available options:


What they mean:

  • Single: object wants to join the main STA (the first STA created into the process)
  • Apartment: object wants to join one of the STAs in the process
  • Both: object wants to join either an STA or the MTA
  • Free: object wants to join the MTA
  • Neutral: object wants to join the NTA

ATL adds the appropriate value to the registry script it creates for your coclass. COM depends entirely on the registry, and the threading model is also specified in the registry. Here is an example:

HKCR
{
	NoRemove CLSID
	{
		ForceRemove {80CFA233-86CC-44E3-9A62-BC498D8F2A0E} = s 'CoUserGroups Class'
		{
			ForceRemove Programmable
			InprocServer32 = s '%MODULE%'
			{
				val ThreadingModel = s 'Apartment'
			}
			TypeLib = s '{B8965B61-2A5A-4F34-B9F8-D8859452D345}'
			Version = s '1.0'
		}
	}
}

When that is merged into the Windows Registry, it looks like this:

The possible values in registry are:

  • no value specified: equivalent of ATL ‘Single’
  • Apartment: equivalent of ATL ‘Apartment’
  • Free: equivalent of ATL ‘Free’
  • Both: equivalent of ATL ‘Both’
  • Neutral: equivalent of ATL ‘Neutral’

If you want to read more about COM apartments I suggests articles like this one.

, , , , , , Hits for this post: 13089 .

I recently read an excerpt from Joel Spolsky’s book User Interface Design For Programmers available on his (former) blog. This is a great book about designing user interfaces, with examples of bad and good ideas. I’m getting the printed version and I recommend this to all building UIs.

Now, yesterday I had a problem with Google Documents (which no longer worked on my WinXP machine with any browser, as it continuously unsuccessfully tried to download a 237 bytes file called download.gz) and I though that deleting the cache might help. So I opened Google Chrome options dialog and then the Clear Browsing Data dialog. It looks like this.

I was stunned to see the dialog started with the phrase “Obliterate the following items”. For God’s sake what is obliterating? I want to delete the cache, I don’t care about obliterating, and whatever that means. I don’t want to fetch a dictionary and look-up for the meaning of the word. Excuse me Mr. Google Programmer, that I (probably like many of the people of this world who are not native English speakers) don’t know what “obliterate” means. Yes, it does sound archaic, it does sound like J.R.R. Tolkien but it stops me doing my work. All I wanted to do was selecting what to delete and delete. Instead I spent time figuring whether that means to select what to keep or select what to delete (luckily it didn’t say purge). I had doubts so I had to search for the meaning of the word. Sure, now I know one more (fancy) English word, but overall, I lost one minute doing anything else but deleting the cache.

So, my recommendation to you Mr. Google Programmer is to read Joel Spolsky’s book. I’m sure there are things you can learn from it. And start using simple words and sentences that everyone understands.

As for what “obliterate” means, here it is:

  • Mark for deletion, rub off, or erase
  • Make undecipherable or imperceptible by obscuring or concealing
  • Remove completely from recognition or memory
  • Do away with completely, without leaving a trace
, , Hits for this post: 7238 .

A week ago I was reporting about the problems I had experienced with Office 2010. That was not the end of the story, and it’s probably fair enough to tell how it ends.

After installing Office 2010 64 bit and then 32 bit and both crashing every other 5 minutes, I returned to Office 2007. But then I got the help of Microsoft Support who provided a couple of scripts to clean-up the Windows Registry of anything related to Office 2007 and Office 2010. (The script for Office 2007 is available here; the one for Office 2010 is not yet published). I have then installed Office 2010 32 bit on a clean Registry and now all applications in the package work like a charm. No hanging, no crashing whatsoever. And I must say I was impressed by the support people, how they helped, how they called to check if everything was working, etc. The kind of support I wish to see everywhere.

I also learned that installing the 64 bit version is not recommended unless you really have some demands, like working with huge files, over 2GB (though I’m not sure what are the scenarios when one has Excel files bigger than 2GB). Add-ins for Office 32 bit might not work with the 64 bit version. (Though the add-ins I had in 2007 worked without any update when I installed Office 2010 32 bit.) More information about the 64 bit of Office 2010 can be found in this TechNet article.

, Hits for this post: 6632 .

A new version (1.3) of VSBuildStatus add-in for Visual Studio 2005, 2008 and 2010 is available. It allows you to configure the add-in window to automatically show up when a build/clean/deploy process starts, and/or automatically close when the operation ends.

  • To enable the automatic show of the add-in window when a build/clean/deploy operation starts, check Pop-out automatically when starting a build
  • To enable the automatic hiding of the add-in window when the build/clean/deploy operation ends, check Auto hide when the build ends
    • you can set a delay interval for the hiding, varing from 0 to 300 seconds; if the delay is 0, the window is hidden immediatelly after the build ends
    • to keep the window shown when error(s) occurred during the build/clean/deploy operation, check DO NOT auto hide when an error occurs

Here is a screen short of the properties window. It opens from the Settings button.

The add-in is available on the Visual Studio Gallery.

, , , , Hits for this post: 18524 .

If you are working with COM there are several registry entries that are important and that you need to understand. I will try in this post to clarify them. But before that, let’s enumerate the three possible COM server scenarios. (As a side note, a COM server is a DLL or EXE can contains one or more COM objects; a client is an entity that uses a COM object, which means a COM server can also be the client of another COM server.)

  • inproc: the COM server is loaded into the client process; in this case accessing the COM methods is as simple as using an interface pointer when the client and the in-proc server are in the same thread
  • local: the COM server and the client are loaded in different processes on the same machine; communication is achieved with the use of proxies and stubs via Lightweight RPC
  • remote: the COM server and the client are loaded in different processes on different machines; communication is achieved with the use of proxies and stubs via RPC

In order for the COM Library to be able to locate and instantiate the COM objects correctly, different information is stored in the Windows Registry. The most important information is located under the keys CLSID, TypeLib, Interface and AppID from HKEY_CLASSES_ROOT. The images below show examples for IIS.

HKEY_CLASSES_ROOT\CLSID
Every coclass from the COM server has at least an entry under this key, specifying the CLSID and the ProgID. The CLSID is a GUID that uniquely identifies the class, and the ProgID (programmatic identifier) is a string that identifies the class in a more human readable form. Each ProgID is mapped to a CLSID. The following image shows the mapping for the IIS ProgID.

For each COM class, there must be a key under HKEY_CLASSES_ROOT\CLSID, with the CLSID as the name. The most important sub-keys here are:

  • ProgID: the programmatic identifier, mapped on the CLSID; cam contain a version number (as a suffix)
  • VersionIndependentProgID: a programmatic identifier without the version information
  • InprocServer32: specifies the path of the DLL for the inproc servers
  • LocalServer32: specifies the path of the COM executable for the local (out-of-process) servers
  • TypeLib: indicates the LIBID of the type library that contains the coclass

Here are several screenshots from registry for IIS CLSID.


HKEY_CLASSES_ROOT\TypeLib
Each type library has a key under HKEY_CLASSES_ROOT\TypeLib, with the name of the LIBID. The sub-keys provide information about the physical location of the type library file (.tlb file) and others, such as flags (FLAGS key) the directory that contains the help file for the type library (HELPDIR key). A LIBID is a GUID that uniquely identifies a type library. A *.TLB file is a binary version of an IDL file. This is used by languages such as VB, Java, Javascript and many others in order to be able to use the COM objects.

The following image shows the type lib information for IIS.

HKEY_CLASSES_ROOT\Interface
Information for all interfaces defined in an IDL file (type library) must be added to the registry. Under HKEY_CLASSES_ROOT\Interface must be a key with the IID of the interface. The IID (interface identifier) is a GUID that uniquely identifies an interface. The most important sub-keys are:

  • TypeLib: the LIBID of the type library containing the interface
  • ProxyStubClsid32: the CLSID of the marshaller used to marshal the interface; value {00020424-0000-0000-C000-000000000046} identifies oleaut32.dll, which is the universal marshaler.

The following images show the registry entry for the interface IISBaseObject.

HKEY_CLASSES_ROOT\AppID
An AppID (application identifier) is a GUID that uniquely identifies a COM server and is used to describe security and activation settings; it is used for out-of-proc (local or remote) scenarios. Usually the AppID is the same with a CLSID of a coclass from the COM server (without the risk of collision, because the CLSID and the AppID server different purposes). The most important settings are:

  • AccessPermission: defines the ACL of users that can access the server
  • AuthenticationLevel: defines the authentication level
  • DllSurrogate: identifies the surrogate that can host the DLL; if no value is specified, the default dllhost.exe surrogate is used
  • LaunchPermissions: defines the ACL of users that can launch the application
  • RemoteServerName: identifies the remove server machine

The following images shows the values for an AppID key.

, Hits for this post: 12676 .