#include <winbase.h>
#include <winnls.h>
#include <wingdi.h>
+#include <winreg.h>
#include <ole2.h>
//#include "objbase.h"
//#include "shlguid.h"
#include <wine/test.h>
+#include "initguid.h"
+
+DEFINE_GUID(CLSID_Picture_Metafile,0x315,0,0,0xc0,0,0,0,0,0,0,0x46);
+DEFINE_GUID(CLSID_Picture_Dib,0x316,0,0,0xc0,0,0,0,0,0,0,0x46);
+
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
+#define DEFINE_EXPECT(func) \
+ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+
+#define SET_EXPECT(func) \
+ expect_ ## func = TRUE
+
+#define CHECK_EXPECT2(func) \
+ do { \
+ ok(expect_ ##func, "unexpected call " #func "\n"); \
+ called_ ## func = TRUE; \
+ }while(0)
+
+#define CHECK_EXPECT(func) \
+ do { \
+ CHECK_EXPECT2(func); \
+ expect_ ## func = FALSE; \
+ }while(0)
+
+#define CHECK_CALLED(func) \
+ do { \
+ ok(called_ ## func, "expected " #func "\n"); \
+ expect_ ## func = called_ ## func = FALSE; \
+ }while(0)
+
+DEFINE_EXPECT(Storage_Stat);
+DEFINE_EXPECT(Storage_OpenStream_CompObj);
+DEFINE_EXPECT(Storage_SetClass);
+DEFINE_EXPECT(Storage_CreateStream_CompObj);
+DEFINE_EXPECT(Storage_OpenStream_Ole);
+
static IPersistStorage OleObjectPersistStg;
static IOleCache *cache;
static IRunnableObject *runnable;
+static const CLSID CLSID_WineTestOld =
+{ /* 9474ba1a-258b-490b-bc13-516e9239acd0 */
+ 0x9474ba1a,
+ 0x258b,
+ 0x490b,
+ {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xd0}
+};
+
static const CLSID CLSID_WineTest =
{ /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
0x9474ba1a,
static BOOL g_showRunnable = TRUE;
static BOOL g_isRunning = TRUE;
-static BOOL g_failGetMiscStatus;
+static HRESULT g_GetMiscStatusFailsWith = S_OK;
static HRESULT g_QIFailsWith;
static UINT cf_test_1, cf_test_2, cf_test_3;
+/****************************************************************************
+ * PresentationDataHeader
+ *
+ * This structure represents the header of the \002OlePresXXX stream in
+ * the OLE object storage.
+ */
+typedef struct PresentationDataHeader
+{
+ /* clipformat:
+ * - standard clipformat:
+ * DWORD length = 0xffffffff;
+ * DWORD cfFormat;
+ * - or custom clipformat:
+ * DWORD length;
+ * CHAR format_name[length]; (null-terminated)
+ */
+ DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
+ DVASPECT dvAspect;
+ DWORD lindex;
+ DWORD tymed;
+ DWORD unknown7; /* 0 */
+ DWORD dwObjectExtentX;
+ DWORD dwObjectExtentY;
+ DWORD dwSize;
+} PresentationDataHeader;
+
#define CHECK_EXPECTED_METHOD(method_name) \
do { \
trace("%s\n", method_name); \
while (expected_method_list->flags & TEST_OPTIONAL && \
strcmp(expected_method_list->method, method_name) != 0) \
expected_method_list++; \
- if (expected_method_list->flags & TEST_TODO) \
- todo_wine \
- ok(!strcmp(expected_method_list->method, method_name), \
- "Expected %s to be called instead of %s\n", \
- expected_method_list->method, method_name); \
- else \
+ todo_wine_if (expected_method_list->flags & TEST_TODO) \
ok(!strcmp(expected_method_list->method, method_name), \
"Expected %s to be called instead of %s\n", \
expected_method_list->method, method_name); \
static HRESULT WINAPI OleObject_GetMiscStatus
(
IOleObject *iface,
- DWORD dwAspect,
+ DWORD aspect,
DWORD *pdwStatus
)
{
CHECK_EXPECTED_METHOD("OleObject_GetMiscStatus");
- if(!g_failGetMiscStatus)
+
+ ok(aspect == DVASPECT_CONTENT, "got aspect %d\n", aspect);
+
+ if (g_GetMiscStatusFailsWith == S_OK)
{
*pdwStatus = OLEMISC_RECOMPOSEONRESIZE;
return S_OK;
else
{
*pdwStatus = 0x1234;
- return E_FAIL;
+ return g_GetMiscStatusFailsWith;
}
}
static HRESULT WINAPI OleObjectPersistStg_QueryInterface(IPersistStorage *iface, REFIID riid, void **ppv)
{
trace("OleObjectPersistStg_QueryInterface\n");
- return IUnknown_QueryInterface((IUnknown *)&OleObject, riid, ppv);
+ return IOleObject_QueryInterface(&OleObject, riid, ppv);
}
static ULONG WINAPI OleObjectPersistStg_AddRef(IPersistStorage *iface)
static HRESULT WINAPI OleObjectCache_QueryInterface(IOleCache *iface, REFIID riid, void **ppv)
{
- return IUnknown_QueryInterface((IUnknown *)&OleObject, riid, ppv);
+ return IOleObject_QueryInterface(&OleObject, riid, ppv);
}
static ULONG WINAPI OleObjectCache_AddRef(IOleCache *iface)
static HRESULT WINAPI OleObjectCF_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID riid, void **ppv)
{
- return IUnknown_QueryInterface((IUnknown *)&OleObject, riid, ppv);
+ return IOleObject_QueryInterface(&OleObject, riid, ppv);
}
static HRESULT WINAPI OleObjectCF_LockServer(IClassFactory *iface, BOOL lock)
static HRESULT WINAPI OleObjectRunnable_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
{
- return IUnknown_QueryInterface((IUnknown *)&OleObject, riid, ppv);
+ return IOleObject_QueryInterface(&OleObject, riid, ppv);
}
static ULONG WINAPI OleObjectRunnable_AddRef(IRunnableObject *iface)
{ "OleObject_Release", TEST_OPTIONAL /* NT4 only */ },
{ NULL, 0 }
};
+ static const struct expected_method methods_olerender_draw_with_site[] =
+ {
+ { "OleObject_QueryInterface", 0 },
+ { "OleObject_AddRef", 0 },
+ { "OleObject_QueryInterface", 0 },
+ { "OleObject_AddRef", 0 },
+ { "OleObject_GetMiscStatus", 0 },
+ { "OleObject_QueryInterface", 0 },
+ { "OleObjectPersistStg_AddRef", 0 },
+ { "OleObjectPersistStg_InitNew", 0 },
+ { "OleObjectPersistStg_Release", 0 },
+ { "OleObject_SetClientSite", 0 },
+ { "OleObject_Release", 0 },
+ { "OleObject_QueryInterface", 0 },
+ { "OleObjectRunnable_AddRef", 0 },
+ { "OleObjectRunnable_Run", 0 },
+ { "OleObjectRunnable_Release", 0 },
+ { "OleObject_QueryInterface", 0 },
+ { "OleObjectCache_AddRef", 0 },
+ { "OleObjectCache_Cache", 0 },
+ { "OleObjectCache_Release", 0 },
+ { "OleObject_Release", 0 },
+ { NULL, 0 }
+ };
static const struct expected_method methods_olerender_format[] =
{
{ "OleObject_QueryInterface", 0 },
IOleObject_Release(pObject);
CHECK_NO_EXTRA_METHODS();
+ expected_method_list = methods_olerender_draw_with_site;
+ trace("OleCreate with OLERENDER_DRAW, with site:\n");
+ hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
+ ok_ole_success(hr, "OleCreate");
+ IOleObject_Release(pObject);
+ CHECK_NO_EXTRA_METHODS();
+
+ /* GetMiscStatus fails */
+ g_GetMiscStatusFailsWith = 0x8fafefaf;
+ expected_method_list = methods_olerender_draw_with_site;
+ trace("OleCreate with OLERENDER_DRAW, with site:\n");
+ hr = OleCreate(&CLSID_Equation3, &IID_IOleObject, OLERENDER_DRAW, NULL, (IOleClientSite*)0xdeadbeef, pStorage, (void **)&pObject);
+ ok_ole_success(hr, "OleCreate");
+ IOleObject_Release(pObject);
+ CHECK_NO_EXTRA_METHODS();
+ g_GetMiscStatusFailsWith = S_OK;
+
formatetc.cfFormat = CF_TEXT;
formatetc.ptd = NULL;
formatetc.dwAspect = DVASPECT_CONTENT;
{
HRESULT hr;
IOleObject *pObject;
+ DWORD fmt;
static const struct expected_method methods_oleload[] =
{
/* Test once with IOleObject_GetMiscStatus failing */
expected_method_list = methods_oleload;
- g_failGetMiscStatus = TRUE;
+ g_GetMiscStatusFailsWith = E_FAIL;
trace("OleLoad:\n");
hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
ok(hr == S_OK ||
IOleObject_Release(pObject);
CHECK_NO_EXTRA_METHODS();
}
+ g_GetMiscStatusFailsWith = S_OK;
/* Test again, let IOleObject_GetMiscStatus succeed. */
- g_failGetMiscStatus = FALSE;
expected_method_list = methods_oleload;
trace("OleLoad:\n");
hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject);
IOleObject_Release(pObject);
CHECK_NO_EXTRA_METHODS();
}
+
+ for (fmt = CF_TEXT; fmt < CF_MAX; fmt++)
+ {
+ static const WCHAR olrepres[] = { 2,'O','l','e','P','r','e','s','0','0','0',0 };
+ IStorage *stg;
+ IStream *stream;
+ IUnknown *obj;
+ DWORD data, i, tymed, data_size;
+ PresentationDataHeader header;
+ HDC hdc;
+ HGDIOBJ hobj;
+ RECT rc;
+ char buf[256];
+
+ for (i = 0; i < 7; i++)
+ {
+ hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
+ ok(hr == S_OK, "StgCreateDocfile error %#x\n", hr);
+
+ hr = IStorage_SetClass(stg, &CLSID_WineTest);
+ ok(hr == S_OK, "SetClass error %#x\n", hr);
+
+ hr = IStorage_CreateStream(stg, olrepres, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stream);
+ ok(hr == S_OK, "CreateStream error %#x\n", hr);
+
+ data = ~0;
+ hr = IStream_Write(stream, &data, sizeof(data), NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ data = fmt;
+ hr = IStream_Write(stream, &data, sizeof(data), NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ switch (fmt)
+ {
+ case CF_BITMAP:
+ /* FIXME: figure out stream format */
+ hobj = CreateBitmap(1, 1, 1, 1, NULL);
+ data_size = GetBitmapBits(hobj, sizeof(buf), buf);
+ DeleteObject(hobj);
+ break;
+
+ case CF_METAFILEPICT:
+ case CF_ENHMETAFILE:
+ hdc = CreateMetaFileA(NULL);
+ hobj = CloseMetaFile(hdc);
+ data_size = GetMetaFileBitsEx(hobj, sizeof(buf), buf);
+ DeleteMetaFile(hobj);
+ break;
+
+ default:
+ data_size = sizeof(buf);
+ memset(buf, 'A', sizeof(buf));
+ break;
+ }
+
+ tymed = 1 << i;
+
+ header.unknown3 = 4;
+ header.dvAspect = DVASPECT_CONTENT;
+ header.lindex = -1;
+ header.tymed = tymed;
+ header.unknown7 = 0;
+ header.dwObjectExtentX = 1;
+ header.dwObjectExtentY = 1;
+ header.dwSize = data_size;
+ hr = IStream_Write(stream, &header, sizeof(header), NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ hr = IStream_Write(stream, buf, data_size, NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ IStream_Release(stream);
+
+ hr = OleLoad(stg, &IID_IUnknown, NULL, (void **)&obj);
+ /* FIXME: figure out stream format */
+ if (fmt == CF_BITMAP && hr != S_OK)
+ {
+ IStorage_Release(stg);
+ continue;
+ }
+ ok(hr == S_OK, "OleLoad error %#x: cfFormat = %u, tymed = %u\n", hr, fmt, tymed);
+
+ hdc = CreateCompatibleDC(0);
+ SetRect(&rc, 0, 0, 100, 100);
+ hr = OleDraw(obj, DVASPECT_CONTENT, hdc, &rc);
+ DeleteDC(hdc);
+ if (fmt == CF_METAFILEPICT)
+ ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, tymed = %u\n", hr, fmt, tymed);
+ else if (fmt == CF_ENHMETAFILE)
+todo_wine
+ ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, tymed = %u\n", hr, fmt, tymed);
+ else
+ ok(hr == OLE_E_BLANK || hr == OLE_E_NOTRUNNING || hr == E_FAIL, "OleDraw should fail: %#x, cfFormat = %u, tymed = %u\n", hr, fmt, header.tymed);
+
+ IUnknown_Release(obj);
+ IStorage_Release(stg);
+ }
+ }
}
static BOOL STDMETHODCALLTYPE draw_continue(ULONG_PTR param)
static IDataObject DataObject = { &DataObjectVtbl };
+static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+ if (IsEqualIID(riid, &IID_IUnknown)) *ppv = iface;
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)*ppv);
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI Unknown_Release(IUnknown *iface)
+{
+ return 1;
+}
+
+static const IUnknownVtbl UnknownVtbl =
+{
+ Unknown_QueryInterface,
+ Unknown_AddRef,
+ Unknown_Release
+};
+
+static IUnknown unknown = { &UnknownVtbl };
+
+static void check_enum_cache(IOleCache2 *cache, STATDATA *expect, int num)
+{
+ IEnumSTATDATA *enum_stat;
+ STATDATA stat;
+ HRESULT hr;
+
+ hr = IOleCache2_EnumCache( cache, &enum_stat );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ while (IEnumSTATDATA_Next(enum_stat, 1, &stat, NULL) == S_OK)
+ {
+ ok( stat.formatetc.cfFormat == expect->formatetc.cfFormat, "got %d expect %d\n",
+ stat.formatetc.cfFormat, expect->formatetc.cfFormat );
+ ok( !stat.formatetc.ptd == !expect->formatetc.ptd, "got %p expect %p\n",
+ stat.formatetc.ptd, expect->formatetc.ptd );
+ ok( stat.formatetc.dwAspect == expect->formatetc.dwAspect, "got %d expect %d\n",
+ stat.formatetc.dwAspect, expect->formatetc.dwAspect );
+ ok( stat.formatetc.lindex == expect->formatetc.lindex, "got %d expect %d\n",
+ stat.formatetc.lindex, expect->formatetc.lindex );
+ ok( stat.formatetc.tymed == expect->formatetc.tymed, "got %d expect %d\n",
+ stat.formatetc.tymed, expect->formatetc.tymed );
+ ok( stat.advf == expect->advf, "got %d expect %d\n", stat.advf, expect->advf );
+ ok( stat.pAdvSink == 0, "got %p\n", stat.pAdvSink );
+ ok( stat.dwConnection == expect->dwConnection, "got %d expect %d\n", stat.dwConnection, expect->dwConnection );
+ num--;
+ expect++;
+ }
+
+ ok( num == 0, "incorrect number. num %d\n", num );
+
+ IEnumSTATDATA_Release( enum_stat );
+}
+
static void test_data_cache(void)
{
HRESULT hr;
IOleCache2 *pOleCache;
+ IOleCache *olecache;
IStorage *pStorage;
+ IUnknown *unk;
IPersistStorage *pPS;
IViewObject *pViewObject;
IOleCacheControl *pOleCacheControl;
{ NULL, 0 }
};
- GetSystemDirectory(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0]));
+ GetSystemDirectoryA(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0]));
expected_method_list = methods_cacheinitnew;
hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pStorage);
ok_ole_success(hr, "StgCreateDocfile");
+ /* aggregation */
+
+ /* requested is not IUnknown */
+ hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IOleCache2, (void**)&pOleCache);
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+ hr = CreateDataCache(&unknown, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(unk != (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
+ ok(unk != (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
+ IOleCache2_Release(pOleCache);
+ IOleCache_Release(olecache);
+ IUnknown_Release(unk);
+
+ hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void**)&unk);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&olecache);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IUnknown_QueryInterface(unk, &IID_IOleCache2, (void**)&pOleCache);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+todo_wine {
+ ok(unk == (IUnknown*)olecache, "got %p, expected %p\n", olecache, unk);
+ ok(unk == (IUnknown*)pOleCache, "got %p, expected %p\n", pOleCache, unk);
+}
+ IOleCache2_Release(pOleCache);
+ IOleCache_Release(olecache);
+ IUnknown_Release(unk);
+
/* Test with new data */
hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IOleCache2, (LPVOID *)&pOleCache);
fmtetc.cfFormat = CF_METAFILEPICT;
stgmedium.tymed = TYMED_MFPICT;
U(stgmedium).hMetaFilePict = OleMetafilePictFromIconAndLabel(
- LoadIcon(NULL, IDI_APPLICATION), wszPath, wszPath, 0);
+ LoadIconA(NULL, (LPSTR)IDI_APPLICATION), wszPath, wszPath, 0);
stgmedium.pUnkForRelease = NULL;
fmtetc.dwAspect = DVASPECT_CONTENT;
IStorage_Release(pStorage);
}
+
+static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
+
+/* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */
+static BYTE dib[] =
+{
+ 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
+
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00,
+ 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static IStorage *create_storage( int num )
+{
+ IStorage *stg;
+ IStream *stm;
+ HRESULT hr;
+ ULONG written;
+
+ hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg );
+ ok( hr == S_OK, "got %08x\n", hr);
+ hr = IStorage_SetClass( stg, &CLSID_Picture_Dib );
+ ok( hr == S_OK, "got %08x\n", hr);
+ hr = IStorage_CreateStream( stg, CONTENTS, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stm );
+ ok( hr == S_OK, "got %08x\n", hr);
+ if (num == 1) /* Set biXPelsPerMeter = 0 */
+ {
+ dib[0x26] = 0;
+ dib[0x27] = 0;
+ }
+ hr = IStream_Write( stm, dib, sizeof(dib), &written );
+ ok( hr == S_OK, "got %08x\n", hr);
+ IStream_Release( stm );
+ return stg;
+}
+
+static HGLOBAL create_dib( void )
+{
+ HGLOBAL h;
+ void *ptr;
+
+ h = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) - sizeof(BITMAPFILEHEADER) );
+ ptr = GlobalLock( h );
+ memcpy( ptr, dib + sizeof(BITMAPFILEHEADER), sizeof(dib) - sizeof(BITMAPFILEHEADER) );
+ GlobalUnlock( h );
+ return h;
+}
+
+static void test_data_cache_dib_contents_stream(int num)
+{
+ HRESULT hr;
+ IUnknown *unk;
+ IPersistStorage *persist;
+ IDataObject *data;
+ IViewObject2 *view;
+ IStorage *stg;
+ IOleCache2 *cache;
+ FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM med;
+ CLSID cls;
+ SIZEL sz;
+ BYTE *ptr;
+ BITMAPINFOHEADER expect_info;
+ STATDATA enum_expect[] =
+ {
+ {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 1 },
+ {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 1 },
+ };
+
+ hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void **)&unk );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ hr = IUnknown_QueryInterface( unk, &IID_IPersistStorage, (void **)&persist );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ hr = IUnknown_QueryInterface( unk, &IID_IDataObject, (void **)&data );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void **)&view );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ hr = IUnknown_QueryInterface( unk, &IID_IOleCache2, (void **)&cache );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+
+ stg = create_storage( num );
+
+ hr = IPersistStorage_Load( persist, stg );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ IStorage_Release( stg );
+
+ hr = IPersistStorage_GetClassID( persist, &cls );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ ok( IsEqualCLSID( &cls, &CLSID_Picture_Dib ), "class id mismatch\n" );
+
+ hr = IDataObject_GetData( data, &fmt, &med );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ ok( med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed );
+ ok( GlobalSize( U(med).hGlobal ) >= sizeof(dib) - sizeof(BITMAPFILEHEADER),
+ "got %lu\n", GlobalSize( U(med).hGlobal ) );
+ ptr = GlobalLock( U(med).hGlobal );
+
+ expect_info = *(BITMAPINFOHEADER *)(dib + sizeof(BITMAPFILEHEADER));
+ if (expect_info.biXPelsPerMeter == 0 || expect_info.biYPelsPerMeter == 0)
+ {
+ HDC hdc = GetDC( 0 );
+ expect_info.biXPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSX ), 10000, 254 );
+ expect_info.biYPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSY ), 10000, 254 );
+ ReleaseDC( 0, hdc );
+ }
+ ok( !memcmp( ptr, &expect_info, sizeof(expect_info) ), "mismatch\n" );
+ ok( !memcmp( ptr + sizeof(expect_info), dib + sizeof(BITMAPFILEHEADER) + sizeof(expect_info),
+ sizeof(dib) - sizeof(BITMAPFILEHEADER) - sizeof(expect_info) ), "mismatch\n" );
+ GlobalUnlock( U(med).hGlobal );
+ ReleaseStgMedium( &med );
+
+ check_enum_cache( cache, enum_expect, 2 );
+
+ hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz );
+ ok( SUCCEEDED(hr), "got %08x\n", hr );
+ if (num == 0)
+ {
+ ok( sz.cx == 1000, "got %d\n", sz.cx );
+ ok( sz.cy == 250, "got %d\n", sz.cy );
+ }
+ else
+ {
+ HDC hdc = GetDC( 0 );
+ LONG x = 2 * 2540 / GetDeviceCaps( hdc, LOGPIXELSX );
+ LONG y = 1 * 2540 / GetDeviceCaps( hdc, LOGPIXELSY );
+ ok( sz.cx == x, "got %d %d\n", sz.cx, x );
+ ok( sz.cy == y, "got %d %d\n", sz.cy, y );
+
+ ReleaseDC( 0, hdc );
+ }
+
+ IOleCache2_Release( cache );
+ IViewObject2_Release( view );
+ IDataObject_Release( data );
+ IPersistStorage_Release( persist );
+ IUnknown_Release( unk );
+}
+
+static void check_bitmap_size( HBITMAP h, int cx, int cy )
+{
+ BITMAP bm;
+
+ GetObjectW( h, sizeof(bm), &bm );
+ ok( bm.bmWidth == cx, "got %d expect %d\n", bm.bmWidth, cx );
+ ok( bm.bmHeight == cy, "got %d expect %d\n", bm.bmHeight, cy );
+}
+
+static void check_dib_size( HGLOBAL h, int cx, int cy )
+{
+ BITMAPINFO *info;
+
+ info = GlobalLock( h );
+ ok( info->bmiHeader.biWidth == cx, "got %d expect %d\n", info->bmiHeader.biWidth, cx );
+ ok( info->bmiHeader.biHeight == cy, "got %d expect %d\n", info->bmiHeader.biHeight, cy );
+ GlobalUnlock( h );
+}
+
+static void test_data_cache_bitmap(void)
+{
+ HRESULT hr;
+ IOleCache2 *cache;
+ IDataObject *data;
+ FORMATETC fmt;
+ DWORD conn;
+ STGMEDIUM med;
+ STATDATA expect[] =
+ {
+ {{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
+ {{ CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, 0, NULL, 0 },
+ {{ CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }, 0, NULL, 0 },
+ {{ CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }, 0, NULL, 0 }
+ };
+
+ hr = CreateDataCache( NULL, &CLSID_NULL, &IID_IOleCache2, (void **)&cache );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ /* create a dib entry which will also create a bitmap entry too */
+ fmt.cfFormat = CF_DIB;
+ fmt.ptd = NULL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.tymed = TYMED_HGLOBAL;
+
+ hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
+ ok( hr == S_OK, "got %08x\n", hr );
+ expect[0].dwConnection = conn;
+ expect[1].dwConnection = conn;
+
+ check_enum_cache( cache, expect, 2 );
+
+ /* now try to add a bitmap */
+ fmt.cfFormat = CF_BITMAP;
+ fmt.tymed = TYMED_GDI;
+
+ hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
+ ok( hr == CACHE_S_SAMECACHE, "got %08x\n", hr );
+
+ /* metafile */
+ fmt.cfFormat = CF_METAFILEPICT;
+ fmt.tymed = TYMED_MFPICT;
+
+ hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
+ ok( hr == S_OK, "got %08x\n", hr );
+ expect[2].dwConnection = conn;
+
+ check_enum_cache( cache, expect, 3);
+
+ /* enhmetafile */
+ fmt.cfFormat = CF_ENHMETAFILE;
+ fmt.tymed = TYMED_ENHMF;
+
+ hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
+ ok( hr == S_OK, "got %08x\n", hr );
+ expect[3].dwConnection = conn;
+
+ check_enum_cache( cache, expect, 4 );
+
+ /* uncache everything */
+ hr = IOleCache2_Uncache( cache, expect[3].dwConnection );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = IOleCache2_Uncache( cache, expect[2].dwConnection );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = IOleCache2_Uncache( cache, expect[0].dwConnection );
+ ok( hr == OLE_E_NOCONNECTION, "got %08x\n", hr );
+
+ check_enum_cache( cache, expect, 0 );
+
+ /* just create a bitmap entry which again adds both dib and bitmap */
+ fmt.cfFormat = CF_BITMAP;
+ fmt.tymed = TYMED_GDI;
+
+ hr = IOleCache2_Cache( cache, &fmt, 0, &conn );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ expect[0].dwConnection = conn;
+ expect[1].dwConnection = conn;
+
+ check_enum_cache( cache, expect, 2 );
+
+ /* Try setting a 1x1 bitmap */
+ hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ med.tymed = TYMED_GDI;
+ U(med).hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
+ med.pUnkForRelease = NULL;
+
+ hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = IDataObject_GetData( data, &fmt, &med );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
+ check_bitmap_size( U(med).hBitmap, 1, 1 );
+ ReleaseStgMedium( &med );
+
+ fmt.cfFormat = CF_DIB;
+ fmt.tymed = TYMED_HGLOBAL;
+ hr = IDataObject_GetData( data, &fmt, &med );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
+ check_dib_size( U(med).hGlobal, 1, 1 );
+ ReleaseStgMedium( &med );
+
+ /* Now set a 2x1 dib */
+ fmt.cfFormat = CF_DIB;
+ fmt.tymed = TYMED_HGLOBAL;
+ med.tymed = TYMED_HGLOBAL;
+ U(med).hGlobal = create_dib();
+
+ hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ fmt.cfFormat = CF_BITMAP;
+ fmt.tymed = TYMED_GDI;
+ hr = IDataObject_GetData( data, &fmt, &med );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
+ check_bitmap_size( U(med).hBitmap, 2, 1 );
+ ReleaseStgMedium( &med );
+
+ fmt.cfFormat = CF_DIB;
+ fmt.tymed = TYMED_HGLOBAL;
+ hr = IDataObject_GetData( data, &fmt, &med );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
+ check_dib_size( U(med).hGlobal, 2, 1 );
+ ReleaseStgMedium( &med );
+
+ IDataObject_Release( data );
+ IOleCache2_Release( cache );
+}
+
static void test_default_handler(void)
{
HRESULT hr;
fmtetc.lindex = -1;
fmtetc.tymed = TYMED_ENHMF;
hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
- todo_wine
ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
fmtetc.cfFormat = CF_TEXT;
fmtetc.lindex = -1;
fmtetc.tymed = TYMED_NULL;
hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
- todo_wine
ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
hr = IOleObject_QueryInterface(pObject, &IID_IRunnableObject, (void **)&pRunnableObject);
g_showRunnable = TRUE;
}
-static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+
+static HRESULT WINAPI OleRun_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv)
{
*ppv = NULL;
- if (IsEqualIID(riid, &IID_IUnknown)) *ppv = iface;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_IRunnableObject)) {
+ *ppv = iface;
+ }
+
if (*ppv)
{
IUnknown_AddRef((IUnknown *)*ppv);
return S_OK;
}
+
return E_NOINTERFACE;
}
-static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
+static ULONG WINAPI OleRun_AddRef(IRunnableObject *iface)
{
return 2;
}
-static ULONG WINAPI Unknown_Release(IUnknown *iface)
+static ULONG WINAPI OleRun_Release(IRunnableObject *iface)
{
return 1;
}
-static const IUnknownVtbl UnknownVtbl =
+static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid)
{
- Unknown_QueryInterface,
- Unknown_AddRef,
- Unknown_Release
+ ok(0, "unexpected\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI OleRun_Run(IRunnableObject *iface, LPBINDCTX ctx)
+{
+ ok(ctx == NULL, "got %p\n", ctx);
+ return 0xdeadc0de;
+}
+
+static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface)
+{
+ ok(0, "unexpected\n");
+ return FALSE;
+}
+
+static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock,
+ BOOL last_unlock_closes)
+{
+ ok(0, "unexpected\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained)
+{
+ ok(0, "unexpected\n");
+ return E_NOTIMPL;
+}
+
+static const IRunnableObjectVtbl oleruntestvtbl =
+{
+ OleRun_QueryInterface,
+ OleRun_AddRef,
+ OleRun_Release,
+ OleRun_GetRunningClass,
+ OleRun_Run,
+ OleRun_IsRunning,
+ OleRun_LockRunning,
+ OleRun_SetContainedObject
};
-static IUnknown unknown = { &UnknownVtbl };
+static IRunnableObject testrunnable = { &oleruntestvtbl };
static void test_OleRun(void)
{
HRESULT hr;
+ /* doesn't support IRunnableObject */
hr = OleRun(&unknown);
ok(hr == S_OK, "OleRun failed 0x%08x\n", hr);
+
+ hr = OleRun((IUnknown*)&testrunnable);
+ ok(hr == 0xdeadc0de, "got 0x%08x\n", hr);
}
static void test_OleLockRunning(void)
{
HRESULT hr;
- hr = OleLockRunning((LPUNKNOWN)&unknown, TRUE, FALSE);
+ hr = OleLockRunning(&unknown, TRUE, FALSE);
ok(hr == S_OK, "OleLockRunning failed 0x%08x\n", hr);
}
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
}
+static const WCHAR comp_objW[] = {1,'C','o','m','p','O','b','j',0};
+static IStream *comp_obj_stream;
+static IStream *ole_stream;
+
+static HRESULT WINAPI Storage_QueryInterface(IStorage *iface, REFIID riid, void **ppvObject)
+{
+ ok(0, "unexpected call to QueryInterface\n");
+ return E_NOTIMPL;
+}
+
+static ULONG WINAPI Storage_AddRef(IStorage *iface)
+{
+ ok(0, "unexpected call to AddRef\n");
+ return 2;
+}
+
+static ULONG WINAPI Storage_Release(IStorage *iface)
+{
+ ok(0, "unexpected call to Release\n");
+ return 1;
+}
+
+static HRESULT WINAPI Storage_CreateStream(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm)
+{
+ ULARGE_INTEGER size = {{0}};
+ LARGE_INTEGER pos = {{0}};
+ HRESULT hr;
+
+ CHECK_EXPECT(Storage_CreateStream_CompObj);
+ ok(!lstrcmpW(pwcsName, comp_objW), "pwcsName = %s\n", wine_dbgstr_w(pwcsName));
+ todo_wine ok(grfMode == (STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
+ ok(!reserved1, "reserved1 = %x\n", reserved1);
+ ok(!reserved2, "reserved2 = %x\n", reserved2);
+ ok(!!ppstm, "ppstm = NULL\n");
+
+ *ppstm = comp_obj_stream;
+ IStream_AddRef(comp_obj_stream);
+ hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
+ hr = IStream_SetSize(comp_obj_stream, size);
+ ok(hr == S_OK, "IStream_SetSize returned %x\n", hr);
+ return S_OK;
+}
+
+static HRESULT WINAPI Storage_OpenStream(IStorage *iface, LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm)
+{
+ static const WCHAR ole1W[] = {1,'O','l','e',0};
+
+ LARGE_INTEGER pos = {{0}};
+ HRESULT hr;
+
+ ok(!reserved1, "reserved1 = %p\n", reserved1);
+ ok(!reserved2, "reserved2 = %x\n", reserved2);
+ ok(!!ppstm, "ppstm = NULL\n");
+
+ if(!lstrcmpW(pwcsName, comp_objW)) {
+ CHECK_EXPECT2(Storage_OpenStream_CompObj);
+ ok(grfMode == STGM_SHARE_EXCLUSIVE, "grfMode = %x\n", grfMode);
+
+ *ppstm = comp_obj_stream;
+ IStream_AddRef(comp_obj_stream);
+ hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
+ return S_OK;
+ }else if(!lstrcmpW(pwcsName, ole1W)) {
+ CHECK_EXPECT(Storage_OpenStream_Ole);
+ ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode);
+
+ *ppstm = ole_stream;
+ IStream_AddRef(ole_stream);
+ hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
+ return S_OK;
+ }
+
+ ok(0, "unexpected call to OpenStream: %s\n", wine_dbgstr_w(pwcsName));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_CreateStorage(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg)
+{
+ ok(0, "unexpected call to CreateStorage\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_OpenStorage(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg)
+{
+ ok(0, "unexpected call to OpenStorage\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_CopyTo(IStorage *iface, DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest)
+{
+ ok(0, "unexpected call to CopyTo\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_MoveElementTo(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags)
+{
+ ok(0, "unexpected call to MoveElementTo\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_Commit(IStorage *iface, DWORD grfCommitFlags)
+{
+ ok(0, "unexpected call to Commit\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_Revert(IStorage *iface)
+{
+ ok(0, "unexpected call to Revert\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_EnumElements(IStorage *iface, DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum)
+{
+ ok(0, "unexpected call to EnumElements\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_DestroyElement(IStorage *iface, LPCOLESTR pwcsName)
+{
+ ok(0, "unexpected call to DestroyElement\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_RenameElement(IStorage *iface, LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName)
+{
+ ok(0, "unexpected call to RenameElement\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_SetElementTimes(IStorage *iface, LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime)
+{
+ ok(0, "unexpected call to SetElementTimes\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_SetClass(IStorage *iface, REFCLSID clsid)
+{
+ CHECK_EXPECT(Storage_SetClass);
+ ok(IsEqualIID(clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(clsid));
+ return S_OK;
+}
+
+static HRESULT WINAPI Storage_SetStateBits(IStorage *iface, DWORD grfStateBits, DWORD grfMask)
+{
+ ok(0, "unexpected call to SetStateBits\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Storage_Stat(IStorage *iface, STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ CHECK_EXPECT2(Storage_Stat);
+ ok(pstatstg != NULL, "pstatstg = NULL\n");
+ ok(grfStatFlag == STATFLAG_NONAME, "grfStatFlag = %x\n", grfStatFlag);
+
+ memset(pstatstg, 0, sizeof(STATSTG));
+ pstatstg->type = STGTY_STORAGE;
+ pstatstg->clsid = CLSID_WineTestOld;
+ return S_OK;
+}
+
+static IStorageVtbl StorageVtbl =
+{
+ Storage_QueryInterface,
+ Storage_AddRef,
+ Storage_Release,
+ Storage_CreateStream,
+ Storage_OpenStream,
+ Storage_CreateStorage,
+ Storage_OpenStorage,
+ Storage_CopyTo,
+ Storage_MoveElementTo,
+ Storage_Commit,
+ Storage_Revert,
+ Storage_EnumElements,
+ Storage_DestroyElement,
+ Storage_RenameElement,
+ Storage_SetElementTimes,
+ Storage_SetClass,
+ Storage_SetStateBits,
+ Storage_Stat
+};
+
+static IStorage Storage = { &StorageVtbl };
+
+static void test_OleDoAutoConvert(void)
+{
+ static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
+ static struct {
+ DWORD reserved1;
+ DWORD version;
+ DWORD reserved2[5];
+ DWORD ansi_user_type_len;
+ DWORD ansi_clipboard_format_len;
+ DWORD reserved3;
+ DWORD unicode_marker;
+ DWORD unicode_user_type_len;
+ DWORD unicode_clipboard_format_len;
+ DWORD reserved4;
+ } comp_obj_data;
+ static struct {
+ DWORD version;
+ DWORD flags;
+ DWORD link_update_option;
+ DWORD reserved1;
+ DWORD reserved_moniker_stream_size;
+ DWORD relative_source_moniker_stream_size;
+ DWORD absolute_source_moniker_stream_size;
+ DWORD clsid_indicator;
+ CLSID clsid;
+ DWORD reserved_display_name;
+ DWORD reserved2;
+ DWORD local_update_time;
+ DWORD local_check_update_time;
+ DWORD remote_update_time;
+ } ole_data;
+
+ LARGE_INTEGER pos = {{0}};
+ WCHAR buf[39+6];
+ DWORD i, ret;
+ HKEY root;
+ CLSID clsid;
+ HRESULT hr;
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &comp_obj_stream);
+ ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
+ hr = IStream_Write(comp_obj_stream, (char*)&comp_obj_data, sizeof(comp_obj_data), NULL);
+ ok(hr == S_OK, "IStream_Write returned %x\n", hr);
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &ole_stream);
+ ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr);
+ hr = IStream_Write(ole_stream, (char*)&ole_data, sizeof(ole_data), NULL);
+ ok(hr == S_OK, "IStream_Write returned %x\n", hr);
+
+ clsid = IID_WineTest;
+ hr = OleDoAutoConvert(NULL, &clsid);
+ ok(hr == E_INVALIDARG, "OleDoAutoConvert returned %x\n", hr);
+ ok(IsEqualIID(&clsid, &IID_NULL), "clsid = %s\n", wine_dbgstr_guid(&clsid));
+
+ if(0) /* crashes on Win7 */
+ OleDoAutoConvert(&Storage, NULL);
+
+ clsid = IID_WineTest;
+ SET_EXPECT(Storage_Stat);
+ hr = OleDoAutoConvert(&Storage, &clsid);
+ ok(hr == REGDB_E_CLASSNOTREG, "OleDoAutoConvert returned %x\n", hr);
+ CHECK_CALLED(Storage_Stat);
+ ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
+
+ lstrcpyW(buf, clsidW);
+ StringFromGUID2(&CLSID_WineTestOld, buf+6, 39);
+
+ ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL);
+ if(ret != ERROR_SUCCESS) {
+ win_skip("not enough permissions to create CLSID key (%u)\n", ret);
+ return;
+ }
+
+ clsid = IID_WineTest;
+ SET_EXPECT(Storage_Stat);
+ hr = OleDoAutoConvert(&Storage, &clsid);
+ ok(hr == REGDB_E_KEYMISSING, "OleDoAutoConvert returned %x\n", hr);
+ CHECK_CALLED(Storage_Stat);
+ ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid));
+
+ hr = OleSetAutoConvert(&CLSID_WineTestOld, &CLSID_WineTest);
+ ok_ole_success(hr, "OleSetAutoConvert");
+
+ hr = OleGetAutoConvert(&CLSID_WineTestOld, &clsid);
+ ok_ole_success(hr, "OleGetAutoConvert");
+ ok(IsEqualIID(&clsid, &CLSID_WineTest), "incorrect clsid: %s\n", wine_dbgstr_guid(&clsid));
+
+ clsid = IID_WineTest;
+ SET_EXPECT(Storage_Stat);
+ SET_EXPECT(Storage_OpenStream_CompObj);
+ SET_EXPECT(Storage_SetClass);
+ SET_EXPECT(Storage_CreateStream_CompObj);
+ SET_EXPECT(Storage_OpenStream_Ole);
+ hr = OleDoAutoConvert(&Storage, &clsid);
+ ok(hr == S_OK, "OleDoAutoConvert returned %x\n", hr);
+ CHECK_CALLED(Storage_Stat);
+ CHECK_CALLED(Storage_OpenStream_CompObj);
+ CHECK_CALLED(Storage_SetClass);
+ CHECK_CALLED(Storage_CreateStream_CompObj);
+ CHECK_CALLED(Storage_OpenStream_Ole);
+ ok(IsEqualIID(&clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(&clsid));
+
+ hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
+ hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
+ ok(hr == S_OK, "IStream_Read returned %x\n", hr);
+ ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
+ ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
+ ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
+ ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
+ ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
+ ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
+ ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
+ ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
+ ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
+ ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
+ ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
+
+ hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
+ hr = IStream_Read(ole_stream, &ole_data, sizeof(ole_data), NULL);
+ ok(hr == S_OK, "IStream_Read returned %x\n", hr);
+ ok(ole_data.version == 0, "version = %x\n", ole_data.version);
+ ok(ole_data.flags == 4, "flags = %x\n", ole_data.flags);
+ for(i=2; i<sizeof(ole_data)/sizeof(DWORD); i++)
+ ok(((DWORD*)&ole_data)[i] == 0, "ole_data[%d] = %x\n", i, ((DWORD*)&ole_data)[i]);
+
+ SET_EXPECT(Storage_OpenStream_Ole);
+ hr = SetConvertStg(&Storage, TRUE);
+ ok(hr == S_OK, "SetConvertStg returned %x\n", hr);
+ CHECK_CALLED(Storage_OpenStream_Ole);
+
+ SET_EXPECT(Storage_OpenStream_CompObj);
+ SET_EXPECT(Storage_Stat);
+ SET_EXPECT(Storage_CreateStream_CompObj);
+ hr = WriteFmtUserTypeStg(&Storage, 0, NULL);
+ ok(hr == S_OK, "WriteFmtUserTypeStg returned %x\n", hr);
+ todo_wine CHECK_CALLED(Storage_OpenStream_CompObj);
+ CHECK_CALLED(Storage_Stat);
+ CHECK_CALLED(Storage_CreateStream_CompObj);
+ hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek returned %x\n", hr);
+ hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL);
+ ok(hr == S_OK, "IStream_Read returned %x\n", hr);
+ ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1);
+ ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version);
+ ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]);
+ ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1)));
+ ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len);
+ ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len);
+ ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3);
+ ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker);
+ ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len);
+ ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len);
+ ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4);
+
+ ret = IStream_Release(comp_obj_stream);
+ ok(!ret, "comp_obj_stream was not freed\n");
+ ret = IStream_Release(ole_stream);
+ ok(!ret, "ole_stream was not freed\n");
+
+ ret = RegDeleteKeyA(root, "AutoConvertTo");
+ ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
+ ret = RegDeleteKeyA(root, "");
+ ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
+ RegCloseKey(root);
+}
+
START_TEST(ole2)
{
DWORD dwRegister;
ok_ole_success(hr, "CoRevokeClassObject");
test_data_cache();
+ test_data_cache_dib_contents_stream( 0 );
+ test_data_cache_dib_contents_stream( 1 );
+ test_data_cache_bitmap();
test_default_handler();
test_runnable();
test_OleRun();
test_OleLockRunning();
test_OleDraw();
+ test_OleDoAutoConvert();
CoUninitialize();
}