ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

http.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.