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