>>It's a bug in Tortoise to assume that all calling apps have called CoInitialize.
Wrong!
Tortoise has nothing to do with it.
The previously mentioned CMyOverlayIcon is a test example, which can be found here:
http://www.codeproject.com/shell/overlayicon.asp
and it also doesn't work.
Without CoInitialize any overlay dll does not have a single chance to be loaded in the TC process.
The matter is that overlay icon extension is a COM-server, i.e. a dll, which can be loaded in the client process only during the CoCreateInstance function call, and no other way.
If CoCreateInstance detects that CoInitialize call was not executed beforehand, it will not even try to load the dll.
Please refer to the basics of the COM technology.
If CoInitialize was not called before OverlayManager initialization, NO OVERLAY EXTENSIONS will work!
Using debugger it is easy to find out where OverlayManager is initialized:
TC calls SHGetFileInfo:
==================
api_hook.dll!New_CoCreateInstance(const _GUID & rclsid={30351346-7B7D-4FCC-81B4-1E394CA267EB}, IUnknown * pUnkOuter=0x00000000, unsigned long dwClsContext=0x00000401, const _GUID & riid={0C6C4200-C589-11D0-999A-00C04FD655E1}, void * * ppv=0x000bef74) Line 82 C++
shell32.dll!_SHCoCreateInstance() - 0x292e5 bytes
shell32.dll!_SHExtCoCreateInstance@24() + 0x1e bytes
shell32.dll!_DCA_SHExtCoCreateInstance@16() + 0x2a bytes
shell32.dll!CFSIconOverlayManager::_s_LoadIconOverlayIdentifiers() + 0x10c bytes
shell32.dll!CFSIconOverlayManager::_InitializeHdsaIconOverlays() + 0xb bytes
shell32.dll!CFSIconOverlayManager::CreateInstance() + 0x4c bytes
shell32.dll!_IconOverlayManagerInit@0() + 0x256 bytes
shell32.dll!_GetIconOverlayManager@4() + 0x17 bytes
shell32.dll!_FileIconInit@4() + 0x15e bytes
shell32.dll!_SHGetImageList@12() + 0x90 bytes
shell32.dll!_GetFileInfoSections() + 0xaa bytes
shell32.dll!_SHGetFileInfoW@20() + 0x11b bytes
shell32.dll!_SHGetFileInfoA@20() + 0x70 bytes
TOTALCMD.EXE!00578333()
==================
despite of MSDN:
==================
You must initialize Component Object Model (COM) with CoInitialize or OleInitialize prior to calling SHGetFileInfo.
==================
This is what causes unpredictable behavior, for example, any overlay COM-dll are not loaded into the process.
>>Total Commander calls InitializeOLE2 only after creating its windows, to make it start faster.
This could work for Pentium1-133, but now such an "optimization" is useless, (first if all, because CoInitializeEx call goes very fast with Pentium3 and later, secondly, because Windows2000-XP call CoInitializeEx before the window creation anyway (in contrast to Vista, which lets the developer explicitly set CoInitializeEx parameters)), and even dangerous and harmful.
If you are so eager to keep it - please make it optional!
TC also should call ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
BEFORE the first addressing to SHGetFileInfo.
Then, TC can create its windows and call OleInitialize...
P.S.
Please look at this function
IShellIconOverlayManager::LoadNonloadedOverlayIdentifiers