diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index c865cf35add..6e1a024c19e 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -861,9 +861,6 @@ static HRESULT opc_part_create(struct opc_part_set *set, IOpcPartUri *name, cons { struct opc_part *part; - if (!name) - return E_POINTER; - if (!opc_array_reserve((void **)&set->parts, &set->size, set->count + 1, sizeof(*set->parts))) return E_OUTOFMEMORY; @@ -898,6 +895,21 @@ static HRESULT opc_part_create(struct opc_part_set *set, IOpcPartUri *name, cons return S_OK; } +static struct opc_part *opc_part_set_get_part(const struct opc_part_set *part_set, IOpcPartUri *name) +{ + BOOL is_equal; + size_t i; + + for (i = 0; i < part_set->count; ++i) + { + is_equal = FALSE; + if (IOpcPartUri_IsEqual(part_set->parts[i]->name, (IUri *)name, &is_equal) == S_OK && is_equal) + return part_set->parts[i]; + } + + return NULL; +} + static HRESULT WINAPI opc_part_set_QueryInterface(IOpcPartSet *iface, REFIID iid, void **out) { TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); @@ -944,11 +956,28 @@ static ULONG WINAPI opc_part_set_Release(IOpcPartSet *iface) return refcount; } -static HRESULT WINAPI opc_part_set_GetPart(IOpcPartSet *iface, IOpcPartUri *name, IOpcPart **part) +static HRESULT WINAPI opc_part_set_GetPart(IOpcPartSet *iface, IOpcPartUri *name, IOpcPart **out) { - FIXME("iface %p, name %p, part %p stub!\n", iface, name, part); + struct opc_part_set *part_set = impl_from_IOpcPartSet(iface); + struct opc_part *part; - return E_NOTIMPL; + TRACE("iface %p, name %p, out %p.\n", iface, name, out); + + if (!out) + return E_POINTER; + + *out = NULL; + + if (!name) + return E_POINTER; + + if ((part = opc_part_set_get_part(part_set, name))) + { + *out = &part->IOpcPart_iface; + IOpcPart_AddRef(*out); + } + + return *out ? S_OK : OPC_E_NO_SUCH_PART; } static HRESULT WINAPI opc_part_set_CreatePart(IOpcPartSet *iface, IOpcPartUri *name, LPCWSTR content_type, @@ -959,6 +988,17 @@ static HRESULT WINAPI opc_part_set_CreatePart(IOpcPartSet *iface, IOpcPartUri *n TRACE("iface %p, name %p, content_type %s, compression_options %#x, part %p.\n", iface, name, debugstr_w(content_type), compression_options, part); + if (!part) + return E_POINTER; + + *part = NULL; + + if (!name) + return E_POINTER; + + if (opc_part_set_get_part(part_set, name)) + return OPC_E_DUPLICATE_PART; + return opc_part_create(part_set, name, content_type, compression_options, part); } diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index ab8c2e47a57..2bcf46fb9b7 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -42,16 +42,17 @@ static void test_package(void) static const WCHAR uriW[] = {'/','u','r','i',0}; static const WCHAR rootW[] = {'/',0}; IOpcRelationshipSet *relset, *relset2; + IOpcPartUri *part_uri, *part_uri2; IOpcPartSet *partset, *partset2; + OPC_COMPRESSION_OPTIONS options; IStream *stream, *stream2; + IOpcPart *part, *part2; IOpcRelationship *rel; - IOpcPartUri *part_uri; IOpcFactory *factory; IOpcPackage *package; LARGE_INTEGER move; ULARGE_INTEGER pos; IUri *target_uri; - IOpcPart *part; char buff[16]; IOpcUri *uri; HRESULT hr; @@ -80,11 +81,55 @@ static void test_package(void) hr = IOpcFactory_CreatePartUri(factory, uriW, &part_uri); ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr); + hr = IOpcFactory_CreatePartUri(factory, uriW, &part_uri2); + ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr); + + part = (void *)0xdeadbeef; hr = IOpcPartSet_CreatePart(partset, NULL, typeW, OPC_COMPRESSION_NONE, &part); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + ok(part == NULL, "Unexpected pointer %p.\n", part); - hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, OPC_COMPRESSION_NONE, &part); + hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, OPC_COMPRESSION_NONE, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, 0xdeadbeef, &part); ok(SUCCEEDED(hr), "Failed to create a part, hr %#x.\n", hr); + hr = IOpcPart_GetCompressionOptions(part, &options); + ok(SUCCEEDED(hr), "Failed to get compression options, hr %#x.\n", hr); + ok(options == 0xdeadbeef, "Unexpected compression options %#x.\n", options); + + part2 = (void *)0xdeadbeef; + hr = IOpcPartSet_CreatePart(partset, part_uri, typeW, OPC_COMPRESSION_NONE, &part2); + ok(hr == OPC_E_DUPLICATE_PART, "Unexpected hr %#x.\n", hr); + ok(part2 == NULL, "Unexpected instance %p.\n", part2); + + part2 = (void *)0xdeadbeef; + hr = IOpcPartSet_CreatePart(partset, part_uri2, typeW, OPC_COMPRESSION_NONE, &part2); + ok(hr == OPC_E_DUPLICATE_PART, "Unexpected hr %#x.\n", hr); + ok(part2 == NULL, "Unexpected instance %p.\n", part2); + IOpcPartUri_Release(part_uri2); + + hr = IOpcPartSet_GetPart(partset, NULL, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + part2 = (void *)0xdeadbeef; + hr = IOpcPartSet_GetPart(partset, NULL, &part2); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + ok(part2 == NULL, "Unexpected pointer %p.\n", part2); + + hr = IOpcPartSet_GetPart(partset, part_uri, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IOpcPartSet_GetPart(partset, part_uri, &part2); + ok(SUCCEEDED(hr), "Failed to get part, hr %#x.\n", hr); + IOpcPart_Release(part2); + + hr = IOpcFactory_CreatePartUri(factory, targetW, &part_uri2); + ok(SUCCEEDED(hr), "Failed to create part uri, hr %#x.\n", hr); + + hr = IOpcPartSet_GetPart(partset, part_uri2, &part2); + ok(hr == OPC_E_NO_SUCH_PART, "Unexpected hr %#x.\n", hr); + IOpcPartUri_Release(part_uri2); hr = IOpcPart_GetContentStream(part, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); diff --git a/include/opcbase.idl b/include/opcbase.idl index 8523271217c..d8507535634 100644 --- a/include/opcbase.idl +++ b/include/opcbase.idl @@ -43,7 +43,9 @@ typedef [v1_enum] enum cpp_quote("#define OPC_E_NONCONFORMING_URI MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x1)") cpp_quote("#define OPC_E_RELATIONSHIP_URI_REQUIRED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x3)") +cpp_quote("#define OPC_E_DUPLICATE_PART MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0xb)") cpp_quote("#define OPC_E_INVALID_RELATIONSHIP_TARGET MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x12)") +cpp_quote("#define OPC_E_NO_SUCH_PART MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x18)") cpp_quote("#define OPC_E_NO_SUCH_RELATIONSHIP MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x48)") cpp_quote("#define OPC_E_ENUM_COLLECTION_CHANGED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x50)") cpp_quote("#define OPC_E_ENUM_INVALID_POSITION MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x53)")