For engineers engaged in COM component development, the concept of apartment is hard to understand, and Microsoft has very few explanations on this aspect. In the future, describe the concept of apartment.
1. Call Stack during com library Initialization
Coinitializeex (null, coinit_apartmentthreaded) Stack
> User32.dll! _ Createdomainwexw @ 48 () + 0x1c bytes
Ole32.dll! Initmainthreadwnd () + 0x3c bytes
Ole32.dll! Wcoinitializeex () + 0x2fd99 bytes
Ole32.dll! _ Coinitializeex @ 8 () + 0xc6 bytes
Singleapartment.exe! Main (INT argc = 1, char ** argv = 0x003d39c0) Row 172 + 0xc byte C ++
Singleapartment.exe! _ Tmaincrtstartup () Row 318 + 0x19 bytes C
Singleapartment.exe! Maincrtstartup () Row 187 C
Kernel32.dll! _ Baseprocessstart @ 4 () + 0x23 bytes
For coinitializeex (null, coinit_coinit_multithreaded), the following stack is not called.
> User32.dll! _ Createdomainwexw @ 48 () + 0x1c bytes
Ole32.dll! Initmainthreadwnd () + 0x3c bytes
Ii. COM component creation process
Stack when a component is created for a thread initialized by coinitializeex (null, coinit_multithreaded)
> Ole32.dll! Cservercontextactivator: createinstance () + 0x2b5 bytes
Ole32.dll! Activationpropertiesin: delegatecreateinstance () + 0x4b bytes
Ole32.dll! Capartmentactivator: createinstance () + 0x72 bytes
Rpcrt4.dll! _ Invoke @ 12 () + 0x30 bytes
Rpcrt4.dll! _ MCM stubcall2 @ 16 () + 0x215 bytes
Rpcrt4.dll! _ Cstdstubbuffer_invoke @ 12 () + 0x82 bytes
Ole32.dll! Syncstubinvoke () + 0x33 bytes
Ole32.dll! Stubinvoke () + 0x73 bytes
Ole32.dll! Cctxcomchnl: contextinvoke () + 0xd2 bytes
Ole32.dll! Mtainvoke () + 0x1a bytes
Ole32.dll! Stainvoke () + 0x4e bytes
Ole32.dll! Appinvoke () + 0x3a0 bytes
Ole32.dll! Cominvokewithlockandipid () + 0x23d bytes
Ole32.dll! Cominvoke () + 0x5a bytes
Ole32.dll! Threaddispatch () + 0x1a bytes
Ole32.dll! Threadwndproc () + 0x93 bytes
User32.dll! _ Internalcallwinproc @ 20 () + 0x28 bytes
User32.dll! _ Usercallwinproccheckwow @ 32 () + 0xb7 bytes
User32.dll! _ Dispatchmessageworker @ 8 () + 0xdc bytes
User32.dll! _ Dispatchmessagew @ 4 () + 0xf bytes
Ole32.dll! Cdllhost: staworkerloop () + 0x6b bytes
Ole32.dll! Cdllhost: workerthread () + 0xc4 bytes
Ole32.dll! Dllhostthreadentry () + 0xd bytes
Ole32.dll! Crpcthread: workerloop () + 0x1e bytes
Ole32.dll! Crpcthreadcache: rpcworkerthreadentry () + 0x1b bytes
Kernel32.dll! _ Basethreadstart @ 8 () + 0x37 bytes
For coinitializeex (null, coinit_apartmentthreaded ),
> Ole32.dll! Cservercontextactivator: createinstance () + 0x2b5 bytes
Ole32.dll! Activationpropertiesin: delegatecreateinstance () + 0x4b bytes
Ole32.dll! Capartmentactivator: createinstance () + 0x72 bytes
Ole32.dll! Cprocessactivator: ccicallback () + 0x3d bytes
Ole32.dll! Cprocessactivator: attemptactivation () + 0x2c bytes
Ole32.dll! Cprocessactivator: activatebycontext () + 0x46 bytes
Ole32.dll! Cprocessactivator: createinstance () + 0x49 bytes
Ole32.dll! Activationpropertiesin: delegatecreateinstance () + 0x4b bytes
Ole32.dll! Cclientcontextactivator: createinstance () + 0x8f bytes
Ole32.dll! Activationpropertiesin: delegatecreateinstance () + 0x4b bytes
Ole32.dll! Icocreateinstanceex () + 0x2d332 bytes
Ole32.dll! Ccomactivator: docreateinstance () + 0x28 bytes
Ole32.dll! _ Cocreateinstanceex @ 24 () + 0x1e bytes
Ole32.dll! _ Cocreateinstance @ 20 () + 0x34 bytes
Singleapartment.exe! Main (INT argc = 1, char ** argv = 0x003d3a78) Row 187 + 0x1a byte C ++
Singleapartment.exe! _ Tmaincrtstartup () Row 318 + 0x19 bytes C
Singleapartment.exe! Maincrtstartup () Row 187 C
Kernel32.dll! _ Baseprocessstart @ 4 () + 0x23 bytes
Iii. Thread conditions during COM component creation
For coinitializeex (null, coinit_multithreaded) thread Creation
After the component is created, three threads are created in addition to the main thread.
> 3836 _ tmaincrtstartup Main Normal 0
3080 threadstartroutine _ kifastsystemcallret @ 0 normal 0
2576 crpcthreadcache: rpcworkerthreadentry _ kifastsystemcallret @ 0 normal 0
1188 crpcthreadcache: rpcworkerthreadentry _ kifastsystemcallret @ 0 normal 0
The thread used when a component is created in the main thread after a secondary thread is created.
3836 _ tmaincrtstartup apartmentmsgwaitformultipleobject normal 0
3080 threadstartroutine _ kifastsystemcallret @ 0 normal 0
2576 crpcthreadcache: rpcworkerthreadentry _ kifastsystemcallret @ 0 normal 0
1188 crpcthreadcache: rpcworkerthreadentry _ kifastsystemcallret @ 0 normal 0
> 2372 threadproc normal 0
By setting breakpoints, we can find that when the initial com library is coinit_multithreaded, the access component interface is actually switched to the 1188 crpcthreadcache: rpcworkerthreadentry thread for execution.
After the component com library is released, there are three threads.
> 2536 _ tmaincrtstartup Main Normal 0
3496 threadstartroutine _ kifastsystemcallret @ 0 normal 0
2272 crpcthreadcache: rpcworkerthreadentry _ kifastsystemcallret @ 0 normal 0
Coinitializeex (null, coinit_apartmentthreaded) thread Creation
No thread is created.