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 < sizeof(args)/sizeof(args[0]); 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 void test_OleCreatePictureIndirect(void) 554 { 555 OLE_HANDLE handle; 556 IPicture *pict; 557 HRESULT hr; 558 short type; 559 560 if (0) 561 { 562 /* crashes on native */ 563 OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, NULL); 564 } 565 566 hr = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict); 567 ok(hr == S_OK, "hr %08x\n", hr); 568 569 type = PICTYPE_NONE; 570 hr = IPicture_get_Type(pict, &type); 571 ok(hr == S_OK, "hr %08x\n", hr); 572 ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type); 573 574 handle = 0xdeadbeef; 575 hr = IPicture_get_Handle(pict, &handle); 576 ok(hr == S_OK, "hr %08x\n", hr); 577 ok(handle == 0, "handle %08x\n", handle); 578 579 IPicture_Release(pict); 580 } 581 582 static void test_apm(void) 583 { 584 OLE_HANDLE handle; 585 LPSTREAM stream; 586 IPicture *pict; 587 HGLOBAL hglob; 588 LPBYTE *data; 589 LONG cxy; 590 BOOL keep; 591 short type; 592 593 hglob = GlobalAlloc (0, sizeof(apmdata)); 594 data = GlobalLock(hglob); 595 memcpy(data, apmdata, sizeof(apmdata)); 596 597 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream)); 598 ole_check(pOleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict)); 599 600 ole_check(IPicture_get_Handle(pict, &handle)); 601 ok(handle != 0, "handle is null\n"); 602 603 ole_check(IPicture_get_Type(pict, &type)); 604 expect_eq(type, PICTYPE_METAFILE, short, "%d"); 605 606 ole_check(IPicture_get_Height(pict, &cxy)); 607 expect_eq(cxy, 1667, LONG, "%d"); 608 609 ole_check(IPicture_get_Width(pict, &cxy)); 610 expect_eq(cxy, 1323, LONG, "%d"); 611 612 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep)); 613 todo_wine expect_eq(keep, FALSE, LONG, "%d"); 614 615 ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL); 616 IPicture_Release(pict); 617 IStream_Release(stream); 618 } 619 620 static void test_metafile(void) 621 { 622 LPSTREAM stream; 623 IPicture *pict; 624 HGLOBAL hglob; 625 LPBYTE *data; 626 627 hglob = GlobalAlloc (0, sizeof(metafile)); 628 data = GlobalLock(hglob); 629 memcpy(data, metafile, sizeof(metafile)); 630 631 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream)); 632 /* Windows does not load simple metafiles */ 633 ole_expect(pOleLoadPictureEx(stream, sizeof(metafile), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict), E_FAIL); 634 635 IStream_Release(stream); 636 } 637 638 static void test_enhmetafile(void) 639 { 640 OLE_HANDLE handle; 641 LPSTREAM stream; 642 IPicture *pict; 643 HGLOBAL hglob; 644 LPBYTE *data; 645 LONG cxy; 646 BOOL keep; 647 short type; 648 649 hglob = GlobalAlloc (0, sizeof(enhmetafile)); 650 data = GlobalLock(hglob); 651 memcpy(data, enhmetafile, sizeof(enhmetafile)); 652 653 ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream)); 654 ole_check(pOleLoadPictureEx(stream, sizeof(enhmetafile), TRUE, &IID_IPicture, 10, 10, 0, (LPVOID *)&pict)); 655 656 ole_check(IPicture_get_Handle(pict, &handle)); 657 ok(handle != 0, "handle is null\n"); 658 659 ole_check(IPicture_get_Type(pict, &type)); 660 expect_eq(type, PICTYPE_ENHMETAFILE, short, "%d"); 661 662 ole_check(IPicture_get_Height(pict, &cxy)); 663 expect_eq(cxy, -23, LONG, "%d"); 664 665 ole_check(IPicture_get_Width(pict, &cxy)); 666 expect_eq(cxy, -25, LONG, "%d"); 667 668 ole_check(IPicture_get_KeepOriginalFormat(pict, &keep)); 669 todo_wine expect_eq(keep, FALSE, LONG, "%d"); 670 671 IPicture_Release(pict); 672 IStream_Release(stream); 673 } 674 675 static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy, 676 OLE_XPOS_HIMETRIC xSrc, 677 OLE_YPOS_HIMETRIC ySrc, 678 OLE_XSIZE_HIMETRIC cxSrc, 679 OLE_YSIZE_HIMETRIC cySrc, 680 const RECT *bounds) 681 { 682 VARIANT ret, args[10]; 683 HRESULT hr, hr_disp; 684 DISPPARAMS params; 685 IDispatch *disp; 686 int i; 687 688 hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds); 689 690 IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp); 691 692 /* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */ 693 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) 694 V_VT(&args[i]) = VT_I4; 695 696 /* pack arguments and call */ 697 V_INT_PTR(&args[0]) = (INT_PTR)bounds; 698 V_I4(&args[1]) = cySrc; 699 V_I4(&args[2]) = cxSrc; 700 V_I4(&args[3]) = ySrc; 701 V_I4(&args[4]) = xSrc; 702 V_I4(&args[5]) = cy; 703 V_I4(&args[6]) = cx; 704 V_I4(&args[7]) = y; 705 V_I4(&args[8]) = x; 706 V_I4(&args[9]) = HandleToLong(hdc); 707 708 params.rgvarg = args; 709 params.rgdispidNamedArgs = NULL; 710 params.cArgs = 10; 711 params.cNamedArgs = 0; 712 713 V_VT(&ret) = VT_EMPTY; 714 hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, 715 ¶ms, &ret, NULL, NULL); 716 ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n", 717 hr_disp, hr); 718 719 IDispatch_Release(disp); 720 721 return hr; 722 } 723 724 static void test_Render(void) 725 { 726 IPicture *pic; 727 HRESULT hres; 728 short type; 729 PICTDESC desc; 730 OLE_XSIZE_HIMETRIC pWidth; 731 OLE_YSIZE_HIMETRIC pHeight; 732 COLORREF result, expected; 733 HDC hdc = create_render_dc(); 734 735 /* test IPicture::Render return code on uninitialized picture */ 736 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 737 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 738 hres = IPicture_get_Type(pic, &type); 739 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres); 740 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type); 741 /* zero dimensions */ 742 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL); 743 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 744 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL); 745 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 746 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL); 747 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 748 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL); 749 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 750 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL); 751 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 752 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL); 753 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 754 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL); 755 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 756 /* nonzero dimensions, PICTYPE_UNINITIALIZED */ 757 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL); 758 ole_expect(hres, S_OK); 759 IPicture_Release(pic); 760 761 desc.cbSizeofstruct = sizeof(PICTDESC); 762 desc.picType = PICTYPE_ICON; 763 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION); 764 if(!desc.icon.hicon){ 765 win_skip("LoadIcon failed. Skipping...\n"); 766 delete_render_dc(hdc); 767 return; 768 } 769 770 hres = OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (void **)&pic); 771 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 772 /* zero dimensions, PICTYPE_ICON */ 773 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL); 774 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 775 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL); 776 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 777 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL); 778 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 779 hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL); 780 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 781 hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL); 782 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 783 hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL); 784 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 785 hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL); 786 ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE); 787 788 /* Check if target size and position is respected */ 789 IPicture_get_Width(pic, &pWidth); 790 IPicture_get_Height(pic, &pHeight); 791 792 SetPixelV(hdc, 0, 0, 0x00223344); 793 SetPixelV(hdc, 5, 5, 0x00223344); 794 SetPixelV(hdc, 10, 10, 0x00223344); 795 expected = GetPixel(hdc, 0, 0); 796 797 hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL); 798 ole_expect(hres, S_OK); 799 800 if(hres != S_OK) goto done; 801 802 /* Evaluate the rendered Icon */ 803 result = GetPixel(hdc, 0, 0); 804 ok(result == expected, 805 "Color at 0,0 should be unchanged 0x%06X, but was 0x%06X\n", expected, result); 806 result = GetPixel(hdc, 5, 5); 807 ok(result != expected, 808 "Color at 5,5 should have changed, but still was 0x%06X\n", expected); 809 result = GetPixel(hdc, 10, 10); 810 ok(result == expected, 811 "Color at 10,10 should be unchanged 0x%06X, but was 0x%06X\n", expected, result); 812 813 done: 814 IPicture_Release(pic); 815 delete_render_dc(hdc); 816 } 817 818 static void test_get_Attributes(void) 819 { 820 IPicture *pic; 821 HRESULT hres; 822 short type; 823 DWORD attr; 824 825 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 826 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 827 hres = IPicture_get_Type(pic, &type); 828 ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres); 829 ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type); 830 831 hres = IPicture_get_Attributes(pic, NULL); 832 ole_expect(hres, E_POINTER); 833 834 attr = 0xdeadbeef; 835 hres = IPicture_get_Attributes(pic, &attr); 836 ole_expect(hres, S_OK); 837 ok(attr == 0, "IPicture_get_Attributes does not reset attr to zero, got %d\n", attr); 838 839 IPicture_Release(pic); 840 } 841 842 static void test_get_Handle(void) 843 { 844 IPicture *pic; 845 HRESULT hres; 846 847 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 848 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 849 hres = IPicture_get_Handle(pic, NULL); 850 ole_expect(hres, E_POINTER); 851 852 IPicture_Release(pic); 853 } 854 855 static void test_get_Type(void) 856 { 857 IPicture *pic; 858 HRESULT hres; 859 860 hres = OleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void **)&pic); 861 ok(hres == S_OK, "Failed to create a picture, hr %#x.\n", hres); 862 863 hres = IPicture_get_Type(pic, NULL); 864 ole_expect(hres, E_POINTER); 865 866 IPicture_Release(pic); 867 } 868 869 static void test_OleLoadPicturePath(void) 870 { 871 static WCHAR emptyW[] = {0}; 872 873 IPicture *pic; 874 HRESULT hres; 875 int i; 876 char temp_path[MAX_PATH]; 877 char temp_file[MAX_PATH]; 878 WCHAR temp_fileW[MAX_PATH + 5] = {'f','i','l','e',':','/','/','/'}; 879 HANDLE file; 880 DWORD size; 881 WCHAR *ptr; 882 VARIANT var; 883 884 const struct 885 { 886 LPOLESTR szURLorPath; 887 REFIID riid; 888 IPicture **pic; 889 } invalid_parameters[] = 890 { 891 {NULL, NULL, NULL}, 892 {NULL, NULL, &pic}, 893 {NULL, &IID_IPicture, NULL}, 894 {NULL, &IID_IPicture, &pic}, 895 {emptyW, NULL, NULL}, 896 {emptyW, &IID_IPicture, NULL}, 897 }; 898 899 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++) 900 { 901 pic = (IPicture *)0xdeadbeef; 902 hres = OleLoadPicturePath(invalid_parameters[i].szURLorPath, NULL, 0, 0, 903 invalid_parameters[i].riid, 904 (void **)invalid_parameters[i].pic); 905 ok(hres == E_INVALIDARG, 906 "[%d] Expected OleLoadPicturePath to return E_INVALIDARG, got 0x%08x\n", i, hres); 907 ok(pic == (IPicture *)0xdeadbeef, 908 "[%d] Expected output pointer to be 0xdeadbeef, got %p\n", i, pic); 909 } 910 911 pic = (IPicture *)0xdeadbeef; 912 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, NULL, (void **)&pic); 913 todo_wine 914 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */ 915 broken(hres == E_UNEXPECTED) || /* NT4 */ 916 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */ 917 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres); 918 ok(pic == NULL, 919 "Expected the output interface pointer to be NULL, got %p\n", pic); 920 921 pic = (IPicture *)0xdeadbeef; 922 hres = OleLoadPicturePath(emptyW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 923 todo_wine 924 ok(hres == INET_E_UNKNOWN_PROTOCOL || /* XP/Vista+ */ 925 broken(hres == E_UNEXPECTED) || /* NT4 */ 926 broken(hres == E_OUTOFMEMORY), /* Win2k/Win2k3 */ 927 "Expected OleLoadPicturePath to return INET_E_UNKNOWN_PROTOCOL, got 0x%08x\n", hres); 928 ok(pic == NULL, 929 "Expected the output interface pointer to be NULL, got %p\n", pic); 930 931 /* Create a local temporary image file for testing. */ 932 GetTempPathA(sizeof(temp_path), temp_path); 933 GetTempFileNameA(temp_path, "bmp", 0, temp_file); 934 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 935 FILE_ATTRIBUTE_NORMAL, NULL); 936 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL); 937 CloseHandle(file); 938 939 MultiByteToWideChar(CP_ACP, 0, temp_file, -1, temp_fileW + 8, sizeof(temp_fileW)/sizeof(WCHAR) - 8); 940 941 /* Try a normal DOS path. */ 942 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic); 943 ok(hres == S_OK || 944 broken(hres == E_UNEXPECTED), /* NT4 */ 945 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres); 946 if (pic) 947 IPicture_Release(pic); 948 949 VariantInit(&var); 950 V_VT(&var) = VT_BSTR; 951 V_BSTR(&var) = SysAllocString(temp_fileW + 8); 952 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 953 ok(hres == S_OK, "OleLoadPictureFile error %#x\n", hres); 954 IPicture_Release(pic); 955 VariantClear(&var); 956 957 /* Try a DOS path with tacked on "file:". */ 958 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 959 ok(hres == S_OK || 960 broken(hres == E_UNEXPECTED), /* NT4 */ 961 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres); 962 if (pic) 963 IPicture_Release(pic); 964 965 VariantInit(&var); 966 V_VT(&var) = VT_BSTR; 967 V_BSTR(&var) = SysAllocString(temp_fileW); 968 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 969 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 970 VariantClear(&var); 971 972 DeleteFileA(temp_file); 973 974 /* Try with a nonexistent file. */ 975 hres = OleLoadPicturePath(temp_fileW + 8, NULL, 0, 0, &IID_IPicture, (void **)&pic); 976 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */ 977 broken(hres == E_UNEXPECTED) || /* NT4 */ 978 broken(hres == E_FAIL), /*Win2k */ 979 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres); 980 981 VariantInit(&var); 982 V_VT(&var) = VT_BSTR; 983 V_BSTR(&var) = SysAllocString(temp_fileW + 8); 984 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 985 ok(hres == CTL_E_FILENOTFOUND, "wrong error %#x\n", hres); 986 VariantClear(&var); 987 988 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 989 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */ 990 broken(hres == E_UNEXPECTED) || /* NT4 */ 991 broken(hres == E_FAIL), /* Win2k */ 992 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres); 993 994 VariantInit(&var); 995 V_VT(&var) = VT_BSTR; 996 V_BSTR(&var) = SysAllocString(temp_fileW); 997 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 998 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 999 VariantClear(&var); 1000 1001 file = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1002 FILE_ATTRIBUTE_NORMAL, NULL); 1003 WriteFile(file, bmpimage, sizeof(bmpimage), &size, NULL); 1004 CloseHandle(file); 1005 1006 /* Try a "file:" URL with slash separators. */ 1007 ptr = temp_fileW + 8; 1008 while (*ptr) 1009 { 1010 if (*ptr == '\\') 1011 *ptr = '/'; 1012 ptr++; 1013 } 1014 1015 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1016 ok(hres == S_OK || 1017 broken(hres == E_UNEXPECTED), /* NT4 */ 1018 "Expected OleLoadPicturePath to return S_OK, got 0x%08x\n", hres); 1019 if (pic) 1020 IPicture_Release(pic); 1021 1022 VariantInit(&var); 1023 V_VT(&var) = VT_BSTR; 1024 V_BSTR(&var) = SysAllocString(temp_fileW); 1025 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1026 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 1027 VariantClear(&var); 1028 1029 DeleteFileA(temp_file); 1030 1031 /* Try with a nonexistent file. */ 1032 hres = OleLoadPicturePath(temp_fileW, NULL, 0, 0, &IID_IPicture, (void **)&pic); 1033 ok(hres == INET_E_RESOURCE_NOT_FOUND || /* XP+ */ 1034 broken(hres == E_UNEXPECTED) || /* NT4 */ 1035 broken(hres == E_FAIL), /* Win2k */ 1036 "Expected OleLoadPicturePath to return INET_E_RESOURCE_NOT_FOUND, got 0x%08x\n", hres); 1037 1038 VariantInit(&var); 1039 V_VT(&var) = VT_BSTR; 1040 V_BSTR(&var) = SysAllocString(temp_fileW); 1041 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1042 ok(hres == CTL_E_PATHFILEACCESSERROR, "wrong error %#x\n", hres); 1043 VariantClear(&var); 1044 1045 VariantInit(&var); 1046 V_VT(&var) = VT_INT; 1047 V_INT(&var) = 762; 1048 hres = OleLoadPictureFile(var, (IDispatch **)&pic); 1049 ok(hres == CTL_E_FILENOTFOUND, "wrong error %#x\n", hres); 1050 1051 if (0) /* crashes under Windows */ 1052 hres = OleLoadPictureFile(var, NULL); 1053 } 1054 1055 static void test_himetric(void) 1056 { 1057 static const BYTE bmp_bits[1024]; 1058 OLE_XSIZE_HIMETRIC cx; 1059 OLE_YSIZE_HIMETRIC cy; 1060 IPicture *pic; 1061 PICTDESC desc; 1062 HBITMAP bmp; 1063 HRESULT hr; 1064 HICON icon; 1065 HDC hdc; 1066 INT d; 1067 1068 desc.cbSizeofstruct = sizeof(desc); 1069 desc.picType = PICTYPE_BITMAP; 1070 desc.bmp.hpal = NULL; 1071 1072 hdc = CreateCompatibleDC(0); 1073 1074 bmp = CreateBitmap(1.9 * GetDeviceCaps(hdc, LOGPIXELSX), 1075 1.9 * GetDeviceCaps(hdc, LOGPIXELSY), 1, 1, NULL); 1076 1077 desc.bmp.hbitmap = bmp; 1078 1079 /* size in himetric units reported rounded up to next integer value */ 1080 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1081 ok(hr == S_OK, "got 0x%08x\n", hr); 1082 1083 cx = 0; 1084 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSX)), 2540, GetDeviceCaps(hdc, LOGPIXELSX)); 1085 hr = IPicture_get_Width(pic, &cx); 1086 ok(hr == S_OK, "got 0x%08x\n", hr); 1087 ok(cx == d, "got %d, expected %d\n", cx, d); 1088 1089 cy = 0; 1090 d = MulDiv((INT)(1.9 * GetDeviceCaps(hdc, LOGPIXELSY)), 2540, GetDeviceCaps(hdc, LOGPIXELSY)); 1091 hr = IPicture_get_Height(pic, &cy); 1092 ok(hr == S_OK, "got 0x%08x\n", hr); 1093 ok(cy == d, "got %d, expected %d\n", cy, d); 1094 1095 DeleteObject(bmp); 1096 IPicture_Release(pic); 1097 1098 /* same thing with icon */ 1099 icon = CreateIcon(NULL, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 1100 1, 1, bmp_bits, bmp_bits); 1101 ok(icon != NULL, "failed to create icon\n"); 1102 1103 desc.picType = PICTYPE_ICON; 1104 desc.icon.hicon = icon; 1105 1106 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1107 ok(hr == S_OK, "got 0x%08x\n", hr); 1108 1109 cx = 0; 1110 d = MulDiv(GetSystemMetrics(SM_CXICON), 2540, GetDeviceCaps(hdc, LOGPIXELSX)); 1111 hr = IPicture_get_Width(pic, &cx); 1112 ok(hr == S_OK, "got 0x%08x\n", hr); 1113 ok(cx == d, "got %d, expected %d\n", cx, d); 1114 1115 cy = 0; 1116 d = MulDiv(GetSystemMetrics(SM_CYICON), 2540, GetDeviceCaps(hdc, LOGPIXELSY)); 1117 hr = IPicture_get_Height(pic, &cy); 1118 ok(hr == S_OK, "got 0x%08x\n", hr); 1119 ok(cy == d, "got %d, expected %d\n", cy, d); 1120 1121 IPicture_Release(pic); 1122 DestroyIcon(icon); 1123 1124 DeleteDC(hdc); 1125 } 1126 1127 static void test_load_save_bmp(void) 1128 { 1129 IPicture *pic; 1130 PICTDESC desc; 1131 short type; 1132 OLE_HANDLE handle; 1133 HGLOBAL hmem; 1134 DWORD *mem; 1135 IPersistStream *src_stream; 1136 IStream *dst_stream; 1137 LARGE_INTEGER offset; 1138 HRESULT hr; 1139 LONG size; 1140 1141 desc.cbSizeofstruct = sizeof(desc); 1142 desc.picType = PICTYPE_BITMAP; 1143 desc.bmp.hpal = 0; 1144 desc.bmp.hbitmap = CreateBitmap(1, 1, 1, 1, NULL); 1145 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1146 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1147 1148 type = -1; 1149 hr = IPicture_get_Type(pic, &type); 1150 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1151 ok(type == PICTYPE_BITMAP,"expected picture type PICTYPE_BITMAP, got %d\n", type); 1152 1153 hr = IPicture_get_Handle(pic, &handle); 1154 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1155 ok(IntToPtr(handle) == desc.bmp.hbitmap, "get_Handle returned wrong handle %#x\n", handle); 1156 1157 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096); 1158 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1159 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr); 1160 1161 size = -1; 1162 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1163 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1164 ok(size == 66, "expected 66, got %d\n", size); 1165 mem = GlobalLock(hmem); 1166 ok(!memcmp(&mem[0], "BM", 2), "got wrong bmp header %04x\n", mem[0]); 1167 GlobalUnlock(hmem); 1168 1169 size = -1; 1170 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1171 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr); 1172 ok(size == -1, "expected -1, got %d\n", size); 1173 1174 offset.QuadPart = 0; 1175 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1176 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1177 1178 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1179 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1180 1181 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1182 ok(hr == S_OK, "Save error %#x\n", hr); 1183 1184 IPersistStream_Release(src_stream); 1185 IStream_Release(dst_stream); 1186 1187 mem = GlobalLock(hmem); 1188 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1189 ok(mem[1] == 66, "expected stream size 66, got %u\n", mem[1]); 1190 ok(!memcmp(&mem[2], "BM", 2), "got wrong bmp header %04x\n", mem[2]); 1191 1192 GlobalUnlock(hmem); 1193 GlobalFree(hmem); 1194 1195 DeleteObject(desc.bmp.hbitmap); 1196 IPicture_Release(pic); 1197 } 1198 1199 static void test_load_save_icon(void) 1200 { 1201 IPicture *pic; 1202 PICTDESC desc; 1203 short type; 1204 OLE_HANDLE handle; 1205 HGLOBAL hmem; 1206 DWORD *mem; 1207 IPersistStream *src_stream; 1208 IStream *dst_stream; 1209 LARGE_INTEGER offset; 1210 HRESULT hr; 1211 LONG size; 1212 1213 desc.cbSizeofstruct = sizeof(desc); 1214 desc.picType = PICTYPE_ICON; 1215 desc.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION); 1216 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1217 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1218 1219 type = -1; 1220 hr = IPicture_get_Type(pic, &type); 1221 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1222 ok(type == PICTYPE_ICON,"expected picture type PICTYPE_ICON, got %d\n", type); 1223 1224 hr = IPicture_get_Handle(pic, &handle); 1225 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1226 ok(IntToPtr(handle) == desc.icon.hicon, "get_Handle returned wrong handle %#x\n", handle); 1227 1228 hmem = GlobalAlloc(GMEM_ZEROINIT, 8192); 1229 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1230 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr); 1231 1232 size = -1; 1233 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1234 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1235 todo_wine 1236 ok(size == 766, "expected 766, got %d\n", size); 1237 mem = GlobalLock(hmem); 1238 ok(mem[0] == 0x00010000, "got wrong icon header %04x\n", mem[0]); 1239 GlobalUnlock(hmem); 1240 1241 size = -1; 1242 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1243 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr); 1244 ok(size == -1, "expected -1, got %d\n", size); 1245 1246 offset.QuadPart = 0; 1247 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1248 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1249 1250 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1251 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1252 1253 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1254 ok(hr == S_OK, "Saveerror %#x\n", hr); 1255 1256 IPersistStream_Release(src_stream); 1257 IStream_Release(dst_stream); 1258 1259 mem = GlobalLock(hmem); 1260 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1261 todo_wine 1262 ok(mem[1] == 766, "expected stream size 766, got %u\n", mem[1]); 1263 ok(mem[2] == 0x00010000, "got wrong icon header %04x\n", mem[2]); 1264 1265 GlobalUnlock(hmem); 1266 GlobalFree(hmem); 1267 1268 DestroyIcon(desc.icon.hicon); 1269 IPicture_Release(pic); 1270 } 1271 1272 static void test_load_save_empty_picture(void) 1273 { 1274 IPicture *pic; 1275 PICTDESC desc; 1276 short type; 1277 OLE_HANDLE handle; 1278 HGLOBAL hmem; 1279 DWORD *mem; 1280 IPersistStream *src_stream; 1281 IStream *dst_stream, *stream; 1282 LARGE_INTEGER offset; 1283 HRESULT hr; 1284 LONG size; 1285 1286 memset(&pic, 0, sizeof(pic)); 1287 desc.cbSizeofstruct = sizeof(desc); 1288 desc.picType = PICTYPE_NONE; 1289 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void **)&pic); 1290 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1291 1292 type = -1; 1293 hr = IPicture_get_Type(pic, &type); 1294 ok(hr == S_OK, "get_Type error %#x\n", hr); 1295 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type); 1296 1297 handle = (OLE_HANDLE)0xdeadbeef; 1298 hr = IPicture_get_Handle(pic, &handle); 1299 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1300 ok(!handle, "get_Handle returned wrong handle %#x\n", handle); 1301 1302 hmem = GlobalAlloc(GMEM_ZEROINIT, 4096); 1303 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1304 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr); 1305 1306 size = -1; 1307 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1308 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1309 ok(size == -1, "expected -1, got %d\n", size); 1310 1311 size = -1; 1312 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1313 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1314 ok(size == -1, "expected -1, got %d\n", size); 1315 1316 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1317 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1318 1319 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1320 ok(hr == S_OK, "Save error %#x\n", hr); 1321 1322 mem = GlobalLock(hmem); 1323 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1324 ok(mem[1] == 0, "expected stream size 0, got %u\n", mem[1]); 1325 GlobalUnlock(hmem); 1326 1327 IPersistStream_Release(src_stream); 1328 IPicture_Release(pic); 1329 1330 /* first with statable and seekable stream */ 1331 offset.QuadPart = 0; 1332 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1333 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1334 1335 pic = NULL; 1336 hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic); 1337 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr); 1338 ok(pic != NULL,"picture should not be not NULL\n"); 1339 if (pic != NULL) 1340 { 1341 type = -1; 1342 hr = IPicture_get_Type(pic, &type); 1343 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1344 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type); 1345 1346 handle = (OLE_HANDLE)0xdeadbeef; 1347 hr = IPicture_get_Handle(pic, &handle); 1348 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1349 ok(!handle, "get_Handle returned wrong handle %#x\n", handle); 1350 1351 IPicture_Release(pic); 1352 } 1353 IStream_Release(dst_stream); 1354 1355 /* again with non-statable and non-seekable stream */ 1356 stream = NoStatStream_Construct(hmem); 1357 ok(stream != NULL, "failed to create empty image stream\n"); 1358 1359 pic = NULL; 1360 hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic); 1361 ok(hr == S_OK, "OleLoadPicture error %#x\n", hr); 1362 ok(pic != NULL,"picture should not be not NULL\n"); 1363 if (pic != NULL) 1364 { 1365 type = -1; 1366 hr = IPicture_get_Type(pic, &type); 1367 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1368 ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type); 1369 1370 handle = (OLE_HANDLE)0xdeadbeef; 1371 hr = IPicture_get_Handle(pic, &handle); 1372 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1373 ok(!handle, "get_Handle returned wrong handle %#x\n", handle); 1374 1375 IPicture_Release(pic); 1376 } 1377 /* Non-statable impl always deletes on release */ 1378 IStream_Release(stream); 1379 } 1380 1381 static void test_load_save_emf(void) 1382 { 1383 HDC hdc; 1384 IPicture *pic; 1385 PICTDESC desc; 1386 short type; 1387 OLE_HANDLE handle; 1388 HGLOBAL hmem; 1389 DWORD *mem; 1390 ENHMETAHEADER *emh; 1391 IPersistStream *src_stream; 1392 IStream *dst_stream; 1393 LARGE_INTEGER offset; 1394 HRESULT hr; 1395 LONG size; 1396 1397 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); 1398 ok(hdc != 0, "CreateEnhMetaFileA failed\n"); 1399 1400 desc.cbSizeofstruct = sizeof(desc); 1401 desc.picType = PICTYPE_ENHMETAFILE; 1402 desc.emf.hemf = CloseEnhMetaFile(hdc); 1403 ok(desc.emf.hemf != 0, "CloseEnhMetaFile failed\n"); 1404 hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic); 1405 ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr); 1406 1407 type = -1; 1408 hr = IPicture_get_Type(pic, &type); 1409 ok(hr == S_OK,"get_Type error %#8x\n", hr); 1410 ok(type == PICTYPE_ENHMETAFILE,"expected PICTYPE_ENHMETAFILE, got %d\n", type); 1411 1412 hr = IPicture_get_Handle(pic, &handle); 1413 ok(hr == S_OK,"get_Handle error %#8x\n", hr); 1414 ok(IntToPtr(handle) == desc.emf.hemf, "get_Handle returned wrong handle %#x\n", handle); 1415 1416 hmem = GlobalAlloc(GMEM_MOVEABLE, 0); 1417 hr = CreateStreamOnHGlobal(hmem, FALSE, &dst_stream); 1418 ok(hr == S_OK, "createstreamonhglobal error %#x\n", hr); 1419 1420 size = -1; 1421 hr = IPicture_SaveAsFile(pic, dst_stream, TRUE, &size); 1422 ok(hr == S_OK, "IPicture_SaveasFile error %#x\n", hr); 1423 ok(size == 128, "expected 128, got %d\n", size); 1424 emh = GlobalLock(hmem); 1425 if (size) 1426 { 1427 ok(emh->iType == EMR_HEADER, "wrong iType %04x\n", emh->iType); 1428 ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08x\n", emh->dSignature); 1429 } 1430 GlobalUnlock(hmem); 1431 1432 size = -1; 1433 hr = IPicture_SaveAsFile(pic, dst_stream, FALSE, &size); 1434 ok(hr == E_FAIL, "expected E_FAIL, got %#x\n", hr); 1435 ok(size == -1, "expected -1, got %d\n", size); 1436 1437 offset.QuadPart = 0; 1438 hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL); 1439 ok(hr == S_OK, "IStream_Seek %#x\n", hr); 1440 1441 hr = IPicture_QueryInterface(pic, &IID_IPersistStream, (void **)&src_stream); 1442 ok(hr == S_OK, "QueryInterface error %#x\n", hr); 1443 1444 hr = IPersistStream_Save(src_stream, dst_stream, TRUE); 1445 ok(hr == S_OK, "Save error %#x\n", hr); 1446 1447 IPersistStream_Release(src_stream); 1448 IStream_Release(dst_stream); 1449 1450 mem = GlobalLock(hmem); 1451 ok(!memcmp(mem, "lt\0\0", 4), "got wrong stream header %04x\n", mem[0]); 1452 ok(mem[1] == 128, "expected 128, got %u\n", mem[1]); 1453 emh = (ENHMETAHEADER *)(mem + 2); 1454 ok(emh->iType == EMR_HEADER, "wrong iType %04x\n", emh->iType); 1455 ok(emh->dSignature == ENHMETA_SIGNATURE, "wrong dSignature %08x\n", emh->dSignature); 1456 1457 GlobalUnlock(hmem); 1458 GlobalFree(hmem); 1459 1460 DeleteEnhMetaFile(desc.emf.hemf); 1461 IPicture_Release(pic); 1462 } 1463 1464 START_TEST(olepicture) 1465 { 1466 hOleaut32 = GetModuleHandleA("oleaut32.dll"); 1467 pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture"); 1468 pOleLoadPictureEx = (void*)GetProcAddress(hOleaut32, "OleLoadPictureEx"); 1469 if (!pOleLoadPicture) 1470 { 1471 win_skip("OleLoadPicture is not available\n"); 1472 return; 1473 } 1474 1475 /* Test regular 1x1 pixel images of gif, jpg, bmp type */ 1476 test_pic(gifimage, sizeof(gifimage)); 1477 test_pic(jpgimage, sizeof(jpgimage)); 1478 test_pic(bmpimage, sizeof(bmpimage)); 1479 test_pic(bmpimage_rle8, sizeof(bmpimage_rle8)); 1480 test_pic(gif4pixel, sizeof(gif4pixel)); 1481 /* FIXME: No PNG support in Windows... */ 1482 if (0) test_pic(pngimage, sizeof(pngimage)); 1483 test_empty_image(); 1484 test_empty_image_2(); 1485 if (pOleLoadPictureEx) 1486 { 1487 test_apm(); 1488 test_metafile(); 1489 test_enhmetafile(); 1490 } 1491 else 1492 win_skip("OleLoadPictureEx is not available\n"); 1493 test_Invoke(); 1494 test_OleCreatePictureIndirect(); 1495 test_Render(); 1496 test_get_Attributes(); 1497 test_get_Handle(); 1498 test_get_Type(); 1499 test_OleLoadPicturePath(); 1500 test_himetric(); 1501 test_load_save_bmp(); 1502 test_load_save_icon(); 1503 test_load_save_empty_picture(); 1504 test_load_save_emf(); 1505 } 1506 1507 1508 /* Helper functions only ... */ 1509 1510 1511 static inline NoStatStreamImpl *impl_from_IStream(IStream *iface) 1512 { 1513 return CONTAINING_RECORD(iface, NoStatStreamImpl, IStream_iface); 1514 } 1515 1516 static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This) 1517 { 1518 GlobalFree(This->supportHandle); 1519 This->supportHandle=0; 1520 HeapFree(GetProcessHeap(), 0, This); 1521 } 1522 1523 static ULONG WINAPI NoStatStreamImpl_AddRef( 1524 IStream* iface) 1525 { 1526 NoStatStreamImpl* const This = impl_from_IStream(iface); 1527 return InterlockedIncrement(&This->ref); 1528 } 1529 1530 static HRESULT WINAPI NoStatStreamImpl_QueryInterface( 1531 IStream* iface, 1532 REFIID riid, /* [in] */ 1533 void** ppvObject) /* [iid_is][out] */ 1534 { 1535 NoStatStreamImpl* const This = impl_from_IStream(iface); 1536 if (ppvObject==0) return E_INVALIDARG; 1537 *ppvObject = 0; 1538 1539 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IStream, riid)) 1540 *ppvObject = &This->IStream_iface; 1541 1542 if ((*ppvObject)==0) 1543 return E_NOINTERFACE; 1544 NoStatStreamImpl_AddRef(iface); 1545 return S_OK; 1546 } 1547 1548 static ULONG WINAPI NoStatStreamImpl_Release( 1549 IStream* iface) 1550 { 1551 NoStatStreamImpl* const This = impl_from_IStream(iface); 1552 ULONG newRef = InterlockedDecrement(&This->ref); 1553 if (newRef==0) 1554 NoStatStreamImpl_Destroy(This); 1555 return newRef; 1556 } 1557 1558 static HRESULT WINAPI NoStatStreamImpl_Read( 1559 IStream* iface, 1560 void* pv, /* [length_is][size_is][out] */ 1561 ULONG cb, /* [in] */ 1562 ULONG* pcbRead) /* [out] */ 1563 { 1564 NoStatStreamImpl* const This = impl_from_IStream(iface); 1565 void* supportBuffer; 1566 ULONG bytesReadBuffer; 1567 ULONG bytesToReadFromBuffer; 1568 1569 if (pcbRead==0) 1570 pcbRead = &bytesReadBuffer; 1571 bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb); 1572 supportBuffer = GlobalLock(This->supportHandle); 1573 memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer); 1574 This->currentPosition.u.LowPart+=bytesToReadFromBuffer; 1575 *pcbRead = bytesToReadFromBuffer; 1576 GlobalUnlock(This->supportHandle); 1577 if(*pcbRead == cb) 1578 return S_OK; 1579 return S_FALSE; 1580 } 1581 1582 static HRESULT WINAPI NoStatStreamImpl_Write( 1583 IStream* iface, 1584 const void* pv, /* [size_is][in] */ 1585 ULONG cb, /* [in] */ 1586 ULONG* pcbWritten) /* [out] */ 1587 { 1588 NoStatStreamImpl* const This = impl_from_IStream(iface); 1589 void* supportBuffer; 1590 ULARGE_INTEGER newSize; 1591 ULONG bytesWritten = 0; 1592 1593 if (pcbWritten == 0) 1594 pcbWritten = &bytesWritten; 1595 if (cb == 0) 1596 return S_OK; 1597 newSize.u.HighPart = 0; 1598 newSize.u.LowPart = This->currentPosition.u.LowPart + cb; 1599 if (newSize.u.LowPart > This->streamSize.u.LowPart) 1600 IStream_SetSize(iface, newSize); 1601 1602 supportBuffer = GlobalLock(This->supportHandle); 1603 memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb); 1604 This->currentPosition.u.LowPart+=cb; 1605 *pcbWritten = cb; 1606 GlobalUnlock(This->supportHandle); 1607 return S_OK; 1608 } 1609 1610 static HRESULT WINAPI NoStatStreamImpl_Seek( 1611 IStream* iface, 1612 LARGE_INTEGER dlibMove, /* [in] */ 1613 DWORD dwOrigin, /* [in] */ 1614 ULARGE_INTEGER* plibNewPosition) /* [out] */ 1615 { 1616 NoStatStreamImpl* const This = impl_from_IStream(iface); 1617 ULARGE_INTEGER newPosition; 1618 switch (dwOrigin) 1619 { 1620 case STREAM_SEEK_SET: 1621 newPosition.u.HighPart = 0; 1622 newPosition.u.LowPart = 0; 1623 break; 1624 case STREAM_SEEK_CUR: 1625 newPosition = This->currentPosition; 1626 break; 1627 case STREAM_SEEK_END: 1628 newPosition = This->streamSize; 1629 break; 1630 default: 1631 return STG_E_INVALIDFUNCTION; 1632 } 1633 if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart) 1634 return STG_E_INVALIDFUNCTION; 1635 newPosition.QuadPart += dlibMove.QuadPart; 1636 if (plibNewPosition) *plibNewPosition = newPosition; 1637 This->currentPosition = newPosition; 1638 return S_OK; 1639 } 1640 1641 static HRESULT WINAPI NoStatStreamImpl_SetSize( 1642 IStream* iface, 1643 ULARGE_INTEGER libNewSize) /* [in] */ 1644 { 1645 NoStatStreamImpl* const This = impl_from_IStream(iface); 1646 HGLOBAL supportHandle; 1647 if (libNewSize.u.HighPart != 0) 1648 return STG_E_INVALIDFUNCTION; 1649 if (This->streamSize.u.LowPart == libNewSize.u.LowPart) 1650 return S_OK; 1651 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0); 1652 if (supportHandle == 0) 1653 return STG_E_MEDIUMFULL; 1654 This->supportHandle = supportHandle; 1655 This->streamSize.u.LowPart = libNewSize.u.LowPart; 1656 return S_OK; 1657 } 1658 1659 static HRESULT WINAPI NoStatStreamImpl_CopyTo( 1660 IStream* iface, 1661 IStream* pstm, /* [unique][in] */ 1662 ULARGE_INTEGER cb, /* [in] */ 1663 ULARGE_INTEGER* pcbRead, /* [out] */ 1664 ULARGE_INTEGER* pcbWritten) /* [out] */ 1665 { 1666 HRESULT hr = S_OK; 1667 BYTE tmpBuffer[128]; 1668 ULONG bytesRead, bytesWritten, copySize; 1669 ULARGE_INTEGER totalBytesRead; 1670 ULARGE_INTEGER totalBytesWritten; 1671 1672 if ( pstm == 0 ) 1673 return STG_E_INVALIDPOINTER; 1674 totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0; 1675 totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0; 1676 1677 while ( cb.u.LowPart > 0 ) 1678 { 1679 if ( cb.u.LowPart >= 128 ) 1680 copySize = 128; 1681 else 1682 copySize = cb.u.LowPart; 1683 IStream_Read(iface, tmpBuffer, copySize, &bytesRead); 1684 totalBytesRead.u.LowPart += bytesRead; 1685 IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten); 1686 totalBytesWritten.u.LowPart += bytesWritten; 1687 if (bytesRead != bytesWritten) 1688 { 1689 hr = STG_E_MEDIUMFULL; 1690 break; 1691 } 1692 if (bytesRead!=copySize) 1693 cb.u.LowPart = 0; 1694 else 1695 cb.u.LowPart -= bytesRead; 1696 } 1697 if (pcbRead) 1698 { 1699 pcbRead->u.LowPart = totalBytesRead.u.LowPart; 1700 pcbRead->u.HighPart = totalBytesRead.u.HighPart; 1701 } 1702 1703 if (pcbWritten) 1704 { 1705 pcbWritten->u.LowPart = totalBytesWritten.u.LowPart; 1706 pcbWritten->u.HighPart = totalBytesWritten.u.HighPart; 1707 } 1708 return hr; 1709 } 1710 1711 static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags) 1712 { 1713 return S_OK; 1714 } 1715 static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; } 1716 1717 static HRESULT WINAPI NoStatStreamImpl_LockRegion( 1718 IStream* iface, 1719 ULARGE_INTEGER libOffset, /* [in] */ 1720 ULARGE_INTEGER cb, /* [in] */ 1721 DWORD dwLockType) /* [in] */ 1722 { 1723 return S_OK; 1724 } 1725 1726 static HRESULT WINAPI NoStatStreamImpl_UnlockRegion( 1727 IStream* iface, 1728 ULARGE_INTEGER libOffset, /* [in] */ 1729 ULARGE_INTEGER cb, /* [in] */ 1730 DWORD dwLockType) /* [in] */ 1731 { 1732 return S_OK; 1733 } 1734 1735 static HRESULT WINAPI NoStatStreamImpl_Stat( 1736 IStream* iface, 1737 STATSTG* pstatstg, /* [out] */ 1738 DWORD grfStatFlag) /* [in] */ 1739 { 1740 return E_NOTIMPL; 1741 } 1742 1743 static HRESULT WINAPI NoStatStreamImpl_Clone( 1744 IStream* iface, 1745 IStream** ppstm) /* [out] */ 1746 { 1747 return E_NOTIMPL; 1748 } 1749 static const IStreamVtbl NoStatStreamImpl_Vtbl; 1750 1751 /* 1752 Build an object that implements IStream, without IStream_Stat capabilities. 1753 Receives a memory handle with data buffer. If memory handle is non-null, 1754 it is assumed to be unlocked, otherwise an internal memory handle is allocated. 1755 In any case the object takes ownership of memory handle and will free it on 1756 object release. 1757 */ 1758 static IStream* NoStatStream_Construct(HGLOBAL hGlobal) 1759 { 1760 NoStatStreamImpl* newStream; 1761 1762 newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl)); 1763 if (newStream!=0) 1764 { 1765 newStream->IStream_iface.lpVtbl = &NoStatStreamImpl_Vtbl; 1766 newStream->ref = 1; 1767 newStream->supportHandle = hGlobal; 1768 1769 if (!newStream->supportHandle) 1770 newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | 1771 GMEM_SHARE, 0); 1772 newStream->currentPosition.u.HighPart = 0; 1773 newStream->currentPosition.u.LowPart = 0; 1774 newStream->streamSize.u.HighPart = 0; 1775 newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle); 1776 } 1777 return &newStream->IStream_iface; 1778 } 1779 1780 1781 static const IStreamVtbl NoStatStreamImpl_Vtbl = 1782 { 1783 NoStatStreamImpl_QueryInterface, 1784 NoStatStreamImpl_AddRef, 1785 NoStatStreamImpl_Release, 1786 NoStatStreamImpl_Read, 1787 NoStatStreamImpl_Write, 1788 NoStatStreamImpl_Seek, 1789 NoStatStreamImpl_SetSize, 1790 NoStatStreamImpl_CopyTo, 1791 NoStatStreamImpl_Commit, 1792 NoStatStreamImpl_Revert, 1793 NoStatStreamImpl_LockRegion, 1794 NoStatStreamImpl_UnlockRegion, 1795 NoStatStreamImpl_Stat, 1796 NoStatStreamImpl_Clone 1797 }; 1798