Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenutility.c
Go to the documentation of this file.
00001 /* 00002 * Wininet - Utility functions 00003 * 00004 * Copyright 1999 Corel Corporation 00005 * Copyright 2002 CodeWeavers Inc. 00006 * 00007 * Ulrich Czekalla 00008 * Aric Stewart 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 */ 00024 00025 #include "config.h" 00026 #include "wine/port.h" 00027 00028 #if defined(__MINGW32__) || defined (_MSC_VER) 00029 #include <ws2tcpip.h> 00030 #endif 00031 00032 #include <stdarg.h> 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include <time.h> 00036 00037 #include "windef.h" 00038 #include "winbase.h" 00039 #include "wininet.h" 00040 #include "winnls.h" 00041 00042 #include "wine/debug.h" 00043 #include "internet.h" 00044 00045 WINE_DEFAULT_DEBUG_CHANNEL(wininet); 00046 00047 #ifndef HAVE_GETADDRINFO 00048 00049 /* critical section to protect non-reentrant gethostbyname() */ 00050 static CRITICAL_SECTION cs_gethostbyname; 00051 static CRITICAL_SECTION_DEBUG critsect_debug = 00052 { 00053 0, 0, &cs_gethostbyname, 00054 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 00055 0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") } 00056 }; 00057 static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 }; 00058 00059 #endif 00060 00061 #define TIME_STRING_LEN 30 00062 00063 time_t ConvertTimeString(LPCWSTR asctime) 00064 { 00065 WCHAR tmpChar[TIME_STRING_LEN]; 00066 WCHAR *tmpChar2; 00067 struct tm t; 00068 int timelen = strlenW(asctime); 00069 00070 if(!timelen) 00071 return 0; 00072 00073 /* FIXME: the atoiWs below rely on that tmpChar is \0 padded */ 00074 memset( tmpChar, 0, sizeof(tmpChar) ); 00075 lstrcpynW(tmpChar, asctime, TIME_STRING_LEN); 00076 00077 /* Assert that the string is the expected length */ 00078 if (strlenW(asctime) >= TIME_STRING_LEN) FIXME("\n"); 00079 00080 /* Convert a time such as 'Mon, 15 Nov 1999 16:09:35 GMT' into a SYSTEMTIME structure 00081 * We assume the time is in this format 00082 * and divide it into easy to swallow chunks 00083 */ 00084 tmpChar[3]='\0'; 00085 tmpChar[7]='\0'; 00086 tmpChar[11]='\0'; 00087 tmpChar[16]='\0'; 00088 tmpChar[19]='\0'; 00089 tmpChar[22]='\0'; 00090 tmpChar[25]='\0'; 00091 00092 memset( &t, 0, sizeof(t) ); 00093 t.tm_year = atoiW(tmpChar+12) - 1900; 00094 t.tm_mday = atoiW(tmpChar+5); 00095 t.tm_hour = atoiW(tmpChar+17); 00096 t.tm_min = atoiW(tmpChar+20); 00097 t.tm_sec = atoiW(tmpChar+23); 00098 00099 /* and month */ 00100 tmpChar2 = tmpChar + 8; 00101 switch(tmpChar2[2]) 00102 { 00103 case 'n': 00104 if(tmpChar2[1]=='a') 00105 t.tm_mon = 0; 00106 else 00107 t.tm_mon = 5; 00108 break; 00109 case 'b': 00110 t.tm_mon = 1; 00111 break; 00112 case 'r': 00113 if(tmpChar2[1]=='a') 00114 t.tm_mon = 2; 00115 else 00116 t.tm_mon = 3; 00117 break; 00118 case 'y': 00119 t.tm_mon = 4; 00120 break; 00121 case 'l': 00122 t.tm_mon = 6; 00123 break; 00124 case 'g': 00125 t.tm_mon = 7; 00126 break; 00127 case 'p': 00128 t.tm_mon = 8; 00129 break; 00130 case 't': 00131 t.tm_mon = 9; 00132 break; 00133 case 'v': 00134 t.tm_mon = 10; 00135 break; 00136 case 'c': 00137 t.tm_mon = 11; 00138 break; 00139 default: 00140 FIXME("\n"); 00141 } 00142 00143 return mktime(&t); 00144 } 00145 00146 00147 BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, 00148 struct sockaddr *psa, socklen_t *sa_len) 00149 { 00150 WCHAR *found; 00151 char *name; 00152 int len, sz; 00153 #ifdef HAVE_GETADDRINFO 00154 struct addrinfo *res, hints; 00155 int ret; 00156 #else 00157 struct hostent *phe; 00158 struct sockaddr_in *sin = (struct sockaddr_in *)psa; 00159 #endif 00160 00161 TRACE("%s\n", debugstr_w(lpszServerName)); 00162 00163 /* Validate server name first 00164 * Check if there is sth. like 00165 * pinger.macromedia.com:80 00166 * if yes, eliminate the :80.... 00167 */ 00168 found = strchrW(lpszServerName, ':'); 00169 if (found) 00170 len = found - lpszServerName; 00171 else 00172 len = strlenW(lpszServerName); 00173 00174 sz = WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, NULL, 0, NULL, NULL ); 00175 if (!(name = heap_alloc(sz + 1))) return FALSE; 00176 WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, name, sz, NULL, NULL ); 00177 name[sz] = 0; 00178 00179 #ifdef HAVE_GETADDRINFO 00180 memset( &hints, 0, sizeof(struct addrinfo) ); 00181 /* Prefer IPv4 to IPv6 addresses, since some servers do not listen on 00182 * their IPv6 addresses even though they have IPv6 addresses in the DNS. 00183 */ 00184 hints.ai_family = AF_INET; 00185 00186 ret = getaddrinfo( name, NULL, &hints, &res ); 00187 HeapFree( GetProcessHeap(), 0, name ); 00188 if (ret != 0) 00189 { 00190 TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(lpszServerName), gai_strerror(ret)); 00191 hints.ai_family = AF_INET6; 00192 ret = getaddrinfo( name, NULL, &hints, &res ); 00193 if (ret != 0) 00194 { 00195 TRACE("failed to get address of %s (%s)\n", debugstr_w(lpszServerName), gai_strerror(ret)); 00196 return FALSE; 00197 } 00198 } 00199 if (*sa_len < res->ai_addrlen) 00200 { 00201 WARN("address too small\n"); 00202 freeaddrinfo( res ); 00203 return FALSE; 00204 } 00205 *sa_len = res->ai_addrlen; 00206 memcpy( psa, res->ai_addr, res->ai_addrlen ); 00207 /* Copy port */ 00208 switch (res->ai_family) 00209 { 00210 case AF_INET: 00211 ((struct sockaddr_in *)psa)->sin_port = htons(nServerPort); 00212 break; 00213 case AF_INET6: 00214 ((struct sockaddr_in6 *)psa)->sin6_port = htons(nServerPort); 00215 break; 00216 } 00217 00218 freeaddrinfo( res ); 00219 #else 00220 EnterCriticalSection( &cs_gethostbyname ); 00221 phe = gethostbyname(name); 00222 HeapFree( GetProcessHeap(), 0, name ); 00223 00224 if (NULL == phe) 00225 { 00226 TRACE("failed to get address of %s (%d)\n", debugstr_w(lpszServerName), h_errno); 00227 LeaveCriticalSection( &cs_gethostbyname ); 00228 return FALSE; 00229 } 00230 if (*sa_len < sizeof(struct sockaddr_in)) 00231 { 00232 WARN("address too small\n"); 00233 LeaveCriticalSection( &cs_gethostbyname ); 00234 return FALSE; 00235 } 00236 *sa_len = sizeof(struct sockaddr_in); 00237 memset(sin,0,sizeof(struct sockaddr_in)); 00238 memcpy((char *)&sin->sin_addr, phe->h_addr, phe->h_length); 00239 sin->sin_family = phe->h_addrtype; 00240 sin->sin_port = htons(nServerPort); 00241 00242 LeaveCriticalSection( &cs_gethostbyname ); 00243 #endif 00244 return TRUE; 00245 } 00246 00247 /* 00248 * Helper function for sending async Callbacks 00249 */ 00250 00251 static const char *get_callback_name(DWORD dwInternetStatus) { 00252 static const wininet_flag_info internet_status[] = { 00253 #define FE(x) { x, #x } 00254 FE(INTERNET_STATUS_RESOLVING_NAME), 00255 FE(INTERNET_STATUS_NAME_RESOLVED), 00256 FE(INTERNET_STATUS_CONNECTING_TO_SERVER), 00257 FE(INTERNET_STATUS_CONNECTED_TO_SERVER), 00258 FE(INTERNET_STATUS_SENDING_REQUEST), 00259 FE(INTERNET_STATUS_REQUEST_SENT), 00260 FE(INTERNET_STATUS_RECEIVING_RESPONSE), 00261 FE(INTERNET_STATUS_RESPONSE_RECEIVED), 00262 FE(INTERNET_STATUS_CTL_RESPONSE_RECEIVED), 00263 FE(INTERNET_STATUS_PREFETCH), 00264 FE(INTERNET_STATUS_CLOSING_CONNECTION), 00265 FE(INTERNET_STATUS_CONNECTION_CLOSED), 00266 FE(INTERNET_STATUS_HANDLE_CREATED), 00267 FE(INTERNET_STATUS_HANDLE_CLOSING), 00268 FE(INTERNET_STATUS_REQUEST_COMPLETE), 00269 FE(INTERNET_STATUS_REDIRECT), 00270 FE(INTERNET_STATUS_INTERMEDIATE_RESPONSE), 00271 FE(INTERNET_STATUS_USER_INPUT_REQUIRED), 00272 FE(INTERNET_STATUS_STATE_CHANGE), 00273 FE(INTERNET_STATUS_COOKIE_SENT), 00274 FE(INTERNET_STATUS_COOKIE_RECEIVED), 00275 FE(INTERNET_STATUS_PRIVACY_IMPACTED), 00276 FE(INTERNET_STATUS_P3P_HEADER), 00277 FE(INTERNET_STATUS_P3P_POLICYREF), 00278 FE(INTERNET_STATUS_COOKIE_HISTORY) 00279 #undef FE 00280 }; 00281 DWORD i; 00282 00283 for (i = 0; i < (sizeof(internet_status) / sizeof(internet_status[0])); i++) { 00284 if (internet_status[i].val == dwInternetStatus) return internet_status[i].name; 00285 } 00286 return "Unknown"; 00287 } 00288 00289 VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext, 00290 DWORD dwInternetStatus, LPVOID lpvStatusInfo, 00291 DWORD dwStatusInfoLength) 00292 { 00293 LPVOID lpvNewInfo = NULL; 00294 00295 if( !hdr->lpfnStatusCB ) 00296 return; 00297 00298 /* the IE5 version of wininet does not 00299 send callbacks if dwContext is zero */ 00300 if( !dwContext ) 00301 return; 00302 00303 lpvNewInfo = lpvStatusInfo; 00304 if(hdr->dwInternalFlags & INET_CALLBACKW) { 00305 switch(dwInternetStatus) { 00306 case INTERNET_STATUS_NAME_RESOLVED: 00307 case INTERNET_STATUS_CONNECTING_TO_SERVER: 00308 case INTERNET_STATUS_CONNECTED_TO_SERVER: 00309 lpvNewInfo = heap_strdupAtoW(lpvStatusInfo); 00310 dwStatusInfoLength *= sizeof(WCHAR); 00311 break; 00312 case INTERNET_STATUS_RESOLVING_NAME: 00313 case INTERNET_STATUS_REDIRECT: 00314 lpvNewInfo = heap_strdupW(lpvStatusInfo); 00315 break; 00316 } 00317 }else { 00318 switch(dwInternetStatus) 00319 { 00320 case INTERNET_STATUS_NAME_RESOLVED: 00321 case INTERNET_STATUS_CONNECTING_TO_SERVER: 00322 case INTERNET_STATUS_CONNECTED_TO_SERVER: 00323 lpvNewInfo = heap_alloc(strlen(lpvStatusInfo) + 1); 00324 if (lpvNewInfo) strcpy(lpvNewInfo, lpvStatusInfo); 00325 break; 00326 case INTERNET_STATUS_RESOLVING_NAME: 00327 case INTERNET_STATUS_REDIRECT: 00328 lpvNewInfo = heap_strdupWtoA(lpvStatusInfo); 00329 dwStatusInfoLength /= sizeof(WCHAR); 00330 break; 00331 } 00332 } 00333 00334 TRACE(" callback(%p) (%p (%p), %08lx, %d (%s), %p, %d)\n", 00335 hdr->lpfnStatusCB, hdr->hInternet, hdr, dwContext, dwInternetStatus, get_callback_name(dwInternetStatus), 00336 lpvNewInfo, dwStatusInfoLength); 00337 00338 hdr->lpfnStatusCB(hdr->hInternet, dwContext, dwInternetStatus, 00339 lpvNewInfo, dwStatusInfoLength); 00340 00341 TRACE(" end callback().\n"); 00342 00343 if(lpvNewInfo != lpvStatusInfo) 00344 HeapFree(GetProcessHeap(), 0, lpvNewInfo); 00345 } 00346 00347 static void SendAsyncCallbackProc(WORKREQUEST *workRequest) 00348 { 00349 struct WORKREQ_SENDCALLBACK const *req = &workRequest->u.SendCallback; 00350 00351 TRACE("%p\n", workRequest->hdr); 00352 00353 INTERNET_SendCallback(workRequest->hdr, 00354 req->dwContext, req->dwInternetStatus, req->lpvStatusInfo, 00355 req->dwStatusInfoLength); 00356 00357 /* And frees the copy of the status info */ 00358 HeapFree(GetProcessHeap(), 0, req->lpvStatusInfo); 00359 } 00360 00361 void SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext, 00362 DWORD dwInternetStatus, LPVOID lpvStatusInfo, 00363 DWORD dwStatusInfoLength) 00364 { 00365 TRACE("(%p, %08lx, %d (%s), %p, %d): %sasync call with callback %p\n", 00366 hdr, dwContext, dwInternetStatus, get_callback_name(dwInternetStatus), 00367 lpvStatusInfo, dwStatusInfoLength, 00368 hdr->dwFlags & INTERNET_FLAG_ASYNC ? "" : "non ", 00369 hdr->lpfnStatusCB); 00370 00371 if (!(hdr->lpfnStatusCB)) 00372 return; 00373 00374 if (hdr->dwFlags & INTERNET_FLAG_ASYNC) 00375 { 00376 WORKREQUEST workRequest; 00377 struct WORKREQ_SENDCALLBACK *req; 00378 void *lpvStatusInfo_copy = lpvStatusInfo; 00379 00380 if (lpvStatusInfo) 00381 { 00382 lpvStatusInfo_copy = heap_alloc(dwStatusInfoLength); 00383 memcpy(lpvStatusInfo_copy, lpvStatusInfo, dwStatusInfoLength); 00384 } 00385 00386 workRequest.asyncproc = SendAsyncCallbackProc; 00387 workRequest.hdr = WININET_AddRef( hdr ); 00388 req = &workRequest.u.SendCallback; 00389 req->dwContext = dwContext; 00390 req->dwInternetStatus = dwInternetStatus; 00391 req->lpvStatusInfo = lpvStatusInfo_copy; 00392 req->dwStatusInfoLength = dwStatusInfoLength; 00393 00394 INTERNET_AsyncCall(&workRequest); 00395 } 00396 else 00397 INTERNET_SendCallback(hdr, dwContext, dwInternetStatus, 00398 lpvStatusInfo, dwStatusInfoLength); 00399 } Generated on Sun May 27 2012 04:17:15 for ReactOS by
1.7.6.1
|