[prev in list] [next in list] [prev in thread] [next in thread]
List: wine-devel
Subject: Re: implementing DllCanUnloadNow questions
From: James Hawkins <truiken () gmail ! com>
Date: 2004-11-30 23:33:20
Message-ID: 22821af30411301533a9f6b20 () mail ! gmail ! com
[Download RAW message or body]
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:
> 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 "..."?
> 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 "..."?
--
James Hawkins
["msi-dllcanunloadnow.diff" (text/x-patch)]
Index: dlls/msi/msi.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/msi.c,v
retrieving revision 1.42
diff -u -r1.42 msi.c
--- dlls/msi/msi.c 7 Oct 2004 03:06:50 -0000 1.42
+++ dlls/msi/msi.c 1 Dec 2004 00:29:19 -0000
@@ -42,6 +42,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi);
+/* for reference counting */
+LONG cLocks = 0;
+
/*
* The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
* which is a problem because LPCTSTR isn't defined when compiling wine.
@@ -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;
+}
+
/******************************************************************
* DllCanUnloadNow (MSI.@)
*/
BOOL WINAPI MSI_DllCanUnloadNow(void)
{
- return S_FALSE;
+ return (cLocks > 0) ? S_FALSE : S_OK;
}
UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic