1 /* 2 * Copyright 2007 Robert Shearman for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #define COBJMACROS 20 #define CONST_VTABLE 21 22 #include <wine/test.h> 23 #include <stdarg.h> 24 #include <stddef.h> 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "ole2.h" 29 #include "urlmon.h" 30 #include "wininet.h" 31 32 #define DEFINE_EXPECT(func) \ 33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 34 35 #define SET_EXPECT(func) \ 36 expect_ ## func = TRUE 37 38 #define CHECK_EXPECT(func) \ 39 do { \ 40 ok(expect_ ##func, "unexpected call " #func "\n"); \ 41 expect_ ## func = FALSE; \ 42 called_ ## func = TRUE; \ 43 }while(0) 44 45 #define CHECK_EXPECT2(func) \ 46 do { \ 47 ok(expect_ ##func, "unexpected call " #func "\n"); \ 48 called_ ## func = TRUE; \ 49 }while(0) 50 51 #define CHECK_CALLED(func) \ 52 do { \ 53 ok(called_ ## func, "expected " #func "\n"); \ 54 expect_ ## func = called_ ## func = FALSE; \ 55 }while(0) 56 57 #define CHECK_NOT_CALLED(func) \ 58 do { \ 59 ok(!called_ ## func, "unexpected " #func "\n"); \ 60 expect_ ## func = called_ ## func = FALSE; \ 61 }while(0) 62 63 #define CLEAR_CALLED(func) \ 64 expect_ ## func = called_ ## func = FALSE 65 66 DEFINE_EXPECT(QueryInterface_IServiceProvider); 67 DEFINE_EXPECT(OnStartBinding); 68 DEFINE_EXPECT(OnProgress_FINDINGRESOURCE); 69 DEFINE_EXPECT(OnProgress_CONNECTING); 70 DEFINE_EXPECT(OnProgress_SENDINGREQUEST); 71 DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE); 72 DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA); 73 DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA); 74 DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA); 75 DEFINE_EXPECT(OnStopBinding); 76 DEFINE_EXPECT(OnDataAvailable); 77 DEFINE_EXPECT(GetBindInfo); 78 79 static const CHAR wszIndexHtmlA[] = "index.html"; 80 static WCHAR INDEX_HTML[MAX_PATH]; 81 static const char szHtmlDoc[] = "<HTML></HTML>"; 82 83 static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv) 84 { 85 if (IsEqualGUID(&IID_IBindStatusCallback, riid) || 86 IsEqualGUID(&IID_IUnknown, riid)) 87 { 88 *ppv = iface; 89 return S_OK; 90 } 91 else if (IsEqualGUID(&IID_IServiceProvider, riid)) 92 { 93 CHECK_EXPECT(QueryInterface_IServiceProvider); 94 } 95 96 return E_NOINTERFACE; 97 } 98 99 static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface) 100 { 101 return 2; 102 } 103 104 static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface) 105 { 106 return 1; 107 } 108 109 static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, 110 IBinding *pib) 111 { 112 HRESULT hres; 113 IMoniker *mon; 114 115 CHECK_EXPECT(OnStartBinding); 116 117 ok(pib != NULL, "pib should not be NULL\n"); 118 119 hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon); 120 ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n"); 121 if(SUCCEEDED(hres)) 122 IMoniker_Release(mon); 123 124 return S_OK; 125 } 126 127 static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) 128 { 129 ok(0, "unexpected call\n"); 130 return E_NOTIMPL; 131 } 132 133 static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved) 134 { 135 ok(0, "unexpected call\n"); 136 return E_NOTIMPL; 137 } 138 139 static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, 140 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 141 { 142 switch(ulStatusCode) { 143 case BINDSTATUS_FINDINGRESOURCE: 144 CHECK_EXPECT(OnProgress_FINDINGRESOURCE); 145 break; 146 case BINDSTATUS_CONNECTING: 147 CHECK_EXPECT(OnProgress_CONNECTING); 148 break; 149 case BINDSTATUS_SENDINGREQUEST: 150 CHECK_EXPECT(OnProgress_SENDINGREQUEST); 151 break; 152 case BINDSTATUS_MIMETYPEAVAILABLE: 153 CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE); 154 break; 155 case BINDSTATUS_BEGINDOWNLOADDATA: 156 CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA); 157 ok(szStatusText != NULL, "szStatusText == NULL\n"); 158 break; 159 case BINDSTATUS_DOWNLOADINGDATA: 160 CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA); 161 break; 162 case BINDSTATUS_ENDDOWNLOADDATA: 163 CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA); 164 ok(szStatusText != NULL, "szStatusText == NULL\n"); 165 break; 166 case BINDSTATUS_CACHEFILENAMEAVAILABLE: 167 ok(szStatusText != NULL, "szStatusText == NULL\n"); 168 break; 169 default: 170 todo_wine { ok(0, "unexpected code %d\n", ulStatusCode); } 171 }; 172 return S_OK; 173 } 174 175 static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError) 176 { 177 CHECK_EXPECT(OnStopBinding); 178 179 /* ignore DNS failure */ 180 if (hresult != HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED)) 181 { 182 ok(SUCCEEDED(hresult), "Download failed: %08x\n", hresult); 183 ok(szError == NULL, "szError should be NULL\n"); 184 } 185 186 return S_OK; 187 } 188 189 static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) 190 { 191 DWORD cbSize; 192 193 CHECK_EXPECT(GetBindInfo); 194 195 *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA; 196 cbSize = pbindinfo->cbSize; 197 memset(pbindinfo, 0, cbSize); 198 pbindinfo->cbSize = cbSize; 199 200 return S_OK; 201 } 202 203 static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, 204 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed) 205 { 206 HRESULT hres; 207 DWORD readed; 208 BYTE buf[512]; 209 210 CHECK_EXPECT2(OnDataAvailable); 211 212 if (0) 213 { 214 /* FIXME: Uncomment after removing BindToStorage hack. */ 215 ok(pformatetc != NULL, "pformatetx == NULL\n"); 216 if(pformatetc) { 217 ok(pformatetc->cfFormat == 0xc02d, "clipformat=%x\n", pformatetc->cfFormat); 218 ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd); 219 ok(pformatetc->dwAspect == 1, "dwAspect=%u\n", pformatetc->dwAspect); 220 ok(pformatetc->lindex == -1, "lindex=%d\n", pformatetc->lindex); 221 ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%u\n", pformatetc->tymed); 222 } 223 224 ok(pstgmed != NULL, "stgmeg == NULL\n"); 225 if(pstgmed) { 226 ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%u\n", pstgmed->tymed); 227 ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n"); 228 ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n"); 229 } 230 } 231 232 if(U(*pstgmed).pstm) { 233 do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed); 234 while(hres == S_OK); 235 ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08x\n", hres); 236 } 237 238 return S_OK; 239 } 240 241 static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk) 242 { 243 ok(0, "unexpected call\n"); 244 return E_NOTIMPL; 245 } 246 247 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { 248 statusclb_QueryInterface, 249 statusclb_AddRef, 250 statusclb_Release, 251 statusclb_OnStartBinding, 252 statusclb_GetPriority, 253 statusclb_OnLowResource, 254 statusclb_OnProgress, 255 statusclb_OnStopBinding, 256 statusclb_GetBindInfo, 257 statusclb_OnDataAvailable, 258 statusclb_OnObjectAvailable 259 }; 260 261 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl }; 262 263 static void set_file_url(char *path) 264 { 265 char INDEX_HTML_A[MAX_PATH]; 266 267 lstrcpyA(INDEX_HTML_A, "file:///"); 268 lstrcatA(INDEX_HTML_A, path); 269 MultiByteToWideChar(CP_ACP, 0, INDEX_HTML_A, -1, INDEX_HTML, MAX_PATH); 270 } 271 272 static void create_file(void) 273 { 274 HANDLE file; 275 DWORD size; 276 CHAR path[MAX_PATH]; 277 278 file = CreateFileA(wszIndexHtmlA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 279 FILE_ATTRIBUTE_NORMAL, NULL); 280 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); 281 if(file == INVALID_HANDLE_VALUE) 282 return; 283 284 WriteFile(file, szHtmlDoc, sizeof(szHtmlDoc)-1, &size, NULL); 285 CloseHandle(file); 286 287 GetCurrentDirectoryA(MAX_PATH, path); 288 lstrcatA(path, "\\"); 289 lstrcatA(path, wszIndexHtmlA); 290 set_file_url(path); 291 } 292 293 static void test_URLOpenBlockingStreamW(void) 294 { 295 HRESULT hr; 296 IStream *pStream = NULL; 297 char buffer[256]; 298 299 hr = URLOpenBlockingStreamW(NULL, NULL, &pStream, 0, &BindStatusCallback); 300 ok(hr == E_INVALIDARG, "URLOpenBlockingStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr); 301 if (0) /* crashes on Win2k */ 302 { 303 hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, NULL, 0, &BindStatusCallback); 304 ok(hr == E_INVALIDARG, "URLOpenBlockingStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr); 305 } 306 307 SET_EXPECT(GetBindInfo); 308 SET_EXPECT(QueryInterface_IServiceProvider); 309 SET_EXPECT(OnStartBinding); 310 SET_EXPECT(OnProgress_SENDINGREQUEST); 311 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE); 312 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA); 313 SET_EXPECT(OnProgress_ENDDOWNLOADDATA); 314 SET_EXPECT(OnStopBinding); 315 316 hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, &pStream, 0, &BindStatusCallback); 317 ok(hr == S_OK, "URLOpenBlockingStreamW failed with error 0x%08x\n", hr); 318 319 CHECK_CALLED(GetBindInfo); 320 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider); 321 CHECK_CALLED(OnStartBinding); 322 CHECK_CALLED(OnProgress_SENDINGREQUEST); 323 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); 324 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA); 325 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA); 326 CHECK_CALLED(OnStopBinding); 327 328 ok(pStream != NULL, "pStream is NULL\n"); 329 if(pStream) 330 { 331 buffer[0] = 0; 332 hr = IStream_Read(pStream, buffer, sizeof(buffer), NULL); 333 ok(hr == S_OK, "IStream_Read failed with error 0x%08x\n", hr); 334 ok(!memcmp(buffer, szHtmlDoc, sizeof(szHtmlDoc)-1), "read data differs from file\n"); 335 336 IStream_Release(pStream); 337 } 338 339 hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, &pStream, 0, NULL); 340 ok(hr == S_OK, "URLOpenBlockingStreamW failed with error 0x%08x\n", hr); 341 342 ok(pStream != NULL, "pStream is NULL\n"); 343 if(pStream) 344 { 345 buffer[0] = 0; 346 hr = IStream_Read(pStream, buffer, sizeof(buffer), NULL); 347 ok(hr == S_OK, "IStream_Read failed with error 0x%08x\n", hr); 348 ok(!memcmp(buffer, szHtmlDoc, sizeof(szHtmlDoc)-1), "read data differs from file\n"); 349 350 IStream_Release(pStream); 351 } 352 } 353 354 static void test_URLOpenStreamW(void) 355 { 356 HRESULT hr; 357 358 hr = URLOpenStreamW(NULL, NULL, 0, &BindStatusCallback); 359 ok(hr == E_INVALIDARG, "URLOpenStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr); 360 361 SET_EXPECT(GetBindInfo); 362 SET_EXPECT(QueryInterface_IServiceProvider); 363 SET_EXPECT(OnStartBinding); 364 SET_EXPECT(OnProgress_SENDINGREQUEST); 365 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE); 366 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA); 367 SET_EXPECT(OnProgress_ENDDOWNLOADDATA); 368 SET_EXPECT(OnDataAvailable); 369 SET_EXPECT(OnStopBinding); 370 371 hr = URLOpenStreamW(NULL, INDEX_HTML, 0, &BindStatusCallback); 372 ok(hr == S_OK, "URLOpenStreamW failed with error 0x%08x\n", hr); 373 374 CHECK_CALLED(GetBindInfo); 375 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider); 376 CHECK_CALLED(OnStartBinding); 377 CHECK_CALLED(OnProgress_SENDINGREQUEST); 378 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); 379 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA); 380 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA); 381 CHECK_CALLED(OnDataAvailable); 382 CHECK_CALLED(OnStopBinding); 383 384 hr = URLOpenStreamW(NULL, INDEX_HTML, 0, NULL); 385 ok(hr == S_OK, "URLOpenStreamW failed with error 0x%08x\n", hr); 386 } 387 388 START_TEST(stream) 389 { 390 if(!GetProcAddress(GetModuleHandleA("urlmon.dll"), "CompareSecurityIds")) { 391 win_skip("Too old IE\n"); 392 return; 393 } 394 395 create_file(); 396 test_URLOpenBlockingStreamW(); 397 test_URLOpenStreamW(); 398 DeleteFileA(wszIndexHtmlA); 399 } 400