The platform is 32bit XP PRO SP2. I wrote a simple NT service that uses CoRegisterClassObject() in its main thread. More or less the pseudo-code is the following: main_thread() { CoInitialize(); CoRegisterClassObject(CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE); CoCreateInstance(CLSCTX_INPROC_SERVER); >>> S_OK wait_for_service_main_to_complete(); } service_main_thread() { CoInitialize(); CoCreateInstance(CLSCTX_INPROC_SERVER); >>> REGDB_E_CLASSNOTREG } Why does CoCreateInstance() fail with REGDB_E_CLASSNOTREG in the service main thread but succeeds in the process main thread? Both thread are running under the same account according to GetSecurityInfo()+LookupAccountSid() and the service is running as LocalSystem. -- // Alessandro Angeli // MVP :: DirectShow / MediaFoundation // mvpnews at riseoftheants dot com // http://www.riseoftheants.com/mmx/faq.htm
CoInitialize initializes a STA. One of the requirements for STA objects to interop with objects in other STA threads is that all the threads involved must pump messages. Now, if I understand your sample correctly : ServiceMain is run in a thread that is launched when wait_for_service_main_to_complete calls StartServiceCtrlDispatcher. StartServiceCtrlDispatcher does not pump messages. This means that the service_main_thread() call to CoCreateInstance will time out when trying to access the class factory registered in the main_thread. Which will probably prompt COM to try an create the object from scratch from the registry, and, given that you're trying to register the inproc server manually like this - will fail with REGDB_E_CLASSNOTREG because you probably havnt got a inprocserver32 dll entry. "Alessandro Angeli" wrote in message news:%23P39OwS4HHA.1208@TK2MSFTNGP03.phx.gbl... > The platform is 32bit XP PRO SP2. I wrote a simple NT > service that uses CoRegisterClassObject() in its main > thread. More or less the pseudo-code is the following: > > main_thread() > { > CoInitialize(); > CoRegisterClassObject(CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE); > CoCreateInstance(CLSCTX_INPROC_SERVER); >>> S_OK > wait_for_service_main_to_complete(); > } > > service_main_thread() > { > CoInitialize(); > CoCreateInstance(CLSCTX_INPROC_SERVER); >>> > REGDB_E_CLASSNOTREG > } > > Why does CoCreateInstance() fail with REGDB_E_CLASSNOTREG in > the service main thread but succeeds in the process main > thread? Both thread are running under the same account > according to GetSecurityInfo()+LookupAccountSid() and the > service is running as LocalSystem. > > -- > // Alessandro Angeli > // MVP :: DirectShow / MediaFoundation > // mvpnews at riseoftheants dot com > // http://www.riseoftheants.com/mmx/faq.htm > > >
From: "Chris Becke" > CoInitialize initializes a STA. One of the requirements > for STA objects to interop with objects in other STA > threads is that all the threads involved must pump > messages. [...] Thanks for your reply. I changed the code as following: main_thread() { CoInitialize(); wait_for_message_thread_to_be_ready(); CoCreateInstance(CLSCTX_INPROC_SERVER); >>> REGDB_E_CLASSNOTREG wait_for_service_main_to_complete(); } message_thread() { CoInitialize(); CoRegisterClassObject(CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE); signal_readiness(); while(GetMessage()) DispatchMessage(); >>> no message is ever dispatched here } service_main_thread() { CoInitialize(); CoCreateInstance(CLSCTX_INPROC_SERVER); >>> REGDB_E_CLASSNOTREG } However the result is the same in the service main thread and now the creation elso fails in the process main thread. -- // Alessandro Angeli // MVP :: DirectShow / MediaFoundation // mvpnews at riseoftheants dot com // http://www.riseoftheants.com/mmx/faq.htm
Well, damn. I have experience with using CoRegisterClassObject this way in regular applications - Perhaps the requirements for COM objects in services is greater. Reading http://msdn2.microsoft.com/en-us/library/ms809975.aspx might help more than I can at this point in terms of getting registration to succeed. "Alessandro Angeli" wrote in message news:uCDV7114HHA.2312@TK2MSFTNGP06.phx.gbl... > From: "Chris Becke" > >> CoInitialize initializes a STA. One of the requirements >> for STA objects to interop with objects in other STA >> threads is that all the threads involved must pump >> messages. > [...] > > Thanks for your reply. I changed the code as following: > > main_thread() > { > CoInitialize(); > wait_for_message_thread_to_be_ready(); > CoCreateInstance(CLSCTX_INPROC_SERVER); > >>> REGDB_E_CLASSNOTREG > wait_for_service_main_to_complete(); > } > > message_thread() > { > CoInitialize(); > CoRegisterClassObject(CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE); > signal_readiness(); > while(GetMessage()) DispatchMessage(); > >>> no message is ever dispatched here > } > > service_main_thread() > { > CoInitialize(); > CoCreateInstance(CLSCTX_INPROC_SERVER); > >>> REGDB_E_CLASSNOTREG > } > > However the result is the same in the service main thread and now the > creation elso fails in the process main thread. > > -- > // Alessandro Angeli > // MVP :: DirectShow / MediaFoundation > // mvpnews at riseoftheants dot com > // http://www.riseoftheants.com/mmx/faq.htm > > >
Actually, two other things. CoCreateInstance on an object that was registered via CoRegisterClassObject in the same thread is very likley to work as there is no marshling required and COM doesnt need to check anything about the object in the registry. If you are passing any sort of custom interface to CoCreateInstance then COM will absolutley require that the marshling object be registered. Even if you just ask for IUnknown, there is a strong liklyhood that COM *needs* some registry entries to exist when trying to connect to a class factory in a different apartment. To debug this you need to get this scenario working first in a simple desktop application with two threads. Then add the additional debugging and development complexity of instantiating as a service. "Alessandro Angeli" wrote in message news:uCDV7114HHA.2312@TK2MSFTNGP06.phx.gbl... > From: "Chris Becke" > >> CoInitialize initializes a STA. One of the requirements >> for STA objects to interop with objects in other STA >> threads is that all the threads involved must pump >> messages. > [...] > > Thanks for your reply. I changed the code as following: > > main_thread() > { > CoInitialize(); > wait_for_message_thread_to_be_ready(); > CoCreateInstance(CLSCTX_INPROC_SERVER); > >>> REGDB_E_CLASSNOTREG > wait_for_service_main_to_complete(); > } > > message_thread() > { > CoInitialize(); > CoRegisterClassObject(CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE); > signal_readiness(); > while(GetMessage()) DispatchMessage(); > >>> no message is ever dispatched here > } > > service_main_thread() > { > CoInitialize(); > CoCreateInstance(CLSCTX_INPROC_SERVER); > >>> REGDB_E_CLASSNOTREG > } > > However the result is the same in the service main thread and now the > creation elso fails in the process main thread. > > -- > // Alessandro Angeli > // MVP :: DirectShow / MediaFoundation > // mvpnews at riseoftheants dot com > // http://www.riseoftheants.com/mmx/faq.htm > > >
I suspect your problem is due to wrong apartment model. Switch to MTA and your current troubles will cease to exist (to be replaced with a whole new set of troubles to make your objects thread safe to be sure...) -- ===================================== Alexander Nickolov Microsoft MVP [VC], MCSD email: agnickolov@mvps.org MVP VC FAQ: http://vcfaq.mvps.org ===================================== "Alessandro Angeli" wrote in message news:uCDV7114HHA.2312@TK2MSFTNGP06.phx.gbl... > From: "Chris Becke" > >> CoInitialize initializes a STA. One of the requirements >> for STA objects to interop with objects in other STA >> threads is that all the threads involved must pump >> messages. > [...] > > Thanks for your reply. I changed the code as following: > > main_thread() > { > CoInitialize(); > wait_for_message_thread_to_be_ready(); > CoCreateInstance(CLSCTX_INPROC_SERVER); > >>> REGDB_E_CLASSNOTREG > wait_for_service_main_to_complete(); > } > > message_thread() > { > CoInitialize(); > CoRegisterClassObject(CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE); > signal_readiness(); > while(GetMessage()) DispatchMessage(); > >>> no message is ever dispatched here > } > > service_main_thread() > { > CoInitialize(); > CoCreateInstance(CLSCTX_INPROC_SERVER); > >>> REGDB_E_CLASSNOTREG > } > > However the result is the same in the service main thread and now the > creation elso fails in the process main thread. > > -- > // Alessandro Angeli > // MVP :: DirectShow / MediaFoundation > // mvpnews at riseoftheants dot com > // http://www.riseoftheants.com/mmx/faq.htm > > >
From: "Alexander Nickolov" > I suspect your problem is due to wrong apartment model. > Switch to MTA and your current troubles will cease to > exist (to be replaced with a whole new set of troubles to > make your objects thread safe to be sure...) Thanks, I'll try this first which is easy (my objects are always born thread-safe out of habit :-)), then Chris' suggestion if this doesn't work. Just a very dumb question since the naming has always confused me: STA = COINIT_APARTMENTTHREADED requires marshalling and it's CoInitialize()'s and OleInitialize()'s choice MTA = COINIT_MULTITHREADED CoInitializeEx()'s default So, if I want free threading without any marshalling, where thread safety is implemented by the objects, I should always use CoInitializeEx(COINIT_MULTITHREADED) instead of CoInitialize(), right? -- // Alessandro Angeli // MVP :: DirectShow / MediaFoundation // mvpnews at riseoftheants dot com // http://www.riseoftheants.com/mmx/faq.htm
Correct. -- ===================================== Alexander Nickolov Microsoft MVP [VC], MCSD email: agnickolov@mvps.org MVP VC FAQ: http://vcfaq.mvps.org ===================================== "Alessandro Angeli" wrote in message news:ub8DxpC5HHA.4676@TK2MSFTNGP05.phx.gbl... > From: "Alexander Nickolov" > >> I suspect your problem is due to wrong apartment model. >> Switch to MTA and your current troubles will cease to >> exist (to be replaced with a whole new set of troubles to >> make your objects thread safe to be sure...) > > Thanks, I'll try this first which is easy (my objects are always born > thread-safe out of habit :-)), then Chris' suggestion if this doesn't > work. > > Just a very dumb question since the naming has always confused me: > > STA = COINIT_APARTMENTTHREADED > requires marshalling and it's CoInitialize()'s > and OleInitialize()'s choice > MTA = COINIT_MULTITHREADED > CoInitializeEx()'s default > > So, if I want free threading without any marshalling, where thread safety > is implemented by the objects, I should always use > CoInitializeEx(COINIT_MULTITHREADED) instead of CoInitialize(), right? > > > -- > // Alessandro Angeli > // MVP :: DirectShow / MediaFoundation > // mvpnews at riseoftheants dot com > // http://www.riseoftheants.com/mmx/faq.htm >
From: "Alexander Nickolov" > I suspect your problem is due to wrong apartment model. > Switch to MTA and your current troubles will cease to > exist (to be replaced with a whole new set of troubles to > make your objects thread safe to be sure...) It looks like it was a problem of interface marshalling (I have a custom interface) like Chris supposed. In fact, following Alexander's suggestion to go from STA to MTA to get rid of marshalling, everything seems to work as exptected now. Thank you both for your help! -- // Alessandro Angeli // MVP :: DirectShow / MediaFoundation // mvpnews at riseoftheants dot com // http://www.riseoftheants.com/mmx/faq.htm