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