I sent this message a couple months ago, but I got no response so I'll try again.
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.
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?
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?
-- James Hawkins
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
On Tue, 30 Nov 2004 15:34:50 -0600, Robert Shearman rob@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:
- 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 "..."?
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 "..."?
On Tue, 30 Nov 2004 18:33:20 -0500, James Hawkins wrote:
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 "..."?
It's just the function that creates the object. There are no real source conventions in Wine unfortunately so it could be called anything.
Look for a function that HeapAllocs a struct then sets its ->refcount member to 1 (may not be called ->refcount of course).
thanks -mike
James Hawkins wrote:
On Tue, 30 Nov 2004 15:34:50 -0600, Robert Shearman rob@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:
- 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