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