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, refcount %lu.\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, refcount %lu.\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("%p, %p, %lu, %p.\n", iface
, buff
, size
, num_read
);
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
);
119 TRACE("%p, %p, %lu, %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 %ld.\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("%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());
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("%p, %#lx 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("%p, %s, %s, %ld 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("%p, %s, %s, %ld 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("%p, %p, %#lx.\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
= 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());
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 IUri
*part_uri
, *root_uri
, *combined
;
326 TRACE("iface %p, uri %s, out %p.\n", iface
, debugstr_w(uri
), out
);
333 if (FAILED(hr
= CreateUri(uri
, Uri_CREATE_ALLOW_RELATIVE
, 0, &part_uri
)))
335 WARN("Failed to create uri, hr %#lx.\n", 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
);
346 hr
= CoInternetCombineIUri(root_uri
, part_uri
, 0, &combined
, 0);
347 IUri_Release(root_uri
);
348 IUri_Release(part_uri
);
351 WARN("Failed to combine URIs, hr %#lx.\n", hr
);
355 hr
= opc_part_uri_create(combined
, NULL
, out
);
356 IUri_Release(combined
);
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
);
383 static HRESULT WINAPI
opc_factory_WritePackageToStream(IOpcFactory
*iface
, IOpcPackage
*package
, OPC_WRITE_FLAGS flags
,
386 TRACE("iface %p, package %p, flags %#x, stream %p.\n", iface
, package
, flags
, stream
);
388 if (!package
|| !stream
)
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
);
402 static const IOpcFactoryVtbl opc_factory_vtbl
=
404 opc_factory_QueryInterface
,
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
);
431 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
432 return E_NOINTERFACE
;
435 static ULONG WINAPI
opc_class_factory_AddRef(IClassFactory
*iface
)
440 static ULONG WINAPI
opc_class_factory_Release(IClassFactory
*iface
)
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
);
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
);
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
));