ntdll: Allow NtQueryVolumeInformationFile to make async volume information queries.
[wine/zf.git] / dlls / wmphoto / unix_lib.c
blob235828941f778c97d5917c725d81987ab5fa3bba
1 /*
2 * unix_lib.c - This is the Unix side of the Unix interface.
4 * Copyright 2020 Esme Povirk
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
30 #define NONAMELESSUNION
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winternl.h"
36 #include "winbase.h"
37 #include "objbase.h"
39 #include "initguid.h"
40 #ifdef SONAME_LIBJXRGLUE
41 #define ERR JXR_ERR
42 #include <JXRGlue.h>
43 #undef ERR
44 #endif
46 #include "wincodecs_private.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
51 #include "wincodecs_common.h"
53 #ifdef SONAME_LIBJXRGLUE
54 static void *libjxrglue;
55 static typeof(PKImageDecode_Create_WMP) *pPKImageDecode_Create_WMP;
57 static const struct
59 const WICPixelFormatGUID *format;
60 UINT bpp;
61 } pixel_format_bpp[] =
63 {&GUID_PKPixelFormat128bppRGBAFixedPoint, 128},
64 {&GUID_PKPixelFormat128bppRGBAFloat, 128},
65 {&GUID_PKPixelFormat128bppRGBFloat, 128},
66 {&GUID_PKPixelFormat16bppRGB555, 16},
67 {&GUID_PKPixelFormat16bppRGB565, 16},
68 {&GUID_PKPixelFormat16bppGray, 16},
69 {&GUID_PKPixelFormat16bppGrayFixedPoint, 16},
70 {&GUID_PKPixelFormat16bppGrayHalf, 16},
71 {&GUID_PKPixelFormat24bppBGR, 24},
72 {&GUID_PKPixelFormat24bppRGB, 24},
73 {&GUID_PKPixelFormat32bppBGR, 32},
74 {&GUID_PKPixelFormat32bppRGB101010, 32},
75 {&GUID_PKPixelFormat32bppBGRA, 32},
76 {&GUID_PKPixelFormat32bppCMYK, 32},
77 {&GUID_PKPixelFormat32bppGrayFixedPoint, 32},
78 {&GUID_PKPixelFormat32bppGrayFloat, 32},
79 {&GUID_PKPixelFormat32bppRGBE, 32},
80 {&GUID_PKPixelFormat40bppCMYKAlpha, 40},
81 {&GUID_PKPixelFormat48bppRGB, 48},
82 {&GUID_PKPixelFormat48bppRGBFixedPoint, 48},
83 {&GUID_PKPixelFormat48bppRGBHalf, 48},
84 {&GUID_PKPixelFormat64bppCMYK, 64},
85 {&GUID_PKPixelFormat64bppRGBA, 64},
86 {&GUID_PKPixelFormat64bppRGBAFixedPoint, 64},
87 {&GUID_PKPixelFormat64bppRGBAHalf, 64},
88 {&GUID_PKPixelFormat80bppCMYKAlpha, 80},
89 {&GUID_PKPixelFormat8bppGray, 8},
90 {&GUID_PKPixelFormat96bppRGBFixedPoint, 96},
91 {&GUID_PKPixelFormatBlackWhite, 1},
94 static inline UINT pixel_format_get_bpp(const WICPixelFormatGUID *format)
96 int i;
97 for (i = 0; i < ARRAY_SIZE(pixel_format_bpp); ++i)
98 if (IsEqualGUID(format, pixel_format_bpp[i].format)) return pixel_format_bpp[i].bpp;
99 return 0;
102 struct wmp_decoder
104 struct decoder decoder_iface;
105 struct WMPStream WMPStream_iface;
106 PKImageDecode *decoder;
107 IStream *stream;
108 struct decoder_frame frame;
109 UINT frame_stride;
110 BYTE *frame_data;
113 static inline struct wmp_decoder *impl_from_decoder(struct decoder *iface)
115 return CONTAINING_RECORD(iface, struct wmp_decoder, decoder_iface);
118 static inline struct wmp_decoder *impl_from_WMPStream(struct WMPStream *iface)
120 return CONTAINING_RECORD(iface, struct wmp_decoder, WMPStream_iface);
123 static JXR_ERR wmp_stream_Close(struct WMPStream **piface)
125 TRACE("iface %p\n", piface);
126 return WMP_errSuccess;
129 static Bool wmp_stream_EOS(struct WMPStream *iface)
131 FIXME("iface %p, stub!\n", iface);
132 return FALSE;
135 static JXR_ERR wmp_stream_Read(struct WMPStream *iface, void *buf, size_t len)
137 struct wmp_decoder *This = impl_from_WMPStream(iface);
138 ULONG count;
139 if (FAILED(stream_read(This->stream, buf, len, &count)) || count != len)
141 WARN("Failed to read data!\n");
142 return WMP_errFileIO;
144 return WMP_errSuccess;
147 static JXR_ERR wmp_stream_Write(struct WMPStream *iface, const void *buf, size_t len)
149 struct wmp_decoder *This = impl_from_WMPStream(iface);
150 ULONG count;
151 if (FAILED(stream_write(This->stream, buf, len, &count)) || count != len)
153 WARN("Failed to write data!\n");
154 return WMP_errFileIO;
156 return WMP_errSuccess;
159 static JXR_ERR wmp_stream_SetPos(struct WMPStream *iface, size_t pos)
161 struct wmp_decoder *This = impl_from_WMPStream(iface);
162 if (FAILED(stream_seek(This->stream, pos, STREAM_SEEK_SET, NULL)))
164 WARN("Failed to set stream pos!\n");
165 return WMP_errFileIO;
167 return WMP_errSuccess;
170 static JXR_ERR wmp_stream_GetPos(struct WMPStream *iface, size_t *pos)
172 struct wmp_decoder *This = impl_from_WMPStream(iface);
173 ULONGLONG ofs;
174 if (FAILED(stream_seek(This->stream, 0, STREAM_SEEK_CUR, &ofs)))
176 WARN("Failed to get stream pos!\n");
177 return WMP_errFileIO;
179 *pos = ofs;
180 return WMP_errSuccess;
183 HRESULT CDECL wmp_decoder_initialize(struct decoder *iface, IStream *stream, struct decoder_stat *st)
185 struct wmp_decoder *This = impl_from_decoder(iface);
186 HRESULT hr;
187 Float dpix, dpiy;
188 I32 width, height;
189 U32 count;
191 TRACE("iface %p, stream %p, st %p\n", iface, stream, st);
193 if (This->stream)
194 return WINCODEC_ERR_WRONGSTATE;
196 This->stream = stream;
197 if (FAILED(hr = stream_seek(This->stream, 0, STREAM_SEEK_SET, NULL)))
198 return hr;
199 if (This->decoder->Initialize(This->decoder, &This->WMPStream_iface))
201 ERR("Failed to initialize jxrlib decoder!\n");
202 return E_FAIL;
205 if (This->decoder->GetFrameCount(This->decoder, &st->frame_count))
207 ERR("Failed to get frame count!\n");
208 return E_FAIL;
211 if (st->frame_count > 1) FIXME("multi frame JPEG-XR not implemented\n");
212 st->frame_count = 1;
213 st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
214 WICBitmapDecoderCapabilityCanDecodeSomeImages |
215 WICBitmapDecoderCapabilityCanEnumerateMetadata;
217 if (This->decoder->SelectFrame(This->decoder, 0))
219 ERR("Failed to select frame 0!\n");
220 return E_FAIL;
222 if (This->decoder->GetPixelFormat(This->decoder, &This->frame.pixel_format))
224 ERR("Failed to get frame pixel format!\n");
225 return E_FAIL;
227 if (This->decoder->GetSize(This->decoder, &width, &height))
229 ERR("Failed to get frame size!\n");
230 return E_FAIL;
232 if (This->decoder->GetResolution(This->decoder, &dpix, &dpiy))
234 ERR("Failed to get frame resolution!\n");
235 return E_FAIL;
237 if (This->decoder->GetColorContext(This->decoder, NULL, &count))
239 ERR("Failed to get frame color context size!\n");
240 return E_FAIL;
243 if (!(This->frame.bpp = pixel_format_get_bpp(&This->frame.pixel_format))) return E_FAIL;
244 This->frame.width = width;
245 This->frame.height = height;
246 This->frame.dpix = dpix;
247 This->frame.dpiy = dpiy;
248 This->frame.num_colors = 0;
249 if (count) This->frame.num_color_contexts = 1;
250 else This->frame.num_color_contexts = 0;
252 return S_OK;
255 HRESULT CDECL wmp_decoder_get_frame_info(struct decoder *iface, UINT frame, struct decoder_frame *info)
257 struct wmp_decoder *This = impl_from_decoder(iface);
259 TRACE("iface %p, frame %d, info %p\n", iface, frame, info);
261 if (frame > 0)
263 FIXME("multi frame JPEG-XR not implemented\n");
264 return E_NOTIMPL;
267 *info = This->frame;
268 return S_OK;
271 HRESULT CDECL wmp_decoder_copy_pixels(struct decoder *iface, UINT frame, const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
273 struct wmp_decoder *This = impl_from_decoder(iface);
274 PKRect pkrect;
275 U8 *frame_data;
277 TRACE("iface %p, frame %d, rect %p, stride %d, buffersize %d, buffer %p\n", iface, frame, prc, stride, buffersize, buffer);
279 if (frame > 0)
281 FIXME("multi frame JPEG-XR not implemented\n");
282 return E_NOTIMPL;
285 if (!This->frame_data)
287 pkrect.X = 0;
288 pkrect.Y = 0;
289 pkrect.Width = This->frame.width;
290 pkrect.Height = This->frame.height;
291 This->frame_stride = (This->frame.width * This->frame.bpp + 7) / 8;
292 if (!(frame_data = RtlAllocateHeap(GetProcessHeap(), 0, This->frame.height * This->frame_stride)))
293 return E_FAIL;
294 if (This->decoder->Copy(This->decoder, &pkrect, frame_data, stride))
296 ERR("Failed to copy frame data!\n");
297 RtlFreeHeap(GetProcessHeap(), 0, frame_data);
298 return E_FAIL;
301 This->frame_data = frame_data;
304 return copy_pixels(This->frame.bpp, This->frame_data,
305 This->frame.width, This->frame.height, This->frame_stride,
306 prc, stride, buffersize, buffer);
309 HRESULT CDECL wmp_decoder_get_metadata_blocks(struct decoder* iface, UINT frame, UINT *count, struct decoder_block **blocks)
311 TRACE("iface %p, frame %d, count %p, blocks %p\n", iface, frame, count, blocks);
313 *count = 0;
314 *blocks = NULL;
315 return S_OK;
318 HRESULT CDECL wmp_decoder_get_color_context(struct decoder* iface, UINT frame, UINT num, BYTE **data, DWORD *datasize)
320 struct wmp_decoder *This = impl_from_decoder(iface);
321 U32 count;
322 U8 *bytes;
324 TRACE("iface %p, frame %d, num %u, data %p, datasize %p\n", iface, frame, num, data, datasize);
326 *datasize = 0;
327 *data = NULL;
329 if (This->decoder->GetColorContext(This->decoder, NULL, &count))
331 ERR("Failed to get frame color context size!\n");
332 return E_FAIL;
334 *datasize = count;
336 bytes = RtlAllocateHeap(GetProcessHeap(), 0, count);
337 if (!bytes)
338 return E_OUTOFMEMORY;
340 if (This->decoder->GetColorContext(This->decoder, bytes, &count))
342 ERR("Failed to get frame color context!\n");
343 RtlFreeHeap(GetProcessHeap(), 0, bytes);
344 return E_FAIL;
347 *data = bytes;
348 return S_OK;
351 void CDECL wmp_decoder_destroy(struct decoder* iface)
353 struct wmp_decoder *This = impl_from_decoder(iface);
355 TRACE("iface %p\n", iface);
357 This->decoder->Release(&This->decoder);
358 RtlFreeHeap(GetProcessHeap(), 0, This->frame_data);
359 RtlFreeHeap(GetProcessHeap(), 0, This);
362 static const struct decoder_funcs wmp_decoder_vtable = {
363 wmp_decoder_initialize,
364 wmp_decoder_get_frame_info,
365 wmp_decoder_copy_pixels,
366 wmp_decoder_get_metadata_blocks,
367 wmp_decoder_get_color_context,
368 wmp_decoder_destroy
371 HRESULT CDECL wmp_decoder_create(struct decoder_info *info, struct decoder **result)
373 struct wmp_decoder *This;
374 PKImageDecode *decoder;
376 if (!pPKImageDecode_Create_WMP || pPKImageDecode_Create_WMP(&decoder)) return E_FAIL;
377 This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This));
378 if (!This)
379 return E_OUTOFMEMORY;
381 This->decoder_iface.vtable = &wmp_decoder_vtable;
382 This->WMPStream_iface.Close = &wmp_stream_Close;
383 This->WMPStream_iface.EOS = &wmp_stream_EOS;
384 This->WMPStream_iface.Read = &wmp_stream_Read;
385 This->WMPStream_iface.Write = &wmp_stream_Write;
386 This->WMPStream_iface.SetPos = &wmp_stream_SetPos;
387 This->WMPStream_iface.GetPos = &wmp_stream_GetPos;
389 This->decoder = decoder;
390 This->stream = NULL;
391 memset(&This->frame, 0, sizeof(This->frame));
392 This->frame_stride = 0;
393 This->frame_data = NULL;
395 *result = &This->decoder_iface;
397 info->container_format = GUID_ContainerFormatWmp;
398 info->block_format = GUID_ContainerFormatWmp;
399 info->clsid = CLSID_WICWmpDecoder;
401 return S_OK;
403 #endif
405 static const struct win32_funcs *win32_funcs;
407 HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size)
409 return win32_funcs->stream_getsize(stream, size);
412 HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read)
414 return win32_funcs->stream_read(stream, buffer, read, bytes_read);
417 HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position)
419 return win32_funcs->stream_seek(stream, ofs, origin, new_position);
422 HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULONG *bytes_written)
424 return win32_funcs->stream_write(stream, buffer, write, bytes_written);
427 HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result)
429 if (IsEqualGUID(decoder_clsid, &CLSID_WICWmpDecoder))
430 #ifdef SONAME_LIBJXRGLUE
431 return wmp_decoder_create(info, result);
432 #else
434 WARN("jxrlib support not compiled in, returning E_NOINTERFACE.\n");
435 return E_NOINTERFACE;
437 #endif
439 FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result);
440 return E_NOTIMPL;
443 HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result)
445 FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(encoder_clsid), info, result);
446 return E_NOTIMPL;
449 static const struct unix_funcs unix_funcs = {
450 decoder_create,
451 decoder_initialize,
452 decoder_get_frame_info,
453 decoder_copy_pixels,
454 decoder_get_metadata_blocks,
455 decoder_get_color_context,
456 decoder_destroy,
457 encoder_create,
458 encoder_initialize,
459 encoder_get_supported_format,
460 encoder_create_frame,
461 encoder_write_lines,
462 encoder_commit_frame,
463 encoder_commit_file,
464 encoder_destroy
467 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
469 if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
471 win32_funcs = ptr_in;
473 #ifdef SONAME_LIBJXRGLUE
474 if (!(libjxrglue = dlopen(SONAME_LIBJXRGLUE, RTLD_NOW)))
475 ERR("failed to load %s\n", SONAME_LIBJXRGLUE);
476 else if (!(pPKImageDecode_Create_WMP = dlsym(libjxrglue, "PKImageDecode_Create_WMP")))
477 ERR("unable to find PKImageDecode_Create_WMP in %s!\n", SONAME_LIBJXRGLUE);
478 #else
479 ERR("jxrlib support not compiled in!\n");
480 #endif
482 *(const struct unix_funcs **)ptr_out = &unix_funcs;
483 return STATUS_SUCCESS;