[WINDOWSCODECS] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / windowscodecs / icnsformat.c
1 /*
2 * Copyright 2010 Damjan Jovanovic
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <stdarg.h>
23
24 #ifdef HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H
25 #define GetCurrentProcess GetCurrentProcess_Mac
26 #define GetCurrentThread GetCurrentThread_Mac
27 #define LoadResource LoadResource_Mac
28 #define AnimatePalette AnimatePalette_Mac
29 #define EqualRgn EqualRgn_Mac
30 #define FillRgn FillRgn_Mac
31 #define FrameRgn FrameRgn_Mac
32 #define GetPixel GetPixel_Mac
33 #define InvertRgn InvertRgn_Mac
34 #define LineTo LineTo_Mac
35 #define OffsetRgn OffsetRgn_Mac
36 #define PaintRgn PaintRgn_Mac
37 #define Polygon Polygon_Mac
38 #define ResizePalette ResizePalette_Mac
39 #define SetRectRgn SetRectRgn_Mac
40 #define EqualRect EqualRect_Mac
41 #define FillRect FillRect_Mac
42 #define FrameRect FrameRect_Mac
43 #define GetCursor GetCursor_Mac
44 #define InvertRect InvertRect_Mac
45 #define OffsetRect OffsetRect_Mac
46 #define PtInRect PtInRect_Mac
47 #define SetCursor SetCursor_Mac
48 #define SetRect SetRect_Mac
49 #define ShowCursor ShowCursor_Mac
50 #define UnionRect UnionRect_Mac
51 #include <ApplicationServices/ApplicationServices.h>
52 #undef GetCurrentProcess
53 #undef GetCurrentThread
54 #undef LoadResource
55 #undef AnimatePalette
56 #undef EqualRgn
57 #undef FillRgn
58 #undef FrameRgn
59 #undef GetPixel
60 #undef InvertRgn
61 #undef LineTo
62 #undef OffsetRgn
63 #undef PaintRgn
64 #undef Polygon
65 #undef ResizePalette
66 #undef SetRectRgn
67 #undef EqualRect
68 #undef FillRect
69 #undef FrameRect
70 #undef GetCursor
71 #undef InvertRect
72 #undef OffsetRect
73 #undef PtInRect
74 #undef SetCursor
75 #undef SetRect
76 #undef ShowCursor
77 #undef UnionRect
78 #endif
79
80 #define COBJMACROS
81
82 #include "windef.h"
83 #include "winbase.h"
84 #include "objbase.h"
85
86 #include "wincodecs_private.h"
87
88 #include "wine/debug.h"
89 #include "wine/library.h"
90
91 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
92
93 #if defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) && \
94 MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
95
96 typedef struct IcnsEncoder {
97 IWICBitmapEncoder IWICBitmapEncoder_iface;
98 LONG ref;
99 IStream *stream;
100 IconFamilyHandle icns_family;
101 BOOL any_frame_committed;
102 int outstanding_commits;
103 BOOL committed;
104 CRITICAL_SECTION lock;
105 } IcnsEncoder;
106
107 static inline IcnsEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
108 {
109 return CONTAINING_RECORD(iface, IcnsEncoder, IWICBitmapEncoder_iface);
110 }
111
112 typedef struct IcnsFrameEncode {
113 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
114 IcnsEncoder *encoder;
115 LONG ref;
116 BOOL initialized;
117 UINT size;
118 OSType icns_type;
119 BYTE* icns_image;
120 int lines_written;
121 BOOL committed;
122 } IcnsFrameEncode;
123
124 static inline IcnsFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
125 {
126 return CONTAINING_RECORD(iface, IcnsFrameEncode, IWICBitmapFrameEncode_iface);
127 }
128
129 static HRESULT WINAPI IcnsFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
130 void **ppv)
131 {
132 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
133 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
134
135 if (!ppv) return E_INVALIDARG;
136
137 if (IsEqualIID(&IID_IUnknown, iid) ||
138 IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
139 {
140 *ppv = &This->IWICBitmapFrameEncode_iface;
141 }
142 else
143 {
144 *ppv = NULL;
145 return E_NOINTERFACE;
146 }
147
148 IUnknown_AddRef((IUnknown*)*ppv);
149 return S_OK;
150 }
151
152 static ULONG WINAPI IcnsFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
153 {
154 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
155 ULONG ref = InterlockedIncrement(&This->ref);
156
157 TRACE("(%p) refcount=%u\n", iface, ref);
158
159 return ref;
160 }
161
162 static ULONG WINAPI IcnsFrameEncode_Release(IWICBitmapFrameEncode *iface)
163 {
164 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
165 ULONG ref = InterlockedDecrement(&This->ref);
166
167 TRACE("(%p) refcount=%u\n", iface, ref);
168
169 if (ref == 0)
170 {
171 if (!This->committed)
172 {
173 EnterCriticalSection(&This->encoder->lock);
174 This->encoder->outstanding_commits--;
175 LeaveCriticalSection(&This->encoder->lock);
176 }
177 HeapFree(GetProcessHeap(), 0, This->icns_image);
178
179 IWICBitmapEncoder_Release(&This->encoder->IWICBitmapEncoder_iface);
180 HeapFree(GetProcessHeap(), 0, This);
181 }
182
183 return ref;
184 }
185
186 static HRESULT WINAPI IcnsFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
187 IPropertyBag2 *pIEncoderOptions)
188 {
189 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
190 HRESULT hr = S_OK;
191
192 TRACE("(%p,%p)\n", iface, pIEncoderOptions);
193
194 EnterCriticalSection(&This->encoder->lock);
195
196 if (This->initialized)
197 {
198 hr = WINCODEC_ERR_WRONGSTATE;
199 goto end;
200 }
201 This->initialized = TRUE;
202
203 end:
204 LeaveCriticalSection(&This->encoder->lock);
205 return hr;
206 }
207
208 static HRESULT WINAPI IcnsFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
209 UINT uiWidth, UINT uiHeight)
210 {
211 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
212 HRESULT hr = S_OK;
213
214 TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
215
216 EnterCriticalSection(&This->encoder->lock);
217
218 if (!This->initialized || This->icns_image)
219 {
220 hr = WINCODEC_ERR_WRONGSTATE;
221 goto end;
222 }
223
224 if (uiWidth != uiHeight)
225 {
226 WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth, uiHeight);
227 hr = E_INVALIDARG;
228 goto end;
229 }
230
231 switch (uiWidth)
232 {
233 case 16:
234 case 32:
235 case 48:
236 case 128:
237 case 256:
238 case 512:
239 break;
240 default:
241 WARN("cannot generate ICNS icon from %dx%d image\n", This->size, This->size);
242 hr = E_INVALIDARG;
243 goto end;
244 }
245
246 This->size = uiWidth;
247
248 end:
249 LeaveCriticalSection(&This->encoder->lock);
250 return hr;
251 }
252
253 static HRESULT WINAPI IcnsFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
254 double dpiX, double dpiY)
255 {
256 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
257 HRESULT hr = S_OK;
258
259 TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
260
261 EnterCriticalSection(&This->encoder->lock);
262
263 if (!This->initialized || This->icns_image)
264 {
265 hr = WINCODEC_ERR_WRONGSTATE;
266 goto end;
267 }
268
269 end:
270 LeaveCriticalSection(&This->encoder->lock);
271 return S_OK;
272 }
273
274 static HRESULT WINAPI IcnsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
275 WICPixelFormatGUID *pPixelFormat)
276 {
277 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
278 HRESULT hr = S_OK;
279
280 TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
281
282 EnterCriticalSection(&This->encoder->lock);
283
284 if (!This->initialized || This->icns_image)
285 {
286 hr = WINCODEC_ERR_WRONGSTATE;
287 goto end;
288 }
289
290 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
291
292 end:
293 LeaveCriticalSection(&This->encoder->lock);
294 return S_OK;
295 }
296
297 static HRESULT WINAPI IcnsFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
298 UINT cCount, IWICColorContext **ppIColorContext)
299 {
300 FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
301 return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI IcnsFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
305 IWICPalette *pIPalette)
306 {
307 FIXME("(%p,%p): stub\n", iface, pIPalette);
308 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
309 }
310
311 static HRESULT WINAPI IcnsFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
312 IWICBitmapSource *pIThumbnail)
313 {
314 FIXME("(%p,%p): stub\n", iface, pIThumbnail);
315 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
316 }
317
318 static HRESULT WINAPI IcnsFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
319 UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
320 {
321 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
322 HRESULT hr = S_OK;
323 UINT i;
324
325 TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
326
327 EnterCriticalSection(&This->encoder->lock);
328
329 if (!This->initialized || !This->size)
330 {
331 hr = WINCODEC_ERR_WRONGSTATE;
332 goto end;
333 }
334 if (lineCount == 0 || lineCount + This->lines_written > This->size)
335 {
336 hr = E_INVALIDARG;
337 goto end;
338 }
339
340 if (!This->icns_image)
341 {
342 switch (This->size)
343 {
344 case 16: This->icns_type = kIconServices16PixelDataARGB; break;
345 case 32: This->icns_type = kIconServices32PixelDataARGB; break;
346 case 48: This->icns_type = kIconServices48PixelDataARGB; break;
347 case 128: This->icns_type = kIconServices128PixelDataARGB; break;
348 case 256: This->icns_type = kIconServices256PixelDataARGB; break;
349 case 512: This->icns_type = kIconServices512PixelDataARGB; break;
350 default:
351 WARN("cannot generate ICNS icon from %dx%d image\n", This->size, This->size);
352 hr = E_INVALIDARG;
353 goto end;
354 }
355 This->icns_image = HeapAlloc(GetProcessHeap(), 0, This->size * This->size * 4);
356 if (!This->icns_image)
357 {
358 WARN("failed to allocate image buffer\n");
359 hr = E_FAIL;
360 goto end;
361 }
362 }
363
364 for (i = 0; i < lineCount; i++)
365 {
366 BYTE *src_row, *dst_row;
367 UINT j;
368 src_row = pbPixels + cbStride * i;
369 dst_row = This->icns_image + (This->lines_written + i)*(This->size*4);
370 /* swap bgr -> rgb */
371 for (j = 0; j < This->size*4; j += 4)
372 {
373 dst_row[j] = src_row[j+3];
374 dst_row[j+1] = src_row[j+2];
375 dst_row[j+2] = src_row[j+1];
376 dst_row[j+3] = src_row[j];
377 }
378 }
379 This->lines_written += lineCount;
380
381 end:
382 LeaveCriticalSection(&This->encoder->lock);
383 return hr;
384 }
385
386 static HRESULT WINAPI IcnsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
387 IWICBitmapSource *pIBitmapSource, WICRect *prc)
388 {
389 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
390 HRESULT hr;
391
392 TRACE("(%p,%p,%s)\n", iface, pIBitmapSource, debug_wic_rect(prc));
393
394 if (!This->initialized)
395 return WINCODEC_ERR_WRONGSTATE;
396
397 hr = configure_write_source(iface, pIBitmapSource, prc,
398 &GUID_WICPixelFormat32bppBGRA, This->size, This->size,
399 1.0, 1.0);
400
401 if (SUCCEEDED(hr))
402 {
403 hr = write_source(iface, pIBitmapSource, prc,
404 &GUID_WICPixelFormat32bppBGRA, 32, This->size, This->size);
405 }
406
407 return hr;
408 }
409
410 static HRESULT WINAPI IcnsFrameEncode_Commit(IWICBitmapFrameEncode *iface)
411 {
412 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
413 Handle handle;
414 OSErr ret;
415 HRESULT hr = S_OK;
416
417 TRACE("(%p)\n", iface);
418
419 EnterCriticalSection(&This->encoder->lock);
420
421 if (!This->icns_image || This->lines_written != This->size || This->committed)
422 {
423 hr = WINCODEC_ERR_WRONGSTATE;
424 goto end;
425 }
426
427 ret = PtrToHand(This->icns_image, &handle, This->size * This->size * 4);
428 if (ret != noErr || !handle)
429 {
430 WARN("PtrToHand failed with error %d\n", ret);
431 hr = E_FAIL;
432 goto end;
433 }
434
435 ret = SetIconFamilyData(This->encoder->icns_family, This->icns_type, handle);
436 DisposeHandle(handle);
437
438 if (ret != noErr)
439 {
440 WARN("SetIconFamilyData failed for image with error %d\n", ret);
441 hr = E_FAIL;
442 goto end;
443 }
444
445 This->committed = TRUE;
446 This->encoder->any_frame_committed = TRUE;
447 This->encoder->outstanding_commits--;
448
449 end:
450 LeaveCriticalSection(&This->encoder->lock);
451 return hr;
452 }
453
454 static HRESULT WINAPI IcnsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
455 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
456 {
457 FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
458 return E_NOTIMPL;
459 }
460
461 static const IWICBitmapFrameEncodeVtbl IcnsEncoder_FrameVtbl = {
462 IcnsFrameEncode_QueryInterface,
463 IcnsFrameEncode_AddRef,
464 IcnsFrameEncode_Release,
465 IcnsFrameEncode_Initialize,
466 IcnsFrameEncode_SetSize,
467 IcnsFrameEncode_SetResolution,
468 IcnsFrameEncode_SetPixelFormat,
469 IcnsFrameEncode_SetColorContexts,
470 IcnsFrameEncode_SetPalette,
471 IcnsFrameEncode_SetThumbnail,
472 IcnsFrameEncode_WritePixels,
473 IcnsFrameEncode_WriteSource,
474 IcnsFrameEncode_Commit,
475 IcnsFrameEncode_GetMetadataQueryWriter
476 };
477
478 static HRESULT WINAPI IcnsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
479 void **ppv)
480 {
481 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
482 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
483
484 if (!ppv) return E_INVALIDARG;
485
486 if (IsEqualIID(&IID_IUnknown, iid) ||
487 IsEqualIID(&IID_IWICBitmapEncoder, iid))
488 {
489 *ppv = &This->IWICBitmapEncoder_iface;
490 }
491 else
492 {
493 *ppv = NULL;
494 return E_NOINTERFACE;
495 }
496
497 IUnknown_AddRef((IUnknown*)*ppv);
498 return S_OK;
499 }
500
501 static ULONG WINAPI IcnsEncoder_AddRef(IWICBitmapEncoder *iface)
502 {
503 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
504 ULONG ref = InterlockedIncrement(&This->ref);
505
506 TRACE("(%p) refcount=%u\n", iface, ref);
507
508 return ref;
509 }
510
511 static ULONG WINAPI IcnsEncoder_Release(IWICBitmapEncoder *iface)
512 {
513 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
514 ULONG ref = InterlockedDecrement(&This->ref);
515
516 TRACE("(%p) refcount=%u\n", iface, ref);
517
518 if (ref == 0)
519 {
520 This->lock.DebugInfo->Spare[0] = 0;
521 DeleteCriticalSection(&This->lock);
522 if (This->icns_family)
523 DisposeHandle((Handle)This->icns_family);
524 if (This->stream)
525 IStream_Release(This->stream);
526 HeapFree(GetProcessHeap(), 0, This);
527 }
528
529 return ref;
530 }
531
532 static HRESULT WINAPI IcnsEncoder_Initialize(IWICBitmapEncoder *iface,
533 IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
534 {
535 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
536 HRESULT hr = S_OK;
537
538 TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
539
540 EnterCriticalSection(&This->lock);
541
542 if (This->icns_family)
543 {
544 hr = WINCODEC_ERR_WRONGSTATE;
545 goto end;
546 }
547 This->icns_family = (IconFamilyHandle)NewHandle(0);
548 if (!This->icns_family)
549 {
550 WARN("error creating icns family\n");
551 hr = E_FAIL;
552 goto end;
553 }
554 IStream_AddRef(pIStream);
555 This->stream = pIStream;
556
557 end:
558 LeaveCriticalSection(&This->lock);
559
560 return hr;
561 }
562
563 static HRESULT WINAPI IcnsEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
564 GUID *pguidContainerFormat)
565 {
566 FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidContainerFormat));
567 return E_NOTIMPL;
568 }
569
570 static HRESULT WINAPI IcnsEncoder_GetEncoderInfo(IWICBitmapEncoder *iface,
571 IWICBitmapEncoderInfo **ppIEncoderInfo)
572 {
573 FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo);
574 return E_NOTIMPL;
575 }
576
577 static HRESULT WINAPI IcnsEncoder_SetColorContexts(IWICBitmapEncoder *iface,
578 UINT cCount, IWICColorContext **ppIColorContext)
579 {
580 FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
581 return E_NOTIMPL;
582 }
583
584 static HRESULT WINAPI IcnsEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
585 {
586 TRACE("(%p,%p)\n", iface, pIPalette);
587 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
588 }
589
590 static HRESULT WINAPI IcnsEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
591 {
592 TRACE("(%p,%p)\n", iface, pIThumbnail);
593 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
594 }
595
596 static HRESULT WINAPI IcnsEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
597 {
598 TRACE("(%p,%p)\n", iface, pIPreview);
599 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
600 }
601
602 static HRESULT WINAPI IcnsEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
603 IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
604 {
605 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
606 HRESULT hr = S_OK;
607 IcnsFrameEncode *frameEncode = NULL;
608
609 TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
610
611 EnterCriticalSection(&This->lock);
612
613 if (!This->icns_family)
614 {
615 hr = WINCODEC_ERR_NOTINITIALIZED;
616 goto end;
617 }
618
619 if (ppIEncoderOptions)
620 {
621 hr = CreatePropertyBag2(NULL, 0, ppIEncoderOptions);
622 if (FAILED(hr))
623 goto end;
624 }
625
626 frameEncode = HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsFrameEncode));
627 if (frameEncode == NULL)
628 {
629 hr = E_OUTOFMEMORY;
630 goto end;
631 }
632 frameEncode->IWICBitmapFrameEncode_iface.lpVtbl = &IcnsEncoder_FrameVtbl;
633 frameEncode->encoder = This;
634 frameEncode->ref = 1;
635 frameEncode->initialized = FALSE;
636 frameEncode->size = 0;
637 frameEncode->icns_image = NULL;
638 frameEncode->lines_written = 0;
639 frameEncode->committed = FALSE;
640 *ppIFrameEncode = &frameEncode->IWICBitmapFrameEncode_iface;
641 This->outstanding_commits++;
642 IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface);
643
644 end:
645 LeaveCriticalSection(&This->lock);
646
647 return hr;
648 }
649
650 static HRESULT WINAPI IcnsEncoder_Commit(IWICBitmapEncoder *iface)
651 {
652 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
653 size_t buffer_size;
654 HRESULT hr = S_OK;
655 ULONG byteswritten;
656
657 TRACE("(%p)\n", iface);
658
659 EnterCriticalSection(&This->lock);
660
661 if (!This->any_frame_committed || This->outstanding_commits > 0 || This->committed)
662 {
663 hr = WINCODEC_ERR_WRONGSTATE;
664 goto end;
665 }
666
667 buffer_size = GetHandleSize((Handle)This->icns_family);
668 hr = IStream_Write(This->stream, *This->icns_family, buffer_size, &byteswritten);
669 if (FAILED(hr) || byteswritten != buffer_size)
670 {
671 WARN("writing file failed, hr = 0x%08X\n", hr);
672 hr = E_FAIL;
673 goto end;
674 }
675
676 This->committed = TRUE;
677
678 end:
679 LeaveCriticalSection(&This->lock);
680 return hr;
681 }
682
683 static HRESULT WINAPI IcnsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
684 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
685 {
686 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
687 return E_NOTIMPL;
688 }
689
690 static const IWICBitmapEncoderVtbl IcnsEncoder_Vtbl = {
691 IcnsEncoder_QueryInterface,
692 IcnsEncoder_AddRef,
693 IcnsEncoder_Release,
694 IcnsEncoder_Initialize,
695 IcnsEncoder_GetContainerFormat,
696 IcnsEncoder_GetEncoderInfo,
697 IcnsEncoder_SetColorContexts,
698 IcnsEncoder_SetPalette,
699 IcnsEncoder_SetThumbnail,
700 IcnsEncoder_SetPreview,
701 IcnsEncoder_CreateNewFrame,
702 IcnsEncoder_Commit,
703 IcnsEncoder_GetMetadataQueryWriter
704 };
705
706 HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv)
707 {
708 IcnsEncoder *This;
709 HRESULT ret;
710
711 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
712
713 *ppv = NULL;
714
715 This = HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsEncoder));
716 if (!This) return E_OUTOFMEMORY;
717
718 This->IWICBitmapEncoder_iface.lpVtbl = &IcnsEncoder_Vtbl;
719 This->ref = 1;
720 This->stream = NULL;
721 This->icns_family = NULL;
722 This->any_frame_committed = FALSE;
723 This->outstanding_commits = 0;
724 This->committed = FALSE;
725 InitializeCriticalSection(&This->lock);
726 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IcnsEncoder.lock");
727
728 ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
729 IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
730
731 return ret;
732 }
733
734 #else /* !defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) ||
735 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 */
736
737 HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv)
738 {
739 ERR("Trying to save ICNS picture, but ICNS support is not compiled in.\n");
740 return E_FAIL;
741 }
742
743 #endif