mstask: Use wide-char string literals.
[wine.git] / dlls / opcservices / factory.c
blob7ee66676c9da77723376c0aebb57f1736184b8d3
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 increasing refcount to %u.\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 decreasing refcount to %u.\n", iface, refcount);
85 if (!refcount)
87 CloseHandle(stream->hfile);
88 heap_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("iface %p, buff %p, size %u, num_read %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 %d.\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("iface %p, data %p, size %u, num_written %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 %d.\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("iface %p, move %s, origin %d, newpos %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("iface %p, flags %#x 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("iface %p, offset %s, size %s, lock_type %d 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("iface %p, offset %s, size %s, lock_type %d 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("iface %p, statstg %p, flag %d.\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 = heap_alloc_zero(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 heap_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 %#x.\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 %#x.\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 %#x.\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("iface %p, filename %s, io_mode %d, sa %p, flags %#x, stream %p.\n", iface, debugstr_w(filename),
364 io_mode, sa, flags, stream);
366 return opc_filestream_create(filename, io_mode, sa, flags, stream);
369 static HRESULT WINAPI opc_factory_CreatePackage(IOpcFactory *iface, IOpcPackage **package)
371 TRACE("iface %p, package %p.\n", iface, package);
373 return opc_package_create(iface, package);
376 static HRESULT WINAPI opc_factory_ReadPackageFromStream(IOpcFactory *iface, IStream *stream,
377 OPC_READ_FLAGS flags, IOpcPackage **package)
379 FIXME("iface %p, stream %p, flags %#x, package %p stub!\n", iface, stream, flags, package);
381 return E_NOTIMPL;
384 static HRESULT WINAPI opc_factory_WritePackageToStream(IOpcFactory *iface, IOpcPackage *package, OPC_WRITE_FLAGS flags,
385 IStream *stream)
387 TRACE("iface %p, package %p, flags %#x, stream %p.\n", iface, package, flags, stream);
389 if (!package || !stream)
390 return E_POINTER;
392 return opc_package_write(package, flags, stream);
395 static HRESULT WINAPI opc_factory_CreateDigitalSignatureManager(IOpcFactory *iface, IOpcPackage *package,
396 IOpcDigitalSignatureManager **signature_manager)
398 FIXME("iface %p, package %p, signature_manager %p stub!\n", iface, package, signature_manager);
400 return E_NOTIMPL;
403 static const IOpcFactoryVtbl opc_factory_vtbl =
405 opc_factory_QueryInterface,
406 opc_factory_AddRef,
407 opc_factory_Release,
408 opc_factory_CreatePackageRootUri,
409 opc_factory_CreatePartUri,
410 opc_factory_CreateStreamOnFile,
411 opc_factory_CreatePackage,
412 opc_factory_ReadPackageFromStream,
413 opc_factory_WritePackageToStream,
414 opc_factory_CreateDigitalSignatureManager,
417 static IOpcFactory opc_factory = { &opc_factory_vtbl };
419 static HRESULT WINAPI opc_class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
421 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
423 if (IsEqualGUID(iid, &IID_IClassFactory) ||
424 IsEqualGUID(iid, &IID_IUnknown))
426 IClassFactory_AddRef(iface);
427 *out = iface;
428 return S_OK;
431 *out = NULL;
432 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
433 return E_NOINTERFACE;
436 static ULONG WINAPI opc_class_factory_AddRef(IClassFactory *iface)
438 return 2;
441 static ULONG WINAPI opc_class_factory_Release(IClassFactory *iface)
443 return 1;
446 static HRESULT WINAPI opc_class_factory_CreateInstance(IClassFactory *iface,
447 IUnknown *outer, REFIID iid, void **out)
449 TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
451 if (outer)
452 return CLASS_E_NOAGGREGATION;
454 return IOpcFactory_QueryInterface(&opc_factory, iid, out);
457 static HRESULT WINAPI opc_class_factory_LockServer(IClassFactory *iface, BOOL dolock)
459 FIXME("iface %p, dolock %d stub!\n", iface, dolock);
460 return S_OK;
463 static const struct IClassFactoryVtbl opc_class_factory_vtbl =
465 opc_class_factory_QueryInterface,
466 opc_class_factory_AddRef,
467 opc_class_factory_Release,
468 opc_class_factory_CreateInstance,
469 opc_class_factory_LockServer
472 static IClassFactory opc_class_factory = { &opc_class_factory_vtbl };
474 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
476 TRACE("clsid %s, iid %s, out %p\n", debugstr_guid(clsid), debugstr_guid(iid), out);
478 if (IsEqualCLSID(clsid, &CLSID_OpcFactory))
479 return IClassFactory_QueryInterface(&opc_class_factory, iid, out);
481 WARN("Unsupported class %s.\n", debugstr_guid(clsid));
482 return E_NOTIMPL;
485 HRESULT WINAPI DllCanUnloadNow(void)
487 return S_FALSE;
490 static HINSTANCE OPC_hInstance;
492 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, void *reserved)
494 OPC_hInstance = hInstDLL;
496 switch (reason)
498 case DLL_PROCESS_ATTACH:
499 DisableThreadLibraryCalls(hInstDLL);
500 break;
502 return TRUE;
505 HRESULT WINAPI DllRegisterServer(void)
507 return __wine_register_resources( OPC_hInstance );
510 HRESULT WINAPI DllUnregisterServer(void)
512 return __wine_unregister_resources( OPC_hInstance );