home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / inet.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  73KB  |  2,880 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <afxtempl.h>
  13. #include <afxinet.h>
  14.  
  15. #pragma warning(disable: 4706) // assignment within conditional
  16.  
  17. #ifdef AFX_INET_SEG
  18. #pragma code_seg(AFX_INET_SEG)
  19. #endif
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. #define new DEBUG_NEW
  27.  
  28. #ifdef _AFXDLL
  29. #pragma comment(lib, "wininet.lib")
  30. #endif
  31.  
  32. /////////////////////////////////////////////////////////////////////////////
  33. // non-localized useful strings
  34.  
  35. typedef struct tagServiceTable {
  36.     DWORD dwService;
  37.     LPCTSTR pstrIdentifier;
  38. } SvcTable;
  39.  
  40. AFX_STATIC_DATA const TCHAR _afxURLftp[] = _T("ftp://");
  41. AFX_STATIC_DATA const TCHAR _afxURLgopher[] = _T("gopher://");
  42. AFX_STATIC_DATA const TCHAR _afxURLhttp[] = _T("http://");
  43.  
  44. const LPCTSTR CHttpConnection::szHtmlVerbs[] = {
  45.     _T("POST"),
  46.     _T("GET"),
  47.     _T("HEAD"),
  48.     _T("PUT"),
  49.     _T("LINK"),
  50.     _T("DELETE"),
  51.     _T("UNLINK"),
  52. };
  53.  
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // map of HINTERNETs to CInternetSessions* for callbacks
  57.  
  58. // forward declared because we need a #pragma -- see end of this file
  59.  
  60. class CSessionMapPtrToPtr : public CMapPtrToPtr
  61. {
  62. private:
  63.     CCriticalSection m_sect;
  64.  
  65. public:
  66.     CSessionMapPtrToPtr() { }
  67.     ~CSessionMapPtrToPtr() { }
  68.  
  69.     void SetAt(HINTERNET hInternet, CInternetSession* pSess)
  70.     {
  71.         m_sect.Lock();
  72.         CMapPtrToPtr::SetAt(hInternet, pSess);
  73.         m_sect.Unlock();
  74.     }
  75.  
  76.     void RemoveKey(HINTERNET hInternet)
  77.     {
  78.         m_sect.Lock();
  79.         CMapPtrToPtr::RemoveKey(hInternet);
  80.         m_sect.Unlock();
  81.     }
  82.  
  83.     BOOL Lookup(HINTERNET hInternet, CInternetSession*& refpSession)
  84.     {
  85.         BOOL bRet;
  86.         m_sect.Lock();
  87.         bRet = CMapPtrToPtr::Lookup(hInternet, (void*&) refpSession);
  88.         m_sect.Unlock();
  89.         return bRet;
  90.     }
  91. };
  92.  
  93. extern CSessionMapPtrToPtr _afxSessionMap;
  94.  
  95.  
  96. /////////////////////////////////////////////////////////////////////////////
  97. // Global Functions
  98.  
  99. AFX_STATIC BOOL AFXAPI _AfxParseURLWorker(LPCTSTR pstrURL,
  100.     LPURL_COMPONENTS lpComponents, DWORD& dwServiceType,
  101.     INTERNET_PORT& nPort, DWORD dwFlags)
  102. {
  103.     // this function will return bogus stuff if lpComponents
  104.     // isn't set up to copy the components
  105.  
  106.     ASSERT(lpComponents != NULL && pstrURL != NULL);
  107.     if (lpComponents == NULL || pstrURL == NULL)
  108.         return FALSE;
  109.     ASSERT(lpComponents->dwHostNameLength == 0 ||
  110.             lpComponents->lpszHostName != NULL);
  111.     ASSERT(lpComponents->dwUrlPathLength == 0 ||
  112.             lpComponents->lpszUrlPath != NULL);
  113.     ASSERT(lpComponents->dwUserNameLength == 0 ||
  114.             lpComponents->lpszUserName != NULL);
  115.     ASSERT(lpComponents->dwPasswordLength == 0 ||
  116.             lpComponents->lpszPassword != NULL);
  117.  
  118.     ASSERT(AfxIsValidAddress(lpComponents, sizeof(URL_COMPONENTS), TRUE));
  119.  
  120.     LPTSTR pstrCanonicalizedURL;
  121.     TCHAR szCanonicalizedURL[INTERNET_MAX_URL_LENGTH];
  122.     DWORD dwNeededLength = INTERNET_MAX_URL_LENGTH;
  123.     BOOL bRetVal;
  124.     BOOL bMustFree = FALSE;
  125.     DWORD dwCanonicalizeFlags = dwFlags &
  126.         (ICU_NO_ENCODE | ICU_DECODE | ICU_NO_META |
  127.         ICU_ENCODE_SPACES_ONLY | ICU_BROWSER_MODE);
  128.     DWORD dwCrackFlags = dwFlags & (ICU_ESCAPE | ICU_USERNAME);
  129.  
  130.     bRetVal = InternetCanonicalizeUrl(pstrURL, szCanonicalizedURL,
  131.         &dwNeededLength, dwCanonicalizeFlags);
  132.  
  133.     if (!bRetVal)
  134.     {
  135.         if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  136.             return FALSE;
  137.  
  138.         pstrCanonicalizedURL = new TCHAR[dwNeededLength];
  139.         bMustFree = TRUE;
  140.         bRetVal = InternetCanonicalizeUrl(pstrURL, pstrCanonicalizedURL,
  141.             &dwNeededLength, dwCanonicalizeFlags);
  142.         if (!bRetVal)
  143.         {
  144.             delete [] pstrCanonicalizedURL;
  145.             return FALSE;
  146.         }
  147.     }
  148.     else
  149.         pstrCanonicalizedURL = szCanonicalizedURL;
  150.  
  151.     // now that it's safely canonicalized, crack it
  152.  
  153.     bRetVal = InternetCrackUrl(pstrCanonicalizedURL, 0,
  154.                         dwCrackFlags, lpComponents);
  155.     if (bMustFree)
  156.         delete [] pstrCanonicalizedURL;
  157.  
  158.     // convert to MFC-style service ID
  159.  
  160.     if (!bRetVal)
  161.         dwServiceType = AFX_INET_SERVICE_UNK;
  162.     else
  163.     {
  164.         nPort = lpComponents->nPort;
  165.         switch (lpComponents->nScheme)
  166.         {
  167.         case INTERNET_SCHEME_FTP:
  168.             dwServiceType = AFX_INET_SERVICE_FTP;
  169.             break;
  170.  
  171.         case INTERNET_SCHEME_GOPHER:
  172.             dwServiceType = AFX_INET_SERVICE_GOPHER;
  173.             break;
  174.  
  175.         case INTERNET_SCHEME_HTTP:
  176.             dwServiceType = AFX_INET_SERVICE_HTTP;
  177.             break;
  178.  
  179.         case INTERNET_SCHEME_HTTPS:
  180.             dwServiceType = AFX_INET_SERVICE_HTTPS;
  181.             break;
  182.  
  183.         case INTERNET_SCHEME_FILE:
  184.             dwServiceType = AFX_INET_SERVICE_FILE;
  185.             break;
  186.  
  187.         case INTERNET_SCHEME_NEWS:
  188.             dwServiceType = AFX_INET_SERVICE_NNTP;
  189.             break;
  190.  
  191.         case INTERNET_SCHEME_MAILTO:
  192.             dwServiceType = AFX_INET_SERVICE_MAILTO;
  193.             break;
  194.  
  195.         default:
  196.             dwServiceType = AFX_INET_SERVICE_UNK;
  197.         }
  198.     }
  199.  
  200.     return bRetVal;
  201. }
  202.  
  203. BOOL AFXAPI AfxParseURLEx(LPCTSTR pstrURL, DWORD& dwServiceType,
  204.     CString& strServer, CString& strObject, INTERNET_PORT& nPort,
  205.     CString& strUsername, CString& strPassword, DWORD dwFlags/* = 0*/)
  206. {
  207.     dwServiceType = AFX_INET_SERVICE_UNK;
  208.  
  209.     ASSERT(pstrURL != NULL);
  210.     if (pstrURL == NULL)
  211.         return FALSE;
  212.  
  213.     URL_COMPONENTS urlComponents;
  214.     memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
  215.     urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  216.  
  217.     urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
  218.     urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_HOST_NAME_LENGTH+1);
  219.     urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
  220.     urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_PATH_LENGTH+1);
  221.     urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
  222.     urlComponents.lpszUserName = strUsername.GetBuffer(INTERNET_MAX_USER_NAME_LENGTH+1);
  223.     urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
  224.     urlComponents.lpszPassword = strPassword.GetBuffer(INTERNET_MAX_PASSWORD_LENGTH+1);
  225.  
  226.     BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
  227.                     dwServiceType, nPort, dwFlags);
  228.  
  229.     strServer.ReleaseBuffer();
  230.     strObject.ReleaseBuffer();
  231.     strUsername.ReleaseBuffer();
  232.     strPassword.ReleaseBuffer();
  233.     return bRetVal;
  234. }
  235.  
  236. BOOL AFXAPI AfxParseURL(LPCTSTR pstrURL, DWORD& dwServiceType,
  237.     CString& strServer, CString& strObject, INTERNET_PORT& nPort)
  238. {
  239.     dwServiceType = AFX_INET_SERVICE_UNK;
  240.  
  241.     ASSERT(pstrURL != NULL);
  242.     if (pstrURL == NULL)
  243.         return FALSE;
  244.  
  245.     URL_COMPONENTS urlComponents;
  246.     memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
  247.     urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  248.  
  249.     urlComponents.dwHostNameLength = INTERNET_MAX_URL_LENGTH;
  250.     urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
  251.     urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
  252.     urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
  253.  
  254.     BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
  255.                     dwServiceType, nPort, ICU_BROWSER_MODE);
  256.  
  257.     strServer.ReleaseBuffer();
  258.     strObject.ReleaseBuffer();
  259.     return bRetVal;
  260. }
  261.  
  262.  
  263. DWORD AFXAPI AfxGetInternetHandleType(HINTERNET hQuery)
  264. {
  265.     DWORD dwServiceType;
  266.     DWORD dwTypeLen = sizeof(dwServiceType);
  267.     if (hQuery == NULL ||
  268.         !InternetQueryOption(hQuery, INTERNET_OPTION_HANDLE_TYPE,
  269.             &dwServiceType, &dwTypeLen))
  270.         return AFX_INET_SERVICE_UNK;
  271.     else
  272.         return dwServiceType;
  273. }
  274.  
  275. AFX_STATIC BOOL AFXAPI
  276. _AfxQueryCStringInternetOption(HINTERNET hHandle, DWORD dwOption, CString& refString)
  277. {
  278.     DWORD dwLength = 0;
  279.     LPTSTR pstrBuffer;
  280.  
  281.     if (hHandle == NULL)
  282.         return FALSE;
  283.  
  284.     if (!InternetQueryOption(hHandle, dwOption, NULL, &dwLength) &&
  285.         GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  286.     {
  287.         refString.Empty();
  288.         return FALSE;
  289.     }
  290.  
  291.     pstrBuffer = refString.GetBuffer(dwLength);
  292.     BOOL bRet = InternetQueryOption(hHandle, dwOption, pstrBuffer, &dwLength);
  293.     refString.ReleaseBuffer();
  294.     return bRet;
  295. }
  296.  
  297. #ifdef _DEBUG
  298. void AFXAPI AfxInternetStatusCallbackDebug(HINTERNET hInternet,
  299.     DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  300.     DWORD dwStatusInformationLength)
  301. {
  302.     UNUSED_ALWAYS(hInternet);
  303.     TRACE1("Internet ctxt=%d: ", dwContext);
  304.  
  305.     switch (dwInternetStatus)
  306.     {
  307.     case INTERNET_STATUS_RESOLVING_NAME:
  308.         TRACE1("resolving name for %s\n", lpvStatusInformation);
  309.         break;
  310.  
  311.     case INTERNET_STATUS_NAME_RESOLVED:
  312.         TRACE1("resolved name for %s!\n", lpvStatusInformation);
  313.         break;
  314.  
  315.     case INTERNET_STATUS_HANDLE_CREATED:
  316.         TRACE1("handle %8.8X created\n", hInternet);
  317.         break;
  318.  
  319.     case INTERNET_STATUS_CONNECTING_TO_SERVER:
  320.         {
  321.         sockaddr* pSockAddr = (sockaddr*) lpvStatusInformation;
  322.         TRACE1("connecting to socket address \"%s\"\n", pSockAddr->sa_data);
  323.         }
  324.         break;
  325.  
  326.     case INTERNET_STATUS_REQUEST_SENT:
  327.         TRACE0("request sent!\n");
  328.         break;
  329.  
  330.     case INTERNET_STATUS_SENDING_REQUEST:
  331.         TRACE0("sending request...\n");
  332.         break;
  333.  
  334.     case INTERNET_STATUS_CONNECTED_TO_SERVER:
  335.         TRACE0("connected to socket address!\n");
  336.         break;
  337.  
  338.     case INTERNET_STATUS_RECEIVING_RESPONSE:
  339.         TRACE0("receiving response...\n");
  340.         break;
  341.  
  342.     case INTERNET_STATUS_RESPONSE_RECEIVED:
  343.         TRACE0("response received!\n");
  344.         break;
  345.  
  346.     case INTERNET_STATUS_CLOSING_CONNECTION:
  347.         TRACE1("closing connection %8.8X\n", hInternet);
  348.         break;
  349.  
  350.     case INTERNET_STATUS_CONNECTION_CLOSED:
  351.         TRACE1("connection %8.8X closed!\n", hInternet);
  352.         break;
  353.  
  354.     case INTERNET_STATUS_HANDLE_CLOSING:
  355.         TRACE1("handle %8.8X closed!\n", hInternet);
  356.         break;
  357.  
  358.     case INTERNET_STATUS_REQUEST_COMPLETE:
  359.         if (dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT))
  360.         {
  361.             INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*) lpvStatusInformation;
  362.             TRACE2("request complete, dwResult = %8.8X, dwError = %8.8X\n",
  363.                 pResult->dwResult, pResult->dwError);
  364.         }
  365.         else
  366.             TRACE0("request complete.\n");
  367.         break;
  368.  
  369.     case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
  370.     case INTERNET_STATUS_REDIRECT:
  371.     default:
  372.         TRACE1("Unknown status: %d\n", dwInternetStatus);
  373.         break;
  374.     }
  375.  
  376.     return;
  377. }
  378. #endif // _DEBUG
  379.  
  380. void AFXAPI AfxInternetStatusCallback(HINTERNET hInternet, DWORD dwContext,
  381.     DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  382.     DWORD dwStatusInformationLength)
  383. {
  384.     CInternetSession* pSession;
  385.  
  386. #ifdef _DEBUG
  387.     if (afxTraceFlags & traceInternet)
  388.         AfxInternetStatusCallbackDebug(hInternet, dwContext,
  389.             dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
  390. #endif
  391.  
  392.     if (_afxSessionMap.Lookup(hInternet, pSession))
  393.     {
  394.         pSession->OnStatusCallback(dwContext, dwInternetStatus,
  395.             lpvStatusInformation, dwStatusInformationLength);
  396.     }
  397.  
  398.     // note that an entry we can't match is simply ignored as
  399.     // WININET can send notifications for handles that we can't
  400.     // see -- such as when using InternetOpenURL()
  401. }
  402.  
  403.  
  404. /////////////////////////////////////////////////////////////////////////////
  405. // CInternetSession
  406.  
  407. CInternetSession::~CInternetSession()
  408. {
  409.     Close();
  410. }
  411.  
  412. CInternetSession::CInternetSession(LPCTSTR pstrAgent /* = NULL */,
  413.     DWORD dwContext /* = 1 */,
  414.     DWORD dwAccessType /* = PRE_CONFIG_INTERNET_ACCESS */,
  415.     LPCTSTR pstrProxyName /* = NULL */,
  416.     LPCTSTR pstrProxyBypass /* = NULL */,
  417.     DWORD dwFlags /* = 0 */)
  418. {
  419.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  420.     m_bCallbackEnabled = FALSE;
  421.     m_pOldCallback = NULL;
  422.  
  423.     m_dwContext = dwContext;
  424.     if (pstrAgent == NULL)
  425.         pstrAgent = AfxGetAppName();
  426.     m_hSession = InternetOpen(pstrAgent, dwAccessType,
  427.         pstrProxyName, pstrProxyBypass, dwFlags);
  428.  
  429.     if (m_hSession == NULL)
  430.         AfxThrowInternetException(m_dwContext);
  431.     else
  432.         _afxSessionMap.SetAt(m_hSession, this);
  433. }
  434.  
  435. void CInternetSession::Close()
  436. {
  437.     if (m_bCallbackEnabled)
  438.         EnableStatusCallback(FALSE);
  439.  
  440.     if (m_hSession != NULL)
  441.     {
  442.         InternetCloseHandle(m_hSession);
  443.         _afxSessionMap.RemoveKey(m_hSession);
  444.         m_hSession = NULL;
  445.     }
  446. }
  447.  
  448. CGopherConnection* CInternetSession::GetGopherConnection(LPCTSTR pstrServer,
  449.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
  450.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  451. {
  452.     ASSERT(AfxIsValidString(pstrServer));
  453.  
  454.     CGopherConnection* pReturn = new CGopherConnection(this,
  455.         pstrServer, pstrUserName, pstrPassword, m_dwContext, nPort);
  456.     return pReturn;
  457. }
  458.  
  459. CFtpConnection* CInternetSession::GetFtpConnection(LPCTSTR pstrServer,
  460.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
  461.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  462.     BOOL bPassive /* = FALSE */)
  463. {
  464.     ASSERT(AfxIsValidString(pstrServer));
  465.  
  466.     CFtpConnection* pReturn = new CFtpConnection(this,
  467.         pstrServer, pstrUserName, pstrPassword, m_dwContext,
  468.         nPort, bPassive);
  469.     return pReturn;
  470. }
  471.  
  472. CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
  473.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  474.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
  475. {
  476.     ASSERT(AfxIsValidString(pstrServer));
  477.  
  478.     CHttpConnection* pReturn = new CHttpConnection(this,
  479.         pstrServer, nPort, pstrUserName, pstrPassword, m_dwContext);
  480.     return pReturn;
  481. }
  482.  
  483. CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
  484.     DWORD dwFlags, INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  485.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
  486. {
  487.     ASSERT(AfxIsValidString(pstrServer));
  488.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  489.  
  490.     CHttpConnection* pReturn = new CHttpConnection(this, pstrServer,
  491.             dwFlags, nPort, pstrUserName, pstrPassword, m_dwContext);
  492.     return pReturn;
  493. }
  494.  
  495. CStdioFile* CInternetSession::OpenURL(LPCTSTR pstrURL,
  496.     DWORD dwContext /* = 0 */, DWORD dwFlags /* = INTERNET_FLAG_TRANSFER_BINARY */,
  497.     LPCTSTR pstrHeaders /* = NULL */, DWORD dwHeadersLength /* = 0 */)
  498. {
  499.     ASSERT(AfxIsValidString(pstrURL));
  500.     ASSERT(dwHeadersLength == 0 || pstrHeaders != NULL);
  501.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  502.  
  503.     // must have TRANSFER_BINARY or TRANSFER_ASCII but not both
  504. #define _AFX_TRANSFER_MASK (INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII)
  505.     ASSERT((dwFlags & _AFX_TRANSFER_MASK) != 0);
  506.     ASSERT((dwFlags & _AFX_TRANSFER_MASK) != _AFX_TRANSFER_MASK);
  507.  
  508.     if (dwContext == 1)
  509.         dwContext = m_dwContext;
  510.  
  511.     DWORD dwServiceType;
  512.     CString strServer;
  513.     CString strObject;
  514.     INTERNET_PORT nPort;
  515.     CStdioFile* pReturn;
  516.  
  517.     BOOL bParsed = AfxParseURL(pstrURL, dwServiceType, strServer, strObject, nPort);
  518.  
  519.     // if it turns out to be a file...
  520.     if (bParsed && dwServiceType == AFX_INET_SERVICE_FILE)
  521.     {
  522.         int nMode = CFile::modeRead | CFile::shareCompat;
  523.         if (dwFlags & INTERNET_FLAG_TRANSFER_BINARY)
  524.             nMode |= CFile::typeBinary;
  525.         else
  526.             nMode |= CFile::typeText;
  527.  
  528.         pReturn = new CStdioFile(strObject, nMode);
  529.     }
  530.     else
  531.     {
  532.         HINTERNET hOpener;
  533.  
  534.         hOpener = InternetOpenUrl(m_hSession, pstrURL, pstrHeaders,
  535.             dwHeadersLength, dwFlags, dwContext);
  536.  
  537.         if (hOpener == NULL)
  538.             AfxThrowInternetException(m_dwContext);
  539.  
  540.         if (!bParsed)
  541.             dwServiceType = AfxGetInternetHandleType(hOpener);
  542.  
  543.         switch (dwServiceType)
  544.         {
  545.             case INTERNET_HANDLE_TYPE_GOPHER_FILE:
  546.             case AFX_INET_SERVICE_GOPHER:
  547.             //WINBUG: WININET supplies no way to
  548.             // convert from a URL to a Gopher locator
  549.                 pReturn = new CGopherFile(hOpener, m_hSession, _T(""),
  550.                     0, dwContext);
  551.                 _afxSessionMap.SetAt(hOpener, this);
  552.                 break;
  553.  
  554.             case INTERNET_HANDLE_TYPE_FTP_FILE:
  555.             case AFX_INET_SERVICE_FTP:
  556.                 pReturn = new CInternetFile(hOpener, m_hSession, strObject,
  557.                     strServer, dwContext, TRUE);
  558.                 _afxSessionMap.SetAt(hOpener, this);
  559.                 break;
  560.  
  561.             case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
  562.             case AFX_INET_SERVICE_HTTP:
  563.             case AFX_INET_SERVICE_HTTPS:
  564.                 pReturn = new CHttpFile(hOpener, m_hSession, strObject, strServer,
  565.                     CHttpConnection::szHtmlVerbs[CHttpConnection::HTTP_VERB_GET],
  566.                     dwContext);
  567.                 _afxSessionMap.SetAt(hOpener, this);
  568.                 break;
  569.  
  570.             default:
  571.                 TRACE1("Error: Unidentified service type: %8.8X\n", dwServiceType);
  572.                 pReturn = NULL;
  573.         }
  574.     }
  575.  
  576.     return pReturn;
  577. }
  578.  
  579. BOOL CInternetSession::SetOption(DWORD dwOption, LPVOID lpBuffer,
  580.     DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  581. {
  582.     ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  583.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  584.         dwOption <= INTERNET_LAST_OPTION);
  585.     ASSERT(dwBufferLength != 0);
  586.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  587.  
  588.     // bogus flag?
  589.     ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
  590.  
  591.     return InternetSetOptionEx(m_hSession, dwOption,
  592.         lpBuffer, dwBufferLength, dwFlags);
  593. }
  594.  
  595. BOOL CInternetSession::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  596.     LPDWORD lpdwBufferLength) const
  597. {
  598.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  599.         dwOption <= INTERNET_LAST_OPTION);
  600.     ASSERT_POINTER(lpdwBufferLength, DWORD);
  601.     ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  602.     ASSERT(*lpdwBufferLength != 0);
  603.  
  604.     return InternetQueryOption(m_hSession, dwOption,
  605.         lpBuffer, lpdwBufferLength);
  606. }
  607.  
  608. BOOL CInternetSession::QueryOption(DWORD dwOption, DWORD& dwValue) const
  609. {
  610.     DWORD dwLen = sizeof(DWORD);
  611.     return InternetQueryOption(m_hSession, dwOption,
  612.         &dwValue, &dwLen);
  613. }
  614.  
  615. BOOL CInternetSession::QueryOption(DWORD dwOption, CString& refString) const
  616. {
  617.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  618.         dwOption <= INTERNET_LAST_OPTION);
  619.  
  620.     return _AfxQueryCStringInternetOption(m_hSession, dwOption, refString);
  621. }
  622.  
  623. void CInternetSession::OnStatusCallback(DWORD dwContext,
  624.     DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  625.     DWORD dwStatusInformationLength)
  626. {
  627.     ASSERT(m_bCallbackEnabled != NULL);
  628.  
  629.     if (m_pOldCallback != NULL)
  630.     {
  631.         (*m_pOldCallback)(m_hSession, dwContext, dwInternetStatus,
  632.             lpvStatusInformation, dwStatusInformationLength);
  633.     }
  634. }
  635.  
  636. BOOL CInternetSession::EnableStatusCallback(BOOL bEnable /* = TRUE */)
  637. {
  638.     ASSERT(!bEnable || m_hSession != NULL);
  639.     if (m_hSession == NULL)
  640.         return FALSE;
  641.  
  642.     BOOL bResult = TRUE;
  643.  
  644.     if (bEnable)
  645.     {
  646.         ASSERT(!m_bCallbackEnabled);
  647.         if (!m_bCallbackEnabled)
  648.         {
  649.             INTERNET_STATUS_CALLBACK pRet =
  650.                 InternetSetStatusCallback(m_hSession, AfxInternetStatusCallback);
  651.  
  652.             if (pRet != INTERNET_INVALID_STATUS_CALLBACK)
  653.             {
  654.                 m_pOldCallback = pRet;
  655.                 m_bCallbackEnabled = TRUE;
  656.             }
  657.             else
  658.                 AfxThrowInternetException(m_dwContext);
  659.         }
  660.     }
  661.     else
  662.     {
  663.         ASSERT(m_bCallbackEnabled);
  664.  
  665.         if (m_bCallbackEnabled)
  666.         {
  667.             InternetSetStatusCallback(m_hSession, NULL);
  668.             m_bCallbackEnabled = FALSE;
  669.         }
  670.     }
  671.  
  672.     return bResult;
  673. }
  674.  
  675. BOOL CInternetSession::SetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPCTSTR pstrCookieData)
  676. {
  677.     ASSERT(AfxIsValidString(pstrUrl));
  678.     ASSERT(AfxIsValidString(pstrCookieName));
  679.     return InternetSetCookie(pstrUrl, pstrCookieName, pstrCookieData);
  680. }
  681.  
  682. BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPTSTR pstrCookieData, DWORD dwBufLen)
  683. {
  684.     ASSERT(AfxIsValidString(pstrUrl));
  685.     ASSERT(AfxIsValidString(pstrCookieName));
  686.     ASSERT(pstrCookieData != NULL);
  687.     return InternetGetCookie(pstrUrl, pstrCookieName, pstrCookieData, &dwBufLen);
  688. }
  689.  
  690. DWORD CInternetSession::GetCookieLength(LPCSTR pstrUrl, LPCTSTR pstrCookieName)
  691. {
  692.     ASSERT(AfxIsValidString(pstrUrl));
  693.     ASSERT(AfxIsValidString(pstrCookieName));
  694.  
  695.     DWORD dwRet;
  696.     if (!InternetGetCookie(pstrUrl, pstrCookieName, NULL, &dwRet))
  697.         dwRet = 0;
  698.     return dwRet;
  699. }
  700.  
  701. BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, CString& strCookieData)
  702. {
  703.     ASSERT(AfxIsValidString(pstrUrl));
  704.     ASSERT(AfxIsValidString(pstrCookieName));
  705.  
  706.     DWORD dwLen = GetCookieLength(pstrUrl, pstrCookieName);
  707.  
  708.     LPTSTR pstrTarget = strCookieData.GetBuffer(dwLen+1);
  709.     BOOL bRetVal = InternetGetCookie(pstrUrl, pstrCookieName, pstrTarget, &dwLen);
  710.     strCookieData.ReleaseBuffer(dwLen);
  711.  
  712.     if (!bRetVal)
  713.         strCookieData.Empty();
  714.     return bRetVal;
  715. }
  716.  
  717. #ifdef _DEBUG
  718. void CInternetSession::Dump(CDumpContext& dc) const
  719. {
  720.     CObject::Dump(dc);
  721.     dc << "m_hSession = " << m_hSession;
  722.     dc << "\nm_dwContext = " << m_dwContext;
  723. }
  724. #endif
  725.  
  726.  
  727. /////////////////////////////////////////////////////////////////////////////
  728. // Internet Files
  729.  
  730. CInternetFile::CInternetFile(HINTERNET hFile, HINTERNET /* hSession */,
  731.     LPCTSTR pstrFileName, LPCTSTR pstrServer, DWORD dwContext, BOOL bReadMode)
  732.     : m_dwContext(dwContext)
  733. {
  734.     // caller must set _afxSessionMap()!
  735.  
  736.     ASSERT(AfxIsValidString(pstrServer));
  737.     ASSERT(AfxIsValidString(pstrFileName));
  738.     ASSERT(hFile != NULL);
  739.  
  740.     m_strFileName = pstrFileName;
  741.     m_strServerName = pstrServer;
  742.  
  743.     m_hFile = hFile;
  744.     m_bReadMode = bReadMode;
  745.  
  746.     m_pbReadBuffer = NULL;
  747.     m_pbWriteBuffer = NULL;
  748.  
  749.     m_nReadBufferSize = 0;
  750.     m_nReadBufferPos = 0;
  751.     m_nWriteBufferSize = 0;
  752.     m_nWriteBufferPos = 0;
  753.     m_nReadBufferBytes = 0;
  754. }
  755.  
  756. CInternetFile::CInternetFile(HINTERNET hFile,
  757.     LPCTSTR pstrFileName, CInternetConnection* pConnection, BOOL bReadMode)
  758. {
  759.     ASSERT(AfxIsValidString(pstrFileName));
  760.     ASSERT(pConnection != NULL);
  761.     ASSERT_VALID(pConnection);
  762.     ASSERT(hFile != NULL);
  763.  
  764.     _afxSessionMap.SetAt(hFile, pConnection->GetSession());
  765.  
  766.     m_strFileName = pstrFileName;
  767.  
  768.     m_dwContext = pConnection->GetContext();
  769.     m_strServerName = pConnection->GetServerName();
  770.     m_hFile = hFile;
  771.     m_bReadMode = bReadMode;
  772.  
  773.     m_pbReadBuffer = NULL;
  774.     m_pbWriteBuffer = NULL;
  775.  
  776.     m_nReadBufferSize = 0;
  777.     m_nReadBufferPos = 0;
  778.     m_nWriteBufferSize = 0;
  779.     m_nWriteBufferPos = 0;
  780.     m_nReadBufferBytes = 0;
  781. }
  782.  
  783. BOOL CInternetFile::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  784.     LPDWORD lpdwBufferLength) const
  785. {
  786.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  787.         dwOption <= INTERNET_LAST_OPTION);
  788.     ASSERT_POINTER(lpdwBufferLength, DWORD);
  789.     ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  790.     ASSERT(*lpdwBufferLength != 0);
  791.     ASSERT(m_hFile != NULL);
  792.  
  793.     return InternetQueryOption(m_hFile, dwOption,
  794.         lpBuffer, lpdwBufferLength);
  795. }
  796.  
  797. BOOL CInternetFile::QueryOption(DWORD dwOption, DWORD& dwValue) const
  798. {
  799.     ASSERT(m_hFile != NULL);
  800.  
  801.     DWORD dwLen = sizeof(DWORD);
  802.     return InternetQueryOption(m_hFile, dwOption,
  803.         &dwValue, &dwLen);
  804. }
  805.  
  806. BOOL CInternetFile::QueryOption(DWORD dwOption, CString& refString) const
  807. {
  808.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  809.         dwOption <= INTERNET_LAST_OPTION);
  810.     ASSERT(m_hFile != NULL);
  811.  
  812.     return _AfxQueryCStringInternetOption(m_hFile, dwOption, refString);
  813. }
  814.  
  815. BOOL CInternetFile::SetOption(DWORD dwOption, LPVOID lpBuffer,
  816.     DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  817. {
  818.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  819.         dwOption <= INTERNET_LAST_OPTION);
  820.     ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  821.     ASSERT(dwBufferLength != 0);
  822.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  823.  
  824.     // bogus flag?
  825.     ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
  826.  
  827.     return InternetSetOptionEx(m_hFile, dwOption,
  828.         lpBuffer, dwBufferLength, dwFlags);
  829. }
  830.  
  831. BOOL CInternetFile::SetReadBufferSize(UINT nReadSize)
  832. {
  833.     ASSERT_VALID(this);
  834.     BOOL bRet = TRUE;
  835.  
  836.     if (nReadSize != -1 && nReadSize != m_nReadBufferSize)
  837.     {
  838.         if (m_nReadBufferPos > nReadSize)
  839.             bRet = FALSE;
  840.         else
  841.         {
  842.             if (nReadSize == 0)
  843.             {
  844.                 delete [] m_pbReadBuffer;
  845.                 m_pbReadBuffer = NULL;
  846.             }
  847.             else if (m_pbReadBuffer == NULL)
  848.             {
  849.                 m_pbReadBuffer = new BYTE[nReadSize];
  850.                 m_nReadBufferPos = nReadSize;
  851.             }
  852.             else
  853.             {
  854.                 DWORD dwMoved = m_nReadBufferSize - m_nReadBufferPos;
  855.                 LPBYTE pbTemp = m_pbReadBuffer;
  856.                 m_pbReadBuffer = new BYTE[nReadSize];
  857.  
  858.                 if (dwMoved > 0)
  859.                 {
  860.                     memcpy(m_pbReadBuffer, pbTemp + m_nReadBufferPos, dwMoved);
  861.                     m_nReadBufferPos = 0;
  862.                     m_nReadBufferBytes = dwMoved;
  863.                 }
  864.                 else
  865.                 {
  866.                     m_nReadBufferBytes = 0;
  867.                     m_nReadBufferPos = nReadSize;
  868.                 }
  869.                 delete [] pbTemp;
  870.             }
  871.  
  872.             m_nReadBufferSize = nReadSize;
  873.         }
  874.     }
  875.  
  876.     return bRet;
  877. }
  878.  
  879. BOOL CInternetFile::SetWriteBufferSize(UINT nWriteSize)
  880. {
  881.     ASSERT_VALID(this);
  882.     BOOL bRet = TRUE;
  883.  
  884.     if (nWriteSize != m_nWriteBufferSize)
  885.     {
  886.         if (m_nWriteBufferPos > nWriteSize)
  887.             Flush();
  888.  
  889.         if (nWriteSize == 0)
  890.         {
  891.             delete [] m_pbWriteBuffer;
  892.             m_pbWriteBuffer = NULL;
  893.         }
  894.         else if (m_pbWriteBuffer == NULL)
  895.         {
  896.             m_pbWriteBuffer = new BYTE[nWriteSize];
  897.             m_nWriteBufferPos = 0;
  898.         }
  899.         else
  900.         {
  901.             LPBYTE pbTemp = m_pbWriteBuffer;
  902.             m_pbWriteBuffer = new BYTE[nWriteSize];
  903.  
  904.             memcpy(m_pbWriteBuffer, pbTemp, m_nWriteBufferPos);
  905.             delete [] pbTemp;
  906.         }
  907.  
  908.         m_nWriteBufferSize = nWriteSize;
  909.     }
  910.  
  911.     return bRet;
  912. }
  913.  
  914. LONG CInternetFile::Seek(LONG lOffset, UINT nFrom)
  915. {
  916.     ASSERT_VALID(this);
  917.     ASSERT(m_hFile != NULL);
  918.     ASSERT(m_bReadMode);
  919.     ASSERT(m_pbReadBuffer == NULL);
  920.  
  921.     // can't do this on a file for writing
  922.     // can't do this on a file that's got a buffer
  923.  
  924.     if (!m_bReadMode || m_pbReadBuffer != NULL)
  925.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  926.  
  927.     switch (nFrom)
  928.     {
  929.         case begin:
  930.             nFrom = FILE_BEGIN;
  931.             break;
  932.  
  933.         case current:
  934.             nFrom = FILE_CURRENT;
  935.             break;
  936.  
  937.         case end:
  938.             nFrom = FILE_END;
  939.             break;
  940.  
  941.         default:
  942.             ASSERT(FALSE);  // got a bogus nFrom value
  943.             AfxThrowInternetException(m_dwContext, ERROR_INVALID_PARAMETER);
  944.             break;
  945.     }
  946.  
  947.     LONG lRet;
  948.     lRet = InternetSetFilePointer(m_hFile, lOffset, NULL, nFrom, m_dwContext);
  949.     if (lRet == -1)
  950.         AfxThrowInternetException(m_dwContext);
  951.  
  952.     return lRet;
  953. }
  954.  
  955. CInternetFile::~CInternetFile()
  956. {
  957.     if (m_hFile != NULL)
  958.     {
  959. #ifdef _DEBUG
  960.         USES_CONVERSION;
  961.         LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
  962.         TRACE2("Warning: destroying an open %s with handle %8.8X\n",
  963.             pszName, m_hFile);
  964. #endif
  965.         Close();
  966.     }
  967.  
  968.     if (m_pbReadBuffer != NULL)
  969.         delete m_pbReadBuffer;
  970.  
  971.     if (m_pbWriteBuffer != NULL)
  972.         delete m_pbWriteBuffer;
  973. }
  974.  
  975. void CInternetFile::Abort()
  976. {
  977.     ASSERT_VALID(this);
  978.     if (m_hFile != NULL)
  979.         Close();
  980.     m_strFileName.Empty();
  981. }
  982.  
  983. void CInternetFile::Flush()
  984. {
  985.     if (m_pbWriteBuffer != NULL && m_nWriteBufferPos > 0)
  986.     {
  987.         DWORD dwBytes;
  988.  
  989.         if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
  990.                 m_nWriteBufferPos, &dwBytes))
  991.             AfxThrowInternetException(m_dwContext);
  992.  
  993.         if (dwBytes != m_nWriteBufferPos)
  994.             AfxThrowInternetException(m_dwContext);
  995.  
  996.         m_nWriteBufferPos = 0;
  997.     }
  998. }
  999.  
  1000. void CInternetFile::Close()
  1001. {
  1002.     if (m_hFile != NULL)
  1003.     {
  1004.         Flush();
  1005.         InternetCloseHandle(m_hFile);
  1006.         _afxSessionMap.RemoveKey(m_hFile);
  1007.         m_hFile = NULL;
  1008.  
  1009.         if (m_pbWriteBuffer != NULL)
  1010.         {
  1011.             delete [] m_pbWriteBuffer;
  1012.             m_pbWriteBuffer = NULL;
  1013.         }
  1014.  
  1015.         if (m_pbReadBuffer != NULL)
  1016.         {
  1017.             delete [] m_pbReadBuffer;
  1018.             m_pbReadBuffer = NULL;
  1019.         }
  1020.     }
  1021. }
  1022.  
  1023. UINT CInternetFile::Read(LPVOID lpBuf, UINT nCount)
  1024. {
  1025.     ASSERT_VALID(this);
  1026.     ASSERT(AfxIsValidAddress(lpBuf, nCount));
  1027.     ASSERT(m_hFile != NULL);
  1028.     ASSERT(m_bReadMode);
  1029.  
  1030.     DWORD dwBytes;
  1031.  
  1032.     if (!m_bReadMode || m_hFile == NULL)
  1033.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1034.  
  1035.     if (m_pbReadBuffer == NULL)
  1036.     {
  1037.         if (!InternetReadFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
  1038.                 AfxThrowInternetException(m_dwContext);
  1039.         return dwBytes;
  1040.     }
  1041.  
  1042.     LPBYTE lpbBuf = (LPBYTE) lpBuf;
  1043.  
  1044.     // if the requested size is bigger than our buffer,
  1045.     // then handle it directly
  1046.  
  1047.     if (nCount >= m_nReadBufferSize)
  1048.     {
  1049.         DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
  1050.         memcpy(lpBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
  1051.         m_nReadBufferPos = m_nReadBufferSize;
  1052.         if (!InternetReadFile(m_hFile, lpbBuf+dwMoved, nCount-dwMoved, &dwBytes))
  1053.                 AfxThrowInternetException(m_dwContext);
  1054.         dwBytes += dwMoved;
  1055.     }
  1056.     else
  1057.     {
  1058.         if (m_nReadBufferPos + nCount >= m_nReadBufferBytes)
  1059.         {
  1060.             DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
  1061.             memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
  1062.  
  1063.             DWORD dwRead;
  1064.             if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  1065.                     &dwRead))
  1066.                 AfxThrowInternetException(m_dwContext);
  1067.             m_nReadBufferBytes = dwRead;
  1068.  
  1069.             dwRead = min(nCount - dwMoved, m_nReadBufferBytes);
  1070.             memcpy(lpbBuf + dwMoved, m_pbReadBuffer, dwRead);
  1071.             m_nReadBufferPos = dwRead;
  1072.             dwBytes = dwMoved + dwRead;
  1073.         }
  1074.         else
  1075.         {
  1076.             memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, nCount);
  1077.             m_nReadBufferPos += nCount;
  1078.             dwBytes = nCount;
  1079.         }
  1080.     }
  1081.  
  1082.     return dwBytes;
  1083. }
  1084.  
  1085. void CInternetFile::Write(const void* lpBuf, UINT nCount)
  1086. {
  1087.     ASSERT_VALID(this);
  1088.     ASSERT(m_hFile != NULL);
  1089.     ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  1090.     ASSERT(m_bReadMode == FALSE || m_bReadMode == -1);
  1091.  
  1092.     if (m_bReadMode == TRUE || m_hFile == NULL)
  1093.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1094.  
  1095.     DWORD dwBytes;
  1096.     if (m_pbWriteBuffer == NULL)
  1097.     {
  1098.         if (!InternetWriteFile(m_hFile, lpBuf, nCount, &dwBytes))
  1099.             AfxThrowInternetException(m_dwContext);
  1100.  
  1101.         if (dwBytes != nCount)
  1102.             AfxThrowInternetException(m_dwContext);
  1103.     }
  1104.     else
  1105.     {
  1106.         if ((m_nWriteBufferPos + nCount) >= m_nWriteBufferSize)
  1107.         {
  1108.             // write what is in the buffer just now
  1109.  
  1110.             if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
  1111.                     m_nWriteBufferPos, &dwBytes))
  1112.                 AfxThrowInternetException(m_dwContext);
  1113.  
  1114.             // reset the buffer position since it is now clean
  1115.  
  1116.             m_nWriteBufferPos = 0;
  1117.         }
  1118.  
  1119.         // if we can't hope to buffer the write request,
  1120.         // do it immediately ... otherwise, buffer it!
  1121.  
  1122.         if (nCount >= m_nWriteBufferSize)
  1123.         {
  1124.             if (!InternetWriteFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
  1125.                 AfxThrowInternetException(m_dwContext);
  1126.         }
  1127.         else
  1128.         {
  1129.             memcpy(m_nWriteBufferPos + m_pbWriteBuffer, lpBuf, nCount);
  1130.             m_nWriteBufferPos += nCount;
  1131.         }
  1132.     }
  1133. }
  1134.  
  1135. void CInternetFile::WriteString(LPCTSTR pstr)
  1136. {
  1137.     ASSERT(m_bReadMode == TRUE || m_bReadMode == -1);
  1138.     ASSERT(AfxIsValidString(pstr));
  1139.     ASSERT_VALID(this);
  1140.     ASSERT(m_hFile != NULL);
  1141.  
  1142.     if (m_bReadMode == TRUE)
  1143.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1144.  
  1145.     Write(pstr, lstrlen(pstr));
  1146. }
  1147.  
  1148. LPTSTR CInternetFile::ReadString(LPTSTR pstr, UINT nMax)
  1149. {
  1150.     ASSERT_VALID(this);
  1151.     ASSERT(m_hFile != NULL);
  1152.     ASSERT(AfxIsValidAddress(pstr, nMax*sizeof(TCHAR)));
  1153.     DWORD dwRead;
  1154.  
  1155.     // if we're reading line-by-line, we must have a buffer
  1156.  
  1157.     if (m_pbReadBuffer == NULL)
  1158.     {
  1159.         if (!SetReadBufferSize(4096))   // arbitrary but reasonable
  1160.             return NULL;
  1161.         if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  1162.                 &dwRead))
  1163.             AfxThrowInternetException(m_dwContext);
  1164.         m_nReadBufferBytes = dwRead;
  1165.         m_nReadBufferPos = 0;
  1166.     }
  1167.  
  1168.     LPTSTR pstrChar = (LPTSTR) (m_pbReadBuffer + m_nReadBufferPos);
  1169.     LPTSTR pstrTarget = pstr;
  1170.  
  1171.     while (--nMax)
  1172.     {
  1173.         if (m_nReadBufferPos >= m_nReadBufferBytes)
  1174.         {
  1175.             if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  1176.                     &dwRead))
  1177.                 AfxThrowInternetException(m_dwContext);
  1178.             m_nReadBufferBytes = dwRead;
  1179.             if (m_nReadBufferBytes == 0)
  1180.             {
  1181.                 *pstrTarget = '\0';
  1182.                 if (pstrTarget == pstr)
  1183.                     return NULL;
  1184.                 else
  1185.                     return pstr;
  1186.             }
  1187.             else
  1188.             {
  1189.                 m_nReadBufferPos = 0;
  1190.                 pstrChar = (LPTSTR) m_pbReadBuffer;
  1191.             }
  1192.         }
  1193.  
  1194.         if (*pstrChar != '\r')
  1195.             *pstrTarget++ = *pstrChar;
  1196.  
  1197.         m_nReadBufferPos++;
  1198.         if (*pstrChar++ == '\n')
  1199.             break;
  1200.     }
  1201.  
  1202.     *pstrTarget = '\0';
  1203.     return pstr;
  1204. }
  1205.  
  1206. BOOL CInternetFile::ReadString(CString& rString)
  1207. {
  1208.     ASSERT_VALID(this);
  1209.     ASSERT(m_hFile != NULL);
  1210.  
  1211.     rString = _T("");    // empty string without deallocating
  1212.     const int nMaxSize = 128;
  1213.  
  1214.     LPTSTR pstrPlace = rString.GetBuffer(nMaxSize);
  1215.     LPTSTR pstrResult;
  1216.     int nLen;
  1217.  
  1218.     do
  1219.     {
  1220.         pstrResult = ReadString(pstrPlace, nMaxSize);
  1221.         rString.ReleaseBuffer();
  1222.  
  1223.         // if string is read completely or EOF
  1224.         if (pstrResult == NULL ||
  1225.             (nLen = lstrlen(pstrPlace)) < (nMaxSize-1) ||
  1226.             pstrPlace[nLen-1] == '\n')
  1227.             break;
  1228.  
  1229.         nLen = rString.GetLength();
  1230.         pstrPlace = rString.GetBuffer(nMaxSize + nLen) + nLen;
  1231.     } while (1);
  1232.  
  1233.     // remove '\n' from end of string if present
  1234.     pstrPlace = rString.GetBuffer(0);
  1235.     nLen = rString.GetLength();
  1236.     if (nLen != 0 && pstrPlace[nLen-1] == '\n')
  1237.         pstrPlace[nLen-1] = '\0';
  1238.     rString.ReleaseBuffer();
  1239.  
  1240.     return (pstrResult != NULL);
  1241. }
  1242.  
  1243. DWORD CInternetFile::GetLength() const
  1244. {
  1245.     ASSERT_VALID(this);
  1246.     ASSERT(m_hFile != NULL);
  1247.  
  1248.     DWORD dwRet = 0;
  1249.  
  1250.     if (m_hFile != NULL)
  1251.     {
  1252.         if (!InternetQueryDataAvailable(m_hFile, &dwRet, 0, 0))
  1253.             dwRet = 0;
  1254.     }
  1255.  
  1256.     return dwRet;
  1257. }
  1258.  
  1259. void CInternetFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  1260. {
  1261.     ASSERT_VALID(this);
  1262.     ASSERT(m_hFile != NULL);
  1263.  
  1264.     AfxThrowNotSupportedException();
  1265. }
  1266.  
  1267. void CInternetFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  1268. {
  1269.     ASSERT_VALID(this);
  1270.     ASSERT(m_hFile != NULL);
  1271.  
  1272.     AfxThrowNotSupportedException();
  1273. }
  1274.  
  1275. void CInternetFile::SetLength(DWORD)
  1276. {
  1277.     ASSERT_VALID(this);
  1278.     ASSERT(m_hFile != NULL);
  1279.  
  1280.     AfxThrowNotSupportedException();
  1281. }
  1282.  
  1283. CFile* CInternetFile::Duplicate() const
  1284. {
  1285.     ASSERT_VALID(this);
  1286.     ASSERT(m_pStream != NULL);
  1287.  
  1288.     AfxThrowNotSupportedException();
  1289.     return NULL;
  1290. }
  1291.  
  1292. #ifdef _DEBUG
  1293. void CInternetFile::AssertValid() const
  1294. {
  1295.     // Don't call CStdioFile's AsssertValid()
  1296.     CFile::AssertValid();
  1297.  
  1298.     ASSERT(m_hConnection != NULL);
  1299.  
  1300.     // make sure we really have a decent handle
  1301.     if (m_hFile != NULL)
  1302.     {
  1303.         DWORD dwResult = AfxGetInternetHandleType(m_hFile);
  1304.  
  1305.         if (IsKindOf(RUNTIME_CLASS(CHttpFile)))
  1306.         {
  1307.             ASSERT(dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1308.         }
  1309.         else if (IsKindOf(RUNTIME_CLASS(CGopherFile)))
  1310.         {
  1311.             ASSERT(dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE ||
  1312.                 dwResult == INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML ||
  1313.                 dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML ||
  1314.                 dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1315.         }
  1316.         else if (IsKindOf(RUNTIME_CLASS(CInternetFile)))
  1317.         {
  1318.             ASSERT(dwResult == INTERNET_HANDLE_TYPE_FTP_FILE ||
  1319.                 dwResult == INTERNET_HANDLE_TYPE_FTP_FILE_HTML ||
  1320.                 dwResult == INTERNET_HANDLE_TYPE_FTP_FIND_HTML ||
  1321.                 dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1322.         }
  1323.         else
  1324.             ASSERT(FALSE);  // some bogus object!
  1325.     }
  1326. }
  1327.  
  1328. void CInternetFile::Dump(CDumpContext& dc) const
  1329. {
  1330.     CObject::Dump(dc);
  1331.  
  1332.     dc << "\na " << GetRuntimeClass()->m_lpszClassName;
  1333.     dc << " with handle " << (UINT)m_hFile;
  1334. }
  1335. #endif
  1336.  
  1337. /////////////////////////////////////////////////////////////////////////////
  1338. // CInternetConnection
  1339.  
  1340. CInternetConnection::CInternetConnection(CInternetSession* pSession,
  1341.     LPCTSTR pstrServerName,
  1342.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1343.     DWORD dwContext /* = 1 */)
  1344.     : m_strServerName(pstrServerName)
  1345. {
  1346.     ASSERT(pSession != NULL);
  1347.     ASSERT_VALID(pSession);
  1348.     ASSERT(pstrServerName != NULL);
  1349.  
  1350.     m_nPort = nPort;
  1351.     m_pSession = pSession;
  1352.     m_hConnection = NULL;
  1353.     if (dwContext == 1)
  1354.         dwContext = pSession->GetContext();
  1355.     m_dwContext = dwContext;
  1356. }
  1357.  
  1358. CInternetConnection::~CInternetConnection()
  1359. {
  1360.     if (m_hConnection != NULL)
  1361.     {
  1362. #ifdef _DEBUG
  1363.         USES_CONVERSION;
  1364.         LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
  1365.         TRACE3("Warning: Disconnecting %s handle %8.8X in context %8.8X at destruction.\n",
  1366.             pszName, m_hConnection, m_dwContext);
  1367. #endif
  1368.         Close();
  1369.     }
  1370. }
  1371.  
  1372. BOOL CInternetConnection::SetOption(DWORD dwOption, LPVOID lpBuffer,
  1373.     DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  1374. {
  1375.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1376.         dwOption <= INTERNET_LAST_OPTION);
  1377.     ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  1378.     ASSERT(dwBufferLength != 0);
  1379.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1380.  
  1381.     // bogus flag?
  1382.     ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
  1383.  
  1384.     return InternetSetOptionEx(m_hConnection, dwOption,
  1385.         lpBuffer, dwBufferLength, dwFlags);
  1386. }
  1387.  
  1388. BOOL CInternetConnection::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  1389.     LPDWORD lpdwBufferLength) const
  1390. {
  1391.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1392.         dwOption <= INTERNET_LAST_OPTION);
  1393.     ASSERT_POINTER(lpdwBufferLength, DWORD);
  1394.     ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  1395.     ASSERT(*lpdwBufferLength != 0);
  1396.  
  1397.     return InternetQueryOption(m_hConnection, dwOption,
  1398.         lpBuffer, lpdwBufferLength);
  1399. }
  1400.  
  1401. BOOL CInternetConnection::QueryOption(DWORD dwOption, DWORD& dwValue) const
  1402. {
  1403.     DWORD dwLen = sizeof(DWORD);
  1404.     return InternetQueryOption(m_hConnection, dwOption,
  1405.         &dwValue, &dwLen);
  1406. }
  1407.  
  1408. BOOL CInternetConnection::QueryOption(DWORD dwOption, CString& refString) const
  1409. {
  1410.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1411.         dwOption <= INTERNET_LAST_OPTION);
  1412.  
  1413.     return _AfxQueryCStringInternetOption(m_hConnection, dwOption, refString);
  1414. }
  1415.  
  1416. void CInternetConnection::Close()
  1417. {
  1418.     if (m_hConnection != NULL)
  1419.     {
  1420.         InternetCloseHandle(m_hConnection);
  1421.         _afxSessionMap.RemoveKey(m_hConnection);
  1422.         m_hConnection = NULL;
  1423.     }
  1424. }
  1425.  
  1426. #ifdef _DEBUG
  1427. void CInternetConnection::Dump(CDumpContext& dc) const
  1428. {
  1429.     CObject::Dump(dc);
  1430.     dc << "m_hConnection = " << m_hConnection;
  1431. }
  1432.  
  1433. void CInternetConnection::AssertValid() const
  1434. {
  1435.     CObject::AssertValid();
  1436. }
  1437. #endif
  1438.  
  1439.  
  1440. /////////////////////////////////////////////////////////////////////////////
  1441. // CFtpConnection
  1442.  
  1443. CFtpConnection::~CFtpConnection()
  1444. {
  1445. }
  1446.  
  1447. CFtpConnection::CFtpConnection(CInternetSession* pSession,
  1448.     HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
  1449.     : CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER,
  1450.     dwContext)
  1451. {
  1452.     ASSERT(pSession != NULL);
  1453.     ASSERT(AfxIsValidString(pstrServer));
  1454.  
  1455.     BOOL bBadType = FALSE;
  1456.     if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_FTP)
  1457.     {
  1458.         ASSERT(FALSE);      // used the wrong handle type
  1459.         bBadType = TRUE;
  1460.     }
  1461.  
  1462.     m_strServerName = pstrServer;
  1463.     m_hConnection = hConnected;
  1464.     if (m_hConnection == NULL || bBadType)
  1465.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1466.     else
  1467.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1468. }
  1469.  
  1470. CFtpConnection::CFtpConnection(CInternetSession* pSession,
  1471.     LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
  1472.     LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
  1473.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1474.     BOOL bPassive /* = FALSE */)
  1475.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1476. {
  1477.     ASSERT(pSession != NULL);
  1478.     ASSERT_KINDOF(CInternetSession, pSession);
  1479.     ASSERT(AfxIsValidString(pstrServer));
  1480.  
  1481.     m_strServerName = pstrServer;
  1482.  
  1483.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1484.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_FTP,
  1485.         (bPassive ? INTERNET_FLAG_PASSIVE : 0), m_dwContext);
  1486.  
  1487.     if (m_hConnection == NULL)
  1488.         AfxThrowInternetException(m_dwContext, ::GetLastError());
  1489.     else
  1490.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1491. }
  1492.  
  1493. void CFtpConnection::Close()
  1494. {
  1495.     CInternetConnection::Close();
  1496. }
  1497.  
  1498. BOOL CFtpConnection::Remove(LPCTSTR pstrFileName)
  1499. {
  1500.     ASSERT_VALID(this);
  1501.     ASSERT(m_hConnection != NULL);
  1502.     ASSERT(AfxIsValidString(pstrFileName));
  1503.  
  1504.     return FtpDeleteFile(m_hConnection, pstrFileName);
  1505. }
  1506.  
  1507. BOOL CFtpConnection::Rename(LPCTSTR pstrExisting, LPCTSTR pstrNew)
  1508. {
  1509.     ASSERT_VALID(this);
  1510.     ASSERT(m_hConnection != NULL);
  1511.     ASSERT(AfxIsValidString(pstrExisting));
  1512.     ASSERT(AfxIsValidString(pstrNew));
  1513.  
  1514.     return FtpRenameFile(m_hConnection, pstrExisting, pstrNew);
  1515. }
  1516.  
  1517. BOOL CFtpConnection::CreateDirectory(LPCTSTR pstrDirName)
  1518. {
  1519.     ASSERT_VALID(this);
  1520.     ASSERT(m_hConnection != NULL);
  1521.     ASSERT(AfxIsValidString(pstrDirName));
  1522.  
  1523.     return FtpCreateDirectory(m_hConnection, pstrDirName);
  1524. }
  1525.  
  1526. BOOL CFtpConnection::RemoveDirectory(LPCTSTR pstrDirName)
  1527. {
  1528.     ASSERT_VALID(this);
  1529.     ASSERT(m_hConnection != NULL);
  1530.     ASSERT(AfxIsValidString(pstrDirName));
  1531.  
  1532.     return FtpRemoveDirectory(m_hConnection, pstrDirName);
  1533. }
  1534.  
  1535. BOOL CFtpConnection::SetCurrentDirectory(LPCTSTR pstrDirName)
  1536. {
  1537.     ASSERT_VALID(this);
  1538.     ASSERT(m_hConnection != NULL);
  1539.     ASSERT(AfxIsValidString(pstrDirName));
  1540.  
  1541.     return FtpSetCurrentDirectory(m_hConnection, pstrDirName);
  1542. }
  1543.  
  1544. BOOL CFtpConnection::GetCurrentDirectory(LPTSTR pstrDirName,
  1545.     LPDWORD lpdwLen) const
  1546. {
  1547.     ASSERT_VALID(this);
  1548.     ASSERT(m_hConnection != NULL);
  1549.     ASSERT(AfxIsValidAddress(pstrDirName, *lpdwLen));
  1550.     ASSERT(lpdwLen != 0);
  1551.  
  1552.     return FtpGetCurrentDirectory(m_hConnection, pstrDirName, lpdwLen);
  1553. }
  1554.  
  1555. BOOL CFtpConnection::GetCurrentDirectoryAsURL(CString& strDirName) const
  1556. {
  1557.     CString strDirectory;
  1558.     if (!GetCurrentDirectory(strDirectory))
  1559.         return FALSE;
  1560.  
  1561.     strDirName = _afxURLftp;
  1562.     strDirName += GetServerName();
  1563.  
  1564.     if (strDirectory[0] != '/')
  1565.         strDirName += '/';
  1566.  
  1567.     strDirName += strDirectory;
  1568.     return TRUE;
  1569. }
  1570.  
  1571. BOOL CFtpConnection::GetCurrentDirectoryAsURL(LPTSTR pstrName,
  1572.     LPDWORD lpdwLen) const
  1573. {
  1574.     ASSERT(lpdwLen != NULL);
  1575.     ASSERT_POINTER(lpdwLen, DWORD);
  1576.     ASSERT(AfxIsValidAddress(pstrName, *lpdwLen));
  1577.     ASSERT(*lpdwLen != 0);
  1578.  
  1579.     CString strTemp;
  1580.  
  1581.     if (lpdwLen == NULL || !GetCurrentDirectoryAsURL(strTemp))
  1582.         return FALSE;
  1583.  
  1584.     if (pstrName == NULL)
  1585.         *lpdwLen = strTemp.GetLength();
  1586.     else
  1587.         lstrcpyn(pstrName, (LPCTSTR) strTemp, max(0, *lpdwLen -1));
  1588.  
  1589.     return TRUE;
  1590. }
  1591.  
  1592. BOOL CFtpConnection::GetCurrentDirectory(CString& strDirName) const
  1593. {
  1594.     ASSERT_VALID(this);
  1595.     ASSERT(m_hConnection != NULL);
  1596.  
  1597.     DWORD dwLen = INTERNET_MAX_PATH_LENGTH;
  1598.     LPTSTR pstrTarget = strDirName.GetBufferSetLength(dwLen);
  1599.     BOOL bRet = FtpGetCurrentDirectory(m_hConnection, pstrTarget, &dwLen);
  1600.  
  1601.     if (bRet)
  1602.         strDirName.ReleaseBuffer(dwLen);
  1603.     else
  1604.         strDirName.ReleaseBuffer(0);
  1605.  
  1606.     return bRet;
  1607. }
  1608.  
  1609. CInternetFile* CFtpConnection::OpenFile(LPCTSTR pstrFileName,
  1610.     DWORD dwAccess /* = GENERIC_READ */,
  1611.     DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
  1612.     DWORD dwContext /* = 1 */)
  1613. {
  1614.     ASSERT_VALID(this);
  1615.     ASSERT(m_hConnection != NULL);
  1616.     ASSERT(dwAccess != (GENERIC_READ | GENERIC_WRITE));
  1617.     ASSERT(dwAccess == GENERIC_READ || dwAccess == GENERIC_WRITE);
  1618.     ASSERT(AfxIsValidString(pstrFileName));
  1619.  
  1620.     HINTERNET hFile;
  1621.     if (dwContext == 1)
  1622.         dwContext = m_dwContext;
  1623.  
  1624.     hFile = FtpOpenFile(m_hConnection, pstrFileName, dwAccess,
  1625.         dwFlags, dwContext);
  1626.     if (hFile == NULL)
  1627.         AfxThrowInternetException(dwContext);
  1628.  
  1629.     CInternetFile* pFile = new CInternetFile(hFile, pstrFileName, this,
  1630.         (dwAccess == GENERIC_READ));
  1631.     return pFile;
  1632. }
  1633.  
  1634. BOOL CFtpConnection::PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile,
  1635.     DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
  1636.     DWORD dwContext /* = 1 */)
  1637. {
  1638.     ASSERT_VALID(this);
  1639.     ASSERT(m_hConnection != NULL);
  1640.     ASSERT(AfxIsValidString(pstrRemoteFile));
  1641.     ASSERT(AfxIsValidString(pstrLocalFile));
  1642.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1643.  
  1644.     if (dwContext == 1)
  1645.         dwContext = m_dwContext;
  1646.  
  1647.     return FtpPutFile(m_hConnection, pstrLocalFile, pstrRemoteFile,
  1648.         dwFlags, dwContext);
  1649. }
  1650.  
  1651. BOOL CFtpConnection::GetFile(LPCTSTR pstrRemoteFile, LPCTSTR pstrLocalFile,
  1652.     BOOL bFailIfExists /* = TRUE */,
  1653.     DWORD dwAttributes /* = FILE_ATTRIBUTE_NORMAL */,
  1654.     DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */, DWORD dwContext /* = 1 */)
  1655. {
  1656.     ASSERT_VALID(this);
  1657.     ASSERT(m_hConnection != NULL);
  1658.     ASSERT(AfxIsValidString(pstrRemoteFile));
  1659.     ASSERT(AfxIsValidString(pstrLocalFile));
  1660.     ASSERT(!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY));
  1661.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1662.  
  1663.     if (dwContext == 1)
  1664.         dwContext = m_dwContext;
  1665.  
  1666.     return FtpGetFile(m_hConnection, pstrRemoteFile, pstrLocalFile,
  1667.         bFailIfExists, dwAttributes, dwFlags, dwContext);
  1668. }
  1669.  
  1670. #ifdef _DEBUG
  1671. void CFtpConnection::Dump(CDumpContext& dc) const
  1672. {
  1673.     CInternetConnection::Dump(dc);
  1674.     dc << "\nm_strServerName = " << m_strServerName;
  1675. }
  1676.  
  1677. void CFtpConnection::AssertValid() const
  1678. {
  1679.     ASSERT(m_pSession != NULL);
  1680.     if (m_hConnection != NULL)
  1681.     {
  1682.         ASSERT(AfxGetInternetHandleType(m_hConnection)
  1683.                 == INTERNET_HANDLE_TYPE_CONNECT_FTP);
  1684.     }
  1685. }
  1686. #endif
  1687.  
  1688.  
  1689. /////////////////////////////////////////////////////////////////////////////
  1690. // CGopherConnection
  1691.  
  1692. CGopherConnection::~CGopherConnection()
  1693. {
  1694. }
  1695.  
  1696. CGopherConnection::CGopherConnection(CInternetSession* pSession,
  1697.     LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
  1698.     LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
  1699.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  1700.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1701. {
  1702.     ASSERT(pSession != NULL);
  1703.     ASSERT_KINDOF(CInternetSession, pSession);
  1704.     ASSERT(AfxIsValidString(pstrServer));
  1705.  
  1706.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1707.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_GOPHER,
  1708.         0, m_dwContext);
  1709.  
  1710.     if (m_hConnection == NULL)
  1711.         AfxThrowInternetException(m_dwContext);
  1712.     else
  1713.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1714. }
  1715.  
  1716. CGopherConnection::CGopherConnection(CInternetSession* pSession,
  1717.     HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
  1718.     : CInternetConnection(pSession, pstrServer,
  1719.         INTERNET_INVALID_PORT_NUMBER, dwContext)
  1720. {
  1721.     ASSERT(pSession != NULL);
  1722.     ASSERT(AfxIsValidString(pstrServer));
  1723.  
  1724.     BOOL bBadType = FALSE;
  1725.     if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_GOPHER)
  1726.     {
  1727.         ASSERT(FALSE);      // used the wrong handle type
  1728.         bBadType = TRUE;
  1729.     }
  1730.  
  1731.     m_hConnection = hConnected;
  1732.     if (m_hConnection == NULL || bBadType)
  1733.         AfxThrowInternetException(m_dwContext);
  1734.     else
  1735.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1736. }
  1737.  
  1738. CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrLocator)
  1739. {
  1740.     CGopherLocator ret(pstrLocator, lstrlen(pstrLocator));
  1741.     return ret;
  1742. }
  1743.  
  1744. CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrServerName,
  1745.     LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType,
  1746.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  1747. {
  1748.     TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
  1749.     DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
  1750.     ASSERT(AfxIsValidString(pstrDisplayString));
  1751.     ASSERT(AfxIsValidString(pstrServerName));
  1752.     ASSERT(AfxIsValidString(pstrSelectorString));
  1753.  
  1754.     if (!GopherCreateLocator(pstrServerName, nPort,
  1755.             pstrDisplayString, pstrSelectorString, dwGopherType,
  1756.             szLocator, &dwLocLen))
  1757.         AfxThrowInternetException(0);
  1758.  
  1759.     CGopherLocator ret(szLocator, dwLocLen);
  1760.     return ret;
  1761. }
  1762.  
  1763. CGopherLocator CGopherConnection::CreateLocator(
  1764.     LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType)
  1765. {
  1766.     TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
  1767.     DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
  1768.     ASSERT(AfxIsValidString(pstrDisplayString));
  1769.     ASSERT(AfxIsValidString(pstrSelectorString));
  1770.  
  1771.     if (!GopherCreateLocator(m_strServerName, m_nPort,
  1772.             pstrDisplayString, pstrSelectorString, dwGopherType,
  1773.             szLocator, &dwLocLen))
  1774.         AfxThrowInternetException(m_dwContext);
  1775.  
  1776.     CGopherLocator ret(szLocator, dwLocLen);
  1777.     return ret;
  1778. }
  1779.  
  1780.  
  1781. BOOL CGopherConnection::GetAttribute(CGopherLocator& refLocator,
  1782.     CString strRequestedAttributes, CString& strResult)
  1783. {
  1784.     DWORD dwLen = 4*MIN_GOPHER_ATTRIBUTE_LENGTH; // more than the minimum
  1785.     BOOL bRet;
  1786.     LPTSTR pstrResult = strResult.GetBuffer(dwLen);
  1787.  
  1788.     if (!GopherGetAttribute(m_hConnection, (LPCTSTR) refLocator,
  1789.             pstrResult, NULL, dwLen, &dwLen,
  1790.             NULL, m_dwContext))
  1791.     {
  1792.         bRet = FALSE;
  1793.         strResult.ReleaseBuffer(0);
  1794.     }
  1795.     else
  1796.     {
  1797.         bRet = TRUE;
  1798.         strResult.ReleaseBuffer(dwLen);
  1799.     }
  1800.  
  1801.     return bRet;
  1802. }
  1803.  
  1804. CGopherFile* CGopherConnection::OpenFile(CGopherLocator& refLocator,
  1805.     DWORD dwFlags /* = 0 */, LPCTSTR pstrView /* = NULL */,
  1806.     DWORD dwContext /* = 1 */)
  1807. {
  1808.     ASSERT_VALID(this);
  1809.     ASSERT(m_hConnection != NULL);
  1810.  
  1811.     HINTERNET hFile;
  1812.     if (dwContext == 1)
  1813.         dwContext = m_dwContext;
  1814.  
  1815.     hFile = GopherOpenFile(m_hConnection, (LPCTSTR) refLocator, pstrView,
  1816.         dwFlags, dwContext);
  1817.  
  1818.     if (hFile == NULL)
  1819.         AfxThrowInternetException(dwContext);
  1820.  
  1821.     CGopherFile* pFile = new CGopherFile(hFile, refLocator, this);
  1822.     return pFile;
  1823. }
  1824.  
  1825. void CGopherConnection::Close()
  1826. {
  1827.     CInternetConnection::Close();
  1828. }
  1829.  
  1830. #ifdef _DEBUG
  1831. void CGopherConnection::Dump(CDumpContext& dc) const
  1832. {
  1833.     CInternetConnection::Dump(dc);
  1834.     dc << "\nm_strServerName = " << m_strServerName;
  1835. }
  1836.  
  1837. void CGopherConnection::AssertValid() const
  1838. {
  1839.     ASSERT(m_pSession != NULL);
  1840.     if (m_hConnection != NULL)
  1841.     {
  1842.         ASSERT(AfxGetInternetHandleType(m_hConnection)
  1843.                 == INTERNET_HANDLE_TYPE_CONNECT_GOPHER);
  1844.     }
  1845. }
  1846. #endif
  1847.  
  1848.  
  1849. /////////////////////////////////////////////////////////////////////////////
  1850. // CHttpConnection
  1851.  
  1852. CHttpConnection::~CHttpConnection()
  1853. {
  1854. }
  1855.  
  1856. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1857.     HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext /* = 0 */)
  1858.     : CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER, dwContext)
  1859. {
  1860.     ASSERT(pSession != NULL);
  1861.     ASSERT(AfxIsValidString(pstrServer));
  1862.  
  1863.     BOOL bBadType = FALSE;
  1864.     if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_HTTP)
  1865.     {
  1866.         ASSERT(FALSE);      // used the wrong handle type
  1867.         bBadType = TRUE;
  1868.     }
  1869.  
  1870.     m_hConnection = hConnected;
  1871.     if (m_hConnection == NULL || bBadType)
  1872.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1873.     else
  1874.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1875. }
  1876.  
  1877. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1878.     LPCTSTR pstrServer,
  1879.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1880.     LPCTSTR pstrUserName /* = NULL */,
  1881.     LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 1 */)
  1882.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1883. {
  1884.     ASSERT(pSession != NULL);
  1885.     ASSERT_KINDOF(CInternetSession, pSession);
  1886.     ASSERT(AfxIsValidString(pstrServer));
  1887.  
  1888.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1889.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
  1890.         0, m_dwContext);
  1891.  
  1892.     if (m_hConnection == NULL)
  1893.         AfxThrowInternetException(m_dwContext);
  1894.     else
  1895.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1896. }
  1897.  
  1898. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1899.     LPCTSTR pstrServer, DWORD dwFlags,
  1900.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1901.     LPCTSTR pstrUserName /* = NULL */,
  1902.     LPCTSTR pstrPassword /* = NULL */,
  1903.     DWORD dwContext /* = 1 */)
  1904.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1905. {
  1906.     ASSERT(pSession != NULL);
  1907.     ASSERT_KINDOF(CInternetSession, pSession);
  1908.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1909.     ASSERT(AfxIsValidString(pstrServer));
  1910.  
  1911.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1912.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
  1913.         dwFlags, m_dwContext);
  1914.  
  1915.     if (m_hConnection == NULL)
  1916.         AfxThrowInternetException(m_dwContext);
  1917.     else
  1918.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1919. }
  1920.  
  1921. void CHttpConnection::Close()
  1922. {
  1923.     CInternetConnection::Close();
  1924. }
  1925.  
  1926. CHttpFile* CHttpConnection::OpenRequest(LPCTSTR pstrVerb,
  1927.     LPCTSTR pstrObjectName, LPCTSTR pstrReferer, DWORD dwContext,
  1928.     LPCTSTR* ppstrAcceptTypes, LPCTSTR pstrVersion, DWORD dwFlags)
  1929. {
  1930.     ASSERT_VALID(this);
  1931.     ASSERT(m_hConnection != NULL);
  1932.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1933.  
  1934.     if (dwContext == 1)
  1935.         dwContext = m_dwContext;
  1936.  
  1937.     if (pstrVersion == NULL)
  1938.         pstrVersion = HTTP_VERSION;
  1939.  
  1940.     HINTERNET hFile;
  1941.     hFile = HttpOpenRequest(m_hConnection, pstrVerb, pstrObjectName,
  1942.         pstrVersion, pstrReferer, ppstrAcceptTypes, dwFlags, dwContext);
  1943.  
  1944.     CHttpFile* pRet = new CHttpFile(hFile, pstrVerb, pstrObjectName, this);
  1945.     pRet->m_dwContext = dwContext;
  1946.     return pRet;
  1947. }
  1948.  
  1949. CHttpFile* CHttpConnection::OpenRequest(int nVerb,
  1950.     LPCTSTR pstrObjectName, LPCTSTR pstrReferer /* = NULL */, DWORD dwContext,
  1951.     LPCTSTR* ppstrAcceptTypes /* = NULL */,
  1952.     LPCTSTR pstrVersion /* = NULL */, DWORD dwFlags)
  1953. {
  1954.     ASSERT_VALID(this);
  1955.     ASSERT(m_hConnection != NULL);
  1956.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1957.     ASSERT(AfxIsValidString(pstrObjectName));
  1958.  
  1959.     ASSERT(nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX);
  1960.  
  1961.     LPCTSTR pstrVerb;
  1962.     if (nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX)
  1963.         pstrVerb = szHtmlVerbs[nVerb];
  1964.     else
  1965.         pstrVerb = _T("");
  1966.  
  1967.     return OpenRequest(pstrVerb, pstrObjectName, pstrReferer,
  1968.         dwContext, ppstrAcceptTypes, pstrVersion, dwFlags);
  1969. }
  1970.  
  1971. #ifdef _DEBUG
  1972. void CHttpConnection::Dump(CDumpContext& dc) const
  1973. {
  1974.     CInternetConnection::Dump(dc);
  1975.     dc << "\nm_strServerName = " << m_strServerName;
  1976. }
  1977.  
  1978. void CHttpConnection::AssertValid() const
  1979. {
  1980.     ASSERT(m_pSession != NULL);
  1981.     if (m_hConnection != NULL)
  1982.     {
  1983.         ASSERT(AfxGetInternetHandleType(m_hConnection)
  1984.                 == INTERNET_HANDLE_TYPE_CONNECT_HTTP);
  1985.     }
  1986. }
  1987. #endif
  1988.  
  1989.  
  1990. /////////////////////////////////////////////////////////////////////////////
  1991. // CHttpFile
  1992.  
  1993. CHttpFile::CHttpFile(HINTERNET hFile, HINTERNET hSession, LPCTSTR pstrObject,
  1994.     LPCTSTR pstrServer, LPCTSTR pstrVerb, DWORD dwContext)
  1995.  : CInternetFile(hFile, hSession, pstrObject, pstrServer, dwContext, TRUE),
  1996.     m_strVerb(pstrVerb), m_strObject(pstrObject)
  1997. {
  1998.     // caller must set _afxSessionMap!
  1999.     ASSERT(AfxIsValidString(pstrVerb));
  2000. }
  2001.  
  2002.  
  2003. CHttpFile::CHttpFile(HINTERNET hFile, LPCTSTR pstrVerb, LPCTSTR pstrObject,
  2004.     CHttpConnection* pConnection)
  2005.  : CInternetFile(hFile, pstrObject, pConnection, TRUE),
  2006.     m_strVerb(pstrVerb), m_strObject(pstrObject)
  2007. {
  2008.     ASSERT(pstrVerb != NULL);
  2009.     ASSERT(pstrObject != NULL);
  2010.     ASSERT(pConnection != NULL);
  2011.     ASSERT_VALID(pConnection);
  2012. }
  2013.  
  2014. CHttpFile::~CHttpFile()
  2015. {
  2016. }
  2017.  
  2018. void CHttpFile::Close()
  2019. {
  2020.     CInternetFile::Close();
  2021. }
  2022.  
  2023. DWORD CHttpFile::ErrorDlg(CWnd* pParent /* = NULL */,
  2024.     DWORD dwError /* = ERROR_INTERNET_INCORRECT_PASSWORD */,
  2025.     DWORD dwFlags /* = FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS*/,
  2026.     LPVOID* lppvData /* = NULL */)
  2027. {
  2028.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2029.     HWND hWnd;
  2030.     LPVOID lpEmpty;
  2031.     LPVOID* lppvHolder;
  2032.  
  2033.     if (lppvData == NULL)
  2034.     {
  2035.         lpEmpty = NULL;
  2036.         lppvHolder = &lpEmpty;
  2037.     }
  2038.     else
  2039.         lppvHolder = lppvData;
  2040.  
  2041.     if (pParent == NULL || pParent->m_hWnd == NULL)
  2042.         hWnd = GetDesktopWindow();
  2043.     else
  2044.         hWnd = pParent->m_hWnd;
  2045.  
  2046.     return InternetErrorDlg(hWnd, m_hFile, dwError, dwFlags, lppvHolder);
  2047. }
  2048.  
  2049. CString CHttpFile::GetVerb() const
  2050. {
  2051.     ASSERT_VALID(this);
  2052.     ASSERT(m_hFile != NULL);
  2053.  
  2054.     return m_strVerb;
  2055. }
  2056.  
  2057. CString CHttpFile::GetObject() const
  2058. {
  2059.     ASSERT_VALID(this);
  2060.     ASSERT(m_hFile != NULL);
  2061.  
  2062.     return m_strObject;
  2063. }
  2064.  
  2065. CString CHttpFile::GetFileURL() const
  2066. {
  2067.     ASSERT_VALID(this);
  2068.     ASSERT(m_hFile != NULL);
  2069.  
  2070.     CString str(_afxURLhttp);
  2071.     if (m_hConnection != NULL)
  2072.     {
  2073.         str += m_strServerName;
  2074.         int nLen = m_strObject.GetLength();
  2075.         if (nLen > 0)
  2076.         {
  2077.             if (m_strObject[0] != '/' && m_strObject[0] != '\\')
  2078.                 str += '/';
  2079.             str += m_strObject;
  2080.         }
  2081.     }
  2082.  
  2083.     return str;
  2084. }
  2085.  
  2086. BOOL CHttpFile::AddRequestHeaders(LPCTSTR pstrHeaders,
  2087.     DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */,
  2088.     int dwHeadersLen /* = -1 */)
  2089. {
  2090.     ASSERT(AfxIsValidString(pstrHeaders));
  2091.     ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
  2092.     ASSERT_VALID(this);
  2093.     ASSERT(m_hFile != NULL);
  2094.  
  2095.     if (dwHeadersLen == -1)
  2096.         if (pstrHeaders == NULL)
  2097.             dwHeadersLen = 0;
  2098.         else
  2099.             dwHeadersLen = lstrlen(pstrHeaders);
  2100.  
  2101.     return HttpAddRequestHeaders(m_hFile, pstrHeaders, dwHeadersLen,
  2102.         dwModifiers);
  2103. }
  2104.  
  2105. BOOL CHttpFile::AddRequestHeaders(CString& str,
  2106.     DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */)
  2107. {
  2108.     return AddRequestHeaders((LPCTSTR) str, dwModifiers, str.GetLength());
  2109. }
  2110.  
  2111. BOOL CHttpFile::SendRequest(LPCTSTR pstrHeaders /* = NULL */,
  2112.     DWORD dwHeadersLen /* = 0 */, LPVOID lpOptional /* = NULL */,
  2113.     DWORD dwOptionalLen /* = 0 */)
  2114. {
  2115.     ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
  2116.     ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
  2117.     ASSERT_VALID(this);
  2118.     ASSERT(m_hFile != NULL);
  2119.  
  2120.     BOOL bRet = HttpSendRequest(m_hFile,
  2121.         pstrHeaders, dwHeadersLen, lpOptional, dwOptionalLen);
  2122.  
  2123.     if (!bRet)
  2124.         AfxThrowInternetException(m_dwContext);
  2125.  
  2126.     return bRet;
  2127. }
  2128.  
  2129. BOOL CHttpFile::EndRequest(
  2130.     DWORD dwFlags /* = 0 */,
  2131.     LPINTERNET_BUFFERS lpBuffIn /* = NULL */, DWORD dwContext /* = 1 */)
  2132. {
  2133.     ASSERT(m_hFile != NULL);
  2134.     ASSERT(m_bReadMode == -1);
  2135.  
  2136.     if (dwContext == 1)
  2137.         dwContext = m_dwContext;
  2138.  
  2139.     BOOL bRet = HttpEndRequest(m_hFile, lpBuffIn, dwFlags, dwContext);
  2140.  
  2141.     if (!bRet)
  2142.         AfxThrowInternetException(m_dwContext);
  2143.     return bRet;
  2144. }
  2145.  
  2146. BOOL CHttpFile::SendRequestEx(DWORD dwTotalLen,
  2147.     DWORD dwFlags /* = HSR_INITIATE */, DWORD dwContext /* = 1 */)
  2148. {
  2149.     ASSERT(m_hFile != NULL);
  2150.  
  2151.     INTERNET_BUFFERS buffer;
  2152.     memset(&buffer, 0, sizeof(buffer));
  2153.     buffer.dwStructSize = sizeof(buffer);
  2154.     buffer.dwBufferTotal = dwTotalLen;
  2155.  
  2156.     if (dwContext == 1)
  2157.         dwContext = m_dwContext;
  2158.  
  2159.     return SendRequestEx(&buffer, NULL, dwFlags, dwContext);
  2160. }
  2161.  
  2162. BOOL CHttpFile::SendRequestEx(LPINTERNET_BUFFERS lpBuffIn,
  2163.     LPINTERNET_BUFFERS lpBuffOut, DWORD dwFlags /* = HSR_INITIATE */,
  2164.     DWORD dwContext /* = 1 */)
  2165. {
  2166.     ASSERT(m_hFile != NULL);
  2167.     ASSERT_NULL_OR_POINTER(lpBuffIn, INTERNET_BUFFERS);
  2168.     ASSERT_NULL_OR_POINTER(lpBuffOut, INTERNET_BUFFERS);
  2169.  
  2170.     if (dwContext == 1)
  2171.         dwContext = m_dwContext;
  2172.  
  2173.     BOOL bRet = HttpSendRequestEx(m_hFile, lpBuffIn, lpBuffOut,
  2174.         dwFlags, dwContext);
  2175.  
  2176.     if (!bRet)
  2177.         AfxThrowInternetException(m_dwContext);
  2178.  
  2179.     m_bReadMode = -1;
  2180.     return bRet;
  2181. }
  2182.  
  2183. BOOL CHttpFile::SendRequest(CString& strHeaders,
  2184.     LPVOID lpOptional /* = NULL */, DWORD dwOptionalLen /* = 0 */)
  2185. {
  2186.     ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
  2187.     ASSERT_VALID(this);
  2188.     ASSERT(m_hFile != NULL);
  2189.  
  2190.     return SendRequest((LPCTSTR) strHeaders, strHeaders.GetLength(),
  2191.         lpOptional, dwOptionalLen);
  2192. }
  2193.  
  2194. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel,
  2195.     LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex) const
  2196. {
  2197.     ASSERT((HTTP_QUERY_HEADER_MASK & dwInfoLevel) <= HTTP_QUERY_MAX &&
  2198.         dwInfoLevel != 0);
  2199.     ASSERT(lpvBuffer != NULL && *lpdwBufferLength > 0);
  2200.     ASSERT_VALID(this);
  2201.     ASSERT(m_hFile != NULL);
  2202.  
  2203.     return HttpQueryInfo(m_hFile, dwInfoLevel, lpvBuffer,
  2204.         lpdwBufferLength, lpdwIndex);
  2205. }
  2206.  
  2207. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, DWORD& dwResult,
  2208.     LPDWORD lpdwIndex /* = NULL */) const
  2209. {
  2210.     dwInfoLevel |= HTTP_QUERY_FLAG_NUMBER;
  2211.     DWORD dwDWSize = sizeof(DWORD);
  2212.     return QueryInfo(dwInfoLevel, &dwResult, &dwDWSize, lpdwIndex);
  2213. }
  2214.  
  2215. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, SYSTEMTIME* pSystemTime,
  2216.     LPDWORD lpdwIndex /* = NULL */) const
  2217. {
  2218.     dwInfoLevel |= HTTP_QUERY_FLAG_SYSTEMTIME;
  2219.     DWORD dwTimeSize = sizeof(SYSTEMTIME);
  2220.     return QueryInfo(dwInfoLevel, pSystemTime, &dwTimeSize, lpdwIndex);
  2221. }
  2222.  
  2223. BOOL CHttpFile::QueryInfoStatusCode(DWORD& dwStatusCode) const
  2224. {
  2225.     ASSERT_VALID(this);
  2226.     ASSERT(m_hFile != NULL);
  2227.  
  2228.     TCHAR szBuffer[80];
  2229.     DWORD dwLen = _countof(szBuffer);
  2230.     BOOL bRet;
  2231.  
  2232.     bRet = HttpQueryInfo(m_hFile, HTTP_QUERY_STATUS_CODE,
  2233.                 szBuffer, &dwLen, NULL);
  2234.  
  2235.     if (bRet)
  2236.         dwStatusCode = (DWORD) _ttol(szBuffer);
  2237.     return bRet;
  2238. }
  2239.  
  2240. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, CString& str,
  2241.     LPDWORD lpdwIndex) const
  2242. {
  2243.     ASSERT(dwInfoLevel <= HTTP_QUERY_MAX && dwInfoLevel >= 0);
  2244.     ASSERT_VALID(this);
  2245.     ASSERT(m_hFile != NULL);
  2246.  
  2247.     BOOL bRet;
  2248.     DWORD dwLen = 0;
  2249.  
  2250.     // ask for nothing to see how long the return really is
  2251.  
  2252.     str.Empty();
  2253.     if (HttpQueryInfo(m_hFile, dwInfoLevel, NULL, &dwLen, 0))
  2254.         bRet = TRUE;
  2255.     else
  2256.     {
  2257.         // now that we know how long it is, ask for exactly that much
  2258.         // space and really request the header from the API
  2259.  
  2260.         LPTSTR pstr = str.GetBufferSetLength(dwLen);
  2261.         bRet = HttpQueryInfo(m_hFile, dwInfoLevel, pstr, &dwLen, lpdwIndex);
  2262.         if (bRet)
  2263.             str.ReleaseBuffer(dwLen);
  2264.         else
  2265.             str.ReleaseBuffer(0);
  2266.     }
  2267.  
  2268.     return bRet;
  2269. }
  2270.  
  2271. #ifdef _DEBUG
  2272. void CHttpFile::Dump(CDumpContext& dc) const
  2273. {
  2274.     dc << "\nm_strFileName = " << m_strFileName;
  2275.     dc << "\nm_strVerb = " << m_strVerb;
  2276. }
  2277.  
  2278. void CHttpFile::AssertValid() const
  2279. {
  2280.     CInternetFile::AssertValid();
  2281. }
  2282. #endif
  2283.  
  2284. /////////////////////////////////////////////////////////////////////////////
  2285. // CGopherFile
  2286.  
  2287. CGopherFile::CGopherFile(HINTERNET hFile, CGopherLocator& refLocator,
  2288.     CGopherConnection* pConnection)
  2289.     : CInternetFile(hFile, _T(""), pConnection, TRUE),
  2290.         m_Locator(refLocator)
  2291. {
  2292.     ASSERT(pConnection != NULL);
  2293.     ASSERT_VALID(pConnection);
  2294. }
  2295.  
  2296. CGopherFile::CGopherFile(HINTERNET hFile, HINTERNET hSession,
  2297.     LPCTSTR pstrLocator, DWORD dwLocLen, DWORD dwContext)
  2298.     : CInternetFile(hFile, hSession, _T(""), _T(""), dwContext, TRUE),
  2299.         m_Locator(pstrLocator, dwLocLen)
  2300. {
  2301.     // caller muset set _afxSessionMap!
  2302. }
  2303.  
  2304. CGopherFile::~CGopherFile()
  2305. {
  2306. }
  2307.  
  2308. void CGopherFile::Close()
  2309. {
  2310.     CInternetFile::Close();
  2311. }
  2312.  
  2313. void CGopherFile::Write(const void* lpBuf, UINT nCount)
  2314. {
  2315.     UNUSED_ALWAYS(lpBuf);
  2316.     UNUSED_ALWAYS(nCount);
  2317.  
  2318.     ASSERT(FALSE);
  2319.     AfxThrowNotSupportedException();
  2320. }
  2321.  
  2322. void CGopherFile::WriteString(LPCTSTR pstr)
  2323. {
  2324.     UNUSED_ALWAYS(pstr);
  2325.  
  2326.     ASSERT(FALSE);
  2327.     AfxThrowNotSupportedException();
  2328. }
  2329.  
  2330. #ifdef _DEBUG
  2331. void CGopherFile::Dump(CDumpContext& dc) const
  2332. {
  2333.     CInternetFile::Dump(dc);
  2334. }
  2335.  
  2336. void CGopherFile::AssertValid() const
  2337. {
  2338.     CInternetFile::AssertValid();
  2339. }
  2340. #endif
  2341.  
  2342. /////////////////////////////////////////////////////////////////////////////
  2343. // CFtpFileFind
  2344.  
  2345. CFtpFileFind::CFtpFileFind(CFtpConnection* pConnection, DWORD dwContext)
  2346. {
  2347.     ASSERT(pConnection != NULL);
  2348.     ASSERT_KINDOF(CFtpConnection, pConnection);
  2349.  
  2350.     m_pConnection = pConnection;
  2351.     if (dwContext == 1)
  2352.         dwContext = pConnection->GetContext();
  2353.     m_dwContext = dwContext;
  2354.     m_chDirSeparator = '/';
  2355. }
  2356.  
  2357. CFtpFileFind::~CFtpFileFind()
  2358. {
  2359. }
  2360.  
  2361. BOOL CFtpFileFind::FindFile(LPCTSTR pstrName /* = NULL */,
  2362.     DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2363. {
  2364.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2365.     ASSERT(m_pConnection != NULL);
  2366.     ASSERT_VALID(m_pConnection);
  2367.  
  2368.     if (m_pConnection == NULL)
  2369.         return FALSE;
  2370.  
  2371.     Close();
  2372.     m_pNextInfo = new WIN32_FIND_DATA;
  2373.     m_bGotLast = FALSE;
  2374.  
  2375.     if (pstrName == NULL)
  2376.         pstrName = _T("*");
  2377.     lstrcpy(((LPWIN32_FIND_DATA) m_pNextInfo)->cFileName, pstrName);
  2378.  
  2379.     m_hContext = FtpFindFirstFile((HINTERNET) *m_pConnection,
  2380.         pstrName, (LPWIN32_FIND_DATA) m_pNextInfo, dwFlags, m_dwContext);
  2381.  
  2382.     if (m_hContext == NULL)
  2383.     {
  2384.         Close();
  2385.         return FALSE;
  2386.     }
  2387.  
  2388.     LPCTSTR pstrRoot = _tcspbrk(pstrName, _T("\\/"));
  2389.     CString strCWD;
  2390.     m_pConnection->GetCurrentDirectory(strCWD);
  2391.  
  2392.     if (pstrRoot == NULL)
  2393.     {
  2394.         if (m_pConnection->SetCurrentDirectory(pstrName))
  2395.         {
  2396.             m_pConnection->GetCurrentDirectory(m_strRoot);
  2397.             m_pConnection->SetCurrentDirectory(strCWD);
  2398.         }
  2399.         else
  2400.             m_strRoot = strCWD;
  2401.     }
  2402.     else
  2403.     {
  2404.         // find the last forward or backward whack
  2405.  
  2406.         int nLast;
  2407.         LPCTSTR pstrOther = _tcsrchr(pstrName, '\\');
  2408.         pstrRoot = _tcsrchr(pstrName, '/');
  2409.  
  2410.         if (pstrRoot == NULL)
  2411.             pstrRoot = pstrName;
  2412.         if (pstrOther == NULL)
  2413.             pstrOther = pstrName;
  2414.  
  2415.         if (pstrRoot >= pstrOther)
  2416.             nLast = pstrRoot - pstrName;
  2417.         else
  2418.             nLast = pstrOther - pstrName;
  2419.  
  2420.         // from the start to the last whack is the root
  2421.  
  2422.         if (nLast == 0)
  2423.             nLast++;
  2424.  
  2425.         m_strRoot = pstrName;
  2426.         m_strRoot = m_strRoot.Left(nLast);
  2427.     }
  2428.  
  2429.     return TRUE;
  2430. }
  2431.  
  2432. BOOL CFtpFileFind::FindNextFile()
  2433. {
  2434.     ASSERT(m_hContext != NULL);
  2435.     if (m_hContext == NULL)
  2436.         return FALSE;
  2437.  
  2438.     if (m_pFoundInfo == NULL)
  2439.         m_pFoundInfo = new WIN32_FIND_DATA;
  2440.  
  2441.     ASSERT_VALID(this);
  2442.     void* pTemp = m_pFoundInfo;
  2443.     m_pFoundInfo = m_pNextInfo;
  2444.     m_pNextInfo = pTemp;
  2445.  
  2446.     return InternetFindNextFile(m_hContext, m_pNextInfo);
  2447. }
  2448.  
  2449. void CFtpFileFind::CloseContext()
  2450. {
  2451.     if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
  2452.     {
  2453.         InternetCloseHandle(m_hContext);
  2454.         m_hContext = NULL;
  2455.     }
  2456.  
  2457.     return;
  2458. }
  2459.  
  2460. CString CFtpFileFind::GetFileURL() const
  2461. {
  2462.     ASSERT_VALID(this);
  2463.     ASSERT(m_hContext != NULL);
  2464.  
  2465.     CString str;
  2466.  
  2467.     if (m_hContext != NULL)
  2468.     {
  2469.         str += _afxURLftp;
  2470.         str += m_pConnection->GetServerName();
  2471.         str += GetFilePath();
  2472.     }
  2473.  
  2474.     return str;
  2475. }
  2476.  
  2477. #ifdef _DEBUG
  2478. void CFtpFileFind::Dump(CDumpContext& dc) const
  2479. {
  2480.     CFileFind::Dump(dc);
  2481.     dc << "m_hContext = " << m_hContext;
  2482. }
  2483.  
  2484. void CFtpFileFind::AssertValid() const
  2485. {
  2486.     CFileFind::AssertValid();
  2487. }
  2488. #endif
  2489.  
  2490.  
  2491. /////////////////////////////////////////////////////////////////////////////
  2492. // CGopherFileFind
  2493.  
  2494. CGopherFileFind::CGopherFileFind(CGopherConnection* pConnection,
  2495.     DWORD dwContext)
  2496. {
  2497.     ASSERT(pConnection != NULL);
  2498.     ASSERT_KINDOF(CGopherConnection, pConnection);
  2499.  
  2500.     m_pConnection = pConnection;
  2501.     if (dwContext == 1)
  2502.         dwContext = pConnection->GetContext();
  2503.     m_dwContext = dwContext;
  2504. }
  2505.  
  2506. CGopherFileFind::~CGopherFileFind()
  2507. {
  2508. }
  2509.  
  2510. BOOL CGopherFileFind::FindFile(LPCTSTR pstrString,
  2511.     DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2512. {
  2513.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2514.     Close();
  2515.  
  2516.     m_pNextInfo = new GOPHER_FIND_DATA;
  2517.     m_bGotLast = FALSE;
  2518.  
  2519.     m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
  2520.         NULL, pstrString,
  2521.         (GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
  2522.  
  2523.     if (m_hContext == NULL)
  2524.         Close();
  2525.     return (m_hContext != NULL);
  2526. }
  2527.  
  2528. BOOL CGopherFileFind::FindFile(CGopherLocator& refLocator,
  2529.     LPCTSTR pstrString, DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2530. {
  2531.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2532.     Close();
  2533.  
  2534.     m_pNextInfo = new GOPHER_FIND_DATA;
  2535.     m_pFoundInfo = new GOPHER_FIND_DATA;
  2536.     m_bGotLast = FALSE;
  2537.  
  2538.     m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
  2539.         (LPCTSTR) refLocator, pstrString,
  2540.         (GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
  2541.  
  2542.     if (m_hContext == NULL)
  2543.         Close();
  2544.     return (m_hContext != NULL);
  2545. }
  2546.  
  2547. BOOL CGopherFileFind::FindNextFile()
  2548. {
  2549.     ASSERT(m_hContext != NULL);
  2550.     if (m_hContext == NULL)
  2551.         return FALSE;
  2552.  
  2553.     if (m_pFoundInfo == NULL)
  2554.         m_pFoundInfo = new GOPHER_FIND_DATA;
  2555.  
  2556.     ASSERT_VALID(this);
  2557.     void* pTemp = m_pFoundInfo;
  2558.     m_pFoundInfo = m_pNextInfo;
  2559.     m_pNextInfo = pTemp;
  2560.  
  2561.     return InternetFindNextFile(m_hContext, m_pNextInfo);
  2562. }
  2563.  
  2564. void CGopherFileFind::CloseContext()
  2565. {
  2566.     if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
  2567.     {
  2568.         InternetCloseHandle(m_hContext);
  2569.         m_hContext = NULL;
  2570.     }
  2571.  
  2572.     return;
  2573. }
  2574.  
  2575. CString CGopherFileFind::GetFileName() const
  2576. {
  2577.     AfxThrowNotSupportedException();
  2578.     return CString();
  2579. }
  2580.  
  2581. CString CGopherFileFind::GetFilePath() const
  2582. {
  2583.     AfxThrowNotSupportedException();
  2584.     return CString();
  2585. }
  2586.  
  2587. CString CGopherFileFind::GetFileTitle() const
  2588. {
  2589.     AfxThrowNotSupportedException();
  2590.     return CString();
  2591. }
  2592.  
  2593. BOOL CGopherFileFind::IsDots() const
  2594. {
  2595.     // gophers never have dots
  2596.     return FALSE;
  2597. }
  2598.  
  2599. BOOL CGopherFileFind::GetLastWriteTime(FILETIME* pTimeStamp) const
  2600. {
  2601.     ASSERT(m_hContext != NULL);
  2602.     ASSERT_POINTER(pTimeStamp, FILETIME);
  2603.     ASSERT_VALID(this);
  2604.  
  2605.     if (m_pFoundInfo != NULL && pTimeStamp != NULL)
  2606.     {
  2607.         *pTimeStamp = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime;
  2608.         return TRUE;
  2609.     }
  2610.     else
  2611.         return FALSE;
  2612. }
  2613.  
  2614. BOOL CGopherFileFind::GetLastAccessTime(FILETIME* pTimeStamp) const
  2615. {
  2616.     ASSERT_POINTER(pTimeStamp, FILETIME);
  2617.     return GetLastWriteTime(pTimeStamp);
  2618. }
  2619.  
  2620. BOOL CGopherFileFind::GetCreationTime(FILETIME* pTimeStamp) const
  2621. {
  2622.     ASSERT_POINTER(pTimeStamp, FILETIME);
  2623.     return GetLastWriteTime(pTimeStamp);
  2624. }
  2625.  
  2626. BOOL CGopherFileFind::GetLastWriteTime(CTime& refTime) const
  2627. {
  2628.     ASSERT(m_hContext != NULL);
  2629.     ASSERT_VALID(this);
  2630.  
  2631.     if (m_pFoundInfo != NULL)
  2632.     {
  2633.         refTime = CTime(((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime);
  2634.         return TRUE;
  2635.     }
  2636.     else
  2637.         return FALSE;
  2638. }
  2639.  
  2640. BOOL CGopherFileFind::GetCreationTime(CTime& refTime) const
  2641. {
  2642.     return GetLastWriteTime(refTime);
  2643. }
  2644.  
  2645. BOOL CGopherFileFind::GetLastAccessTime(CTime& refTime) const
  2646. {
  2647.     return GetLastWriteTime(refTime);
  2648. }
  2649.  
  2650.  
  2651. CString CGopherFileFind::GetFileURL() const
  2652. {
  2653.     AfxThrowNotSupportedException();
  2654.     return CString();
  2655. }
  2656.  
  2657. CString CGopherFileFind::GetRoot() const
  2658. {
  2659.     AfxThrowNotSupportedException();
  2660.     return CString();
  2661. }
  2662.  
  2663. CGopherLocator CGopherFileFind::GetLocator() const
  2664. {
  2665.     ASSERT_VALID(this);
  2666.     ASSERT(m_pConnection != NULL && m_hContext != NULL);
  2667.  
  2668.     return m_pConnection->CreateLocator(
  2669.         ((LPGOPHER_FIND_DATA) m_pFoundInfo)->Locator);
  2670. }
  2671.  
  2672. CString CGopherFileFind::GetScreenName() const
  2673. {
  2674.     ASSERT_VALID(this);
  2675.     ASSERT(m_hContext != NULL);
  2676.  
  2677.     CString str;
  2678.  
  2679.     if (m_pFoundInfo != NULL)
  2680.         str = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->DisplayString;
  2681.  
  2682.     return str;
  2683. }
  2684.  
  2685. DWORD CGopherFileFind::GetLength() const
  2686. {
  2687.     ASSERT_VALID(this);
  2688.  
  2689.     if (m_pFoundInfo != NULL)
  2690.         return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow;
  2691.     else
  2692.         return 0;
  2693. }
  2694.  
  2695. #if defined(_X86_) || defined(_ALPHA_)
  2696. __int64 CGopherFileFind::GetLength64() const
  2697. {
  2698.     ASSERT_VALID(this);
  2699.  
  2700.     if (m_pFoundInfo != NULL)
  2701.         return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow +
  2702.                 (((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeHigh << 32);
  2703.     else
  2704.         return 0;
  2705. }
  2706. #endif
  2707.  
  2708. #ifdef _DEBUG
  2709. void CGopherFileFind::Dump(CDumpContext& dc) const
  2710. {
  2711.     CFileFind::Dump(dc);
  2712.     dc << "m_hContext = " << m_hContext;
  2713. }
  2714.  
  2715. void CGopherFileFind::AssertValid() const
  2716. {
  2717.     CFileFind::AssertValid();
  2718. }
  2719. #endif
  2720.  
  2721.  
  2722. /////////////////////////////////////////////////////////////////////////////
  2723. // CGopherLocator
  2724.  
  2725. CGopherLocator::CGopherLocator(LPCTSTR pstrLocator, DWORD dwLocLen)
  2726. {
  2727.     ASSERT(AfxIsValidString(pstrLocator));
  2728.     LPTSTR pstr = m_Locator.GetBufferSetLength(dwLocLen);
  2729.     memcpy(pstr, pstrLocator, dwLocLen);
  2730.     m_Locator.ReleaseBuffer(dwLocLen);
  2731.     m_dwBufferLength = dwLocLen;
  2732. }
  2733.  
  2734. CGopherLocator::~CGopherLocator()
  2735. {
  2736. }
  2737.  
  2738. /////////////////////////////////////////////////////////////////////////////
  2739. // exception handling
  2740.  
  2741. void AFXAPI AfxThrowInternetException(DWORD dwContext, DWORD dwError /* = 0 */)
  2742. {
  2743.     if (dwError == 0)
  2744.         dwError = ::GetLastError();
  2745.  
  2746.     CInternetException* pException = new CInternetException(dwError);
  2747.     pException->m_dwContext = dwContext;
  2748.  
  2749.     TRACE1("Warning: throwing CInternetException for error %d\n", dwError);
  2750.     THROW(pException);
  2751. }
  2752.  
  2753.  
  2754. BOOL CInternetException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError,
  2755.         PUINT pnHelpContext)
  2756. {
  2757.     ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
  2758.  
  2759.     if (pnHelpContext != NULL)
  2760.         *pnHelpContext = 0;
  2761.  
  2762.     LPTSTR lpBuffer;
  2763.     BOOL bRet = TRUE;
  2764.  
  2765.     HINSTANCE hWinINetLibrary;
  2766.     hWinINetLibrary = ::LoadLibraryA("WININET.DLL");
  2767.  
  2768.     if (hWinINetLibrary == NULL ||
  2769.         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  2770.             hWinINetLibrary, m_dwError,
  2771.             MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  2772.             (LPTSTR) &lpBuffer, 0, NULL) == 0)
  2773.     {
  2774.         // it failed! try Windows...
  2775.  
  2776.         bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  2777.             NULL,  m_dwError,
  2778.             MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  2779.             (LPTSTR) &lpBuffer, 0, NULL);
  2780.     }
  2781.  
  2782.     if (!bRet)
  2783.         *pstrError = '\0';
  2784.     else
  2785.     {
  2786.         if (m_dwError == ERROR_INTERNET_EXTENDED_ERROR)
  2787.         {
  2788.             LPTSTR lpExtended;
  2789.             DWORD dwLength = 0;
  2790.             DWORD dwError;
  2791.  
  2792.             // find the length of the error
  2793.             if (!InternetGetLastResponseInfo(&dwError, NULL, &dwLength) &&
  2794.                 GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2795.             {
  2796.                 lpExtended = (LPTSTR) LocalAlloc(LPTR, dwLength);
  2797.                 InternetGetLastResponseInfo(&dwError, lpExtended, &dwLength);
  2798.                 lstrcpyn(pstrError, lpExtended, nMaxError);
  2799.                 pstrError += dwLength;
  2800.                 nMaxError -= dwLength;
  2801.                 if (nMaxError < 0)
  2802.                     nMaxError = 0;
  2803.                 LocalFree(lpExtended);
  2804.             }
  2805.             else
  2806.                 TRACE0("Warning: Extended error reported with no response info\n");
  2807.             bRet = TRUE;
  2808.         }
  2809.         else
  2810.         {
  2811.             lstrcpyn(pstrError, lpBuffer, nMaxError);
  2812.             bRet = TRUE;
  2813.         }
  2814.  
  2815.         LocalFree(lpBuffer);
  2816.     }
  2817.  
  2818. #ifndef _AFXDLL
  2819.     ::FreeLibrary(hWinINetLibrary);
  2820. #endif
  2821.     return bRet;
  2822. }
  2823.  
  2824. CInternetException::CInternetException(DWORD dwError)
  2825. {
  2826.     m_dwError = dwError;
  2827. }
  2828.  
  2829. CInternetException::~CInternetException()
  2830. {
  2831. }
  2832.  
  2833. #ifdef _DEBUG
  2834. void CInternetException::Dump(CDumpContext& dc) const
  2835. {
  2836.     CObject::Dump(dc);
  2837.  
  2838.     dc << "m_dwError = " << m_dwError;
  2839.     dc << "\nm_dwContext = " << m_dwContext;
  2840. }
  2841. #endif
  2842.  
  2843. /////////////////////////////////////////////////////////////////////////////
  2844. // Inline function declarations expanded out-of-line
  2845.  
  2846. #ifndef _AFX_ENABLE_INLINES
  2847.  
  2848. // expand inlines for OLE dialog APIs
  2849. static char _szAfxInetInl[] = "afxinet.inl";
  2850. #undef THIS_FILE
  2851. #define THIS_FILE _szAfxInetInl
  2852. #define _AFXINET_INLINE
  2853. #include "afxinet.inl"
  2854.  
  2855. #endif //!_AFX_ENABLE_INLINES
  2856.  
  2857. /////////////////////////////////////////////////////////////////////////////
  2858. // Pre-startup code
  2859.  
  2860. #ifdef AFX_INIT_SEG
  2861. #pragma code_seg(AFX_INIT_SEG)
  2862. #endif
  2863.  
  2864. IMPLEMENT_DYNAMIC(CInternetException, CException)
  2865. IMPLEMENT_DYNAMIC(CInternetFile, CStdioFile)
  2866. IMPLEMENT_DYNAMIC(CHttpFile, CInternetFile)
  2867. IMPLEMENT_DYNAMIC(CGopherFile, CInternetFile)
  2868. IMPLEMENT_DYNAMIC(CInternetSession, CObject)
  2869. IMPLEMENT_DYNAMIC(CInternetConnection, CObject)
  2870. IMPLEMENT_DYNAMIC(CFtpConnection, CInternetConnection)
  2871. IMPLEMENT_DYNAMIC(CHttpConnection, CInternetConnection)
  2872. IMPLEMENT_DYNAMIC(CGopherConnection, CInternetConnection)
  2873. IMPLEMENT_DYNAMIC(CFtpFileFind, CFileFind)
  2874. IMPLEMENT_DYNAMIC(CGopherFileFind, CFileFind)
  2875.  
  2876. #pragma warning(disable: 4074)
  2877. #pragma init_seg(compiler)
  2878.  
  2879. CSessionMapPtrToPtr _afxSessionMap;
  2880.