home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activedocument / range / cache.cpp next >
C/C++ Source or Header  |  1996-05-09  |  6KB  |  207 lines

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