From: Vibhav Pant vibhavp@gmail.com
--- dlls/opcservices/compress.c | 126 +++++++++++++++++++++++++++ dlls/opcservices/factory.c | 12 ++- dlls/opcservices/opc_private.h | 2 + dlls/opcservices/package.c | 6 ++ dlls/opcservices/tests/opcservices.c | 2 +- include/opcbase.idl | 2 + 6 files changed, 147 insertions(+), 3 deletions(-)
diff --git a/dlls/opcservices/compress.c b/dlls/opcservices/compress.c index 748293d7acd..fab203a1664 100644 --- a/dlls/opcservices/compress.c +++ b/dlls/opcservices/compress.c @@ -85,6 +85,7 @@ struct central_directory_end DWORD directory_offset; WORD comment_length; }; + #pragma pack(pop)
#define CENTRAL_DIR_SIGNATURE 0x02014b50 @@ -346,3 +347,128 @@ HRESULT compress_add_file(struct zip_archive *archive, const WCHAR *path,
return S_OK; } + +struct zip_part_set +{ + IOpcPartSet IOpcPartSet_iface; + LONG ref; +}; + +static inline struct zip_part_set *impl_from_IOpcPartSet(IOpcPartSet *iface) +{ + return CONTAINING_RECORD(iface, struct zip_part_set, IOpcPartSet_iface); +} + +static HRESULT WINAPI zip_part_set_QueryInterface(IOpcPartSet *iface, REFIID iid, void **out) +{ + struct zip_part_set *part_set = impl_from_IOpcPartSet(iface); + + TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IOpcPartSet)) + { + *out = &part_set->IOpcPartSet_iface; + IOpcPartSet_AddRef(iface); + return S_OK; + } + + *out = NULL; + WARN("Unsupported interface %s.\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI zip_part_set_AddRef(IOpcPartSet *iface) +{ + struct zip_part_set *part_set = impl_from_IOpcPartSet(iface); + + TRACE("(%p)\n", iface); + + return InterlockedIncrement(&part_set->ref); +} + +static ULONG WINAPI zip_part_set_Release(IOpcPartSet *iface) +{ + struct zip_part_set *part_set = impl_from_IOpcPartSet(iface); + ULONG ref = InterlockedDecrement(&part_set->ref); + + TRACE("(%p)\n", iface); + + if (!ref) + free(part_set); + return ref; +} + +static HRESULT WINAPI zip_part_set_GetPart(IOpcPartSet *iface, IOpcPartUri *name, IOpcPart **part) +{ + FIXME("(%p, %p, %p) stub\n", iface, name, part); + + *part = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI zip_part_set_CreatePart(IOpcPartSet *iface, IOpcPartUri *name, const WCHAR *type, + OPC_COMPRESSION_OPTIONS opts, IOpcPart **out) +{ + FIXME("(%p, %p, %p, %d, %p)\n", iface, name, debugstr_w(type), opts, out); + + *out = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI zip_part_set_DeletePart(IOpcPartSet *iface, IOpcPartUri *name) +{ + FIXME("(%p, %p)", iface, name); + + return E_NOTIMPL; +} + +static HRESULT WINAPI zip_part_set_PartExists(IOpcPartSet *iface, IOpcPartUri *name, BOOL *exists) +{ + FIXME("(%p, %p, %p) stub\n", iface, name, exists); + + return E_NOTIMPL; +} + +static HRESULT WINAPI zip_part_set_GetEnumerator(IOpcPartSet *iface, IOpcPartEnumerator **out) +{ + FIXME("(%p, %p) stub\n", iface, out); + + *out = NULL; + return E_NOTIMPL; +} + +static const IOpcPartSetVtbl zip_part_set_vtbl = +{ + /* IUnknown */ + zip_part_set_QueryInterface, + zip_part_set_AddRef, + zip_part_set_Release, + /* IPartSet */ + zip_part_set_GetPart, + zip_part_set_CreatePart, + zip_part_set_DeletePart, + zip_part_set_PartExists, + zip_part_set_GetEnumerator, +}; + +static HRESULT zip_part_set_create(IOpcPartSet **out) +{ + struct zip_part_set *part_set; + + if (!(part_set = calloc(1, sizeof(*part_set)))) + return E_OUTOFMEMORY; + + *out = &part_set->IOpcPartSet_iface; + part_set->IOpcPartSet_iface.lpVtbl = &zip_part_set_vtbl; + part_set->ref = 1; + *out = &part_set->IOpcPartSet_iface; + + return S_OK; +} + +HRESULT compress_open_archive(IOpcFactory *factory, IStream *stream, IOpcPartSet **part_set) +{ + FIXME("(%p, %p, %p) stub\n", factory, stream, part_set); + + return zip_part_set_create(part_set); +} diff --git a/dlls/opcservices/factory.c b/dlls/opcservices/factory.c index fcebb977c1d..5e9cab65471 100644 --- a/dlls/opcservices/factory.c +++ b/dlls/opcservices/factory.c @@ -375,9 +375,17 @@ static HRESULT WINAPI opc_factory_CreatePackage(IOpcFactory *iface, IOpcPackage static HRESULT WINAPI opc_factory_ReadPackageFromStream(IOpcFactory *iface, IStream *stream, OPC_READ_FLAGS flags, IOpcPackage **package) { - FIXME("iface %p, stream %p, flags %#x, package %p stub!\n", iface, stream, flags, package); + IOpcPartSet *part_set; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, stream %p, flags %#x, package %p\n", iface, stream, flags, package); + + if (flags) + FIXME("Unsupported flags: %#x\n", flags); + + if (FAILED(hr = compress_open_archive(iface, stream, &part_set))) + return hr; + return opc_package_create_with_partset(iface, part_set, package); }
static HRESULT WINAPI opc_factory_WritePackageToStream(IOpcFactory *iface, IOpcPackage *package, OPC_WRITE_FLAGS flags, diff --git a/dlls/opcservices/opc_private.h b/dlls/opcservices/opc_private.h index cfd8ee864b2..045716cf3e6 100644 --- a/dlls/opcservices/opc_private.h +++ b/dlls/opcservices/opc_private.h @@ -56,6 +56,7 @@ struct opc_uri };
extern HRESULT opc_package_create(IOpcFactory *factory, IOpcPackage **package); +extern HRESULT opc_package_create_with_partset(IOpcFactory *factory, IOpcPartSet *part_set, IOpcPackage **package); extern HRESULT opc_part_uri_create(IUri *uri, struct opc_uri *source_uri, IOpcPartUri **part_uri); extern HRESULT opc_root_uri_create(IOpcUri **opc_uri);
@@ -66,3 +67,4 @@ extern HRESULT compress_create_archive(IStream *output, struct zip_archive **arc extern HRESULT compress_add_file(struct zip_archive *archive, const WCHAR *path, IStream *content, OPC_COMPRESSION_OPTIONS options); extern void compress_finalize_archive(struct zip_archive *archive); +extern HRESULT compress_open_archive(IOpcFactory *factory, IStream *stream, IOpcPartSet **part_set); diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index e080b386c61..29fd766ccb6 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -1511,6 +1511,11 @@ static const IOpcPackageVtbl opc_package_vtbl = };
HRESULT opc_package_create(IOpcFactory *factory, IOpcPackage **out) +{ + return opc_package_create_with_partset(factory, NULL, out); +} + +HRESULT opc_package_create_with_partset(IOpcFactory *factory, IOpcPartSet *part_set, IOpcPackage **out) { struct opc_package *package; HRESULT hr; @@ -1526,6 +1531,7 @@ HRESULT opc_package_create(IOpcFactory *factory, IOpcPackage **out) free(package); return hr; } + if (part_set) IOpcPartSet_AddRef((package->part_set = part_set));
*out = &package->IOpcPackage_iface; TRACE("Created package %p.\n", *out); diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index 34ef87ad80b..8e878dff669 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -1313,7 +1313,7 @@ static void test_read_package(void) ok(hr == S_OK, "Failed to seek stream, hr %#lx.\n", hr);
hr = IOpcFactory_ReadPackageFromStream(factory, stream, OPC_READ_DEFAULT, &package); - todo_wine ok(hr == S_OK, "Failed to read package, hr %#lx.\n", hr); + ok(hr == S_OK, "Failed to read package, hr %#lx.\n", hr); IStream_Release(stream); if (FAILED(hr)) { diff --git a/include/opcbase.idl b/include/opcbase.idl index fcf641481e2..6f86045561e 100644 --- a/include/opcbase.idl +++ b/include/opcbase.idl @@ -51,3 +51,5 @@ cpp_quote("#define OPC_E_NO_SUCH_RELATIONSHIP MAKE_HRESULT(SEVERITY_ERROR, FACIL cpp_quote("#define OPC_E_ENUM_COLLECTION_CHANGED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x50)") cpp_quote("#define OPC_E_ENUM_CANNOT_MOVE_NEXT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x51)") cpp_quote("#define OPC_E_ENUM_INVALID_POSITION MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x53)") +cpp_quote("#define OPC_E_ZIP_CORRUPTED_ARCHIVE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x1002)") +cpp_quote("#define OPC_E_ZIP_DUPLICATE_NAME MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x100b)")