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
31 #include "wine/debug.h"
33 #include "opc_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msopc
);
39 IStream IStream_iface
;
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
))
59 IStream_AddRef(iface
);
64 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
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
);
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
);
87 CloseHandle(stream
->hfile
);
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
);
99 TRACE("iface %p, buff %p, size %u, num_read %p.\n", iface
, buff
, size
, num_read
);
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
);
119 TRACE("iface %p, data %p, size %u, num_written %p.\n", iface
, data
, size
, num_written
);
122 num_written
= &written
;
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());
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());
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
));
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
);
162 static HRESULT WINAPI
opc_filestream_Commit(IStream
*iface
, DWORD flags
)
164 FIXME("iface %p, flags %#x stub!\n", iface
, flags
);
169 static HRESULT WINAPI
opc_filestream_Revert(IStream
*iface
)
171 FIXME("iface %p stub!\n", iface
);
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
);
185 static HRESULT WINAPI
opc_filestream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER offset
, ULARGE_INTEGER size
,
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
);
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
);
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
;
218 static HRESULT WINAPI
opc_filestream_Clone(IStream
*iface
, IStream
**result
)
220 FIXME("iface %p, result %p stub!\n", iface
, result
);
225 static const IStreamVtbl opc_filestream_vtbl
=
227 opc_filestream_QueryInterface
,
228 opc_filestream_AddRef
,
229 opc_filestream_Release
,
231 opc_filestream_Write
,
233 opc_filestream_SetSize
,
234 opc_filestream_CopyTo
,
235 opc_filestream_Commit
,
236 opc_filestream_Revert
,
237 opc_filestream_LockRegion
,
238 opc_filestream_UnlockRegion
,
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
)
254 case OPC_STREAM_IO_READ
:
255 access
= GENERIC_READ
;
256 creation
= OPEN_EXISTING
;
258 case OPC_STREAM_IO_WRITE
:
259 access
= GENERIC_WRITE
;
260 creation
= CREATE_ALWAYS
;
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());
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
);
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
))
293 IOpcFactory_AddRef(iface
);
297 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
298 return E_NOINTERFACE
;
301 static ULONG WINAPI
opc_factory_AddRef(IOpcFactory
*iface
)
306 static ULONG WINAPI
opc_factory_Release(IOpcFactory
*iface
)
311 static HRESULT WINAPI
opc_factory_CreatePackageRootUri(IOpcFactory
*iface
, IOpcUri
**uri
)
313 TRACE("iface %p, uri %p.\n", iface
, uri
);
318 return opc_root_uri_create(uri
);
321 static HRESULT WINAPI
opc_factory_CreatePartUri(IOpcFactory
*iface
, LPCWSTR uri
, IOpcPartUri
**out
)
323 static const WCHAR rootW
[] = {'/',0};
324 IUri
*part_uri
, *root_uri
, *combined
;
327 TRACE("iface %p, uri %s, out %p.\n", iface
, debugstr_w(uri
), out
);
334 if (FAILED(hr
= CreateUri(uri
, Uri_CREATE_ALLOW_RELATIVE
, 0, &part_uri
)))
336 WARN("Failed to create uri, hr %#x.\n", hr
);
340 if (FAILED(hr
= CreateUri(rootW
, Uri_CREATE_ALLOW_RELATIVE
, 0, &root_uri
)))
342 WARN("Failed to create root uri, hr %#x.\n", hr
);
343 IUri_Release(part_uri
);
347 hr
= CoInternetCombineIUri(root_uri
, part_uri
, 0, &combined
, 0);
348 IUri_Release(root_uri
);
349 IUri_Release(part_uri
);
352 WARN("Failed to combine URIs, hr %#x.\n", hr
);
356 hr
= opc_part_uri_create(combined
, NULL
, out
);
357 IUri_Release(combined
);
361 static HRESULT WINAPI
opc_factory_CreateStreamOnFile(IOpcFactory
*iface
, LPCWSTR filename
,
362 OPC_STREAM_IO_MODE io_mode
, SECURITY_ATTRIBUTES
*sa
, DWORD flags
, IStream
**stream
)
364 TRACE("iface %p, filename %s, io_mode %d, sa %p, flags %#x, stream %p.\n", iface
, debugstr_w(filename
),
365 io_mode
, sa
, flags
, stream
);
367 return opc_filestream_create(filename
, io_mode
, sa
, flags
, stream
);
370 static HRESULT WINAPI
opc_factory_CreatePackage(IOpcFactory
*iface
, IOpcPackage
**package
)
372 TRACE("iface %p, package %p.\n", iface
, package
);
374 return opc_package_create(iface
, package
);
377 static HRESULT WINAPI
opc_factory_ReadPackageFromStream(IOpcFactory
*iface
, IStream
*stream
,
378 OPC_READ_FLAGS flags
, IOpcPackage
**package
)
380 FIXME("iface %p, stream %p, flags %#x, package %p stub!\n", iface
, stream
, flags
, package
);
385 static HRESULT WINAPI
opc_factory_WritePackageToStream(IOpcFactory
*iface
, IOpcPackage
*package
, OPC_WRITE_FLAGS flags
,
388 TRACE("iface %p, package %p, flags %#x, stream %p.\n", iface
, package
, flags
, stream
);
390 if (!package
|| !stream
)
393 return opc_package_write(package
, flags
, stream
);
396 static HRESULT WINAPI
opc_factory_CreateDigitalSignatureManager(IOpcFactory
*iface
, IOpcPackage
*package
,
397 IOpcDigitalSignatureManager
**signature_manager
)
399 FIXME("iface %p, package %p, signature_manager %p stub!\n", iface
, package
, signature_manager
);
404 static const IOpcFactoryVtbl opc_factory_vtbl
=
406 opc_factory_QueryInterface
,
409 opc_factory_CreatePackageRootUri
,
410 opc_factory_CreatePartUri
,
411 opc_factory_CreateStreamOnFile
,
412 opc_factory_CreatePackage
,
413 opc_factory_ReadPackageFromStream
,
414 opc_factory_WritePackageToStream
,
415 opc_factory_CreateDigitalSignatureManager
,
418 static IOpcFactory opc_factory
= { &opc_factory_vtbl
};
420 static HRESULT WINAPI
opc_class_factory_QueryInterface(IClassFactory
*iface
, REFIID iid
, void **out
)
422 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
424 if (IsEqualGUID(iid
, &IID_IClassFactory
) ||
425 IsEqualGUID(iid
, &IID_IUnknown
))
427 IClassFactory_AddRef(iface
);
433 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
434 return E_NOINTERFACE
;
437 static ULONG WINAPI
opc_class_factory_AddRef(IClassFactory
*iface
)
442 static ULONG WINAPI
opc_class_factory_Release(IClassFactory
*iface
)
447 static HRESULT WINAPI
opc_class_factory_CreateInstance(IClassFactory
*iface
,
448 IUnknown
*outer
, REFIID iid
, void **out
)
450 TRACE("iface %p, outer %p, iid %s, out %p.\n", iface
, outer
, debugstr_guid(iid
), out
);
453 return CLASS_E_NOAGGREGATION
;
455 return IOpcFactory_QueryInterface(&opc_factory
, iid
, out
);
458 static HRESULT WINAPI
opc_class_factory_LockServer(IClassFactory
*iface
, BOOL dolock
)
460 FIXME("iface %p, dolock %d stub!\n", iface
, dolock
);
464 static const struct IClassFactoryVtbl opc_class_factory_vtbl
=
466 opc_class_factory_QueryInterface
,
467 opc_class_factory_AddRef
,
468 opc_class_factory_Release
,
469 opc_class_factory_CreateInstance
,
470 opc_class_factory_LockServer
473 static IClassFactory opc_class_factory
= { &opc_class_factory_vtbl
};
475 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID iid
, void **out
)
477 TRACE("clsid %s, iid %s, out %p\n", debugstr_guid(clsid
), debugstr_guid(iid
), out
);
479 if (IsEqualCLSID(clsid
, &CLSID_OpcFactory
))
480 return IClassFactory_QueryInterface(&opc_class_factory
, iid
, out
);
482 WARN("Unsupported class %s.\n", debugstr_guid(clsid
));
486 HRESULT WINAPI
DllCanUnloadNow(void)
491 static HINSTANCE OPC_hInstance
;
493 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD reason
, void *reserved
)
495 OPC_hInstance
= hInstDLL
;
499 case DLL_PROCESS_ATTACH
:
500 DisableThreadLibraryCalls(hInstDLL
);
506 HRESULT WINAPI
DllRegisterServer(void)
508 return __wine_register_resources( OPC_hInstance
);
511 HRESULT WINAPI
DllUnregisterServer(void)
513 return __wine_unregister_resources( OPC_hInstance
);