//--------------------------------------------------------------------
// Microsoft ADO
//
// (c) 1996 Microsoft Corporation. All Rights Reserved.
//
// @doc
//
// @moduleadoisapi.cpp | ADO ISAPI sample application
//
// @devnote None
//--------------------------------------------------------------------
#include <afxdisp.h>
#include <crtdbg.h>
#include <ole2.h>
#include <initguid.h>
#include <stdio.h>
#include "adoid.h"
#include "adoint.h"
#include "httpext.h"
VOIDPatchQuery(char *szQuery, char **ppszPatchedQuery);
HRESULTFetchData(EXTENSION_CONTROL_BLOCK *pECB);
HRESULTOutputErrors(EXTENSION_CONTROL_BLOCK *pECB, HRESULT hrError);
voidOutputString(EXTENSION_CONTROL_BLOCK *pECB, LPCSTR szBuffer);
const LPCWSTRx_lpcszSource = L"OLE_DB_NWind_Jet";
const LPCWSTRx_lpcszUser = L"Admin";
const LPCWSTRx_lpcszPassword = L"";
#defineMAX_VALUE_SIZE128
ADOConnection*g_piConnection = NULL;
// Called by the system when processes and threads are initialized and terminated,
// or upon calls to the LoadLibrary and FreeLibrary functions.
BOOL WINAPIDllEntryPoint(
HINSTANCEhinstDLL,
DWORDfdwReason,
LPVOIDlpvReserved)
{
if (DLL_PROCESS_DETACH == fdwReason)
{
if (g_piConnection)
g_piConnection->Release();
CoUninitialize();
}
return TRUE;
}
BOOL WINAPIGetExtensionVersion(
HSE_VERSION_INFO *pVer)
{
pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
lstrcpynA( pVer->lpszExtensionDesc,
"Sample ADO ISAPI Application",
HSE_MAX_EXT_DLL_NAME_LEN );
return TRUE;
} // GetExtensionVersion()
DWORD WINAPIHttpExtensionProc(
EXTENSION_CONTROL_BLOCK *pECB )
{
DWORDdwWritten;
charszContent[] = "Content-type: text/html\r\n\r\n";
dwWritten = sizeof(szContent);
pECB->ServerSupportFunction (pECB->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
&dwWritten,
(LPDWORD)szContent);
if (FAILED(FetchData(pECB)))
return HSE_STATUS_ERROR;
else
return HSE_STATUS_SUCCESS;
}
charConvertHexToDec(char cHex)
{
if ((toupper(cHex) >= 'A') && (toupper(cHex) <= 'F'))
return cHex - 'A' + 10;
else
return cHex - '0';
}
// Hack to clean up the query string. This code will work
// for most, but not all cases. For instance when the query
// string has embedded '+', this code will not work.
VOID PatchQuery(
char *szQuery,
char **ppszPatchedQuery)
{
char *p = szQuery + 1;
while (*p++)
{
if (*p == '+') //replace '+' by ' '
*p = ' ';
if (*p == '%') //a number begins
{
char ch;
if (*++p)
{
ch = ConvertHexToDec(*p) << 4; //convert the first digit
if (*++p)
{
ch |= ConvertHexToDec(*p); //convert the 2nd digit
if (!*(p + 1))
{
*(p-2) = ch;
*(p-1) = '\0';
break;
}
else
{
*(p-2) = ' ';
*(p-1) = ' ';
*p = ch;
}
}
}
}
}
*ppszPatchedQuery = szQuery + 1;
return;
}
VOID OutputString(
EXTENSION_CONTROL_BLOCK *pECB,
LPCSTR szBuffer)
{
DWORD dwBuffer = strlen(szBuffer);
pECB->WriteClient(pECB->ConnID, (PVOID) szBuffer, &dwBuffer, 0);
}
HRESULTOutputErrors(
EXTENSION_CONTROL_BLOCK *pECB,
HRESULT hrError)
{
ADOErrors*piErrors = NULL;
ADOError*piError = NULL;
HRESULThr;
BSTRbstrError;
charszBuffer[128];
LONGlErrorCount;
// output hresult
sprintf(szBuffer, "<P><H1>Error Fetching Data</H1>"
"<P><H3>HRESULT</H3> %ld", hrError);
OutputString(pECB, szBuffer);
// output error description if available
if (g_piConnection != NULL)
{
hr = g_piConnection->get_Errors(&piErrors);
if (FAILED(hr))goto ErrorExit;
hr = piErrors->get_Count(&lErrorCount);
if (FAILED(hr))goto ErrorExit;
if (lErrorCount > 0)
{
OutputString(pECB, "<p><H3>Error Description</H3>");
for (short i = 0; i < lErrorCount; i++)
{
hr = piErrors->get_Item(COleVariant(i), &piError);
if (FAILED(hr))goto ErrorExit;
hr = piError->get_Description(&bstrError);
if (FAILED(hr))goto ErrorExit;
OutputString(pECB, CString((LPCWSTR)bstrError));
OutputString(pECB, "<p>");
SysFreeString(bstrError);
piError->Release();
piError = NULL;
}
}
}
ErrorExit:
if (piError)
piError->Release();
if (piErrors)
piErrors->Release();
return hr;
}
HRESULTFetchData(
EXTENSION_CONTROL_BLOCK *pECB)
{
HRESULThr;
ADOConnection*piConnection = NULL;
ADORecordset*piRecordSet= NULL;
ADOFields*piFields = NULL;
ADOField*piField = NULL;
longlFieldCount = 0;
shorti;
COleVariantvarFieldVal;
char*pszPatchedQuery;
BSTRbstrPatchedQuery = NULL;
BSTRbstrName = NULL;
BSTRbstrSource = NULL;
BSTRbstrUser = NULL;
BSTRbstrPassword = NULL;
VARIANTvNull;
VARIANT_BOOLfEOF;
OutputString(pECB, "<HEAD><TITLE>Query Results"
"</TITLE></HEAD>\r\n<BODY>\r\n");
PatchQuery(pECB->lpszQueryString, &pszPatchedQuery);
OutputString(pECB, "<P><H1>Query String</H1>");
OutputString(pECB, pszPatchedQuery);
if ( g_piConnection == NULL )
{
bstrSource = SysAllocString( x_lpcszSource );
bstrUser = SysAllocString( x_lpcszUser );
bstrPassword = SysAllocString( x_lpcszPassword );
if ( bstrSource == NULL || bstrUser == NULL || bstrPassword == NULL ) goto errNoUninit;
hr = CoInitialize(NULL);
if (FAILED(hr))goto errNoUninit;
hr = CoCreateInstance(CLSID_CADOConnection, NULL, CLSCTX_INPROC_SERVER, IID_IADOConnection, (LPVOID *)&piConnection);
if (FAILED(hr))
{
CoUninitialize();
goto errNoUninit;
}
hr = piConnection->Open( bstrSource, bstrUser, bstrPassword );
if (FAILED(hr))
{
piConnection->Release();
CoUninitialize();
goto errNoUninit;
}
g_piConnection = piConnection;
}
hr = CoInitialize(NULL);
if (FAILED(hr))goto errNoUninit;
hr = CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_INPROC_SERVER, IID_IADORecordset, (LPVOID *)&piRecordSet);
if (FAILED(hr))goto errFreeStuff;
// Allocate BSTR.
bstrPatchedQuery = SysAllocStringLen(NULL, strlen(pszPatchedQuery) );
//Check returned BSTR.
if (bstrPatchedQuery == NULL )goto errFreeStuff;
// Convert the multibyte string to a wide-character string.
if ( MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszPatchedQuery, strlen(pszPatchedQuery), bstrPatchedQuery, strlen(pszPatchedQuery)) == 0 )
goto errFreeStuff;
hr = piRecordSet->put_Source(bstrPatchedQuery);
if (FAILED(hr))goto errFreeStuff;
hr = piRecordSet->putref_ActiveConnection(g_piConnection);
if (FAILED(hr))goto errFreeStuff;
vNull.vt = VT_ERROR;
vNull.scode = DISP_E_PARAMNOTFOUND;
hr = piRecordSet->Open(vNull, vNull, adOpenKeyset, adLockOptimistic, adCmdText);
if (FAILED(hr))goto errFreeStuff;
hr = piRecordSet->get_Fields(&piFields);
if (FAILED(hr))goto errFreeStuff;
hr = piFields->get_Count(&lFieldCount);
if (FAILED(hr))goto errFreeStuff;
OutputString(pECB, "<P><H1>Query Results</H1>");
OutputString(pECB, "<P><TABLE BORDER=1 CELLSPACING=4>");
//
// print column names
//
OutputString(pECB, "<TR>");
for ( i = 0; i < lFieldCount; i++ )
{
OutputString(pECB, "<TH>");
hr = piFields->get_Item(COleVariant(i), &piField);
if (FAILED(hr))goto errFreeStuff;
hr = piField->get_Name(&bstrName);
if (FAILED(hr))goto errFreeStuff;
OutputString(pECB, CString(bstrName)); //convert bstr to CString
SysFreeString(bstrName);
piField->Release();
piField = NULL;
}
//
// print data
//
hr = piRecordSet->get_EOF(&fEOF);
if (FAILED(hr))goto errFreeStuff;
while (!fEOF)
{
OutputString(pECB, "<TR>");
for (i = 0; i < lFieldCount; i++)
{
OutputString(pECB, "<TD>");
hr = piFields->get_Item(COleVariant(i), &piField);
if (FAILED(hr))goto errFreeStuff;
hr = piField->get_Value(&varFieldVal);
if (FAILED(hr))goto errFreeStuff;
if (FAILED(VariantChangeType(&varFieldVal, &varFieldVal, 0, VT_BSTR)))
OutputString(pECB, "N/A");
else
OutputString(pECB, CString(varFieldVal.bstrVal));
varFieldVal.Clear();
piField->Release();
piField = NULL;
}
OutputString(pECB, "</TR>");
hr = piRecordSet->MoveNext();
if (FAILED(hr))goto errFreeStuff;
hr = piRecordSet->get_EOF(&fEOF);
if (FAILED(hr))goto errFreeStuff;
}
OutputString(pECB, "</TABLE>");
OutputString(pECB, "</BODY>\r\n");
errFreeStuff:
if (piField)
piField->Release();
if (piFields)
piFields->Release();
if (piRecordSet)
piRecordSet->Release();
CoUninitialize();
errNoUninit:
SysFreeString(bstrSource);
SysFreeString(bstrUser);
SysFreeString(bstrPassword);
SysFreeString(bstrPatchedQuery);
if (FAILED(hr))
{
TCHAR szBuf[256];
wsprintf(szBuf, _T("Error: %d \n"), hr);
OutputErrors(pECB, hr);
}
OutputString(pECB, "</BODY>\r\n");
return hr;
}