mirror of
https://github.com/reactos/reactos.git
synced 2025-04-04 04:26:32 +00:00
[OLE32] Sync with Wine 3.0. CORE-14225
This commit is contained in:
parent
d4c87f7aa8
commit
2178977b54
12 changed files with 828 additions and 524 deletions
|
@ -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.
|
||||
|
|
|
@ -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 *) */
|
||||
|
|
|
@ -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 <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)
|
||||
{
|
||||
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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue