[OLE32] Sync with Wine Staging 2.16. CORE-13762

a56bc8f ole32: Store proxy/stub CLSIDs per process, not per apartment.
3b44927 ole32: New high resolution cursors generated from SVG.
5a3b87a ole32: Avoid null pointer dereferences in CoGetTreatAsClass.
13c6d37 ole32: Add stub for OleGetIconOfFile.
33a720b ole32: InitNew() should fail if there is a current storage.
966e8a2 ole32: Create initial cache entries for the CLSID_Picture_ classes.
111b72f ole32: Add the ability to create an entry without returning it.
705ccd7 ole32: Start allocating regular cache entries with id of 2.
0267564 ole32: Fix incorrectly assigned member in the presentation stream.
85a1309 ole32: Make bitmap_info_size() static.

svn path=/trunk/; revision=75890
This commit is contained in:
Amine Khaldi 2017-09-17 22:56:11 +00:00
parent 88ff4126bc
commit 7634613083
10 changed files with 175 additions and 69 deletions

View file

@ -146,6 +146,17 @@ struct registered_psclsid
CLSID clsid;
};
static struct list registered_psclsid_list = LIST_INIT(registered_psclsid_list);
static CRITICAL_SECTION cs_registered_psclsid_list;
static CRITICAL_SECTION_DEBUG psclsid_cs_debug =
{
0, 0, &cs_registered_psclsid_list,
{ &psclsid_cs_debug.ProcessLocksList, &psclsid_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": cs_registered_psclsid_list") }
};
static CRITICAL_SECTION cs_registered_psclsid_list = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
/*
* This is a marshallable object exposing registered local servers.
* IServiceProvider is used only because it happens meet requirements
@ -600,7 +611,6 @@ static APARTMENT *apartment_construct(DWORD model)
list_init(&apt->proxies);
list_init(&apt->stubmgrs);
list_init(&apt->psclsids);
list_init(&apt->loaded_dlls);
apt->ipidc = 0;
apt->refs = 1;
@ -711,6 +721,21 @@ static void COM_RevokeAllClasses(const struct apartment *apt)
LeaveCriticalSection( &csRegisteredClassList );
}
static void revoke_registered_psclsids(void)
{
struct registered_psclsid *psclsid, *psclsid2;
EnterCriticalSection( &cs_registered_psclsid_list );
LIST_FOR_EACH_ENTRY_SAFE(psclsid, psclsid2, &registered_psclsid_list, struct registered_psclsid, entry)
{
list_remove(&psclsid->entry);
HeapFree(GetProcessHeap(), 0, psclsid);
}
LeaveCriticalSection( &cs_registered_psclsid_list );
}
/******************************************************************************
* Implementation of the manual reset event object. (CLSID_ManualResetEvent)
*/
@ -1151,15 +1176,6 @@ DWORD apartment_release(struct apartment *apt)
stub_manager_int_release(stubmgr);
}
LIST_FOR_EACH_SAFE(cursor, cursor2, &apt->psclsids)
{
struct registered_psclsid *registered_psclsid =
LIST_ENTRY(cursor, struct registered_psclsid, entry);
list_remove(&registered_psclsid->entry);
HeapFree(GetProcessHeap(), 0, registered_psclsid);
}
/* if this assert fires, then another thread took a reference to a
* stub manager without taking a reference to the containing
* apartment, which it must do. */
@ -1966,6 +1982,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
{
TRACE("() - Releasing the COM libraries\n");
revoke_registered_psclsids();
RunningObjectTableImpl_UnInitialize();
}
else if (lCOMRefCnt<1) {
@ -2558,17 +2575,17 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
if (!pclsid)
return E_INVALIDARG;
EnterCriticalSection(&apt->cs);
EnterCriticalSection(&cs_registered_psclsid_list);
LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry)
LIST_FOR_EACH_ENTRY(registered_psclsid, &registered_psclsid_list, struct registered_psclsid, entry)
if (IsEqualIID(&registered_psclsid->iid, riid))
{
*pclsid = registered_psclsid->clsid;
LeaveCriticalSection(&apt->cs);
LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK;
}
LeaveCriticalSection(&apt->cs);
LeaveCriticalSection(&cs_registered_psclsid_list);
data.cbSize = sizeof(data);
if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
@ -2613,6 +2630,9 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
*
* NOTES
*
* Unlike CoRegisterClassObject(), CLSIDs registered with CoRegisterPSClsid()
* will be returned from other apartments in the same process.
*
* This function does not add anything to the registry and the effects are
* limited to the lifetime of the current process.
*
@ -2632,28 +2652,28 @@ HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
return CO_E_NOTINITIALIZED;
}
EnterCriticalSection(&apt->cs);
EnterCriticalSection(&cs_registered_psclsid_list);
LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry)
LIST_FOR_EACH_ENTRY(registered_psclsid, &registered_psclsid_list, struct registered_psclsid, entry)
if (IsEqualIID(&registered_psclsid->iid, riid))
{
registered_psclsid->clsid = *rclsid;
LeaveCriticalSection(&apt->cs);
LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK;
}
registered_psclsid = HeapAlloc(GetProcessHeap(), 0, sizeof(struct registered_psclsid));
if (!registered_psclsid)
{
LeaveCriticalSection(&apt->cs);
LeaveCriticalSection(&cs_registered_psclsid_list);
return E_OUTOFMEMORY;
}
registered_psclsid->iid = *riid;
registered_psclsid->clsid = *rclsid;
list_add_head(&apt->psclsids, &registered_psclsid->entry);
list_add_head(&registered_psclsid_list, &registered_psclsid->entry);
LeaveCriticalSection(&apt->cs);
LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK;
}
@ -3803,6 +3823,10 @@ HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID clsidNew)
LONG len = sizeof(szClsidNew);
TRACE("(%s,%p)\n", debugstr_guid(clsidOld), clsidNew);
if (!clsidOld || !clsidNew)
return E_INVALIDARG;
*clsidNew = *clsidOld; /* copy over old value */
res = COM_OpenKeyForCLSID(clsidOld, wszTreatAs, KEY_READ, &hkey);

View file

@ -126,7 +126,6 @@ struct apartment
struct list stubmgrs; /* stub managers for exported objects (CS cs) */
BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */
LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */
struct list psclsids; /* list of registered PS CLSIDs (CS cs) */
struct list loaded_dlls; /* list of dlls loaded by this apartment (CS cs) */
DWORD host_apt_tid; /* thread ID of apartment hosting objects of differing threading model (CS cs) */
HWND host_apt_hwnd; /* handle to apartment window of host apartment (CS cs) */

View file

@ -67,7 +67,7 @@ typedef struct PresentationDataHeader
DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
DVASPECT dvAspect;
DWORD lindex;
DWORD tymed;
DWORD advf;
DWORD unknown7; /* 0 */
DWORD dwObjectExtentX;
DWORD dwObjectExtentY;
@ -145,7 +145,9 @@ struct DataCache
*/
DWORD sinkAspects;
DWORD sinkAdviseFlag;
IAdviseSink* sinkInterface;
IAdviseSink *sinkInterface;
CLSID clsid;
IStorage *presentationStorage;
/* list of cache entries */
@ -214,7 +216,7 @@ const char *debugstr_formatetc(const FORMATETC *formatetc)
*
* Return the size of the bitmap info structure including color table.
*/
int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
{
unsigned int colors, size, masks = 0;
@ -305,10 +307,10 @@ static DataCacheEntry *DataCache_GetEntryForFormatEtc(DataCache *This, const FOR
/* checks that the clipformat and tymed are valid and returns an error if they
* aren't and CACHE_S_NOTSUPPORTED if they are valid, but can't be rendered by
* DataCache_Draw */
static HRESULT check_valid_clipformat_and_tymed(CLIPFORMAT cfFormat, DWORD tymed, BOOL load)
static HRESULT check_valid_clipformat_and_tymed(CLIPFORMAT cfFormat, DWORD tymed)
{
if (!cfFormat || !tymed ||
(cfFormat == CF_METAFILEPICT && (tymed == TYMED_MFPICT || load)) ||
(cfFormat == CF_METAFILEPICT && tymed == TYMED_MFPICT) ||
(cfFormat == CF_BITMAP && tymed == TYMED_GDI) ||
(cfFormat == CF_DIB && tymed == TYMED_HGLOBAL) ||
(cfFormat == CF_ENHMETAFILE && tymed == TYMED_ENHMF))
@ -345,30 +347,38 @@ static BOOL init_cache_entry(DataCacheEntry *entry, const FORMATETC *fmt, DWORD
}
static HRESULT DataCache_CreateEntry(DataCache *This, const FORMATETC *formatetc, DWORD advf,
DataCacheEntry **cache_entry, BOOL load)
BOOL automatic, DataCacheEntry **cache_entry)
{
HRESULT hr;
DWORD id = automatic ? 1 : This->last_cache_id;
DataCacheEntry *entry;
hr = check_valid_clipformat_and_tymed(formatetc->cfFormat, formatetc->tymed, load);
hr = check_valid_clipformat_and_tymed(formatetc->cfFormat, formatetc->tymed);
if (FAILED(hr))
return hr;
if (hr == CACHE_S_FORMATETC_NOTSUPPORTED)
TRACE("creating unsupported format %d\n", formatetc->cfFormat);
*cache_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(**cache_entry));
if (!*cache_entry)
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
if (!entry)
return E_OUTOFMEMORY;
if (!init_cache_entry(*cache_entry, formatetc, advf, This->last_cache_id))
if (!init_cache_entry(entry, formatetc, advf, id))
goto fail;
list_add_tail(&This->cache_list, &(*cache_entry)->entry);
This->last_cache_id++;
if (automatic)
list_add_head(&This->cache_list, &entry->entry);
else
{
list_add_tail(&This->cache_list, &entry->entry);
This->last_cache_id++;
}
if (cache_entry) *cache_entry = entry;
return hr;
fail:
HeapFree(GetProcessHeap(), 0, *cache_entry);
HeapFree(GetProcessHeap(), 0, entry);
return E_OUTOFMEMORY;
}
@ -783,7 +793,7 @@ static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storag
header.unknown3 = 4;
header.dvAspect = cache_entry->fmtetc.dwAspect;
header.lindex = cache_entry->fmtetc.lindex;
header.tymed = cache_entry->stgmedium.tymed;
header.advf = cache_entry->advise_flags;
header.unknown7 = 0;
header.dwObjectExtentX = 0;
header.dwObjectExtentY = 0;
@ -1013,6 +1023,66 @@ static inline void DataCacheEntry_HandsOffStorage(DataCacheEntry *cache_entry)
}
}
static inline DWORD tymed_from_cf( DWORD cf )
{
switch( cf )
{
case CF_BITMAP: return TYMED_GDI;
case CF_METAFILEPICT: return TYMED_MFPICT;
case CF_ENHMETAFILE: return TYMED_ENHMF;
case CF_DIB:
default: return TYMED_HGLOBAL;
}
}
/****************************************************************
* create_automatic_entry
*
* Creates an appropriate cache entry for one of the CLSID_Picture_
* classes. The connection id of the entry is one. Any pre-existing
* automatic entry is re-assigned a new connection id, and moved to
* the end of the list.
*/
static HRESULT create_automatic_entry(DataCache *cache, const CLSID *clsid)
{
static const struct data
{
const CLSID *clsid;
FORMATETC fmt;
} data[] =
{
{ &CLSID_Picture_Dib, { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
{ &CLSID_Picture_Metafile, { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
{ &CLSID_Picture_EnhMetafile, { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
{ NULL }
};
const struct data *ptr = data;
struct list *head;
DataCacheEntry *entry;
if (IsEqualCLSID( &cache->clsid, clsid )) return S_OK;
/* move and reassign any pre-existing automatic entry */
if ((head = list_head( &cache->cache_list )))
{
entry = LIST_ENTRY( head, DataCacheEntry, entry );
if (entry->id == 1)
{
list_remove( &entry->entry );
entry->id = cache->last_cache_id++;
list_add_tail( &cache->cache_list, &entry->entry );
}
}
while (ptr->clsid)
{
if (IsEqualCLSID( clsid, ptr->clsid ))
return DataCache_CreateEntry( cache, &ptr->fmt, 0, TRUE, NULL );
ptr++;
}
return S_OK;
}
/*********************************************************
* Method implementation for the non delegating IUnknown
* part of the DataCache class.
@ -1334,22 +1404,9 @@ static ULONG WINAPI DataCache_IPersistStorage_Release(
static HRESULT WINAPI DataCache_GetClassID(IPersistStorage *iface, CLSID *clsid)
{
DataCache *This = impl_from_IPersistStorage( iface );
HRESULT hr;
STATSTG statstg;
TRACE( "(%p, %p)\n", iface, clsid );
if (This->presentationStorage)
{
hr = IStorage_Stat( This->presentationStorage, &statstg, STATFLAG_NONAME );
if (SUCCEEDED(hr))
{
*clsid = statstg.clsid;
return S_OK;
}
}
*clsid = CLSID_NULL;
TRACE( "(%p, %p) returning %s\n", iface, clsid, debugstr_guid(&This->clsid) );
*clsid = This->clsid;
return S_OK;
}
@ -1386,22 +1443,33 @@ static HRESULT WINAPI DataCache_InitNew(
IStorage* pStg)
{
DataCache *This = impl_from_IPersistStorage(iface);
CLSID clsid;
HRESULT hr;
TRACE("(%p, %p)\n", iface, pStg);
if (This->presentationStorage != NULL)
IStorage_Release(This->presentationStorage);
return CO_E_ALREADYINITIALIZED;
This->presentationStorage = pStg;
IStorage_AddRef(This->presentationStorage);
This->dirty = TRUE;
ReadClassStg( pStg, &clsid );
hr = create_automatic_entry( This, &clsid );
if (FAILED(hr))
{
IStorage_Release( pStg );
This->presentationStorage = NULL;
return hr;
}
This->clsid = clsid;
return S_OK;
}
static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, IStream *stm,
static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD advf, IStream *stm,
enum stream_type type )
{
DataCacheEntry *cache_entry;
@ -1411,7 +1479,7 @@ static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, IStream *
cache_entry = DataCache_GetEntryForFormatEtc( This, fmt );
if (!cache_entry)
hr = DataCache_CreateEntry( This, fmt, 0, &cache_entry, TRUE );
hr = DataCache_CreateEntry( This, fmt, advf, FALSE, &cache_entry );
if (SUCCEEDED( hr ))
{
DataCacheEntry_DiscardData( cache_entry );
@ -1457,9 +1525,9 @@ static HRESULT parse_pres_streams( DataCache *This, IStorage *stg )
fmtetc.ptd = NULL; /* FIXME */
fmtetc.dwAspect = header.dvAspect;
fmtetc.lindex = header.lindex;
fmtetc.tymed = header.tymed;
fmtetc.tymed = tymed_from_cf( clipformat );
add_cache_entry( This, &fmtetc, stm, pres_stream );
add_cache_entry( This, &fmtetc, header.advf, stm, pres_stream );
}
IStream_Release( stm );
}
@ -1490,7 +1558,7 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg, IStream *s
return E_FAIL;
}
return add_cache_entry( This, fmt, stm, contents_stream );
return add_cache_entry( This, fmt, 0, stm, contents_stream );
}
static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
@ -1508,11 +1576,22 @@ static HRESULT WINAPI DataCache_Load( IPersistStorage *iface, IStorage *pStg )
DataCache *This = impl_from_IPersistStorage(iface);
HRESULT hr;
IStream *stm;
CLSID clsid;
DataCacheEntry *entry, *cursor2;
TRACE("(%p, %p)\n", iface, pStg);
IPersistStorage_HandsOffStorage( iface );
LIST_FOR_EACH_ENTRY_SAFE( entry, cursor2, &This->cache_list, DataCacheEntry, entry )
DataCacheEntry_Destroy( This, entry );
ReadClassStg( pStg, &clsid );
hr = create_automatic_entry( This, &clsid );
if (FAILED( hr )) return hr;
This->clsid = clsid;
hr = IStorage_OpenStream( pStg, CONTENTS, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
0, &stm );
if (SUCCEEDED( hr ))
@ -2162,7 +2241,7 @@ static HRESULT WINAPI DataCache_Cache(
return CACHE_S_SAMECACHE;
}
hr = DataCache_CreateEntry(This, &fmt_cpy, advf, &cache_entry, FALSE);
hr = DataCache_CreateEntry(This, &fmt_cpy, advf, FALSE, &cache_entry);
if (SUCCEEDED(hr))
{
@ -2593,12 +2672,16 @@ static DataCache* DataCache_Construct(
newObject->sinkAspects = 0;
newObject->sinkAdviseFlag = 0;
newObject->sinkInterface = 0;
newObject->clsid = CLSID_NULL;
newObject->presentationStorage = NULL;
list_init(&newObject->cache_list);
newObject->last_cache_id = 1;
newObject->last_cache_id = 2;
newObject->dirty = FALSE;
newObject->running_object = NULL;
create_automatic_entry( newObject, clsid );
newObject->clsid = *clsid;
return newObject;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

View file

@ -53,6 +53,15 @@ HGLOBAL WINAPI OleGetIconOfClass(REFCLSID rclsid, LPOLESTR lpszLabel, BOOL fUseT
return NULL;
}
/***********************************************************************
* OleGetIconOfFile [OLE32.@]
*/
HGLOBAL WINAPI OleGetIconOfFile(LPOLESTR path, BOOL use_file_as_label)
{
FIXME("(%s, %d), stub!\n", debugstr_w(path), use_file_as_label);
return NULL;
}
/***********************************************************************
* OleRegEnumFormatEtc [OLE32.@]
*/
@ -74,12 +83,3 @@ HRESULT WINAPI CoGetCallerTID(LPDWORD lpdwTID)
FIXME("stub!\n");
return E_NOTIMPL;
}
/***********************************************************************
* OleGetIconOfFile [OLE32.@]
*/
HGLOBAL WINAPI OleGetIconOfFile(LPOLESTR path, BOOL use_file_as_label)
{
FIXME("(%p, %d), stub!\n", path, use_file_as_label);
return NULL;
}

View file

@ -236,7 +236,7 @@
@ stdcall OleGetAutoConvert(ptr ptr)
@ stdcall OleGetClipboard(ptr)
@ stdcall OleGetIconOfClass(ptr ptr long)
@ stdcall OleGetIconOfFile(ptr long)
@ stdcall OleGetIconOfFile(wstr long)
@ stdcall OleInitialize(ptr)
@ stdcall OleInitializeWOW(long long)
@ stdcall OleIsCurrentClipboard(ptr)

View file

@ -139,7 +139,7 @@ reactos/dll/win32/ntdsapi # Synced to WineStaging-2.9
reactos/dll/win32/objsel # Synced to WineStaging-2.9
reactos/dll/win32/odbc32 # Synced to WineStaging-2.9. Depends on port of Linux ODBC.
reactos/dll/win32/odbccp32 # Synced to WineStaging-2.9
reactos/dll/win32/ole32 # Synced to WineStaging-2.9
reactos/dll/win32/ole32 # Synced to WineStaging-2.16
reactos/dll/win32/oleacc # Synced to WineStaging-2.9
reactos/dll/win32/oleaut32 # Synced to WineStaging-2.9
reactos/dll/win32/olecli32 # Synced to WineStaging-2.9