kernelbase/tests: Use win_skip() for missing APIs.
[wine.git] / dlls / opcservices / factory.c
blobfcebb977c1df9de417757ee6038718af3a5f853b
1 /*
2 * Copyright 2018 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
25 #include "initguid.h"
26 #include "ole2.h"
27 #include "rpcproxy.h"
28 #include "msopc.h"
29 #include "xmllite.h"
31 #include "wine/debug.h"
33 #include "opc_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msopc);
37 struct opc_filestream
39 IStream IStream_iface;
40 LONG refcount;
42 HANDLE hfile;
45 static inline struct opc_filestream *impl_from_IStream(IStream *iface)
47 return CONTAINING_RECORD(iface, struct opc_filestream, IStream_iface);
50 static HRESULT WINAPI opc_filestream_QueryInterface(IStream *iface, REFIID iid, void **out)
52 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
54 if (IsEqualIID(iid, &IID_IStream) ||
55 IsEqualIID(iid, &IID_ISequentialStream) ||
56 IsEqualIID(iid, &IID_IUnknown))
58 *out = iface;
59 IStream_AddRef(iface);
60 return S_OK;
63 *out = NULL;
64 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
65 return E_NOINTERFACE;
68 static ULONG WINAPI opc_filestream_AddRef(IStream *iface)
70 struct opc_filestream *stream = impl_from_IStream(iface);
71 ULONG refcount = InterlockedIncrement(&stream->refcount);
73 TRACE("%p, refcount %lu.\n", iface, refcount);
75 return refcount;
78 static ULONG WINAPI opc_filestream_Release(IStream *iface)
80 struct opc_filestream *stream = impl_from_IStream(iface);
81 ULONG refcount = InterlockedDecrement(&stream->refcount);
83 TRACE("%p, refcount %lu.\n", iface, refcount);
85 if (!refcount)
87 CloseHandle(stream->hfile);
88 free(stream);
91 return refcount;
94 static HRESULT WINAPI opc_filestream_Read(IStream *iface, void *buff, ULONG size, ULONG *num_read)
96 struct opc_filestream *stream = impl_from_IStream(iface);
97 DWORD read = 0;
99 TRACE("%p, %p, %lu, %p.\n", iface, buff, size, num_read);
101 if (!num_read)
102 num_read = &read;
104 *num_read = 0;
105 if (!ReadFile(stream->hfile, buff, size, num_read, NULL))
107 WARN("Failed to read file, error %ld.\n", GetLastError());
108 return HRESULT_FROM_WIN32(GetLastError());
111 return *num_read == size ? S_OK : S_FALSE;
114 static HRESULT WINAPI opc_filestream_Write(IStream *iface, const void *data, ULONG size, ULONG *num_written)
116 struct opc_filestream *stream = impl_from_IStream(iface);
117 DWORD written = 0;
119 TRACE("%p, %p, %lu, %p.\n", iface, data, size, num_written);
121 if (!num_written)
122 num_written = &written;
124 *num_written = 0;
125 if (!WriteFile(stream->hfile, data, size, num_written, NULL))
127 WARN("Failed to write to file, error %ld.\n", GetLastError());
128 return HRESULT_FROM_WIN32(GetLastError());
131 return S_OK;
134 static HRESULT WINAPI opc_filestream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *newpos)
136 struct opc_filestream *stream = impl_from_IStream(iface);
138 TRACE("%p, %s, %ld, %p.\n", iface, wine_dbgstr_longlong(move.QuadPart), origin, newpos);
140 if (!SetFilePointerEx(stream->hfile, move, (LARGE_INTEGER *)newpos, origin))
141 return HRESULT_FROM_WIN32(GetLastError());
143 return S_OK;
146 static HRESULT WINAPI opc_filestream_SetSize(IStream *iface, ULARGE_INTEGER size)
148 FIXME("iface %p, size %s stub!\n", iface, wine_dbgstr_longlong(size.QuadPart));
150 return E_NOTIMPL;
153 static HRESULT WINAPI opc_filestream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER size,
154 ULARGE_INTEGER *num_read, ULARGE_INTEGER *written)
156 FIXME("iface %p, dest %p, size %s, num_read %p, written %p stub!\n", iface, dest,
157 wine_dbgstr_longlong(size.QuadPart), num_read, written);
159 return E_NOTIMPL;
162 static HRESULT WINAPI opc_filestream_Commit(IStream *iface, DWORD flags)
164 FIXME("%p, %#lx stub!\n", iface, flags);
166 return E_NOTIMPL;
169 static HRESULT WINAPI opc_filestream_Revert(IStream *iface)
171 FIXME("iface %p stub!\n", iface);
173 return E_NOTIMPL;
176 static HRESULT WINAPI opc_filestream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
177 ULARGE_INTEGER size, DWORD lock_type)
179 FIXME("%p, %s, %s, %ld stub!\n", iface, wine_dbgstr_longlong(offset.QuadPart),
180 wine_dbgstr_longlong(size.QuadPart), lock_type);
182 return E_NOTIMPL;
185 static HRESULT WINAPI opc_filestream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size,
186 DWORD lock_type)
188 FIXME("%p, %s, %s, %ld stub!\n", iface, wine_dbgstr_longlong(offset.QuadPart),
189 wine_dbgstr_longlong(size.QuadPart), lock_type);
191 return E_NOTIMPL;
194 static HRESULT WINAPI opc_filestream_Stat(IStream *iface, STATSTG *statstg, DWORD flag)
196 struct opc_filestream *stream = impl_from_IStream(iface);
197 BY_HANDLE_FILE_INFORMATION fi;
199 TRACE("%p, %p, %#lx.\n", iface, statstg, flag);
201 if (!statstg)
202 return E_POINTER;
204 memset(&fi, 0, sizeof(fi));
205 GetFileInformationByHandle(stream->hfile, &fi);
207 memset(statstg, 0, sizeof(*statstg));
208 statstg->type = STGTY_STREAM;
209 statstg->cbSize.u.LowPart = fi.nFileSizeLow;
210 statstg->cbSize.u.HighPart = fi.nFileSizeHigh;
211 statstg->mtime = fi.ftLastWriteTime;
212 statstg->ctime = fi.ftCreationTime;
213 statstg->atime = fi.ftLastAccessTime;
215 return S_OK;
218 static HRESULT WINAPI opc_filestream_Clone(IStream *iface, IStream **result)
220 FIXME("iface %p, result %p stub!\n", iface, result);
222 return E_NOTIMPL;
225 static const IStreamVtbl opc_filestream_vtbl =
227 opc_filestream_QueryInterface,
228 opc_filestream_AddRef,
229 opc_filestream_Release,
230 opc_filestream_Read,
231 opc_filestream_Write,
232 opc_filestream_Seek,
233 opc_filestream_SetSize,
234 opc_filestream_CopyTo,
235 opc_filestream_Commit,
236 opc_filestream_Revert,
237 opc_filestream_LockRegion,
238 opc_filestream_UnlockRegion,
239 opc_filestream_Stat,
240 opc_filestream_Clone,
243 static HRESULT opc_filestream_create(const WCHAR *filename, OPC_STREAM_IO_MODE io_mode, SECURITY_ATTRIBUTES *sa,
244 DWORD flags, IStream **out)
246 struct opc_filestream *stream;
247 DWORD access, creation;
249 if (!filename || !out)
250 return E_POINTER;
252 switch (io_mode)
254 case OPC_STREAM_IO_READ:
255 access = GENERIC_READ;
256 creation = OPEN_EXISTING;
257 break;
258 case OPC_STREAM_IO_WRITE:
259 access = GENERIC_WRITE;
260 creation = CREATE_ALWAYS;
261 break;
262 default:
263 return E_INVALIDARG;
266 if (!(stream = calloc(1, sizeof(*stream))))
267 return E_OUTOFMEMORY;
269 stream->hfile = CreateFileW(filename, access, 0, sa, creation, flags, NULL);
270 if (stream->hfile == INVALID_HANDLE_VALUE)
272 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
273 free(stream);
274 return hr;
277 stream->IStream_iface.lpVtbl = &opc_filestream_vtbl;
278 stream->refcount = 1;
280 *out = &stream->IStream_iface;
281 TRACE("Created file stream %p.\n", *out);
282 return S_OK;
285 static HRESULT WINAPI opc_factory_QueryInterface(IOpcFactory *iface, REFIID iid, void **out)
287 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
289 if (IsEqualIID(iid, &IID_IOpcFactory) ||
290 IsEqualIID(iid, &IID_IUnknown))
292 *out = iface;
293 IOpcFactory_AddRef(iface);
294 return S_OK;
297 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
298 return E_NOINTERFACE;
301 static ULONG WINAPI opc_factory_AddRef(IOpcFactory *iface)
303 return 2;
306 static ULONG WINAPI opc_factory_Release(IOpcFactory *iface)
308 return 1;
311 static HRESULT WINAPI opc_factory_CreatePackageRootUri(IOpcFactory *iface, IOpcUri **uri)
313 TRACE("iface %p, uri %p.\n", iface, uri);
315 if (!uri)
316 return E_POINTER;
318 return opc_root_uri_create(uri);
321 static HRESULT WINAPI opc_factory_CreatePartUri(IOpcFactory *iface, LPCWSTR uri, IOpcPartUri **out)
323 IUri *part_uri, *root_uri, *combined;
324 HRESULT hr;
326 TRACE("iface %p, uri %s, out %p.\n", iface, debugstr_w(uri), out);
328 if (!out)
329 return E_POINTER;
331 *out = NULL;
333 if (FAILED(hr = CreateUri(uri, Uri_CREATE_ALLOW_RELATIVE, 0, &part_uri)))
335 WARN("Failed to create uri, hr %#lx.\n", hr);
336 return hr;
339 if (FAILED(hr = CreateUri(L"/", Uri_CREATE_ALLOW_RELATIVE, 0, &root_uri)))
341 WARN("Failed to create root uri, hr %#lx.\n", hr);
342 IUri_Release(part_uri);
343 return hr;
346 hr = CoInternetCombineIUri(root_uri, part_uri, 0, &combined, 0);
347 IUri_Release(root_uri);
348 IUri_Release(part_uri);
349 if (FAILED(hr))
351 WARN("Failed to combine URIs, hr %#lx.\n", hr);
352 return hr;
355 hr = opc_part_uri_create(combined, NULL, out);
356 IUri_Release(combined);
357 return hr;
360 static HRESULT WINAPI opc_factory_CreateStreamOnFile(IOpcFactory *iface, LPCWSTR filename,
361 OPC_STREAM_IO_MODE io_mode, SECURITY_ATTRIBUTES *sa, DWORD flags, IStream **stream)
363 TRACE("%p, %s, %d, %p, %#lx, %p.\n", iface, debugstr_w(filename), io_mode, sa, flags, stream);
365 return opc_filestream_create(filename, io_mode, sa, flags, stream);
368 static HRESULT WINAPI opc_factory_CreatePackage(IOpcFactory *iface, IOpcPackage **package)
370 TRACE("iface %p, package %p.\n", iface, package);
372 return opc_package_create(iface, package);
375 static HRESULT WINAPI opc_factory_ReadPackageFromStream(IOpcFactory *iface, IStream *stream,
376 OPC_READ_FLAGS flags, IOpcPackage **package)
378 FIXME("iface %p, stream %p, flags %#x, package %p stub!\n", iface, stream, flags, package);
380 return E_NOTIMPL;
383 static HRESULT WINAPI opc_factory_WritePackageToStream(IOpcFactory *iface, IOpcPackage *package, OPC_WRITE_FLAGS flags,
384 IStream *stream)
386 TRACE("iface %p, package %p, flags %#x, stream %p.\n", iface, package, flags, stream);
388 if (!package || !stream)
389 return E_POINTER;
391 return opc_package_write(package, flags, stream);
394 static HRESULT WINAPI opc_factory_CreateDigitalSignatureManager(IOpcFactory *iface, IOpcPackage *package,
395 IOpcDigitalSignatureManager **signature_manager)
397 FIXME("iface %p, package %p, signature_manager %p stub!\n", iface, package, signature_manager);
399 return E_NOTIMPL;
402 static const IOpcFactoryVtbl opc_factory_vtbl =
404 opc_factory_QueryInterface,
405 opc_factory_AddRef,
406 opc_factory_Release,
407 opc_factory_CreatePackageRootUri,
408 opc_factory_CreatePartUri,
409 opc_factory_CreateStreamOnFile,
410 opc_factory_CreatePackage,
411 opc_factory_ReadPackageFromStream,
412 opc_factory_WritePackageToStream,
413 opc_factory_CreateDigitalSignatureManager,
416 static IOpcFactory opc_factory = { &opc_factory_vtbl };
418 static HRESULT WINAPI opc_class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
420 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
422 if (IsEqualGUID(iid, &IID_IClassFactory) ||
423 IsEqualGUID(iid, &IID_IUnknown))
425 IClassFactory_AddRef(iface);
426 *out = iface;
427 return S_OK;
430 *out = NULL;
431 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
432 return E_NOINTERFACE;
435 static ULONG WINAPI opc_class_factory_AddRef(IClassFactory *iface)
437 return 2;
440 static ULONG WINAPI opc_class_factory_Release(IClassFactory *iface)
442 return 1;
445 static HRESULT WINAPI opc_class_factory_CreateInstance(IClassFactory *iface,
446 IUnknown *outer, REFIID iid, void **out)
448 TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
450 if (outer)
451 return CLASS_E_NOAGGREGATION;
453 return IOpcFactory_QueryInterface(&opc_factory, iid, out);
456 static HRESULT WINAPI opc_class_factory_LockServer(IClassFactory *iface, BOOL dolock)
458 FIXME("iface %p, dolock %d stub!\n", iface, dolock);
459 return S_OK;
462 static const struct IClassFactoryVtbl opc_class_factory_vtbl =
464 opc_class_factory_QueryInterface,
465 opc_class_factory_AddRef,
466 opc_class_factory_Release,
467 opc_class_factory_CreateInstance,
468 opc_class_factory_LockServer
471 static IClassFactory opc_class_factory = { &opc_class_factory_vtbl };
473 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
475 TRACE("clsid %s, iid %s, out %p\n", debugstr_guid(clsid), debugstr_guid(iid), out);
477 if (IsEqualCLSID(clsid, &CLSID_OpcFactory))
478 return IClassFactory_QueryInterface(&opc_class_factory, iid, out);
480 WARN("Unsupported class %s.\n", debugstr_guid(clsid));
481 return E_NOTIMPL;