CACHE.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:6k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // ===========================================================================
  2. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. // PARTICULAR PURPOSE.
  6. //
  7. // Copyright 1996 Microsoft Corporation.  All Rights Reserved.
  8. // ===========================================================================
  9. #include <windows.h>
  10. #include <wininet.h>
  11. #include "range.h"
  12. //==============================================================================
  13. BOOL QueryHeaders
  14. (
  15.      HANDLE                hRequest,
  16.      PHTTP_REQUESTCB_PARAM pCBParam,
  17.      SYSTEMTIME*           pstLastModified
  18. )
  19. {
  20.     DWORD cbBuf;
  21.     BOOL fRet;
  22.     pCBParam->CallbackType     = REQUESTCB_STARTED;
  23.     pCBParam->fdwRequestFlags  = HTTP_REQUEST_FROM_CACHE;
  24.         
  25.     // Get if the server supports ranges from the response headers.
  26.     static char szBytes[] ="bytes";
  27.     char szBuf[sizeof(szBytes)];
  28.     cbBuf = sizeof(szBytes);
  29.     fRet = HttpQueryInfo
  30.         (hRequest, HTTP_QUERY_ACCEPT_RANGES, szBuf, &cbBuf, 0);
  31.     if (fRet && !lstrcmpi (szBuf, szBytes))
  32.         pCBParam->fdwRequestFlags |= HTTP_REQUEST_ACCEPT_RANGES;
  33.     // Get the response code.
  34.     cbBuf = sizeof(pCBParam->dwResponseCode);
  35.     fRet = HttpQueryInfo
  36.     (
  37.         hRequest,
  38.         HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  39.         &pCBParam->dwResponseCode,
  40.         &cbBuf,
  41.         NULL
  42.     );
  43.     if (!fRet)
  44.        pCBParam->dwResponseCode = 0;
  45.   
  46.     // Get the last modified time from the response headers.
  47.     cbBuf = sizeof(*pstLastModified);
  48.     fRet = HttpQueryInfo
  49.     (
  50.         hRequest,
  51.         HTTP_QUERY_FLAG_SYSTEMTIME | HTTP_QUERY_LAST_MODIFIED,
  52.         pstLastModified,
  53.         &cbBuf, 
  54.         NULL
  55.     );
  56.     pCBParam->pstLastModified = fRet? pstLastModified : NULL;
  57.     // Get the content length from the cache file size.
  58.     pCBParam->dwContentLength =
  59.         InternetSetFilePointer (hRequest, NULL, 0, FILE_END, 0);
  60.     return TRUE;
  61. }
  62. //==============================================================================
  63. BOOL HttpReadFromCache (PHTTP_REQUEST_PARAM pParam)
  64. {
  65.     // Locals that must be initialized before goto done.
  66.     BOOL fSuccess = FALSE;
  67.     HANDLE hInternet = NULL;
  68.     HANDLE hConnect  = NULL;
  69.     HANDLE hRequest  = NULL;
  70.     PVOID pRead = NULL;
  71.     HRESULT hrRequest = S_OK;
  72.     
  73.     // Initialize wininet
  74.     hInternet = InternetOpen
  75.         ("RR", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_OFFLINE);
  76.     if (!hInternet)
  77.         goto done;
  78.     hRequest = InternetOpenUrl
  79.         (hInternet, pParam->pszUrl, NULL, 0, INTERNET_FLAG_OFFLINE, 0);
  80.     if (!hRequest)
  81.         goto done;
  82.     // Initialize callback parameters.
  83.     HTTP_REQUESTCB_PARAM CBParam;
  84.     CBParam.cbStruct         = sizeof(CBParam);
  85.     CBParam.dwRequestCtx     = pParam->dwRequestCtx;
  86.     // Allocate read buffer
  87.     DWORD cbRead;
  88.     cbRead = 4096;
  89.     pRead  = LocalAlloc (LMEM_FIXED, cbRead);
  90.     if (!pRead)
  91.     {
  92.         SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  93.         goto done;
  94.     }
  95.     SYSTEMTIME st;
  96.     if (!QueryHeaders (hRequest, &CBParam, &st))
  97.         goto done;
  98.     fSuccess = TRUE;
  99.     
  100.     // Notify the client that request is started.
  101.     if (!(*pParam->pfnRequestCB) (&CBParam))
  102.         goto notify;
  103.     // Set up ranges to read.    
  104.     HTTP_REQUEST_RANGE EntireRange;
  105.     PHTTP_REQUEST_RANGE pRanges;
  106.     DWORD cRanges;
  107.     if (pParam->cRanges)
  108.     {
  109.         pRanges = pParam->pRanges;
  110.         cRanges = pParam->cRanges;
  111.     }
  112.     else
  113.     {
  114.         EntireRange.dwOffset = 0;
  115.         EntireRange.dwSize = CBParam.dwContentLength;   
  116.         pRanges = &EntireRange;
  117.         cRanges = 1;
  118.     }
  119.     // Loop over the ranges, reading into the buffer.
  120.     CBParam.CallbackType = REQUESTCB_DATA;
  121.     CBParam.lpDataBuffer = pRead;
  122.     while (cRanges--)
  123.     {
  124.         CBParam.dwDataOffset = pRanges->dwOffset;
  125.         DWORD cbRange        = pRanges->dwSize;
  126.         if (!cbRange)
  127.             cbRange = InternetSetFilePointer (hRequest, 0, NULL, FILE_END, 0)
  128.               - pRanges->dwOffset;
  129.               
  130.         while (cbRange) // Loop until we have all the data for the range.
  131.         {
  132.             InternetSetFilePointer
  133.                 (hRequest, CBParam.dwDataOffset, NULL, FILE_BEGIN, 0);
  134.             
  135.             if (!InternetReadFile
  136.                 (hRequest, pRead, min(cbRead, cbRange), &CBParam.cbDataLength))
  137.             {
  138.                 hrRequest = E_FAIL;
  139.                 goto notify;
  140.             }
  141.             // Check for EOF
  142.             if (!CBParam.cbDataLength)
  143.                 break;
  144.             // Call the client with data.
  145.             if (!(*pParam->pfnRequestCB) (&CBParam))
  146.                 goto notify;
  147.             CBParam.dwDataOffset += CBParam.cbDataLength;
  148.             cbRange              -= CBParam.cbDataLength;
  149.         }
  150.         // Advance to next range.
  151.         pRanges++;
  152.         
  153.     } // end while (cRanges--)
  154. notify:
  155.     // Notify the client we are done.
  156.     CBParam.CallbackType = REQUESTCB_DONE;
  157.     CBParam.hrRequest = hrRequest;
  158.     (*pParam->pfnRequestCB) (&CBParam);
  159.     
  160. done:
  161.     if (pRead)
  162.         LocalFree ((HLOCAL) pRead);
  163.     if (hRequest)
  164.         InternetCloseHandle (hRequest);
  165.     if (hConnect)
  166.         InternetCloseHandle (hConnect);
  167.     if (hInternet)
  168.         InternetCloseHandle (hInternet);
  169.     return fSuccess;
  170. }
  171. //==============================================================================
  172. BOOL HttpReadRequest (PHTTP_REQUEST_PARAM pParam)
  173. {
  174.     if (pParam->cbStruct != sizeof(HTTP_REQUEST_PARAM))
  175.     {
  176.         SetLastError (ERROR_INVALID_PARAMETER);
  177.         return FALSE;
  178.     }
  179.     if (HttpReadFromCache (pParam))
  180.         return TRUE;
  181.     return HttpReadFromServer (pParam);
  182. }