home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / ado / isapi / adoisapi.cpp next >
Encoding:
C/C++ Source or Header  |  1997-11-13  |  5.4 KB  |  232 lines

  1. //--------------------------------------------------------------------
  2. // Microsoft ADO
  3. //
  4. // (c) 1996 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // @doc
  7. //
  8. // @module    adoisapi.cpp | ADO ISAPI sample application
  9. //
  10. // @devnote None
  11. //--------------------------------------------------------------------
  12.  
  13.  
  14. #import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF", "EndOfFile")
  15. #include <httpext.h>
  16. #include <stdio.h>
  17.  
  18. VOID PatchQuery(char *szQuery, char **ppszPatchedQuery);
  19. HRESULT    FetchData(EXTENSION_CONTROL_BLOCK *pECB);
  20. VOID OutputErrors(EXTENSION_CONTROL_BLOCK *pECB, HRESULT hrError);
  21. VOID OutputString(EXTENSION_CONTROL_BLOCK *pECB, LPCSTR szBuffer);
  22.  
  23. const PCSTR g_pszConnection = "dsn=OLE_DB_NWind_Jet;uid=Admin;pwd=;";
  24.  
  25. BOOL WINAPI    GetExtensionVersion(HSE_VERSION_INFO *pVer)
  26. {
  27.     pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
  28.  
  29.     lstrcpynA( pVer->lpszExtensionDesc, "Sample ADO ISAPI Application", HSE_MAX_EXT_DLL_NAME_LEN );
  30.  
  31.     return TRUE;
  32. }               
  33.  
  34. DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB )
  35. {
  36.     DWORD    dwWritten;
  37.     char    szContent[] = "Content-type: text/html\r\n\r\n";
  38.     
  39.     dwWritten = sizeof(szContent);
  40.     pECB->ServerSupportFunction (pECB->ConnID,
  41.                                  HSE_REQ_SEND_RESPONSE_HEADER,
  42.                                  NULL,
  43.                                  &dwWritten,
  44.                                  (LPDWORD)szContent);
  45.  
  46.     if (FAILED(FetchData(pECB)))
  47.         return HSE_STATUS_ERROR;
  48.     else
  49.         return HSE_STATUS_SUCCESS;
  50. }
  51.  
  52. char ConvertHexToDec(char cHex)
  53. {
  54.     if ((toupper(cHex) >= 'A') && (toupper(cHex) <= 'F'))
  55.         return cHex - 'A' + 10;
  56.     else
  57.         return cHex - '0';
  58. }
  59.  
  60. // Hack to clean up the query string. This code will work
  61. // for most, but not all cases. For instance when the query 
  62. // string has embedded '+', this code will not work.
  63. VOID PatchQuery(char *szQuery, char **ppszPatchedQuery)
  64. {
  65.     char *p = szQuery + 1;
  66.     
  67.     while (*p++)
  68.     {
  69.         if (*p == '+') //replace '+' by ' '
  70.             *p = ' ';
  71.  
  72.         if (*p == '%') //a number begins
  73.         {
  74.             char ch;
  75.  
  76.             if (*++p)
  77.             {
  78.                 ch = ConvertHexToDec(*p) << 4; //convert the first digit
  79.  
  80.                 if (*++p)
  81.                 {
  82.                     ch |= ConvertHexToDec(*p);  //convert the 2nd digit
  83.                     
  84.                     if (!*(p + 1))
  85.                     {
  86.                         *(p-2) = ch;
  87.                         *(p-1) = '\0';
  88.                         break;
  89.                     }
  90.                     else
  91.                     {
  92.                         *(p-2) = ' ';
  93.                         *(p-1) = ' ';
  94.                         *p = ch;
  95.                     }
  96.                 }
  97.             }
  98.         }
  99.     }
  100.  
  101.     *ppszPatchedQuery = szQuery + 1;
  102.       return;
  103. }
  104.  
  105. VOID OutputString(EXTENSION_CONTROL_BLOCK *pECB, LPCSTR szBuffer)
  106. {
  107.     DWORD dwBuffer = strlen(szBuffer);
  108.     pECB->WriteClient(pECB->ConnID, (PVOID) szBuffer, &dwBuffer, 0);
  109. }
  110.  
  111. VOID OutputErrors(EXTENSION_CONTROL_BLOCK *pECB, _com_error &e)
  112. {
  113.     char        szBuffer[512];
  114.     
  115.     // output hresult
  116.     OutputString(pECB, "<P><H1>Error Fetching Data</H1>");
  117.  
  118.     sprintf(szBuffer, "<p>Code = %08lx", e.Error());
  119.     OutputString(pECB, szBuffer);
  120.  
  121.     sprintf(szBuffer, "<p>Code meaning = %s", e.ErrorMessage());
  122.     OutputString(pECB, szBuffer);
  123.  
  124.     _bstr_t bstrSource(e.Source());
  125.     sprintf(szBuffer, "<p>Source = %s", (LPCSTR) bstrSource);
  126.     OutputString(pECB, szBuffer);
  127.     
  128.     _bstr_t bstrDescription(e.Description());
  129.     sprintf(szBuffer, "<p>Description = %s", (LPCSTR) bstrDescription);
  130.     OutputString(pECB, szBuffer);
  131.     
  132.     return;
  133. }
  134.  
  135. HRESULT    FetchData(EXTENSION_CONTROL_BLOCK *pECB)
  136. {
  137.     HRESULT            hr = NOERROR;
  138.     bool            fComInitialized = false;
  139.     _RecordsetPtr    pRs = NULL;
  140.     FieldPtr        *rgflds = NULL;
  141.     long            lNumFields, lFld;
  142.     char            *pszPatchedQuery;
  143.     _variant_t        vValue;
  144.     
  145.     OutputString(pECB, "<HEAD><TITLE>Query Results"
  146.                         "</TITLE></HEAD>\r\n<BODY>\r\n");
  147.         
  148.     PatchQuery(pECB->lpszQueryString, &pszPatchedQuery);
  149.  
  150.     OutputString(pECB, "<P><H1>Query String</H1>");
  151.     OutputString(pECB, pszPatchedQuery);        
  152.     
  153.     try
  154.     {
  155.         if (FAILED(hr = ::CoInitialize(NULL)))
  156.             _com_issue_error(hr);
  157.         
  158.         fComInitialized = true;
  159.  
  160.         // Open the recordset
  161.         pRs.CreateInstance("ADODB.Recordset.1.5");
  162.         pRs->Open(pszPatchedQuery, g_pszConnection, adOpenForwardOnly, adLockReadOnly, adCmdUnknown);
  163.             
  164.         lNumFields = pRs->Fields->Count;
  165.  
  166.         rgflds = new FieldPtr[lNumFields];
  167.         if (!rgflds)
  168.             _com_issue_error(E_OUTOFMEMORY);
  169.         memset(rgflds, 0, lNumFields * sizeof(FieldPtr));
  170.  
  171.         for (lFld = 0; lFld < lNumFields; lFld++)
  172.             rgflds[lFld] = pRs->Fields->GetItem(lFld);
  173.         
  174.         OutputString(pECB, "<P><H1>Query Results</H1>");
  175.         OutputString(pECB, "<P><TABLE BORDER=1 CELLSPACING=4>");
  176.  
  177.         //
  178.         // print column names
  179.         //
  180.         OutputString(pECB, "<TR>");
  181.  
  182.         for (lFld = 0; lFld < lNumFields; lFld++)
  183.         {
  184.             OutputString(pECB, "<TH>");
  185.             OutputString(pECB, (PCSTR)(_bstr_t)rgflds[lFld]->Name);
  186.         }
  187.         
  188.         //
  189.         // print data
  190.         // 
  191.         while (VARIANT_FALSE == pRs->EndOfFile)
  192.         {
  193.              OutputString(pECB, "<TR>");
  194.  
  195.             for (lFld = 0; lFld < lNumFields; lFld++)
  196.             {
  197.                  OutputString(pECB, "<TD>");
  198.  
  199.                 vValue = rgflds[lFld]->Value;
  200.                 if (VT_NULL == vValue.vt)
  201.                     OutputString(pECB, "(Null)");
  202.                 else
  203.                     OutputString(pECB, (PCSTR)(_bstr_t)vValue);
  204.             }
  205.  
  206.              OutputString(pECB, "</TR>");
  207.  
  208.             pRs->MoveNext();
  209.         }
  210.  
  211.         OutputString(pECB, "</TABLE>");
  212.         OutputString(pECB, "</BODY>\r\n");
  213.     }
  214.     catch (_com_error &e)
  215.     {
  216.         OutputErrors(pECB, e);
  217.         hr = e.Error();
  218.     }
  219.  
  220.     if (rgflds)
  221.             delete[] rgflds;
  222.     
  223.     pRs = NULL;
  224.  
  225.     if (fComInitialized)
  226.         ::CoUninitialize();
  227.     
  228.     OutputString(pECB, "</BODY>\r\n");
  229.  
  230.     return hr;
  231. }
  232.