1 /* 2 * OLEPICTURE test program 3 * 4 * Copyright 2005 Marcus Meissner 5 * Copyright 2012 Dmitry Timoshkov 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <math.h> 25 #include <float.h> 26 27 #define COBJMACROS 28 #define CONST_VTABLE 29 #ifndef __REACTOS__ 30 #define NONAMELESSUNION 31 #endif 32 33 #include "wine/test.h" 34 #include <windef.h> 35 #include <winbase.h> 36 #include <winuser.h> 37 #include <wingdi.h> 38 #include <winnls.h> 39 #include <winerror.h> 40 #include <winnt.h> 41 42 #include <urlmon.h> 43 #include <wtypes.h> 44 #include <olectl.h> 45 #include <objidl.h> 46 47 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); } 48 49 #define ole_expect(expr, expect) { \ 50 HRESULT r = expr; \ 51 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \ 52 } 53 54 #define ole_check(expr) ole_expect(expr, S_OK); 55 56 static HMODULE hOleaut32; 57 58 static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*); 59 static HRESULT (WINAPI *pOleLoadPictureEx)(LPSTREAM,LONG,BOOL,REFIID,DWORD,DWORD,DWORD,LPVOID*); 60 61 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr) 62 63 /* 1x1 pixel gif */ 64 static const unsigned char gifimage[35] = { 65 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff, 66 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44, 67 0x01,0x00,0x3b 68 }; 69 70 /* 1x1 pixel jpg */ 71 static const unsigned char jpgimage[285] = { 72 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c, 73 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05, 74 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b, 75 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13, 76 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17, 77 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05, 78 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e, 79 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, 80 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, 81 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0, 82 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11, 83 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 84 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00, 85 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4, 86 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 87 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00, 88 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01, 89 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9 90 }; 91 92 /* 1x1 pixel png */ 93 static const unsigned char pngimage[285] = { 94 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, 95 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53, 96 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b, 97 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5, 98 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41, 99 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59, 100 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 101 }; 102 103 /* 1bpp BI_RGB 1x1 pixel bmp */ 104 static const unsigned char bmpimage[66] = { 105 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, 106 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00, 107 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, 108 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00, 109 0x00,0x00 110 }; 111 112 /* 8bpp BI_RLE8 1x1 pixel bmp */ 113 static const unsigned char bmpimage_rle8[] = { 114 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, 115 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00, 116 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, 117 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x01, 118 0x00,0x00 119 }; 120 121 /* 2x2 pixel gif */ 122 static const unsigned char gif4pixel[42] = { 123 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00, 124 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00, 125 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b 126 }; 127 128 /* APM with an empty metafile with some padding zeros - looks like under Window the 129 * metafile data should be at least 20 bytes */ 130 static const unsigned char apmdata[] = { 131 0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05, 132 0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00, 133 0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 134 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 135 }; 136 137 /* MF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */ 138 static const unsigned char metafile[] = { 139 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00, 140 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 141 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a, 142 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 143 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00, 144 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 145 0x00, 0x00 146 }; 147 148 /* EMF_TEXTOUT_ON_PATH_BITS from gdi32/tests/metafile.c */ 149 static const unsigned char enhmetafile[] = { 150 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 154 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff, 155 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 156 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 157 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 160 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 162 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, 163 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00, 164 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 165 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 166 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 167 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 168 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41, 169 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 170 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 172 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 173 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00, 174 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 175 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 176 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 177 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 178 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 179 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 180 0x14, 0x00, 0x00, 0x00 181 }; 182 183 static HBITMAP stock_bm; 184 185 static HDC create_render_dc( void ) 186 { 187 HDC dc = CreateCompatibleDC( NULL ); 188 BITMAPINFO info = {{sizeof(info.bmiHeader), 100, 100, 1, 32, BI_RGB }}; 189 void *bits; 190 HBITMAP dib = CreateDIBSection( NULL, &info, DIB_RGB_COLORS, &bits, NULL, 0 ); 191 192 stock_bm = SelectObject( dc, dib ); 193 return dc; 194 } 195 196 static void delete_render_dc( HDC dc ) 197 { 198 HBITMAP dib = SelectObject( dc, stock_bm ); 199 DeleteObject( dib ); 200 DeleteDC( dc ); 201 } 202 203 typedef struct NoStatStreamImpl 204 { 205 IStream IStream_iface; 206 LONG ref; 207 208 HGLOBAL supportHandle; 209 ULARGE_INTEGER streamSize; 210 ULARGE_INTEGER currentPosition; 211 } NoStatStreamImpl; 212 213 static IStream* NoStatStream_Construct(HGLOBAL hGlobal); 214 215 static void 216 test_pic_with_stream(LPSTREAM stream, unsigned int imgsize) 217 { 218 IPicture* pic = NULL; 219 HRESULT hres; 220 LPVOID pvObj = NULL; 221 OLE_HANDLE handle, hPal; 222 OLE_XSIZE_HIMETRIC width; 223 OLE_YSIZE_HIMETRIC height; 224 short type; 225 DWORD attr; 226 ULONG res; 227 228 pvObj = NULL; 229 hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj); 230 pic = pvObj; 231 232 ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres); 233 ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n"); 234 if (pic == NULL) 235 return; 236 237 pvObj = NULL; 238 hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj); 239 240 ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres); 241 ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n"); 242 243 IPicture_Release ((IPicture*)pvObj); 244 245 handle = 0; 246 hres = IPicture_get_Handle (pic, &handle); 247 ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres); 248 ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n"); 249 250 if (handle) 251 { 252 BITMAP bmp; 253 GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp); 254 ok(bmp.bmBits != 0, "not a dib\n"); 255 } 256 257 width = 0; 258 hres = IPicture_get_Width (pic, &width); 259 ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres); 260 ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n"); 261 262 height = 0; 263 hres = IPicture_get_Height (pic, &height); 264 ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres); 265 ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n"); 266 267 type = 0; 268 hres = IPicture_get_Type (pic, &type); 269 ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres); 270 ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP); 271 272 attr = 0; 273 hres = IPicture_get_Attributes (pic, &attr); 274 ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres); 275 ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr); 276 277 hPal = 0; 278 hres = IPicture_get_hPal (pic, &hPal); 279 ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres); 280 /* a single pixel b/w image has no palette */ 281 ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal); 282 283 res = IPicture_Release (pic); 284 ok (res == 0, "refcount after release is %d, but should be 0?\n", res); 285 } 286 287 static void 288 test_pic(const unsigned char *imgdata, unsigned int imgsize) 289 { 290 LPSTREAM stream; 291 HGLOBAL hglob; 292 LPBYTE data; 293 HRESULT hres; 294 LARGE_INTEGER seekto; 295 ULARGE_INTEGER newpos1; 296 DWORD * header; 297 unsigned int i,j; 298 299 /* Let the fun begin */ 300 hglob = GlobalAlloc (0, imgsize); 301 data = GlobalLock (hglob); 302 memcpy(data, imgdata, imgsize); 303 GlobalUnlock(hglob); data = NULL; 304 305 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream); 306 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres); 307 308 memset(&seekto,0,sizeof(seekto)); 309 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1); 310 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres); 311 test_pic_with_stream(stream, imgsize); 312 313 IStream_Release(stream); 314 315 /* again with Non Statable and Non Seekable stream */ 316 stream = NoStatStream_Construct(hglob); 317 hglob = 0; /* Non-statable impl always deletes on release */ 318 test_pic_with_stream(stream, 0); 319 320 IStream_Release(stream); 321 for (i = 1; i <= 8; i++) { 322 /* more fun!!! */ 323 hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD))); 324 data = GlobalLock (hglob); 325 header = (DWORD *)data; 326 327 /* multiple copies of header */ 328 memcpy(data,"lt\0\0",4); 329 header[1] = imgsize; 330 for (j = 2; j <= i; j++) { 331 memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD)); 332 } 333 memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize); 334 GlobalUnlock(hglob); data = NULL; 335 336 hres = CreateStreamOnHGlobal (hglob, FALSE, &stream); 337 ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres); 338 339 memset(&seekto,0,sizeof(seekto)); 340 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1); 341 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres); 342 test_pic_with_stream(stream, imgsize); 343 344 IStream_Release(stream); 345 346 /* again with Non Statable and Non Seekable stream */ 347 stream = NoStatStream_Construct(hglob); 348 hglob = 0; /* Non-statable impl always deletes on release */ 349 test_pic_with_stream(stream, 0); 350 351 IStream_Release(stream); 352 } 353 } 354 355 static void test_empty_image(void) { 356 LPBYTE data; 357 LPSTREAM stream; 358 IPicture* pic = NULL; 359 HRESULT hres; 360 LPVOID pvObj = NULL; 361 HGLOBAL hglob; 362 OLE_HANDLE handle; 363 ULARGE_INTEGER newpos1; 364 LARGE_INTEGER seekto; 365 short type; 366 DWORD attr; 367 368 /* Empty image. Happens occasionally in VB programs. */ 369 hglob = GlobalAlloc (0, 8); 370 data = GlobalLock (hglob); 371 memcpy(data,"lt\0\0",4); 372 ((DWORD*)data)[1] = 0; 373 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream); 374 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres); 375 376 memset(&seekto,0,sizeof(seekto)); 377 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1); 378 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres); 379 380 pvObj = NULL; 381 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj); 382 pic = pvObj; 383 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres); 384 ok(pic != NULL,"empty picture not loaded, pic is NULL\n"); 385 386 hres = IPicture_get_Type (pic, &type); 387 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres); 388 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type); 389 390 attr = 0xdeadbeef; 391 hres = IPicture_get_Attributes (pic, &attr); 392 ok (hres == S_OK,"empty picture get attributes failed with hres 0x%08x\n", hres); 393 ok (attr == 0,"attr is %d, but should be 0\n", attr); 394 395 hres = IPicture_get_Handle (pic, &handle); 396 ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres); 397 ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle); 398 IPicture_Release (pic); 399 IStream_Release (stream); 400 } 401 402 static void test_empty_image_2(void) { 403 LPBYTE data; 404 LPSTREAM stream; 405 IPicture* pic = NULL; 406 HRESULT hres; 407 LPVOID pvObj = NULL; 408 HGLOBAL hglob; 409 ULARGE_INTEGER newpos1; 410 LARGE_INTEGER seekto; 411 short type; 412 413 /* Empty image at random stream position. */ 414 hglob = GlobalAlloc (0, 200); 415 data = GlobalLock (hglob); 416 data += 42; 417 memcpy(data,"lt\0\0",4); 418 ((DWORD*)data)[1] = 0; 419 hres = CreateStreamOnHGlobal (hglob, TRUE, &stream); 420 ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres); 421 422 memset(&seekto,0,sizeof(seekto)); 423 seekto.u.LowPart = 42; 424 hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1); 425 ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres); 426 427 pvObj = NULL; 428 hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj); 429 pic = pvObj; 430 ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres); 431 ok(pic != NULL,"empty picture not loaded, pic is NULL\n"); 432 433 hres = IPicture_get_Type (pic, &type); 434 ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres); 435 ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type); 436 437 IPicture_Release (pic); 438 IStream_Release (stream); 439 } 440 441 static void test_Invoke(void) 442 { 443 IPictureDisp *picdisp; 444 HRESULT hr; 445 VARIANTARG vararg, args[10]; 446 DISPPARAMS dispparams; 447 VARIANT varresult; 448 IStream *stream; 449 HGLOBAL hglob; 450 void *data; 451 HDC hdc; 452 int i; 453 454 hglob = GlobalAlloc (0, sizeof(gifimage)); 455 data = GlobalLock(hglob); 456 memcpy(data, gifimage, sizeof(gifimage)); 457 GlobalUnlock(hglob); 458 459 hr = CreateStreamOnHGlobal (hglob, FALSE, &stream); 460 ok_ole_success(hr, "CreateStreamOnHGlobal"); 461 462 hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp); 463 IStream_Release(stream); 464 GlobalFree(hglob); 465 ok_ole_success(hr, "OleLoadPicture"); 466 467 V_VT(&vararg) = VT_BOOL; 468 V_BOOL(&vararg) = VARIANT_FALSE; 469 dispparams.cNamedArgs = 0; 470 dispparams.rgdispidNamedArgs = NULL; 471 dispparams.cArgs = 1; 472 dispparams.rgvarg = &vararg; 473 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); 474 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr); 475 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); 476 ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr); 477 478 dispparams.cArgs = 0; 479 dispparams.rgvarg = NULL; 480 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); 481 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr); 482 483 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL); 484 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr); 485 486 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL); 487 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr); 488 489 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL); 490 ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr); 491 492 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL); 493 ok_ole_success(hr, "IPictureDisp_Invoke"); 494 ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult)); 495 496 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL); 497 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr); 498 499 hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL); 500 ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr); 501 502 dispparams.cArgs = 1; 503 dispparams.rgvarg = &vararg; 504 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL); 505 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr); 506 507 dispparams.cArgs = 1; 508 dispparams.rgvarg = &vararg; 509 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL); 510 ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr); 511 512 /* DISPID_PICT_RENDER */ 513 hdc = create_render_dc(); 514 515 for (i = 0; i < ARRAY_SIZE(args); i++) 516 V_VT(&args[i]) = VT_I4; 517 518 V_I4(&args[0]) = 0; 519 V_I4(&args[1]) = 10; 520 V_I4(&args[2]) = 10; 521 V_I4(&args[3]) = 0; 522 V_I4(&args[4]) = 0; 523 V_I4(&args[5]) = 10; 524 V_I4(&args[6]) = 10; 525 V_I4(&args[7]) = 0; 526 V_I4(&args[8]) = 0; 527 V_I4(&args[9]) = HandleToLong(hdc); 528 529 dispparams.rgvarg = args; 530 dispparams.rgdispidNamedArgs = NULL; 531 dispparams.cArgs = 10; 532 dispparams.cNamedArgs = 0; 533 534 V_VT(&varresult) = VT_EMPTY; 535 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL); 536 ok(hr == S_OK, "got 0x%08x\n", hr); 537 538 /* Try with one argument set to VT_I2, it'd still work if coerced. */ 539 V_VT(&args[3]) = VT_I2; 540 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL); 541 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr); 542 V_VT(&args[3]) = VT_I4; 543 544 /* Wrong argument count */ 545 dispparams.cArgs = 9; 546 hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL); 547 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr); 548 549 delete_render_dc(hdc); 550 IPictureDisp_Release(picdisp); 551 } 552 553 static HRESULT create_picture(short type, IPicture **pict) 554 { 555 PICTDESC desc; 556 557 desc.cbSizeofstruct = sizeof(desc); 558 desc.picType = type; 559 560 switch (type) 561 { 562 case PICTYPE_UNINITIALIZED: 563 return OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)pict); 564 565 case PICTYPE_NONE: 566 break; 567 568 case PICTYPE_BITMAP: 569 desc.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL); 570 desc.bmp.hpal = (HPALETTE)0xbeefdead; 571 break; 572 573 case PICTYPE_ICON: 574 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION); 575 break; 576 577 case PICTYPE_METAFILE: 578 { 579 HDC hdc = CreateMetaFileA(NULL); 580 desc.wmf.hmeta = CloseMetaFile(hdc); 581 desc.wmf.xExt = 1; 582 desc.wmf.yExt = 1; 583 break; 584 } 585 586 case PICTYPE_ENHMETAFILE: 587 { 588 HDC hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); 589 desc.emf.hemf = CloseEnhMetaFile(hdc); 590 break; 591 } 592 593 default: 594 ok(0, "picture type %d is not supported\n", type); 595 return E_NOTIMPL; 596 } 597 598 return OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)pict); 599 } 600 601 static void test_OleCreatePictureIndirect(void) 602 { 603 PICTDESC desc; 604 OLE_HANDLE handle; 605 IPicture *pict; 606 HRESULT hr; 607 short type, i; 608 609 if (0) 610 { 611 /* crashes on native */ 612 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL); 613 } 614 615 desc.cbSizeofstruct = sizeof(desc); 616 desc.picType = PICTYPE_UNINITIALIZED; 617 pict = (void *)0xdeadbeef; 618 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pict); 619 ok(hr == E_UNEXPECTED, "got %#x\n", hr); 620 ok(pict == NULL, "got %p\n", pict); 621 622 for (i = PICTYPE_UNINITIALIZED; i <= PICTYPE_ENHMETAFILE; i++) 623 { 624 hr = create_picture(i, &pict); 625 ok(hr == S_OK, "%d: got %#x\n", i, hr); 626 627 type = 0xdead; 628 hr = IPicture_get_Type(pict, &type); 629 ok(hr == S_OK, "%d: got %#x\n", i, hr); 630 ok(type == i, "%d: got %d\n", i, type); 631 632 handle = 0xdeadbeef; 633 hr = IPicture_get_Handle(pict, &handle); 634 ok(hr == S_OK, "%d: got %#x\n", i, hr); 635 if (type == PICTYPE_UNINITIALIZED || type == PICTYPE_NONE) 636 ok(handle == 0, "%d: got %#x\n", i, handle); 637 else 638 ok(handle != 0 && handle != 0xdeadbeef, "%d: got %#x\n", i, handle); 639 640 handle = 0xdeadbeef; 641 hr = IPicture_get_hPal(pict, &handle); 642 if (type == PICTYPE_BITMAP) 643 { 644 ok(hr == S_OK, "%d: got %#x\n", i, hr); 645 ok(handle == 0xbeefdead, "%d: got %#x\n", i, handle); 646 } 647 else 648 { 649 ok(hr == E_FAIL, "%d: got %#x\n", i, hr); 650 ok(handle == 0xdeadbeef || handle == 0 /* win64 */, "%d: got %#x\n", i, handle); 651 } 652 653 hr = IPicture_set_hPal(pict, HandleToUlong(GetStockObject(DEFAULT_PALETTE))); 654 if (type == PICTYPE_BITMAP) 655 ok(hr == S_OK, "%d: got %#x\n", i, hr); 656 else 657 ok(hr == E_FAIL, "%d: got %#x\n", i, hr); 658 659 IPicture_Release(pict); 660 } 661 } 662 663 static void test_apm(void) 664 { 665 OLE_HANDLE handle; 666 LPSTREAM stream; 667 IPicture *pict; 668 HGLOBAL hglob; 669 LPBYTE *data; 670 LONG cxy; 671 BOOL keep; 672 short type; 673 674 hglob = GlobalAlloc (0, sizeof(apmdata)); 675 data = GlobalLock(hglob); 676 memcpy(data, apmdata, sizeof(apmdata)); 677 678 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream)); 679 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict)); 680 681 ole_check(IPicture_get_Handle(pict, &handle)); 682 ok(handle != 0, "handle is null\n"); 683 684 ole_check(IPicture_get_Type(pict, &type)); 685 expect_eq(type, PICTYPE_METAFILE, short, "%d"); 686 687 ole_check(IPicture_get_Height(pict, &cxy)); 688 expect_eq(cxy, 1667, LONG, "%d"); 689 690 ole_check(IPicture_get_Width(pict, &cxy)); 691 expect_eq(cxy, 1323, LONG, "%d"); 692 693 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep)); 694 todo_wine expect_eq(keep, FALSE, LONG, "%d"); 695 696 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL); 697 IPicture_Release(pict); 698 IStream_Release(stream); 699 } 700 701 static void test_metafile(void) 702 { 703 LPSTREAM stream; 704 IPicture *pict; 705 HGLOBAL hglob; 706 LPBYTE *data; 707 708 hglob = GlobalAlloc (0, sizeof(metafile)); 709 data = GlobalLock(hglob); 710 memcpy(data, metafile, sizeof(metafile)); 711 712 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream)); 713 /* Windows does not load simple metafiles */ 714 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL); 715 716 IStream_Release(stream); 717 } 718 719 static void test_enhmetafile(void) 720 { 721 OLE_HANDLE handle; 722 LPSTREAM stream; 723 IPicture *pict; 724 HGLOBAL hglob; 725 LPBYTE *data; 726 LONG cxy; 727 BOOL keep; 728 short type; 729 730 hglob = GlobalAlloc (0, sizeof(enhmetafile)); 731 data = GlobalLock(hglob); 732 memcpy(data, enhmetafile, sizeof(enhmetafile)); 733 734 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream)); 735 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict)); 736 737 ole_check(IPicture_get_Handle(pict, &handle)); 738 ok(handle != 0, "handle is null\n"); 739 740 ole_check(IPicture_get_Type(pict, &type)); 741 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d"); 742 743 ole_check(IPicture_get_Height(pict, &cxy)); 744 expect_eq(cxy, -23, LONG, "%d"); 745 746 ole_check(IPicture_get_Width(pict, &cxy)); 747 expect_eq(cxy, -25, LONG, "%d"); 748 749 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep)); 750 todo_wine expect_eq(keep, FALSE, LONG, "%d"); 751 752 IPicture_Release(pict); 753 IStream_Release(stream); 754 } 755 756 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy, 757 OLE_XPOS_HIMETRIC xSrc, 758 OLE_YPOS_HIMETRIC ySrc, 759 OLE_XSIZE_HIMETRIC cxSrc, 760 OLE_YSIZE_HIMETRIC cySrc, 761 const RECT *bounds) 762 { 763 VARIANT ret, args[10]; 764 HRESULT hr, hr_disp; 765 DISPPARAMS params; 766 IDispatch *disp; 767 int i; 768 769 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds); 770 771 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp); 772 773 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */ 774 for (i = 0; i < ARRAY_SIZE(args); i++) 775 V_VT(&args[i]) = VT_I4; 776 777 /* pack arguments and call */ 778 V_INT_PTR(&args[0]) = (INT_PTR)bounds; 779 V_I4(&args[1]) = cySrc; 780 V_I4(&args[2]) = cxSrc; 781 V_I4(&args[3]) = ySrc; 782 V_I4(&args[4]) = xSrc; 783 V_I4(&args[5]) = cy; 784 V_I4(&args[6]) = cx; 785 V_I4(&args[7]) = y; 786 V_I4(&args[8]) = x; 787 V_I4(&args[9]) = HandleToLong(hdc); 788 789 params.rgvarg = args; 790 params.rgdispidNamedArgs = NULL; 791 params.cArgs = 10; 792 params.cNamedArgs = 0; 793 794 V_VT(&ret) = VT_EMPTY; 795 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, 796 ¶ms, &ret, NULL, NULL); 797 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n", 798 hr_disp, hr); 799 800 IDispatch_Release(disp); 801 802 return hr; 803 } 804 805 static void test_Render(void) 806 { 807 IPicture *pic; 808 HRESULT hres; 809 short type; 810 PICTDESC desc; 811 OLE_XSIZE_HIMETRIC pWidth; 812 OLE_YSIZE_HIMETRIC pHeight; 813 COLORREF result, expected; 814 HDC hdc = create_render_dc(); 815 816 /* test IPicture::Render return code on uninitialized picture */ 817 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 818 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 819 hres = IPicture_get_Type(pic, &type); 820 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres); 821 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type); 822 /* zero dimensions */ 823 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL); 824 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 825 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL); 826 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 827 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL); 828 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 829 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL); 830 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 831 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL); 832 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 833 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL); 834 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 835 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL); 836 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 837 /* nonzero dimensions, PICTYPE_UNINITIALIZED */ 838 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL); 839 ole_expect(hres, S_OK); 840 IPicture_Release(pic); 841 842 desc.cbSizeofstruct = sizeof(PICTDESC); 843 desc.picType = PICTYPE_ICON; 844 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION); 845 if(!desc.icon.hicon){ 846 win_skip("LoadIcon failed. Skipping...\n"); 847 delete_render_dc(hdc); 848 return; 849 } 850 851 hres = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pic); 852 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 853 /* zero dimensions, PICTYPE_ICON */ 854 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL); 855 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 856 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL); 857 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 858 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL); 859 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 860 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL); 861 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 862 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL); 863 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 864 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL); 865 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 866 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL); 867 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 868 869 /* Check if target size and position is respected */ 870 IPicture_get_Width(pic, &pWidth); 871 IPicture_get_Height(pic, &pHeight); 872 873 SetPixelV(hdc, 0, 0, 0x00223344); 874 SetPixelV(hdc, 5, 5, 0x00223344); 875 SetPixelV(hdc, 10, 10, 0x00223344); 876 expected = GetPixel(hdc, 0, 0); 877 878 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, pHeight, pWidth, -pHeight, NULL); 879 ole_expect(hres, S_OK); 880 881 if(hres != S_OK) goto done; 882 883 /* Evaluate the rendered Icon */ 884 result = GetPixel(hdc, 0, 0); 885 ok(result == expected, 886 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result); 887 result = GetPixel(hdc, 5, 5); 888 ok(result != expected, 889 "Color at 5,5 should have changed, but still was 0x%06X\n", expected); 890 result = GetPixel(hdc, 10, 10); 891 ok(result == expected, 892 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result); 893 894 done: 895 IPicture_Release(pic); 896 delete_render_dc(hdc); 897 } 898 899 static void test_get_Attributes(void) 900 { 901 IPicture *pic; 902 HRESULT hres; 903 short type; 904 DWORD attr; 905 906 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 907 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 908 hres = IPicture_get_Type(pic, &type); 909 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres); 910 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type); 911 912 hres = IPicture_get_Attributes(pic, NULL); 913 ole_expect(hres, E_POINTER); 914 915 attr = 0xdeadbeef; 916 hres = IPicture_get_Attributes(pic, &attr); 917 ole_expect(hres, S_OK); 918 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr); 919 920 IPicture_Release(pic); 921 } 922 923 static void test_get_Handle(void) 924 { 925 IPicture *pic; 926 HRESULT hres; 927 928 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 929 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 930 hres = IPicture_get_Handle(pic, NULL); 931 ole_expect(hres, E_POINTER); 932 933 IPicture_Release(pic); 934 } 935 936 static void test_get_Type(void) 937 { 938 IPicture *pic; 939 HRESULT hres; 940 941 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 942 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 943 944 hres = IPicture_get_Type(pic, NULL); 945 ole_expect(hres, E_POINTER); 946 947 IPicture_Release(pic); 948 } 949 950 static void test_OleLoadPicturePath(void) 951 { 952 static WCHAR emptyW[] = {0}; 953 954 IPicture *pic; 955 HRESULT hres; 956 int i; 957 char temp_path[MAX_PATH]; 958 char temp_file[MAX_PATH]; 959 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'}; 960 HANDLE file; 961 DWORD size; 962 WCHAR *ptr; 963 VARIANT var; 964 965 const struct 966 { 967 LPOLESTR szURLorPath; 968 REFIID riid; 969 IPicture **pic; 970 } invalid_parameters[] = 971 { 972 {NULL, NULL, NULL}, 973 {NULL, NULL, &pic}, 974 {NULL, &IID_IPicture, NULL}, 975 {NULL, &IID_IPicture, &pic}, 976 {emptyW, NULL, NULL}, 977 {emptyW, &IID_IPicture, NULL}, 978 }; 979 980 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++) 981 { 982 pic = (IPicture *)0xdeadbeef; 983 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0, 984 invalid_parameters[i].riid, 985 (void **)invalid_parameters[i].pic); 986 ok(hres == E_INVALIDARG, 987 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres); 988 ok(pic == (IPicture *)0xdeadbeef, 989 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic); 990 } 991 992 pic = (IPicture *)0xdeadbeef; 993 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic); 994 todo_wine 995 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */ 996 broken(hres == E_UNEXPECTED) || /* NT4 */ 997 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */ 998 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres); 999 ok(pic == NULL, 1000 "Expected the output interface pointer to be NULL, got %p\n", pic); 1001 1002 pic = (IPicture *)0xdeadbeef; 1003 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1004 todo_wine 1005 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */ 1006 broken(hres == E_UNEXPECTED) || /* NT4 */ 1007 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */ 1008 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres); 1009 ok(pic == NULL, 1010 "Expected the output interface pointer to be NULL, got %p\n", pic); 1011 1012 /* Create a local temporary image file for testing. */ 1013 GetTempPathA(sizeof(temp_path), temp_path); 1014 GetTempFileNameA(temp_path, "bmp", 0, temp_file); 1015 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1016 FILE_ATTRIBUTE_NORMAL, NULL); 1017 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL); 1018 CloseHandle(file); 1019 1020 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, ARRAY_SIZE(temp_fileW) - 8); 1021 1022 /* Try a normal DOS path. */ 1023 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1024 ok(hres == S_OK || 1025 broken(hres == E_UNEXPECTED), /* NT4 */ 1026 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres); 1027 if (pic) 1028 IPicture_Release(pic); 1029 1030 VariantInit(&var); 1031 V_VT(&var) = VT_BSTR; 1032 V_BSTR(&var) = SysAllocString(temp_fileW + 8); 1033 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1034 ok(hres == S_OK, "OleLoadPictureFile error %#x\n", hres); 1035 IPicture_Release(pic); 1036 VariantClear(&var); 1037 1038 /* Try a DOS path with tacked on "file:". */ 1039 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1040 ok(hres == S_OK || 1041 broken(hres == E_UNEXPECTED), /* NT4 */ 1042 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres); 1043 if (pic) 1044 IPicture_Release(pic); 1045 1046 VariantInit(&var); 1047 V_VT(&var) = VT_BSTR; 1048 V_BSTR(&var) = SysAllocString(temp_fileW); 1049 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1050 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 1051 VariantClear(&var); 1052 1053 DeleteFileA(temp_file); 1054 1055 /* Try with a nonexistent file. */ 1056 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1057 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */ 1058 broken(hres == E_UNEXPECTED) || /* NT4 */ 1059 broken(hres == E_FAIL), /*Win2k */ 1060 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres); 1061 1062 VariantInit(&var); 1063 V_VT(&var) = VT_BSTR; 1064 V_BSTR(&var) = SysAllocString(temp_fileW + 8); 1065 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1066 ok(hres == CTL_E_FILENOTFOUND, "wrong error %#x\n", hres); 1067 VariantClear(&var); 1068 1069 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1070 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */ 1071 broken(hres == E_UNEXPECTED) || /* NT4 */ 1072 broken(hres == E_FAIL), /* Win2k */ 1073 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres); 1074 1075 VariantInit(&var); 1076 V_VT(&var) = VT_BSTR; 1077 V_BSTR(&var) = SysAllocString(temp_fileW); 1078 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1079 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 1080 VariantClear(&var); 1081 1082 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1083 FILE_ATTRIBUTE_NORMAL, NULL); 1084 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL); 1085 CloseHandle(file); 1086 1087 /* Try a "file:" URL with slash separators. */ 1088 ptr = temp_fileW + 8; 1089 while (*ptr) 1090 { 1091 if (*ptr == '\\') 1092 *ptr = '/'; 1093 ptr++; 1094 } 1095 1096 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1097 ok(hres == S_OK || 1098 broken(hres == E_UNEXPECTED), /* NT4 */ 1099 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres); 1100 if (pic) 1101 IPicture_Release(pic); 1102 1103 VariantInit(&var); 1104 V_VT(&var) = VT_BSTR; 1105 V_BSTR(&var) = SysAllocString(temp_fileW); 1106 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1107 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 1108 VariantClear(&var); 1109 1110 DeleteFileA(temp_file); 1111 1112 /* Try with a nonexistent file. */ 1113 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1114 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */ 1115 broken(hres == E_UNEXPECTED) || /* NT4 */ 1116 broken(hres == E_FAIL), /* Win2k */ 1117 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres); 1118 1119 VariantInit(&var); 1120 V_VT(&var) = VT_BSTR; 1121 V_BSTR(&var) = SysAllocString(temp_fileW); 1122 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1123 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 1124 VariantClear(&var); 1125 1126 VariantInit(&var); 1127 V_VT(&var) = VT_INT; 1128 V_INT(&var) = 762; 1129 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1130 ok(hres == CTL_E_FILENOTFOUND, "wrong error %#x\n", hres); 1131 1132 if (0) /* crashes under Windows */ 1133 hres = OleLoadPictureFile(var, NULL); 1134 } 1135 1136 static void test_himetric(void) 1137 { 1138 static const BYTE bmp_bits[1024]; 1139 OLE_XSIZE_HIMETRIC cx; 1140 OLE_YSIZE_HIMETRIC cy; 1141 IPicture *pic; 1142 PICTDESC desc; 1143 HBITMAP bmp; 1144 HRESULT hr; 1145 HICON icon; 1146 HDC hdc; 1147 INT d; 1148 1149 desc.cbSizeofstruct = sizeof(desc); 1150 desc.picType = PICTYPE_BITMAP; 1151 desc.bmp.hpal = NULL; 1152 1153 hdc = CreateCompatibleDC(0); 1154 1155 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX), 1156 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL); 1157 1158 desc.bmp.hbitmap = bmp; 1159 1160 /* size in himetric units reported rounded up to next integer value */ 1161 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1162 ok(hr == S_OK, "got 0x%08x\n", hr); 1163 1164 cx = 0; 1165 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX)); 1166 hr = IPicture_get_Width(pic, &cx); 1167 ok(hr == S_OK, "got 0x%08x\n", hr); 1168 ok(cx == d, "got %d, expected %d\n", cx, d); 1169 1170 cy = 0; 1171 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY)); 1172 hr = IPicture_get_Height(pic, &cy); 1173 ok(hr == S_OK, "got 0x%08x\n", hr); 1174 ok(cy == d, "got %d, expected %d\n", cy, d); 1175 1176 DeleteObject(bmp); 1177 IPicture_Release(pic); 1178 1179 /* same thing with icon */ 1180 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 1181 1, 1, bmp_bits, bmp_bits); 1182 ok(icon != NULL, "failed to create icon\n"); 1183 1184 desc.picType = PICTYPE_ICON; 1185 desc.icon.hicon = icon; 1186 1187 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1188 ok(hr == S_OK, "got 0x%08x\n", hr); 1189 1190 cx = 0; 1191 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX)); 1192 hr = IPicture_get_Width(pic, &cx); 1193 ok(hr == S_OK, "got 0x%08x\n", hr); 1194 ok(cx == d, "got %d, expected %d\n", cx, d); 1195 1196 cy = 0; 1197 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY)); 1198 hr = IPicture_get_Height(pic, &cy); 1199 ok(hr == S_OK, "got 0x%08x\n", hr); 1200 ok(cy == d, "got %d, expected %d\n", cy, d); 1201 1202 IPicture_Release(pic); 1203 DestroyIcon(icon); 1204 1205 DeleteDC(hdc); 1206 } 1207 1208 static void test_load_save_bmp(void) 1209 { 1210 IPicture *pic; 1211 PICTDESC desc; 1212 short type; 1213 OLE_HANDLE handle; 1214 HGLOBAL hmem; 1215 DWORD *mem; 1216 IPersistStream *src_stream; 1217 IStream *dst_stream; 1218 LARGE_INTEGER offset; 1219 HRESULT hr; 1220 LONG size; 1221 1222 desc.cbSizeofstruct = sizeof(desc); 1223 desc.picType = PICTYPE_BITMAP; 1224 desc.bmp.hpal = 0; 1225 desc.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL); 1226 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1227 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1228 1229 type = -1; 1230 hr = IPicture_get_Type(pic, &type); 1231 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1232 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type); 1233 1234 hr = IPicture_get_Handle(pic, &handle); 1235 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1236 ok(IntToPtr(handle) == desc.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle); 1237 1238 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096); 1239 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1240 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr); 1241 1242 size = -1; 1243 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1244 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1245 ok(size == 66, "expected 66, got %d\n", size); 1246 mem = GlobalLock(hmem); 1247 ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04x\n", mem[0]); 1248 GlobalUnlock(hmem); 1249 1250 size = -1; 1251 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1252 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr); 1253 ok(size == -1, "expected -1, got %d\n", size); 1254 1255 offset.QuadPart = 0; 1256 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1257 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1258 1259 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1260 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1261 1262 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1263 ok(hr == S_OK, "Save error %#x\n", hr); 1264 1265 IPersistStream_Release(src_stream); 1266 IStream_Release(dst_stream); 1267 1268 mem = GlobalLock(hmem); 1269 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1270 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]); 1271 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]); 1272 1273 GlobalUnlock(hmem); 1274 GlobalFree(hmem); 1275 1276 DeleteObject(desc.bmp.hbitmap); 1277 IPicture_Release(pic); 1278 } 1279 1280 static void test_load_save_icon(void) 1281 { 1282 IPicture *pic; 1283 PICTDESC desc; 1284 short type; 1285 OLE_HANDLE handle; 1286 HGLOBAL hmem; 1287 DWORD *mem; 1288 IPersistStream *src_stream; 1289 IStream *dst_stream; 1290 LARGE_INTEGER offset; 1291 HRESULT hr; 1292 LONG size; 1293 1294 desc.cbSizeofstruct = sizeof(desc); 1295 desc.picType = PICTYPE_ICON; 1296 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION); 1297 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1298 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1299 1300 type = -1; 1301 hr = IPicture_get_Type(pic, &type); 1302 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1303 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type); 1304 1305 hr = IPicture_get_Handle(pic, &handle); 1306 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1307 ok(IntToPtr(handle) == desc.icon.hicon, "get_Handle returned wrong handle %#x\n", handle); 1308 1309 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192); 1310 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1311 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr); 1312 1313 size = -1; 1314 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1315 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1316 todo_wine 1317 ok(size == 766, "expected 766, got %d\n", size); 1318 mem = GlobalLock(hmem); 1319 ok(mem[0] == 0x00010000, "got wrong icon header %04x\n", mem[0]); 1320 GlobalUnlock(hmem); 1321 1322 size = -1; 1323 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1324 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr); 1325 ok(size == -1, "expected -1, got %d\n", size); 1326 1327 offset.QuadPart = 0; 1328 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1329 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1330 1331 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1332 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1333 1334 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1335 ok(hr == S_OK, "Saveerror %#x\n", hr); 1336 1337 IPersistStream_Release(src_stream); 1338 IStream_Release(dst_stream); 1339 1340 mem = GlobalLock(hmem); 1341 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1342 todo_wine 1343 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]); 1344 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]); 1345 1346 GlobalUnlock(hmem); 1347 GlobalFree(hmem); 1348 1349 DestroyIcon(desc.icon.hicon); 1350 IPicture_Release(pic); 1351 } 1352 1353 static void test_load_save_empty_picture(void) 1354 { 1355 IPicture *pic; 1356 PICTDESC desc; 1357 short type; 1358 OLE_HANDLE handle; 1359 HGLOBAL hmem; 1360 DWORD *mem; 1361 IPersistStream *src_stream; 1362 IStream *dst_stream, *stream; 1363 LARGE_INTEGER offset; 1364 HRESULT hr; 1365 LONG size; 1366 1367 memset(&pic, 0, sizeof(pic)); 1368 desc.cbSizeofstruct = sizeof(desc); 1369 desc.picType = PICTYPE_NONE; 1370 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic); 1371 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1372 1373 type = -1; 1374 hr = IPicture_get_Type(pic, &type); 1375 ok(hr == S_OK, "get_Type error %#x\n", hr); 1376 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type); 1377 1378 handle = (OLE_HANDLE)0xdeadbeef; 1379 hr = IPicture_get_Handle(pic, &handle); 1380 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1381 ok(!handle, "get_Handle returned wrong handle %#x\n", handle); 1382 1383 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096); 1384 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1385 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr); 1386 1387 size = -1; 1388 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1389 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1390 ok(size == -1, "expected -1, got %d\n", size); 1391 1392 size = -1; 1393 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1394 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1395 ok(size == -1, "expected -1, got %d\n", size); 1396 1397 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1398 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1399 1400 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1401 ok(hr == S_OK, "Save error %#x\n", hr); 1402 1403 mem = GlobalLock(hmem); 1404 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1405 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]); 1406 GlobalUnlock(hmem); 1407 1408 IPersistStream_Release(src_stream); 1409 IPicture_Release(pic); 1410 1411 /* first with statable and seekable stream */ 1412 offset.QuadPart = 0; 1413 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1414 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1415 1416 pic = NULL; 1417 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic); 1418 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr); 1419 ok(pic != NULL,"picture should not be not NULL\n"); 1420 if (pic != NULL) 1421 { 1422 type = -1; 1423 hr = IPicture_get_Type(pic, &type); 1424 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1425 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type); 1426 1427 handle = (OLE_HANDLE)0xdeadbeef; 1428 hr = IPicture_get_Handle(pic, &handle); 1429 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1430 ok(!handle, "get_Handle returned wrong handle %#x\n", handle); 1431 1432 IPicture_Release(pic); 1433 } 1434 IStream_Release(dst_stream); 1435 1436 /* again with non-statable and non-seekable stream */ 1437 stream = NoStatStream_Construct(hmem); 1438 ok(stream != NULL, "failed to create empty image stream\n"); 1439 1440 pic = NULL; 1441 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic); 1442 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr); 1443 ok(pic != NULL,"picture should not be not NULL\n"); 1444 if (pic != NULL) 1445 { 1446 type = -1; 1447 hr = IPicture_get_Type(pic, &type); 1448 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1449 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type); 1450 1451 handle = (OLE_HANDLE)0xdeadbeef; 1452 hr = IPicture_get_Handle(pic, &handle); 1453 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1454 ok(!handle, "get_Handle returned wrong handle %#x\n", handle); 1455 1456 IPicture_Release(pic); 1457 } 1458 /* Non-statable impl always deletes on release */ 1459 IStream_Release(stream); 1460 } 1461 1462 static void test_load_save_emf(void) 1463 { 1464 HDC hdc; 1465 IPicture *pic; 1466 PICTDESC desc; 1467 short type; 1468 OLE_HANDLE handle; 1469 HGLOBAL hmem; 1470 DWORD *mem; 1471 ENHMETAHEADER *emh; 1472 IPersistStream *src_stream; 1473 IStream *dst_stream; 1474 LARGE_INTEGER offset; 1475 HRESULT hr; 1476 LONG size; 1477 1478 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); 1479 ok(hdc != 0, "CreateEnhMetaFileA failed\n"); 1480 1481 desc.cbSizeofstruct = sizeof(desc); 1482 desc.picType = PICTYPE_ENHMETAFILE; 1483 desc.emf.hemf = CloseEnhMetaFile(hdc); 1484 ok(desc.emf.hemf != 0, "CloseEnhMetaFile failed\n"); 1485 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1486 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1487 1488 type = -1; 1489 hr = IPicture_get_Type(pic, &type); 1490 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1491 ok(type == PICTYPE_ENHMETAFILE,"expected PICTYPE_ENHMETAFILE, got %d\n", type); 1492 1493 hr = IPicture_get_Handle(pic, &handle); 1494 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1495 ok(IntToPtr(handle) == desc.emf.hemf, "get_Handle returned wrong handle %#x\n", handle); 1496 1497 hmem = GlobalAlloc(GMEM_MOVEABLE, 0); 1498 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1499 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr); 1500 1501 size = -1; 1502 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1503 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1504 ok(size == 128, "expected 128, got %d\n", size); 1505 emh = GlobalLock(hmem); 1506 if (size) 1507 { 1508 ok(emh->iType == EMR_HEADER, "wrong iType %04x\n", emh->iType); 1509 ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08x\n", emh->dSignature); 1510 } 1511 GlobalUnlock(hmem); 1512 1513 size = -1; 1514 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1515 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr); 1516 ok(size == -1, "expected -1, got %d\n", size); 1517 1518 offset.QuadPart = 0; 1519 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1520 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1521 1522 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1523 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1524 1525 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1526 ok(hr == S_OK, "Save error %#x\n", hr); 1527 1528 IPersistStream_Release(src_stream); 1529 IStream_Release(dst_stream); 1530 1531 mem = GlobalLock(hmem); 1532 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1533 ok(mem[1] == 128, "expected 128, got %u\n", mem[1]); 1534 emh = (ENHMETAHEADER *)(mem + 2); 1535 ok(emh->iType == EMR_HEADER, "wrong iType %04x\n", emh->iType); 1536 ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08x\n", emh->dSignature); 1537 1538 GlobalUnlock(hmem); 1539 GlobalFree(hmem); 1540 1541 DeleteEnhMetaFile(desc.emf.hemf); 1542 IPicture_Release(pic); 1543 } 1544 1545 START_TEST(olepicture) 1546 { 1547 hOleaut32 = GetModuleHandleA("oleaut32.dll"); 1548 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture"); 1549 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx"); 1550 if (!pOleLoadPicture) 1551 { 1552 win_skip("OleLoadPicture is not available\n"); 1553 return; 1554 } 1555 1556 /* Test regular 1x1 pixel images of gif, jpg, bmp type */ 1557 test_pic(gifimage, sizeof(gifimage)); 1558 test_pic(jpgimage, sizeof(jpgimage)); 1559 test_pic(bmpimage, sizeof(bmpimage)); 1560 test_pic(bmpimage_rle8, sizeof(bmpimage_rle8)); 1561 test_pic(gif4pixel, sizeof(gif4pixel)); 1562 /* FIXME: No PNG support in Windows... */ 1563 if (0) test_pic(pngimage, sizeof(pngimage)); 1564 test_empty_image(); 1565 test_empty_image_2(); 1566 if (pOleLoadPictureEx) 1567 { 1568 test_apm(); 1569 test_metafile(); 1570 test_enhmetafile(); 1571 } 1572 else 1573 win_skip("OleLoadPictureEx is not available\n"); 1574 test_Invoke(); 1575 test_OleCreatePictureIndirect(); 1576 test_Render(); 1577 test_get_Attributes(); 1578 test_get_Handle(); 1579 test_get_Type(); 1580 test_OleLoadPicturePath(); 1581 test_himetric(); 1582 test_load_save_bmp(); 1583 test_load_save_icon(); 1584 test_load_save_empty_picture(); 1585 test_load_save_emf(); 1586 } 1587 1588 1589 /* Helper functions only ... */ 1590 1591 1592 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface) 1593 { 1594 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface); 1595 } 1596 1597 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This) 1598 { 1599 GlobalFree(This->supportHandle); 1600 This->supportHandle=0; 1601 HeapFree(GetProcessHeap(), 0, This); 1602 } 1603 1604 static ULONG WINAPI NoStatStreamImpl_AddRef( 1605 IStream* iface) 1606 { 1607 NoStatStreamImpl* const This = impl_from_IStream(iface); 1608 return InterlockedIncrement(&This->ref); 1609 } 1610 1611 static HRESULT WINAPI NoStatStreamImpl_QueryInterface( 1612 IStream* iface, 1613 REFIID riid, /* [in] */ 1614 void** ppvObject) /* [iid_is][out] */ 1615 { 1616 NoStatStreamImpl* const This = impl_from_IStream(iface); 1617 if (ppvObject==0) return E_INVALIDARG; 1618 *ppvObject = 0; 1619 1620 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IStream, riid)) 1621 *ppvObject = &This->IStream_iface; 1622 1623 if ((*ppvObject)==0) 1624 return E_NOINTERFACE; 1625 NoStatStreamImpl_AddRef(iface); 1626 return S_OK; 1627 } 1628 1629 static ULONG WINAPI NoStatStreamImpl_Release( 1630 IStream* iface) 1631 { 1632 NoStatStreamImpl* const This = impl_from_IStream(iface); 1633 ULONG newRef = InterlockedDecrement(&This->ref); 1634 if (newRef==0) 1635 NoStatStreamImpl_Destroy(This); 1636 return newRef; 1637 } 1638 1639 static HRESULT WINAPI NoStatStreamImpl_Read( 1640 IStream* iface, 1641 void* pv, /* [length_is][size_is][out] */ 1642 ULONG cb, /* [in] */ 1643 ULONG* pcbRead) /* [out] */ 1644 { 1645 NoStatStreamImpl* const This = impl_from_IStream(iface); 1646 void* supportBuffer; 1647 ULONG bytesReadBuffer; 1648 ULONG bytesToReadFromBuffer; 1649 1650 if (pcbRead==0) 1651 pcbRead = &bytesReadBuffer; 1652 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb); 1653 supportBuffer = GlobalLock(This->supportHandle); 1654 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer); 1655 This->currentPosition.u.LowPart+=bytesToReadFromBuffer; 1656 *pcbRead = bytesToReadFromBuffer; 1657 GlobalUnlock(This->supportHandle); 1658 if(*pcbRead == cb) 1659 return S_OK; 1660 return S_FALSE; 1661 } 1662 1663 static HRESULT WINAPI NoStatStreamImpl_Write( 1664 IStream* iface, 1665 const void* pv, /* [size_is][in] */ 1666 ULONG cb, /* [in] */ 1667 ULONG* pcbWritten) /* [out] */ 1668 { 1669 NoStatStreamImpl* const This = impl_from_IStream(iface); 1670 void* supportBuffer; 1671 ULARGE_INTEGER newSize; 1672 ULONG bytesWritten = 0; 1673 1674 if (pcbWritten == 0) 1675 pcbWritten = &bytesWritten; 1676 if (cb == 0) 1677 return S_OK; 1678 newSize.u.HighPart = 0; 1679 newSize.u.LowPart = This->currentPosition.u.LowPart + cb; 1680 if (newSize.u.LowPart > This->streamSize.u.LowPart) 1681 IStream_SetSize(iface, newSize); 1682 1683 supportBuffer = GlobalLock(This->supportHandle); 1684 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb); 1685 This->currentPosition.u.LowPart+=cb; 1686 *pcbWritten = cb; 1687 GlobalUnlock(This->supportHandle); 1688 return S_OK; 1689 } 1690 1691 static HRESULT WINAPI NoStatStreamImpl_Seek( 1692 IStream* iface, 1693 LARGE_INTEGER dlibMove, /* [in] */ 1694 DWORD dwOrigin, /* [in] */ 1695 ULARGE_INTEGER* plibNewPosition) /* [out] */ 1696 { 1697 NoStatStreamImpl* const This = impl_from_IStream(iface); 1698 ULARGE_INTEGER newPosition; 1699 switch (dwOrigin) 1700 { 1701 case STREAM_SEEK_SET: 1702 newPosition.u.HighPart = 0; 1703 newPosition.u.LowPart = 0; 1704 break; 1705 case STREAM_SEEK_CUR: 1706 newPosition = This->currentPosition; 1707 break; 1708 case STREAM_SEEK_END: 1709 newPosition = This->streamSize; 1710 break; 1711 default: 1712 return STG_E_INVALIDFUNCTION; 1713 } 1714 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart) 1715 return STG_E_INVALIDFUNCTION; 1716 newPosition.QuadPart += dlibMove.QuadPart; 1717 if (plibNewPosition) *plibNewPosition = newPosition; 1718 This->currentPosition = newPosition; 1719 return S_OK; 1720 } 1721 1722 static HRESULT WINAPI NoStatStreamImpl_SetSize( 1723 IStream* iface, 1724 ULARGE_INTEGER libNewSize) /* [in] */ 1725 { 1726 NoStatStreamImpl* const This = impl_from_IStream(iface); 1727 HGLOBAL supportHandle; 1728 if (libNewSize.u.HighPart != 0) 1729 return STG_E_INVALIDFUNCTION; 1730 if (This->streamSize.u.LowPart == libNewSize.u.LowPart) 1731 return S_OK; 1732 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0); 1733 if (supportHandle == 0) 1734 return STG_E_MEDIUMFULL; 1735 This->supportHandle = supportHandle; 1736 This->streamSize.u.LowPart = libNewSize.u.LowPart; 1737 return S_OK; 1738 } 1739 1740 static HRESULT WINAPI NoStatStreamImpl_CopyTo( 1741 IStream* iface, 1742 IStream* pstm, /* [unique][in] */ 1743 ULARGE_INTEGER cb, /* [in] */ 1744 ULARGE_INTEGER* pcbRead, /* [out] */ 1745 ULARGE_INTEGER* pcbWritten) /* [out] */ 1746 { 1747 HRESULT hr = S_OK; 1748 BYTE tmpBuffer[128]; 1749 ULONG bytesRead, bytesWritten, copySize; 1750 ULARGE_INTEGER totalBytesRead; 1751 ULARGE_INTEGER totalBytesWritten; 1752 1753 if ( pstm == 0 ) 1754 return STG_E_INVALIDPOINTER; 1755 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0; 1756 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0; 1757 1758 while ( cb.u.LowPart > 0 ) 1759 { 1760 if ( cb.u.LowPart >= 128 ) 1761 copySize = 128; 1762 else 1763 copySize = cb.u.LowPart; 1764 IStream_Read(iface, tmpBuffer, copySize, &bytesRead); 1765 totalBytesRead.u.LowPart += bytesRead; 1766 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten); 1767 totalBytesWritten.u.LowPart += bytesWritten; 1768 if (bytesRead != bytesWritten) 1769 { 1770 hr = STG_E_MEDIUMFULL; 1771 break; 1772 } 1773 if (bytesRead!=copySize) 1774 cb.u.LowPart = 0; 1775 else 1776 cb.u.LowPart -= bytesRead; 1777 } 1778 if (pcbRead) 1779 { 1780 pcbRead->u.LowPart = totalBytesRead.u.LowPart; 1781 pcbRead->u.HighPart = totalBytesRead.u.HighPart; 1782 } 1783 1784 if (pcbWritten) 1785 { 1786 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart; 1787 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart; 1788 } 1789 return hr; 1790 } 1791 1792 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags) 1793 { 1794 return S_OK; 1795 } 1796 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; } 1797 1798 static HRESULT WINAPI NoStatStreamImpl_LockRegion( 1799 IStream* iface, 1800 ULARGE_INTEGER libOffset, /* [in] */ 1801 ULARGE_INTEGER cb, /* [in] */ 1802 DWORD dwLockType) /* [in] */ 1803 { 1804 return S_OK; 1805 } 1806 1807 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion( 1808 IStream* iface, 1809 ULARGE_INTEGER libOffset, /* [in] */ 1810 ULARGE_INTEGER cb, /* [in] */ 1811 DWORD dwLockType) /* [in] */ 1812 { 1813 return S_OK; 1814 } 1815 1816 static HRESULT WINAPI NoStatStreamImpl_Stat( 1817 IStream* iface, 1818 STATSTG* pstatstg, /* [out] */ 1819 DWORD grfStatFlag) /* [in] */ 1820 { 1821 return E_NOTIMPL; 1822 } 1823 1824 static HRESULT WINAPI NoStatStreamImpl_Clone( 1825 IStream* iface, 1826 IStream** ppstm) /* [out] */ 1827 { 1828 return E_NOTIMPL; 1829 } 1830 static const IStreamVtbl NoStatStreamImpl_Vtbl; 1831 1832 /* 1833 Build an object that implements IStream, without IStream_Stat capabilities. 1834 Receives a memory handle with data buffer. If memory handle is non-null, 1835 it is assumed to be unlocked, otherwise an internal memory handle is allocated. 1836 In any case the object takes ownership of memory handle and will free it on 1837 object release. 1838 */ 1839 static IStream* NoStatStream_Construct(HGLOBAL hGlobal) 1840 { 1841 NoStatStreamImpl* newStream; 1842 1843 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl)); 1844 if (newStream!=0) 1845 { 1846 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl; 1847 newStream->ref = 1; 1848 newStream->supportHandle = hGlobal; 1849 1850 if (!newStream->supportHandle) 1851 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | 1852 GMEM_SHARE, 0); 1853 newStream->currentPosition.u.HighPart = 0; 1854 newStream->currentPosition.u.LowPart = 0; 1855 newStream->streamSize.u.HighPart = 0; 1856 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle); 1857 } 1858 return &newStream->IStream_iface; 1859 } 1860 1861 1862 static const IStreamVtbl NoStatStreamImpl_Vtbl = 1863 { 1864 NoStatStreamImpl_QueryInterface, 1865 NoStatStreamImpl_AddRef, 1866 NoStatStreamImpl_Release, 1867 NoStatStreamImpl_Read, 1868 NoStatStreamImpl_Write, 1869 NoStatStreamImpl_Seek, 1870 NoStatStreamImpl_SetSize, 1871 NoStatStreamImpl_CopyTo, 1872 NoStatStreamImpl_Commit, 1873 NoStatStreamImpl_Revert, 1874 NoStatStreamImpl_LockRegion, 1875 NoStatStreamImpl_UnlockRegion, 1876 NoStatStreamImpl_Stat, 1877 NoStatStreamImpl_Clone 1878 }; 1879