Hi,
I just thought I'd document the CLEANLOCALSTORAGE use in oleaut32 for anyone that wants to implement it, although I can't implement it now for obvious reasons.
First of all the background: the reason CLEANLOCALSTORAGE is needed is because the structures returned from various Get* functions in ITypeInfo and ITypeLib have pointers that have been allocated opaquely and have to be freed using the corresponding Release* function. AFAICS, the problem is not that the memory will not be freed (the RPC runtime should traverse the structure thoroughly and release all of the pointers with NdrOleFree), but that some of the memory may not need to be freed (and memory corruption could take place if it were).
So what should the various CLEANLOCALSTORAGE functions actually do?
CLEANLOCALSTORAGE_UserFree - nothing, as the marshaled DWORD does not need to be freed. CLEANLOCALSTORAGE_UserMarshal: o DWORD align the buffer. o Put the storage type into the buffer and increment it. o Call the relevent freer for the storage type, passing in the memory pointed to in CLEANLOCALSTORAGE. o Release the interface in CLEANLOCALSTORAGE. o Set memory pointed to in CLEANLOCALSTORAGE to NULL (so that the memory isn't freed again by the RPC runtime). CLEANLOCALSTORAGE_UserUnmarshal: o DWORD align the buffer. o Take the storage type from the buffer, increment the buffer and put the storage type into CLEANLOCALSTORAGE. CLEANLOCALSTORAGE_UserSize: o DWORD align the size and add sizeof(DWORD) to it.
What should each of the Get* functions do that have a corresponding Release* function?
o Put a type into CLEANLOCALSTORAGE (see below for what number this should be). o AddRef the interface to call the Release* function on and put it into CLEANLOCALSTORAGE. o Put a pointer to a pointer to the structure that is being allocated into CLEANLOCALSTORAGE.
What type number corresponds to what function? ITypeComp_Bind - 0x66 or 0x76, depending on what is returned. ITypeInfo_GetTypeAttr - 0x74 ITypeInfo_GetFuncDesc - 0x66 ITypeInfo_GetVarDesc - 0x76 ITypeLib_GetLibAttr - 0x6c
Note: it may be necessary to zero out certain fields of the various structures in the stub functions so that bad pointers don't get marshalled.
Thanks,
P.S. Take care to deep free all memory when releasing the pointers on the proxy side when implementing the Release*_Proxy functions.
On Wed, 19 Apr 2006 00:24:07 +0100, Robert Shearman wrote:
Hi,
I just thought I'd document the CLEANLOCALSTORAGE use in oleaut32 for anyone that wants to implement it, although I can't implement it now for obvious reasons.
Rob, can you put this stuff on the wiki?
On Wed, Apr 19, 2006 at 12:24:07AM +0100, Robert Shearman wrote:
Hi,
I just thought I'd document the CLEANLOCALSTORAGE use in oleaut32 for anyone that wants to implement it, although I can't implement it now for obvious reasons.
Great, thanks. I just sent a patch to wine-patches that implements this for GetLibAttr.
First of all the background: the reason CLEANLOCALSTORAGE is needed is because the structures returned from various Get* functions in ITypeInfo and ITypeLib have pointers that have been allocated opaquely and have to be freed using the corresponding Release* function. AFAICS, the problem is not that the memory will not be freed (the RPC runtime should traverse the structure thoroughly and release all of the pointers with NdrOleFree), but that some of the memory may not need to be freed (and memory corruption could take place if it were).
Yeah, and the reason it works is that the CLEANLOCALSTORAGE paramater is last and hence marshalled after the structure of interest, so we get a chance to call the _Release function before the stub does its own cleanup.
Huw.