implementing DllCanUnloadNow questions
Robert Shearman
rob at codeweavers.com
Wed Dec 1 10:53:25 CST 2004
James Hawkins wrote:
>On Tue, 30 Nov 2004 15:34:50 -0600, Robert Shearman <rob at codeweavers.com> wrote:
>
>
>>James Hawkins wrote:
>>
>>
>>
>>>I would like to work on the DllCanUnloadNow janitorial task, but I was
>>>wondering if there are any patches or examples of dll's that correctly
>>>implement this so that I can do it right.
>>>
>>>
>>>
>>>
>>I don't know of any examples so far, but Mike Hearn and I will be
>>tackling OLE soon, so that will involve cleaning up ole32. However, that
>>probably won't happen until we've done some groundwork on COM first, so
>>feel free to beat us to it and make a shining example of a DLL that
>>correctly implements DllCanUnloadNow.
>>
>>
>>
>>
>>
>>>Is LockServer(TRUE/FALSE) the same as this example?
>>>
>>>static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
>>> IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
>>> FIXME("(%p)->(%d),stub!\n",This,dolock);
>>> return S_OK;
>>>}
>>>
>>>If they are the same, what is needed to complete this stub? I would
>>>think that there would be a refCount variable that is incremented if
>>>dolock is true and decremented if dolock is false. Also, should the
>>>LockServer functions be listed in the spec files of the dlls?
>>>
>>>
>>>
>>>
>>No, the LockServer functions are part of IClassFactory vtables. Only
>>DllCanUnloadNow needs to be exported.
>>
>>
>>
>>>After implementing LockServer, it should be an easy matter to do a
>>>check for refCount == 0 to see if the dll can be unloaded or not. Am
>>>I heading in the right direction?
>>>
>>>
>>>
>>>
>>To implement DllCanUnloadNow properly you need to do the following:
>>1. Add a variable "LONG cLocks" and two function for manipulating it:
>>void LockModule()
>>{
>> InterlockedIncrement(&cLocks);
>>}
>>
>>void UnlockModule()
>>{
>> InterlockedDecrement(&cLocks);
>>}
>>2. Increment cLocks on construction of every heap object:
>>static HRESULT Example_Construct(...)
>>{
>>...
>> LockModule();
>> return S_OK;
>>}
>>3. Decrement cLocks on destruction of every heap object:
>>static ULONG Example_Release(...)
>>{
>> ...
>> res = InterlockedDecrement(&This->cRefs);
>> if (!res)
>> {
>> /* Free object's resources, including memory, etc. */
>> UnlockModule();
>> }
>>}
>>4. For non-heap based objects (commonly objects with no state, like
>>IClassFactory):
>>static ULONG Example_AddRef(...)
>>{
>> LockModule();
>> return 2; /* non-heap object */
>>}
>>
>>static ULONG Example_Release(...)
>>{
>> UnlockModule();
>> return 1;
>>}
>>5. Implement IClassFactory_LockServer's as follows:
>>HRESULT WINAPI Example_LockServer(...)
>>{
>> if (bLock)
>> LockModule();
>> else
>> UnlockModule();
>> return S_OK;
>>}
>>6. Then implement DllCanUnloadNow:
>>HRESULT WINAPI DllCanUnloadNow()
>>{
>> return cLocks > 0 : S_FALSE : S_OK;
>>}
>>
>>Rob
>>
>>
>>
>
>Attached is my beginning attempts at adding DllCanUnloadNow to msi.
>There are a couple questions I have though.
>
>
>
>>static HRESULT Example_Construct(...)
>>{
>>...
>> LockModule();
>> return S_OK;
>>}
>>
>>
>
>Is _Construct the same as _AddRef()? I'm thinking it's not. If it
>isn't, I need to add a MSI_Construct to msi. What are the parameters
>to the Construct function and what would usually go in the place of
>the "..."?
>
>
The _Construct function has a similar purpose to the C++ constructor,
except that we usually allocate the memory in _Construct as well
(whereas the C++ normally compiler does this). The parameters and return
value vary according to the situation. If the object has a number of
properties that are set up at creation time, then these should be passed
to the constructor.
>>static ULONG Example_Release(...)
>>{
>> ...
>> res = InterlockedDecrement(&This->cRefs);
>> if (!res)
>> {
>> /* Free object's resources, including memory, etc. */
>> UnlockModule();
>> }
>>}
>>
>>
>
>
>
>>static ULONG Example_Release(...)
>>{
>> UnlockModule();
>> return 1;
>>}
>>
>>
>
>Are these _Release's referring to the same function? If not, what is
>the difference? If so, which one should be implemented and what
>usually goes in the place of the "..."?
>
>
The difference is that the first one is a heap based object, so it does
the ref-counting itself, whereas the second is a non-heap based object
where it makes no sense to keep an internal ref-count so UnlockModule is
always called (and LockModule is always called in AddRef).
>------------------------------------------------------------------------
>
>@@ -1567,12 +1570,32 @@
> return S_OK;
> }
>
>+void LockModule()
>+{
>+ InterlockedIncrement(&cLocks);
>+}
>+
>+void UnlockModule()
>+{
>+ InterlockedDecrement(&cLocks);
>+}
>+
>+HRESULT WINAPI MSI_LockServer(LPCLASSFACTORY iface,BOOL bLock)
>+{
>+ if (bLock)
>+ LockModule();
>+ else
>+ UnlockModule();
>+
>+ return S_OK;
>+}
>+
>
>
Not quite right. The _LockServer method should be the one included in
the IClassFactory implementation's vtable and I don't see this in this
patch.
Rob
More information about the wine-devel
mailing list