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