When you register a COM object in the Running Object Table with a zero flag (requesting a weak ref), the ROT increments the ref count by 1. The act of getting an object from the ROT increases the ref count by one more. Once that one is freed, the object stays alive with a ref count of at least one. Its registration in the ROT isn't magically revoked upon retrieval, either.
How is that weak? How is that different from strong registration?
Strong registration follows the same pattern - both registering and retrieval increments the ref count by one.
The interface pointer that the ROT returns to in-apartment clients is not a proxy; the ROT has no way of knowing that I've freed my retrieved interface pointer.
really removal from ROT behavior dependent not only from
ROTFLAGS_REGISTRATIONKEEPSALIVEflag but also are (and how) your object implementedIExternalConnection( special note for @IInspectable only - yes all this is undocumented, unsupported, can changed - so please not read more ).
when we register object in ROT com always query him for
IExternalConnectioninterface. if object not implemented it - used default implementation.in case
ROTFLAGS_REGISTRATIONKEEPSALIVEalready at registration timeIExternalConnection::AddConnectioncalled. so we already have 1 external connection. withoutROTFLAGS_REGISTRATIONKEEPSALIVE- this method not called.every time when somebody call
IRunningObjectTable::GetObject(! from another apartment) theCRemoteUnknown::RemAddRefcalled in our process. this method callIExternalConnection::AddConnectiononly if we register withoutROTFLAGS_REGISTRATIONKEEPSALIVEflag .every time when we final
Releaseobject (!on proxy, obtained from previousGetObjectcall ) -CRemoteUnknown::RemReleaseWorkercalled in our local process. and it internally callIExternalConnection::ReleaseConnectiononly in case noROTFLAGS_REGISTRATIONKEEPSALIVEon object. default implementation ofIExternalConnectioncalledCStdMarshal::Disconnect->InternalIrotRevokewhen external reference (not tottal object reference) reach 0 andfLastReleaseCloses == TRUE- as result our object is revoked from ROT. but if we implemetIExternalConnectionby self we can call or not callCoDisconnectObjectso we can be revoked or not from ROT.and finally when we direct or indirect call
IRunningObjectTable::Revokecom callIExternalConnection::ReleaseConnectionif we register withROTFLAGS_REGISTRATIONKEEPSALIVE.so conclusion:
if we register with
ROTFLAGS_REGISTRATIONKEEPSALIVE-IExternalConnection::AddConnectionwill be called only once at registration time (really can be called sayn+1time andntime -ReleaseConnection- but all this insideIRunningObjectTable::Registercall.). when somebody get our object from ROT - we will be not notified about this. and finallyIExternalConnection::ReleaseConnectionwill be called also only once when we callIRunningObjectTable::Revoke.from the other hand, if we not use
ROTFLAGS_REGISTRATIONKEEPSALIVEflag -IExternalConnectionmethods will be not called onRegisterandRevoke. but it will be multiple time called onIRunningObjectTable::GetObjectand finalRelease(on object proxy). if we not implementedIExternalConnectionyourself or callCoDisconnectObjectwhen external refs reach 0 andfLastReleaseCloses- we will be removed from ROT. but we free not callCoDisconnectObject(in this case behavior will be like we useROTFLAGS_REGISTRATIONKEEPSALIVE) or say call it under some condition.advantage - we can track every our object use in case no
ROTFLAGS_REGISTRATIONKEEPSALIVEflag and decide by self are need disconnect when external refs reach 0 or not.and the last - if we call
IRunningObjectTable::GetObjectfrom same apartment where we callIRunningObjectTable::Register- we got not proxy, but direct object pointer. in this case of course will be no calls toIExternalConnectionmethods