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

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

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