https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2178977b544fe2737850b…
commit 2178977b544fe2737850b3590174ea1942865ecb
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sat Jan 20 12:57:25 2018 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Sat Jan 20 12:57:25 2018 +0100
[OLE32] Sync with Wine 3.0. CORE-14225
---
dll/win32/ole32/compobj.c | 70 +++--
dll/win32/ole32/compobj_private.h | 4 +-
dll/win32/ole32/datacache.c | 627 +++++++++++++++++++++++++++-----------
dll/win32/ole32/enumx.c | 16 +-
dll/win32/ole32/enumx.h | 5 +-
dll/win32/ole32/hglobalstream.c | 372 ++++++++++------------
dll/win32/ole32/rpc.c | 9 +-
dll/win32/ole32/stg_prop.c | 52 +---
dll/win32/ole32/storage32.c | 4 +-
dll/win32/ole32/storage32.h | 11 +-
dll/win32/ole32/usrmarshal.c | 178 +++++++++--
media/doc/README.WINE | 2 +-
12 files changed, 827 insertions(+), 523 deletions(-)
diff --git a/dll/win32/ole32/compobj.c b/dll/win32/ole32/compobj.c
index cdadd0f349..fd912d4e73 100644
--- a/dll/win32/ole32/compobj.c
+++ b/dll/win32/ole32/compobj.c
@@ -1702,12 +1702,6 @@ HWND apartment_getwindow(const struct apartment *apt)
return apt->win;
}
-void apartment_joinmta(void)
-{
- apartment_addref(MTA);
- COM_CurrentInfo()->apt = MTA;
-}
-
static void COM_TlsDestroy(void)
{
struct oletls *info = NtCurrentTeb()->ReservedForOle;
@@ -1812,6 +1806,40 @@ HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie)
return S_OK;
}
+HRESULT enter_apartment( struct oletls *info, DWORD model )
+{
+ HRESULT hr = S_OK;
+
+ if (!info->apt)
+ {
+ if (!apartment_get_or_create( model ))
+ return E_OUTOFMEMORY;
+ }
+ else if (!apartment_is_model( info->apt, model ))
+ {
+ WARN( "Attempt to change threading model of this apartment from %s to
%s\n",
+ info->apt->multi_threaded ? "multi-threaded" :
"apartment threaded",
+ model & COINIT_APARTMENTTHREADED ? "apartment threaded" :
"multi-threaded" );
+ return RPC_E_CHANGED_MODE;
+ }
+ else
+ hr = S_FALSE;
+
+ info->inits++;
+
+ return hr;
+}
+
+void leave_apartment( struct oletls *info )
+{
+ if (!--info->inits)
+ {
+ if (info->ole_inits)
+ WARN( "Uninitializing apartment while Ole is still initialized\n"
);
+ apartment_release( info->apt );
+ info->apt = NULL;
+ }
+}
/******************************************************************************
* CoInitialize [OLE32.@]
@@ -1870,8 +1898,7 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved)
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
{
struct oletls *info = COM_CurrentInfo();
- HRESULT hr = S_OK;
- APARTMENT *apt;
+ HRESULT hr;
TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
@@ -1900,24 +1927,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved,
DWORD dwCoIni
if (info->spy)
IInitializeSpy_PreInitialize(info->spy, dwCoInit, info->inits);
- if (!(apt = info->apt))
- {
- apt = apartment_get_or_create(dwCoInit);
- if (!apt) return E_OUTOFMEMORY;
- }
- else if (!apartment_is_model(apt, dwCoInit))
- {
- /* Changing the threading model after it's been set is illegal. If this warning
is triggered by Wine
- code then we are probably using the wrong threading model to implement that API.
*/
- ERR("Attempt to change threading model of this apartment from %s to %s\n",
- apt->multi_threaded ? "multi-threaded" : "apartment
threaded",
- dwCoInit & COINIT_APARTMENTTHREADED ? "apartment threaded" :
"multi-threaded");
- return RPC_E_CHANGED_MODE;
- }
- else
- hr = S_FALSE;
-
- info->inits++;
+ hr = enter_apartment( info, dwCoInit );
if (info->spy)
IInitializeSpy_PostInitialize(info->spy, hr, dwCoInit, info->inits);
@@ -1964,13 +1974,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
return;
}
- if (!--info->inits)
- {
- if (info->ole_inits)
- WARN("uninitializing apartment while Ole is still initialized\n");
- apartment_release(info->apt);
- info->apt = NULL;
- }
+ leave_apartment( info );
/*
* Decrease the reference count.
diff --git a/dll/win32/ole32/compobj_private.h b/dll/win32/ole32/compobj_private.h
index 672b39460b..c1739f57e9 100644
--- a/dll/win32/ole32/compobj_private.h
+++ b/dll/win32/ole32/compobj_private.h
@@ -233,8 +233,8 @@ static inline HRESULT apartment_getoxid(const struct apartment *apt,
OXID *oxid)
}
HRESULT apartment_createwindowifneeded(struct apartment *apt) DECLSPEC_HIDDEN;
HWND apartment_getwindow(const struct apartment *apt) DECLSPEC_HIDDEN;
-void apartment_joinmta(void) DECLSPEC_HIDDEN;
-
+HRESULT enter_apartment(struct oletls *info, DWORD model) DECLSPEC_HIDDEN;
+void leave_apartment(struct oletls *info) 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 *)
*/
diff --git a/dll/win32/ole32/datacache.c b/dll/win32/ole32/datacache.c
index 8c3fe48e52..e3697761e0 100644
--- a/dll/win32/ole32/datacache.c
+++ b/dll/win32/ole32/datacache.c
@@ -64,7 +64,8 @@ typedef struct PresentationDataHeader
* DWORD length;
* CHAR format_name[length]; (null-terminated)
*/
- DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
+ DWORD tdSize; /* This is actually a truncated DVTARGETDEVICE, if tdSize >
sizeof(DWORD)
+ then there are tdSize - sizeof(DWORD) more bytes before dvAspect */
DVASPECT dvAspect;
DWORD lindex;
DWORD advf;
@@ -86,8 +87,6 @@ typedef struct DataCacheEntry
struct list entry;
/* format of this entry */
FORMATETC fmtetc;
- /* the clipboard format of the data */
- CLIPFORMAT data_cf;
/* cached data */
STGMEDIUM stgmedium;
/*
@@ -295,10 +294,10 @@ static DataCacheEntry *DataCache_GetEntryForFormatEtc(DataCache
*This, const FOR
LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
{
/* FIXME: also compare DVTARGETDEVICEs */
- if ((!cache_entry->fmtetc.cfFormat || !fmt.cfFormat || (fmt.cfFormat ==
cache_entry->fmtetc.cfFormat)) &&
+ if ((fmt.cfFormat == cache_entry->fmtetc.cfFormat) &&
(fmt.dwAspect == cache_entry->fmtetc.dwAspect) &&
(fmt.lindex == cache_entry->fmtetc.lindex) &&
- (!cache_entry->fmtetc.tymed || !fmt.tymed || (fmt.tymed ==
cache_entry->fmtetc.tymed)))
+ ((fmt.tymed == cache_entry->fmtetc.tymed) ||
!cache_entry->fmtetc.cfFormat)) /* tymed is ignored for view caching */
return cache_entry;
}
return NULL;
@@ -307,19 +306,23 @@ 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)
+static HRESULT check_valid_formatetc( const FORMATETC *fmt )
{
- if (!cfFormat || !tymed ||
- (cfFormat == CF_METAFILEPICT && tymed == TYMED_MFPICT) ||
- (cfFormat == CF_BITMAP && tymed == TYMED_GDI) ||
- (cfFormat == CF_DIB && tymed == TYMED_HGLOBAL) ||
- (cfFormat == CF_ENHMETAFILE && tymed == TYMED_ENHMF))
+ /* DVASPECT_ICON must be CF_METAFILEPICT */
+ if (fmt->dwAspect == DVASPECT_ICON && fmt->cfFormat != CF_METAFILEPICT)
+ return DV_E_FORMATETC;
+
+ if (!fmt->cfFormat ||
+ (fmt->cfFormat == CF_METAFILEPICT && fmt->tymed == TYMED_MFPICT) ||
+ (fmt->cfFormat == CF_BITMAP && fmt->tymed == TYMED_GDI) ||
+ (fmt->cfFormat == CF_DIB && fmt->tymed == TYMED_HGLOBAL) ||
+ (fmt->cfFormat == CF_ENHMETAFILE && fmt->tymed == TYMED_ENHMF))
return S_OK;
- else if (tymed == TYMED_HGLOBAL)
+ else if (fmt->tymed == TYMED_HGLOBAL)
return CACHE_S_FORMATETC_NOTSUPPORTED;
else
{
- WARN("invalid clipformat/tymed combination: %d/%d\n", cfFormat, tymed);
+ WARN("invalid clipformat/tymed combination: %d/%d\n", fmt->cfFormat,
fmt->tymed);
return DV_E_TYMED;
}
}
@@ -332,7 +335,6 @@ static BOOL init_cache_entry(DataCacheEntry *entry, const FORMATETC
*fmt, DWORD
hr = copy_formatetc(&entry->fmtetc, fmt);
if (FAILED(hr)) return FALSE;
- entry->data_cf = 0;
entry->stgmedium.tymed = TYMED_NULL;
entry->stgmedium.pUnkForRelease = NULL;
entry->stream = NULL;
@@ -353,7 +355,7 @@ static HRESULT DataCache_CreateEntry(DataCache *This, const FORMATETC
*formatetc
DWORD id = automatic ? 1 : This->last_cache_id;
DataCacheEntry *entry;
- hr = check_valid_clipformat_and_tymed(formatetc->cfFormat, formatetc->tymed);
+ hr = check_valid_formatetc( formatetc );
if (FAILED(hr))
return hr;
if (hr == CACHE_S_FORMATETC_NOTSUPPORTED)
@@ -454,6 +456,10 @@ static HRESULT read_clipformat(IStream *stream, CLIPFORMAT
*clipformat)
hr = IStream_Read(stream, &length, sizeof(length), &read);
if (hr != S_OK || read != sizeof(length))
return DV_E_CLIPFORMAT;
+ if (!length) {
+ /* No clipboard format present */
+ return S_OK;
+ }
if (length == -1)
{
DWORD cf;
@@ -483,11 +489,16 @@ static HRESULT write_clipformat(IStream *stream, CLIPFORMAT
clipformat)
{
DWORD length;
HRESULT hr;
+ char format_name[256];
if (clipformat < 0xc000)
length = -1;
else
- length = GetClipboardFormatNameA(clipformat, NULL, 0);
+ {
+ length = GetClipboardFormatNameA(clipformat, format_name, sizeof(format_name));
+ /* If there is a clipboard format name, we need to include its terminating \0 */
+ if (length) length++;
+ }
hr = IStream_Write(stream, &length, sizeof(length), NULL);
if (FAILED(hr))
return hr;
@@ -498,12 +509,7 @@ static HRESULT write_clipformat(IStream *stream, CLIPFORMAT
clipformat)
}
else
{
- char *format_name = HeapAlloc(GetProcessHeap(), 0, length);
- if (!format_name)
- return E_OUTOFMEMORY;
- GetClipboardFormatNameA(clipformat, format_name, length);
hr = IStream_Write(stream, format_name, length, NULL);
- HeapFree(GetProcessHeap(), 0, format_name);
}
return hr;
}
@@ -618,7 +624,6 @@ static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm
)
GlobalUnlock( hmfpict );
if (SUCCEEDED( hr ))
{
- cache_entry->data_cf = cache_entry->fmtetc.cfFormat;
cache_entry->stgmedium.tymed = TYMED_MFPICT;
cache_entry->stgmedium.u.hMetaFilePict = hmfpict;
}
@@ -703,7 +708,6 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
GlobalUnlock( hglobal );
- cache_entry->data_cf = cache_entry->fmtetc.cfFormat;
cache_entry->stgmedium.tymed = TYMED_HGLOBAL;
cache_entry->stgmedium.u.hGlobal = hglobal;
@@ -756,112 +760,273 @@ static HRESULT DataCacheEntry_LoadData(DataCacheEntry
*cache_entry)
return hr;
}
-static HRESULT DataCacheEntry_CreateStream(DataCacheEntry *cache_entry,
- IStorage *storage, IStream **stream)
+static void init_stream_header(DataCacheEntry *entry, PresentationDataHeader *header)
{
- WCHAR wszName[] =
{2,'O','l','e','P','r','e','s',
- '0' + (cache_entry->stream_number / 100) % 10,
- '0' + (cache_entry->stream_number / 10) % 10,
- '0' + cache_entry->stream_number % 10, 0};
-
- /* FIXME: cache the created stream in This? */
- return IStorage_CreateStream(storage, wszName,
- STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
- 0, 0, stream);
+ if (entry->fmtetc.ptd)
+ FIXME("ptd not serialized\n");
+ header->tdSize = sizeof(header->tdSize);
+ header->dvAspect = entry->fmtetc.dwAspect;
+ header->lindex = entry->fmtetc.lindex;
+ header->advf = entry->advise_flags;
+ header->unknown7 = 0;
+ header->dwObjectExtentX = 0;
+ header->dwObjectExtentY = 0;
+ header->dwSize = 0;
}
-static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage,
- BOOL same_as_load)
+static HRESULT save_dib(DataCacheEntry *entry, BOOL contents, IStream *stream)
{
- PresentationDataHeader header;
- HRESULT hr;
- IStream *pres_stream;
- void *data = NULL;
-
- TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number,
debugstr_formatetc(&cache_entry->fmtetc));
+ HRESULT hr = S_OK;
+ int data_size = 0;
+ BITMAPINFO *bmi = NULL;
- hr = DataCacheEntry_CreateStream(cache_entry, storage, &pres_stream);
- if (FAILED(hr))
- return hr;
+ if (entry->stgmedium.tymed != TYMED_NULL)
+ {
+ data_size = GlobalSize(entry->stgmedium.u.hGlobal);
+ bmi = GlobalLock(entry->stgmedium.u.hGlobal);
+ }
- hr = write_clipformat(pres_stream, cache_entry->data_cf);
- if (FAILED(hr))
- return hr;
+ if (!contents)
+ {
+ PresentationDataHeader header;
- if (cache_entry->fmtetc.ptd)
- FIXME("ptd not serialized\n");
- header.unknown3 = 4;
- header.dvAspect = cache_entry->fmtetc.dwAspect;
- header.lindex = cache_entry->fmtetc.lindex;
- header.advf = cache_entry->advise_flags;
- header.unknown7 = 0;
- header.dwObjectExtentX = 0;
- header.dwObjectExtentY = 0;
- header.dwSize = 0;
-
- /* size the data */
- switch (cache_entry->data_cf)
- {
- case CF_METAFILEPICT:
+ init_stream_header(entry, &header);
+ hr = write_clipformat(stream, entry->fmtetc.cfFormat);
+ if (FAILED(hr)) goto end;
+ if (data_size)
{
- if (cache_entry->stgmedium.tymed != TYMED_NULL)
+ header.dwSize = data_size;
+ /* Size in units of 0.01mm (ie. MM_HIMETRIC) */
+ if (bmi->bmiHeader.biXPelsPerMeter != 0 &&
bmi->bmiHeader.biYPelsPerMeter != 0)
{
- const METAFILEPICT *mfpict =
GlobalLock(cache_entry->stgmedium.u.hMetaFilePict);
- if (!mfpict)
- {
- IStream_Release(pres_stream);
- return DV_E_STGMEDIUM;
- }
- header.dwObjectExtentX = mfpict->xExt;
- header.dwObjectExtentY = mfpict->yExt;
- header.dwSize = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
- GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
+ header.dwObjectExtentX = MulDiv(bmi->bmiHeader.biWidth, 100000,
bmi->bmiHeader.biXPelsPerMeter);
+ header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 100000,
bmi->bmiHeader.biYPelsPerMeter);
+ }
+ else
+ {
+ HDC hdc = GetDC(0);
+ header.dwObjectExtentX = MulDiv(bmi->bmiHeader.biWidth, 2540,
GetDeviceCaps(hdc, LOGPIXELSX));
+ header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 2540,
GetDeviceCaps(hdc, LOGPIXELSY));
+ ReleaseDC(0, hdc);
}
- break;
}
- default:
- break;
+ hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
+ if (hr == S_OK && data_size)
+ hr = IStream_Write(stream, bmi, data_size, NULL);
}
-
- /*
- * Write the header.
- */
- hr = IStream_Write(pres_stream, &header, sizeof(PresentationDataHeader),
- NULL);
- if (FAILED(hr))
+ else if(data_size)
{
- IStream_Release(pres_stream);
- return hr;
+ BITMAPFILEHEADER bmp_fhdr;
+
+ bmp_fhdr.bfType = 0x4d42;
+ bmp_fhdr.bfSize = data_size + sizeof(BITMAPFILEHEADER);
+ bmp_fhdr.bfReserved1 = bmp_fhdr.bfReserved2 = 0;
+ bmp_fhdr.bfOffBits = bitmap_info_size(bmi, DIB_RGB_COLORS) +
sizeof(BITMAPFILEHEADER);
+ hr = IStream_Write(stream, &bmp_fhdr, sizeof(BITMAPFILEHEADER), NULL);
+ if (hr == S_OK)
+ hr = IStream_Write(stream, bmi, data_size, NULL);
}
- /* get the data */
- switch (cache_entry->data_cf)
+end:
+ if (bmi) GlobalUnlock(entry->stgmedium.u.hGlobal);
+ 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;
+ int data_size = 0;
+ void *data = NULL;
+ METAFILEPICT *mfpict = NULL;
+
+ if (!contents)
{
- case CF_METAFILEPICT:
+ PresentationDataHeader header;
+
+ init_stream_header(entry, &header);
+ hr = write_clipformat(stream, entry->fmtetc.cfFormat);
+ if (FAILED(hr)) return hr;
+ if (entry->stgmedium.tymed != TYMED_NULL)
{
- if (cache_entry->stgmedium.tymed != TYMED_NULL)
+ mfpict = GlobalLock(entry->stgmedium.u.hMetaFilePict);
+ if (!mfpict)
+ return DV_E_STGMEDIUM;
+ data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
+ header.dwObjectExtentX = mfpict->xExt;
+ header.dwObjectExtentY = mfpict->yExt;
+ header.dwSize = data_size;
+ data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
+ if (!data)
{
- const METAFILEPICT *mfpict =
GlobalLock(cache_entry->stgmedium.u.hMetaFilePict);
- if (!mfpict)
- {
- IStream_Release(pres_stream);
- return DV_E_STGMEDIUM;
- }
- data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
- GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
- GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
+ GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
+ return E_OUTOFMEMORY;
}
- break;
+ GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
+ GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
}
- default:
- break;
+ hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
+ if (hr == S_OK && data_size)
+ hr = IStream_Write(stream, data, data_size, NULL);
+ HeapFree(GetProcessHeap(), 0, data);
}
+ else if (entry->stgmedium.tymed != TYMED_NULL)
+ {
+ struct meta_placeable meta_place_rec;
+ WORD *check;
- if (data)
- hr = IStream_Write(pres_stream, data, header.dwSize, NULL);
- HeapFree(GetProcessHeap(), 0, data);
+ mfpict = GlobalLock(entry->stgmedium.u.hMetaFilePict);
+ if (!mfpict)
+ return DV_E_STGMEDIUM;
+ data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
+ data = HeapAlloc(GetProcessHeap(), 0, data_size);
+ if (!data)
+ {
+ GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
+ return E_OUTOFMEMORY;
+ }
+ GetMetaFileBitsEx(mfpict->hMF, data_size, data);
+
+ /* units are in 1/8th of a point (1 point is 1/72th of an inch) */
+ meta_place_rec.key = 0x9ac6cdd7;
+ meta_place_rec.hwmf = 0;
+ meta_place_rec.inch = 576;
+ meta_place_rec.bounding_box[0] = 0;
+ meta_place_rec.bounding_box[1] = 0;
+ meta_place_rec.bounding_box[2] = 0;
+ meta_place_rec.bounding_box[3] = 0;
+ meta_place_rec.checksum = 0;
+ meta_place_rec.reserved = 0;
+
+ /* These values are rounded down so MulDiv won't do the right thing */
+ meta_place_rec.bounding_box[2] = (LONGLONG)mfpict->xExt * meta_place_rec.inch
/ 2540;
+ meta_place_rec.bounding_box[3] = (LONGLONG)mfpict->yExt * meta_place_rec.inch
/ 2540;
+ GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
+
+ for (check = (WORD *)&meta_place_rec; check != (WORD
*)&meta_place_rec.checksum; check++)
+ meta_place_rec.checksum ^= *check;
+ hr = IStream_Write(stream, &meta_place_rec, sizeof(struct meta_placeable),
NULL);
+ if (hr == S_OK && data_size)
+ hr = IStream_Write(stream, data, data_size, NULL);
+ HeapFree(GetProcessHeap(), 0, data);
+ }
+
+ return hr;
+}
+
+static HRESULT save_emf(DataCacheEntry *entry, BOOL contents, IStream *stream)
+{
+ HRESULT hr = S_OK;
+ int data_size = 0;
+ BYTE *data;
+
+ if (!contents)
+ {
+ PresentationDataHeader header;
+ METAFILEPICT *mfpict;
+ HDC hdc = GetDC(0);
+
+ init_stream_header(entry, &header);
+ hr = write_clipformat(stream, entry->fmtetc.cfFormat);
+ if (FAILED(hr))
+ {
+ ReleaseDC(0, hdc);
+ return hr;
+ }
+ data_size = GetWinMetaFileBits(entry->stgmedium.u.hEnhMetaFile, 0, NULL,
MM_ANISOTROPIC, hdc);
+ header.dwSize = data_size;
+ data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
+ if (!data)
+ {
+ ReleaseDC(0, hdc);
+ return E_OUTOFMEMORY;
+ }
+ GetWinMetaFileBits(entry->stgmedium.u.hEnhMetaFile, header.dwSize, data,
MM_ANISOTROPIC, hdc);
+ ReleaseDC(0, hdc);
+ mfpict = (METAFILEPICT *)data;
+ header.dwObjectExtentX = mfpict->xExt;
+ header.dwObjectExtentY = mfpict->yExt;
+ hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
+ if (hr == S_OK && data_size)
+ hr = IStream_Write(stream, data, data_size, NULL);
+ HeapFree(GetProcessHeap(), 0, data);
+ }
+ else if (entry->stgmedium.tymed != TYMED_NULL)
+ {
+ data_size = GetEnhMetaFileBits(entry->stgmedium.u.hEnhMetaFile, 0, NULL);
+ data = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) + sizeof(ENHMETAHEADER) +
data_size);
+ if (!data) return E_OUTOFMEMORY;
+ *((DWORD *)data) = sizeof(ENHMETAHEADER);
+ GetEnhMetaFileBits(entry->stgmedium.u.hEnhMetaFile, data_size, data +
sizeof(DWORD) + sizeof(ENHMETAHEADER));
+ memcpy(data + sizeof(DWORD), data + sizeof(DWORD) + sizeof(ENHMETAHEADER),
sizeof(ENHMETAHEADER));
+ data_size += sizeof(DWORD) + sizeof(ENHMETAHEADER);
+ hr = IStream_Write(stream, data, data_size, NULL);
+ HeapFree(GetProcessHeap(), 0, data);
+ }
- IStream_Release(pres_stream);
+ return hr;
+}
+
+static const WCHAR CONTENTS[] =
{'C','O','N','T','E','N','T','S',0};
+static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage,
+ BOOL contents, IStream **stream)
+{
+ WCHAR pres[] =
{2,'O','l','e','P','r','e','s',
+ '0' + (cache_entry->stream_number / 100) % 10,
+ '0' + (cache_entry->stream_number / 10) % 10,
+ '0' + cache_entry->stream_number % 10, 0};
+ const WCHAR *name;
+
+ if (contents)
+ name = CONTENTS;
+ else
+ name = pres;
+
+ return IStorage_CreateStream(storage, name,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
+ 0, 0, stream);
+}
+
+static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage,
+ BOOL same_as_load)
+{
+ HRESULT hr;
+ IStream *stream;
+ BOOL contents = (cache_entry->id == 1);
+
+ TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number,
debugstr_formatetc(&cache_entry->fmtetc));
+
+ hr = create_stream(cache_entry, storage, contents, &stream);
+ if (FAILED(hr))
+ return hr;
+
+ switch (cache_entry->fmtetc.cfFormat)
+ {
+ case CF_DIB:
+ hr = save_dib(cache_entry, contents, stream);
+ break;
+ case CF_METAFILEPICT:
+ hr = save_mfpict(cache_entry, contents, stream);
+ break;
+ case CF_ENHMETAFILE:
+ hr = save_emf(cache_entry, contents, stream);
+ break;
+ default:
+ FIXME("got unsupported clipboard format %x\n",
cache_entry->fmtetc.cfFormat);
+ }
+
+ IStream_Release(stream);
return hr;
}
@@ -904,12 +1069,12 @@ static HRESULT copy_stg_medium(CLIPFORMAT cf, STGMEDIUM *dest_stgm,
return S_OK;
}
-static HGLOBAL synthesize_dib( HBITMAP bm )
+static HRESULT synthesize_dib( HBITMAP bm, STGMEDIUM *med )
{
HDC hdc = GetDC( 0 );
BITMAPINFOHEADER header;
BITMAPINFO *bmi;
- HGLOBAL ret = 0;
+ HRESULT hr = E_FAIL;
DWORD header_size;
memset( &header, 0, sizeof(header) );
@@ -917,34 +1082,64 @@ static HGLOBAL synthesize_dib( HBITMAP bm )
if (!GetDIBits( hdc, bm, 0, 0, NULL, (BITMAPINFO *)&header, DIB_RGB_COLORS ))
goto done;
header_size = bitmap_info_size( (BITMAPINFO *)&header, DIB_RGB_COLORS );
- if (!(ret = GlobalAlloc( GMEM_MOVEABLE, header_size + header.biSizeImage ))) goto
done;
- bmi = GlobalLock( ret );
+ if (!(med->u.hGlobal = GlobalAlloc( GMEM_MOVEABLE, header_size +
header.biSizeImage ))) goto done;
+ bmi = GlobalLock( med->u.hGlobal );
memset( bmi, 0, header_size );
memcpy( bmi, &header, header.biSize );
GetDIBits( hdc, bm, 0, abs(header.biHeight), (char *)bmi + header_size, bmi,
DIB_RGB_COLORS );
- GlobalUnlock( ret );
+ GlobalUnlock( med->u.hGlobal );
+ med->tymed = TYMED_HGLOBAL;
+ med->pUnkForRelease = NULL;
+ hr = S_OK;
done:
ReleaseDC( 0, hdc );
- return ret;
+ return hr;
}
-static HBITMAP synthesize_bitmap( HGLOBAL dib )
+static HRESULT synthesize_bitmap( HGLOBAL dib, STGMEDIUM *med )
{
- HBITMAP ret = 0;
+ HRESULT hr = E_FAIL;
BITMAPINFO *bmi;
HDC hdc = GetDC( 0 );
if ((bmi = GlobalLock( dib )))
{
/* FIXME: validate data size */
- ret = CreateDIBitmap( hdc, &bmi->bmiHeader, CBM_INIT,
- (char *)bmi + bitmap_info_size( bmi, DIB_RGB_COLORS ),
- bmi, DIB_RGB_COLORS );
+ med->u.hBitmap = CreateDIBitmap( hdc, &bmi->bmiHeader, CBM_INIT,
+ (char *)bmi + bitmap_info_size( bmi,
DIB_RGB_COLORS ),
+ bmi, DIB_RGB_COLORS );
GlobalUnlock( dib );
+ med->tymed = TYMED_GDI;
+ med->pUnkForRelease = NULL;
+ hr = S_OK;
}
ReleaseDC( 0, hdc );
- return ret;
+ 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,
@@ -952,7 +1147,8 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
STGMEDIUM *stgmedium,
BOOL fRelease)
{
- STGMEDIUM dib_copy;
+ STGMEDIUM copy;
+ HRESULT hr;
if ((!cache_entry->fmtetc.cfFormat && !formatetc->cfFormat) ||
(cache_entry->fmtetc.tymed == TYMED_NULL && formatetc->tymed ==
TYMED_NULL) ||
@@ -964,15 +1160,21 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
cache_entry->dirty = TRUE;
ReleaseStgMedium(&cache_entry->stgmedium);
- cache_entry->data_cf = cache_entry->fmtetc.cfFormat ?
cache_entry->fmtetc.cfFormat : formatetc->cfFormat;
if (formatetc->cfFormat == CF_BITMAP)
{
- dib_copy.tymed = TYMED_HGLOBAL;
- dib_copy.u.hGlobal = synthesize_dib( stgmedium->u.hBitmap );
- dib_copy.pUnkForRelease = NULL;
+ hr = synthesize_dib( stgmedium->u.hBitmap, © );
+ if (FAILED(hr)) return hr;
if (fRelease) ReleaseStgMedium(stgmedium);
- stgmedium = &dib_copy;
+ stgmedium = ©
+ fRelease = TRUE;
+ }
+ else if (formatetc->cfFormat == CF_METAFILEPICT &&
cache_entry->fmtetc.cfFormat == CF_ENHMETAFILE)
+ {
+ hr = synthesize_emf( stgmedium->u.hMetaFilePict, © );
+ if (FAILED(hr)) return hr;
+ if (fRelease) ReleaseStgMedium(stgmedium);
+ stgmedium = ©
fRelease = TRUE;
}
@@ -982,8 +1184,7 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
return S_OK;
}
else
- return copy_stg_medium(cache_entry->data_cf,
- &cache_entry->stgmedium, stgmedium);
+ return copy_stg_medium(cache_entry->fmtetc.cfFormat,
&cache_entry->stgmedium, stgmedium);
}
static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, FORMATETC *fmt,
STGMEDIUM *stgmedium)
@@ -998,19 +1199,14 @@ static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry,
FORMATETC *fm
return OLE_E_BLANK;
if (fmt->cfFormat == CF_BITMAP)
- {
- stgmedium->tymed = TYMED_GDI;
- stgmedium->u.hBitmap = synthesize_bitmap( cache_entry->stgmedium.u.hGlobal
);
- stgmedium->pUnkForRelease = NULL;
- return S_OK;
- }
- return copy_stg_medium(cache_entry->data_cf, stgmedium,
&cache_entry->stgmedium);
+ return synthesize_bitmap( cache_entry->stgmedium.u.hGlobal, stgmedium );
+
+ return copy_stg_medium(cache_entry->fmtetc.cfFormat, stgmedium,
&cache_entry->stgmedium);
}
static inline HRESULT DataCacheEntry_DiscardData(DataCacheEntry *cache_entry)
{
ReleaseStgMedium(&cache_entry->stgmedium);
- cache_entry->data_cf = cache_entry->fmtetc.cfFormat;
return S_OK;
}
@@ -1108,7 +1304,10 @@ static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
if (IsEqualIID(&IID_IUnknown, riid))
{
- *ppvObject = iface;
+ if (this->outer_unk == iface) /* non-aggregated, return IUnknown from IOleCache2
*/
+ *ppvObject = &this->IOleCache2_iface;
+ else
+ *ppvObject = iface;
}
else if (IsEqualIID(&IID_IDataObject, riid))
{
@@ -1230,6 +1429,8 @@ static HRESULT WINAPI DataCache_GetData(
DataCache *This = impl_from_IDataObject(iface);
DataCacheEntry *cache_entry;
+ TRACE("(%p, %s, %p)\n", iface, debugstr_formatetc(pformatetcIn), pmedium);
+
memset(pmedium, 0, sizeof(*pmedium));
cache_entry = DataCache_GetEntryForFormatEtc(This, pformatetcIn);
@@ -1561,8 +1762,6 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage
*stg, IStream *s
return add_cache_entry( This, fmt, 0, stm, contents_stream );
}
-static const WCHAR CONTENTS[] =
{'C','O','N','T','E','N','T','S',0};
-
/************************************************************************
* DataCache_Load (IPersistStorage)
*
@@ -1621,35 +1820,14 @@ static HRESULT WINAPI DataCache_Load( IPersistStorage *iface,
IStorage *pStg )
* our responsibility to copy the information when saving to a new
* storage.
*/
-static HRESULT WINAPI DataCache_Save(
- IPersistStorage* iface,
- IStorage* pStg,
- BOOL fSameAsLoad)
+static HRESULT WINAPI DataCache_Save(IPersistStorage* iface, IStorage *stg, BOOL
same_as_load)
{
DataCache *This = impl_from_IPersistStorage(iface);
DataCacheEntry *cache_entry;
- BOOL dirty = FALSE;
HRESULT hr = S_OK;
unsigned short stream_number = 0;
- TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
-
- dirty = This->dirty;
- if (!dirty)
- {
- LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
- {
- dirty = cache_entry->dirty;
- if (dirty)
- break;
- }
- }
-
- /* this is a shortcut if nothing changed */
- if (!dirty && !fSameAsLoad && This->presentationStorage)
- {
- return IStorage_CopyTo(This->presentationStorage, 0, NULL, NULL, pStg);
- }
+ TRACE("(%p, %p, %d)\n", iface, stg, same_as_load);
/* assign stream numbers to the cache entries */
LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
@@ -1665,17 +1843,17 @@ static HRESULT WINAPI DataCache_Save(
/* write out the cache entries */
LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
{
- if (!fSameAsLoad || cache_entry->dirty)
+ if (!same_as_load || cache_entry->dirty)
{
- hr = DataCacheEntry_Save(cache_entry, pStg, fSameAsLoad);
+ hr = DataCacheEntry_Save(cache_entry, stg, same_as_load);
if (FAILED(hr))
break;
- cache_entry->dirty = FALSE;
+ if (same_as_load) cache_entry->dirty = FALSE;
}
}
- This->dirty = FALSE;
+ if (same_as_load) This->dirty = FALSE;
return hr;
}
@@ -1826,7 +2004,7 @@ static HRESULT WINAPI DataCache_Draw(
if (pfnContinue && !pfnContinue(dwContinue)) return E_ABORT;
- switch (cache_entry->data_cf)
+ switch (cache_entry->fmtetc.cfFormat)
{
case CF_METAFILEPICT:
{
@@ -2085,7 +2263,7 @@ static HRESULT WINAPI DataCache_GetExtent(
continue;
- switch (cache_entry->data_cf)
+ switch (cache_entry->fmtetc.cfFormat)
{
case CF_METAFILEPICT:
{
@@ -2231,6 +2409,13 @@ static HRESULT WINAPI DataCache_Cache(
fmt_cpy.tymed = TYMED_HGLOBAL;
}
+ /* View caching DVASPECT_ICON gets converted to CF_METAFILEPICT */
+ if (fmt_cpy.dwAspect == DVASPECT_ICON && fmt_cpy.cfFormat == 0)
+ {
+ fmt_cpy.cfFormat = CF_METAFILEPICT;
+ fmt_cpy.tymed = TYMED_MFPICT;
+ }
+
*pdwConnection = 0;
cache_entry = DataCache_GetEntryForFormatEtc(This, &fmt_cpy);
@@ -2327,12 +2512,10 @@ fail:
return hr;
}
-static HRESULT WINAPI DataCache_InitCache(
- IOleCache2* iface,
- IDataObject* pDataObject)
+static HRESULT WINAPI DataCache_InitCache( IOleCache2 *iface, IDataObject *data )
{
- FIXME("stub\n");
- return E_NOTIMPL;
+ TRACE( "(%p %p)\n", iface, data );
+ return IOleCache2_UpdateCache( iface, data, UPDFCACHE_ALLBUTNODATACACHE, NULL );
}
static HRESULT WINAPI DataCache_IOleCache2_SetData(
@@ -2364,14 +2547,102 @@ static HRESULT WINAPI DataCache_IOleCache2_SetData(
return OLE_E_BLANK;
}
-static HRESULT WINAPI DataCache_UpdateCache(
- IOleCache2* iface,
- LPDATAOBJECT pDataObject,
- DWORD grfUpdf,
- LPVOID pReserved)
+static BOOL entry_updatable( DataCacheEntry *entry, DWORD mode )
{
- FIXME("(%p, 0x%x, %p): stub\n", pDataObject, grfUpdf, pReserved);
- return E_NOTIMPL;
+ BOOL is_blank = entry->stgmedium.tymed == TYMED_NULL;
+
+ if ((mode & UPDFCACHE_ONLYIFBLANK) && !is_blank) return FALSE;
+
+ if ((mode & UPDFCACHE_NODATACACHE) && (entry->advise_flags &
ADVF_NODATA)) return TRUE;
+ if ((mode & UPDFCACHE_ONSAVECACHE) && (entry->advise_flags &
ADVFCACHE_ONSAVE)) return TRUE;
+ if ((mode & UPDFCACHE_ONSTOPCACHE) && (entry->advise_flags &
ADVF_DATAONSTOP)) return TRUE;
+ if ((mode & UPDFCACHE_NORMALCACHE) && (entry->advise_flags == 0))
return TRUE;
+ if ((mode & UPDFCACHE_IFBLANK) && (is_blank &&
!(entry->advise_flags & ADVF_NODATA))) return TRUE;
+
+ return FALSE;
+}
+
+static HRESULT WINAPI DataCache_UpdateCache( IOleCache2 *iface, IDataObject *data,
+ DWORD mode, void *reserved )
+{
+ DataCache *This = impl_from_IOleCache2(iface);
+ DataCacheEntry *cache_entry;
+ STGMEDIUM med;
+ HRESULT hr = S_OK;
+ CLIPFORMAT view_list[] = { CF_METAFILEPICT, CF_ENHMETAFILE, CF_DIB, CF_BITMAP };
+ FORMATETC fmt;
+ int i, slots = 0;
+ BOOL done_one = FALSE;
+
+ TRACE( "(%p %p %08x %p)\n", iface, data, mode, reserved );
+
+ LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry )
+ {
+ slots++;
+
+ if (!entry_updatable( cache_entry, mode ))
+ {
+ done_one = TRUE;
+ continue;
+ }
+
+ fmt = cache_entry->fmtetc;
+
+ if (fmt.cfFormat)
+ {
+ hr = IDataObject_GetData( data, &fmt, &med );
+ if (hr != S_OK && fmt.cfFormat == CF_DIB)
+ {
+ fmt.cfFormat = CF_BITMAP;
+ fmt.tymed = TYMED_GDI;
+ hr = IDataObject_GetData( data, &fmt, &med );
+ }
+ if (hr != S_OK && fmt.cfFormat == CF_ENHMETAFILE)
+ {
+ fmt.cfFormat = CF_METAFILEPICT;
+ fmt.tymed = TYMED_MFPICT;
+ hr = IDataObject_GetData( data, &fmt, &med );
+ }
+ if (hr == S_OK)
+ {
+ hr = DataCacheEntry_SetData( cache_entry, &fmt, &med, TRUE );
+ if (hr != S_OK) ReleaseStgMedium( &med );
+ else done_one = TRUE;
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof(view_list) / sizeof(view_list[0]); i++)
+ {
+ fmt.cfFormat = view_list[i];
+ fmt.tymed = tymed_from_cf( fmt.cfFormat );
+ hr = IDataObject_QueryGetData( data, &fmt );
+ if (hr == S_OK)
+ {
+ hr = IDataObject_GetData( data, &fmt, &med );
+ if (hr == S_OK)
+ {
+ if (fmt.cfFormat == CF_BITMAP)
+ {
+ cache_entry->fmtetc.cfFormat = CF_DIB;
+ cache_entry->fmtetc.tymed = TYMED_HGLOBAL;
+ }
+ else
+ {
+ cache_entry->fmtetc.cfFormat = fmt.cfFormat;
+ cache_entry->fmtetc.tymed = fmt.tymed;
+ }
+ hr = DataCacheEntry_SetData( cache_entry, &fmt, &med,
TRUE );
+ if (hr != S_OK) ReleaseStgMedium( &med );
+ else done_one = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return (!slots || done_one) ? S_OK : CACHE_E_NOCACHE_UPDATED;
}
static HRESULT WINAPI DataCache_DiscardCache(
diff --git a/dll/win32/ole32/enumx.c b/dll/win32/ole32/enumx.c
index 3af0cd19ff..7399a0214e 100644
--- a/dll/win32/ole32/enumx.c
+++ b/dll/win32/ole32/enumx.c
@@ -30,8 +30,6 @@ struct tagEnumSTATPROPSETSTG_impl
struct list *current;
ULONG elem_size;
GUID riid;
- IUnknown *parent;
- enumx_copy_cb copy_cb;
};
/************************************************************************
@@ -82,7 +80,6 @@ ULONG WINAPI enumx_Release(enumx_impl *This)
list_remove(x);
HeapFree(GetProcessHeap(), 0, x);
}
- IUnknown_Release(This->parent);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
@@ -104,10 +101,7 @@ HRESULT WINAPI enumx_Next(enumx_impl *This, ULONG celt,
p = rgelt;
while (count < celt && This->current && This->current !=
&This->elements)
{
- if (This->copy_cb)
- This->copy_cb(This->parent, &This->current[1], p);
- else
- memcpy(p, &This->current[1], This->elem_size);
+ memcpy(p, &This->current[1], This->elem_size);
p += This->elem_size;
This->current = This->current->next;
count++;
@@ -164,8 +158,7 @@ HRESULT WINAPI enumx_Clone(
*
* Allocate a generic enumerator
*/
-enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size,
- IUnknown *parent, enumx_copy_cb copy_cb)
+enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size)
{
enumx_impl *enumx;
@@ -177,11 +170,6 @@ enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG
elem_size,
enumx->current = NULL;
enumx->elem_size = elem_size;
enumx->riid = *riid;
- enumx->parent = parent;
- enumx->copy_cb = copy_cb;
-
- IUnknown_AddRef(parent);
-
list_init(&enumx->elements);
}
diff --git a/dll/win32/ole32/enumx.h b/dll/win32/ole32/enumx.h
index 6f784e140a..d4347d9e33 100644
--- a/dll/win32/ole32/enumx.h
+++ b/dll/win32/ole32/enumx.h
@@ -21,8 +21,6 @@
typedef struct tagEnumSTATPROPSETSTG_impl enumx_impl;
-typedef void (*enumx_copy_cb)(IUnknown *parent, void *orig, void *dest);
-
extern HRESULT WINAPI enumx_QueryInterface(enumx_impl *, REFIID, void**) DECLSPEC_HIDDEN;
extern ULONG WINAPI enumx_AddRef(enumx_impl *) DECLSPEC_HIDDEN;
extern ULONG WINAPI enumx_Release(enumx_impl *) DECLSPEC_HIDDEN;
@@ -30,8 +28,7 @@ extern HRESULT WINAPI enumx_Next(enumx_impl *, ULONG, void *, ULONG *)
DECLSPEC_
extern HRESULT WINAPI enumx_Skip(enumx_impl *, ULONG) DECLSPEC_HIDDEN;
extern HRESULT WINAPI enumx_Reset(enumx_impl *) DECLSPEC_HIDDEN;
extern HRESULT WINAPI enumx_Clone(enumx_impl *, enumx_impl **) DECLSPEC_HIDDEN;
-extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG,
- IUnknown *, enumx_copy_cb) DECLSPEC_HIDDEN;
+extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG) DECLSPEC_HIDDEN;
extern void *enumx_add_element(enumx_impl *, const void *) DECLSPEC_HIDDEN;
#endif /* __OLE_ENUM_H__ */
diff --git a/dll/win32/ole32/hglobalstream.c b/dll/win32/ole32/hglobalstream.c
index 6a82b716f1..732e6c6c81 100644
--- a/dll/win32/ole32/hglobalstream.c
+++ b/dll/win32/ole32/hglobalstream.c
@@ -5,7 +5,6 @@
* for streams contained supported by an HGLOBAL pointer.
*
* Copyright 1999 Francis Beaudet
- * Copyright 2016 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,158 +23,7 @@
#include "precomp.h"
-WINE_DEFAULT_DEBUG_CHANNEL(hglobalstream);
-
-struct handle_wrapper
-{
- LONG ref;
- HGLOBAL hglobal;
- ULONG size;
- BOOL delete_on_release;
- CRITICAL_SECTION lock;
-};
-
-static void handle_addref(struct handle_wrapper *handle)
-{
- InterlockedIncrement(&handle->ref);
-}
-
-static void handle_release(struct handle_wrapper *handle)
-{
- ULONG ref = InterlockedDecrement(&handle->ref);
-
- if (!ref)
- {
- if (handle->delete_on_release)
- {
- GlobalFree(handle->hglobal);
- handle->hglobal = NULL;
- }
-
- handle->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&handle->lock);
- HeapFree(GetProcessHeap(), 0, handle);
- }
-}
-
-static ULONG handle_read(struct handle_wrapper *handle, ULONG *pos, void *dest, ULONG
len)
-{
- void *source;
-
- EnterCriticalSection(&handle->lock);
-
- if (*pos < handle->size)
- len = min(handle->size - *pos, len);
- else
- len = 0;
-
- source = GlobalLock(handle->hglobal);
- if (source)
- {
- memcpy(dest, (char *)source + *pos, len);
- *pos += len;
- GlobalUnlock(handle->hglobal);
- }
- else
- {
- WARN("read from invalid hglobal %p\n", handle->hglobal);
- len = 0;
- }
-
- LeaveCriticalSection(&handle->lock);
- return len;
-}
-
-static ULONG handle_write(struct handle_wrapper *handle, ULONG *pos, const void *source,
ULONG len)
-{
- void *dest;
-
- if (!len)
- return 0;
-
- EnterCriticalSection(&handle->lock);
-
- if (*pos + len > handle->size)
- {
- HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, *pos + len, GMEM_MOVEABLE);
- if (hglobal)
- {
- handle->hglobal = hglobal;
- handle->size = *pos + len;
- }
- else
- {
- len = 0;
- goto done;
- }
- }
-
- dest = GlobalLock(handle->hglobal);
- if (dest)
- {
- memcpy((char *)dest + *pos, source, len);
- *pos += len;
- GlobalUnlock(handle->hglobal);
- }
- else
- {
- WARN("write to invalid hglobal %p\n", handle->hglobal);
- /* len = 0; */
- }
-
-done:
- LeaveCriticalSection(&handle->lock);
- return len;
-}
-
-static HGLOBAL handle_gethglobal(struct handle_wrapper *handle)
-{
- return handle->hglobal;
-}
-
-static HRESULT handle_setsize(struct handle_wrapper *handle, ULONG size)
-{
- HRESULT hr = S_OK;
-
- EnterCriticalSection(&handle->lock);
-
- if (handle->size != size)
- {
- HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, size, GMEM_MOVEABLE);
- if (hglobal)
- {
- handle->hglobal = hglobal;
- handle->size = size;
- }
- else
- hr = E_OUTOFMEMORY;
- }
-
- LeaveCriticalSection(&handle->lock);
- return hr;
-}
-
-static ULONG handle_getsize(struct handle_wrapper *handle)
-{
- return handle->size;
-}
-
-static struct handle_wrapper *handle_create(HGLOBAL hglobal, BOOL delete_on_release)
-{
- struct handle_wrapper *handle;
-
- handle = HeapAlloc(GetProcessHeap(), 0, sizeof(*handle));
- if (handle)
- {
- handle->ref = 1;
- handle->hglobal = hglobal;
- handle->size = GlobalSize(hglobal);
- handle->delete_on_release = delete_on_release;
- InitializeCriticalSection(&handle->lock);
- handle->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
handle_wrapper.lock");
- }
- return handle;
-}
+WINE_DEFAULT_DEBUG_CHANNEL(storage);
/****************************************************************************
* HGLOBALStreamImpl definition.
@@ -188,7 +36,14 @@ typedef struct
IStream IStream_iface;
LONG ref;
- struct handle_wrapper *handle;
+ /* support for the stream */
+ HGLOBAL supportHandle;
+
+ /* if TRUE the HGLOBAL is destroyed when the stream is finally released */
+ BOOL deleteOnRelease;
+
+ /* size of the stream */
+ ULARGE_INTEGER streamSize;
/* current position of the cursor */
ULARGE_INTEGER currentPosition;
@@ -240,7 +95,12 @@ static ULONG WINAPI HGLOBALStreamImpl_Release(
if (!ref)
{
- handle_release(This->handle);
+ if (This->deleteOnRelease)
+ {
+ GlobalFree(This->supportHandle);
+ This->supportHandle = NULL;
+ }
+
HeapFree(GetProcessHeap(), 0, This);
}
@@ -263,12 +123,59 @@ static HRESULT WINAPI HGLOBALStreamImpl_Read(
ULONG* pcbRead) /* [out] */
{
HGLOBALStreamImpl* This = impl_from_IStream(iface);
- ULONG num_bytes;
- TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbRead);
+ void* supportBuffer;
+ ULONG bytesReadBuffer;
+ ULONG bytesToReadFromBuffer;
+
+ TRACE("(%p, %p, %d, %p)\n", iface,
+ pv, cb, pcbRead);
+
+ /*
+ * If the caller is not interested in the number of bytes read,
+ * we use another buffer to avoid "if" statements in the code.
+ */
+ if (pcbRead==0)
+ pcbRead = &bytesReadBuffer;
+
+ /*
+ * Using the known size of the stream, calculate the number of bytes
+ * to read from the block chain
+ */
+ bytesToReadFromBuffer = min( This->streamSize.u.LowPart -
This->currentPosition.u.LowPart, cb);
+
+ /*
+ * Lock the buffer in position and copy the data.
+ */
+ supportBuffer = GlobalLock(This->supportHandle);
+ if (!supportBuffer)
+ {
+ WARN("read from invalid hglobal %p\n", This->supportHandle);
+ *pcbRead = 0;
+ return S_OK;
+ }
+
+ memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart,
bytesToReadFromBuffer);
- num_bytes = handle_read(This->handle, &This->currentPosition.u.LowPart, pv,
cb);
- if (pcbRead) *pcbRead = num_bytes;
+ /*
+ * Move the current position to the new position
+ */
+ This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
+
+ /*
+ * Return the number of bytes read.
+ */
+ *pcbRead = bytesToReadFromBuffer;
+
+ /*
+ * Cleanup
+ */
+ GlobalUnlock(This->supportHandle);
+
+ /*
+ * Always returns S_OK even if the end of the stream is reached before the
+ * buffer is filled
+ */
return S_OK;
}
@@ -290,14 +197,71 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
ULONG* pcbWritten) /* [out] */
{
HGLOBALStreamImpl* This = impl_from_IStream(iface);
- ULONG num_bytes;
+
+ void* supportBuffer;
+ ULARGE_INTEGER newSize;
+ ULONG bytesWritten = 0;
TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbWritten);
- num_bytes = handle_write(This->handle, &This->currentPosition.u.LowPart, pv,
cb);
- if (pcbWritten) *pcbWritten = num_bytes;
+ /*
+ * If the caller is not interested in the number of bytes written,
+ * we use another buffer to avoid "if" statements in the code.
+ */
+ if (pcbWritten == 0)
+ pcbWritten = &bytesWritten;
+
+ if (cb == 0)
+ goto out;
+
+ *pcbWritten = 0;
+
+ newSize.u.HighPart = 0;
+ newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
+
+ /*
+ * Verify if we need to grow the stream
+ */
+ if (newSize.u.LowPart > This->streamSize.u.LowPart)
+ {
+ /* grow stream */
+ HRESULT hr = IStream_SetSize(iface, newSize);
+ if (FAILED(hr))
+ {
+ ERR("IStream_SetSize failed with error 0x%08x\n", hr);
+ return hr;
+ }
+ }
+
+ /*
+ * Lock the buffer in position and copy the data.
+ */
+ supportBuffer = GlobalLock(This->supportHandle);
+ if (!supportBuffer)
+ {
+ WARN("write to invalid hglobal %p\n", This->supportHandle);
+ return S_OK;
+ }
+
+ memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
- return (num_bytes < cb) ? E_OUTOFMEMORY : S_OK;
+ /*
+ * Move the current position to the new position
+ */
+ This->currentPosition.u.LowPart+=cb;
+
+ /*
+ * Cleanup
+ */
+ GlobalUnlock(This->supportHandle);
+
+out:
+ /*
+ * Return the number of bytes read.
+ */
+ *pcbWritten = cb;
+
+ return S_OK;
}
/***
@@ -335,7 +299,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Seek(
case STREAM_SEEK_CUR:
break;
case STREAM_SEEK_END:
- newPosition.QuadPart = handle_getsize(This->handle);
+ newPosition = This->streamSize;
break;
default:
hr = STG_E_SEEKERROR;
@@ -380,13 +344,29 @@ static HRESULT WINAPI HGLOBALStreamImpl_SetSize(
ULARGE_INTEGER libNewSize) /* [in] */
{
HGLOBALStreamImpl* This = impl_from_IStream(iface);
+ HGLOBAL supportHandle;
TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart);
/*
* HighPart is ignored as shown in tests
*/
- return handle_setsize(This->handle, libNewSize.u.LowPart);
+
+ if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
+ return S_OK;
+
+ /*
+ * Re allocate the HGlobal to fit the new size of the stream.
+ */
+ supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
+
+ if (supportHandle == 0)
+ return E_OUTOFMEMORY;
+
+ This->supportHandle = supportHandle;
+ This->streamSize.u.LowPart = libNewSize.u.LowPart;
+
+ return S_OK;
}
/***
@@ -534,49 +514,24 @@ static HRESULT WINAPI HGLOBALStreamImpl_Stat(
pstatstg->pwcsName = NULL;
pstatstg->type = STGTY_STREAM;
- pstatstg->cbSize.QuadPart = handle_getsize(This->handle);
+ pstatstg->cbSize = This->streamSize;
return S_OK;
}
-static const IStreamVtbl HGLOBALStreamImplVtbl;
-
-static HGLOBALStreamImpl *HGLOBALStreamImpl_Create(void)
-{
- HGLOBALStreamImpl *This;
-
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
- if (This)
- {
- This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
- This->ref = 1;
- }
- return This;
-}
-
static HRESULT WINAPI HGLOBALStreamImpl_Clone(
IStream* iface,
IStream** ppstm) /* [out] */
{
HGLOBALStreamImpl* This = impl_from_IStream(iface);
- HGLOBALStreamImpl* clone;
ULARGE_INTEGER dummy;
LARGE_INTEGER offset;
+ HRESULT hr;
- if (!ppstm) return E_INVALIDARG;
-
- *ppstm = NULL;
-
- TRACE(" Cloning %p (seek position=%d)\n", iface,
This->currentPosition.u.LowPart);
-
- clone = HGLOBALStreamImpl_Create();
- if (!clone) return E_OUTOFMEMORY;
-
- *ppstm = &clone->IStream_iface;
-
- handle_addref(This->handle);
- clone->handle = This->handle;
-
+ TRACE(" Cloning %p (deleteOnRelease=%d seek
position=%ld)\n",iface,This->deleteOnRelease,(long)This->currentPosition.QuadPart);
+ hr = CreateStreamOnHGlobal(This->supportHandle, FALSE, ppstm);
+ if(FAILED(hr))
+ return hr;
offset.QuadPart = (LONGLONG)This->currentPosition.QuadPart;
IStream_Seek(*ppstm, offset, STREAM_SEEK_SET, &dummy);
return S_OK;
@@ -613,19 +568,28 @@ HRESULT WINAPI CreateStreamOnHGlobal(
if (!ppstm)
return E_INVALIDARG;
- This = HGLOBALStreamImpl_Create();
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl));
if (!This) return E_OUTOFMEMORY;
- /* allocate a handle if one is not supplied */
- if (!hGlobal)
- hGlobal = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE, 0);
+ This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
+ This->ref = 1;
+
+ /* initialize the support */
+ This->supportHandle = hGlobal;
+ This->deleteOnRelease = fDeleteOnRelease;
- This->handle = handle_create(hGlobal, fDeleteOnRelease);
+ /* allocate a handle if one is not supplied */
+ if (!This->supportHandle)
+ This->supportHandle = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE, 0);
/* start at the beginning */
This->currentPosition.u.HighPart = 0;
This->currentPosition.u.LowPart = 0;
+ /* initialize the size of the stream to the size of the handle */
+ This->streamSize.u.HighPart = 0;
+ This->streamSize.u.LowPart = GlobalSize(This->supportHandle);
+
*ppstm = &This->IStream_iface;
return S_OK;
@@ -638,16 +602,16 @@ HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL*
phglobal)
{
HGLOBALStreamImpl* pStream;
- if (!pstm || !phglobal)
+ if (pstm == NULL)
return E_INVALIDARG;
- pStream = impl_from_IStream(pstm);
+ pStream = (HGLOBALStreamImpl*) pstm;
/*
* Verify that the stream object was created with CreateStreamOnHGlobal.
*/
if (pStream->IStream_iface.lpVtbl == &HGLOBALStreamImplVtbl)
- *phglobal = handle_gethglobal(pStream->handle);
+ *phglobal = pStream->supportHandle;
else
{
*phglobal = 0;
diff --git a/dll/win32/ole32/rpc.c b/dll/win32/ole32/rpc.c
index 985c622ac6..eb1bf5bb74 100644
--- a/dll/win32/ole32/rpc.c
+++ b/dll/win32/ole32/rpc.c
@@ -1474,16 +1474,17 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
else
{
BOOL joined = FALSE;
- if (!COM_CurrentInfo()->apt)
+ struct oletls *info = COM_CurrentInfo();
+
+ if (!info->apt)
{
- apartment_joinmta();
+ enter_apartment(info, COINIT_MULTITHREADED);
joined = TRUE;
}
RPC_ExecuteCall(params);
if (joined)
{
- apartment_release(COM_CurrentInfo()->apt);
- COM_CurrentInfo()->apt = NULL;
+ leave_apartment(info);
}
}
diff --git a/dll/win32/ole32/stg_prop.c b/dll/win32/ole32/stg_prop.c
index aca47c8cd4..a9308d68da 100644
--- a/dll/win32/ole32/stg_prop.c
+++ b/dll/win32/ole32/stg_prop.c
@@ -1004,18 +1004,15 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl
*This,
if (This->codePage != CP_UNICODE)
ptr[cbEntry - 1] = '\0';
else
- ((LPWSTR)ptr)[cbEntry - 1] = 0;
+ *((LPWSTR)ptr + cbEntry / sizeof(WCHAR)) = '\0';
hr = PropertyStorage_StoreNameWithId(This, (char*)ptr, This->codePage,
propid);
if (This->codePage == CP_UNICODE)
{
- /* cbEntry is the number of characters */
- cbEntry *= 2;
-
/* Unicode entries are padded to DWORD boundaries */
if (cbEntry % sizeof(DWORD))
ptr += sizeof(DWORD) - (cbEntry % sizeof(DWORD));
}
- ptr += cbEntry;
+ ptr += sizeof(DWORD) + cbEntry;
}
return hr;
}
@@ -1056,10 +1053,6 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop,
const BYTE *data,
prop->u.bVal = *data;
TRACE("Read byte 0x%x\n", prop->u.bVal);
break;
- case VT_BOOL:
- StorageUtl_ReadWord(data, 0, (WORD*)&prop->u.boolVal);
- TRACE("Read bool %d\n", prop->u.boolVal);
- break;
case VT_I2:
StorageUtl_ReadWord(data, 0, (WORD*)&prop->u.iVal);
TRACE("Read short %d\n", prop->u.iVal);
@@ -1078,18 +1071,6 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop,
const BYTE *data,
StorageUtl_ReadDWord(data, 0, &prop->u.ulVal);
TRACE("Read ulong %d\n", prop->u.ulVal);
break;
- case VT_I8:
- StorageUtl_ReadULargeInteger(data, 0, (ULARGE_INTEGER *)&prop->u.hVal);
- TRACE("Read long long %s\n",
wine_dbgstr_longlong(prop->u.hVal.QuadPart));
- break;
- case VT_UI8:
- StorageUtl_ReadULargeInteger(data, 0, &prop->u.uhVal);
- TRACE("Read ulong long %s\n",
wine_dbgstr_longlong(prop->u.uhVal.QuadPart));
- break;
- case VT_R8:
- memcpy(&prop->u.dblVal, data, sizeof(double));
- TRACE("Read double %f\n", prop->u.dblVal);
- break;
case VT_LPSTR:
{
DWORD count;
@@ -2383,9 +2364,7 @@ static HRESULT create_EnumSTATPROPSETSTG(
enumx = enumx_allocate(&IID_IEnumSTATPROPSETSTG,
&IEnumSTATPROPSETSTG_Vtbl,
- sizeof (STATPROPSETSTG),
- (IUnknown*)&This->base.IStorage_iface,
- NULL);
+ sizeof (STATPROPSETSTG));
/* add all the property set elements into a list */
r = IStorage_EnumElements(stg, 0, NULL, 0, &penum);
@@ -2478,27 +2457,6 @@ static HRESULT WINAPI IEnumSTATPROPSTG_fnClone(
return enumx_Clone((enumx_impl*)iface, (enumx_impl**)ppenum);
}
-static void prop_enum_copy_cb(IUnknown *parent, void *orig, void *dest)
-{
- PropertyStorage_impl *storage =
impl_from_IPropertyStorage((IPropertyStorage*)parent);
- STATPROPSTG *src_prop = orig;
- STATPROPSTG *dest_prop = dest;
- LPWSTR name;
-
- dest_prop->propid = src_prop->propid;
- dest_prop->vt = src_prop->vt;
- dest_prop->lpwstrName = NULL;
-
- if (dictionary_find(storage->propid_to_name, UlongToPtr(src_prop->propid),
(void**)&name))
- {
- DWORD size = (strlenW(name) + 1) * sizeof(WCHAR);
-
- dest_prop->lpwstrName = CoTaskMemAlloc(size);
- if (!dest_prop->lpwstrName) return;
- memcpy(dest_prop->lpwstrName, name, size);
- }
-}
-
static BOOL prop_enum_stat(const void *k, const void *v, void *extra, void *arg)
{
enumx_impl *enumx = arg;
@@ -2525,9 +2483,7 @@ static HRESULT create_EnumSTATPROPSTG(
enumx = enumx_allocate(&IID_IEnumSTATPROPSTG,
&IEnumSTATPROPSTG_Vtbl,
- sizeof (STATPROPSTG),
- (IUnknown*)&This->IPropertyStorage_iface,
- prop_enum_copy_cb);
+ sizeof (STATPROPSTG));
dictionary_enumerate(This->propid_to_prop, prop_enum_stat, enumx);
diff --git a/dll/win32/ole32/storage32.c b/dll/win32/ole32/storage32.c
index 6443197d93..6adf3c7c19 100644
--- a/dll/win32/ole32/storage32.c
+++ b/dll/win32/ole32/storage32.c
@@ -2067,7 +2067,7 @@ static HRESULT WINAPI StorageBaseImpl_SetClass(
HRESULT hRes;
DirEntry currentEntry;
- TRACE("(%p, %p)\n", iface, clsid);
+ TRACE("(%p, %s)\n", iface, wine_dbgstr_guid(clsid));
if (This->reverted)
return STG_E_REVERTED;
@@ -7249,6 +7249,8 @@ BlockChainStream* BlockChainStream_Construct(
BlockChainStream* newStream;
newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(BlockChainStream));
+ if(!newStream)
+ return NULL;
newStream->parentStorage = parentStorage;
newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder;
diff --git a/dll/win32/ole32/storage32.h b/dll/win32/ole32/storage32.h
index 51be7d4f86..4f692fe585 100644
--- a/dll/win32/ole32/storage32.h
+++ b/dll/win32/ole32/storage32.h
@@ -517,20 +517,25 @@ StgStreamImpl* StgStreamImpl_Construct(
/******************************************************************************
* Endian conversion macros
*/
-#undef htole32
-#undef htole16
-
#ifdef WORDS_BIGENDIAN
+#ifndef htole32
#define htole32(x) RtlUlongByteSwap(x)
+#endif
+#ifndef htole16
#define htole16(x) RtlUshortByteSwap(x)
+#endif
#define lendian32toh(x) RtlUlongByteSwap(x)
#define lendian16toh(x) RtlUshortByteSwap(x)
#else
+#ifndef htole32
#define htole32(x) (x)
+#endif
+#ifndef htole16
#define htole16(x) (x)
+#endif
#define lendian32toh(x) (x)
#define lendian16toh(x) (x)
diff --git a/dll/win32/ole32/usrmarshal.c b/dll/win32/ole32/usrmarshal.c
index 4de57fd818..9a56bd0933 100644
--- a/dll/win32/ole32/usrmarshal.c
+++ b/dll/win32/ole32/usrmarshal.c
@@ -80,11 +80,11 @@ static const char* debugstr_user_flags(ULONG *pFlags)
* the first parameter is an unsigned long.
* This function is only intended to be called by the RPC runtime.
*/
-ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG StartingSize, CLIPFORMAT *pCF)
+ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG size, CLIPFORMAT *pCF)
{
- ULONG size = StartingSize;
+ TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), size, pCF);
- TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pCF);
+ ALIGN_LENGTH(size, 3);
size += 8;
@@ -129,6 +129,8 @@ unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(ULONG *pFlags,
unsigned char *
{
TRACE("(%s, %p, &0x%04x\n", debugstr_user_flags(pFlags), pBuffer,
*pCF);
+ ALIGN_POINTER(pBuffer, 3);
+
/* only need to marshal the name if it is not a pre-defined type and
* we are going remote */
if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
@@ -191,6 +193,8 @@ unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(ULONG *pFlags,
unsigned char
TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pCF);
+ ALIGN_POINTER(pBuffer, 3);
+
fContext = *(DWORD *)pBuffer;
pBuffer += 4;
@@ -264,18 +268,23 @@ static ULONG handle_UserSize(ULONG *pFlags, ULONG StartingSize,
HANDLE *handle)
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
return StartingSize;
}
+
+ ALIGN_LENGTH(StartingSize, 3);
return StartingSize + sizeof(RemotableHandle);
}
static unsigned char * handle_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE
*handle)
{
- RemotableHandle *remhandle = (RemotableHandle *)pBuffer;
+ RemotableHandle *remhandle;
if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
{
ERR("can't remote a local handle\n");
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
return pBuffer;
}
+
+ ALIGN_POINTER(pBuffer, 3);
+ remhandle = (RemotableHandle *)pBuffer;
remhandle->fContext = WDT_INPROC_CALL;
remhandle->u.hInproc = (LONG_PTR)*handle;
return pBuffer + sizeof(RemotableHandle);
@@ -283,7 +292,10 @@ static unsigned char * handle_UserMarshal(ULONG *pFlags, unsigned
char *pBuffer,
static unsigned char * handle_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE
*handle)
{
- RemotableHandle *remhandle = (RemotableHandle *)pBuffer;
+ RemotableHandle *remhandle;
+
+ ALIGN_POINTER(pBuffer, 3);
+ remhandle = (RemotableHandle *)pBuffer;
if (remhandle->fContext != WDT_INPROC_CALL)
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
*handle = (HANDLE)(LONG_PTR)remhandle->u.hInproc;
@@ -566,10 +578,28 @@ void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
* the first parameter is a ULONG.
* This function is only intended to be called by the RPC runtime.
*/
-ULONG __RPC_USER HBITMAP_UserSize(ULONG *pFlags, ULONG StartingSize, HBITMAP *phBmp)
+ULONG __RPC_USER HBITMAP_UserSize(ULONG *flags, ULONG size, HBITMAP *bmp)
{
- FIXME(":stub\n");
- return StartingSize;
+ TRACE("(%s, %d, %p)\n", debugstr_user_flags(flags), size, *bmp);
+
+ ALIGN_LENGTH(size, 3);
+
+ size += sizeof(ULONG);
+ if (LOWORD(*flags) == MSHCTX_INPROC)
+ size += sizeof(ULONG);
+ else
+ {
+ size += sizeof(ULONG);
+
+ if (*bmp)
+ {
+ size += sizeof(ULONG);
+ size += FIELD_OFFSET(userBITMAP, cbSize);
+ size += GetBitmapBits(*bmp, 0, NULL);
+ }
+ }
+
+ return size;
}
/******************************************************************************
@@ -591,10 +621,45 @@ ULONG __RPC_USER HBITMAP_UserSize(ULONG *pFlags, ULONG StartingSize,
HBITMAP *ph
* the first parameter is a ULONG.
* This function is only intended to be called by the RPC runtime.
*/
-unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *pFlags, unsigned char *pBuffer,
HBITMAP *phBmp)
+unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *flags, unsigned char *buffer,
HBITMAP *bmp)
{
- FIXME(":stub\n");
- return pBuffer;
+ TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, *bmp);
+
+ ALIGN_POINTER(buffer, 3);
+
+ if (LOWORD(*flags) == MSHCTX_INPROC)
+ {
+ *(ULONG *)buffer = WDT_INPROC_CALL;
+ buffer += sizeof(ULONG);
+ *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
+ buffer += sizeof(ULONG);
+ }
+ else
+ {
+ *(ULONG *)buffer = WDT_REMOTE_CALL;
+ buffer += sizeof(ULONG);
+ *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
+ buffer += sizeof(ULONG);
+
+ if (*bmp)
+ {
+ static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
+ BITMAP bitmap;
+ ULONG bitmap_size;
+
+ bitmap_size = GetBitmapBits(*bmp, 0, NULL);
+ *(ULONG *)buffer = bitmap_size;
+ buffer += sizeof(ULONG);
+
+ GetObjectW(*bmp, sizeof(BITMAP), &bitmap);
+ memcpy(buffer, &bitmap, header_size);
+ buffer += header_size;
+
+ GetBitmapBits(*bmp, bitmap_size, buffer);
+ buffer += bitmap_size;
+ }
+ }
+ return buffer;
}
/******************************************************************************
@@ -616,10 +681,56 @@ unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *pFlags,
unsigned char *pBu
* the first parameter is an ULONG.
* This function is only intended to be called by the RPC runtime.
*/
-unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer,
HBITMAP *phBmp)
+unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *flags, unsigned char *buffer,
HBITMAP *bmp)
{
- FIXME(":stub\n");
- return pBuffer;
+ ULONG context;
+
+ TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, bmp);
+
+ ALIGN_POINTER(buffer, 3);
+
+ context = *(ULONG *)buffer;
+ buffer += sizeof(ULONG);
+
+ if (context == WDT_INPROC_CALL)
+ {
+ *bmp = *(HBITMAP *)buffer;
+ buffer += sizeof(*bmp);
+ }
+ else if (context == WDT_REMOTE_CALL)
+ {
+ ULONG handle = *(ULONG *)buffer;
+ buffer += sizeof(ULONG);
+
+ if (handle)
+ {
+ static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
+ BITMAP bitmap;
+ ULONG bitmap_size;
+ unsigned char *bits;
+
+ bitmap_size = *(ULONG *)buffer;
+ buffer += sizeof(ULONG);
+ bits = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
+
+ memcpy(&bitmap, buffer, header_size);
+ buffer += header_size;
+
+ memcpy(bits, buffer, bitmap_size);
+ buffer += bitmap_size;
+
+ bitmap.bmBits = bits;
+ *bmp = CreateBitmapIndirect(&bitmap);
+
+ HeapFree(GetProcessHeap(), 0, bits);
+ }
+ else
+ *bmp = NULL;
+ }
+ else
+ RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
+
+ return buffer;
}
/******************************************************************************
@@ -640,9 +751,12 @@ unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *pFlags,
unsigned char *p
* which the first parameter is a ULONG.
* This function is only intended to be called by the RPC runtime.
*/
-void __RPC_USER HBITMAP_UserFree(ULONG *pFlags, HBITMAP *phBmp)
+void __RPC_USER HBITMAP_UserFree(ULONG *flags, HBITMAP *bmp)
{
- FIXME(":stub\n");
+ TRACE("(%s, %p)\n", debugstr_user_flags(flags), *bmp);
+
+ if (LOWORD(*flags) != MSHCTX_INPROC)
+ DeleteObject(*bmp);
}
/******************************************************************************
@@ -963,11 +1077,11 @@ void __RPC_USER HMETAFILE_UserFree(ULONG *pFlags, HMETAFILE *phmf)
* the first parameter is a ULONG.
* This function is only intended to be called by the RPC runtime.
*/
-ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *pFlags, ULONG StartingSize, HENHMETAFILE
*phEmf)
+ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *pFlags, ULONG size, HENHMETAFILE *phEmf)
{
- ULONG size = StartingSize;
+ TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), size, *phEmf);
- TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, *phEmf);
+ ALIGN_LENGTH(size, 3);
size += sizeof(ULONG);
if (LOWORD(*pFlags) == MSHCTX_INPROC)
@@ -1012,6 +1126,8 @@ unsigned char * __RPC_USER HENHMETAFILE_UserMarshal(ULONG *pFlags,
unsigned char
{
TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phEmf);
+ ALIGN_POINTER(pBuffer, 3);
+
if (LOWORD(*pFlags) == MSHCTX_INPROC)
{
if (sizeof(*phEmf) == 8)
@@ -1070,6 +1186,8 @@ unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *pFlags,
unsigned ch
TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, phEmf);
+ ALIGN_POINTER(pBuffer, 3);
+
fContext = *(ULONG *)pBuffer;
pBuffer += sizeof(ULONG);
@@ -1155,11 +1273,11 @@ void __RPC_USER HENHMETAFILE_UserFree(ULONG *pFlags, HENHMETAFILE
*phEmf)
* the first parameter is a ULONG.
* This function is only intended to be called by the RPC runtime.
*/
-ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *pFlags, ULONG StartingSize, HMETAFILEPICT
*phMfp)
+ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *pFlags, ULONG size, HMETAFILEPICT *phMfp)
{
- ULONG size = StartingSize;
+ TRACE("(%s, %d, &%p)\n", debugstr_user_flags(pFlags), size, *phMfp);
- TRACE("(%s, %d, &%p)\n", debugstr_user_flags(pFlags), StartingSize,
*phMfp);
+ ALIGN_LENGTH(size, 3);
size += sizeof(ULONG);
@@ -1209,6 +1327,8 @@ unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal(ULONG *pFlags,
unsigned cha
{
TRACE("(%s, %p, &%p)\n", debugstr_user_flags(pFlags), pBuffer, *phMfp);
+ ALIGN_POINTER(pBuffer, 3);
+
if (LOWORD(*pFlags) == MSHCTX_INPROC)
{
if (sizeof(HMETAFILEPICT) == 8)
@@ -1272,6 +1392,8 @@ unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG
*pFlags, unsigned c
TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, phMfp);
+ ALIGN_POINTER(pBuffer, 3);
+
fContext = *(ULONG *)pBuffer;
pBuffer += sizeof(ULONG);
@@ -1602,9 +1724,7 @@ ULONG __RPC_USER STGMEDIUM_UserSize(ULONG *pFlags, ULONG
StartingSize, STGMEDIUM
case TYMED_GDI:
TRACE("TYMED_GDI\n");
if (pStgMedium->u.hBitmap)
- {
- FIXME("not implemented for GDI object %p\n",
pStgMedium->u.hBitmap);
- }
+ size = HBITMAP_UserSize(pFlags, size, &pStgMedium->u.hBitmap);
break;
case TYMED_MFPICT:
TRACE("TYMED_MFPICT\n");
@@ -1714,9 +1834,7 @@ unsigned char * __RPC_USER STGMEDIUM_UserMarshal(ULONG *pFlags,
unsigned char *p
case TYMED_GDI:
TRACE("TYMED_GDI\n");
if (pStgMedium->u.hBitmap)
- {
- FIXME("not implemented for GDI object %p\n",
pStgMedium->u.hBitmap);
- }
+ pBuffer = HBITMAP_UserMarshal(pFlags, pBuffer,
&pStgMedium->u.hBitmap);
break;
case TYMED_MFPICT:
TRACE("TYMED_MFPICT\n");
@@ -1852,9 +1970,7 @@ unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags,
unsigned char
case TYMED_GDI:
TRACE("TYMED_GDI\n");
if (content)
- {
- FIXME("not implemented for GDI object\n");
- }
+ pBuffer = HBITMAP_UserUnmarshal(pFlags, pBuffer,
&pStgMedium->u.hBitmap);
else
pStgMedium->u.hBitmap = NULL;
break;
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index 5cc918b237..4b324f3b1d 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -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.16
+reactos/dll/win32/ole32 # Synced to Wine-3.0
reactos/dll/win32/oleacc # Synced to WineStaging-2.9
reactos/dll/win32/oleaut32 # Synced to WineStaging-2.16
reactos/dll/win32/olecli32 # Synced to WineStaging-2.9