From e0e314780a9d8efa147492b78820824ed091c17f Mon Sep 17 00:00:00 2001 From: Lionel Ulmer Date: Mon, 9 Feb 2004 21:45:38 +0000 Subject: [PATCH] Implemented proper asynchronous InternetOpenUrl handling. --- dlls/wininet/http.c | 49 +++++------- dlls/wininet/internet.c | 198 +++++++++++++++++++++++++++++++++--------------- dlls/wininet/internet.h | 19 +++++ 3 files changed, 176 insertions(+), 90 deletions(-) diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index c554d7bbf63..700a96560d1 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -89,13 +89,6 @@ BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr); INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr, LPCSTR lpszField); BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQA lpwhr, INT index); -inline static LPSTR HTTP_strdup( LPCSTR str ) -{ - LPSTR ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 ); - if (ret) strcpy( ret, str ); - return ret; -} - /*********************************************************************** * HttpAddRequestHeadersA (WININET.@) * @@ -131,7 +124,7 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest, return TRUE; TRACE("copying header: %s\n", lpszHeader); - buffer = HTTP_strdup(lpszHeader); + buffer = WININET_strdup(lpszHeader); lpszStart = buffer; do @@ -252,14 +245,14 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession, workRequest.asyncall = HTTPOPENREQUESTA; workRequest.handle = hHttpSession; req = &workRequest.u.HttpOpenRequestA; - req->lpszVerb = HTTP_strdup(lpszVerb); - req->lpszObjectName = HTTP_strdup(lpszObjectName); + req->lpszVerb = WININET_strdup(lpszVerb); + req->lpszObjectName = WININET_strdup(lpszObjectName); if (lpszVersion) - req->lpszVersion = HTTP_strdup(lpszVersion); + req->lpszVersion = WININET_strdup(lpszVersion); else req->lpszVersion = 0; if (lpszReferrer) - req->lpszReferrer = HTTP_strdup(lpszReferrer); + req->lpszReferrer = WININET_strdup(lpszReferrer); else req->lpszReferrer = 0; req->lpszAcceptTypes = lpszAcceptTypes; @@ -535,7 +528,7 @@ static BOOL HTTP_DealWithProxy( LPWININETAPPINFOA hIC, HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); lpwhr->lpszPath = url; /* FIXME: Do I have to free lpwhs->lpszServerName here ? */ - lpwhs->lpszServerName = HTTP_strdup(UrlComponents.lpszHostName); + lpwhs->lpszServerName = WININET_strdup(UrlComponents.lpszHostName); lpwhs->nServerPort = UrlComponents.nPort; return TRUE; @@ -622,9 +615,9 @@ HINTERNET WINAPI HTTP_HttpOpenRequestA(HINTERNET hHttpSession, } if (NULL == lpszVerb) - lpwhr->lpszVerb = HTTP_strdup("GET"); + lpwhr->lpszVerb = WININET_strdup("GET"); else if (strlen(lpszVerb)) - lpwhr->lpszVerb = HTTP_strdup(lpszVerb); + lpwhr->lpszVerb = WININET_strdup(lpszVerb); if (NULL != lpszReferrer && strlen(lpszReferrer)) { @@ -638,9 +631,9 @@ HINTERNET WINAPI HTTP_HttpOpenRequestA(HINTERNET hHttpSession, InternetCrackUrlA(lpszReferrer, 0, 0, &UrlComponents); if (strlen(UrlComponents.lpszHostName)) - lpwhr->lpszHostName = HTTP_strdup(UrlComponents.lpszHostName); + lpwhr->lpszHostName = WININET_strdup(UrlComponents.lpszHostName); } else { - lpwhr->lpszHostName = HTTP_strdup(lpwhs->lpszServerName); + lpwhr->lpszHostName = WININET_strdup(lpwhs->lpszServerName); } if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0) HTTP_DealWithProxy( hIC, lpwhs, lpwhr ); @@ -996,7 +989,7 @@ BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders, workRequest.handle = hHttpRequest; req = &workRequest.u.HttpSendRequestA; if (lpszHeaders) - req->lpszHeader = HTTP_strdup(lpszHeaders); + req->lpszHeader = WININET_strdup(lpszHeaders); else req->lpszHeader = 0; req->dwHeaderLength = dwHeaderLength; @@ -1109,15 +1102,15 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQA lpwhr, LPCSTR lpszUrl, LPCSTR if (NULL != lpwhs->lpszServerName) HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); - lpwhs->lpszServerName = HTTP_strdup(hostName); + lpwhs->lpszServerName = WININET_strdup(hostName); if (NULL != lpwhs->lpszUserName) HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName); - lpwhs->lpszUserName = HTTP_strdup(userName); + lpwhs->lpszUserName = WININET_strdup(userName); lpwhs->nServerPort = urlComponents.nPort; if (NULL != lpwhr->lpszHostName) HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName); - lpwhr->lpszHostName=HTTP_strdup(hostName); + lpwhr->lpszHostName=WININET_strdup(hostName); SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext, INTERNET_STATUS_RESOLVING_NAME, @@ -1238,7 +1231,7 @@ BOOL WINAPI HTTP_HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders, /* If we don't have a path we set it to root */ if (NULL == lpwhr->lpszPath) - lpwhr->lpszPath = HTTP_strdup("/"); + lpwhr->lpszPath = WININET_strdup("/"); if(strncmp(lpwhr->lpszPath, "http://", sizeof("http://") -1) != 0 && lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */ @@ -1270,7 +1263,7 @@ BOOL WINAPI HTTP_HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders, */ if ((len > 2) && (memcmp(lpszHeaders + (len - 2), "\r\n", 2) == 0)) { - lpszHeaders_r_n = HTTP_strdup(lpszHeaders); + lpszHeaders_r_n = WININET_strdup(lpszHeaders); } else { @@ -1617,9 +1610,9 @@ HINTERNET HTTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName, FIXME("Proxy bypass is ignored.\n"); } if (NULL != lpszServerName) - lpwhs->lpszServerName = HTTP_strdup(lpszServerName); + lpwhs->lpszServerName = WININET_strdup(lpszServerName); if (NULL != lpszUserName) - lpwhs->lpszUserName = HTTP_strdup(lpszUserName); + lpwhs->lpszUserName = WININET_strdup(lpszUserName); lpwhs->nServerPort = nServerPort; if (hIC->lpfnStatusCB) @@ -1976,7 +1969,7 @@ BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWO if (!lpwhr->StdHeaders[index].lpszField) { - lphttpHdr->lpszField = HTTP_strdup(field); + lphttpHdr->lpszField = WININET_strdup(field); if (dwModifier & HTTP_ADDHDR_FLAG_REQ) lphttpHdr->wFlags |= HDR_ISREQUEST; @@ -2237,8 +2230,8 @@ BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr) if (NULL != lph) { lpwhr->pCustHeaders = lph; - lpwhr->pCustHeaders[count-1].lpszField = HTTP_strdup(lpHdr->lpszField); - lpwhr->pCustHeaders[count-1].lpszValue = HTTP_strdup(lpHdr->lpszValue); + lpwhr->pCustHeaders[count-1].lpszField = WININET_strdup(lpHdr->lpszField); + lpwhr->pCustHeaders[count-1].lpszValue = WININET_strdup(lpHdr->lpszValue); lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags; lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount; lpwhr->nCustHeaders++; diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index ba62429a44b..9efd1d226ef 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -82,6 +82,8 @@ typedef struct } WITHREADERROR, *LPWITHREADERROR; BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData); +HINTERNET WINAPI INTERNET_InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, + LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext); VOID INTERNET_ExecuteWork(); DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES; @@ -1996,81 +1998,142 @@ BOOL WINAPI InternetCheckConnectionW(LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRes /********************************************************** - * InternetOpenUrlA (WININET.@) + * INTERNET_InternetOpenUrlA (internal) * * Opens an URL * * RETURNS * handle of connection or NULL on failure */ -HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, +HINTERNET WINAPI INTERNET_InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext) { - URL_COMPONENTSA urlComponents; - char protocol[32], hostName[MAXHOSTNAME], userName[1024]; - char password[1024], path[2048], extra[1024]; - HINTERNET client = NULL, client1 = NULL; - - TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders), - dwHeadersLength, dwFlags, dwContext); - - urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); - urlComponents.lpszScheme = protocol; - urlComponents.dwSchemeLength = 32; - urlComponents.lpszHostName = hostName; - urlComponents.dwHostNameLength = MAXHOSTNAME; - urlComponents.lpszUserName = userName; - urlComponents.dwUserNameLength = 1024; - urlComponents.lpszPassword = password; - urlComponents.dwPasswordLength = 1024; - urlComponents.lpszUrlPath = path; - urlComponents.dwUrlPathLength = 2048; - urlComponents.lpszExtraInfo = extra; - urlComponents.dwExtraInfoLength = 1024; - if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents)) - return NULL; - switch(urlComponents.nScheme) { - case INTERNET_SCHEME_FTP: - if(urlComponents.nPort == 0) - urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT; - client = InternetConnectA(hInternet, hostName, urlComponents.nPort, - userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext); - return FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext); - case INTERNET_SCHEME_HTTP: - case INTERNET_SCHEME_HTTPS: - { - LPCSTR accept[2] = { "*/*", NULL }; - if(urlComponents.nPort == 0) { - if(urlComponents.nScheme == INTERNET_SCHEME_HTTP) - urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - else - urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; - } - client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName, - password, INTERNET_SERVICE_HTTP, dwFlags, dwContext); - if(client == NULL) - return NULL; - client1 = HttpOpenRequestA(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext); - if(client1 == NULL) { - InternetCloseHandle(client); - return NULL; + URL_COMPONENTSA urlComponents; + char protocol[32], hostName[MAXHOSTNAME], userName[1024]; + char password[1024], path[2048], extra[1024]; + HINTERNET client = NULL, client1 = NULL; + + TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders), + dwHeadersLength, dwFlags, dwContext); + + urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); + urlComponents.lpszScheme = protocol; + urlComponents.dwSchemeLength = 32; + urlComponents.lpszHostName = hostName; + urlComponents.dwHostNameLength = MAXHOSTNAME; + urlComponents.lpszUserName = userName; + urlComponents.dwUserNameLength = 1024; + urlComponents.lpszPassword = password; + urlComponents.dwPasswordLength = 1024; + urlComponents.lpszUrlPath = path; + urlComponents.dwUrlPathLength = 2048; + urlComponents.lpszExtraInfo = extra; + urlComponents.dwExtraInfoLength = 1024; + if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents)) + return NULL; + switch(urlComponents.nScheme) { + case INTERNET_SCHEME_FTP: + if(urlComponents.nPort == 0) + urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT; + client = InternetConnectA(hInternet, hostName, urlComponents.nPort, + userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext); + client1 = FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext); + break; + + case INTERNET_SCHEME_HTTP: + case INTERNET_SCHEME_HTTPS: { + LPCSTR accept[2] = { "*/*", NULL }; + if(urlComponents.nPort == 0) { + if(urlComponents.nScheme == INTERNET_SCHEME_HTTP) + urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; + else + urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; + } + client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName, + password, INTERNET_SERVICE_HTTP, dwFlags, dwContext); + if(client == NULL) + break; + client1 = HttpOpenRequestA(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext); + if(client1 == NULL) { + InternetCloseHandle(client); + break; + } + HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD); + if (!HTTP_HttpSendRequestA(client1, NULL, 0, NULL, 0)) { + InternetCloseHandle(client1); + InternetCloseHandle(client); + client1 = NULL; + break; + } } - HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD); - if((!HttpSendRequestA(client1, NULL, 0, NULL, 0)) && (GetLastError() != ERROR_IO_PENDING)) { - InternetCloseHandle(client1); - InternetCloseHandle(client); - return NULL; + case INTERNET_SCHEME_GOPHER: + /* gopher doesn't seem to be implemented in wine, but it's supposed + * to be supported by InternetOpenUrlA. */ + default: + break; } + + TRACE(" %p <--\n", client1); + return client1; - } - case INTERNET_SCHEME_GOPHER: - /* gopher doesn't seem to be implemented in wine, but it's supposed - * to be supported by InternetOpenUrlA. */ - default: - return NULL; - } } +/********************************************************** + * InternetOpenUrlA (WININET.@) + * + * Opens an URL + * + * RETURNS + * handle of connection or NULL on failure + */ +HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, + LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext) +{ + HINTERNET ret = NULL; + LPWININETAPPINFOA hIC = NULL; + + TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders), + dwHeadersLength, dwFlags, dwContext); + + hIC = (LPWININETAPPINFOA) WININET_GetObject( hInternet ); + if (NULL == hIC || hIC->hdr.htype != WH_HINIT) { + INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); + goto lend; + } + + if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { + WORKREQUEST workRequest; + struct WORKREQ_INTERNETOPENURLA *req; + + workRequest.asyncall = INTERNETOPENURLA; + workRequest.handle = hInternet; + req = &workRequest.u.InternetOpenUrlA; + if (lpszUrl) + req->lpszUrl = WININET_strdup(lpszUrl); + else + req->lpszUrl = 0; + if (lpszHeaders) + req->lpszHeaders = WININET_strdup(lpszHeaders); + else + req->lpszHeaders = 0; + req->dwHeadersLength = dwHeadersLength; + req->dwFlags = dwFlags; + req->dwContext = dwContext; + + INTERNET_AsyncCall(&workRequest); + /* + * This is from windows. + */ + SetLastError(ERROR_IO_PENDING); + } else { + ret = INTERNET_InternetOpenUrlA(hInternet, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext); + } + + lend: + TRACE(" %p <--\n", ret); + + return ret; +} /********************************************************** * InternetOpenUrlW (WININET.@) @@ -2470,6 +2533,17 @@ VOID INTERNET_ExecuteWork() req->dwStatusInfoLength); } break; + + case INTERNETOPENURLA: + { + struct WORKREQ_INTERNETOPENURLA *req = &workRequest.u.InternetOpenUrlA; + + INTERNET_InternetOpenUrlA(workRequest.handle, req->lpszUrl, + req->lpszHeaders, req->dwHeadersLength, req->dwFlags, req->dwContext); + HeapFree(GetProcessHeap(), 0, req->lpszUrl); + HeapFree(GetProcessHeap(), 0, req->lpszHeaders); + } + break; } } diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index e3fcd4144d8..c66c9b3d56a 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -54,6 +54,13 @@ typedef struct #endif } WININET_NETCONNECTION; +inline static LPSTR WININET_strdup( LPCSTR str ) +{ + LPSTR ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 ); + if (ret) strcpy( ret, str ); + return ret; +} + typedef enum { WH_HINIT = INTERNET_HANDLE_TYPE_INTERNET, @@ -181,6 +188,7 @@ typedef enum HTTPSENDREQUESTA, HTTPOPENREQUESTA, SENDCALLBACK, + INTERNETOPENURLA, } ASYNC_FUNC; struct WORKREQ_FTPPUTFILEA @@ -282,6 +290,16 @@ struct WORKREQ_SENDCALLBACK DWORD dwStatusInfoLength; }; +struct WORKREQ_INTERNETOPENURLA +{ + HINTERNET hInternet; + LPSTR lpszUrl; + LPSTR lpszHeaders; + DWORD dwHeadersLength; + DWORD dwFlags; + DWORD dwContext; +}; + typedef struct WORKREQ { ASYNC_FUNC asyncall; @@ -302,6 +320,7 @@ typedef struct WORKREQ struct WORKREQ_HTTPOPENREQUESTA HttpOpenRequestA; struct WORKREQ_HTTPSENDREQUESTA HttpSendRequestA; struct WORKREQ_SENDCALLBACK SendCallback; + struct WORKREQ_INTERNETOPENURLA InternetOpenUrlA; } u; struct WORKREQ *next; -- 2.11.4.GIT