diff --git a/dll/win32/ole32/compobj.c b/dll/win32/ole32/compobj.c index cdadd0f349a..fd912d4e739 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 672b39460b5..c1739f57e96 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 8c3fe48e528..e3697761e09 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,16 +760,240 @@ 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', + 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 save_dib(DataCacheEntry *entry, BOOL contents, IStream *stream) +{ + HRESULT hr = S_OK; + int data_size = 0; + BITMAPINFO *bmi = NULL; + + if (entry->stgmedium.tymed != TYMED_NULL) + { + data_size = GlobalSize(entry->stgmedium.u.hGlobal); + bmi = GlobalLock(entry->stgmedium.u.hGlobal); + } + + if (!contents) + { + PresentationDataHeader header; + + init_stream_header(entry, &header); + hr = write_clipformat(stream, entry->fmtetc.cfFormat); + if (FAILED(hr)) goto end; + if (data_size) + { + header.dwSize = data_size; + /* Size in units of 0.01mm (ie. MM_HIMETRIC) */ + if (bmi->bmiHeader.biXPelsPerMeter != 0 && bmi->bmiHeader.biYPelsPerMeter != 0) + { + 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); + } + } + hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL); + if (hr == S_OK && data_size) + hr = IStream_Write(stream, bmi, data_size, NULL); + } + else if(data_size) + { + 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); + } + +end: + if (bmi) GlobalUnlock(entry->stgmedium.u.hGlobal); + return hr; +} + +#include +struct meta_placeable +{ + DWORD key; + WORD hwmf; + WORD bounding_box[4]; + WORD inch; + DWORD reserved; + WORD checksum; +}; +#include + +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) + { + 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) + { + 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) + { + GlobalUnlock(entry->stgmedium.u.hMetaFilePict); + return E_OUTOFMEMORY; + } + GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data); + GlobalUnlock(entry->stgmedium.u.hMetaFilePict); + } + 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; + + 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); + } + + 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; - /* FIXME: cache the created stream in This? */ - return IStorage_CreateStream(storage, wszName, + if (contents) + name = CONTENTS; + else + name = pres; + + return IStorage_CreateStream(storage, name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, stream); } @@ -773,95 +1001,32 @@ static HRESULT DataCacheEntry_CreateStream(DataCacheEntry *cache_entry, static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage, BOOL same_as_load) { - PresentationDataHeader header; HRESULT hr; - IStream *pres_stream; - void *data = NULL; + 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 = DataCacheEntry_CreateStream(cache_entry, storage, &pres_stream); + hr = create_stream(cache_entry, storage, contents, &stream); if (FAILED(hr)) return hr; - hr = write_clipformat(pres_stream, cache_entry->data_cf); - if (FAILED(hr)) - return hr; - - 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) + switch (cache_entry->fmtetc.cfFormat) { - case CF_METAFILEPICT: - { - if (cache_entry->stgmedium.tymed != TYMED_NULL) - { - 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); - } - break; - } - default: - break; + 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); } - /* - * Write the header. - */ - hr = IStream_Write(pres_stream, &header, sizeof(PresentationDataHeader), - NULL); - if (FAILED(hr)) - { - IStream_Release(pres_stream); - return hr; - } - - /* get the data */ - switch (cache_entry->data_cf) - { - case CF_METAFILEPICT: - { - if (cache_entry->stgmedium.tymed != TYMED_NULL) - { - 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); - } - break; - } - default: - break; - } - - if (data) - hr = IStream_Write(pres_stream, data, header.dwSize, NULL); - HeapFree(GetProcessHeap(), 0, data); - - IStream_Release(pres_stream); + 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 3af0cd19ffa..7399a0214e4 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 6f784e140a3..d4347d9e335 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 6a82b716f19..732e6c6c81a 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; - num_bytes = handle_read(This->handle, &This->currentPosition.u.LowPart, pv, cb); - if (pcbRead) *pcbRead = num_bytes; + 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); + + /* + * 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; - return (num_bytes < cb) ? E_OUTOFMEMORY : S_OK; + 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); + + /* + * 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; - This->handle = handle_create(hGlobal, fDeleteOnRelease); + /* initialize the support */ + This->supportHandle = hGlobal; + This->deleteOnRelease = 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 985c622ac67..eb1bf5bb746 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 aca47c8cd4d..a9308d68da3 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 6443197d939..6adf3c7c19d 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 51be7d4f86c..4f692fe5856 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 4de57fd8184..9a56bd09332 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 5cc918b237c..4b324f3b1da 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