Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhttp.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2005 Jacek Caban 00003 * Copyright 2007 Misha Koshelev 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00018 */ 00019 00020 #include "urlmon_main.h" 00021 #include "wininet.h" 00022 00023 #define NO_SHLWAPI_REG 00024 #include "shlwapi.h" 00025 00026 #include "wine/debug.h" 00027 00028 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 00029 00030 typedef struct { 00031 Protocol base; 00032 00033 IInternetProtocolEx IInternetProtocolEx_iface; 00034 IInternetPriority IInternetPriority_iface; 00035 IWinInetHttpInfo IWinInetHttpInfo_iface; 00036 00037 BOOL https; 00038 IHttpNegotiate *http_negotiate; 00039 WCHAR *full_header; 00040 00041 LONG ref; 00042 } HttpProtocol; 00043 00044 static inline HttpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) 00045 { 00046 return CONTAINING_RECORD(iface, HttpProtocol, IInternetProtocolEx_iface); 00047 } 00048 00049 static inline HttpProtocol *impl_from_IInternetPriority(IInternetPriority *iface) 00050 { 00051 return CONTAINING_RECORD(iface, HttpProtocol, IInternetPriority_iface); 00052 } 00053 00054 static inline HttpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface) 00055 { 00056 return CONTAINING_RECORD(iface, HttpProtocol, IWinInetHttpInfo_iface); 00057 } 00058 00059 static const WCHAR default_headersW[] = { 00060 'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',':',' ','g','z','i','p',',',' ','d','e','f','l','a','t','e',0}; 00061 00062 static LPWSTR query_http_info(HttpProtocol *This, DWORD option) 00063 { 00064 LPWSTR ret = NULL; 00065 DWORD len = 0; 00066 BOOL res; 00067 00068 res = HttpQueryInfoW(This->base.request, option, NULL, &len, NULL); 00069 if (!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 00070 ret = heap_alloc(len); 00071 res = HttpQueryInfoW(This->base.request, option, ret, &len, NULL); 00072 } 00073 if(!res) { 00074 TRACE("HttpQueryInfoW(%d) failed: %08x\n", option, GetLastError()); 00075 heap_free(ret); 00076 return NULL; 00077 } 00078 00079 return ret; 00080 } 00081 00082 static inline BOOL set_security_flag(HttpProtocol *This, DWORD new_flag) 00083 { 00084 DWORD flags, size = sizeof(flags); 00085 BOOL res; 00086 00087 res = InternetQueryOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size); 00088 if(res) { 00089 flags |= new_flag; 00090 res = InternetSetOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, size); 00091 } 00092 if(!res) 00093 ERR("Failed to set security flag(s): %x\n", new_flag); 00094 00095 return res; 00096 } 00097 00098 static inline HRESULT internet_error_to_hres(DWORD error) 00099 { 00100 switch(error) 00101 { 00102 case ERROR_INTERNET_SEC_CERT_DATE_INVALID: 00103 case ERROR_INTERNET_SEC_CERT_CN_INVALID: 00104 case ERROR_INTERNET_INVALID_CA: 00105 case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED: 00106 return INET_E_INVALID_CERTIFICATE; 00107 case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR: 00108 case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR: 00109 case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION: 00110 return INET_E_REDIRECT_FAILED; 00111 default: 00112 return INET_E_DOWNLOAD_FAILURE; 00113 } 00114 } 00115 00116 static HRESULT handle_http_error(HttpProtocol *This, DWORD error) 00117 { 00118 IServiceProvider *serv_prov; 00119 IWindowForBindingUI *wfb_ui; 00120 IHttpSecurity *http_security; 00121 BOOL security_problem; 00122 HRESULT hres; 00123 00124 switch(error) { 00125 case ERROR_INTERNET_SEC_CERT_DATE_INVALID: 00126 case ERROR_INTERNET_SEC_CERT_CN_INVALID: 00127 case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR: 00128 case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR: 00129 case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION: 00130 case ERROR_INTERNET_INVALID_CA: 00131 case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED: 00132 security_problem = TRUE; 00133 break; 00134 default: 00135 security_problem = FALSE; 00136 } 00137 00138 hres = IInternetProtocolSink_QueryInterface(This->base.protocol_sink, &IID_IServiceProvider, 00139 (void**)&serv_prov); 00140 if(FAILED(hres)) { 00141 ERR("Failed to get IServiceProvider.\n"); 00142 return E_ABORT; 00143 } 00144 00145 if(security_problem) { 00146 hres = IServiceProvider_QueryService(serv_prov, &IID_IHttpSecurity, &IID_IHttpSecurity, 00147 (void**)&http_security); 00148 if(SUCCEEDED(hres)) { 00149 hres = IHttpSecurity_OnSecurityProblem(http_security, error); 00150 IHttpSecurity_Release(http_security); 00151 00152 if(hres != S_FALSE) 00153 { 00154 BOOL res = FALSE; 00155 00156 IServiceProvider_Release(serv_prov); 00157 00158 if(hres == S_OK) { 00159 if(error == ERROR_INTERNET_SEC_CERT_DATE_INVALID) 00160 res = set_security_flag(This, SECURITY_FLAG_IGNORE_CERT_DATE_INVALID); 00161 else if(error == ERROR_INTERNET_SEC_CERT_CN_INVALID) 00162 res = set_security_flag(This, SECURITY_FLAG_IGNORE_CERT_CN_INVALID); 00163 else if(error == ERROR_INTERNET_INVALID_CA) 00164 res = set_security_flag(This, SECURITY_FLAG_IGNORE_UNKNOWN_CA); 00165 00166 if(res) 00167 return RPC_E_RETRY; 00168 00169 FIXME("Don't know how to ignore error %d\n", error); 00170 return E_ABORT; 00171 } 00172 00173 if(hres == E_ABORT) 00174 return E_ABORT; 00175 if(hres == RPC_E_RETRY) 00176 return RPC_E_RETRY; 00177 00178 return internet_error_to_hres(error); 00179 } 00180 } 00181 } 00182 00183 hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI, 00184 (void**)&wfb_ui); 00185 if(SUCCEEDED(hres)) { 00186 HWND hwnd; 00187 const IID *iid_reason; 00188 00189 if(security_problem) 00190 iid_reason = &IID_IHttpSecurity; 00191 else if(error == ERROR_INTERNET_INCORRECT_PASSWORD) 00192 iid_reason = &IID_IAuthenticate; 00193 else 00194 iid_reason = &IID_IWindowForBindingUI; 00195 00196 hres = IWindowForBindingUI_GetWindow(wfb_ui, iid_reason, &hwnd); 00197 if(SUCCEEDED(hres) && hwnd) 00198 { 00199 DWORD res; 00200 00201 res = InternetErrorDlg(hwnd, This->base.request, error, 00202 FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, 00203 NULL); 00204 00205 if(res == ERROR_INTERNET_FORCE_RETRY || res == ERROR_SUCCESS) 00206 hres = RPC_E_RETRY; 00207 else 00208 hres = E_FAIL; 00209 } 00210 IWindowForBindingUI_Release(wfb_ui); 00211 } 00212 00213 IServiceProvider_Release(serv_prov); 00214 00215 if(hres == RPC_E_RETRY) 00216 return hres; 00217 00218 return internet_error_to_hres(error); 00219 } 00220 00221 static ULONG send_http_request(HttpProtocol *This) 00222 { 00223 INTERNET_BUFFERSW send_buffer = {sizeof(INTERNET_BUFFERSW)}; 00224 BOOL res; 00225 00226 send_buffer.lpcszHeader = This->full_header; 00227 send_buffer.dwHeadersLength = send_buffer.dwHeadersTotal = strlenW(This->full_header); 00228 00229 if(This->base.bind_info.dwBindVerb != BINDVERB_GET) { 00230 switch(This->base.bind_info.stgmedData.tymed) { 00231 case TYMED_HGLOBAL: 00232 /* Native does not use GlobalLock/GlobalUnlock, so we won't either */ 00233 send_buffer.lpvBuffer = This->base.bind_info.stgmedData.u.hGlobal; 00234 send_buffer.dwBufferLength = send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData; 00235 break; 00236 case TYMED_ISTREAM: { 00237 LARGE_INTEGER offset; 00238 00239 send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData; 00240 if(!This->base.post_stream) { 00241 This->base.post_stream = This->base.bind_info.stgmedData.u.pstm; 00242 IStream_AddRef(This->base.post_stream); 00243 } 00244 00245 offset.QuadPart = 0; 00246 IStream_Seek(This->base.post_stream, offset, STREAM_SEEK_SET, NULL); 00247 break; 00248 } 00249 default: 00250 FIXME("Unsupported This->base.bind_info.stgmedData.tymed %d\n", This->base.bind_info.stgmedData.tymed); 00251 } 00252 } 00253 00254 if(This->base.post_stream) 00255 res = HttpSendRequestExW(This->base.request, &send_buffer, NULL, 0, 0); 00256 else 00257 res = HttpSendRequestW(This->base.request, send_buffer.lpcszHeader, send_buffer.dwHeadersLength, 00258 send_buffer.lpvBuffer, send_buffer.dwBufferLength); 00259 00260 return res ? 0 : GetLastError(); 00261 } 00262 00263 static inline HttpProtocol *impl_from_Protocol(Protocol *prot) 00264 { 00265 return CONTAINING_RECORD(prot, HttpProtocol, base); 00266 } 00267 00268 static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags, 00269 HINTERNET internet_session, IInternetBindInfo *bind_info) 00270 { 00271 HttpProtocol *This = impl_from_Protocol(prot); 00272 LPWSTR addl_header = NULL, post_cookie = NULL; 00273 IServiceProvider *service_provider = NULL; 00274 IHttpNegotiate2 *http_negotiate2 = NULL; 00275 BSTR url, host, user, pass, path; 00276 LPOLESTR accept_mimes[257]; 00277 const WCHAR **accept_types; 00278 BYTE security_id[512]; 00279 DWORD len, port; 00280 ULONG num, error; 00281 BOOL res, b; 00282 HRESULT hres; 00283 00284 static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] = 00285 {{'G','E','T',0}, 00286 {'P','O','S','T',0}, 00287 {'P','U','T',0}}; 00288 00289 hres = IUri_GetPort(uri, &port); 00290 if(FAILED(hres)) 00291 return hres; 00292 00293 hres = IUri_GetHost(uri, &host); 00294 if(FAILED(hres)) 00295 return hres; 00296 00297 hres = IUri_GetUserName(uri, &user); 00298 if(SUCCEEDED(hres)) { 00299 hres = IUri_GetPassword(uri, &pass); 00300 00301 if(SUCCEEDED(hres)) { 00302 This->base.connection = InternetConnectW(internet_session, host, port, user, pass, 00303 INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base); 00304 SysFreeString(pass); 00305 } 00306 SysFreeString(user); 00307 } 00308 SysFreeString(host); 00309 if(FAILED(hres)) 00310 return hres; 00311 if(!This->base.connection) { 00312 WARN("InternetConnect failed: %d\n", GetLastError()); 00313 return INET_E_CANNOT_CONNECT; 00314 } 00315 00316 num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1; 00317 hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ACCEPT_MIMES, accept_mimes, num, &num); 00318 if(hres == INET_E_USE_DEFAULT_SETTING) { 00319 static const WCHAR default_accept_mimeW[] = {'*','/','*',0}; 00320 static const WCHAR *default_accept_mimes[] = {default_accept_mimeW, NULL}; 00321 00322 accept_types = default_accept_mimes; 00323 num = 0; 00324 }else if(hres == S_OK) { 00325 accept_types = (const WCHAR**)accept_mimes; 00326 }else { 00327 WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres); 00328 return INET_E_NO_VALID_MEDIA; 00329 } 00330 accept_mimes[num] = 0; 00331 00332 if(This->https) 00333 request_flags |= INTERNET_FLAG_SECURE; 00334 00335 hres = IUri_GetPathAndQuery(uri, &path); 00336 if(SUCCEEDED(hres)) { 00337 This->base.request = HttpOpenRequestW(This->base.connection, 00338 This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM 00339 ? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb, 00340 path, NULL, NULL, accept_types, request_flags, (DWORD_PTR)&This->base); 00341 SysFreeString(path); 00342 } 00343 while(num--) 00344 CoTaskMemFree(accept_mimes[num]); 00345 if(FAILED(hres)) 00346 return hres; 00347 if (!This->base.request) { 00348 WARN("HttpOpenRequest failed: %d\n", GetLastError()); 00349 return INET_E_RESOURCE_NOT_FOUND; 00350 } 00351 00352 hres = IInternetProtocolSink_QueryInterface(This->base.protocol_sink, &IID_IServiceProvider, 00353 (void **)&service_provider); 00354 if (hres != S_OK) { 00355 WARN("IInternetProtocolSink_QueryInterface IID_IServiceProvider failed: %08x\n", hres); 00356 return hres; 00357 } 00358 00359 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, 00360 &IID_IHttpNegotiate, (void **)&This->http_negotiate); 00361 if (hres != S_OK) { 00362 WARN("IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x\n", hres); 00363 IServiceProvider_Release(service_provider); 00364 return hres; 00365 } 00366 00367 hres = IUri_GetAbsoluteUri(uri, &url); 00368 if(FAILED(hres)) { 00369 IServiceProvider_Release(service_provider); 00370 return hres; 00371 } 00372 00373 hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, default_headersW, 00374 0, &addl_header); 00375 SysFreeString(url); 00376 if(hres != S_OK) { 00377 WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres); 00378 IServiceProvider_Release(service_provider); 00379 return hres; 00380 } 00381 00382 len = addl_header ? strlenW(addl_header) : 0; 00383 00384 This->full_header = heap_alloc(len*sizeof(WCHAR)+sizeof(default_headersW)); 00385 if(!This->full_header) { 00386 IServiceProvider_Release(service_provider); 00387 return E_OUTOFMEMORY; 00388 } 00389 00390 if(len) 00391 memcpy(This->full_header, addl_header, len*sizeof(WCHAR)); 00392 CoTaskMemFree(addl_header); 00393 memcpy(This->full_header+len, default_headersW, sizeof(default_headersW)); 00394 00395 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2, 00396 &IID_IHttpNegotiate2, (void **)&http_negotiate2); 00397 IServiceProvider_Release(service_provider); 00398 if(hres != S_OK) { 00399 WARN("IServiceProvider_QueryService IID_IHttpNegotiate2 failed: %08x\n", hres); 00400 /* No goto done as per native */ 00401 }else { 00402 len = sizeof(security_id)/sizeof(security_id[0]); 00403 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, security_id, &len, 0); 00404 IHttpNegotiate2_Release(http_negotiate2); 00405 if (hres != S_OK) 00406 WARN("IHttpNegotiate2_GetRootSecurityId failed: %08x\n", hres); 00407 } 00408 00409 /* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */ 00410 00411 if(This->base.bind_info.dwBindVerb == BINDVERB_POST) { 00412 num = 0; 00413 hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_POST_COOKIE, &post_cookie, 1, &num); 00414 if(hres == S_OK && num) { 00415 if(!InternetSetOptionW(This->base.request, INTERNET_OPTION_SECONDARY_CACHE_KEY, 00416 post_cookie, lstrlenW(post_cookie))) 00417 WARN("InternetSetOption INTERNET_OPTION_SECONDARY_CACHE_KEY failed: %d\n", GetLastError()); 00418 CoTaskMemFree(post_cookie); 00419 } 00420 } 00421 00422 b = TRUE; 00423 res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b)); 00424 if(!res) 00425 WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError()); 00426 00427 do { 00428 error = send_http_request(This); 00429 00430 if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS) 00431 return S_OK; 00432 00433 hres = handle_http_error(This, error); 00434 00435 } while(hres == RPC_E_RETRY); 00436 00437 WARN("HttpSendRequest failed: %d\n", error); 00438 return hres; 00439 } 00440 00441 static HRESULT HttpProtocol_end_request(Protocol *protocol) 00442 { 00443 BOOL res; 00444 00445 res = HttpEndRequestW(protocol->request, NULL, 0, 0); 00446 if(!res && GetLastError() != ERROR_IO_PENDING) { 00447 FIXME("HttpEndRequest failed: %u\n", GetLastError()); 00448 return E_FAIL; 00449 } 00450 00451 return S_OK; 00452 } 00453 00454 static HRESULT HttpProtocol_start_downloading(Protocol *prot) 00455 { 00456 HttpProtocol *This = impl_from_Protocol(prot); 00457 LPWSTR content_type, content_length, ranges; 00458 DWORD len = sizeof(DWORD); 00459 DWORD status_code; 00460 BOOL res; 00461 HRESULT hres; 00462 00463 static const WCHAR wszDefaultContentType[] = 00464 {'t','e','x','t','/','h','t','m','l',0}; 00465 00466 if(!This->http_negotiate) { 00467 WARN("Expected IHttpNegotiate pointer to be non-NULL\n"); 00468 return S_OK; 00469 } 00470 00471 res = HttpQueryInfoW(This->base.request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, 00472 &status_code, &len, NULL); 00473 if(res) { 00474 LPWSTR response_headers = query_http_info(This, HTTP_QUERY_RAW_HEADERS_CRLF); 00475 if(response_headers) { 00476 hres = IHttpNegotiate_OnResponse(This->http_negotiate, status_code, response_headers, 00477 NULL, NULL); 00478 heap_free(response_headers); 00479 if (hres != S_OK) { 00480 WARN("IHttpNegotiate_OnResponse failed: %08x\n", hres); 00481 return S_OK; 00482 } 00483 } 00484 }else { 00485 WARN("HttpQueryInfo failed: %d\n", GetLastError()); 00486 } 00487 00488 ranges = query_http_info(This, HTTP_QUERY_ACCEPT_RANGES); 00489 if(ranges) { 00490 IInternetProtocolSink_ReportProgress(This->base.protocol_sink, BINDSTATUS_ACCEPTRANGES, NULL); 00491 heap_free(ranges); 00492 } 00493 00494 content_type = query_http_info(This, HTTP_QUERY_CONTENT_TYPE); 00495 if(content_type) { 00496 /* remove the charset, if present */ 00497 LPWSTR p = strchrW(content_type, ';'); 00498 if (p) *p = '\0'; 00499 00500 IInternetProtocolSink_ReportProgress(This->base.protocol_sink, 00501 (This->base.bindf & BINDF_FROMURLMON) 00502 ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE, 00503 content_type); 00504 heap_free(content_type); 00505 }else { 00506 WARN("HttpQueryInfo failed: %d\n", GetLastError()); 00507 IInternetProtocolSink_ReportProgress(This->base.protocol_sink, 00508 (This->base.bindf & BINDF_FROMURLMON) 00509 ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE, 00510 wszDefaultContentType); 00511 } 00512 00513 content_length = query_http_info(This, HTTP_QUERY_CONTENT_LENGTH); 00514 if(content_length) { 00515 This->base.content_length = atoiW(content_length); 00516 heap_free(content_length); 00517 } 00518 00519 return S_OK; 00520 } 00521 00522 static void HttpProtocol_close_connection(Protocol *prot) 00523 { 00524 HttpProtocol *This = impl_from_Protocol(prot); 00525 00526 if(This->http_negotiate) { 00527 IHttpNegotiate_Release(This->http_negotiate); 00528 This->http_negotiate = NULL; 00529 } 00530 00531 if(This->full_header) { 00532 heap_free(This->full_header); 00533 This->full_header = NULL; 00534 } 00535 } 00536 00537 static void HttpProtocol_on_error(Protocol *prot, DWORD error) 00538 { 00539 HttpProtocol *This = impl_from_Protocol(prot); 00540 HRESULT hres; 00541 00542 TRACE("(%p) %d\n", prot, error); 00543 00544 if(prot->flags & FLAG_FIRST_CONTINUE_COMPLETE) { 00545 FIXME("Not handling error %d\n", error); 00546 return; 00547 } 00548 00549 while((hres = handle_http_error(This, error)) == RPC_E_RETRY) { 00550 error = send_http_request(This); 00551 00552 if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS) 00553 return; 00554 } 00555 00556 protocol_abort(prot, hres); 00557 protocol_close_connection(prot); 00558 return; 00559 } 00560 00561 static const ProtocolVtbl AsyncProtocolVtbl = { 00562 HttpProtocol_open_request, 00563 HttpProtocol_end_request, 00564 HttpProtocol_start_downloading, 00565 HttpProtocol_close_connection, 00566 HttpProtocol_on_error 00567 }; 00568 00569 static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) 00570 { 00571 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00572 00573 *ppv = NULL; 00574 if(IsEqualGUID(&IID_IUnknown, riid)) { 00575 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00576 *ppv = &This->IInternetProtocolEx_iface; 00577 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { 00578 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); 00579 *ppv = &This->IInternetProtocolEx_iface; 00580 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { 00581 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); 00582 *ppv = &This->IInternetProtocolEx_iface; 00583 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) { 00584 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv); 00585 *ppv = &This->IInternetProtocolEx_iface; 00586 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) { 00587 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv); 00588 *ppv = &This->IInternetPriority_iface; 00589 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) { 00590 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv); 00591 *ppv = &This->IWinInetHttpInfo_iface; 00592 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { 00593 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); 00594 *ppv = &This->IWinInetHttpInfo_iface; 00595 } 00596 00597 if(*ppv) { 00598 IInternetProtocol_AddRef(iface); 00599 return S_OK; 00600 } 00601 00602 WARN("not supported interface %s\n", debugstr_guid(riid)); 00603 return E_NOINTERFACE; 00604 } 00605 00606 static ULONG WINAPI HttpProtocol_AddRef(IInternetProtocolEx *iface) 00607 { 00608 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00609 LONG ref = InterlockedIncrement(&This->ref); 00610 TRACE("(%p) ref=%d\n", This, ref); 00611 return ref; 00612 } 00613 00614 static ULONG WINAPI HttpProtocol_Release(IInternetProtocolEx *iface) 00615 { 00616 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00617 LONG ref = InterlockedDecrement(&This->ref); 00618 00619 TRACE("(%p) ref=%d\n", This, ref); 00620 00621 if(!ref) { 00622 protocol_close_connection(&This->base); 00623 heap_free(This); 00624 00625 URLMON_UnlockModule(); 00626 } 00627 00628 return ref; 00629 } 00630 00631 static HRESULT WINAPI HttpProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl, 00632 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, 00633 DWORD grfPI, HANDLE_PTR dwReserved) 00634 { 00635 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00636 IUri *uri; 00637 HRESULT hres; 00638 00639 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, 00640 pOIBindInfo, grfPI, dwReserved); 00641 00642 hres = CreateUri(szUrl, 0, 0, &uri); 00643 if(FAILED(hres)) 00644 return hres; 00645 00646 hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink, 00647 pOIBindInfo, grfPI, (HANDLE*)dwReserved); 00648 00649 IUri_Release(uri); 00650 return hres; 00651 } 00652 00653 static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData) 00654 { 00655 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00656 00657 TRACE("(%p)->(%p)\n", This, pProtocolData); 00658 00659 return protocol_continue(&This->base, pProtocolData); 00660 } 00661 00662 static HRESULT WINAPI HttpProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason, 00663 DWORD dwOptions) 00664 { 00665 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00666 00667 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); 00668 00669 return protocol_abort(&This->base, hrReason); 00670 } 00671 00672 static HRESULT WINAPI HttpProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions) 00673 { 00674 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00675 00676 TRACE("(%p)->(%08x)\n", This, dwOptions); 00677 00678 protocol_close_connection(&This->base); 00679 return S_OK; 00680 } 00681 00682 static HRESULT WINAPI HttpProtocol_Suspend(IInternetProtocolEx *iface) 00683 { 00684 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00685 FIXME("(%p)\n", This); 00686 return E_NOTIMPL; 00687 } 00688 00689 static HRESULT WINAPI HttpProtocol_Resume(IInternetProtocolEx *iface) 00690 { 00691 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00692 FIXME("(%p)\n", This); 00693 return E_NOTIMPL; 00694 } 00695 00696 static HRESULT WINAPI HttpProtocol_Read(IInternetProtocolEx *iface, void *pv, 00697 ULONG cb, ULONG *pcbRead) 00698 { 00699 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00700 00701 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); 00702 00703 return protocol_read(&This->base, pv, cb, pcbRead); 00704 } 00705 00706 static HRESULT WINAPI HttpProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove, 00707 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 00708 { 00709 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00710 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); 00711 return E_NOTIMPL; 00712 } 00713 00714 static HRESULT WINAPI HttpProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions) 00715 { 00716 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00717 00718 TRACE("(%p)->(%08x)\n", This, dwOptions); 00719 00720 return protocol_lock_request(&This->base); 00721 } 00722 00723 static HRESULT WINAPI HttpProtocol_UnlockRequest(IInternetProtocolEx *iface) 00724 { 00725 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00726 00727 TRACE("(%p)\n", This); 00728 00729 return protocol_unlock_request(&This->base); 00730 } 00731 00732 static HRESULT WINAPI HttpProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri, 00733 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, 00734 DWORD grfPI, HANDLE *dwReserved) 00735 { 00736 HttpProtocol *This = impl_from_IInternetProtocolEx(iface); 00737 DWORD scheme = 0; 00738 HRESULT hres; 00739 00740 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, 00741 pOIBindInfo, grfPI, dwReserved); 00742 00743 hres = IUri_GetScheme(pUri, &scheme); 00744 if(FAILED(hres)) 00745 return hres; 00746 if(scheme != (This->https ? URL_SCHEME_HTTPS : URL_SCHEME_HTTP)) 00747 return MK_E_SYNTAX; 00748 00749 return protocol_start(&This->base, (IInternetProtocol*)&This->IInternetProtocolEx_iface, pUri, 00750 pOIProtSink, pOIBindInfo); 00751 } 00752 00753 static const IInternetProtocolExVtbl HttpProtocolVtbl = { 00754 HttpProtocol_QueryInterface, 00755 HttpProtocol_AddRef, 00756 HttpProtocol_Release, 00757 HttpProtocol_Start, 00758 HttpProtocol_Continue, 00759 HttpProtocol_Abort, 00760 HttpProtocol_Terminate, 00761 HttpProtocol_Suspend, 00762 HttpProtocol_Resume, 00763 HttpProtocol_Read, 00764 HttpProtocol_Seek, 00765 HttpProtocol_LockRequest, 00766 HttpProtocol_UnlockRequest, 00767 HttpProtocol_StartEx 00768 }; 00769 00770 static HRESULT WINAPI HttpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) 00771 { 00772 HttpProtocol *This = impl_from_IInternetPriority(iface); 00773 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); 00774 } 00775 00776 static ULONG WINAPI HttpPriority_AddRef(IInternetPriority *iface) 00777 { 00778 HttpProtocol *This = impl_from_IInternetPriority(iface); 00779 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); 00780 } 00781 00782 static ULONG WINAPI HttpPriority_Release(IInternetPriority *iface) 00783 { 00784 HttpProtocol *This = impl_from_IInternetPriority(iface); 00785 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); 00786 } 00787 00788 static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nPriority) 00789 { 00790 HttpProtocol *This = impl_from_IInternetPriority(iface); 00791 00792 TRACE("(%p)->(%d)\n", This, nPriority); 00793 00794 This->base.priority = nPriority; 00795 return S_OK; 00796 } 00797 00798 static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority) 00799 { 00800 HttpProtocol *This = impl_from_IInternetPriority(iface); 00801 00802 TRACE("(%p)->(%p)\n", This, pnPriority); 00803 00804 *pnPriority = This->base.priority; 00805 return S_OK; 00806 } 00807 00808 static const IInternetPriorityVtbl HttpPriorityVtbl = { 00809 HttpPriority_QueryInterface, 00810 HttpPriority_AddRef, 00811 HttpPriority_Release, 00812 HttpPriority_SetPriority, 00813 HttpPriority_GetPriority 00814 }; 00815 00816 static HRESULT WINAPI HttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv) 00817 { 00818 HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); 00819 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); 00820 } 00821 00822 static ULONG WINAPI HttpInfo_AddRef(IWinInetHttpInfo *iface) 00823 { 00824 HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); 00825 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); 00826 } 00827 00828 static ULONG WINAPI HttpInfo_Release(IWinInetHttpInfo *iface) 00829 { 00830 HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); 00831 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); 00832 } 00833 00834 static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption, 00835 void *pBuffer, DWORD *pcbBuffer) 00836 { 00837 HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); 00838 TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer); 00839 00840 if(!This->base.request) 00841 return E_FAIL; 00842 00843 if(!InternetQueryOptionW(This->base.request, dwOption, pBuffer, pcbBuffer)) 00844 return S_FALSE; 00845 return S_OK; 00846 } 00847 00848 static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, 00849 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) 00850 { 00851 HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); 00852 TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); 00853 00854 if(!This->base.request) 00855 return E_FAIL; 00856 00857 if(!HttpQueryInfoW(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags)) { 00858 if(pBuffer) 00859 memset(pBuffer, 0, *pcbBuffer); 00860 return S_OK; 00861 } 00862 return S_OK; 00863 } 00864 00865 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { 00866 HttpInfo_QueryInterface, 00867 HttpInfo_AddRef, 00868 HttpInfo_Release, 00869 HttpInfo_QueryOption, 00870 HttpInfo_QueryInfo 00871 }; 00872 00873 static HRESULT create_http_protocol(BOOL https, void **ppobj) 00874 { 00875 HttpProtocol *ret; 00876 00877 ret = heap_alloc_zero(sizeof(HttpProtocol)); 00878 if(!ret) 00879 return E_OUTOFMEMORY; 00880 00881 ret->base.vtbl = &AsyncProtocolVtbl; 00882 ret->IInternetProtocolEx_iface.lpVtbl = &HttpProtocolVtbl; 00883 ret->IInternetPriority_iface.lpVtbl = &HttpPriorityVtbl; 00884 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl; 00885 00886 ret->https = https; 00887 ret->ref = 1; 00888 00889 *ppobj = &ret->IInternetProtocolEx_iface; 00890 00891 URLMON_LockModule(); 00892 return S_OK; 00893 } 00894 00895 HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) 00896 { 00897 TRACE("(%p %p)\n", pUnkOuter, ppobj); 00898 00899 return create_http_protocol(FALSE, ppobj); 00900 } 00901 00902 HRESULT HttpSProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) 00903 { 00904 TRACE("(%p %p)\n", pUnkOuter, ppobj); 00905 00906 return create_http_protocol(TRUE, ppobj); 00907 } Generated on Sat May 26 2012 04:25:12 for ReactOS by
1.7.6.1
|