[OLE32] Sync with Wine Staging 3.9. CORE-14656

This commit is contained in:
Amine Khaldi 2018-06-04 03:45:35 +01:00
parent 9ce306e4cc
commit 85037eb745
8 changed files with 327 additions and 196 deletions

View file

@ -723,6 +723,36 @@ static inline BOOL apartment_is_model(const APARTMENT *apt, DWORD model)
return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED));
}
/* gets the multi-threaded apartment if it exists. The caller must
* release the reference from the apartment as soon as the apartment pointer
* is no longer required. */
static APARTMENT *apartment_find_mta(void)
{
APARTMENT *apt;
EnterCriticalSection(&csApartment);
if ((apt = MTA))
apartment_addref(apt);
LeaveCriticalSection(&csApartment);
return apt;
}
/* Return the current apartment if it exists, or, failing that, the MTA. Caller
* must free the returned apartment in either case. */
APARTMENT *apartment_get_current_or_mta(void)
{
APARTMENT *apt = COM_CurrentApt();
if (apt)
{
apartment_addref(apt);
return apt;
}
return apartment_find_mta();
}
static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass)
{
list_remove(&curClass->entry);
@ -1065,8 +1095,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(
TRACE("(%08x)\n",dwRegister);
apt = COM_CurrentApt();
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("COM was not initialized\n");
return CO_E_NOTINITIALIZED;
@ -1097,7 +1126,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(
}
LeaveCriticalSection( &csRegisteredClassList );
apartment_release(apt);
return hr;
}
@ -1151,9 +1180,17 @@ DWORD apartment_release(struct apartment *apt)
ret = InterlockedDecrement(&apt->refs);
TRACE("%s: after = %d\n", wine_dbgstr_longlong(apt->oxid), ret);
if (apt->being_destroyed)
{
LeaveCriticalSection(&csApartment);
return ret;
}
/* destruction stuff that needs to happen under csApartment CS */
if (ret == 0)
{
apt->being_destroyed = TRUE;
if (apt == MTA) MTA = NULL;
else if (apt == MainApartment) MainApartment = NULL;
list_remove(&apt->entry);
@ -1301,31 +1338,6 @@ static APARTMENT *apartment_findmain(void)
return result;
}
/* gets the multi-threaded apartment if it exists. The caller must
* release the reference from the apartment as soon as the apartment pointer
* is no longer required. */
static APARTMENT *apartment_find_multi_threaded(void)
{
APARTMENT *result = NULL;
struct list *cursor;
EnterCriticalSection(&csApartment);
LIST_FOR_EACH( cursor, &apts )
{
struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
if (apt->multi_threaded)
{
result = apt;
apartment_addref(result);
break;
}
}
LeaveCriticalSection(&csApartment);
return result;
}
/* gets the specified class object by loading the appropriate DLL, if
* necessary and calls the DllGetClassObject function for the DLL */
static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
@ -1345,7 +1357,7 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
hr = DllGetClassObject(rclsid, riid, ppv);
if (hr != S_OK)
ERR("DllGetClassObject returned error 0x%08x\n", hr);
ERR("DllGetClassObject returned error 0x%08x for dll %s\n", hr, debugstr_w(dllpath));
return hr;
}
@ -1394,7 +1406,7 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
hr = apartment_loaded_dll->dll->DllGetClassObject(rclsid, riid, ppv);
if (hr != S_OK)
ERR("DllGetClassObject returned error 0x%08x\n", hr);
ERR("DllGetClassObject returned error 0x%08x for dll %s\n", hr, debugstr_w(dllpath));
}
return hr;
@ -2065,9 +2077,11 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
return hr;
}
apt = COM_CurrentApt();
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
manager = get_stub_manager_from_object(apt, lpUnk, FALSE);
if (manager) {
@ -2082,6 +2096,7 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
* not found, making apps think that the object was disconnected, when
* it actually wasn't */
apartment_release(apt);
return S_OK;
}
@ -2589,7 +2604,7 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
static const WCHAR wszInterface[] = {'I','n','t','e','r','f','a','c','e','\\',0};
static const WCHAR wszPSC[] = {'\\','P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
WCHAR path[ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1 + ARRAYSIZE(wszPSC)];
APARTMENT *apt = COM_CurrentApt();
APARTMENT *apt;
struct registered_psclsid *registered_psclsid;
ACTCTX_SECTION_KEYED_DATA data;
HRESULT hr;
@ -2598,11 +2613,12 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
if (!pclsid)
return E_INVALIDARG;
@ -2673,16 +2689,17 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
*/
HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
{
APARTMENT *apt = COM_CurrentApt();
APARTMENT *apt;
struct registered_psclsid *registered_psclsid;
TRACE("(%s, %s)\n", debugstr_guid(riid), debugstr_guid(rclsid));
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
EnterCriticalSection(&cs_registered_psclsid_list);
@ -2808,8 +2825,7 @@ HRESULT WINAPI CoRegisterClassObject(
if ( (lpdwRegister==0) || (pUnk==0) )
return E_INVALIDARG;
apt = COM_CurrentApt();
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("COM was not initialized\n");
return CO_E_NOTINITIALIZED;
@ -2832,16 +2848,21 @@ HRESULT WINAPI CoRegisterClassObject(
if (dwClsContext & CLSCTX_LOCAL_SERVER)
hr = CoLockObjectExternal(foundObject, TRUE, FALSE);
IUnknown_Release(foundObject);
apartment_release(apt);
return hr;
}
IUnknown_Release(foundObject);
ERR("object already registered for class %s\n", debugstr_guid(rclsid));
apartment_release(apt);
return CO_E_OBJISREG;
}
newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
if ( newClass == NULL )
{
apartment_release(apt);
return E_OUTOFMEMORY;
}
newClass->classIdentifier = *rclsid;
newClass->apartment_id = apt->oxid;
@ -2870,7 +2891,10 @@ HRESULT WINAPI CoRegisterClassObject(
hr = get_local_server_stream(apt, &marshal_stream);
if(FAILED(hr))
{
apartment_release(apt);
return hr;
}
hr = RPC_StartLocalServer(&newClass->classIdentifier,
marshal_stream,
@ -2878,6 +2902,7 @@ HRESULT WINAPI CoRegisterClassObject(
&newClass->RpcRegistration);
IStream_Release(marshal_stream);
}
apartment_release(apt);
return S_OK;
}
@ -2995,7 +3020,6 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
IUnknown *regClassObject;
HRESULT hres = E_UNEXPECTED;
APARTMENT *apt;
BOOL release_apt = FALSE;
TRACE("CLSID: %s,IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid));
@ -3004,14 +3028,10 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
*ppv = NULL;
if (!(apt = COM_CurrentApt()))
if (!(apt = apartment_get_current_or_mta()))
{
if (!(apt = apartment_find_multi_threaded()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
release_apt = TRUE;
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
if (pServerInfo) {
@ -3023,7 +3043,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
{
if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler))
{
if (release_apt) apartment_release(apt);
apartment_release(apt);
return FTMarshalCF_Create(iid, ppv);
}
if (IsEqualCLSID(rclsid, &CLSID_GlobalOptions))
@ -3049,7 +3069,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
hres = get_inproc_class_object(apt, &clsreg, &comclass->clsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv);
ReleaseActCtx(data.hActCtx);
if (release_apt) apartment_release(apt);
apartment_release(apt);
return hres;
}
}
@ -3070,7 +3090,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
* is good since we are not returning it in the "out" parameter.
*/
IUnknown_Release(regClassObject);
if (release_apt) apartment_release(apt);
apartment_release(apt);
return hres;
}
@ -3105,7 +3125,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
* other types */
if (SUCCEEDED(hres))
{
if (release_apt) apartment_release(apt);
apartment_release(apt);
return hres;
}
}
@ -3141,11 +3161,11 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(
* other types */
if (SUCCEEDED(hres))
{
if (release_apt) apartment_release(apt);
apartment_release(apt);
return hres;
}
}
if (release_apt) apartment_release(apt);
apartment_release(apt);
/* Next try out of process */
if (CLSCTX_LOCAL_SERVER & dwClsContext)
@ -3304,15 +3324,12 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx(
if(FAILED(hres))
clsid = *rclsid;
if (!(apt = COM_CurrentApt()))
if (!(apt = apartment_get_current_or_mta()))
{
if (!(apt = apartment_find_multi_threaded()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
/*
* The Standard Global Interface Table (GIT) object is a process-wide singleton.
@ -3646,8 +3663,11 @@ HRESULT WINAPI CoLockObjectExternal(
TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n",
pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE");
apt = COM_CurrentApt();
if (!apt) return CO_E_NOTINITIALIZED;
if (!(apt = apartment_get_current_or_mta()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
stubmgr = get_stub_manager_from_object(apt, pUnk, fLock);
if (!stubmgr)
@ -3656,6 +3676,7 @@ HRESULT WINAPI CoLockObjectExternal(
/* Note: native is pretty broken here because it just silently
* fails, without returning an appropriate error code, making apps
* think that the object was disconnected, when it actually wasn't */
apartment_release(apt);
return S_OK;
}
@ -3665,6 +3686,7 @@ HRESULT WINAPI CoLockObjectExternal(
stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases);
stub_manager_int_release(stubmgr);
apartment_release(apt);
return S_OK;
}
@ -5004,22 +5026,19 @@ HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv)
HRESULT WINAPI CoGetContextToken( ULONG_PTR *token )
{
struct oletls *info = COM_CurrentInfo();
APARTMENT *apt;
TRACE("(%p)\n", token);
if (!info)
return E_OUTOFMEMORY;
if (!info->apt)
if (!(apt = apartment_get_current_or_mta()))
{
APARTMENT *apt;
if (!(apt = apartment_find_multi_threaded()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
if (!token)
return E_POINTER;
@ -5095,8 +5114,9 @@ HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
{
struct oletls *info = COM_CurrentInfo();
APARTMENT *apt;
FIXME("(%p, %p): semi-stub\n", type, qualifier);
TRACE("(%p, %p)\n", type, qualifier);
if (!type || !qualifier)
return E_INVALIDARG;
@ -5115,6 +5135,13 @@ HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
*qualifier = APTTYPEQUALIFIER_NONE;
if (!info->apt && (apt = apartment_find_mta()))
{
apartment_release(apt);
*type = APTTYPE_MTA;
*qualifier = APTTYPEQUALIFIER_IMPLICIT_MTA;
}
return info->apt ? S_OK : CO_E_NOTINITIALIZED;
}

View file

@ -142,6 +142,7 @@ struct apartment
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) */
LocalServer *local_server; /* A marshallable object exposing local servers (CS cs) */
BOOL being_destroyed; /* is currently being destroyed */
/* FIXME: OIDs should be given out by RPCSS */
OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */
@ -199,7 +200,7 @@ void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const
void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN;
HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub,
IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) DECLSPEC_HIDDEN;
HRESULT start_apartment_remote_unknown(void) DECLSPEC_HIDDEN;
HRESULT start_apartment_remote_unknown(APARTMENT *apt) DECLSPEC_HIDDEN;
HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags) DECLSPEC_HIDDEN;
@ -211,7 +212,7 @@ void RPC_StartRemoting(struct apartment *apt) DECLSPEC_HIDDEN;
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid,
const OXID_INFO *oxid_info,
DWORD dest_context, void *dest_context_data,
IRpcChannelBuffer **chan) DECLSPEC_HIDDEN;
IRpcChannelBuffer **chan, APARTMENT *apt) DECLSPEC_HIDDEN;
HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN;
void RPC_ExecuteCall(struct dispatch_params *params) DECLSPEC_HIDDEN;
HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN;
@ -247,6 +248,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt) DECLSPEC_HIDDEN;
HWND apartment_getwindow(const struct apartment *apt) DECLSPEC_HIDDEN;
HRESULT enter_apartment(struct oletls *info, DWORD model) DECLSPEC_HIDDEN;
void leave_apartment(struct oletls *info) DECLSPEC_HIDDEN;
APARTMENT *apartment_get_current_or_mta(void) DECLSPEC_HIDDEN;
/* DCOM messages used by the apartment window (not compatible with native) */
#define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */

View file

@ -547,6 +547,41 @@ static HRESULT open_pres_stream( IStorage *stg, int stream_number, IStream **stm
return IStorage_OpenStream( stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
}
static HRESULT synthesize_emf( HMETAFILEPICT data, STGMEDIUM *med )
{
METAFILEPICT *pict;
HRESULT hr = E_FAIL;
UINT size;
void *bits;
if (!(pict = GlobalLock( data ))) return hr;
size = GetMetaFileBitsEx( pict->hMF, 0, NULL );
if ((bits = HeapAlloc( GetProcessHeap(), 0, size )))
{
GetMetaFileBitsEx( pict->hMF, size, bits );
med->u.hEnhMetaFile = SetWinMetaFileBits( size, bits, NULL, pict );
HeapFree( GetProcessHeap(), 0, bits );
med->tymed = TYMED_ENHMF;
med->pUnkForRelease = NULL;
hr = S_OK;
}
GlobalUnlock( data );
return hr;
}
#include <pshpack2.h>
struct meta_placeable
{
DWORD key;
WORD hwmf;
WORD bounding_box[4];
WORD inch;
DWORD reserved;
WORD checksum;
};
#include <poppack.h>
static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm )
{
HRESULT hr;
@ -559,25 +594,26 @@ static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm )
CLIPFORMAT clipformat;
static const LARGE_INTEGER offset_zero;
ULONG read;
if (cache_entry->load_stream_num == STREAM_NUMBER_CONTENTS)
{
FIXME( "Unimplemented for CONTENTS stream\n" );
return E_FAIL;
}
struct meta_placeable mf_place;
hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
if (FAILED( hr )) return hr;
hr = read_clipformat( stm, &clipformat );
if (FAILED( hr )) return hr;
hr = IStream_Read( stm, &header, sizeof(header), &read );
if (hr != S_OK || read != sizeof(header)) return E_FAIL;
if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
{
hr = read_clipformat( stm, &clipformat );
if (hr != S_OK) return hr;
hr = IStream_Read( stm, &header, sizeof(header), &read );
if (hr != S_OK) return hr;
}
else
{
hr = IStream_Read( stm, &mf_place, sizeof(mf_place), &read );
if (hr != S_OK) return hr;
}
hr = IStream_Seek( stm, offset_zero, STREAM_SEEK_CUR, &current_pos );
if (FAILED( hr )) return hr;
stat.cbSize.QuadPart -= current_pos.QuadPart;
hmfpict = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
@ -592,14 +628,23 @@ static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm )
}
hr = IStream_Read( stm, bits, stat.cbSize.u.LowPart, &read );
if (hr != S_OK || read != stat.cbSize.u.LowPart) hr = E_FAIL;
if (SUCCEEDED( hr ))
{
/* FIXME: get this from the stream */
mfpict->mm = MM_ANISOTROPIC;
mfpict->xExt = header.dwObjectExtentX;
mfpict->yExt = header.dwObjectExtentY;
/* FIXME: get this from the stream */
if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
{
mfpict->xExt = header.dwObjectExtentX;
mfpict->yExt = header.dwObjectExtentY;
}
else
{
mfpict->xExt = ((mf_place.bounding_box[2] - mf_place.bounding_box[0])
* 2540) / mf_place.inch;
mfpict->yExt = ((mf_place.bounding_box[3] - mf_place.bounding_box[1])
* 2540) / mf_place.inch;
}
mfpict->hMF = SetMetaFileBitsEx( stat.cbSize.u.LowPart, bits );
if (!mfpict->hMF)
hr = E_FAIL;
@ -623,48 +668,61 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
{
HRESULT hr;
STATSTG stat;
void *dib;
BYTE *dib;
HGLOBAL hglobal;
ULONG read, info_size, bi_size;
BITMAPFILEHEADER file;
BITMAPINFOHEADER *info;
if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
{
FIXME( "Unimplemented for presentation stream\n" );
return E_FAIL;
}
CLIPFORMAT cf;
PresentationDataHeader pres;
ULARGE_INTEGER current_pos;
static const LARGE_INTEGER offset_zero;
hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
if (FAILED( hr )) return hr;
if (stat.cbSize.QuadPart < sizeof(file) + sizeof(DWORD)) return E_FAIL;
hr = IStream_Read( stm, &file, sizeof(file), &read );
if (hr != S_OK || read != sizeof(file)) return E_FAIL;
stat.cbSize.QuadPart -= sizeof(file);
if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
{
hr = read_clipformat( stm, &cf );
if (hr != S_OK) return hr;
hr = IStream_Read( stm, &pres, sizeof(pres), &read );
if (hr != S_OK) return hr;
}
else
{
hr = IStream_Read( stm, &file, sizeof(BITMAPFILEHEADER), &read );
if (hr != S_OK) return hr;
}
hr = IStream_Seek( stm, offset_zero, STREAM_SEEK_CUR, &current_pos );
if (FAILED( hr )) return hr;
stat.cbSize.QuadPart -= current_pos.QuadPart;
hglobal = GlobalAlloc( GMEM_MOVEABLE, stat.cbSize.u.LowPart );
if (!hglobal) return E_OUTOFMEMORY;
dib = GlobalLock( hglobal );
/* read first DWORD of BITMAPINFOHEADER */
hr = IStream_Read( stm, dib, sizeof(DWORD), &read );
if (hr != S_OK || read != sizeof(DWORD)) goto fail;
if (hr != S_OK) goto fail;
bi_size = *(DWORD *)dib;
if (stat.cbSize.QuadPart < bi_size) goto fail;
hr = IStream_Read( stm, (char *)dib + sizeof(DWORD), bi_size - sizeof(DWORD), &read );
if (hr != S_OK || read != bi_size - sizeof(DWORD)) goto fail;
/* read rest of BITMAPINFOHEADER */
hr = IStream_Read( stm, dib + sizeof(DWORD), bi_size - sizeof(DWORD), &read );
if (hr != S_OK) goto fail;
info_size = bitmap_info_size( dib, DIB_RGB_COLORS );
info_size = bitmap_info_size( (BITMAPINFO *)dib, DIB_RGB_COLORS );
if (stat.cbSize.QuadPart < info_size) goto fail;
if (info_size > bi_size)
{
hr = IStream_Read( stm, (char *)dib + bi_size, info_size - bi_size, &read );
if (hr != S_OK || read != info_size - bi_size) goto fail;
hr = IStream_Read( stm, dib + bi_size, info_size - bi_size, &read );
if (hr != S_OK) goto fail;
}
stat.cbSize.QuadPart -= info_size;
if (file.bfOffBits)
/* set Stream pointer to beginning of bitmap bits */
if (cache_entry->load_stream_num == STREAM_NUMBER_CONTENTS && file.bfOffBits)
{
LARGE_INTEGER skip;
@ -675,8 +733,8 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
stat.cbSize.QuadPart -= skip.QuadPart;
}
hr = IStream_Read( stm, (char *)dib + info_size, stat.cbSize.u.LowPart, &read );
if (hr != S_OK || read != stat.cbSize.QuadPart) goto fail;
hr = IStream_Read( stm, dib + info_size, stat.cbSize.u.LowPart, &read );
if (hr != S_OK) goto fail;
if (bi_size >= sizeof(*info))
{
@ -695,15 +753,69 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
cache_entry->stgmedium.tymed = TYMED_HGLOBAL;
cache_entry->stgmedium.u.hGlobal = hglobal;
return S_OK;
return hr;
fail:
GlobalUnlock( hglobal );
GlobalFree( hglobal );
return E_FAIL;
return hr;
}
static HRESULT load_emf( DataCacheEntry *cache_entry, IStream *stm )
{
HRESULT hr;
if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
{
STGMEDIUM stgmed;
hr = load_mf_pict( cache_entry, stm );
if (SUCCEEDED( hr ))
{
hr = synthesize_emf( cache_entry->stgmedium.u.hMetaFilePict, &stgmed );
ReleaseStgMedium( &cache_entry->stgmedium );
}
if (SUCCEEDED( hr ))
cache_entry->stgmedium = stgmed;
}
else
{
STATSTG stat;
BYTE *data;
ULONG read, size_bits;
hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
if (SUCCEEDED( hr ))
{
data = HeapAlloc( GetProcessHeap(), 0, stat.cbSize.u.LowPart );
if (!data) return E_OUTOFMEMORY;
hr = IStream_Read( stm, data, stat.cbSize.u.LowPart, &read );
if (hr != S_OK)
{
HeapFree( GetProcessHeap(), 0, data );
return hr;
}
if (read <= sizeof(DWORD) + sizeof(ENHMETAHEADER))
{
HeapFree( GetProcessHeap(), 0, data );
return E_FAIL;
}
size_bits = read - sizeof(DWORD) - sizeof(ENHMETAHEADER);
cache_entry->stgmedium.u.hEnhMetaFile = SetEnhMetaFileBits( size_bits, data + (read - size_bits) );
cache_entry->stgmedium.tymed = TYMED_ENHMF;
cache_entry->stgmedium.pUnkForRelease = NULL;
HeapFree( GetProcessHeap(), 0, data );
}
}
return hr;
}
/************************************************************************
* DataCacheEntry_LoadData
*
@ -736,6 +848,10 @@ static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry, IStorage *st
hr = load_dib( cache_entry, stm );
break;
case CF_ENHMETAFILE:
hr = load_emf( cache_entry, stm );
break;
default:
FIXME( "Unimplemented clip format %x\n", cache_entry->fmtetc.cfFormat );
hr = E_NOTIMPL;
@ -817,18 +933,6 @@ end:
return hr;
}
#include <pshpack2.h>
struct meta_placeable
{
DWORD key;
WORD hwmf;
WORD bounding_box[4];
WORD inch;
DWORD reserved;
WORD checksum;
};
#include <poppack.h>
static HRESULT save_mfpict(DataCacheEntry *entry, BOOL contents, IStream *stream)
{
HRESULT hr = S_OK;
@ -1118,30 +1222,6 @@ static HRESULT synthesize_bitmap( HGLOBAL dib, STGMEDIUM *med )
return hr;
}
static HRESULT synthesize_emf( HMETAFILEPICT data, STGMEDIUM *med )
{
METAFILEPICT *pict;
HRESULT hr = E_FAIL;
UINT size;
void *bits;
if (!(pict = GlobalLock( data ))) return hr;
size = GetMetaFileBitsEx( pict->hMF, 0, NULL );
if ((bits = HeapAlloc( GetProcessHeap(), 0, size )))
{
GetMetaFileBitsEx( pict->hMF, size, bits );
med->u.hEnhMetaFile = SetWinMetaFileBits( size, bits, NULL, pict );
HeapFree( GetProcessHeap(), 0, bits );
med->tymed = TYMED_ENHMF;
med->pUnkForRelease = NULL;
hr = S_OK;
}
GlobalUnlock( data );
return hr;
}
static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
const FORMATETC *formatetc,
STGMEDIUM *stgmedium,
@ -1763,6 +1843,7 @@ static HRESULT WINAPI DataCache_Load( IPersistStorage *iface, IStorage *stg )
LIST_FOR_EACH_ENTRY_SAFE( entry, cursor2, &This->cache_list, DataCacheEntry, entry )
DataCacheEntry_Destroy( This, entry );
This->clsid = CLSID_NULL;
ReadClassStg( stg, &clsid );
hr = create_automatic_entry( This, &clsid );

View file

@ -313,13 +313,15 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL
* the interfaces were returned */
if (SUCCEEDED(hr))
{
APARTMENT *apt = apartment_get_current_or_mta();
/* try to unmarshal each object returned to us */
for (i = 0; i < nonlocal_mqis; i++)
{
ULONG index = mapping[i];
HRESULT hrobj = qiresults[i].hResult;
if (hrobj == S_OK)
hrobj = unmarshal_object(&qiresults[i].std, COM_CurrentApt(),
hrobj = unmarshal_object(&qiresults[i].std, apt,
This->dest_context,
This->dest_context_data,
pMQIs[index].pIID, &This->oxid_info,
@ -331,6 +333,8 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL
ERR("Failed to get pointer to interface %s\n", debugstr_guid(pMQIs[index].pIID));
pMQIs[index].hr = hrobj;
}
apartment_release(apt);
}
/* free the memory allocated by the proxy */
@ -1010,8 +1014,7 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk
if (This->sorflags & SORFP_NOLIFETIMEMGMT)
return S_FALSE;
apt = COM_CurrentApt();
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
return CO_E_NOTINITIALIZED;
called_in_original_apt = This->parent && (This->parent->oxid == apt->oxid);
@ -1046,7 +1049,7 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk
stdobjref.ipid = This->oxid_info.ipidRemUnknown;
/* do the unmarshal */
hr = unmarshal_object(&stdobjref, COM_CurrentApt(), This->dest_context,
hr = unmarshal_object(&stdobjref, apt, This->dest_context,
This->dest_context_data, &IID_IRemUnknown,
&This->oxid_info, (void**)remunk);
if (hr == S_OK && called_in_original_apt)
@ -1056,6 +1059,7 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk
}
}
LeaveCriticalSection(&This->cs);
apartment_release(apt);
TRACE("got IRemUnknown* pointer %p, hr = 0x%08x\n", *remunk, hr);
@ -1221,11 +1225,11 @@ StdMarshalImpl_MarshalInterface(
STDOBJREF stdobjref;
ULONG res;
HRESULT hres;
APARTMENT *apt = COM_CurrentApt();
APARTMENT *apt;
TRACE("(...,%s,...)\n", debugstr_guid(riid));
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("Apartment not initialized\n");
return CO_E_NOTINITIALIZED;
@ -1235,6 +1239,7 @@ StdMarshalImpl_MarshalInterface(
RPC_StartRemoting(apt);
hres = marshal_object(apt, &stdobjref, riid, pv, dest_context, dest_context_data, mshlflags);
apartment_release(apt);
if (hres != S_OK)
{
ERR("Failed to create ifstub, hres=0x%x\n", hres);
@ -1288,7 +1293,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
&proxy_manager->oxid_info,
proxy_manager->dest_context,
proxy_manager->dest_context_data,
&chanbuf);
&chanbuf, apt);
if (hr == S_OK)
hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref,
riid, chanbuf, &ifproxy);
@ -1324,14 +1329,14 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
STDOBJREF stdobjref;
ULONG res;
HRESULT hres;
APARTMENT *apt = COM_CurrentApt();
APARTMENT *apt;
APARTMENT *stub_apt;
OXID oxid;
TRACE("(...,%s,....)\n", debugstr_guid(riid));
/* we need an apartment to unmarshal into */
if (!apt)
if (!(apt = apartment_get_current_or_mta()))
{
ERR("Apartment not initialized\n");
return CO_E_NOTINITIALIZED;
@ -1339,10 +1344,18 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
/* read STDOBJREF from wire */
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);
if (hres != S_OK) return STG_E_READFAULT;
if (hres != S_OK)
{
apartment_release(apt);
return STG_E_READFAULT;
}
hres = apartment_getoxid(apt, &oxid);
if (hres != S_OK) return hres;
if (hres != S_OK)
{
apartment_release(apt);
return hres;
}
/* check if we're marshalling back to ourselves */
if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))
@ -1357,6 +1370,7 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
stub_manager_ext_release(stubmgr, stdobjref.cPublicRefs, stdobjref.flags & SORFP_TABLEWEAK, FALSE);
stub_manager_int_release(stubmgr);
apartment_release(apt);
return hres;
}
@ -1395,6 +1409,7 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
if (hres != S_OK) WARN("Failed with error 0x%08x\n", hres);
else TRACE("Successfully created proxy %p\n", *ppv);
apartment_release(apt);
return hres;
}

View file

@ -830,14 +830,16 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
ORPC_EXTENT_ARRAY orpc_ext_array;
WIRE_ORPC_EXTENT *first_wire_orpc_extent = NULL;
HRESULT hrFault = S_OK;
APARTMENT *apt = apartment_get_current_or_mta();
TRACE("(%p) iMethod=%d\n", olemsg, olemsg->iMethod);
hr = ClientRpcChannelBuffer_IsCorrectApartment(This, COM_CurrentApt());
hr = ClientRpcChannelBuffer_IsCorrectApartment(This, apt);
if (hr != S_OK)
{
ERR("called from wrong apartment, should have been 0x%s\n",
wine_dbgstr_longlong(This->oxid));
if (apt) apartment_release(apt);
return RPC_E_WRONG_THREAD;
}
/* This situation should be impossible in multi-threaded apartments,
@ -845,11 +847,12 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
* Note: doing a COM call during the processing of a sent message is
* only disallowed if a client call is already being waited for
* completion */
if (!COM_CurrentApt()->multi_threaded &&
if (!apt->multi_threaded &&
COM_CurrentInfo()->pending_call_count_client &&
InSendMessage())
{
ERR("can't make an outgoing COM call in response to a sent message\n");
apartment_release(apt);
return RPC_E_CANTCALLOUT_ININPUTSYNCCALL;
}
@ -967,6 +970,7 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
TRACE("-- 0x%08x\n", hr);
apartment_release(apt);
return hr;
}
@ -1094,7 +1098,7 @@ static const IRpcChannelBufferVtbl ServerRpcChannelBufferVtbl =
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid,
const OXID_INFO *oxid_info,
DWORD dest_context, void *dest_context_data,
IRpcChannelBuffer **chan)
IRpcChannelBuffer **chan, APARTMENT *apt)
{
ClientRpcChannelBuffer *This;
WCHAR endpoint[200];
@ -1148,7 +1152,7 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid,
This->super.dest_context = dest_context;
This->super.dest_context_data = dest_context_data;
This->bind = bind;
apartment_getoxid(COM_CurrentApt(), &This->oxid);
apartment_getoxid(apt, &This->oxid);
This->server_pid = oxid_info->dwPid;
This->event = NULL;
@ -1644,7 +1648,7 @@ void RPC_StartRemoting(struct apartment *apt)
/* FIXME: move remote unknown exporting into this function */
}
start_apartment_remote_unknown();
start_apartment_remote_unknown(apt);
}

View file

@ -73,7 +73,8 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
struct ifstub *stub;
HRESULT hr;
TRACE("oid=%s, stubbuffer=%p, iid=%s\n", wine_dbgstr_longlong(m->oid), sb, debugstr_guid(iid));
TRACE("oid=%s, stubbuffer=%p, iid=%s, dest_context=%x\n", wine_dbgstr_longlong(m->oid), sb,
debugstr_guid(iid), dest_context);
stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
if (!stub) return NULL;
@ -470,7 +471,7 @@ ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tablewea
/* 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 */
static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid)
static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid, struct ifstub **ifstub)
{
struct stub_manager *result = NULL;
struct list *cursor;
@ -480,7 +481,7 @@ static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPI
{
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
if (stub_manager_ipid_to_ifstub(m, ipid))
if ((*ifstub = stub_manager_ipid_to_ifstub(m, ipid)))
{
result = m;
stub_manager_int_addref(result);
@ -497,7 +498,8 @@ static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPI
return result;
}
static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret)
static HRESULT ipid_to_ifstub(const IPID *ipid, APARTMENT **stub_apt,
struct stub_manager **stubmgr_ret, struct ifstub **ifstub)
{
/* FIXME: hack for IRemUnknown */
if (ipid->Data2 == 0xffff)
@ -509,7 +511,7 @@ static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, stru
TRACE("Couldn't find apartment corresponding to TID 0x%04x\n", ipid->Data2);
return RPC_E_INVALID_OBJECT;
}
*stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid);
*stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid, ifstub);
if (!*stubmgr_ret)
{
apartment_release(*stub_apt);
@ -519,6 +521,12 @@ static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, stru
return S_OK;
}
static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stub)
{
struct ifstub *ifstub;
return ipid_to_ifstub(ipid, stub_apt, stub, &ifstub);
}
/* gets the apartment, stub and channel of an object. the caller must
* release the references to all objects (except iface) if the function
* returned success, otherwise no references are returned. */
@ -532,32 +540,22 @@ HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt,
APARTMENT *apt;
HRESULT hr;
hr = ipid_to_stub_manager(ipid, &apt, &stubmgr);
hr = ipid_to_ifstub(ipid, &apt, &stubmgr, &ifstub);
if (hr != S_OK) return RPC_E_DISCONNECTED;
ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid);
if (ifstub)
{
*stub = ifstub->stubbuffer;
IRpcStubBuffer_AddRef(*stub);
*chan = ifstub->chan;
IRpcChannelBuffer_AddRef(*chan);
*stub_apt = apt;
*iid = ifstub->iid;
*iface = ifstub->iface;
*stub = ifstub->stubbuffer;
IRpcStubBuffer_AddRef(*stub);
*chan = ifstub->chan;
IRpcChannelBuffer_AddRef(*chan);
*stub_apt = apt;
*iid = ifstub->iid;
*iface = ifstub->iface;
if (manager)
*manager = stubmgr;
else
stub_manager_int_release(stubmgr);
return S_OK;
}
if (manager)
*manager = stubmgr;
else
{
stub_manager_int_release(stubmgr);
apartment_release(apt);
return RPC_E_DISCONNECTED;
}
return S_OK;
}
/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */
@ -707,18 +705,23 @@ static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface,
USHORT successful_qis = 0;
APARTMENT *apt;
struct stub_manager *stubmgr;
struct ifstub *ifstub;
DWORD dest_context;
void *dest_context_data;
TRACE("(%p)->(%s, %d, %d, %p, %p)\n", iface, debugstr_guid(ripid), cRefs, cIids, iids, ppQIResults);
hr = ipid_to_stub_manager(ripid, &apt, &stubmgr);
hr = ipid_to_ifstub(ripid, &apt, &stubmgr, &ifstub);
if (hr != S_OK) return hr;
IRpcChannelBuffer_GetDestCtx(ifstub->chan, &dest_context, &dest_context_data);
*ppQIResults = CoTaskMemAlloc(sizeof(REMQIRESULT) * cIids);
for (i = 0; i < cIids; i++)
{
HRESULT hrobj = marshal_object(apt, &(*ppQIResults)[i].std, &iids[i],
stubmgr->object, MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
stubmgr->object, dest_context, dest_context_data, MSHLFLAGS_NORMAL);
if (hrobj == S_OK)
successful_qis++;
(*ppQIResults)[i].hResult = hrobj;
@ -812,11 +815,10 @@ static const IRemUnknownVtbl RemUnknown_Vtbl =
};
/* starts the IRemUnknown listener for the current apartment */
HRESULT start_apartment_remote_unknown(void)
HRESULT start_apartment_remote_unknown(APARTMENT *apt)
{
IRemUnknown *pRemUnknown;
HRESULT hr = S_OK;
APARTMENT *apt = COM_CurrentApt();
EnterCriticalSection(&apt->cs);
if (!apt->remunk_exported)

View file

@ -387,7 +387,7 @@ ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *ph
size += sizeof(ULONG);
if (LOWORD(*pFlags == MSHCTX_INPROC))
if (LOWORD(*pFlags) == MSHCTX_INPROC)
size += sizeof(HGLOBAL);
else
{
@ -429,7 +429,7 @@ unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBu
ALIGN_POINTER(pBuffer, 3);
if (LOWORD(*pFlags == MSHCTX_INPROC))
if (LOWORD(*pFlags) == MSHCTX_INPROC)
{
if (sizeof(*phGlobal) == 8)
*(ULONG *)pBuffer = WDT_INPROC64_CALL;
@ -572,7 +572,7 @@ void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
{
TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phGlobal);
if (LOWORD(*pFlags != MSHCTX_INPROC) && *phGlobal)
if (LOWORD(*pFlags) != MSHCTX_INPROC && *phGlobal)
GlobalFree(*phGlobal);
}

View file

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