home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / internet / wwwquote / wwwquote.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  11.0 KB  |  456 lines

  1. // WWWQuote.cpp : Defines the initialization routines for the DLL.
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "WWWQuote.h"
  15. #include "Queries.h"
  16.  
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CWWWQuoteApp
  25.  
  26. BEGIN_MESSAGE_MAP(CWWWQuoteApp, CWinApp)
  27.     //{{AFX_MSG_MAP(CWWWQuoteApp)
  28.         // NOTE - the ClassWizard will add and remove mapping macros here.
  29.         //    DO NOT EDIT what you see in these blocks of generated code!
  30.     //}}AFX_MSG_MAP
  31. END_MESSAGE_MAP()
  32.  
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CWWWQuoteApp construction
  35.  
  36. CWWWQuoteApp::CWWWQuoteApp()
  37. {
  38.     // TODO: add construction code here,
  39.     // Place all significant initialization in InitInstance
  40. }
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // The one and only CWWWQuoteApp object
  44.  
  45. CWWWQuoteApp theApp;
  46.  
  47.  
  48. // Database logins
  49. // and resource type names
  50. // these are some of our
  51. // favorite strings
  52.  
  53. // You might need to change szConnectString to be appropriate for your
  54. // database and database server.
  55.  
  56. static const TCHAR szConnectString[] = _T("UID=sa;PWD=;");
  57. static const TCHAR szHTMLType[] = _T("CustomHTML");
  58.  
  59.  
  60. /////////////////////////////////////////////////////////////////////////////
  61. //
  62.  
  63. CWWWQuote theExtension;
  64.  
  65. BEGIN_PARSE_MAP(CWWWQuote, CHttpServer)
  66.     DEFAULT_PARSE_COMMAND(Quote, CWWWQuote)
  67.     ON_PARSE_COMMAND(Quote, CWWWQuote, ITS_EMPTY)
  68.     ON_PARSE_COMMAND(Issues, CWWWQuote, ITS_PSTR)
  69.     ON_PARSE_COMMAND_PARAMS("Method")
  70.     ON_PARSE_COMMAND(GetQuotes, CWWWQuote, ITS_PSTR ITS_I4
  71.         ITS_I4 ITS_I4 ITS_I4 ITS_I4 ITS_I4)
  72.     ON_PARSE_COMMAND_PARAMS("Ticker=~ Month=0 Year=0 MinMonth=0 MinYear=0 MaxMonth=0 MaxYear=0")
  73.     ON_PARSE_COMMAND(PreviousMonth, CWWWQuote, ITS_PSTR ITS_I4 ITS_I4 ITS_I4 ITS_I4 ITS_I4 ITS_I4)
  74.     ON_PARSE_COMMAND_PARAMS("Ticker Month Year MinMonth MinYear MaxMonth MaxYear")
  75.     ON_PARSE_COMMAND(NextMonth, CWWWQuote, ITS_PSTR ITS_I4 ITS_I4 ITS_I4 ITS_I4 ITS_I4 ITS_I4)
  76.     ON_PARSE_COMMAND_PARAMS("Ticker Month Year MinMonth MinYear MaxMonth MaxYear")
  77. END_PARSE_MAP(CWWWQuote)
  78.  
  79. CWWWQuote::CWWWQuote()
  80. {
  81. }
  82.  
  83. CWWWQuote::~CWWWQuote()
  84. {
  85. }
  86.  
  87. BOOL CWWWQuote::LoadLongResource(CString& str, UINT nID)
  88. {
  89.     HRSRC hRes;
  90.     HINSTANCE hInst = AfxGetResourceHandle();
  91.     BOOL bResult = FALSE;
  92.  
  93.     hRes = FindResource(hInst, MAKEINTRESOURCE(nID), szHTMLType);
  94.     if (hRes == NULL)
  95.         ISAPITRACE1("Error: Resource %d could not be found\r\n", nID);
  96.     else
  97.     {
  98.         DWORD dwSize = SizeofResource(hInst, hRes);
  99.         if (dwSize == 0)
  100.         {
  101.             str.Empty();
  102.             bResult = TRUE;
  103.         }
  104.         else
  105.         {
  106.             LPTSTR pszStorage = str.GetBufferSetLength(dwSize);
  107.  
  108.             HGLOBAL hGlob = LoadResource(hInst, hRes);
  109.             if (hGlob != NULL)
  110.             {
  111.                 LPVOID lpData = LockResource(hGlob);
  112.  
  113.                 if (lpData != NULL)
  114.                 {
  115.                     memcpy(pszStorage, lpData, dwSize);
  116.                     bResult = TRUE;
  117.                 }
  118.  
  119.                 FreeResource(hGlob);
  120.             }
  121.         }
  122.     }
  123.  
  124. #ifdef _DEBUG
  125.     if (!bResult)
  126.         str.Format(_T("<b>Could not find string %d</b>"), nID);
  127. #endif
  128.  
  129.     return bResult;
  130. }
  131.  
  132. void CWWWQuote::WritePageTitle(CHttpServerContext* pCtxt, UINT nID)
  133. {
  134.     CString strTitle;
  135.     CString strAddOn;
  136.  
  137.     strTitle.LoadString(IDS_PAGE_TITLE);
  138.  
  139.     if (strAddOn.LoadString(nID))
  140.     {
  141.         strTitle += ": ";
  142.         strTitle += strAddOn;
  143.     }
  144.  
  145.     *pCtxt << "<title>";
  146.     *pCtxt << strTitle;
  147.     *pCtxt << "</title>";
  148. }
  149.  
  150. void CWWWQuote::Quote(CHttpServerContext* pCtxt)
  151. {
  152.     StartContent(pCtxt);
  153.     WritePageTitle(pCtxt, IDS_WELCOME);
  154.  
  155.     CString strOutput;
  156.     LoadLongResource(strOutput, IDS_HTML_WELCOME);
  157.     *pCtxt << strOutput;
  158.  
  159.     EndContent(pCtxt);
  160. }
  161.  
  162. void CWWWQuote::WriteIssuesHeader(CHttpServerContext* pCtxt)
  163. {
  164.     CString strOutput;
  165.     LoadLongResource(strOutput, IDS_ISSUES_HEADER);
  166.     *pCtxt << strOutput;
  167. }
  168.  
  169. void CWWWQuote::Issues(CHttpServerContext* pCtxt, LPCTSTR pszMethod)
  170. {
  171.     StartContent(pCtxt);
  172.     WritePageTitle(pCtxt, IDS_ISSUES);
  173.  
  174.     BOOL bByCUSIP;
  175.     CString strOutput;
  176.  
  177.     if (_tcscmp(pszMethod, _T("ByCUSIP")) == 0)
  178.         bByCUSIP = TRUE;
  179.     else if (_tcscmp(pszMethod, _T("ByName")) == 0)
  180.         bByCUSIP = FALSE;
  181.     else
  182.     {
  183.         LoadLongResource(strOutput, IDS_HTML_LOOKUPMETHOD);
  184.         *pCtxt << strOutput;
  185.         EndContent(pCtxt);
  186.         return;
  187.     }
  188.  
  189.     try
  190.     {
  191.         CDatabase db;
  192.  
  193.         CString strConnect(szConnectString);
  194.         strConnect += "DSN=Stock Quotes;";
  195.  
  196.         if (!db.OpenEx(szConnectString,
  197.             CDatabase::openReadOnly | CDatabase::noOdbcDialog))
  198.         {
  199.             *pCtxt << _T("ODBC Datasource 'Stock Quotes' could not be opened<br>\r\n");
  200.             *pCtxt << _T("Did you set it up as a <i>system</i> data source?<br>\r\n");
  201.         }
  202.         else
  203.         {
  204.             CIssueQuery IssueQuery(&db, bByCUSIP);
  205.  
  206.             if (IssueQuery.Open())
  207.             {
  208.                 if (IssueQuery.IsBOF())
  209.                     *pCtxt << _T("Sorry, no issues are available at this time.<br>\r\n");
  210.                 else
  211.                 {
  212.                     LPCTSTR pszText;
  213.                     BOOL bFirstRow = TRUE;
  214.  
  215.                     while (!IssueQuery.IsEOF())
  216.                     {
  217.                         if (bFirstRow == TRUE)
  218.                         {
  219.                             WriteIssuesHeader(pCtxt);
  220.                             bFirstRow = FALSE;
  221.                         }
  222.  
  223.                         if (bByCUSIP)
  224.                             pszText = IssueQuery.m_strCUSIP;
  225.                         else
  226.                             pszText = IssueQuery.m_strName;
  227.  
  228.                         strOutput.Format(_T("<OPTION VALUE=\"%s\">%s\r\n"),
  229.                             IssueQuery.m_strTicker, pszText);
  230.  
  231.                         *pCtxt << strOutput;
  232.                         IssueQuery.MoveNext();
  233.                     }
  234.                 }
  235.                 IssueQuery.Close();
  236.             }
  237.             else
  238.                 *pCtxt << _T("Couldn't open record set<br>\r\n");
  239.  
  240.             db.Close();
  241.         }
  242.     }
  243.     catch (CDBException* pEx)
  244.     {
  245.         *pCtxt << _T("WWWQuote Failed: Couldn't open data source\r\n");
  246.  
  247.         TCHAR szError[1024];
  248.         if (pEx->GetErrorMessage(szError, sizeof(szError)))
  249.         {
  250.             *pCtxt << szError;
  251.             *pCtxt << _T("\r\n");
  252.         }
  253.     }
  254.  
  255.     LoadLongResource(strOutput, IDS_ISSUES_TRAILER);
  256.     *pCtxt << strOutput;
  257.  
  258.     EndContent(pCtxt);
  259. }
  260.  
  261. void CWWWQuote::WriteQuoteHeader(CHttpServerContext* pCtxt, LPCTSTR pszTicker)
  262. {
  263.     CString strResource;
  264.     CString strOutput;
  265.     LoadLongResource(strResource, IDS_QUOTE_HEADER);
  266.  
  267.     strOutput.Format(strResource, pszTicker);
  268.     *pCtxt << strOutput;
  269. }
  270.  
  271. void CWWWQuote::WritePrevButton(CHttpServerContext* pCtxt, LPCTSTR pszTicker,
  272.     int nMonth, int nYear, int nMinMonth, int nMinYear,
  273.     int nMaxMonth, int nMaxYear)
  274. {
  275.     CString strResource;
  276.     CString strOutput;
  277.     LoadLongResource(strResource, IDS_PREV_BUTTON);
  278.  
  279.     strOutput.Format(strResource, pszTicker, nMonth, nYear,
  280.         nMinMonth, nMinYear, nMaxMonth, nMaxYear);
  281.     *pCtxt << strOutput;
  282. }
  283.  
  284. void CWWWQuote::WriteNextButton(CHttpServerContext* pCtxt, LPCTSTR pszTicker,
  285.     int nMonth, int nYear, int nMinMonth, int nMinYear,
  286.     int nMaxMonth, int nMaxYear)
  287. {
  288.     CString strResource;
  289.     CString strOutput;
  290.     LoadLongResource(strResource, IDS_NEXT_BUTTON);
  291.  
  292.     strOutput.Format(strResource, pszTicker, nMonth, nYear,
  293.         nMinMonth, nMinYear, nMaxMonth, nMaxYear);
  294.     *pCtxt << strOutput;
  295. }
  296.  
  297. void CWWWQuote::GetQuotes(CHttpServerContext* pCtxt, LPTSTR pstrTicker,
  298.     int nMonth, int nYear, int nMinMonth, int nMinYear, int nMaxMonth,
  299.     int nMaxYear)
  300. {
  301.     StartContent(pCtxt);
  302.     WritePageTitle(pCtxt, IDS_GETQUOTES);
  303.  
  304.     CString strOutput;
  305.  
  306.     // if there's an error, complain to the user
  307.  
  308.     if ((nYear == 0 && nMonth != 99)
  309.         || nMonth == 0 || _tcscmp(pstrTicker, _T("~")) == 0)
  310.     {
  311.         LoadLongResource(strOutput, IDS_GET_QUOTES_ERROR);
  312.         *pCtxt << strOutput;
  313.         return;
  314.     }
  315.  
  316.     // Otherwise, try and fetch the quotes
  317.     // CQuoteQuery knows how to handle the (nMonth == 99) case
  318.  
  319.     try
  320.     {
  321.         CDatabase db;
  322.  
  323.         CString strConnect(szConnectString);
  324.         strConnect += "DSN=Stock Quotes;";
  325.  
  326.         if (!db.OpenEx(szConnectString,
  327.             CDatabase::openReadOnly | CDatabase::noOdbcDialog))
  328.         {
  329.             *pCtxt << _T("ODBC Datasource 'Stock Quotes' could not be opened<br>\r\n");
  330.             *pCtxt << _T("Did you set it up as a <i>system</i> data source?<br>\r\n");
  331.         }
  332.         else
  333.         {
  334.             if (nMinYear == 0 || nMaxYear == 0 ||
  335.                 nMinMonth == 0 || nMaxMonth == 0)
  336.             {
  337.                 CRangeQuery RangeQuery(&db, pstrTicker);
  338.                 if (!RangeQuery.Open())
  339.                 {
  340.                     LoadLongResource(strOutput, IDS_GET_QUOTES_ERROR);
  341.                     *pCtxt << strOutput;
  342.                     return;
  343.                 }
  344.                 RangeQuery.Close();
  345.  
  346.                 nMinYear = RangeQuery.m_tMin.GetYear();
  347.                 nMaxYear = RangeQuery.m_tMax.GetYear();
  348.                 nMinMonth = RangeQuery.m_tMin.GetMonth();
  349.                 nMaxMonth = RangeQuery.m_tMax.GetMonth();
  350.                 nMonth = nMaxMonth;
  351.                 nYear = nMaxYear;
  352.             }
  353.  
  354.             CQuoteQuery QuoteQuery(&db, pstrTicker, nMonth, nYear);
  355.  
  356.             if (QuoteQuery.Open())
  357.             {
  358.                 if (QuoteQuery.IsBOF())
  359.                     *pCtxt << _T("Sorry, no quotes are available at this time.\r\n");
  360.                 else
  361.                 {
  362.                     BOOL bFirstRow = TRUE;
  363.  
  364.                     while (!QuoteQuery.IsEOF())
  365.                     {
  366.                         if (bFirstRow == TRUE)
  367.                         {
  368.                             WriteQuoteHeader(pCtxt, pstrTicker);
  369.                             bFirstRow = FALSE;
  370.                         }
  371.  
  372.                         CString strFormatDate;
  373.                         strFormatDate = QuoteQuery.m_Date.Format(_T("%m/%d/%Y"));
  374.  
  375.                         if (QuoteQuery.m_Volume != -1)
  376.                         {
  377.                             strOutput.Format(IDS_QUOTEROW,
  378.                                 (LPCTSTR) strFormatDate,
  379.                                 (LPCTSTR) QuoteQuery.m_HighAsk,
  380.                                 (LPCTSTR) QuoteQuery.m_LowBid,
  381.                                 (LPCTSTR) QuoteQuery.m_CloseAvg, QuoteQuery.m_Volume);
  382.                         }
  383.                         else
  384.                         {
  385.                             strOutput.Format(IDS_HOLIDAY,
  386.                                 (LPCTSTR) strFormatDate);
  387.                         }
  388.  
  389.                         *pCtxt << strOutput;
  390.                         QuoteQuery.MoveNext();
  391.                     }
  392.                 }
  393.                 QuoteQuery.Close();
  394.  
  395.                 *pCtxt << _T("</TABLE>");
  396.  
  397.                 if (nYear < nMaxYear || (nYear == nMaxYear && nMonth < nMaxMonth))
  398.                     WriteNextButton(pCtxt, pstrTicker, nMonth, nYear,
  399.                         nMinMonth, nMinYear, nMaxMonth, nMaxYear);
  400.  
  401.                 if (nYear > nMinYear || (nYear == nMinYear && nMonth > nMinMonth))
  402.                     WritePrevButton(pCtxt, pstrTicker, nMonth, nYear,
  403.                         nMinMonth, nMinYear, nMaxMonth, nMaxYear);
  404.             }
  405.             else
  406.                 *pCtxt << _T("Couldn't open record set\r\n");
  407.  
  408.             db.Close();
  409.         }
  410.     }
  411.     catch (CDBException* pEx)
  412.     {
  413.         *pCtxt << _T("WWWQuote Failed: Couldn't open data source\r\n");
  414.  
  415.         TCHAR szError[1024];
  416.         if (pEx->GetErrorMessage(szError, sizeof(szError)))
  417.         {
  418.             *pCtxt << szError;
  419.             *pCtxt << _T("\r\n");
  420.         }
  421.     }
  422.  
  423.     EndContent(pCtxt);
  424. }
  425.  
  426.  
  427. void CWWWQuote::PreviousMonth(CHttpServerContext* pCtxt, LPTSTR pstrTicker,
  428.         int nMonth, int nYear, int nMinMonth, int nMinYear,
  429.         int nMaxMonth, int nMaxYear)
  430. {
  431.     nMonth--;
  432.     if (nMonth == 0)
  433.     {
  434.         nMonth = 12;
  435.         nYear--;
  436.     }
  437.  
  438.     GetQuotes(pCtxt, pstrTicker, nMonth, nYear, nMinMonth, nMinYear,
  439.         nMaxMonth, nMaxYear);
  440. }
  441.  
  442. void CWWWQuote::NextMonth(CHttpServerContext* pCtxt, LPTSTR pstrTicker,
  443.         int nMonth, int nYear, int nMinMonth, int nMinYear,
  444.         int nMaxMonth, int nMaxYear)
  445. {
  446.     nMonth++;
  447.     if (nMonth == 13)
  448.     {
  449.         nMonth = 1;
  450.         nYear++;
  451.     }
  452.  
  453.     GetQuotes(pCtxt, pstrTicker, nMonth, nYear, nMinMonth, nMinYear,
  454.         nMaxMonth, nMaxYear);
  455. }
  456.