|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
odbcreq.hxx
Abstract:
ODBC Request class used for ODBC requests from a query file
Author:
John Ludeman (johnl) 22-Feb-1995
Revision History:
Phillich 24-Jan-1996 Added ODBC_REQ::SkipConditionalBlock()
--*/
#ifndef _ODBCREQ_HXX_
#define _ODBCREQ_HXX_
//
// ODBC DLL Module Name
//
#define HTTP_ODBC_DLL "httpodbc.dll"
//
// Contains the maximum number of queries (i.e.,SQLStatement
// statements) IDC supports
//
#define MAX_QUERIES 100
//
// ODBC_REQ callback function for doing output
//
typedef DWORD ( * ODBC_REQ_CALLBACK )( PVOID pvContext, const CHAR * pchOutput, DWORD cbOutput );
//
// ODBC_REQ callback function for sending header
//
typedef BOOL ( * ODBC_REQ_HEADER )( PVOID pvContext, const CHAR * pchStatus, const CHAR * pchHeaders );
//
// ODBC_REQ callback function for searching client supplied
// symbol tables
//
typedef BOOL ( * ODBC_REQ_FIND_SYMBOL )( VOID * pContext, const CHAR * pszSymbolName, STRA * pstrSymbolValue );
//
// These are the types of tags that we recognize in the template
// file
//
enum TAG_TYPE { //
// i.e., a column name with data
//
TAG_TYPE_VALUE = 0, TAG_TYPE_BEGIN_DETAIL, TAG_TYPE_END_DETAIL, TAG_TYPE_IF, TAG_TYPE_ELSE, TAG_TYPE_END_IF, TAG_TYPE_INTEGER, TAG_TYPE_STRING, TAG_TYPE_OP_LT, TAG_TYPE_OP_GT, TAG_TYPE_OP_EQ, TAG_TYPE_OP_CONTAINS, TAG_TYPE_UNKNOWN, TAG_TYPE_VALUE_TO_ESCAPE };
//
// This class handles all of the work related to processing a
// ODBC query file
//
#define ODBC_REQ_SIGNATURE 'ERDO'
#define ODBC_REQ_FREE_SIGNATURE 'fRDO'
class ODBC_REQ { public:
ODBC_REQ( EXTENSION_CONTROL_BLOCK * pECB, DWORD csecConnPool, int nCharset = 0 );
~ODBC_REQ();
BOOL CheckSignature( VOID ) const { return _dwSignature == ODBC_REQ_SIGNATURE; }
HRESULT Create( CONST CHAR * pszQueryFile, CONST CHAR * pszParameters );
BOOL IsValid( VOID ) const { return _fValid; }
HRESULT OpenQueryFile( BOOL * pfAccessDenied );
HRESULT ParseAndQuery( CHAR * pszLoggedOnUser );
HRESULT OutputResults( ODBC_REQ_CALLBACK pfnCallback, PVOID pvContext, STRA * pstrHeaders, ODBC_REQ_HEADER pfnHeader, BOOL fIsAuth, BOOL * pfAccessDenied );
HRESULT AppendHeaders( STRA * pstr );
__inline VOID Close( VOID );
HRESULT LookupSymbol( const CHAR * pchSymbolName, enum TAG_TYPE * pTagType, const CHAR * * ppchValue, DWORD * pcbValue );
HRESULT SetErrorText( const CHAR * lpszError ) { return _strErrorText.Copy( lpszError ); }
BOOL GetLastErrorText( STRA * pstrError );
BOOL IsEqual( ODBC_REQ * pOdbcReq );
CHAR * QueryContentType( VOID ) { return (_strContentType.IsEmpty() ? "text/html" : _strContentType.QueryStr()); }
DWORD QueryMaxRecords( VOID ) const { return _cMaxRecords; }
DWORD QueryCurrentRecordNum( VOID ) const { return _cCurrentRecordNum; }
const CHAR * QueryQueryFile( VOID ) const { return _strQueryFile.QueryStr(); }
const CHAR * QueryTemplateFile( VOID ) const { return _strTemplateFile.QueryStr(); }
DWORD QueryClientParamCount( VOID ) const { return _cClientParams; }
DWORD QueryAllocatedBytes( VOID ) const { return _buffchain.CalcTotalSize(); }
BOOL IsExpired( DWORD csecSysStartup ) { return csecSysStartup >= _csecExpiresAt; }
ODBC_CONNECTION * QueryOdbcConnection( VOID ) { return ( _podbcconnPool ? _podbcconnPool : &_odbcconn ); }
DWORD QueryConnPoolTimeout( VOID ) const { return _csecConnPool; }
HANDLE QueryUserToken( VOID ) { return _hToken; }
PSECURITY_DESCRIPTOR GetSecDesc( VOID ) { return _pSecDesc; }
VOID InvalidateSecDesc( VOID ) { _pSecDesc = NULL; }
BOOL IsAnonymous() { return _fAnonymous; }
VOID * operator new( size_t size ) { DBG_ASSERT( size == sizeof( ODBC_REQ ) ); DBG_ASSERT( sm_pachOdbcRequests != NULL ); return sm_pachOdbcRequests->Alloc(); }
VOID operator delete( VOID * pOdbcRequest ) { DBG_ASSERT( pOdbcRequest != NULL ); DBG_ASSERT( sm_pachOdbcRequests != NULL ); DBG_REQUIRE( sm_pachOdbcRequests->Free( pOdbcRequest ) ); }
static HRESULT Initialize( VOID );
static VOID Terminate( VOID ); protected:
VOID LookupTag( CHAR * pchBeginTag, const CHAR * * ppchAfterTag, const CHAR * * ppchDBValue, DWORD * cbValue, enum TAG_TYPE * pTagType );
HRESULT SendData( ODBC_REQ_CALLBACK pfnCallback, PVOID pvContext, const CHAR * pbData, DWORD cbData, BUFFER_CHAIN_ITEM * * ppbufOut, DWORD * pcbOut );
HRESULT SendEscapedData( ODBC_REQ_CALLBACK pfnCallback, PVOID pvContext, PCSTR pch, DWORD cbIn, LPDWORD pcbOut );
HRESULT NextRow( BOOL * pfLast );
HRESULT ReplaceParams( BUFFER * pbufFile, PARAM_LIST * pParamList );
HRESULT EvaluateExpression( const CHAR * * ppchExpression, BOOL * pfExprValue );
HRESULT EvaluateOperator( const CHAR * * ppchExpression, TAG_TYPE * pOpType );
VOID SkipToTag( const CHAR * * pchIn, const CHAR * pchTag );
BOOL SkipConditionalBlock( const CHAR * * ppchIn, const CHAR * ppchEOF, const CHAR * pchSearchTag );
private:
//
// Signature of the class
//
DWORD _dwSignature;
ODBC_CONNECTION _odbcconn; ODBC_CONNECTION * _podbcconnPool; ODBC_STATEMENT * _podbcstmt;
//
// Contains query file and cache info for template merge file
//
BUFFER _bufQueryFile; DWORD _cbQueryFile;
//
// Buffer chain if this query is going to be cached and the current
// buffer before it has been added to the chain
//
BUFFER_CHAIN _buffchain; BUFFER_CHAIN_ITEM * _pbufOut;
//
// Maximum buffer size of data field
//
DWORD _cchMaxFieldSize;
//
// Current nesting level of if/endif pairs
//
DWORD _cNestedIfs;
//
// The number of seconds to consider the query valid
//
DWORD _csecExpires; // Relative from time of query
DWORD _csecExpiresAt; // Absolute from system start
//
// The maximum number of records to return in a query
//
DWORD _cMaxRecords;
//
// The current record number we are enumerating
//
DWORD _cCurrentRecordNum;
//
// Full path to the web database gateway query file
//
STRA _strQueryFile;
//
// Full path to template file to merge the results with
//
STRA _strTemplateFile;
//
// Data content type, we default to text/html if none is specified
//
STRA _strContentType;
//
// Contains the expires time if we are caching this query
//
STRA _strExpiresTime;
//
// List of odbc options to set on this connection
//
STRA _strOdbcOptions;
//
// TRUE if the first column of retrieved data should be sent directly
// to the client w/o going through an htx merge
//
BOOL _fDirect;
//
// TRUE if we constructed w/o errors
//
BOOL _fValid;
//
// The merged parameter list from the web browser and the default
// parameter list from the query file
//
PARAM_LIST _plParams;
//
// This is the number of parameters passed by the client
//
DWORD _cClientParams;
//
// Required parameters specified in the query file
//
PARAM_LIST _plReqParams;
//
// String translation list and file
//
PARAM_LIST _plTransList; STRA _strTranslationFile;
//
// The impersonation token file opens are performed with
//
HANDLE _hToken;
//
// Holds the Column names and memory for the database values
//
STRA * _pstrCols; STRA * _pstrValues; DWORD * _pcbValues; DWORD _cCols;
//
// If an error that requires an explanation occurs it's stored here
//
STRA _strErrorText;
//
// Contains a client supplied callback for looking up symbols (such as
// HTTP_USER_AGENT). _strSymbolValue is just a storage variable used
// by LookupTag.
//
EXTENSION_CONTROL_BLOCK * _pECB; STRA _strSymbolValue;
//
// Contains an array of queries
//
STRA _strQueries[MAX_QUERIES]; DWORD _cQueries;
//
// Are we the anonymous user?
//
BOOL _fAnonymous;
PSECURITY_DESCRIPTOR _pSecDesc;
//
// Contains the number of seconds to allow this ODBC connection to be
// pooled, zero for no pooling
//
DWORD _csecConnPool;
//
// Charset of .htm, .idc, .htx
//
int _nCharset;
//
// Field Name
//
#define IDC_FIELDNAME_CHARSET "Charset:"
//
// Field Value
//
#define IDC_CHARSET_SJIS "x-sjis"
#define IDC_CHARSET_JIS1 "iso-2022-jp"
#define IDC_CHARSET_JIS2 "x-jis"
#define IDC_CHARSET_EUCJP "x-euc-jp"
// Please add field value for other FE (FEFEFE)
//
// Lookaside
//
static ALLOC_CACHE_HANDLER * sm_pachOdbcRequests;
};
//
// Contains a string or dword expression. Used for evaluating template
// expressions
//
class EXPR_VALUE { public:
EXPR_VALUE( ODBC_REQ * podbcreq ) { _podbcreq = podbcreq; _dwValue = 0; _tagType = TAG_TYPE_UNKNOWN; }
~EXPR_VALUE() {}
BOOL Evaluate( const CHAR * * ppchValue );
BOOL ConvertToInteger( VOID );
BOOL GT( EXPR_VALUE & v2 ); BOOL LT( EXPR_VALUE & v2 ); BOOL EQ( EXPR_VALUE & v2 ); BOOL CONTAINS( EXPR_VALUE & v2 );
TAG_TYPE QueryType( VOID ) const { return _tagType; }
VOID SetType( TAG_TYPE type ) { _tagType = type; }
DWORD QueryInteger( VOID ) const { return _dwValue; }
const CHAR * QueryStr( VOID ) const { return _strValue.QueryStr(); }
VOID UpperCase( VOID ) { CharUpperA( _strValue.QueryStr() ); }
private:
ODBC_REQ * _podbcreq;
//
// Type of value
//
TAG_TYPE _tagType;
//
// Actual values of expression if dword or string
//
DWORD _dwValue; STRA _strValue;
};
//
// Prototypes for ODBC connection pooling
//
BOOL InitializeOdbcPool( VOID );
VOID TerminateOdbcPool( VOID );
HRESULT OpenConnection( IN ODBC_CONNECTION * podbcconnNonPooled, OUT ODBC_CONNECTION * * ppodbcconnToUse, IN DWORD csecPoolODBC, IN const CHAR * pszDataSource, IN const CHAR * pszUserName, IN const CHAR * pszPassword, IN const CHAR * pszLoggedOnUser );
VOID CloseConnection( IN ODBC_CONNECTION * podbcconnPooled, IN BOOL fDelete );
//
// Inline so we can use the CloseConnection of the connection pool
//
__inline VOID ODBC_REQ::Close( VOID ) { //
// If we're not using a pooled connection, close it now, otherwise free
// it to the pool
//
if ( _podbcconnPool == &_odbcconn ) { _odbcconn.Close(); } else { CloseConnection( _podbcconnPool, FALSE ); } }
#endif //_ODBCREQ_HXX_
|