1 /* 2 * Copyright 2012 Vincent Povirk for CodeWeavers 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 21 #include <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "objbase.h" 28 29 #include "wincodecs_private.h" 30 31 #include "wine/debug.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 34 35 /* WARNING: .NET Media Integration Layer (MIL) directly dereferences 36 * BitmapImpl members and depends on its exact layout. 37 */ 38 typedef struct BitmapImpl { 39 IMILUnknown1 IMILUnknown1_iface; 40 LONG ref; 41 IMILBitmapSource IMILBitmapSource_iface; 42 IWICBitmap IWICBitmap_iface; 43 IMILUnknown2 IMILUnknown2_iface; 44 IWICPalette *palette; 45 int palette_set; 46 LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */ 47 BYTE *data; 48 void *view; /* used if data is a section created by an application */ 49 UINT offset; /* offset into view */ 50 UINT width, height; 51 UINT stride; 52 UINT bpp; 53 WICPixelFormatGUID pixelformat; 54 double dpix, dpiy; 55 CRITICAL_SECTION cs; 56 } BitmapImpl; 57 58 typedef struct BitmapLockImpl { 59 IWICBitmapLock IWICBitmapLock_iface; 60 LONG ref; 61 BitmapImpl *parent; 62 UINT width, height; 63 BYTE *data; 64 } BitmapLockImpl; 65 66 static inline BitmapImpl *impl_from_IWICBitmap(IWICBitmap *iface) 67 { 68 return CONTAINING_RECORD(iface, BitmapImpl, IWICBitmap_iface); 69 } 70 71 static inline BitmapImpl *impl_from_IMILBitmapSource(IMILBitmapSource *iface) 72 { 73 return CONTAINING_RECORD(iface, BitmapImpl, IMILBitmapSource_iface); 74 } 75 76 static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface) 77 { 78 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_iface); 79 } 80 81 static inline BitmapImpl *impl_from_IMILUnknown2(IMILUnknown2 *iface) 82 { 83 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown2_iface); 84 } 85 86 static inline BitmapLockImpl *impl_from_IWICBitmapLock(IWICBitmapLock *iface) 87 { 88 return CONTAINING_RECORD(iface, BitmapLockImpl, IWICBitmapLock_iface); 89 } 90 91 static BOOL BitmapImpl_AcquireLock(BitmapImpl *This, int write) 92 { 93 if (write) 94 { 95 return 0 == InterlockedCompareExchange(&This->lock, -1, 0); 96 } 97 else 98 { 99 while (1) 100 { 101 LONG prev_val = This->lock; 102 if (prev_val == -1) 103 return FALSE; 104 if (prev_val == InterlockedCompareExchange(&This->lock, prev_val+1, prev_val)) 105 return TRUE; 106 } 107 } 108 } 109 110 static void BitmapImpl_ReleaseLock(BitmapImpl *This) 111 { 112 while (1) 113 { 114 LONG prev_val = This->lock, new_val; 115 if (prev_val == -1) 116 new_val = 0; 117 else 118 new_val = prev_val - 1; 119 if (prev_val == InterlockedCompareExchange(&This->lock, new_val, prev_val)) 120 break; 121 } 122 } 123 124 125 static HRESULT WINAPI BitmapLockImpl_QueryInterface(IWICBitmapLock *iface, REFIID iid, 126 void **ppv) 127 { 128 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 129 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 130 131 if (!ppv) return E_INVALIDARG; 132 133 if (IsEqualIID(&IID_IUnknown, iid) || 134 IsEqualIID(&IID_IWICBitmapLock, iid)) 135 { 136 *ppv = &This->IWICBitmapLock_iface; 137 } 138 else 139 { 140 FIXME("unknown interface %s\n", debugstr_guid(iid)); 141 *ppv = NULL; 142 return E_NOINTERFACE; 143 } 144 145 IUnknown_AddRef((IUnknown*)*ppv); 146 return S_OK; 147 } 148 149 static ULONG WINAPI BitmapLockImpl_AddRef(IWICBitmapLock *iface) 150 { 151 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 152 ULONG ref = InterlockedIncrement(&This->ref); 153 154 TRACE("(%p) refcount=%u\n", iface, ref); 155 156 return ref; 157 } 158 159 static ULONG WINAPI BitmapLockImpl_Release(IWICBitmapLock *iface) 160 { 161 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 162 ULONG ref = InterlockedDecrement(&This->ref); 163 164 TRACE("(%p) refcount=%u\n", iface, ref); 165 166 if (ref == 0) 167 { 168 BitmapImpl_ReleaseLock(This->parent); 169 IWICBitmap_Release(&This->parent->IWICBitmap_iface); 170 HeapFree(GetProcessHeap(), 0, This); 171 } 172 173 return ref; 174 } 175 176 static HRESULT WINAPI BitmapLockImpl_GetSize(IWICBitmapLock *iface, 177 UINT *puiWidth, UINT *puiHeight) 178 { 179 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 180 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight); 181 182 if (!puiWidth || !puiHeight) 183 return E_INVALIDARG; 184 185 *puiWidth = This->width; 186 *puiHeight = This->height; 187 188 return S_OK; 189 } 190 191 static HRESULT WINAPI BitmapLockImpl_GetStride(IWICBitmapLock *iface, 192 UINT *pcbStride) 193 { 194 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 195 TRACE("(%p,%p)\n", iface, pcbStride); 196 197 if (!pcbStride) 198 return E_INVALIDARG; 199 200 *pcbStride = This->parent->stride; 201 202 return S_OK; 203 } 204 205 static HRESULT WINAPI BitmapLockImpl_GetDataPointer(IWICBitmapLock *iface, 206 UINT *pcbBufferSize, BYTE **ppbData) 207 { 208 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 209 TRACE("(%p,%p,%p)\n", iface, pcbBufferSize, ppbData); 210 211 if (!pcbBufferSize || !ppbData) 212 return E_INVALIDARG; 213 214 *pcbBufferSize = This->parent->stride * (This->height - 1) + 215 ((This->parent->bpp * This->width) + 7)/8; 216 *ppbData = This->data; 217 218 return S_OK; 219 } 220 221 static HRESULT WINAPI BitmapLockImpl_GetPixelFormat(IWICBitmapLock *iface, 222 WICPixelFormatGUID *pPixelFormat) 223 { 224 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); 225 TRACE("(%p,%p)\n", iface, pPixelFormat); 226 227 return IWICBitmap_GetPixelFormat(&This->parent->IWICBitmap_iface, pPixelFormat); 228 } 229 230 static const IWICBitmapLockVtbl BitmapLockImpl_Vtbl = { 231 BitmapLockImpl_QueryInterface, 232 BitmapLockImpl_AddRef, 233 BitmapLockImpl_Release, 234 BitmapLockImpl_GetSize, 235 BitmapLockImpl_GetStride, 236 BitmapLockImpl_GetDataPointer, 237 BitmapLockImpl_GetPixelFormat 238 }; 239 240 static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid, 241 void **ppv) 242 { 243 BitmapImpl *This = impl_from_IWICBitmap(iface); 244 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 245 246 if (!ppv) return E_INVALIDARG; 247 248 if (IsEqualIID(&IID_IUnknown, iid) || 249 IsEqualIID(&IID_IWICBitmapSource, iid) || 250 IsEqualIID(&IID_IWICBitmap, iid)) 251 { 252 *ppv = &This->IWICBitmap_iface; 253 } 254 else if (IsEqualIID(&IID_IMILBitmap, iid) || 255 IsEqualIID(&IID_IMILBitmapSource, iid)) 256 { 257 *ppv = &This->IMILBitmapSource_iface; 258 } 259 else 260 { 261 FIXME("unknown interface %s\n", debugstr_guid(iid)); 262 *ppv = NULL; 263 return E_NOINTERFACE; 264 } 265 266 IUnknown_AddRef((IUnknown*)*ppv); 267 return S_OK; 268 } 269 270 static ULONG WINAPI BitmapImpl_AddRef(IWICBitmap *iface) 271 { 272 BitmapImpl *This = impl_from_IWICBitmap(iface); 273 ULONG ref = InterlockedIncrement(&This->ref); 274 275 TRACE("(%p) refcount=%u\n", iface, ref); 276 277 return ref; 278 } 279 280 static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) 281 { 282 BitmapImpl *This = impl_from_IWICBitmap(iface); 283 ULONG ref = InterlockedDecrement(&This->ref); 284 285 TRACE("(%p) refcount=%u\n", iface, ref); 286 287 if (ref == 0) 288 { 289 if (This->palette) IWICPalette_Release(This->palette); 290 This->cs.DebugInfo->Spare[0] = 0; 291 DeleteCriticalSection(&This->cs); 292 if (This->view) 293 UnmapViewOfFile(This->view); 294 else 295 HeapFree(GetProcessHeap(), 0, This->data); 296 HeapFree(GetProcessHeap(), 0, This); 297 } 298 299 return ref; 300 } 301 302 static HRESULT WINAPI BitmapImpl_GetSize(IWICBitmap *iface, 303 UINT *puiWidth, UINT *puiHeight) 304 { 305 BitmapImpl *This = impl_from_IWICBitmap(iface); 306 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight); 307 308 if (!puiWidth || !puiHeight) 309 return E_INVALIDARG; 310 311 *puiWidth = This->width; 312 *puiHeight = This->height; 313 314 return S_OK; 315 } 316 317 static HRESULT WINAPI BitmapImpl_GetPixelFormat(IWICBitmap *iface, 318 WICPixelFormatGUID *pPixelFormat) 319 { 320 BitmapImpl *This = impl_from_IWICBitmap(iface); 321 TRACE("(%p,%p)\n", iface, pPixelFormat); 322 323 if (!pPixelFormat) 324 return E_INVALIDARG; 325 326 memcpy(pPixelFormat, &This->pixelformat, sizeof(GUID)); 327 328 return S_OK; 329 } 330 331 static HRESULT WINAPI BitmapImpl_GetResolution(IWICBitmap *iface, 332 double *pDpiX, double *pDpiY) 333 { 334 BitmapImpl *This = impl_from_IWICBitmap(iface); 335 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY); 336 337 if (!pDpiX || !pDpiY) 338 return E_INVALIDARG; 339 340 EnterCriticalSection(&This->cs); 341 *pDpiX = This->dpix; 342 *pDpiY = This->dpiy; 343 LeaveCriticalSection(&This->cs); 344 345 return S_OK; 346 } 347 348 static HRESULT WINAPI BitmapImpl_CopyPalette(IWICBitmap *iface, 349 IWICPalette *pIPalette) 350 { 351 BitmapImpl *This = impl_from_IWICBitmap(iface); 352 TRACE("(%p,%p)\n", iface, pIPalette); 353 354 if (!This->palette_set) 355 return WINCODEC_ERR_PALETTEUNAVAILABLE; 356 357 return IWICPalette_InitializeFromPalette(pIPalette, This->palette); 358 } 359 360 static HRESULT WINAPI BitmapImpl_CopyPixels(IWICBitmap *iface, 361 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) 362 { 363 BitmapImpl *This = impl_from_IWICBitmap(iface); 364 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); 365 366 return copy_pixels(This->bpp, This->data, This->width, This->height, 367 This->stride, prc, cbStride, cbBufferSize, pbBuffer); 368 } 369 370 static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock, 371 DWORD flags, IWICBitmapLock **ppILock) 372 { 373 BitmapImpl *This = impl_from_IWICBitmap(iface); 374 BitmapLockImpl *result; 375 WICRect rc; 376 377 TRACE("(%p,%p,%x,%p)\n", iface, prcLock, flags, ppILock); 378 379 if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock) 380 return E_INVALIDARG; 381 382 if (!prcLock) 383 { 384 rc.X = rc.Y = 0; 385 rc.Width = This->width; 386 rc.Height = This->height; 387 prcLock = &rc; 388 } 389 else if (prcLock->X >= This->width || prcLock->Y >= This->height || 390 prcLock->X + prcLock->Width > This->width || 391 prcLock->Y + prcLock->Height > This->height || 392 prcLock->Width <= 0 || prcLock->Height <= 0) 393 return E_INVALIDARG; 394 else if (((prcLock->X * This->bpp) % 8) != 0) 395 { 396 FIXME("Cannot lock at an X coordinate not at a full byte\n"); 397 return E_FAIL; 398 } 399 400 result = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl)); 401 if (!result) 402 return E_OUTOFMEMORY; 403 404 if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite)) 405 { 406 HeapFree(GetProcessHeap(), 0, result); 407 return WINCODEC_ERR_ALREADYLOCKED; 408 } 409 410 result->IWICBitmapLock_iface.lpVtbl = &BitmapLockImpl_Vtbl; 411 result->ref = 1; 412 result->parent = This; 413 result->width = prcLock->Width; 414 result->height = prcLock->Height; 415 result->data = This->data + This->stride * prcLock->Y + 416 (This->bpp * prcLock->X)/8; 417 418 IWICBitmap_AddRef(&This->IWICBitmap_iface); 419 *ppILock = &result->IWICBitmapLock_iface; 420 421 return S_OK; 422 } 423 424 static HRESULT WINAPI BitmapImpl_SetPalette(IWICBitmap *iface, IWICPalette *pIPalette) 425 { 426 BitmapImpl *This = impl_from_IWICBitmap(iface); 427 HRESULT hr; 428 429 TRACE("(%p,%p)\n", iface, pIPalette); 430 431 if (!This->palette) 432 { 433 IWICPalette *new_palette; 434 hr = PaletteImpl_Create(&new_palette); 435 436 if (FAILED(hr)) return hr; 437 438 if (InterlockedCompareExchangePointer((void**)&This->palette, new_palette, NULL)) 439 { 440 /* someone beat us to it */ 441 IWICPalette_Release(new_palette); 442 } 443 } 444 445 hr = IWICPalette_InitializeFromPalette(This->palette, pIPalette); 446 447 if (SUCCEEDED(hr)) 448 This->palette_set = 1; 449 450 return S_OK; 451 } 452 453 static HRESULT WINAPI BitmapImpl_SetResolution(IWICBitmap *iface, 454 double dpiX, double dpiY) 455 { 456 BitmapImpl *This = impl_from_IWICBitmap(iface); 457 TRACE("(%p,%f,%f)\n", iface, dpiX, dpiY); 458 459 EnterCriticalSection(&This->cs); 460 This->dpix = dpiX; 461 This->dpiy = dpiY; 462 LeaveCriticalSection(&This->cs); 463 464 return S_OK; 465 } 466 467 static const IWICBitmapVtbl BitmapImpl_Vtbl = { 468 BitmapImpl_QueryInterface, 469 BitmapImpl_AddRef, 470 BitmapImpl_Release, 471 BitmapImpl_GetSize, 472 BitmapImpl_GetPixelFormat, 473 BitmapImpl_GetResolution, 474 BitmapImpl_CopyPalette, 475 BitmapImpl_CopyPixels, 476 BitmapImpl_Lock, 477 BitmapImpl_SetPalette, 478 BitmapImpl_SetResolution 479 }; 480 481 static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REFIID iid, 482 void **ppv) 483 { 484 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 485 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 486 487 if (!ppv) return E_INVALIDARG; 488 489 if (IsEqualIID(&IID_IUnknown, iid) || 490 IsEqualIID(&IID_IMILBitmap, iid) || 491 IsEqualIID(&IID_IMILBitmapSource, iid)) 492 { 493 IUnknown_AddRef(&This->IMILBitmapSource_iface); 494 *ppv = &This->IMILBitmapSource_iface; 495 return S_OK; 496 } 497 else if (IsEqualIID(&IID_IWICBitmap, iid) || 498 IsEqualIID(&IID_IWICBitmapSource, iid)) 499 { 500 IUnknown_AddRef(&This->IWICBitmap_iface); 501 *ppv = &This->IWICBitmap_iface; 502 return S_OK; 503 } 504 505 FIXME("unknown interface %s\n", debugstr_guid(iid)); 506 *ppv = NULL; 507 return E_NOINTERFACE; 508 } 509 510 static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmapSource *iface) 511 { 512 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 513 return IWICBitmap_AddRef(&This->IWICBitmap_iface); 514 } 515 516 static ULONG WINAPI IMILBitmapImpl_Release(IMILBitmapSource *iface) 517 { 518 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 519 return IWICBitmap_Release(&This->IWICBitmap_iface); 520 } 521 522 static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface, 523 UINT *width, UINT *height) 524 { 525 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 526 TRACE("(%p,%p,%p)\n", iface, width, height); 527 return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height); 528 } 529 530 static const struct 531 { 532 const GUID *WIC_format; 533 int enum_format; 534 } pixel_fmt_map[] = 535 { 536 { &GUID_WICPixelFormatDontCare, 0 }, 537 { &GUID_WICPixelFormat1bppIndexed, 1 }, 538 { &GUID_WICPixelFormat2bppIndexed, 2 }, 539 { &GUID_WICPixelFormat4bppIndexed, 3 }, 540 { &GUID_WICPixelFormat8bppIndexed, 4 }, 541 { &GUID_WICPixelFormatBlackWhite, 5 }, 542 { &GUID_WICPixelFormat2bppGray, 6 }, 543 { &GUID_WICPixelFormat4bppGray, 7 }, 544 { &GUID_WICPixelFormat8bppGray, 8 }, 545 { &GUID_WICPixelFormat16bppBGR555, 9 }, 546 { &GUID_WICPixelFormat16bppBGR565, 0x0a }, 547 { &GUID_WICPixelFormat16bppGray, 0x0b }, 548 { &GUID_WICPixelFormat24bppBGR, 0x0c }, 549 { &GUID_WICPixelFormat24bppRGB, 0x0d }, 550 { &GUID_WICPixelFormat32bppBGR, 0x0e }, 551 { &GUID_WICPixelFormat32bppBGRA, 0x0f }, 552 { &GUID_WICPixelFormat32bppPBGRA, 0x10 }, 553 { &GUID_WICPixelFormat48bppRGB, 0x15 }, 554 { &GUID_WICPixelFormat64bppRGBA, 0x16 }, 555 { &GUID_WICPixelFormat64bppPRGBA, 0x17 }, 556 { &GUID_WICPixelFormat32bppCMYK, 0x1c } 557 }; 558 559 static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface, 560 int *format) 561 { 562 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 563 int i; 564 565 TRACE("(%p,%p)\n", iface, format); 566 567 if (!format) return E_INVALIDARG; 568 569 *format = 0; 570 571 for (i = 0; i < sizeof(pixel_fmt_map)/sizeof(pixel_fmt_map[0]); i++) 572 { 573 if (IsEqualGUID(pixel_fmt_map[i].WIC_format, &This->pixelformat)) 574 { 575 *format = pixel_fmt_map[i].enum_format; 576 break; 577 } 578 } 579 580 TRACE("=> %u\n", *format); 581 return S_OK; 582 } 583 584 static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface, 585 double *dpix, double *dpiy) 586 { 587 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 588 TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); 589 return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy); 590 } 591 592 static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface, 593 IWICPalette *palette) 594 { 595 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 596 TRACE("(%p,%p)\n", iface, palette); 597 return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette); 598 } 599 600 static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface, 601 const WICRect *rc, UINT stride, UINT size, BYTE *buffer) 602 { 603 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 604 TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); 605 return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer); 606 } 607 608 static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **ppv) 609 { 610 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 611 612 TRACE("(%p,%p)\n", iface, ppv); 613 614 if (!ppv) return E_INVALIDARG; 615 616 /* reference count is not incremented here */ 617 *ppv = &This->IMILUnknown1_iface; 618 619 return S_OK; 620 } 621 622 static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmapSource *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock) 623 { 624 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 625 TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock); 626 return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock); 627 } 628 629 static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmapSource *iface, IWICBitmapLock *lock) 630 { 631 TRACE("(%p,%p)\n", iface, lock); 632 IWICBitmapLock_Release(lock); 633 return S_OK; 634 } 635 636 static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmapSource *iface, IWICPalette *palette) 637 { 638 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 639 TRACE("(%p,%p)\n", iface, palette); 640 return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette); 641 } 642 643 static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmapSource *iface, double dpix, double dpiy) 644 { 645 BitmapImpl *This = impl_from_IMILBitmapSource(iface); 646 TRACE("(%p,%f,%f)\n", iface, dpix, dpiy); 647 return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy); 648 } 649 650 static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmapSource *iface, const WICRect *rc) 651 { 652 FIXME("(%p,%p): stub\n", iface, rc); 653 return E_NOTIMPL; 654 } 655 656 static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = 657 { 658 IMILBitmapImpl_QueryInterface, 659 IMILBitmapImpl_AddRef, 660 IMILBitmapImpl_Release, 661 IMILBitmapImpl_GetSize, 662 IMILBitmapImpl_GetPixelFormat, 663 IMILBitmapImpl_GetResolution, 664 IMILBitmapImpl_CopyPalette, 665 IMILBitmapImpl_CopyPixels, 666 IMILBitmapImpl_unknown1, 667 IMILBitmapImpl_Lock, 668 IMILBitmapImpl_Unlock, 669 IMILBitmapImpl_SetPalette, 670 IMILBitmapImpl_SetResolution, 671 IMILBitmapImpl_AddDirtyRect 672 }; 673 674 static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid, 675 void **ppv) 676 { 677 FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); 678 *ppv = NULL; 679 return E_NOINTERFACE; 680 } 681 682 static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface) 683 { 684 BitmapImpl *This = impl_from_IMILUnknown1(iface); 685 return IWICBitmap_AddRef(&This->IWICBitmap_iface); 686 } 687 688 static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface) 689 { 690 BitmapImpl *This = impl_from_IMILUnknown1(iface); 691 return IWICBitmap_Release(&This->IWICBitmap_iface); 692 } 693 694 DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg) 695 { 696 FIXME("(%p,%p): stub\n", iface, arg); 697 } 698 699 static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, void *arg2) 700 { 701 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); 702 return E_NOTIMPL; 703 } 704 705 DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg) 706 { 707 FIXME("(%p,%p): stub\n", iface, arg); 708 return E_NOTIMPL; 709 } 710 711 static HRESULT WINAPI IMILUnknown1Impl_unknown4(IMILUnknown1 *iface, void *arg) 712 { 713 FIXME("(%p,%p): stub\n", iface, arg); 714 return E_NOTIMPL; 715 } 716 717 static HRESULT WINAPI IMILUnknown1Impl_unknown5(IMILUnknown1 *iface, void *arg) 718 { 719 FIXME("(%p,%p): stub\n", iface, arg); 720 return E_NOTIMPL; 721 } 722 723 static HRESULT WINAPI IMILUnknown1Impl_unknown6(IMILUnknown1 *iface, DWORD64 arg) 724 { 725 FIXME("(%p,%s): stub\n", iface, wine_dbgstr_longlong(arg)); 726 return E_NOTIMPL; 727 } 728 729 static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg) 730 { 731 FIXME("(%p,%p): stub\n", iface, arg); 732 return E_NOTIMPL; 733 } 734 735 DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface) 736 { 737 FIXME("(%p): stub\n", iface); 738 return E_NOTIMPL; 739 } 740 741 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8) 742 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8) 743 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4) 744 745 static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl = 746 { 747 IMILUnknown1Impl_QueryInterface, 748 IMILUnknown1Impl_AddRef, 749 IMILUnknown1Impl_Release, 750 THISCALL(IMILUnknown1Impl_unknown1), 751 IMILUnknown1Impl_unknown2, 752 THISCALL(IMILUnknown1Impl_unknown3), 753 IMILUnknown1Impl_unknown4, 754 IMILUnknown1Impl_unknown5, 755 IMILUnknown1Impl_unknown6, 756 IMILUnknown1Impl_unknown7, 757 THISCALL(IMILUnknown1Impl_unknown8) 758 }; 759 760 static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid, 761 void **ppv) 762 { 763 FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); 764 *ppv = NULL; 765 return E_NOINTERFACE; 766 } 767 768 static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface) 769 { 770 FIXME("(%p): stub\n", iface); 771 return 0; 772 } 773 774 static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface) 775 { 776 FIXME("(%p): stub\n", iface); 777 return 0; 778 } 779 780 static HRESULT WINAPI IMILUnknown2Impl_unknown1(IMILUnknown2 *iface, void *arg1, void **arg2) 781 { 782 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); 783 if (arg2) *arg2 = NULL; 784 return E_NOTIMPL; 785 } 786 787 static HRESULT WINAPI IMILUnknown2Impl_unknown2(IMILUnknown2 *iface, void *arg1, void *arg2) 788 { 789 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); 790 return E_NOTIMPL; 791 } 792 793 static HRESULT WINAPI IMILUnknown2Impl_unknown3(IMILUnknown2 *iface, void *arg1) 794 { 795 FIXME("(%p,%p): stub\n", iface, arg1); 796 return E_NOTIMPL; 797 } 798 799 static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl = 800 { 801 IMILUnknown2Impl_QueryInterface, 802 IMILUnknown2Impl_AddRef, 803 IMILUnknown2Impl_Release, 804 IMILUnknown2Impl_unknown1, 805 IMILUnknown2Impl_unknown2, 806 IMILUnknown2Impl_unknown3 807 }; 808 809 HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride, UINT datasize, void *view, 810 UINT offset, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, 811 IWICBitmap **ppIBitmap) 812 { 813 HRESULT hr; 814 BitmapImpl *This; 815 BYTE *data; 816 UINT bpp; 817 818 hr = get_pixelformat_bpp(pixelFormat, &bpp); 819 if (FAILED(hr)) return hr; 820 821 if (!stride) stride = (((bpp*uiWidth)+31)/32)*4; 822 if (!datasize) datasize = stride * uiHeight; 823 824 if (datasize < stride * uiHeight) return WINCODEC_ERR_INSUFFICIENTBUFFER; 825 if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG; 826 827 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl)); 828 if (!This) return E_OUTOFMEMORY; 829 830 if (view) data = (BYTE *)view + offset; 831 else if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize))) 832 { 833 HeapFree(GetProcessHeap(), 0, This); 834 return E_OUTOFMEMORY; 835 } 836 837 This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl; 838 This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl; 839 This->IMILUnknown1_iface.lpVtbl = &IMILUnknown1Impl_Vtbl; 840 This->IMILUnknown2_iface.lpVtbl = &IMILUnknown2Impl_Vtbl; 841 This->ref = 1; 842 This->palette = NULL; 843 This->palette_set = 0; 844 This->lock = 0; 845 This->data = data; 846 This->view = view; 847 This->offset = offset; 848 This->width = uiWidth; 849 This->height = uiHeight; 850 This->stride = stride; 851 This->bpp = bpp; 852 memcpy(&This->pixelformat, pixelFormat, sizeof(GUID)); 853 This->dpix = This->dpiy = 0.0; 854 InitializeCriticalSection(&This->cs); 855 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapImpl.lock"); 856 857 *ppIBitmap = &This->IWICBitmap_iface; 858 859 return S_OK; 860 } 861