sync ole32 with wine 1.1.28

svn path=/trunk/; revision=42905
This commit is contained in:
Christoph von Wittich 2009-08-24 10:51:15 +00:00
parent c0755ff4f4
commit eb65544870
15 changed files with 1047 additions and 648 deletions

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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),

View file

@ -570,7 +570,7 @@ HRESULT WINAPI OleQueryLinkFromData(
IDataObject* pSrcDataObject)
{
FIXME("(%p),stub!\n", pSrcDataObject);
return S_OK;
return S_FALSE;
}
/***********************************************************************

View file

@ -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)

View file

@ -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,

View file

@ -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)
{

View file

@ -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,

View file

@ -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);

View file

@ -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)
{