Returning any HRESULT from FinalConstruct other than S_OK, results in client receiving REGDB_E_CLASSNOTREG
-
Does anyone know what valid values can be returned from FinalConstruct? Originally I was helping out some colleagues on how to set the error information in an ATL component. They wanted to be able to set the COM error information. I showed them what to do so that their COM object implemented ISupportErrorInfo. They want to return information to the client if there is an error accessing certain state information needed for the COM object to do its job. So I told them to put their code in FinalConstruct, but they are saying that the error info in _com_error::Description() is blank. An HRESULT had been set in _com_error, but it just showed as a hex value when added to the watch window with m"_hRes, hr". When they created their COM object they didn't know to click supports ISupportErrorInfo in the atl object wizard, so this has all been added by hand. I tried to test this using a dummy com object implementation on my PC, but the client returns REGDB_E_CLASSNOTREG. I did find a nntp message saying that you should not set any rich error info in FinalConstruct but just to return an HRESULT. However if I return any HRESULT other than S_OK, the client returns REGDB_E_CLASSNOTREG. I have tried other code of ours that tries to set rich error info with AtlReportError etc, but I don't think this ever gets called because they are just constructing other COM objects that usually succeed. When I deliberately change the active code line to set the error information then they too return REGDB_E_CLASSNOTREG.
-
Does anyone know what valid values can be returned from FinalConstruct? Originally I was helping out some colleagues on how to set the error information in an ATL component. They wanted to be able to set the COM error information. I showed them what to do so that their COM object implemented ISupportErrorInfo. They want to return information to the client if there is an error accessing certain state information needed for the COM object to do its job. So I told them to put their code in FinalConstruct, but they are saying that the error info in _com_error::Description() is blank. An HRESULT had been set in _com_error, but it just showed as a hex value when added to the watch window with m"_hRes, hr". When they created their COM object they didn't know to click supports ISupportErrorInfo in the atl object wizard, so this has all been added by hand. I tried to test this using a dummy com object implementation on my PC, but the client returns REGDB_E_CLASSNOTREG. I did find a nntp message saying that you should not set any rich error info in FinalConstruct but just to return an HRESULT. However if I return any HRESULT other than S_OK, the client returns REGDB_E_CLASSNOTREG. I have tried other code of ours that tries to set rich error info with AtlReportError etc, but I don't think this ever gets called because they are just constructing other COM objects that usually succeed. When I deliberately change the active code line to set the error information then they too return REGDB_E_CLASSNOTREG.
Is it possible that the error code is right and their class *hasn't* yet been registered?
-
Is it possible that the error code is right and their class *hasn't* yet been registered?
No, its runtime dependent. For example I can make FinalConstruct's return value dependent on the existence of a file returning S_OK if present and E_OUTOFMEMORY if not and REGDB_E_CLASSNOTREG is caught when the file is absent.
-
No, its runtime dependent. For example I can make FinalConstruct's return value dependent on the existence of a file returning S_OK if present and E_OUTOFMEMORY if not and REGDB_E_CLASSNOTREG is caught when the file is absent.
Ah, sorry - didn't quite pick up on that :-( Anyway - I knocked up a little ATL server project and a client and I get the same behaviour as you (good start). Stepping back through the call stack (and keeping an eye on the value of
EAX
as that's where function return values are stored), it would seem that theREGDB_E_CLASSNOTREG
is introduced inside ole32.dll, i.e. by Windows, because after your InprocServer fails to construct properly, OLE attempts to load your class using other COM server types (e.g. out-of-process server). To cut a long story short, the correctHRESULT
gets passed back to your client so long as you use the correct[CLSCTX](http://msdn.microsoft.com/en-us/library/ms693716\(VS.85\).aspx)[[^](http://msdn.microsoft.com/en-us/library/ms693716\(VS.85\).aspx "New Window")]
enumeration in your call toCoCreateInstance
. Here's the code I used which picks up the correctHRESULT
- my server is an in-process server (i.e. implemented in an ATL DLL project).::CoInitialize(0); CComPtr<IUnknown> wibble; HRESULT hr = wibble.CoCreateInstance(CLSID_paf, 0, CLSCTX_INPROC_SERVER);
To re-iterate, using the appropriate CLSCTX enumeral should allow you to retrieve the correct
HRESULT
. -
Ah, sorry - didn't quite pick up on that :-( Anyway - I knocked up a little ATL server project and a client and I get the same behaviour as you (good start). Stepping back through the call stack (and keeping an eye on the value of
EAX
as that's where function return values are stored), it would seem that theREGDB_E_CLASSNOTREG
is introduced inside ole32.dll, i.e. by Windows, because after your InprocServer fails to construct properly, OLE attempts to load your class using other COM server types (e.g. out-of-process server). To cut a long story short, the correctHRESULT
gets passed back to your client so long as you use the correct[CLSCTX](http://msdn.microsoft.com/en-us/library/ms693716\(VS.85\).aspx)[[^](http://msdn.microsoft.com/en-us/library/ms693716\(VS.85\).aspx "New Window")]
enumeration in your call toCoCreateInstance
. Here's the code I used which picks up the correctHRESULT
- my server is an in-process server (i.e. implemented in an ATL DLL project).::CoInitialize(0); CComPtr<IUnknown> wibble; HRESULT hr = wibble.CoCreateInstance(CLSID_paf, 0, CLSCTX_INPROC_SERVER);
To re-iterate, using the appropriate CLSCTX enumeral should allow you to retrieve the correct
HRESULT
.Wow! Excellent work, thanks for your help. It seems however that you cannot use ISupportErrorInfo, the _com_error::Description is blank. This does however seem to confirm what I read in the microsoft newsgroups, that your not supposed to set any rich error information inside FinalConstruct. This doesn't seemed to be mentioned in MSDN, but then neither is there any info on REGDB_E_CLASSNOTREG for that matter. Many, many thanks the important thing is they can return an error code from CreateInstance. Peter