[2/3] ole32/tests: Add a test for IOleCache storage contents created by IPersistStorage_Save(). (v2)
Dmitry Timoshkov
dmitry at baikal.ru
Thu Oct 19 20:58:57 CDT 2017
v2: Call IPersistStorage_Save() directly instead of OleSave().
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
dlls/ole32/tests/ole2.c | 402 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 402 insertions(+)
diff --git a/dlls/ole32/tests/ole2.c b/dlls/ole32/tests/ole2.c
index 0773bbf189..9ed19f1f9b 100644
--- a/dlls/ole32/tests/ole2.c
+++ b/dlls/ole32/tests/ole2.c
@@ -3315,6 +3315,407 @@ todo_wine
IOleCache2_Release(cache);
}
+#define MAX_STREAM 16
+
+struct stream_def
+{
+ const char *name;
+ int cf;
+ DVASPECT dvAspect;
+ ADVF advf;
+ const void *data;
+ size_t data_size;
+};
+
+struct storage_def
+{
+ const CLSID *clsid;
+ int stream_count;
+ struct stream_def stream[MAX_STREAM];
+};
+
+static const struct storage_def stg_def_0 =
+{
+ &CLSID_NULL, 1,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
+};
+static const struct storage_def stg_def_0_saved =
+{
+ &CLSID_NULL, 0, {{ 0 }}
+};
+static const struct storage_def stg_def_1 =
+{
+ &CLSID_NULL, 2,
+ {{ "Contents", -1, 0, 0, NULL, 0 },
+ { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_1_saved =
+{
+ &CLSID_NULL, 1,
+ {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_2 =
+{
+ &CLSID_ManualResetEvent, 2,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
+ { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_2_saved =
+{
+ &CLSID_NULL, 1,
+ {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_3 =
+{
+ &CLSID_NULL, 5,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
+ { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
+ { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
+ { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
+ { "MyStream", -1, 0, 0, "Hello World!", 13 }}
+};
+static const struct storage_def stg_def_3_saved =
+{
+ &CLSID_NULL, 3,
+ {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
+ { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
+ { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) }}
+};
+static const struct storage_def stg_def_4 =
+{
+ &CLSID_Picture_EnhMetafile, 5,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
+ { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
+ { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
+ { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
+ { "MyStream", -1, 0, 0, "Hello World!", 13 }}
+};
+static const struct storage_def stg_def_4_saved =
+{
+ &CLSID_NULL, 1,
+ {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_5 =
+{
+ &CLSID_Picture_Dib, 5,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
+ { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
+ { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
+ { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
+ { "MyStream", -1, 0, 0, "Hello World!", 13 }}
+};
+static const struct storage_def stg_def_5_saved =
+{
+ &CLSID_NULL, 1,
+ {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_6 =
+{
+ &CLSID_Picture_Metafile, 5,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) },
+ { "\2OlePres001", CF_METAFILEPICT, DVASPECT_CONTENT, ADVF_PRIMEFIRST, mf_blank_bits, sizeof(mf_blank_bits) },
+ { "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 },
+ { "\2OlePres002", CF_DIB, DVASPECT_CONTENT, ADVF_PRIMEFIRST, bmpimage, sizeof(bmpimage) },
+ { "MyStream", -1, 0, 0, "Hello World!", 13 }}
+};
+static const struct storage_def stg_def_6_saved =
+{
+ &CLSID_NULL, 1,
+ {{ "\2OlePres000", 0, DVASPECT_ICON, ADVF_PRIMEFIRST | ADVF_ONLYONCE, NULL, 0 }}
+};
+static const struct storage_def stg_def_7 =
+{
+ &CLSID_Picture_Dib, 1,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
+};
+static const struct storage_def stg_def_7_saved =
+{
+ &CLSID_NULL, 0, {{ 0 }}
+};
+static const struct storage_def stg_def_8 =
+{
+ &CLSID_Picture_Metafile, 1,
+ {{ "Contents", -1, 0, 0, mf_blank_bits, sizeof(mf_blank_bits) }}
+};
+static const struct storage_def stg_def_8_saved =
+{
+ &CLSID_NULL, 0, {{ 0 }}
+};
+static const struct storage_def stg_def_9 =
+{
+ &CLSID_Picture_EnhMetafile, 1,
+ {{ "Contents", -1, 0, 0, bmpimage, sizeof(bmpimage) }}
+};
+static const struct storage_def stg_def_9_saved =
+{
+ &CLSID_NULL, 0, {{ 0 }}
+};
+
+static int read_clipformat(IStream *stream)
+{
+ HRESULT hr;
+ ULONG bytes;
+ int length, clipformat = -2;
+
+ hr = IStream_Read(stream, &length, sizeof(length), &bytes);
+ if (hr != S_OK || bytes != sizeof(length))
+ return -2;
+ if (length == 0)
+ return 0;
+ if (length == -1)
+ {
+ hr = IStream_Read(stream, &clipformat, sizeof(clipformat), &bytes);
+ if (hr != S_OK || bytes != sizeof(clipformat))
+ return -2;
+ }
+ else
+ ok(0, "unhandled clipformat length %d\n", length);
+
+ return clipformat;
+}
+
+static void check_storage_contents(IStorage *stg, const struct storage_def *stg_def,
+ int *enumerated_streams, int *matched_streams)
+{
+ HRESULT hr;
+ IEnumSTATSTG *enumstg;
+ IStream *stream;
+ STATSTG stat;
+ int i, seen_stream[MAX_STREAM] = { 0 };
+
+ if (winetest_debug > 1)
+ trace("check_storage_contents:\n=============================================\n");
+
+ *enumerated_streams = 0;
+ *matched_streams = 0;
+
+ hr = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+todo_wine_if(!IsEqualCLSID(stg_def->clsid, &stat.clsid))
+ ok(IsEqualCLSID(stg_def->clsid, &stat.clsid), "expected %s, got %s\n",
+ wine_dbgstr_guid(stg_def->clsid), wine_dbgstr_guid(&stat.clsid));
+
+ hr = IStorage_EnumElements(stg, 0, NULL, 0, &enumstg);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ for (;;)
+ {
+ ULONG bytes;
+ int clipformat = -1;
+ PresentationDataHeader header;
+ char name[32];
+ BYTE data[256];
+
+ memset(&header, 0, sizeof(header));
+
+ hr = IEnumSTATSTG_Next(enumstg, 1, &stat, NULL);
+ if(hr == S_FALSE) break;
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ if (winetest_debug > 1)
+ trace("name %s, type %u, size %d, clsid %s\n",
+ wine_dbgstr_w(stat.pwcsName), stat.type, stat.cbSize.u.LowPart, wine_dbgstr_guid(&stat.clsid));
+
+ ok(stat.type == STGTY_STREAM, "unexpected %#x\n", stat.type);
+
+ WideCharToMultiByte(CP_ACP, 0, stat.pwcsName, -1, name, sizeof(name), NULL, NULL);
+
+ hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ if (!memcmp(name, "\2OlePres", 7))
+ {
+ clipformat = read_clipformat(stream);
+
+ hr = IStream_Read(stream, &header, sizeof(header), &bytes);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+ ok(bytes >= 24, "read %u bytes, expected to read %u bytes\n", bytes, sizeof(header));
+
+ if (winetest_debug > 1)
+ trace("header: unknown3 %#x, dvAspect %#x, lindex %#x, advf %#x, unknown7 %#x, dwObjectExtentX %#x, dwObjectExtentY %#x, dwSize %#x\n",
+ header.unknown3, header.dvAspect, header.lindex, header.advf, header.unknown7,
+ header.dwObjectExtentX, header.dwObjectExtentY, header.dwSize);
+ }
+
+ memset(data, 0, sizeof(data));
+ hr = IStream_Read(stream, data, sizeof(data), &bytes);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+ if (winetest_debug > 1)
+ trace("stream data (%u bytes): %02x %02x %02x %02x\n", bytes, data[0], data[1], data[2], data[3]);
+
+ for (i = 0; i < stg_def->stream_count; i++)
+ {
+ if (seen_stream[i]) continue;
+
+ if (winetest_debug > 1)
+ trace("%s/%s, %d/%d, %d/%d, %d/%d\n",
+ stg_def->stream[i].name, name,
+ stg_def->stream[i].cf, clipformat,
+ stg_def->stream[i].dvAspect, header.dvAspect,
+ stg_def->stream[i].advf, header.advf);
+
+ if (!strcmp(stg_def->stream[i].name, name) &&
+ stg_def->stream[i].cf == clipformat &&
+ stg_def->stream[i].dvAspect == header.dvAspect &&
+ stg_def->stream[i].advf == header.advf &&
+ stg_def->stream[i].data_size <= bytes &&
+ (!stg_def->stream[i].data_size ||
+ (!memcmp(stg_def->stream[i].data, data, min(stg_def->stream[i].data_size, bytes)))))
+ {
+ if (winetest_debug > 1)
+ trace("stream %d matches def stream %d\n", *enumerated_streams, i);
+ seen_stream[i] = 1;
+ *matched_streams += 1;
+ }
+ }
+
+ CoTaskMemFree(stat.pwcsName);
+ IStream_Release(stream);
+
+ *enumerated_streams += 1;
+ }
+}
+
+static IStorage *create_storage_from_def(const struct storage_def *stg_def)
+{
+ HRESULT hr;
+ IStorage *stg;
+ IStream *stm;
+ int i;
+
+ hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ hr = IStorage_SetClass(stg, stg_def->clsid);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ for (i = 0; i < stg_def->stream_count; i++)
+ {
+ WCHAR name[32];
+
+ MultiByteToWideChar(CP_ACP, 0, stg_def->stream[i].name, -1, name, 32);
+ hr = IStorage_CreateStream(stg, name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ if (stg_def->stream[i].cf != -1)
+ {
+ int clipformat[2];
+ PresentationDataHeader hdr;
+
+ if (stg_def->stream[i].cf)
+ {
+ clipformat[0] = -1;
+ clipformat[1] = stg_def->stream[i].cf;
+ hr = IStream_Write(stm, clipformat, sizeof(clipformat), NULL);
+ }
+ else
+ {
+ clipformat[0] = 0;
+ hr = IStream_Write(stm, &clipformat[0], sizeof(clipformat[0]), NULL);
+ }
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ hdr.unknown3 = 4;
+ hdr.dvAspect = stg_def->stream[i].dvAspect;
+ hdr.lindex = -1;
+ hdr.advf = stg_def->stream[i].advf;
+ hdr.unknown7 = 0;
+ hdr.dwObjectExtentX = 0;
+ hdr.dwObjectExtentY = 0;
+ hdr.dwSize = stg_def->stream[i].data_size;
+ hr = IStream_Write(stm, &hdr, sizeof(hdr), NULL);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+ }
+
+ if (stg_def->stream[i].data_size)
+ {
+ hr = IStream_Write(stm, stg_def->stream[i].data, stg_def->stream[i].data_size, NULL);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+ }
+
+ IStream_Release(stm);
+ }
+
+ return stg;
+}
+
+static void test_data_cache_contents(void)
+{
+ HRESULT hr;
+ IStorage *doc1, *doc2;
+ IOleCache2 *cache;
+ IPersistStorage *stg;
+ int i, enumerated_streams, matched_streams;
+ static const struct
+ {
+ const struct storage_def *in;
+ const struct storage_def *out;
+ } test_data[] =
+ {
+ { &stg_def_0, &stg_def_0_saved },
+ { &stg_def_1, &stg_def_1_saved },
+ { &stg_def_2, &stg_def_2_saved },
+ { &stg_def_3, &stg_def_3_saved },
+ { &stg_def_4, &stg_def_4_saved },
+ { &stg_def_5, &stg_def_5_saved },
+ { &stg_def_6, &stg_def_6_saved },
+ { &stg_def_7, &stg_def_7_saved },
+ { &stg_def_8, &stg_def_8_saved },
+ { &stg_def_9, &stg_def_9_saved },
+ };
+
+ for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
+ {
+ if (winetest_debug > 1)
+ trace("start testing storage def %d\n", i);
+
+ doc1 = create_storage_from_def(test_data[i].in);
+ if (!doc1) continue;
+
+ enumerated_streams = matched_streams = -1;
+ check_storage_contents(doc1, test_data[i].in, &enumerated_streams, &matched_streams);
+ ok(enumerated_streams == matched_streams, "%d in: enumerated %d != matched %d\n", i,
+ enumerated_streams, matched_streams);
+ ok(enumerated_streams == test_data[i].in->stream_count, "%d: created %d != def streams %d\n", i,
+ enumerated_streams, test_data[i].in->stream_count);
+
+ hr = CreateDataCache(NULL, &CLSID_NULL, &IID_IUnknown, (void **)&cache);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+ hr = IOleCache2_QueryInterface(cache, &IID_IPersistStorage, (void **)&stg);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+ hr = IPersistStorage_Load(stg, doc1);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ IStorage_Release(doc1);
+
+ hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &doc2);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ hr = IPersistStorage_IsDirty(stg);
+todo_wine_if(test_data[i].in == &stg_def_4 || test_data[i].in == &stg_def_8 || test_data[i].in == &stg_def_9)
+ ok(hr == S_FALSE, "%d: unexpected %#x\n", i, hr);
+
+ hr = IPersistStorage_Save(stg, doc2, FALSE);
+ ok(hr == S_OK, "unexpected %#x\n", hr);
+
+ IPersistStorage_Release(stg);
+
+ enumerated_streams = matched_streams = -1;
+ check_storage_contents(doc2, test_data[i].out, &enumerated_streams, &matched_streams);
+todo_wine
+ ok(enumerated_streams == matched_streams, "%d out: enumerated %d != matched %d\n", i,
+ enumerated_streams, matched_streams);
+todo_wine
+ ok(enumerated_streams == test_data[i].out->stream_count, "%d: saved streams %d != def streams %d\n", i,
+ enumerated_streams, test_data[i].out->stream_count);
+
+ IStorage_Release(doc2);
+
+ if (winetest_debug > 1)
+ trace("done testing storage def %d\n", i);
+ }
+}
+
START_TEST(ole2)
{
DWORD dwRegister;
@@ -3362,6 +3763,7 @@ START_TEST(ole2)
test_OleDraw();
test_OleDoAutoConvert();
test_data_cache_save();
+ test_data_cache_contents();
CoUninitialize();
}
--
2.14.2
More information about the wine-patches
mailing list