mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / opcservices / tests / opcservices.c
blobcd683b0a206f292787b0ecb8bd2b338bc243f98d
1 /*
2 * OPC Services tests
4 * Copyright 2018 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "windows.h"
24 #include "initguid.h"
25 #include "msopc.h"
26 #include "urlmon.h"
28 #include "wine/heap.h"
29 #include "wine/test.h"
31 static IOpcFactory *create_factory(void)
33 IOpcFactory *factory = NULL;
34 CoCreateInstance(&CLSID_OpcFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IOpcFactory, (void **)&factory);
35 return factory;
38 static void test_package(void)
40 static const WCHAR typeW[] = {'t','y','p','e','/','s','u','b','t','y','p','e',0};
41 static const WCHAR targetW[] = {'t','a','r','g','e','t',0};
42 static const WCHAR uriW[] = {'/','u','r','i',0};
43 static const WCHAR rootW[] = {'/',0};
44 IOpcRelationshipSet *relset, *relset2;
45 IOpcPartUri *part_uri, *part_uri2;
46 IOpcPartSet *partset, *partset2;
47 OPC_COMPRESSION_OPTIONS options;
48 IStream *stream, *stream2;
49 IOpcPart *part, *part2;
50 IOpcRelationship *rel;
51 IOpcFactory *factory;
52 IOpcPackage *package;
53 LARGE_INTEGER move;
54 ULARGE_INTEGER pos;
55 IUri *target_uri;
56 char buff[16];
57 IOpcUri *uri;
58 HRESULT hr;
59 BSTR str;
60 BOOL ret;
62 factory = create_factory();
64 hr = IOpcFactory_CreatePackage(factory, &package);
65 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) /* Vista */, "Failed to create a package, hr %#x.\n", hr);
66 if (FAILED(hr))
68 IOpcFactory_Release(factory);
69 return;
72 hr = IOpcPackage_GetPartSet(package, &partset);
73 ok(SUCCEEDED(hr), "Failed to create a part set, hr %#x.\n", hr);
75 hr = IOpcPackage_GetPartSet(package, &partset2);
76 ok(SUCCEEDED(hr), "Failed to create a part set, hr %#x.\n", hr);
77 ok(partset == partset2, "Expected same part set instance.\n");
78 IOpcPartSet_Release(partset2);
80 /* CreatePart */
81 hr = IOpcFactory_CreatePartUri(factory, uriW, &part_uri);
82 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
84 hr = IOpcFactory_CreatePartUri(factory, uriW, &part_uri2);
85 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
87 part = (void *)0xdeadbeef;
88 hr = IOpcPartSet_CreatePart(partset, NULL, typeW, OPC_COMPRESSION_NONE, &part);
89 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
90 ok(part == NULL, "Unexpected pointer %p.\n", part);
92 hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, OPC_COMPRESSION_NONE, NULL);
93 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
95 hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, 0xdeadbeef, &part);
96 ok(SUCCEEDED(hr), "Failed to create a part, hr %#x.\n", hr);
97 hr = IOpcPart_GetCompressionOptions(part, &options);
98 ok(SUCCEEDED(hr), "Failed to get compression options, hr %#x.\n", hr);
99 ok(options == 0xdeadbeef, "Unexpected compression options %#x.\n", options);
101 part2 = (void *)0xdeadbeef;
102 hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, OPC_COMPRESSION_NONE, &part2);
103 ok(hr == OPC_E_DUPLICATE_PART, "Unexpected hr %#x.\n", hr);
104 ok(part2 == NULL, "Unexpected instance %p.\n", part2);
106 part2 = (void *)0xdeadbeef;
107 hr = IOpcPartSet_CreatePart(partset, part_uri2, typeW, OPC_COMPRESSION_NONE, &part2);
108 ok(hr == OPC_E_DUPLICATE_PART, "Unexpected hr %#x.\n", hr);
109 ok(part2 == NULL, "Unexpected instance %p.\n", part2);
110 IOpcPartUri_Release(part_uri2);
112 hr = IOpcPartSet_GetPart(partset, NULL, NULL);
113 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
115 part2 = (void *)0xdeadbeef;
116 hr = IOpcPartSet_GetPart(partset, NULL, &part2);
117 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
118 ok(part2 == NULL, "Unexpected pointer %p.\n", part2);
120 hr = IOpcPartSet_GetPart(partset, part_uri, NULL);
121 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
123 hr = IOpcPartSet_GetPart(partset, part_uri, &part2);
124 ok(SUCCEEDED(hr), "Failed to get part, hr %#x.\n", hr);
125 IOpcPart_Release(part2);
127 hr = IOpcFactory_CreatePartUri(factory, targetW, &part_uri2);
128 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
130 hr = IOpcPartSet_GetPart(partset, part_uri2, &part2);
131 ok(hr == OPC_E_NO_SUCH_PART, "Unexpected hr %#x.\n", hr);
132 IOpcPartUri_Release(part_uri2);
134 hr = IOpcPart_GetContentStream(part, NULL);
135 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
137 hr = IOpcPart_GetContentStream(part, &stream);
138 ok(SUCCEEDED(hr), "Failed to get content stream, hr %#x.\n", hr);
140 hr = IStream_Write(stream, "abc", 3, NULL);
141 ok(hr == S_OK, "Failed to write content, hr %#x.\n", hr);
143 move.QuadPart = 0;
144 hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, &pos);
145 ok(SUCCEEDED(hr), "Seek failed, hr %#x.\n", hr);
146 ok(pos.QuadPart == 3, "Unexpected position.\n");
148 hr = IOpcPart_GetContentStream(part, &stream2);
149 ok(SUCCEEDED(hr), "Failed to get content stream, hr %#x.\n", hr);
150 ok(stream != stream2, "Unexpected instance.\n");
152 move.QuadPart = 0;
153 hr = IStream_Seek(stream2, move, STREAM_SEEK_CUR, &pos);
154 ok(SUCCEEDED(hr), "Seek failed, hr %#x.\n", hr);
155 ok(pos.QuadPart == 0, "Unexpected position.\n");
157 memset(buff, 0, sizeof(buff));
158 hr = IStream_Read(stream2, buff, sizeof(buff), NULL);
159 ok(hr == S_OK, "Failed to read content, hr %#x.\n", hr);
160 ok(!memcmp(buff, "abc", 3), "Unexpected content.\n");
162 move.QuadPart = 0;
163 hr = IStream_Seek(stream2, move, STREAM_SEEK_CUR, &pos);
164 ok(SUCCEEDED(hr), "Seek failed, hr %#x.\n", hr);
165 ok(pos.QuadPart == 3, "Unexpected position.\n");
167 IStream_Release(stream);
168 IStream_Release(stream2);
170 hr = IOpcPart_GetRelationshipSet(part, &relset);
171 ok(SUCCEEDED(hr), "Failed to get relationship set, hr %#x.\n", hr);
173 hr = IOpcPart_GetRelationshipSet(part, &relset2);
174 ok(SUCCEEDED(hr), "Failed to get relationship set, hr %#x.\n", hr);
175 ok(relset == relset2, "Expected same part set instance.\n");
177 hr = CreateUri(targetW, Uri_CREATE_ALLOW_RELATIVE, 0, &target_uri);
178 ok(SUCCEEDED(hr), "Failed to create target uri, hr %#x.\n", hr);
180 hr = IOpcRelationshipSet_CreateRelationship(relset, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel);
181 ok(SUCCEEDED(hr), "Failed to create relationship, hr %#x.\n", hr);
183 hr = IOpcRelationship_GetSourceUri(rel, &uri);
184 ok(SUCCEEDED(hr), "Failed to get source uri, hr %#x.\n", hr);
185 ok(uri == (IOpcUri *)part_uri, "Unexpected source uri.\n");
187 IOpcUri_Release(uri);
189 IOpcRelationship_Release(rel);
190 IUri_Release(target_uri);
192 IOpcRelationshipSet_Release(relset);
193 IOpcRelationshipSet_Release(relset2);
195 ret = 123;
196 hr = IOpcPartSet_PartExists(partset, NULL, &ret);
197 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
198 ok(ret == 123, "Unexpected return value.\n");
200 hr = IOpcPartSet_PartExists(partset, part_uri, NULL);
201 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
203 ret = FALSE;
204 hr = IOpcPartSet_PartExists(partset, part_uri, &ret);
205 ok(SUCCEEDED(hr), "Unexpected hr %#x.\n", hr);
206 ok(ret, "Expected part to exist.\n");
208 IOpcPartUri_Release(part_uri);
209 IOpcPart_Release(part);
211 /* Relationships */
212 hr = IOpcPackage_GetRelationshipSet(package, &relset);
213 ok(SUCCEEDED(hr), "Failed to get relationship set, hr %#x.\n", hr);
215 hr = IOpcPackage_GetRelationshipSet(package, &relset2);
216 ok(SUCCEEDED(hr), "Failed to get relationship set, hr %#x.\n", hr);
217 ok(relset == relset2, "Expected same part set instance.\n");
218 IOpcRelationshipSet_Release(relset);
219 IOpcRelationshipSet_Release(relset2);
221 IOpcPartSet_Release(partset);
222 IOpcPackage_Release(package);
224 /* Root uri */
225 hr = IOpcFactory_CreatePackageRootUri(factory, NULL);
226 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
227 hr = IOpcFactory_CreatePackageRootUri(factory, &uri);
228 ok(SUCCEEDED(hr), "Failed to create root uri, hr %#x.\n", hr);
229 hr = IOpcUri_GetRawUri(uri, &str);
230 ok(SUCCEEDED(hr), "Failed to get raw uri, hr %#x.\n", hr);
231 ok(!lstrcmpW(str, rootW), "Unexpected uri %s.\n", wine_dbgstr_w(str));
232 SysFreeString(str);
233 IOpcUri_Release(uri);
235 IOpcFactory_Release(factory);
238 #define test_stream_stat(stream, size) test_stream_stat_(__LINE__, stream, size)
239 static void test_stream_stat_(unsigned int line, IStream *stream, ULONG size)
241 STATSTG statstg;
242 HRESULT hr;
244 hr = IStream_Stat(stream, NULL, 0);
245 ok_(__FILE__, line)(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
247 memset(&statstg, 0xff, sizeof(statstg));
248 hr = IStream_Stat(stream, &statstg, 0);
249 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get stat info, hr %#x.\n", hr);
251 ok_(__FILE__, line)(statstg.pwcsName == NULL, "Unexpected name %s.\n", wine_dbgstr_w(statstg.pwcsName));
252 ok_(__FILE__, line)(statstg.type == STGTY_STREAM, "Unexpected type.\n");
253 ok_(__FILE__, line)(statstg.cbSize.QuadPart == size, "Unexpected size %u, expected %u.\n",
254 statstg.cbSize.LowPart, size);
255 ok_(__FILE__, line)(statstg.grfMode == STGM_READ, "Unexpected mode.\n");
256 ok_(__FILE__, line)(statstg.grfLocksSupported == 0, "Unexpected lock mode.\n");
257 ok_(__FILE__, line)(statstg.grfStateBits == 0, "Unexpected state bits.\n");
260 static void test_file_stream(void)
262 static const WCHAR filereadW[] = {'o','p','c','f','i','l','e','r','e','a','d','.','e','x','t',0};
263 WCHAR temppathW[MAX_PATH], pathW[MAX_PATH];
264 IOpcFactory *factory;
265 LARGE_INTEGER move;
266 IStream *stream;
267 char buff[64];
268 HRESULT hr;
269 ULONG size;
271 factory = create_factory();
273 hr = IOpcFactory_CreateStreamOnFile(factory, NULL, OPC_STREAM_IO_READ, NULL, 0, &stream);
274 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
276 GetTempPathW(ARRAY_SIZE(temppathW), temppathW);
277 lstrcpyW(pathW, temppathW);
278 lstrcatW(pathW, filereadW);
279 DeleteFileW(pathW);
281 hr = IOpcFactory_CreateStreamOnFile(factory, pathW, OPC_STREAM_IO_READ, NULL, 0, NULL);
282 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
284 /* File does not exist */
285 hr = IOpcFactory_CreateStreamOnFile(factory, pathW, OPC_STREAM_IO_READ, NULL, 0, &stream);
286 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
288 hr = IOpcFactory_CreateStreamOnFile(factory, pathW, OPC_STREAM_IO_WRITE, NULL, 0, &stream);
289 ok(SUCCEEDED(hr), "Failed to create a write stream, hr %#x.\n", hr);
291 test_stream_stat(stream, 0);
293 size = lstrlenW(pathW) * sizeof(WCHAR);
294 hr = IStream_Write(stream, pathW, size, NULL);
295 ok(hr == S_OK, "Stream write failed, hr %#x.\n", hr);
297 test_stream_stat(stream, size);
298 IStream_Release(stream);
300 /* Invalid I/O mode */
301 hr = IOpcFactory_CreateStreamOnFile(factory, pathW, 10, NULL, 0, &stream);
302 ok(hr == E_INVALIDARG, "Failed to create a write stream, hr %#x.\n", hr);
304 /* Write to read-only stream. */
305 hr = IOpcFactory_CreateStreamOnFile(factory, pathW, OPC_STREAM_IO_READ, NULL, 0, &stream);
306 ok(SUCCEEDED(hr), "Failed to create a read stream, hr %#x.\n", hr);
308 test_stream_stat(stream, size);
309 hr = IStream_Write(stream, pathW, size, NULL);
310 ok(hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), "Stream write failed, hr %#x.\n", hr);
311 IStream_Release(stream);
313 /* Read from write-only stream. */
314 hr = IOpcFactory_CreateStreamOnFile(factory, pathW, OPC_STREAM_IO_WRITE, NULL, 0, &stream);
315 ok(SUCCEEDED(hr), "Failed to create a read stream, hr %#x.\n", hr);
317 test_stream_stat(stream, 0);
318 hr = IStream_Write(stream, pathW, size, NULL);
319 ok(hr == S_OK, "Stream write failed, hr %#x.\n", hr);
320 test_stream_stat(stream, size);
322 move.QuadPart = 0;
323 hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL);
324 ok(SUCCEEDED(hr), "Seek failed, hr %#x.\n", hr);
326 hr = IStream_Read(stream, buff, sizeof(buff), NULL);
327 ok(hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), "Stream read failed, hr %#x.\n", hr);
329 IStream_Release(stream);
331 IOpcFactory_Release(factory);
332 DeleteFileW(pathW);
335 static void test_relationship(void)
337 static const WCHAR absoluteW[] = {'f','i','l','e',':','/','/','h','o','s','t','/','f','i','l','e','.','t','x','t',0};
338 static const WCHAR targetW[] = {'t','a','r','g','e','t',0};
339 static const WCHAR typeW[] = {'t','y','p','e',0};
340 static const WCHAR rootW[] = {'/',0};
341 IUri *target_uri, *target_uri2, *uri;
342 IOpcRelationship *rel, *rel2, *rel3;
343 IOpcUri *source_uri, *source_uri2;
344 IOpcRelationshipSet *rels;
345 IOpcFactory *factory;
346 IOpcPackage *package;
347 IUnknown *unk;
348 DWORD mode;
349 HRESULT hr;
350 WCHAR *id;
351 BOOL ret;
352 BSTR str;
354 factory = create_factory();
356 hr = IOpcFactory_CreatePackage(factory, &package);
357 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) /* Vista */, "Failed to create a package, hr %#x.\n", hr);
358 if (FAILED(hr))
360 IOpcFactory_Release(factory);
361 return;
364 hr = CreateUri(targetW, Uri_CREATE_ALLOW_RELATIVE, 0, &target_uri);
365 ok(SUCCEEDED(hr), "Failed to create target uri, hr %#x.\n", hr);
367 hr = CreateUri(absoluteW, 0, 0, &target_uri2);
368 ok(SUCCEEDED(hr), "Failed to create target uri, hr %#x.\n", hr);
370 hr = IOpcPackage_GetRelationshipSet(package, &rels);
371 ok(SUCCEEDED(hr), "Failed to get part set, hr %#x.\n", hr);
373 rel = (void *)0xdeadbeef;
374 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, NULL, NULL, OPC_URI_TARGET_MODE_INTERNAL, &rel);
375 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
376 ok(rel == NULL, "Unexpected instance %p.\n", rel);
378 rel = (void *)0xdeadbeef;
379 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, NULL, OPC_URI_TARGET_MODE_INTERNAL, &rel);
380 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
381 ok(rel == NULL, "Unexpected instance %p.\n", rel);
383 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, NULL, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel);
384 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
386 /* Absolute target uri with internal mode */
387 rel = (void *)0xdeadbeef;
388 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri2, OPC_URI_TARGET_MODE_INTERNAL, &rel);
389 ok(hr == OPC_E_INVALID_RELATIONSHIP_TARGET, "Unexpected hr %#x.\n", hr);
390 ok(rel == NULL, "Unexpected instance %p.\n", rel);
392 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel);
393 ok(SUCCEEDED(hr), "Failed to create relationship, hr %#x.\n", hr);
395 /* Autogenerated relationship id */
396 hr = IOpcRelationship_GetId(rel, &id);
397 ok(SUCCEEDED(hr), "Failed to get id, hr %#x.\n", hr);
398 ok(lstrlenW(id) == 9 && *id == 'R', "Unexpected relationship id %s.\n", wine_dbgstr_w(id));
400 hr = IOpcRelationshipSet_CreateRelationship(rels, id, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel2);
401 ok(hr == OPC_E_DUPLICATE_RELATIONSHIP, "Failed to create relationship, hr %#x.\n", hr);
403 hr = IOpcRelationshipSet_CreateRelationship(rels, id, typeW, target_uri2, OPC_URI_TARGET_MODE_INTERNAL, &rel2);
404 ok(hr == OPC_E_DUPLICATE_RELATIONSHIP, "Failed to create relationship, hr %#x.\n", hr);
406 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel2);
407 ok(SUCCEEDED(hr), "Failed to create relationship, hr %#x.\n", hr);
409 ret = 123;
410 hr = IOpcRelationshipSet_RelationshipExists(rels, NULL, &ret);
411 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
412 ok(ret == 123, "Unexpected result %d.\n", ret);
414 hr = IOpcRelationshipSet_RelationshipExists(rels, id, NULL);
415 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
417 ret = FALSE;
418 hr = IOpcRelationshipSet_RelationshipExists(rels, id, &ret);
419 ok(SUCCEEDED(hr), "Failed to get relationship, hr %#x.\n", hr);
420 ok(ret, "Unexpected result %d.\n", ret);
422 hr = IOpcRelationshipSet_GetRelationship(rels, id, &rel3);
423 ok(SUCCEEDED(hr), "Failed to get relationship, hr %#x.\n", hr);
424 IOpcRelationship_Release(rel3);
426 hr = IOpcRelationshipSet_GetRelationship(rels, id, NULL);
427 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
429 rel3 = (void *)0xdeadbeef;
430 hr = IOpcRelationshipSet_GetRelationship(rels, NULL, &rel3);
431 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
432 ok(rel3 == NULL, "Expected null pointer.\n");
434 *id = 'r';
435 rel3 = (void *)0xdeadbeef;
436 hr = IOpcRelationshipSet_GetRelationship(rels, id, &rel3);
437 ok(hr == OPC_E_NO_SUCH_RELATIONSHIP, "Unexpected hr %#x.\n", hr);
438 ok(rel3 == NULL, "Expected null pointer.\n");
440 ret = TRUE;
441 hr = IOpcRelationshipSet_RelationshipExists(rels, id, &ret);
442 ok(SUCCEEDED(hr), "Unexpected hr %#x.\n", hr);
443 ok(!ret, "Unexpected result %d.\n", ret);
445 CoTaskMemFree(id);
447 hr = IOpcRelationship_GetTargetUri(rel, &uri);
448 ok(SUCCEEDED(hr), "Failed to get target uri, hr %#x.\n", hr);
449 ok(uri == target_uri, "Unexpected uri.\n");
450 IUri_Release(uri);
452 hr = IOpcRelationship_GetTargetMode(rel, &mode);
453 ok(SUCCEEDED(hr), "Failed to get target mode, hr %#x.\n", hr);
454 ok(mode == OPC_URI_TARGET_MODE_INTERNAL, "Unexpected mode %d.\n", mode);
456 /* Source uri */
457 hr = IOpcFactory_CreatePackageRootUri(factory, &source_uri);
458 ok(SUCCEEDED(hr), "Failed to create root uri, hr %#x.\n", hr);
460 hr = IOpcFactory_CreatePackageRootUri(factory, &source_uri2);
461 ok(SUCCEEDED(hr), "Failed to create root uri, hr %#x.\n", hr);
462 ok(source_uri != source_uri2, "Unexpected uri instance.\n");
464 IOpcUri_Release(source_uri);
465 IOpcUri_Release(source_uri2);
467 hr = IOpcRelationship_GetSourceUri(rel, &source_uri);
468 ok(SUCCEEDED(hr), "Failed to get source uri, hr %#x.\n", hr);
470 hr = IOpcUri_QueryInterface(source_uri, &IID_IOpcPartUri, (void **)&unk);
471 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
473 str = NULL;
474 hr = IOpcUri_GetRawUri(source_uri, &str);
475 ok(SUCCEEDED(hr), "Failed to get raw uri, hr %#x.\n", hr);
476 ok(!lstrcmpW(rootW, str), "Unexpected uri %s.\n", wine_dbgstr_w(str));
477 SysFreeString(str);
479 hr = IOpcRelationship_GetSourceUri(rel2, &source_uri2);
480 ok(SUCCEEDED(hr), "Failed to get source uri, hr %#x.\n", hr);
481 ok(source_uri2 == source_uri, "Unexpected source uri.\n");
483 IOpcUri_Release(source_uri2);
484 IOpcUri_Release(source_uri);
486 IOpcRelationship_Release(rel2);
487 IOpcRelationship_Release(rel);
489 IOpcRelationshipSet_Release(rels);
491 IUri_Release(target_uri);
492 IUri_Release(target_uri2);
493 IOpcPackage_Release(package);
494 IOpcFactory_Release(factory);
497 static WCHAR *strdupAtoW(const char *str)
499 WCHAR *ret = NULL;
500 DWORD len;
502 if (!str) return ret;
503 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
504 ret = heap_alloc(len * sizeof(WCHAR));
505 if (ret)
506 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
507 return ret;
510 static void test_rel_part_uri(void)
512 static const struct
514 const char *uri;
515 const char *rel_uri;
516 HRESULT hr;
517 } rel_part_uri_tests[] =
519 { "/uri", "/_rels/uri.rels" },
520 { "/path/uri", "/path/_rels/uri.rels" },
521 { "path/uri", "/path/_rels/uri.rels" },
522 { "../path/uri", "/path/_rels/uri.rels" },
523 { "../../path/uri", "/path/_rels/uri.rels" },
524 { "/uri.ext", "/_rels/uri.ext.rels" },
525 { "/", "/_rels/.rels" },
526 { "uri", "/_rels/uri.rels" },
527 { "/path/../uri", "/_rels/uri.rels" },
528 { "/path/path/../../uri", "/_rels/uri.rels" },
529 { "/_rels/uri.ext.rels", "", OPC_E_NONCONFORMING_URI },
531 static const struct
533 const char *uri;
534 BOOL ret;
535 } is_rel_part_tests[] =
537 { "/uri", FALSE },
538 { "uri", FALSE },
539 { "/_rels/uri", FALSE },
540 { "/_rels/uri/uri", FALSE },
541 { "/_rels/uri/uri.rels", FALSE },
542 { "/uri/uri.rels", FALSE },
543 { "/uri/_rels/uri.rels", TRUE },
544 { "/_rels/.rels", TRUE },
546 static const WCHAR testuriW[] = {'/','u','r','i',0};
547 IOpcPartUri *part_uri;
548 IOpcFactory *factory;
549 IOpcUri *source_uri;
550 unsigned int i;
551 WCHAR *uriW;
552 HRESULT hr;
554 factory = create_factory();
556 hr = IOpcFactory_CreatePartUri(factory, testuriW, &part_uri);
557 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
559 hr = IOpcPartUri_GetRelationshipsPartUri(part_uri, NULL);
560 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
562 hr = IOpcPartUri_IsRelationshipsPartUri(part_uri, NULL);
563 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
565 hr = IOpcPartUri_GetSourceUri(part_uri, NULL);
566 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
568 source_uri = (void *)0xdeadbeef;
569 hr = IOpcPartUri_GetSourceUri(part_uri, &source_uri);
570 ok(hr == OPC_E_RELATIONSHIP_URI_REQUIRED, "Unexpected hr %#x.\n", hr);
571 ok(source_uri == NULL, "Expected null uri.\n");
573 IOpcPartUri_Release(part_uri);
575 for (i = 0; i < ARRAY_SIZE(rel_part_uri_tests); ++i)
577 BOOL is_root = FALSE;
578 IOpcPartUri *rel_uri;
579 IOpcUri *part_uri;
580 WCHAR *rel_uriW;
582 uriW = strdupAtoW(rel_part_uri_tests[i].uri);
583 rel_uriW = strdupAtoW(rel_part_uri_tests[i].rel_uri);
585 if (!strcmp(rel_part_uri_tests[i].uri, "/"))
587 hr = IOpcFactory_CreatePackageRootUri(factory, &part_uri);
588 is_root = TRUE;
590 else
591 hr = IOpcFactory_CreatePartUri(factory, uriW, (IOpcPartUri **)&part_uri);
592 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
594 rel_uri = (void *)0xdeadbeef;
595 hr = IOpcUri_GetRelationshipsPartUri(part_uri, &rel_uri);
596 if (SUCCEEDED(hr))
598 IOpcPartUri *rel_uri2;
599 IOpcUri *source_uri2;
600 IUnknown *unk = NULL;
601 BOOL ret;
602 BSTR str;
604 hr = IOpcPartUri_GetSourceUri(rel_uri, &source_uri);
605 ok(SUCCEEDED(hr), "Failed to get source uri, hr %#x.\n", hr);
606 hr = IOpcPartUri_GetSourceUri(rel_uri, &source_uri2);
607 ok(SUCCEEDED(hr), "Failed to get source uri, hr %#x.\n", hr);
608 ok(source_uri != source_uri2, "Unexpected instance.\n");
610 hr = IOpcUri_IsEqual(source_uri, NULL, NULL);
611 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
613 ret = 123;
614 hr = IOpcUri_IsEqual(source_uri, NULL, &ret);
615 ok(is_root ? hr == E_POINTER : hr == S_OK, "Unexpected hr %#x.\n", hr);
616 ok(is_root ? ret == 123 : !ret, "Unexpected result.\n");
618 ret = FALSE;
619 hr = IOpcUri_IsEqual(source_uri, (IUri *)source_uri2, &ret);
620 ok(SUCCEEDED(hr), "IsEqual failed, hr %#x.\n", hr);
621 ok(ret, "Expected equal uris.\n");
623 hr = IOpcUri_QueryInterface(source_uri, &IID_IOpcPartUri, (void **)&unk);
624 ok(hr == (is_root ? E_NOINTERFACE : S_OK), "Unexpected hr %#x, %s.\n", hr, rel_part_uri_tests[i].uri);
625 if (unk)
626 IUnknown_Release(unk);
628 IOpcUri_Release(source_uri2);
629 IOpcUri_Release(source_uri);
631 hr = IOpcUri_GetRelationshipsPartUri(part_uri, &rel_uri2);
632 ok(SUCCEEDED(hr), "Failed to get rels part uri, hr %#x.\n", hr);
633 ok(rel_uri2 != rel_uri, "Unexpected instance.\n");
634 IOpcPartUri_Release(rel_uri2);
636 hr = IOpcPartUri_GetRawUri(rel_uri, &str);
637 ok(SUCCEEDED(hr), "Failed to get rel uri, hr %#x.\n", hr);
638 todo_wine_if(i == 3 || i == 4 || i == 8 || i == 9)
639 ok(!lstrcmpW(str, rel_uriW), "%u: unexpected rel uri %s, expected %s.\n", i, wine_dbgstr_w(str),
640 wine_dbgstr_w(rel_uriW));
641 SysFreeString(str);
643 IOpcPartUri_Release(rel_uri);
645 else
647 ok(hr == rel_part_uri_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
648 ok(rel_uri == NULL, "%u: unexpected out pointer.\n", i);
651 heap_free(uriW);
652 heap_free(rel_uriW);
654 IOpcUri_Release(part_uri);
657 for (i = 0; i < ARRAY_SIZE(is_rel_part_tests); ++i)
659 IOpcPartUri *part_uri;
660 BOOL ret;
662 uriW = strdupAtoW(is_rel_part_tests[i].uri);
664 hr = IOpcFactory_CreatePartUri(factory, uriW, &part_uri);
665 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
667 ret = 123;
668 hr = IOpcPartUri_IsRelationshipsPartUri(part_uri, &ret);
669 ok(SUCCEEDED(hr), "Unexpected hr %#x.\n", hr);
670 ok(ret == is_rel_part_tests[i].ret, "%u: unexpected result %d.\n", i, ret);
672 heap_free(uriW);
674 IOpcPartUri_Release(part_uri);
677 IOpcFactory_Release(factory);
680 static void test_part_enumerator(void)
682 static const WCHAR typeW[] = {'t','y','p','e','/','s','u','b','t','y','p','e',0};
683 static const WCHAR uriW[] = {'/','u','r','i',0};
684 IOpcPartEnumerator *partenum, *partenum2;
685 IOpcPart *part, *part2;
686 IOpcPartUri *part_uri;
687 IOpcPackage *package;
688 IOpcFactory *factory;
689 IOpcPartSet *parts;
690 HRESULT hr;
691 BOOL ret;
693 factory = create_factory();
695 hr = IOpcFactory_CreatePackage(factory, &package);
696 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) /* Vista */, "Failed to create a package, hr %#x.\n", hr);
697 if (FAILED(hr))
699 IOpcFactory_Release(factory);
700 return;
703 hr = IOpcPackage_GetPartSet(package, &parts);
704 ok(SUCCEEDED(hr), "Failed to get part set, hr %#x.\n", hr);
706 hr = IOpcPartSet_GetEnumerator(parts, NULL);
707 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
709 hr = IOpcPartSet_GetEnumerator(parts, &partenum);
710 ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
712 hr = IOpcPartSet_GetEnumerator(parts, &partenum2);
713 ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
714 ok(partenum != partenum2, "Unexpected instance.\n");
715 IOpcPartEnumerator_Release(partenum2);
717 hr = IOpcPartEnumerator_GetCurrent(partenum, NULL);
718 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
720 hr = IOpcPartEnumerator_GetCurrent(partenum, &part);
721 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
723 hr = IOpcPartEnumerator_MoveNext(partenum, NULL);
724 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
726 ret = TRUE;
727 hr = IOpcPartEnumerator_MoveNext(partenum, &ret);
728 ok(hr == S_OK, "Failed to move, hr %#x.\n", hr);
729 ok(!ret, "Unexpected result %d.\n", ret);
731 ret = TRUE;
732 hr = IOpcPartEnumerator_MovePrevious(partenum, &ret);
733 ok(hr == S_OK, "Failed to move, hr %#x.\n", hr);
734 ok(!ret, "Unexpected result %d.\n", ret);
736 hr = IOpcFactory_CreatePartUri(factory, uriW, &part_uri);
737 ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr);
739 hr = IOpcPartSet_CreatePart(parts, part_uri, typeW, OPC_COMPRESSION_NONE, &part);
740 ok(SUCCEEDED(hr), "Failed to create a part, hr %#x.\n", hr);
741 IOpcPartUri_Release(part_uri);
743 part2 = (void *)0xdeadbeef;
744 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
745 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
746 ok(part2 == NULL, "Unexpected instance.\n");
748 hr = IOpcPartEnumerator_MoveNext(partenum, NULL);
749 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
751 ret = 123;
752 hr = IOpcPartEnumerator_MoveNext(partenum, &ret);
753 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
754 ok(ret == 123, "Unexpected result %d.\n", ret);
756 hr = IOpcPartEnumerator_MovePrevious(partenum, NULL);
757 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
759 ret = 123;
760 hr = IOpcPartEnumerator_MovePrevious(partenum, &ret);
761 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
762 ok(ret == 123, "Unexpected result %d.\n", ret);
764 hr = IOpcPartEnumerator_Clone(partenum, NULL);
765 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
767 partenum2 = (void *)0xdeadbeef;
768 hr = IOpcPartEnumerator_Clone(partenum, &partenum2);
769 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
770 ok(partenum2 == NULL, "Unexpected instance.\n");
772 IOpcPartEnumerator_Release(partenum);
774 hr = IOpcPartSet_GetEnumerator(parts, &partenum);
775 ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
777 part2 = (void *)0xdeadbeef;
778 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
779 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
780 ok(part2 == NULL, "Unexpected instance.\n");
782 hr = IOpcPartEnumerator_MoveNext(partenum, &ret);
783 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
784 ok(ret, "Unexpected result %d.\n", ret);
786 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
787 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
788 ok(part2 == part, "Unexpected instance.\n");
789 IOpcPart_Release(part2);
791 hr = IOpcPartEnumerator_MoveNext(partenum, &ret);
792 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
793 ok(!ret, "Unexpected result %d.\n", ret);
795 part2 = (void *)0xdeadbeef;
796 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
797 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
798 ok(part2 == NULL, "Unexpected instance.\n");
800 hr = IOpcPartEnumerator_MovePrevious(partenum, &ret);
801 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
802 ok(ret, "Unexpected result %d.\n", ret);
804 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
805 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
806 ok(part2 == part, "Unexpected instance.\n");
807 IOpcPart_Release(part2);
809 hr = IOpcPartEnumerator_MovePrevious(partenum, &ret);
810 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
811 ok(!ret, "Unexpected result %d.\n", ret);
813 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
814 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
816 hr = IOpcPartEnumerator_Clone(partenum, &partenum2);
817 ok(SUCCEEDED(hr), "Clone failed, hr %#x.\n", hr);
819 hr = IOpcPartEnumerator_MoveNext(partenum2, &ret);
820 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
821 ok(ret, "Unexpected result %d.\n", ret);
823 hr = IOpcPartEnumerator_GetCurrent(partenum2, &part2);
824 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
825 IOpcPart_Release(part2);
827 hr = IOpcPartEnumerator_GetCurrent(partenum, &part2);
828 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
830 IOpcPartEnumerator_Release(partenum2);
832 IOpcPartEnumerator_Release(partenum);
834 IOpcPart_Release(part);
836 IOpcPartSet_Release(parts);
838 IOpcPackage_Release(package);
839 IOpcFactory_Release(factory);
842 static void test_rels_enumerator(void)
844 static const WCHAR typeW[] = {'t','y','p','e','/','s','u','b','t','y','p','e',0};
845 static const WCHAR targetW[] = {'t','a','r','g','e','t',0};
846 IOpcRelationshipEnumerator *relsenum, *relsenum2;
847 IOpcRelationship *rel, *rel2;
848 IOpcPackage *package;
849 IOpcFactory *factory;
850 IOpcRelationshipSet *rels;
851 IUri *target_uri;
852 HRESULT hr;
853 BOOL ret;
855 factory = create_factory();
857 hr = IOpcFactory_CreatePackage(factory, &package);
858 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) /* Vista */, "Failed to create a package, hr %#x.\n", hr);
859 if (FAILED(hr))
861 IOpcFactory_Release(factory);
862 return;
865 hr = IOpcPackage_GetRelationshipSet(package, &rels);
866 ok(SUCCEEDED(hr), "Failed to get part set, hr %#x.\n", hr);
868 hr = IOpcRelationshipSet_GetEnumerator(rels, NULL);
869 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
871 hr = IOpcRelationshipSet_GetEnumerator(rels, &relsenum);
872 ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
874 hr = IOpcRelationshipSet_GetEnumerator(rels, &relsenum2);
875 ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
876 ok(relsenum != relsenum2, "Unexpected instance.\n");
877 IOpcRelationshipEnumerator_Release(relsenum2);
879 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, NULL);
880 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
882 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel);
883 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
885 hr = IOpcRelationshipEnumerator_MoveNext(relsenum, NULL);
886 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
888 ret = TRUE;
889 hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
890 ok(hr == S_OK, "Failed to move, hr %#x.\n", hr);
891 ok(!ret, "Unexpected result %d.\n", ret);
893 ret = TRUE;
894 hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
895 ok(hr == S_OK, "Failed to move, hr %#x.\n", hr);
896 ok(!ret, "Unexpected result %d.\n", ret);
898 hr = CreateUri(targetW, Uri_CREATE_ALLOW_RELATIVE, 0, &target_uri);
899 ok(SUCCEEDED(hr), "Failed to create target uri, hr %#x.\n", hr);
901 hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel);
902 ok(SUCCEEDED(hr), "Failed to create relationship, hr %#x.\n", hr);
904 IUri_Release(target_uri);
906 rel2 = (void *)0xdeadbeef;
907 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
908 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
909 ok(rel2 == NULL, "Unexpected instance.\n");
911 hr = IOpcRelationshipEnumerator_MoveNext(relsenum, NULL);
912 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
914 ret = 123;
915 hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
916 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
917 ok(ret == 123, "Unexpected result %d.\n", ret);
919 hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, NULL);
920 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
922 ret = 123;
923 hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
924 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
925 ok(ret == 123, "Unexpected result %d.\n", ret);
927 hr = IOpcRelationshipEnumerator_Clone(relsenum, NULL);
928 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
930 relsenum2 = (void *)0xdeadbeef;
931 hr = IOpcRelationshipEnumerator_Clone(relsenum, &relsenum2);
932 ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
933 ok(relsenum2 == NULL, "Unexpected instance.\n");
935 IOpcRelationshipEnumerator_Release(relsenum);
937 hr = IOpcRelationshipSet_GetEnumerator(rels, &relsenum);
938 ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
940 rel2 = (void *)0xdeadbeef;
941 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
942 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
943 ok(rel2 == NULL, "Unexpected instance.\n");
945 hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
946 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
947 ok(ret, "Unexpected result %d.\n", ret);
949 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
950 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
951 ok(rel2 == rel, "Unexpected instance.\n");
952 IOpcRelationship_Release(rel2);
954 hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
955 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
956 ok(!ret, "Unexpected result %d.\n", ret);
958 rel2 = (void *)0xdeadbeef;
959 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
960 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
961 ok(rel2 == NULL, "Unexpected instance.\n");
963 hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
964 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
965 ok(ret, "Unexpected result %d.\n", ret);
967 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
968 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
969 ok(rel2 == rel, "Unexpected instance.\n");
970 IOpcRelationship_Release(rel2);
972 hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
973 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
974 ok(!ret, "Unexpected result %d.\n", ret);
976 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
977 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
979 hr = IOpcRelationshipEnumerator_Clone(relsenum, &relsenum2);
980 ok(SUCCEEDED(hr), "Clone failed, hr %#x.\n", hr);
982 hr = IOpcRelationshipEnumerator_MoveNext(relsenum2, &ret);
983 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
984 ok(ret, "Unexpected result %d.\n", ret);
986 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum2, &rel2);
987 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
988 IOpcRelationship_Release(rel2);
990 hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
991 ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
993 IOpcRelationshipEnumerator_Release(relsenum2);
995 IOpcRelationshipEnumerator_Release(relsenum);
997 IOpcRelationship_Release(rel);
999 IOpcRelationshipSet_Release(rels);
1001 IOpcPackage_Release(package);
1002 IOpcFactory_Release(factory);
1005 static void test_relative_uri(void)
1007 static const struct
1009 const char *part;
1010 const char *combined;
1011 const char *relative;
1012 const char *relative_broken;
1014 relative_uri_tests[] =
1016 { "/", "/path/path2", "path/path2", "/path/path2" },
1017 { "/", "/path", "path", "/path" },
1018 { "/path/path2", "/path/path2/path3", "path2/path3" },
1019 { "/path/path2", "/path3", "../path3" },
1020 { "/path", "/path", "" },
1021 { "/path", "../path", "" },
1022 { "/path2", "/path", "path" },
1023 { "../path", "/path", "" },
1024 { "../../path", "/path", "" },
1026 IOpcFactory *factory;
1027 unsigned int i;
1029 factory = create_factory();
1031 for (i = 0; i < ARRAY_SIZE(relative_uri_tests); ++i)
1033 WCHAR *uriW, *combinedW, *relativeW, *relative_broken_W;
1034 IOpcPartUri *combined_uri;
1035 IUri *relative_uri;
1036 IOpcUri *part_uri;
1037 IUnknown *unk;
1038 HRESULT hr;
1039 BSTR str;
1041 uriW = strdupAtoW(relative_uri_tests[i].part);
1042 combinedW = strdupAtoW(relative_uri_tests[i].combined);
1043 relativeW = strdupAtoW(relative_uri_tests[i].relative);
1044 relative_broken_W = strdupAtoW(relative_uri_tests[i].relative_broken);
1046 if (!strcmp(relative_uri_tests[i].part, "/"))
1047 hr = IOpcFactory_CreatePackageRootUri(factory, &part_uri);
1048 else
1049 hr = IOpcFactory_CreatePartUri(factory, uriW, (IOpcPartUri **)&part_uri);
1050 ok(SUCCEEDED(hr), "%u: failed to create part uri, hr %#x.\n", i, hr);
1052 hr = IOpcFactory_CreatePartUri(factory, combinedW, &combined_uri);
1053 ok(SUCCEEDED(hr), "%u: failed to create part uri, hr %#x.\n", i, hr);
1055 hr = IOpcUri_GetRelativeUri(part_uri, combined_uri, &relative_uri);
1056 todo_wine
1057 ok(SUCCEEDED(hr), "%u: failed t oget relative uri, hr %#x.\n", i, hr);
1059 if (SUCCEEDED(hr))
1061 hr = IUri_QueryInterface(relative_uri, &IID_IOpcUri, (void **)&unk);
1062 ok(hr == E_NOINTERFACE, "%u: unexpected hr %#x.\n", i, hr);
1064 hr = IUri_GetRawUri(relative_uri, &str);
1065 ok(SUCCEEDED(hr), "%u: failed to get raw uri, hr %#x.\n", i, hr);
1066 ok(!lstrcmpW(str, relativeW) || broken(relative_broken_W && !lstrcmpW(str, relative_broken_W)),
1067 "%u: unexpected relative uri %s.\n", i, wine_dbgstr_w(str));
1068 SysFreeString(str);
1070 IUri_Release(relative_uri);
1072 IOpcUri_Release(part_uri);
1073 IOpcPartUri_Release(combined_uri);
1075 heap_free(uriW);
1076 heap_free(combinedW);
1077 heap_free(relativeW);
1078 heap_free(relative_broken_W);
1081 IOpcFactory_Release(factory);
1084 static void test_combine_uri(void)
1086 static const struct
1088 const char *uri;
1089 const char *relative;
1090 const char *combined;
1092 combine_tests[] =
1094 { "/", "path", "/path" },
1095 { "/path1", "path2", "/path2" },
1096 { "/path1", "../path2", "/path2" },
1097 { "/path1/../path2", "path3", "/path3" },
1099 IOpcFactory *factory;
1100 unsigned int i;
1102 factory = create_factory();
1104 for (i = 0; i < ARRAY_SIZE(combine_tests); ++i)
1106 WCHAR *uriW, *relativeW, *combinedW;
1107 IOpcPartUri *combined_uri;
1108 IUri *relative_uri;
1109 IOpcUri *uri;
1110 HRESULT hr;
1111 BSTR str;
1113 uriW = strdupAtoW(combine_tests[i].uri);
1114 relativeW = strdupAtoW(combine_tests[i].relative);
1115 combinedW = strdupAtoW(combine_tests[i].combined);
1117 if (!strcmp(combine_tests[i].uri, "/"))
1118 hr = IOpcFactory_CreatePackageRootUri(factory, &uri);
1119 else
1120 hr = IOpcFactory_CreatePartUri(factory, uriW, (IOpcPartUri **)&uri);
1121 ok(SUCCEEDED(hr), "%u: failed to create uri, hr %#x.\n", i, hr);
1123 hr = CreateUri(relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative_uri);
1124 ok(SUCCEEDED(hr), "%u: failed to create relative uri, hr %#x.\n", i, hr);
1126 combined_uri = (void *)0xdeadbeef;
1127 hr = IOpcUri_CombinePartUri(uri, NULL, &combined_uri);
1128 ok(hr == E_POINTER, "%u: failed to combine uris, hr %#x.\n", i, hr);
1129 ok(!combined_uri, "Unexpected instance.\n");
1131 hr = IOpcUri_CombinePartUri(uri, relative_uri, NULL);
1132 ok(hr == E_POINTER, "%u: failed to combine uris, hr %#x.\n", i, hr);
1134 hr = IOpcUri_CombinePartUri(uri, relative_uri, &combined_uri);
1135 ok(SUCCEEDED(hr), "%u: failed to combine uris, hr %#x.\n", i, hr);
1137 hr = IOpcPartUri_GetRawUri(combined_uri, &str);
1138 ok(SUCCEEDED(hr), "%u: failed to get raw uri, hr %#x.\n", i, hr);
1139 todo_wine_if(i == 2 || i == 3)
1140 ok(!lstrcmpW(str, combinedW), "%u: unexpected uri %s.\n", i, wine_dbgstr_w(str));
1141 SysFreeString(str);
1143 IOpcPartUri_Release(combined_uri);
1145 heap_free(uriW);
1146 heap_free(relativeW);
1147 heap_free(combinedW);
1149 IOpcUri_Release(uri);
1150 IUri_Release(relative_uri);
1153 IOpcFactory_Release(factory);
1156 static void test_create_part_uri(void)
1158 static const struct
1160 const char *input;
1161 const char *raw_uri;
1163 create_part_uri_tests[] =
1165 { "path", "/path" },
1166 { "../path", "/path" },
1167 { "../../path", "/path" },
1168 { "/path", "/path" },
1169 { "/path1/path2/path3/../path4", "/path1/path2/path4" },
1171 IOpcFactory *factory;
1172 unsigned int i;
1173 HRESULT hr;
1175 factory = create_factory();
1177 for (i = 0; i < ARRAY_SIZE(create_part_uri_tests); ++i)
1179 IOpcPartUri *part_uri;
1180 WCHAR *inputW, *rawW;
1181 IUri *uri;
1182 BSTR str;
1183 BOOL ret;
1185 inputW = strdupAtoW(create_part_uri_tests[i].input);
1186 rawW = strdupAtoW(create_part_uri_tests[i].raw_uri);
1188 hr = IOpcFactory_CreatePartUri(factory, inputW, &part_uri);
1189 ok(SUCCEEDED(hr), "%u: failed to create part uri, hr %#x.\n", i, hr);
1191 hr = IOpcPartUri_GetRawUri(part_uri, &str);
1192 ok(SUCCEEDED(hr), "Failed to get raw uri, hr %#x.\n", hr);
1193 todo_wine_if(i == 1 || i == 2 || i == 4)
1194 ok(!lstrcmpW(str, rawW), "%u: unexpected raw uri %s.\n", i, wine_dbgstr_w(str));
1195 SysFreeString(str);
1197 hr = CreateUri(rawW, Uri_CREATE_ALLOW_RELATIVE, 0, &uri);
1198 ok(SUCCEEDED(hr), "Failed to create uri, hr %#x.\n", hr);
1200 ret = FALSE;
1201 hr = IOpcPartUri_IsEqual(part_uri, uri, &ret);
1202 ok(SUCCEEDED(hr), "IsEqual failed, hr %#x.\n", hr);
1203 todo_wine_if(i == 1 || i == 2 || i == 4)
1204 ok(!!ret, "%u: unexpected result %d.\n", i, ret);
1206 IOpcPartUri_Release(part_uri);
1207 IUri_Release(uri);
1209 heap_free(inputW);
1210 heap_free(rawW);
1213 IOpcFactory_Release(factory);
1216 static HRESULT WINAPI custom_package_QueryInterface(IOpcPackage *iface, REFIID iid, void **out)
1218 if (IsEqualIID(iid, &IID_IOpcPackage) || IsEqualIID(iid, &IID_IUnknown))
1220 *out = iface;
1221 IOpcPackage_AddRef(iface);
1222 return S_OK;
1225 *out = NULL;
1226 return E_NOINTERFACE;
1229 static ULONG WINAPI custom_package_AddRef(IOpcPackage *iface)
1231 return 2;
1234 static ULONG WINAPI custom_package_Release(IOpcPackage *iface)
1236 return 1;
1239 static HRESULT WINAPI custom_package_GetPartSet(IOpcPackage *iface, IOpcPartSet **part_set)
1241 return 0x80000001;
1244 static HRESULT WINAPI custom_package_GetRelationshipSet(IOpcPackage *iface, IOpcRelationshipSet **relationship_set)
1246 return 0x80000001;
1249 static const IOpcPackageVtbl custom_package_vtbl =
1251 custom_package_QueryInterface,
1252 custom_package_AddRef,
1253 custom_package_Release,
1254 custom_package_GetPartSet,
1255 custom_package_GetRelationshipSet,
1258 static void test_write_package(void)
1260 IOpcPackage custom_package = { &custom_package_vtbl };
1261 IOpcFactory *factory;
1262 IOpcPackage *package;
1263 IStream *stream;
1264 HRESULT hr;
1266 factory = create_factory();
1268 hr = IOpcFactory_CreatePackage(factory, &package);
1269 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) /* Vista */, "Failed to create a package, hr %#x.\n", hr);
1270 if (FAILED(hr))
1272 IOpcFactory_Release(factory);
1273 return;
1276 hr = IOpcFactory_WritePackageToStream(factory, NULL, OPC_WRITE_FORCE_ZIP32, NULL);
1277 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1279 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1280 ok(SUCCEEDED(hr), "Failed to create a stream, hr %#x.\n", hr);
1282 hr = IOpcFactory_WritePackageToStream(factory, NULL, OPC_WRITE_FORCE_ZIP32, stream);
1283 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1285 hr = IOpcFactory_WritePackageToStream(factory, &custom_package, OPC_WRITE_FORCE_ZIP32, stream);
1286 ok(hr == 0x80000001, "Unexpected hr %#x.\n", hr);
1288 IStream_Release(stream);
1290 IOpcFactory_Release(factory);
1291 IOpcPackage_Release(package);
1294 START_TEST(opcservices)
1296 IOpcFactory *factory;
1297 HRESULT hr;
1299 hr = CoInitialize(NULL);
1300 ok(SUCCEEDED(hr), "Failed to initialize COM, hr %#x.\n", hr);
1302 if (!(factory = create_factory())) {
1303 win_skip("Failed to create IOpcFactory factory.\n");
1304 CoUninitialize();
1305 return;
1308 test_package();
1309 test_file_stream();
1310 test_relationship();
1311 test_rel_part_uri();
1312 test_part_enumerator();
1313 test_rels_enumerator();
1314 test_relative_uri();
1315 test_combine_uri();
1316 test_create_part_uri();
1317 test_write_package();
1319 IOpcFactory_Release(factory);
1321 CoUninitialize();