mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +00:00
sync ole32 with wine 1.1.28
svn path=/trunk/; revision=42905
This commit is contained in:
parent
c0755ff4f4
commit
eb65544870
|
@ -744,6 +744,30 @@ static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
|
||||
{
|
||||
HENHMETAFILE copy;
|
||||
HRESULT hr;
|
||||
FORMATETC mem_fmt;
|
||||
STGMEDIUM med;
|
||||
|
||||
*mem = NULL;
|
||||
|
||||
mem_fmt = *fmt;
|
||||
mem_fmt.tymed = TYMED_ENHMF;
|
||||
|
||||
hr = IDataObject_GetData(data, &mem_fmt, &med);
|
||||
if(FAILED(hr)) return hr;
|
||||
|
||||
copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL);
|
||||
if(copy) *mem = (HGLOBAL)copy;
|
||||
else hr = E_FAIL;
|
||||
|
||||
ReleaseStgMedium(&med);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* render_format
|
||||
*
|
||||
|
@ -773,6 +797,10 @@ static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
|
|||
{
|
||||
hr = get_data_from_global(data, fmt, &clip_data);
|
||||
}
|
||||
else if(fmt->tymed & TYMED_ENHMF)
|
||||
{
|
||||
hr = get_data_from_enhmetafile(data, fmt, &clip_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("Unhandled tymed %x\n", fmt->tymed);
|
||||
|
@ -997,8 +1025,7 @@ static HRESULT get_priv_data(ole_priv_data **data)
|
|||
{
|
||||
char buf[100];
|
||||
GetClipboardFormatNameA(cf, buf, sizeof(buf));
|
||||
TRACE("\tcf %04x %s\n", cf, buf);
|
||||
;
|
||||
TRACE("cf %04x %s\n", cf, buf);
|
||||
}
|
||||
TRACE("count %d\n", count);
|
||||
size += count * sizeof(ret->entries[0]);
|
||||
|
@ -1106,6 +1133,22 @@ static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
|
|||
return hr;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* get_stgmed_for_emf
|
||||
*
|
||||
* Returns a stg medium with an enhanced metafile based on the handle
|
||||
*/
|
||||
static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
|
||||
{
|
||||
med->pUnkForRelease = NULL;
|
||||
med->tymed = TYMED_NULL;
|
||||
|
||||
med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
|
||||
if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY;
|
||||
med->tymed = TYMED_ENHMF;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
|
||||
{
|
||||
const WCHAR *str1, *str2;
|
||||
|
@ -1195,6 +1238,8 @@ static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
|
|||
hr = get_stgmed_for_global(h, med);
|
||||
else if(mask & TYMED_ISTREAM)
|
||||
hr = get_stgmed_for_stream(h, med);
|
||||
else if(mask & TYMED_ENHMF)
|
||||
hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
|
||||
else
|
||||
{
|
||||
FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
|
||||
|
|
|
@ -278,7 +278,7 @@ static HRESULT WINAPI COMCAT_ICatRegister_QueryInterface(
|
|||
LPVOID *ppvObj)
|
||||
{
|
||||
ComCatMgrImpl *This = (ComCatMgrImpl *)iface;
|
||||
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
|
||||
TRACE("%s\n",debugstr_guid(riid));
|
||||
|
||||
if (ppvObj == NULL) return E_POINTER;
|
||||
|
||||
|
@ -515,7 +515,7 @@ static HRESULT WINAPI COMCAT_ICatInformation_GetCategoryDesc(
|
|||
HKEY key;
|
||||
HRESULT res;
|
||||
|
||||
TRACE("\n\tCATID:\t%s\n\tLCID:\t%X\n",debugstr_guid(rcatid), lcid);
|
||||
TRACE("CATID: %s LCID: %x\n",debugstr_guid(rcatid), lcid);
|
||||
|
||||
if (rcatid == NULL || ppszDesc == NULL) return E_INVALIDARG;
|
||||
|
||||
|
@ -596,12 +596,12 @@ static HRESULT WINAPI COMCAT_ICatInformation_IsClassOfCategories(
|
|||
|
||||
if (WINE_TRACE_ON(ole)) {
|
||||
ULONG count;
|
||||
TRACE("\n\tCLSID:\t%s\n\tImplemented %u\n",debugstr_guid(rclsid),cImplemented);
|
||||
TRACE("CLSID: %s Implemented %u\n",debugstr_guid(rclsid),cImplemented);
|
||||
for (count = 0; count < cImplemented; ++count)
|
||||
TRACE("\t\t%s\n",debugstr_guid(&rgcatidImpl[count]));
|
||||
TRACE("\tRequired %u\n",cRequired);
|
||||
TRACE(" %s\n",debugstr_guid(&rgcatidImpl[count]));
|
||||
TRACE("Required %u\n",cRequired);
|
||||
for (count = 0; count < cRequired; ++count)
|
||||
TRACE("\t\t%s\n",debugstr_guid(&rgcatidReq[count]));
|
||||
TRACE(" %s\n",debugstr_guid(&rgcatidReq[count]));
|
||||
}
|
||||
|
||||
if ((cImplemented && rgcatidImpl == NULL) ||
|
||||
|
@ -637,7 +637,7 @@ static HRESULT WINAPI COMCAT_ICatInformation_EnumImplCategoriesOfClass(
|
|||
'n', 't', 'e', 'd', ' ', 'C', 'a', 't',
|
||||
'e', 'g', 'o', 'r', 'i', 'e', 's', 0 };
|
||||
|
||||
TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid));
|
||||
TRACE("%s\n",debugstr_guid(rclsid));
|
||||
|
||||
if (rclsid == NULL || ppenumCATID == NULL)
|
||||
return E_POINTER;
|
||||
|
@ -659,7 +659,7 @@ static HRESULT WINAPI COMCAT_ICatInformation_EnumReqCategoriesOfClass(
|
|||
'd', ' ', 'C', 'a', 't', 'e', 'g', 'o',
|
||||
'r', 'i', 'e', 's', 0 };
|
||||
|
||||
TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid));
|
||||
TRACE("%s\n",debugstr_guid(rclsid));
|
||||
|
||||
if (rclsid == NULL || ppenumCATID == NULL)
|
||||
return E_POINTER;
|
||||
|
@ -719,7 +719,7 @@ static HRESULT WINAPI COMCAT_IClassFactory_QueryInterface(
|
|||
REFIID riid,
|
||||
LPVOID *ppvObj)
|
||||
{
|
||||
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
|
||||
TRACE("%s\n",debugstr_guid(riid));
|
||||
|
||||
if (ppvObj == NULL) return E_POINTER;
|
||||
|
||||
|
@ -760,7 +760,7 @@ static HRESULT WINAPI COMCAT_IClassFactory_CreateInstance(
|
|||
LPVOID *ppvObj)
|
||||
{
|
||||
HRESULT res;
|
||||
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
|
||||
TRACE("%s\n",debugstr_guid(riid));
|
||||
|
||||
if (ppvObj == NULL) return E_POINTER;
|
||||
|
||||
|
@ -834,7 +834,7 @@ static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_QueryInterface(
|
|||
REFIID riid,
|
||||
LPVOID *ppvObj)
|
||||
{
|
||||
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
|
||||
TRACE("%s\n",debugstr_guid(riid));
|
||||
|
||||
if (ppvObj == NULL) return E_POINTER;
|
||||
|
||||
|
@ -1017,7 +1017,7 @@ static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_QueryInterface(
|
|||
REFIID riid,
|
||||
LPVOID *ppvObj)
|
||||
{
|
||||
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
|
||||
TRACE("%s\n",debugstr_guid(riid));
|
||||
|
||||
if (ppvObj == NULL) return E_POINTER;
|
||||
|
||||
|
@ -1203,7 +1203,7 @@ static HRESULT WINAPI COMCAT_CATID_IEnumGUID_QueryInterface(
|
|||
REFIID riid,
|
||||
LPVOID *ppvObj)
|
||||
{
|
||||
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
|
||||
TRACE("%s\n",debugstr_guid(riid));
|
||||
|
||||
if (ppvObj == NULL) return E_POINTER;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -183,7 +183,7 @@ struct oletls
|
|||
LONG pending_call_count_client; /* number of client calls pending */
|
||||
LONG pending_call_count_server; /* number of server calls pending */
|
||||
DWORD unknown;
|
||||
ULONG_PTR context_token; /* (+38h on x86) */
|
||||
IObjContext *context_token; /* (+38h on x86) */
|
||||
IUnknown *call_state; /* current call context (+3Ch on x86) */
|
||||
DWORD unknown2[46];
|
||||
IUnknown *cancel_object; /* cancel object set by CoSetCancelObject (+F8h on x86) */
|
||||
|
@ -203,7 +203,6 @@ HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv);
|
|||
|
||||
/* Stub Manager */
|
||||
|
||||
ULONG stub_manager_int_addref(struct stub_manager *This);
|
||||
ULONG stub_manager_int_release(struct stub_manager *This);
|
||||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object);
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak);
|
||||
|
@ -253,7 +252,6 @@ void OLEDD_UnInitialize(void);
|
|||
|
||||
APARTMENT *apartment_findfromoxid(OXID oxid, BOOL ref);
|
||||
APARTMENT *apartment_findfromtid(DWORD tid);
|
||||
DWORD apartment_addref(struct apartment *apt);
|
||||
DWORD apartment_release(struct apartment *apt);
|
||||
HRESULT apartment_disconnectproxies(struct apartment *apt);
|
||||
void apartment_disconnectobject(struct apartment *apt, void *object);
|
||||
|
|
|
@ -137,6 +137,11 @@ struct DefaultHandler
|
|||
/* storage passed to Load or InitNew */
|
||||
IStorage *storage;
|
||||
enum storage_state storage_state;
|
||||
|
||||
/* optional class factory for object */
|
||||
IClassFactory *pCFObject;
|
||||
/* TRUE if acting as an inproc server instead of an inproc handler */
|
||||
BOOL inproc_server;
|
||||
};
|
||||
|
||||
typedef struct DefaultHandler DefaultHandler;
|
||||
|
@ -223,6 +228,12 @@ static HRESULT WINAPI DefaultHandler_NDIUnknown_QueryInterface(
|
|||
if (FAILED(hr)) FIXME("interface %s not implemented by data cache\n", debugstr_guid(riid));
|
||||
return hr;
|
||||
}
|
||||
else if (This->inproc_server && This->pOleDelegate)
|
||||
{
|
||||
HRESULT hr = IUnknown_QueryInterface(This->pOleDelegate, riid, ppvObject);
|
||||
if (SUCCEEDED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Check that we obtained an interface. */
|
||||
if (*ppvObject == NULL)
|
||||
|
@ -1901,7 +1912,9 @@ static const IPersistStorageVtbl DefaultHandler_IPersistStorage_VTable =
|
|||
*/
|
||||
static DefaultHandler* DefaultHandler_Construct(
|
||||
REFCLSID clsid,
|
||||
LPUNKNOWN pUnkOuter)
|
||||
LPUNKNOWN pUnkOuter,
|
||||
DWORD flags,
|
||||
IClassFactory *pCF)
|
||||
{
|
||||
DefaultHandler* This = NULL;
|
||||
HRESULT hr;
|
||||
|
@ -1918,6 +1931,8 @@ static DefaultHandler* DefaultHandler_Construct(
|
|||
This->lpvtblIAdviseSink = &DefaultHandler_IAdviseSink_VTable;
|
||||
This->lpvtblIPersistStorage = &DefaultHandler_IPersistStorage_VTable;
|
||||
|
||||
This->inproc_server = (flags & EMBDHLP_INPROC_SERVER) ? TRUE : FALSE;
|
||||
|
||||
/*
|
||||
* Start with one reference count. The caller of this function
|
||||
* must release the interface pointer when it is done.
|
||||
|
@ -1964,6 +1979,30 @@ static DefaultHandler* DefaultHandler_Construct(
|
|||
This->storage = NULL;
|
||||
This->storage_state = storage_state_uninitialised;
|
||||
|
||||
if (This->inproc_server && !(flags & EMBDHLP_DELAYCREATE))
|
||||
{
|
||||
HRESULT hr;
|
||||
This->pCFObject = NULL;
|
||||
if (pCF)
|
||||
hr = IClassFactory_CreateInstance(pCF, NULL, &IID_IOleObject, (void **)&This->pOleDelegate);
|
||||
else
|
||||
hr = CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IOleObject, (void **)&This->pOleDelegate);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage, (void **)&This->pPSDelegate);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IDataObject, (void **)&This->pDataDelegate);
|
||||
if (SUCCEEDED(hr))
|
||||
This->object_state = object_state_running;
|
||||
if (FAILED(hr))
|
||||
WARN("object creation failed with error %08x\n", hr);
|
||||
}
|
||||
else
|
||||
{
|
||||
This->pCFObject = pCF;
|
||||
if (pCF) IClassFactory_AddRef(pCF);
|
||||
}
|
||||
|
||||
return This;
|
||||
}
|
||||
|
||||
|
@ -2011,22 +2050,30 @@ static void DefaultHandler_Destroy(
|
|||
This->storage = NULL;
|
||||
}
|
||||
|
||||
if (This->pCFObject)
|
||||
{
|
||||
IClassFactory_Release(This->pCFObject);
|
||||
This->pCFObject = NULL;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* OleCreateDefaultHandler [OLE32.@]
|
||||
* OleCreateEmbeddingHelper [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI OleCreateDefaultHandler(
|
||||
HRESULT WINAPI OleCreateEmbeddingHelper(
|
||||
REFCLSID clsid,
|
||||
LPUNKNOWN pUnkOuter,
|
||||
DWORD flags,
|
||||
IClassFactory *pCF,
|
||||
REFIID riid,
|
||||
LPVOID* ppvObj)
|
||||
{
|
||||
DefaultHandler* newHandler = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, debugstr_guid(riid), ppvObj);
|
||||
TRACE("(%s, %p, %08x, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, flags, pCF, debugstr_guid(riid), ppvObj);
|
||||
|
||||
if (!ppvObj)
|
||||
return E_POINTER;
|
||||
|
@ -2045,7 +2092,7 @@ HRESULT WINAPI OleCreateDefaultHandler(
|
|||
/*
|
||||
* Try to construct a new instance of the class.
|
||||
*/
|
||||
newHandler = DefaultHandler_Construct(clsid, pUnkOuter);
|
||||
newHandler = DefaultHandler_Construct(clsid, pUnkOuter, flags, pCF);
|
||||
|
||||
if (!newHandler)
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -2063,3 +2110,15 @@ HRESULT WINAPI OleCreateDefaultHandler(
|
|||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* OleCreateDefaultHandler [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter,
|
||||
REFIID riid, LPVOID* ppvObj)
|
||||
{
|
||||
TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter,debugstr_guid(riid), ppvObj);
|
||||
return OleCreateEmbeddingHelper(clsid, pUnkOuter, EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW,
|
||||
NULL, riid, ppvObj);
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ static HRESULT WINAPI IErrorInfoImpl_QueryInterface(
|
|||
VOID** ppvoid)
|
||||
{
|
||||
ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
|
||||
TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvoid);
|
||||
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvoid);
|
||||
|
||||
*ppvoid = NULL;
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
|
|||
|
||||
FTMarshalImpl *This = impl_from_IMarshal(iface);
|
||||
|
||||
TRACE ("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid (riid), ppv);
|
||||
TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppv);
|
||||
return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv);
|
||||
}
|
||||
|
||||
|
|
|
@ -431,7 +431,7 @@ static HRESULT WINAPI Proxy_MarshalInterface(
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
TRACE("writing stdobjref:\n\tflags = %04x\n\tcPublicRefs = %d\n\toxid = %s\n\toid = %s\n\tipid = %s\n",
|
||||
TRACE("writing stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n",
|
||||
stdobjref.flags, stdobjref.cPublicRefs,
|
||||
wine_dbgstr_longlong(stdobjref.oxid),
|
||||
wine_dbgstr_longlong(stdobjref.oid),
|
||||
|
@ -1239,7 +1239,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
|
|||
|
||||
assert(apt);
|
||||
|
||||
TRACE("stdobjref:\n\tflags = %04x\n\tcPublicRefs = %d\n\toxid = %s\n\toid = %s\n\tipid = %s\n",
|
||||
TRACE("stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n",
|
||||
stdobjref->flags, stdobjref->cPublicRefs,
|
||||
wine_dbgstr_longlong(stdobjref->oxid),
|
||||
wine_dbgstr_longlong(stdobjref->oid),
|
||||
|
|
|
@ -570,7 +570,7 @@ HRESULT WINAPI OleQueryLinkFromData(
|
|||
IDataObject* pSrcDataObject)
|
||||
{
|
||||
FIXME("(%p),stub!\n", pSrcDataObject);
|
||||
return S_OK;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
@ stub OleConvertOLESTREAMToIStorageEx
|
||||
@ stdcall OleCreate(ptr ptr long ptr ptr ptr ptr)
|
||||
@ stdcall OleCreateDefaultHandler(ptr ptr ptr ptr)
|
||||
@ stub OleCreateEmbeddingHelper
|
||||
@ stdcall OleCreateEmbeddingHelper(ptr ptr long ptr ptr ptr)
|
||||
@ stub OleCreateEx
|
||||
@ stdcall OleCreateFromData(ptr ptr long ptr ptr ptr ptr)
|
||||
@ stdcall OleCreateFromDataEx(ptr ptr long long long ptr ptr ptr ptr ptr ptr ptr)
|
||||
|
|
|
@ -1477,6 +1477,25 @@ static void PropertyStorage_MakePropertyIdOffset(DWORD propid, DWORD dwOffset,
|
|||
offsetof(PROPERTYIDOFFSET, dwOffset), dwOffset);
|
||||
}
|
||||
|
||||
static inline HRESULT PropertStorage_WriteWStringToStream(IStream *stm,
|
||||
LPCWSTR str, DWORD len, DWORD *written)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
WCHAR *leStr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
HRESULT hr;
|
||||
|
||||
if (!leStr)
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy(leStr, str, len * sizeof(WCHAR));
|
||||
PropertyStorage_ByteSwapString(leStr, len);
|
||||
hr = IStream_Write(stm, leStr, len, written);
|
||||
HeapFree(GetProcessHeap(), 0, leStr);
|
||||
return hr;
|
||||
#else
|
||||
return IStream_Write(stm, str, len, written);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct DictionaryClosure
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -1508,15 +1527,11 @@ static BOOL PropertyStorage_DictionaryWriter(const void *key,
|
|||
if (FAILED(c->hr))
|
||||
goto end;
|
||||
c->bytesWritten += sizeof(DWORD);
|
||||
/* Rather than allocate a copy, I'll swap the string to little-endian
|
||||
* in-place, write it, then swap it back.
|
||||
*/
|
||||
PropertyStorage_ByteSwapString(key, keyLen);
|
||||
c->hr = IStream_Write(This->stm, key, keyLen, &count);
|
||||
PropertyStorage_ByteSwapString(key, keyLen);
|
||||
c->hr = PropertStorage_WriteWStringToStream(This->stm, key, keyLen,
|
||||
&count);
|
||||
if (FAILED(c->hr))
|
||||
goto end;
|
||||
c->bytesWritten += keyLen;
|
||||
c->bytesWritten += keyLen * sizeof(WCHAR);
|
||||
if (keyLen % sizeof(DWORD))
|
||||
{
|
||||
c->hr = IStream_Write(This->stm, &pad,
|
||||
|
|
|
@ -232,6 +232,7 @@ static void StgStreamImpl_OpenBlockChain(
|
|||
{
|
||||
This->smallBlockChain = SmallBlockChainStream_Construct(
|
||||
This->parentStorage->ancestorStorage,
|
||||
NULL,
|
||||
This->ownerProperty);
|
||||
}
|
||||
else
|
||||
|
@ -536,8 +537,6 @@ static HRESULT WINAPI StgStreamImpl_Seek(
|
|||
*
|
||||
* It will change the size of a stream.
|
||||
*
|
||||
* TODO: Switch from small blocks to big blocks and vice versa.
|
||||
*
|
||||
* See the documentation of IStream for more info.
|
||||
*/
|
||||
static HRESULT WINAPI StgStreamImpl_SetSize(
|
||||
|
@ -591,6 +590,7 @@ static HRESULT WINAPI StgStreamImpl_SetSize(
|
|||
{
|
||||
This->smallBlockChain = SmallBlockChainStream_Construct(
|
||||
This->parentStorage->ancestorStorage,
|
||||
NULL,
|
||||
This->ownerProperty);
|
||||
}
|
||||
else
|
||||
|
@ -624,6 +624,19 @@ static HRESULT WINAPI StgStreamImpl_SetSize(
|
|||
&This->smallBlockChain);
|
||||
}
|
||||
}
|
||||
else if ( (This->bigBlockChain!=0) &&
|
||||
(curProperty.size.u.LowPart >= LIMIT_TO_USE_SMALL_BLOCK) )
|
||||
{
|
||||
if (libNewSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK)
|
||||
{
|
||||
/*
|
||||
* Transform the big block chain into a small block chain
|
||||
*/
|
||||
This->smallBlockChain = Storage32Impl_BigBlocksToSmallBlocks(
|
||||
This->parentStorage->ancestorStorage,
|
||||
&This->bigBlockChain);
|
||||
}
|
||||
}
|
||||
|
||||
if (This->smallBlockChain!=0)
|
||||
{
|
||||
|
|
|
@ -104,6 +104,7 @@ static ULARGE_INTEGER BlockChainStream_GetSize(BlockChainStream* This);
|
|||
static ULONG BlockChainStream_GetCount(BlockChainStream* This);
|
||||
|
||||
static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This);
|
||||
static ULONG SmallBlockChainStream_GetHeadOfChain(SmallBlockChainStream* This);
|
||||
static BOOL StorageImpl_WriteDWordToBigBlock( StorageImpl* This,
|
||||
ULONG blockIndex, ULONG offset, DWORD value);
|
||||
static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This,
|
||||
|
@ -3586,9 +3587,13 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
|
|||
} while (cbTotalRead.QuadPart < size.QuadPart);
|
||||
HeapFree(GetProcessHeap(),0,buffer);
|
||||
|
||||
size.u.HighPart = 0;
|
||||
size.u.LowPart = 0;
|
||||
|
||||
if (FAILED(resRead) || FAILED(resWrite))
|
||||
{
|
||||
ERR("conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite);
|
||||
BlockChainStream_SetSize(bbTempChain, size);
|
||||
BlockChainStream_Destroy(bbTempChain);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3597,8 +3602,6 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
|
|||
* Destroy the small block chain.
|
||||
*/
|
||||
propertyIndex = (*ppsbChain)->ownerPropertyIndex;
|
||||
size.u.HighPart = 0;
|
||||
size.u.LowPart = 0;
|
||||
SmallBlockChainStream_SetSize(*ppsbChain, size);
|
||||
SmallBlockChainStream_Destroy(*ppsbChain);
|
||||
*ppsbChain = 0;
|
||||
|
@ -3625,6 +3628,86 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
|
|||
return bigBlockChain;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Storage32Impl_BigBlocksToSmallBlocks
|
||||
*
|
||||
* This method will convert a big block chain to a small block chain.
|
||||
* The big block chain will be destroyed on success.
|
||||
*/
|
||||
SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
|
||||
StorageImpl* This,
|
||||
BlockChainStream** ppbbChain)
|
||||
{
|
||||
ULARGE_INTEGER size, offset, cbTotalRead;
|
||||
ULONG cbRead, cbWritten, propertyIndex, sbHeadOfChain = BLOCK_END_OF_CHAIN;
|
||||
HRESULT resWrite = S_OK, resRead;
|
||||
StgProperty chainProperty;
|
||||
BYTE* buffer;
|
||||
SmallBlockChainStream* sbTempChain;
|
||||
|
||||
TRACE("%p %p\n", This, ppbbChain);
|
||||
|
||||
sbTempChain = SmallBlockChainStream_Construct(This, &sbHeadOfChain,
|
||||
PROPERTY_NULL);
|
||||
|
||||
if(!sbTempChain)
|
||||
return NULL;
|
||||
|
||||
size = BlockChainStream_GetSize(*ppbbChain);
|
||||
SmallBlockChainStream_SetSize(sbTempChain, size);
|
||||
|
||||
offset.u.HighPart = 0;
|
||||
offset.u.LowPart = 0;
|
||||
cbTotalRead.QuadPart = 0;
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, This->bigBlockSize);
|
||||
do
|
||||
{
|
||||
resRead = BlockChainStream_ReadAt(*ppbbChain, offset,
|
||||
This->bigBlockSize, buffer, &cbRead);
|
||||
|
||||
if(FAILED(resRead))
|
||||
break;
|
||||
|
||||
if(cbRead > 0)
|
||||
{
|
||||
cbTotalRead.QuadPart += cbRead;
|
||||
|
||||
resWrite = SmallBlockChainStream_WriteAt(sbTempChain, offset,
|
||||
cbRead, buffer, &cbWritten);
|
||||
|
||||
if(FAILED(resWrite))
|
||||
break;
|
||||
|
||||
offset.u.LowPart += This->bigBlockSize;
|
||||
}
|
||||
}while(cbTotalRead.QuadPart < size.QuadPart);
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
|
||||
size.u.HighPart = 0;
|
||||
size.u.LowPart = 0;
|
||||
|
||||
if(FAILED(resRead) || FAILED(resWrite))
|
||||
{
|
||||
ERR("conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite);
|
||||
SmallBlockChainStream_SetSize(sbTempChain, size);
|
||||
SmallBlockChainStream_Destroy(sbTempChain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* destroy the original big block chain */
|
||||
propertyIndex = (*ppbbChain)->ownerPropertyIndex;
|
||||
BlockChainStream_SetSize(*ppbbChain, size);
|
||||
BlockChainStream_Destroy(*ppbbChain);
|
||||
*ppbbChain = NULL;
|
||||
|
||||
StorageImpl_ReadProperty(This, propertyIndex, &chainProperty);
|
||||
chainProperty.startingBlock = sbHeadOfChain;
|
||||
StorageImpl_WriteProperty(This, propertyIndex, &chainProperty);
|
||||
|
||||
SmallBlockChainStream_Destroy(sbTempChain);
|
||||
return SmallBlockChainStream_Construct(This, NULL, propertyIndex);
|
||||
}
|
||||
|
||||
static void StorageInternalImpl_Destroy( StorageBaseImpl *iface)
|
||||
{
|
||||
StorageInternalImpl* This = (StorageInternalImpl*) iface;
|
||||
|
@ -4577,7 +4660,6 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
|
|||
* BlockChainStream_WriteAt
|
||||
*
|
||||
* Writes the specified number of bytes to this chain at the specified offset.
|
||||
* bytesWritten may be NULL.
|
||||
* Will fail if not all specified number of bytes have been written.
|
||||
*/
|
||||
HRESULT BlockChainStream_WriteAt(BlockChainStream* This,
|
||||
|
@ -4929,6 +5011,7 @@ static ULARGE_INTEGER BlockChainStream_GetSize(BlockChainStream* This)
|
|||
|
||||
SmallBlockChainStream* SmallBlockChainStream_Construct(
|
||||
StorageImpl* parentStorage,
|
||||
ULONG* headOfStreamPlaceHolder,
|
||||
ULONG propertyIndex)
|
||||
{
|
||||
SmallBlockChainStream* newStream;
|
||||
|
@ -4936,6 +5019,7 @@ SmallBlockChainStream* SmallBlockChainStream_Construct(
|
|||
newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(SmallBlockChainStream));
|
||||
|
||||
newStream->parentStorage = parentStorage;
|
||||
newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder;
|
||||
newStream->ownerPropertyIndex = propertyIndex;
|
||||
|
||||
return newStream;
|
||||
|
@ -4958,6 +5042,9 @@ static ULONG SmallBlockChainStream_GetHeadOfChain(
|
|||
StgProperty chainProperty;
|
||||
BOOL readSuccessful;
|
||||
|
||||
if (This->headOfStreamPlaceHolder != NULL)
|
||||
return *(This->headOfStreamPlaceHolder);
|
||||
|
||||
if (This->ownerPropertyIndex)
|
||||
{
|
||||
readSuccessful = StorageImpl_ReadProperty(
|
||||
|
@ -5320,7 +5407,6 @@ HRESULT SmallBlockChainStream_ReadAt(
|
|||
* SmallBlockChainStream_WriteAt
|
||||
*
|
||||
* Writes the specified number of bytes to this chain at the specified offset.
|
||||
* bytesWritten may be NULL.
|
||||
* Will fail if not all specified number of bytes have been written.
|
||||
*/
|
||||
HRESULT SmallBlockChainStream_WriteAt(
|
||||
|
@ -5360,9 +5446,6 @@ HRESULT SmallBlockChainStream_WriteAt(
|
|||
|
||||
/*
|
||||
* Start writing the buffer.
|
||||
*
|
||||
* Here, I'm casting away the constness on the buffer variable
|
||||
* This is OK since we don't intend to modify that buffer.
|
||||
*/
|
||||
*bytesWritten = 0;
|
||||
bufferWalker = buffer;
|
||||
|
@ -5509,26 +5592,32 @@ static BOOL SmallBlockChainStream_Enlarge(
|
|||
blockIndex = SmallBlockChainStream_GetHeadOfChain(This);
|
||||
|
||||
/*
|
||||
* Empty chain
|
||||
* Empty chain. Create the head.
|
||||
*/
|
||||
if (blockIndex == BLOCK_END_OF_CHAIN)
|
||||
{
|
||||
|
||||
StgProperty chainProp;
|
||||
|
||||
StorageImpl_ReadProperty(This->parentStorage, This->ownerPropertyIndex,
|
||||
&chainProp);
|
||||
|
||||
chainProp.startingBlock = SmallBlockChainStream_GetNextFreeBlock(This);
|
||||
|
||||
StorageImpl_WriteProperty(This->parentStorage, This->ownerPropertyIndex,
|
||||
&chainProp);
|
||||
|
||||
blockIndex = chainProp.startingBlock;
|
||||
blockIndex = SmallBlockChainStream_GetNextFreeBlock(This);
|
||||
SmallBlockChainStream_SetNextBlockInChain(
|
||||
This,
|
||||
blockIndex,
|
||||
BLOCK_END_OF_CHAIN);
|
||||
This,
|
||||
blockIndex,
|
||||
BLOCK_END_OF_CHAIN);
|
||||
|
||||
if (This->headOfStreamPlaceHolder != NULL)
|
||||
{
|
||||
*(This->headOfStreamPlaceHolder) = blockIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
StgProperty chainProp;
|
||||
|
||||
StorageImpl_ReadProperty(This->parentStorage, This->ownerPropertyIndex,
|
||||
&chainProp);
|
||||
|
||||
chainProp.startingBlock = blockIndex;
|
||||
|
||||
StorageImpl_WriteProperty(This->parentStorage, This->ownerPropertyIndex,
|
||||
&chainProp);
|
||||
}
|
||||
}
|
||||
|
||||
currentBlock = blockIndex;
|
||||
|
@ -5603,6 +5692,32 @@ BOOL SmallBlockChainStream_SetSize(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* SmallBlockChainStream_GetCount
|
||||
*
|
||||
* Returns the number of small blocks that comprises this chain.
|
||||
* This is not the size of the stream as the last block may not be full!
|
||||
*
|
||||
*/
|
||||
static ULONG SmallBlockChainStream_GetCount(SmallBlockChainStream* This)
|
||||
{
|
||||
ULONG blockIndex;
|
||||
ULONG count = 0;
|
||||
|
||||
blockIndex = SmallBlockChainStream_GetHeadOfChain(This);
|
||||
|
||||
while(blockIndex != BLOCK_END_OF_CHAIN)
|
||||
{
|
||||
count++;
|
||||
|
||||
if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This,
|
||||
blockIndex, &blockIndex)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* SmallBlockChainStream_GetSize
|
||||
*
|
||||
|
@ -5612,6 +5727,17 @@ static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This)
|
|||
{
|
||||
StgProperty chainProperty;
|
||||
|
||||
if(This->headOfStreamPlaceHolder != NULL)
|
||||
{
|
||||
ULARGE_INTEGER result;
|
||||
result.u.HighPart = 0;
|
||||
|
||||
result.u.LowPart = SmallBlockChainStream_GetCount(This) *
|
||||
This->parentStorage->smallBlockSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
StorageImpl_ReadProperty(
|
||||
This->parentStorage,
|
||||
This->ownerPropertyIndex,
|
||||
|
|
|
@ -306,6 +306,10 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
|
|||
StorageImpl* This,
|
||||
SmallBlockChainStream** ppsbChain);
|
||||
|
||||
SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
|
||||
StorageImpl* This,
|
||||
BlockChainStream** ppbbChain);
|
||||
|
||||
/****************************************************************************
|
||||
* StgStreamImpl definitions.
|
||||
*
|
||||
|
@ -464,14 +468,16 @@ struct SmallBlockChainStream
|
|||
{
|
||||
StorageImpl* parentStorage;
|
||||
ULONG ownerPropertyIndex;
|
||||
ULONG* headOfStreamPlaceHolder;
|
||||
};
|
||||
|
||||
/*
|
||||
* Methods of the SmallBlockChainStream class.
|
||||
*/
|
||||
SmallBlockChainStream* SmallBlockChainStream_Construct(
|
||||
StorageImpl* parentStorage,
|
||||
ULONG propertyIndex);
|
||||
StorageImpl* parentStorage,
|
||||
ULONG* headOfStreamPlaceHolder,
|
||||
ULONG propertyIndex);
|
||||
|
||||
void SmallBlockChainStream_Destroy(
|
||||
SmallBlockChainStream* This);
|
||||
|
|
|
@ -42,8 +42,129 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub);
|
||||
static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid);
|
||||
|
||||
/* generates an ipid in the following format (similar to native version):
|
||||
* Data1 = apartment-local ipid counter
|
||||
* Data2 = apartment creator thread ID
|
||||
* Data3 = process ID
|
||||
* Data4 = random value
|
||||
*/
|
||||
static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
|
||||
{
|
||||
HRESULT hr;
|
||||
hr = UuidCreate(ipid);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERR("couldn't create IPID for stub manager %p\n", m);
|
||||
UuidCreateNil(ipid);
|
||||
return hr;
|
||||
}
|
||||
|
||||
ipid->Data1 = InterlockedIncrement(&m->apt->ipidc);
|
||||
ipid->Data2 = (USHORT)m->apt->tid;
|
||||
ipid->Data3 = (USHORT)GetCurrentProcessId();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* registers a new interface stub COM object with the stub manager and returns registration record */
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags)
|
||||
{
|
||||
struct ifstub *stub;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n",
|
||||
wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid));
|
||||
|
||||
stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
|
||||
if (!stub) return NULL;
|
||||
|
||||
hr = RPC_CreateServerChannel(&stub->chan);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, stub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stub->stubbuffer = sb;
|
||||
if (sb) IRpcStubBuffer_AddRef(sb);
|
||||
|
||||
IUnknown_AddRef(iptr);
|
||||
stub->iface = iptr;
|
||||
stub->flags = flags;
|
||||
stub->iid = *iid;
|
||||
|
||||
/* FIXME: find a cleaner way of identifying that we are creating an ifstub
|
||||
* for the remunknown interface */
|
||||
if (flags & MSHLFLAGSP_REMUNKNOWN)
|
||||
stub->ipid = m->oxid_info.ipidRemUnknown;
|
||||
else
|
||||
generate_ipid(m, &stub->ipid);
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
list_add_head(&m->ifstubs, &stub->entry);
|
||||
/* every normal marshal is counted so we don't allow more than we should */
|
||||
if (flags & MSHLFLAGS_NORMAL) m->norm_refs++;
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub)
|
||||
{
|
||||
TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid));
|
||||
|
||||
list_remove(&ifstub->entry);
|
||||
|
||||
RPC_UnregisterInterface(&ifstub->iid);
|
||||
|
||||
if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer);
|
||||
IUnknown_Release(ifstub->iface);
|
||||
IRpcChannelBuffer_Release(ifstub->chan);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, ifstub);
|
||||
}
|
||||
|
||||
static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid)
|
||||
{
|
||||
struct list *cursor;
|
||||
struct ifstub *result = NULL;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
LIST_FOR_EACH( cursor, &m->ifstubs )
|
||||
{
|
||||
struct ifstub *ifstub = LIST_ENTRY( cursor, struct ifstub, entry );
|
||||
|
||||
if (IsEqualGUID(ipid, &ifstub->ipid))
|
||||
{
|
||||
result = ifstub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags)
|
||||
{
|
||||
struct ifstub *result = NULL;
|
||||
struct ifstub *ifstub;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
LIST_FOR_EACH_ENTRY( ifstub, &m->ifstubs, struct ifstub, entry )
|
||||
{
|
||||
if (IsEqualIID(iid, &ifstub->iid) && (ifstub->flags == flags))
|
||||
{
|
||||
result = ifstub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* creates a new stub manager and adds it into the apartment. caller must
|
||||
* release stub manager when it is no longer required. the apartment and
|
||||
|
@ -129,6 +250,44 @@ static void stub_manager_delete(struct stub_manager *m)
|
|||
HeapFree(GetProcessHeap(), 0, m);
|
||||
}
|
||||
|
||||
/* increments the internal refcount */
|
||||
static ULONG stub_manager_int_addref(struct stub_manager *This)
|
||||
{
|
||||
ULONG refs;
|
||||
|
||||
EnterCriticalSection(&This->apt->cs);
|
||||
refs = ++This->refs;
|
||||
LeaveCriticalSection(&This->apt->cs);
|
||||
|
||||
TRACE("before %d\n", refs - 1);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
/* decrements the internal refcount */
|
||||
ULONG stub_manager_int_release(struct stub_manager *This)
|
||||
{
|
||||
ULONG refs;
|
||||
APARTMENT *apt = This->apt;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
refs = --This->refs;
|
||||
|
||||
TRACE("after %d\n", refs);
|
||||
|
||||
/* remove from apartment so no other thread can access it... */
|
||||
if (!refs)
|
||||
list_remove(&This->entry);
|
||||
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
/* ... so now we can delete it without being inside the apartment critsec */
|
||||
if (!refs)
|
||||
stub_manager_delete(This);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
/* gets the stub manager associated with an object - caller must have
|
||||
* a reference to the apartment while a reference to the stub manager is held.
|
||||
* it must also call release on the stub manager when it is no longer needed */
|
||||
|
@ -214,44 +373,6 @@ struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* increments the internal refcount */
|
||||
ULONG stub_manager_int_addref(struct stub_manager *This)
|
||||
{
|
||||
ULONG refs;
|
||||
|
||||
EnterCriticalSection(&This->apt->cs);
|
||||
refs = ++This->refs;
|
||||
LeaveCriticalSection(&This->apt->cs);
|
||||
|
||||
TRACE("before %d\n", refs - 1);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
/* decrements the internal refcount */
|
||||
ULONG stub_manager_int_release(struct stub_manager *This)
|
||||
{
|
||||
ULONG refs;
|
||||
APARTMENT *apt = This->apt;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
refs = --This->refs;
|
||||
|
||||
TRACE("after %d\n", refs);
|
||||
|
||||
/* remove from apartment so no other thread can access it... */
|
||||
if (!refs)
|
||||
list_remove(&This->entry);
|
||||
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
/* ... so now we can delete it without being inside the apartment critsec */
|
||||
if (!refs)
|
||||
stub_manager_delete(This);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
/* add some external references (ie from a client that unmarshaled an ifptr) */
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak)
|
||||
{
|
||||
|
@ -297,46 +418,6 @@ ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tablewea
|
|||
return rc;
|
||||
}
|
||||
|
||||
static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid)
|
||||
{
|
||||
struct list *cursor;
|
||||
struct ifstub *result = NULL;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
LIST_FOR_EACH( cursor, &m->ifstubs )
|
||||
{
|
||||
struct ifstub *ifstub = LIST_ENTRY( cursor, struct ifstub, entry );
|
||||
|
||||
if (IsEqualGUID(ipid, &ifstub->ipid))
|
||||
{
|
||||
result = ifstub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags)
|
||||
{
|
||||
struct ifstub *result = NULL;
|
||||
struct ifstub *ifstub;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
LIST_FOR_EACH_ENTRY( ifstub, &m->ifstubs, struct ifstub, entry )
|
||||
{
|
||||
if (IsEqualIID(iid, &ifstub->iid) && (ifstub->flags == flags))
|
||||
{
|
||||
result = ifstub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* gets the stub manager associated with an ipid - caller must have
|
||||
* a reference to the apartment while a reference to the stub manager is held.
|
||||
* it must also call release on the stub manager when it is no longer needed */
|
||||
|
@ -426,89 +507,6 @@ HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt,
|
|||
}
|
||||
}
|
||||
|
||||
/* generates an ipid in the following format (similar to native version):
|
||||
* Data1 = apartment-local ipid counter
|
||||
* Data2 = apartment creator thread ID
|
||||
* Data3 = process ID
|
||||
* Data4 = random value
|
||||
*/
|
||||
static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
|
||||
{
|
||||
HRESULT hr;
|
||||
hr = UuidCreate(ipid);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERR("couldn't create IPID for stub manager %p\n", m);
|
||||
UuidCreateNil(ipid);
|
||||
return hr;
|
||||
}
|
||||
|
||||
ipid->Data1 = InterlockedIncrement(&m->apt->ipidc);
|
||||
ipid->Data2 = (USHORT)m->apt->tid;
|
||||
ipid->Data3 = (USHORT)GetCurrentProcessId();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* registers a new interface stub COM object with the stub manager and returns registration record */
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags)
|
||||
{
|
||||
struct ifstub *stub;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n",
|
||||
wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid));
|
||||
|
||||
stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
|
||||
if (!stub) return NULL;
|
||||
|
||||
hr = RPC_CreateServerChannel(&stub->chan);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, stub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stub->stubbuffer = sb;
|
||||
if (sb) IRpcStubBuffer_AddRef(sb);
|
||||
|
||||
IUnknown_AddRef(iptr);
|
||||
stub->iface = iptr;
|
||||
stub->flags = flags;
|
||||
stub->iid = *iid;
|
||||
|
||||
/* FIXME: find a cleaner way of identifying that we are creating an ifstub
|
||||
* for the remunknown interface */
|
||||
if (flags & MSHLFLAGSP_REMUNKNOWN)
|
||||
stub->ipid = m->oxid_info.ipidRemUnknown;
|
||||
else
|
||||
generate_ipid(m, &stub->ipid);
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
list_add_head(&m->ifstubs, &stub->entry);
|
||||
/* every normal marshal is counted so we don't allow more than we should */
|
||||
if (flags & MSHLFLAGS_NORMAL) m->norm_refs++;
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub)
|
||||
{
|
||||
TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid));
|
||||
|
||||
list_remove(&ifstub->entry);
|
||||
|
||||
RPC_UnregisterInterface(&ifstub->iid);
|
||||
|
||||
if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer);
|
||||
IUnknown_Release(ifstub->iface);
|
||||
IRpcChannelBuffer_Release(ifstub->chan);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, ifstub);
|
||||
}
|
||||
|
||||
/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue