Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

771 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. odbcreq.hxx
  5. Abstract:
  6. ODBC Request class used for ODBC requests from a query file
  7. Author:
  8. John Ludeman (johnl) 22-Feb-1995
  9. Revision History:
  10. Phillich 24-Jan-1996 Added ODBC_REQ::SkipConditionalBlock()
  11. --*/
  12. #ifndef _ODBCREQ_HXX_
  13. #define _ODBCREQ_HXX_
  14. //
  15. // ODBC DLL Module Name
  16. //
  17. #define HTTP_ODBC_DLL "httpodbc.dll"
  18. //
  19. // Contains the maximum number of queries (i.e.,SQLStatement
  20. // statements) IDC supports
  21. //
  22. #define MAX_QUERIES 100
  23. //
  24. // ODBC_REQ callback function for doing output
  25. //
  26. typedef DWORD ( * ODBC_REQ_CALLBACK )(
  27. PVOID pvContext,
  28. const CHAR * pchOutput,
  29. DWORD cbOutput
  30. );
  31. //
  32. // ODBC_REQ callback function for sending header
  33. //
  34. typedef BOOL ( * ODBC_REQ_HEADER )(
  35. PVOID pvContext,
  36. const CHAR * pchStatus,
  37. const CHAR * pchHeaders
  38. );
  39. //
  40. // ODBC_REQ callback function for searching client supplied
  41. // symbol tables
  42. //
  43. typedef BOOL ( * ODBC_REQ_FIND_SYMBOL )(
  44. VOID * pContext,
  45. const CHAR * pszSymbolName,
  46. STRA * pstrSymbolValue
  47. );
  48. //
  49. // These are the types of tags that we recognize in the template
  50. // file
  51. //
  52. enum TAG_TYPE
  53. {
  54. //
  55. // i.e., a column name with data
  56. //
  57. TAG_TYPE_VALUE = 0,
  58. TAG_TYPE_BEGIN_DETAIL,
  59. TAG_TYPE_END_DETAIL,
  60. TAG_TYPE_IF,
  61. TAG_TYPE_ELSE,
  62. TAG_TYPE_END_IF,
  63. TAG_TYPE_INTEGER,
  64. TAG_TYPE_STRING,
  65. TAG_TYPE_OP_LT,
  66. TAG_TYPE_OP_GT,
  67. TAG_TYPE_OP_EQ,
  68. TAG_TYPE_OP_CONTAINS,
  69. TAG_TYPE_UNKNOWN,
  70. TAG_TYPE_VALUE_TO_ESCAPE
  71. };
  72. //
  73. // This class handles all of the work related to processing a
  74. // ODBC query file
  75. //
  76. #define ODBC_REQ_SIGNATURE 'ERDO'
  77. #define ODBC_REQ_FREE_SIGNATURE 'fRDO'
  78. class ODBC_REQ
  79. {
  80. public:
  81. ODBC_REQ(
  82. EXTENSION_CONTROL_BLOCK * pECB,
  83. DWORD csecConnPool,
  84. int nCharset = 0
  85. );
  86. ~ODBC_REQ();
  87. BOOL
  88. CheckSignature(
  89. VOID
  90. ) const
  91. {
  92. return _dwSignature == ODBC_REQ_SIGNATURE;
  93. }
  94. HRESULT
  95. Create(
  96. CONST CHAR * pszQueryFile,
  97. CONST CHAR * pszParameters
  98. );
  99. BOOL
  100. IsValid(
  101. VOID
  102. ) const
  103. {
  104. return _fValid;
  105. }
  106. HRESULT
  107. OpenQueryFile(
  108. BOOL * pfAccessDenied
  109. );
  110. HRESULT
  111. ParseAndQuery(
  112. CHAR * pszLoggedOnUser
  113. );
  114. HRESULT
  115. OutputResults(
  116. ODBC_REQ_CALLBACK pfnCallback,
  117. PVOID pvContext,
  118. STRA * pstrHeaders,
  119. ODBC_REQ_HEADER pfnHeader,
  120. BOOL fIsAuth,
  121. BOOL * pfAccessDenied
  122. );
  123. HRESULT
  124. AppendHeaders(
  125. STRA * pstr
  126. );
  127. __inline
  128. VOID
  129. Close(
  130. VOID
  131. );
  132. HRESULT
  133. LookupSymbol(
  134. const CHAR * pchSymbolName,
  135. enum TAG_TYPE * pTagType,
  136. const CHAR * * ppchValue,
  137. DWORD * pcbValue
  138. );
  139. HRESULT
  140. SetErrorText(
  141. const CHAR * lpszError
  142. )
  143. {
  144. return _strErrorText.Copy( lpszError );
  145. }
  146. BOOL
  147. GetLastErrorText(
  148. STRA * pstrError
  149. );
  150. BOOL
  151. IsEqual(
  152. ODBC_REQ * pOdbcReq
  153. );
  154. CHAR *
  155. QueryContentType(
  156. VOID
  157. )
  158. {
  159. return (_strContentType.IsEmpty() ?
  160. "text/html" : _strContentType.QueryStr());
  161. }
  162. DWORD
  163. QueryMaxRecords(
  164. VOID
  165. ) const
  166. {
  167. return _cMaxRecords;
  168. }
  169. DWORD
  170. QueryCurrentRecordNum(
  171. VOID
  172. ) const
  173. {
  174. return _cCurrentRecordNum;
  175. }
  176. const
  177. CHAR *
  178. QueryQueryFile(
  179. VOID
  180. ) const
  181. {
  182. return _strQueryFile.QueryStr();
  183. }
  184. const
  185. CHAR *
  186. QueryTemplateFile(
  187. VOID
  188. ) const
  189. {
  190. return _strTemplateFile.QueryStr();
  191. }
  192. DWORD
  193. QueryClientParamCount(
  194. VOID
  195. ) const
  196. {
  197. return _cClientParams;
  198. }
  199. DWORD
  200. QueryAllocatedBytes(
  201. VOID
  202. ) const
  203. {
  204. return _buffchain.CalcTotalSize();
  205. }
  206. BOOL
  207. IsExpired(
  208. DWORD csecSysStartup
  209. )
  210. {
  211. return csecSysStartup >= _csecExpiresAt;
  212. }
  213. ODBC_CONNECTION *
  214. QueryOdbcConnection(
  215. VOID
  216. )
  217. {
  218. return ( _podbcconnPool ? _podbcconnPool : &_odbcconn );
  219. }
  220. DWORD
  221. QueryConnPoolTimeout(
  222. VOID
  223. ) const
  224. {
  225. return _csecConnPool;
  226. }
  227. HANDLE
  228. QueryUserToken(
  229. VOID
  230. )
  231. {
  232. return _hToken;
  233. }
  234. PSECURITY_DESCRIPTOR
  235. GetSecDesc(
  236. VOID
  237. )
  238. {
  239. return _pSecDesc;
  240. }
  241. VOID
  242. InvalidateSecDesc(
  243. VOID
  244. )
  245. {
  246. _pSecDesc = NULL;
  247. }
  248. BOOL
  249. IsAnonymous()
  250. {
  251. return _fAnonymous;
  252. }
  253. VOID *
  254. operator new(
  255. size_t size
  256. )
  257. {
  258. DBG_ASSERT( size == sizeof( ODBC_REQ ) );
  259. DBG_ASSERT( sm_pachOdbcRequests != NULL );
  260. return sm_pachOdbcRequests->Alloc();
  261. }
  262. VOID
  263. operator delete(
  264. VOID * pOdbcRequest
  265. )
  266. {
  267. DBG_ASSERT( pOdbcRequest != NULL );
  268. DBG_ASSERT( sm_pachOdbcRequests != NULL );
  269. DBG_REQUIRE( sm_pachOdbcRequests->Free( pOdbcRequest ) );
  270. }
  271. static
  272. HRESULT
  273. Initialize(
  274. VOID
  275. );
  276. static
  277. VOID
  278. Terminate(
  279. VOID
  280. );
  281. protected:
  282. VOID
  283. LookupTag(
  284. CHAR * pchBeginTag,
  285. const CHAR * * ppchAfterTag,
  286. const CHAR * * ppchDBValue,
  287. DWORD * cbValue,
  288. enum TAG_TYPE * pTagType
  289. );
  290. HRESULT
  291. SendData(
  292. ODBC_REQ_CALLBACK pfnCallback,
  293. PVOID pvContext,
  294. const CHAR * pbData,
  295. DWORD cbData,
  296. BUFFER_CHAIN_ITEM * * ppbufOut,
  297. DWORD * pcbOut
  298. );
  299. HRESULT
  300. SendEscapedData(
  301. ODBC_REQ_CALLBACK pfnCallback,
  302. PVOID pvContext,
  303. PCSTR pch,
  304. DWORD cbIn,
  305. LPDWORD pcbOut
  306. );
  307. HRESULT
  308. NextRow(
  309. BOOL * pfLast
  310. );
  311. HRESULT
  312. ReplaceParams(
  313. BUFFER * pbufFile,
  314. PARAM_LIST * pParamList
  315. );
  316. HRESULT
  317. EvaluateExpression(
  318. const CHAR * * ppchExpression,
  319. BOOL * pfExprValue
  320. );
  321. HRESULT
  322. EvaluateOperator(
  323. const CHAR * * ppchExpression,
  324. TAG_TYPE * pOpType
  325. );
  326. VOID
  327. SkipToTag(
  328. const CHAR * * pchIn,
  329. const CHAR * pchTag
  330. );
  331. BOOL
  332. SkipConditionalBlock(
  333. const CHAR * * ppchIn,
  334. const CHAR * ppchEOF,
  335. const CHAR * pchSearchTag
  336. );
  337. private:
  338. //
  339. // Signature of the class
  340. //
  341. DWORD _dwSignature;
  342. ODBC_CONNECTION _odbcconn;
  343. ODBC_CONNECTION * _podbcconnPool;
  344. ODBC_STATEMENT * _podbcstmt;
  345. //
  346. // Contains query file and cache info for template merge file
  347. //
  348. BUFFER _bufQueryFile;
  349. DWORD _cbQueryFile;
  350. //
  351. // Buffer chain if this query is going to be cached and the current
  352. // buffer before it has been added to the chain
  353. //
  354. BUFFER_CHAIN _buffchain;
  355. BUFFER_CHAIN_ITEM * _pbufOut;
  356. //
  357. // Maximum buffer size of data field
  358. //
  359. DWORD _cchMaxFieldSize;
  360. //
  361. // Current nesting level of if/endif pairs
  362. //
  363. DWORD _cNestedIfs;
  364. //
  365. // The number of seconds to consider the query valid
  366. //
  367. DWORD _csecExpires; // Relative from time of query
  368. DWORD _csecExpiresAt; // Absolute from system start
  369. //
  370. // The maximum number of records to return in a query
  371. //
  372. DWORD _cMaxRecords;
  373. //
  374. // The current record number we are enumerating
  375. //
  376. DWORD _cCurrentRecordNum;
  377. //
  378. // Full path to the web database gateway query file
  379. //
  380. STRA _strQueryFile;
  381. //
  382. // Full path to template file to merge the results with
  383. //
  384. STRA _strTemplateFile;
  385. //
  386. // Data content type, we default to text/html if none is specified
  387. //
  388. STRA _strContentType;
  389. //
  390. // Contains the expires time if we are caching this query
  391. //
  392. STRA _strExpiresTime;
  393. //
  394. // List of odbc options to set on this connection
  395. //
  396. STRA _strOdbcOptions;
  397. //
  398. // TRUE if the first column of retrieved data should be sent directly
  399. // to the client w/o going through an htx merge
  400. //
  401. BOOL _fDirect;
  402. //
  403. // TRUE if we constructed w/o errors
  404. //
  405. BOOL _fValid;
  406. //
  407. // The merged parameter list from the web browser and the default
  408. // parameter list from the query file
  409. //
  410. PARAM_LIST _plParams;
  411. //
  412. // This is the number of parameters passed by the client
  413. //
  414. DWORD _cClientParams;
  415. //
  416. // Required parameters specified in the query file
  417. //
  418. PARAM_LIST _plReqParams;
  419. //
  420. // String translation list and file
  421. //
  422. PARAM_LIST _plTransList;
  423. STRA _strTranslationFile;
  424. //
  425. // The impersonation token file opens are performed with
  426. //
  427. HANDLE _hToken;
  428. //
  429. // Holds the Column names and memory for the database values
  430. //
  431. STRA * _pstrCols;
  432. STRA * _pstrValues;
  433. DWORD * _pcbValues;
  434. DWORD _cCols;
  435. //
  436. // If an error that requires an explanation occurs it's stored here
  437. //
  438. STRA _strErrorText;
  439. //
  440. // Contains a client supplied callback for looking up symbols (such as
  441. // HTTP_USER_AGENT). _strSymbolValue is just a storage variable used
  442. // by LookupTag.
  443. //
  444. EXTENSION_CONTROL_BLOCK * _pECB;
  445. STRA _strSymbolValue;
  446. //
  447. // Contains an array of queries
  448. //
  449. STRA _strQueries[MAX_QUERIES];
  450. DWORD _cQueries;
  451. //
  452. // Are we the anonymous user?
  453. //
  454. BOOL _fAnonymous;
  455. PSECURITY_DESCRIPTOR _pSecDesc;
  456. //
  457. // Contains the number of seconds to allow this ODBC connection to be
  458. // pooled, zero for no pooling
  459. //
  460. DWORD _csecConnPool;
  461. //
  462. // Charset of .htm, .idc, .htx
  463. //
  464. int _nCharset;
  465. //
  466. // Field Name
  467. //
  468. #define IDC_FIELDNAME_CHARSET "Charset:"
  469. //
  470. // Field Value
  471. //
  472. #define IDC_CHARSET_SJIS "x-sjis"
  473. #define IDC_CHARSET_JIS1 "iso-2022-jp"
  474. #define IDC_CHARSET_JIS2 "x-jis"
  475. #define IDC_CHARSET_EUCJP "x-euc-jp"
  476. // Please add field value for other FE (FEFEFE)
  477. //
  478. // Lookaside
  479. //
  480. static ALLOC_CACHE_HANDLER * sm_pachOdbcRequests;
  481. };
  482. //
  483. // Contains a string or dword expression. Used for evaluating template
  484. // expressions
  485. //
  486. class EXPR_VALUE
  487. {
  488. public:
  489. EXPR_VALUE(
  490. ODBC_REQ * podbcreq
  491. )
  492. {
  493. _podbcreq = podbcreq;
  494. _dwValue = 0;
  495. _tagType = TAG_TYPE_UNKNOWN;
  496. }
  497. ~EXPR_VALUE()
  498. {}
  499. BOOL
  500. Evaluate(
  501. const CHAR * * ppchValue
  502. );
  503. BOOL
  504. ConvertToInteger(
  505. VOID
  506. );
  507. BOOL GT( EXPR_VALUE & v2 );
  508. BOOL LT( EXPR_VALUE & v2 );
  509. BOOL EQ( EXPR_VALUE & v2 );
  510. BOOL CONTAINS( EXPR_VALUE & v2 );
  511. TAG_TYPE
  512. QueryType(
  513. VOID
  514. ) const
  515. {
  516. return _tagType;
  517. }
  518. VOID
  519. SetType(
  520. TAG_TYPE type
  521. )
  522. {
  523. _tagType = type;
  524. }
  525. DWORD
  526. QueryInteger(
  527. VOID
  528. ) const
  529. {
  530. return _dwValue;
  531. }
  532. const
  533. CHAR *
  534. QueryStr(
  535. VOID
  536. ) const
  537. {
  538. return _strValue.QueryStr();
  539. }
  540. VOID
  541. UpperCase(
  542. VOID
  543. )
  544. {
  545. CharUpperA( _strValue.QueryStr() );
  546. }
  547. private:
  548. ODBC_REQ * _podbcreq;
  549. //
  550. // Type of value
  551. //
  552. TAG_TYPE _tagType;
  553. //
  554. // Actual values of expression if dword or string
  555. //
  556. DWORD _dwValue;
  557. STRA _strValue;
  558. };
  559. //
  560. // Prototypes for ODBC connection pooling
  561. //
  562. BOOL
  563. InitializeOdbcPool(
  564. VOID
  565. );
  566. VOID
  567. TerminateOdbcPool(
  568. VOID
  569. );
  570. HRESULT
  571. OpenConnection(
  572. IN ODBC_CONNECTION * podbcconnNonPooled,
  573. OUT ODBC_CONNECTION * * ppodbcconnToUse,
  574. IN DWORD csecPoolODBC,
  575. IN const CHAR * pszDataSource,
  576. IN const CHAR * pszUserName,
  577. IN const CHAR * pszPassword,
  578. IN const CHAR * pszLoggedOnUser
  579. );
  580. VOID
  581. CloseConnection(
  582. IN ODBC_CONNECTION * podbcconnPooled,
  583. IN BOOL fDelete
  584. );
  585. //
  586. // Inline so we can use the CloseConnection of the connection pool
  587. //
  588. __inline
  589. VOID
  590. ODBC_REQ::Close(
  591. VOID
  592. )
  593. {
  594. //
  595. // If we're not using a pooled connection, close it now, otherwise free
  596. // it to the pool
  597. //
  598. if ( _podbcconnPool == &_odbcconn )
  599. {
  600. _odbcconn.Close();
  601. }
  602. else
  603. {
  604. CloseConnection( _podbcconnPool, FALSE );
  605. }
  606. }
  607. #endif //_ODBCREQ_HXX_