Source code of Windows XP (NT5)
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.

1892 lines
43 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. odbcconn.cxx
  5. Abstract:
  6. This module defines member functions for ODBC_CONNECTION object.
  7. Author:
  8. Murali R. Krishnan ( MuraliK ) 16-Feb-1995
  9. Environment:
  10. User Mode - Win32.
  11. Project:
  12. Internet Services Common DLL
  13. Functions Exported:
  14. ODBC_PARAMETER::CopyValue( IN LPCWSTR pwszValue);
  15. ODBC_PARAMETER::Bind( IN HSTMT hstmt);
  16. ODBC_STATEMENT::~ODBC_STATEMENT()
  17. ODBC_STATEMENT::PrepareStatement( IN LPCSTR pszStatement)
  18. ODBC_STATEMENT::PrepareStatement( IN LPCWSTR pwszStatement)
  19. ODBC_STATEMENT::BindParameter( IN PODBC_PARAMETER pOdbcParam)
  20. ODBC_STATEMENT::ExecuteStatement( VOID)
  21. ODBC_STATEMENT::ExecDirect( IN LPCSTR pwszSqlCommand, IN DWORD cch)
  22. ODBC_STATEMENT::ExecDirect( IN LPCWSTR pwszSqlCommand, IN DWORD cch)
  23. ODBC_STATEMENT::QueryColNames( OUT STRA * * apstrCols,
  24. OUT DWORD * cCols,
  25. IN DWORD cchMaxFieldSize = 0 );
  26. ODBC_STATEMENT::QueryValuesAsStr( OUT STR * * apstrValues,
  27. OUT DWORD * * apcbValues,
  28. OUT BOOL * pfLast );
  29. ODBC_CONNECTION::~ODBC_CONNECTION();
  30. ODBC_CONNECTION::Open();
  31. ODBC_CONNECTION::Close();
  32. ODBC_CONNECTION::GetLastErrorCode();
  33. ODBC_CONNECTION::AllocStatement();
  34. Revision History:
  35. --*/
  36. /************************************************************
  37. * Include Headers
  38. ************************************************************/
  39. #include "precomp.hxx"
  40. #define TCP_ALLOC(cb) (VOID *)LocalAlloc( LPTR, cb )
  41. #define TCP_FREE(p) LocalFree( (HLOCAL) p )
  42. //
  43. // Since the ODBC does not support UNICODE APIs, we convert unicode to
  44. // ANSI to call the APIs. This will have to go away once we find some
  45. // other better way to do manage the same
  46. //
  47. //
  48. // Constants for display widths
  49. //
  50. #define MAX_NUM_PRECISION 15
  51. //
  52. // Constant for all non string and non binary data. 40 is chosen to
  53. // account for things such as Oracle's numeric types, which can have
  54. // up to 38 digits of precision
  55. //
  56. #define MAX_NONCHAR_DATA_LEN 40
  57. //
  58. // If no default maximum field size is specified, then use this value
  59. // as the maximum
  60. //
  61. #define DEFAULT_MAX_FIELD_SIZE 8192
  62. ALLOC_CACHE_HANDLER * ODBC_STATEMENT::sm_pachOdbcStatements;
  63. /************************************************************
  64. * Local Functions
  65. ************************************************************/
  66. static
  67. inline
  68. VOID
  69. CheckAndPrintErrorMessage(
  70. IN ODBC_CONNECTION * poc,
  71. IN RETCODE rc
  72. )
  73. {
  74. # if DBG
  75. if ( !ODBC_CONNECTION::Success( rc)) {
  76. STRA str;
  77. poc->GetLastErrorText( &str, NULL, rc );
  78. DBGPRINTF( ( DBG_CONTEXT,
  79. "ODBC Error Code( %d). Text: %s\n",
  80. rc,
  81. str.QueryStr() ));
  82. }
  83. # endif // DBG
  84. return;
  85. } // CheckAndPrintErrorMessage()
  86. static inline VOID
  87. CheckAndPrintErrorMessage(
  88. IN ODBC_STATEMENT * pos,
  89. IN RETCODE rc)
  90. {
  91. # if DBG
  92. if ( !ODBC_CONNECTION::Success( rc)) {
  93. STRA str;
  94. pos->GetLastErrorText( &str );
  95. DBGPRINTF( ( DBG_CONTEXT,
  96. "ODBC Error Code( %d). Text: %s\n",
  97. rc,
  98. str.QueryStr() ));
  99. }
  100. # endif // DBG
  101. return;
  102. } // CheckAndPrintErrorMessage()
  103. # if DBG
  104. static VOID
  105. PrintMultiString(
  106. IN char * pszMsg,
  107. IN DWORD cbLen,
  108. IN char * pmsz
  109. )
  110. {
  111. DBGPRINTF( ( DBG_CONTEXT,
  112. "Values of %s. %d bytes.\n", pszMsg, cbLen));
  113. for( char * psz = pmsz;
  114. *psz != '\0';
  115. psz += (strlen( psz) + 1))
  116. {
  117. DBGPRINTF( ( DBG_CONTEXT, "%s\n", psz));
  118. }
  119. return;
  120. } // PrintMultiString()
  121. static VOID
  122. AuxOdbcFunctions( IN HENV henv, IN HDBC hdbc)
  123. /*++
  124. Function useful in walking throug a few additional ODBC functions
  125. to find out the ODBC setup information.
  126. Not to be part of the shipped code. Useful for development purposes.
  127. - MuraliK
  128. --*/
  129. {
  130. RETCODE rc;
  131. //
  132. // Set the trace file to a standard file.
  133. //
  134. rc = pSQLSetConnectOption( hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_ON);
  135. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  136. rc = pSQLSetConnectOption( hdbc, SQL_OPT_TRACEFILE,
  137. ( SQLULEN )"%systemroot%\\system32\\gophsql.log" );
  138. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  139. UCHAR szDriverDesc[ 300];
  140. UCHAR szDriverAttrib[ 300];
  141. SWORD cbDD = 300;
  142. SWORD cbDA = 300;
  143. SWORD cbDDCur = 0;
  144. SWORD cbDACur = 0;
  145. szDriverDesc[0] = szDriverAttrib[0] = '\0';
  146. rc = pSQLDrivers( henv, SQL_FETCH_FIRST,
  147. szDriverDesc, cbDD, &cbDDCur,
  148. szDriverAttrib, cbDA, &cbDACur);
  149. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  150. DBGPRINTF( ( DBG_CONTEXT,
  151. " SQLDrivers( %08x) ==> RetCode = %d."
  152. " Driver Desc. = ( %d bytes) %s. ",
  153. henv, rc, cbDDCur, szDriverDesc));
  154. PrintMultiString( " Driver Attributes",
  155. cbDACur,
  156. (char *) szDriverAttrib);
  157. szDriverDesc[0] = szDriverAttrib[0] = '\0';
  158. cbDDCur = cbDACur = 0;
  159. rc = pSQLDataSources( henv, SQL_FETCH_FIRST,
  160. szDriverDesc, cbDD, &cbDDCur,
  161. szDriverAttrib, cbDA, &cbDACur);
  162. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  163. DBGPRINTF( ( DBG_CONTEXT,
  164. " SQLDataSources( %08x) ==> RetCode = %d."
  165. " Data Sources. = ( %d bytes) %s. ",
  166. henv, rc, cbDDCur, szDriverDesc));
  167. PrintMultiString( " Data Source Description", cbDACur,
  168. (char *) szDriverAttrib);
  169. return;
  170. } // AuxOdbcFunctions()
  171. # endif // DBG
  172. /************************************************************
  173. * Member Functions of ODBC_PARAMETER
  174. ************************************************************/
  175. HRESULT
  176. ODBC_PARAMETER::CopyValue(
  177. IN LPCWSTR pwszValue
  178. )
  179. /*++
  180. Description:
  181. This function copies the given Unicode string as the value
  182. into current parameter marker to be used for future insertion.
  183. Arguments:
  184. pwszValue - pointer to null-terminated string containing
  185. Unicode value to be copied into the parameter
  186. marker.
  187. Returns:
  188. TRUE on success and FALSE if there is any error.
  189. Note:
  190. Since ODBC does not support Unicode directly right now, we
  191. convert string value to be ANSI before copying the value over.
  192. --*/
  193. {
  194. HRESULT hr;
  195. STRA strValue;
  196. hr = strValue.CopyW( pwszValue );
  197. if( FAILED( hr ) )
  198. {
  199. DBGPRINTF(( DBG_CONTEXT,
  200. "Error copying data, hr = 0x%x.\n",
  201. hr ));
  202. return hr;
  203. }
  204. return this->CopyValue( strValue.QueryStr() );
  205. } // ODBC_PARAMETER::CopyValue()
  206. HRESULT
  207. ODBC_PARAMETER::CopyValue(
  208. IN LPSYSTEMTIME lpst
  209. )
  210. /*++
  211. Description:
  212. This function copies the given system time into the ODBC
  213. timestamp structure for the current parameter marker to be
  214. used for future insertion.
  215. Arguments:
  216. lpSystemTime - pointer to System Time structure containing
  217. current time.
  218. Returns:
  219. TRUE on success and FALSE if there is any error.
  220. --*/
  221. {
  222. TIMESTAMP_STRUCT * ptsOdbc;
  223. DBG_ASSERT( lpst != NULL);
  224. DBG_ASSERT( m_CType == SQL_C_TIMESTAMP);
  225. DBG_ASSERT( m_SqlType == SQL_TIMESTAMP);
  226. DBG_ASSERT( m_cbValueMax >= sizeof(TIMESTAMP_STRUCT));
  227. ptsOdbc = ( TIMESTAMP_STRUCT * ) m_pValue;
  228. DBG_ASSERT( m_pValue != NULL);
  229. //
  230. // Copy the individual fields over properly
  231. // The types used in ODBC/Win32 are different
  232. // So do a type specific copy of the values.
  233. //
  234. ptsOdbc->year = (SWORD ) lpst->wYear;
  235. ptsOdbc->month = (UWORD ) lpst->wMonth;
  236. ptsOdbc->day = (UWORD ) lpst->wDay;
  237. ptsOdbc->hour = (UWORD ) lpst->wHour;
  238. ptsOdbc->minute = (UWORD ) lpst->wMinute;
  239. ptsOdbc->second = (UWORD ) lpst->wSecond;
  240. ptsOdbc->fraction = (UDWORD ) lpst->wMilliseconds;
  241. return S_OK;
  242. } // ODBC_PARAMETER::CopyValue()
  243. RETCODE
  244. ODBC_PARAMETER::Bind(
  245. IN HSTMT hStmt
  246. )
  247. /*++
  248. Description:
  249. This functions binds the data about the parameter marker 'this'
  250. ( this object) represents to the statement provided.
  251. Arguments:
  252. hStmt HANDLE for the statement to which this parameter
  253. is to be bound.
  254. Returns:
  255. RETCODE value returned by SQLBindParamater().
  256. --*/
  257. {
  258. RETCODE rc;
  259. DBG_ASSERT( hStmt != SQL_NULL_HSTMT);
  260. rc = pSQLBindParameter( hStmt, // statement
  261. QueryParamNumber(),
  262. QueryParamType(),
  263. QueryCType(),
  264. QuerySqlType(),
  265. QueryPrecision(),
  266. QueryScale(),
  267. QueryValue(),
  268. QueryMaxCbValue(),
  269. &(QueryCbValueRef())
  270. );
  271. return ( rc);
  272. } // ODBC_STATEMENT::BindParameter()
  273. # if DBG
  274. VOID
  275. ODBC_PARAMETER::Print(
  276. VOID
  277. ) const
  278. {
  279. DBGPRINTF( ( DBG_CONTEXT,
  280. "Printing ODBC_PARAMETER ( %08x).\n"
  281. " Num=%u; Type=%d; CType=%d; SqlType=%d; Prec=%u;"
  282. " Scale=%d; CbMax=%d; Cb=%d.\n",
  283. this,
  284. QueryParamNumber(),
  285. QueryParamType(),
  286. QueryCType(),
  287. QuerySqlType(),
  288. QueryPrecision(),
  289. QueryScale(),
  290. QueryMaxCbValue(),
  291. QueryCbValue()));
  292. switch ( QuerySqlType() )
  293. {
  294. case SQL_INTEGER:
  295. {
  296. DWORD dwValue = *(DWORD *) QueryValue();
  297. DBGPRINTF( ( DBG_CONTEXT,
  298. " Integer Value = %u\n",
  299. dwValue ) );
  300. break;
  301. }
  302. case SQL_CHAR:
  303. {
  304. LPCSTR pszValue = (LPCSTR ) QueryValue();
  305. DBGPRINTF( ( DBG_CONTEXT,
  306. "String Value( %08x) = %s\n",
  307. pszValue,
  308. pszValue ) );
  309. break;
  310. }
  311. default:
  312. DBGPRINTF( ( DBG_CONTEXT,
  313. " Type=%d. Unknown value at %08x\n",
  314. QuerySqlType(),
  315. QueryValue() ) );
  316. break;
  317. } // switch
  318. return;
  319. } // ODBC_PARAMETER::Print()
  320. # endif // DBG
  321. /************************************************************
  322. * ODBC_STATEMENT member functions
  323. ************************************************************/
  324. ODBC_STATEMENT::~ODBC_STATEMENT( VOID)
  325. {
  326. //
  327. // Free the statement handle
  328. //
  329. if ( m_hStmt != SQL_NULL_HSTMT) {
  330. m_rc = pSQLFreeStmt( m_hStmt, SQL_DROP);
  331. m_hStmt = SQL_NULL_HSTMT;
  332. // Ignore the error code here.
  333. DBG_ASSERT( ODBC_CONNECTION::Success( m_rc));
  334. IF_DEBUG( ODBC) {
  335. DBGPRINTF( ( DBG_CONTEXT,
  336. "SqlFreeStmt() return code %d.\n",
  337. m_rc));
  338. CheckAndPrintErrorMessage( this, m_rc);
  339. }
  340. }
  341. FreeColumnMemory();
  342. m_dwSignature = ODBC_STATEMENT_FREE_SIGNATURE;
  343. } // ODBC_STATEMENT::~ODBC_STATEMENT()
  344. HRESULT
  345. ODBC_STATEMENT::ExecDirect(
  346. IN LPCSTR pszSqlCommand,
  347. IN DWORD cchSqlCommand
  348. )
  349. {
  350. DBG_ASSERT( CheckSignature() );
  351. BOOL fReturn;
  352. IF_DEBUG( ODBC )
  353. {
  354. DBGPRINTF( ( DBG_CONTEXT,
  355. " Executing the SQL command (%d bytes) %s.\n",
  356. cchSqlCommand * sizeof( CHAR),
  357. pszSqlCommand));
  358. }
  359. //
  360. // SQLExecDirect only likes Unsigned chars !
  361. //
  362. m_rc = pSQLExecDirect( m_hStmt,
  363. (UCHAR FAR *) pszSqlCommand,
  364. cchSqlCommand);
  365. fReturn = ODBC_CONNECTION::Success( m_rc);
  366. IF_DEBUG( ODBC)
  367. {
  368. DBGPRINTF( ( DBG_CONTEXT,
  369. " SQLExecDirect() returns code %d\n",
  370. m_rc));
  371. CheckAndPrintErrorMessage( this, m_rc);
  372. }
  373. if( fReturn )
  374. {
  375. return S_OK;
  376. }
  377. return E_FAIL;
  378. } // ODBC_STATEMENT::ExecDirect()
  379. HRESULT
  380. ODBC_STATEMENT::ExecDirect(
  381. IN LPCWSTR pszSqlCommand,
  382. IN DWORD cchSqlCommand
  383. )
  384. {
  385. HRESULT hr;
  386. STRA strCommand;
  387. DBG_ASSERT( CheckSignature() );
  388. hr = strCommand.CopyW( pszSqlCommand );
  389. if( FAILED( hr ) )
  390. {
  391. DBGPRINTF(( DBG_CONTEXT,
  392. "Error copying sql command, hr = 0x%x.\n",
  393. hr ));
  394. return hr;
  395. }
  396. return ExecDirect( strCommand.QueryStr(), strCommand.QueryCCH() );
  397. } // ODBC_STATEMENT::ExecDirect()
  398. HRESULT
  399. ODBC_STATEMENT::PrepareStatement(
  400. IN LPCSTR pszStatement
  401. )
  402. /*++
  403. This function prepares the SQL statement for future execution.
  404. Arguments:
  405. pszStatement - pointer to null terminated string containing the
  406. statement.
  407. Returns:
  408. HRESULT
  409. --*/
  410. {
  411. BOOL fReturn;
  412. DBG_ASSERT( CheckSignature() );
  413. DBG_ASSERT( QueryErrorCode() == SQL_SUCCESS &&
  414. pszStatement != NULL);
  415. m_rc = pSQLPrepare( m_hStmt, (UCHAR FAR *) pszStatement, SQL_NTS);
  416. IF_DEBUG( ODBC )
  417. {
  418. DBGPRINTF( ( DBG_CONTEXT,
  419. " SQLPrepare( %s) returns ErrorCode = %d.\n",
  420. pszStatement, m_rc));
  421. CheckAndPrintErrorMessage( this, m_rc);
  422. }
  423. m_fPreparedStmt = ODBC_CONNECTION::Success( m_rc );
  424. if( m_fPreparedStmt )
  425. {
  426. return S_OK;
  427. }
  428. return E_FAIL;
  429. } // ODBC_STATEMENT::PrepareStatment()
  430. HRESULT
  431. ODBC_STATEMENT::PrepareStatement(
  432. IN LPCWSTR pwszCommand
  433. )
  434. /*++
  435. This function prepares an ODBC statement for execution.
  436. Since ODBC does not support UNICODE, we convert the statement
  437. into ANSI before calling the APIs.
  438. Arguments:
  439. pwszCommand - pointer to null-terminated string containing the
  440. statement to be prepared.
  441. Returns:
  442. HRESULT
  443. --*/
  444. {
  445. BOOL fReturn = FALSE;
  446. STRA strCommand;
  447. HRESULT hr;
  448. DBG_ASSERT( CheckSignature() );
  449. hr = strCommand.CopyW( pwszCommand );
  450. if( FAILED( hr ) )
  451. {
  452. DBGPRINTF(( DBG_CONTEXT,
  453. "Error copying command, hr = 0x%x.\n",
  454. hr ));
  455. return hr;
  456. }
  457. return PrepareStatement( strCommand.QueryStr() );
  458. } // ODBC_STATEMENT::PrepareStatement()
  459. HRESULT
  460. ODBC_STATEMENT::BindParameter(
  461. IN PODBC_PARAMETER pOdbcParameter
  462. )
  463. {
  464. DBG_ASSERT( CheckSignature() );
  465. DBG_ASSERT( ODBC_CONNECTION::Success( m_rc) &&
  466. pOdbcParameter != NULL);
  467. m_rc = pOdbcParameter->Bind( m_hStmt);
  468. IF_DEBUG( ODBC) {
  469. CheckAndPrintErrorMessage( this, m_rc );
  470. }
  471. if( ODBC_CONNECTION::Success( m_rc ) )
  472. {
  473. return S_OK;
  474. }
  475. return E_FAIL;
  476. } // ODBC_STATEMENT::BindParameter()
  477. HRESULT
  478. ODBC_STATEMENT::ExecuteStatement(
  479. VOID
  480. )
  481. /*++
  482. This function executes a prepared ODBC statement. At the end of
  483. execution, the transaction is also committed to ensure that the
  484. record is automatically written to the database.
  485. Arguments:
  486. None
  487. Returns:
  488. HRESULT
  489. --*/
  490. {
  491. DBG_ASSERT( CheckSignature() );
  492. DBG_ASSERT( m_fPreparedStmt != FALSE);
  493. if ( !ODBC_CONNECTION::Success( QueryErrorCode()) )
  494. {
  495. DBGPRINTF(( DBG_CONTEXT,
  496. "!!WARNING!! - Attempting to use Invalid ODBC Connection!\n" ));
  497. }
  498. m_rc = pSQLExecute( m_hStmt);
  499. IF_DEBUG( ODBC)
  500. {
  501. CheckAndPrintErrorMessage( this, m_rc);
  502. }
  503. if( ODBC_CONNECTION::Success( m_rc ) )
  504. {
  505. return S_OK;
  506. }
  507. return E_FAIL;
  508. } // ODBC_STATEMENT::ExecuteStatement()
  509. HRESULT
  510. ODBC_STATEMENT::QueryRowCount(
  511. OUT DWORD * pcRows
  512. )
  513. /*++
  514. Calls SQLRowCount on the current result set.
  515. NOTE: Not all database implementations support this!!
  516. Arguments:
  517. pcRows - Receives count of rows
  518. Returns:
  519. TRUE on success and FALSE if there are any failures.
  520. Note:
  521. --*/
  522. {
  523. DBG_ASSERT( CheckSignature() );
  524. m_rc = pSQLRowCount( m_hStmt,
  525. (SDWORD *) pcRows );
  526. if( ODBC_CONNECTION::Success( m_rc ) )
  527. {
  528. return S_OK;
  529. }
  530. return E_FAIL;
  531. }
  532. HRESULT
  533. ODBC_STATEMENT::QueryColNames(
  534. STRA * * pastrCols,
  535. DWORD * cCols,
  536. DWORD cchMaxFieldSize,
  537. BOOL * pfHaveResultSet
  538. )
  539. /*++
  540. This method returns the list of column names from the result table
  541. Arguments:
  542. pastrCols - Receives an array of STRAs containing the column names
  543. cCols - Count of columns returned (zero for no result set)
  544. cchMaxFieldSize - Maximum buffer size to allocate for any data
  545. fields, zero means use the default value.
  546. pfHaveResultSet - Set to TRUE if the current query was a SELECT
  547. and thus has rows that can be enumerated
  548. Returns:
  549. TRUE on success and FALSE if there are any failures.
  550. Note:
  551. --*/
  552. {
  553. HRESULT hr;
  554. SWORD nresultcols;
  555. SWORD i;
  556. CHAR achColName[64];
  557. SWORD cchColName;
  558. SWORD ColType;
  559. DWORD cchColLength;
  560. SWORD scale;
  561. SWORD nullable;
  562. *pastrCols = NULL;
  563. *cCols = 0;
  564. *pfHaveResultSet = TRUE;
  565. DBG_ASSERT( CheckSignature() );
  566. //
  567. // Return the old binding info if we already have it
  568. //
  569. if ( m_astrColNames )
  570. {
  571. *pastrCols = m_astrColNames;
  572. *cCols = m_cCols;
  573. return S_OK;
  574. }
  575. //
  576. // Provide a default maximum field size if none was specified
  577. //
  578. if ( !cchMaxFieldSize )
  579. {
  580. cchMaxFieldSize = DEFAULT_MAX_FIELD_SIZE;
  581. }
  582. //
  583. // See what kind of statement it was. If there are no result
  584. // columns, the statement is not a SELECT statement.
  585. //
  586. m_rc = pSQLNumResultCols( m_hStmt,
  587. &nresultcols );
  588. if ( !ODBC_CONNECTION::Success( m_rc ) )
  589. {
  590. return E_FAIL;
  591. }
  592. if ( nresultcols > 0 )
  593. {
  594. //
  595. // Allocate an array of strings for the column names and
  596. // the column values
  597. //
  598. m_cCols = nresultcols;
  599. *cCols = m_cCols;
  600. m_astrColNames = new STRA[m_cCols];
  601. m_astrValues = new STRA[m_cCols];
  602. m_acbValue = new LONG[m_cCols];
  603. if( m_astrColNames == NULL ||
  604. m_astrValues == NULL ||
  605. m_acbValue == NULL )
  606. {
  607. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  608. }
  609. //
  610. // Otherwise, get the column names of the result set and
  611. // use the display_size() function to compute the length
  612. // needed by each data type. Next, bind the columns and
  613. // specify all data will be converted to char.
  614. //
  615. for (i = 0; i < m_cCols; i++ )
  616. {
  617. m_rc = pSQLDescribeCol( m_hStmt,
  618. i + 1,
  619. (UCHAR *) achColName,
  620. (SWORD)sizeof(achColName),
  621. &cchColName,
  622. &ColType,
  623. &cchColLength,
  624. &scale,
  625. &nullable );
  626. if ( !ODBC_CONNECTION::Success( m_rc ) )
  627. {
  628. return E_FAIL;
  629. }
  630. //
  631. // Select the buffer size for the retrieved data for
  632. // this column
  633. //
  634. cchColLength = ODBC_CONNECTION::DisplaySize( ColType,
  635. min( cchColLength, cchMaxFieldSize ) );
  636. //
  637. // Copy the column name and set the column data size
  638. //
  639. hr = m_astrColNames[i].Copy( achColName );
  640. if( FAILED( hr ) )
  641. {
  642. DBGPRINTF(( DBG_CONTEXT,
  643. "Error copying colume name, hr = 0x%x.\n",
  644. hr ));
  645. return hr;
  646. }
  647. hr = m_astrValues[i].Resize( cchColLength + 1 );
  648. if ( FAILED( hr ) )
  649. {
  650. DBGPRINTF(( DBG_CONTEXT,
  651. "Error resizing string buffer, hr = 0x%x.\n",
  652. hr ));
  653. return hr;
  654. }
  655. m_rc = pSQLBindCol( m_hStmt,
  656. i + 1,
  657. SQL_C_CHAR,
  658. m_astrValues[i].QueryStr(),
  659. cchColLength,
  660. &m_acbValue[i] );
  661. if ( !ODBC_CONNECTION::Success( m_rc ) )
  662. {
  663. return E_FAIL;
  664. }
  665. }
  666. *pastrCols = m_astrColNames;
  667. *cCols = m_cCols;
  668. }
  669. else
  670. {
  671. *pfHaveResultSet = FALSE;
  672. }
  673. return S_OK;
  674. }
  675. HRESULT
  676. ODBC_STATEMENT::QueryValuesAsStr(
  677. STRA * * pastrValues,
  678. OUT DWORD * * pacbValues,
  679. BOOL * pfLast
  680. )
  681. /*++
  682. This method gets the data at the current position.
  683. Arguments:
  684. pastrValues - Receives a pointer to an array of strings that contains
  685. the alphanumeric representation of that field
  686. pacbValues - Receives pointer to array of DWORDs that contain the length
  687. of the field
  688. pfLast - Set to TRUE if there are no more values to retrieve
  689. Returns:
  690. HRESULT
  691. Note:
  692. --*/
  693. {
  694. HRESULT hr;
  695. DBG_ASSERT( CheckSignature() );
  696. *pastrValues = NULL;
  697. //
  698. // Build the bindings if we haven't already
  699. //
  700. if ( !m_astrColNames )
  701. {
  702. STRA * astrCols;
  703. DWORD cCols;
  704. BOOL fHaveResultSet;
  705. hr = QueryColNames( &astrCols,
  706. &cCols,
  707. 0,
  708. &fHaveResultSet );
  709. if ( FAILED( hr ) )
  710. {
  711. return hr;
  712. }
  713. }
  714. //
  715. // If there are columns to enumerate, get them now
  716. //
  717. if ( m_astrColNames )
  718. {
  719. DWORD i;
  720. //
  721. // Zero terminate the columns as some drivers don't write
  722. // anything for NULL fields
  723. //
  724. for ( i = 0; i < m_cCols; i++ )
  725. {
  726. *((CHAR *) m_astrValues[i].QueryStr()) = '\0';
  727. m_acbValue[i] = 0;
  728. }
  729. //
  730. // Fill in the binding values
  731. //
  732. m_rc = pSQLFetch( m_hStmt );
  733. if ( m_rc == SQL_NO_DATA_FOUND )
  734. {
  735. *pfLast = TRUE;
  736. }
  737. else
  738. {
  739. if ( !ODBC_CONNECTION::Success( m_rc ) )
  740. {
  741. return E_FAIL;
  742. }
  743. *pfLast = FALSE;
  744. }
  745. *pastrValues = m_astrValues;
  746. *pacbValues = ( DWORD * ) m_acbValue;
  747. }
  748. else
  749. {
  750. *pfLast = TRUE;
  751. }
  752. return S_OK;
  753. }
  754. HRESULT
  755. ODBC_STATEMENT::MoreResults(
  756. BOOL * pfMoreResults
  757. )
  758. /*++
  759. Determines if there are any more results sets to return to
  760. the user
  761. pfMoreResults - Set to TRUE if there are more results in the
  762. result set
  763. --*/
  764. {
  765. DBG_ASSERT( CheckSignature() );
  766. *pfMoreResults = TRUE;
  767. m_rc = pSQLMoreResults( m_hStmt );
  768. if ( m_rc == SQL_NO_DATA_FOUND )
  769. {
  770. *pfMoreResults = FALSE;
  771. return S_OK;
  772. }
  773. if ( !ODBC_CONNECTION::Success( m_rc ))
  774. {
  775. return E_FAIL;
  776. }
  777. return S_OK;
  778. }
  779. VOID
  780. ODBC_STATEMENT::FreeColumnMemory(
  781. VOID
  782. )
  783. /*++
  784. This method frees memory allocated by the QueryColNames and
  785. QueryValuesAsStr methods.
  786. --*/
  787. {
  788. DBG_ASSERT( CheckSignature() );
  789. if ( m_astrColNames ) delete [] m_astrColNames;
  790. if ( m_astrValues ) delete [] m_astrValues;
  791. if ( m_acbValue ) delete [] m_acbValue;
  792. m_astrColNames = NULL;
  793. m_astrValues = NULL;
  794. m_acbValue = NULL;
  795. }
  796. //static
  797. HRESULT
  798. ODBC_STATEMENT::Initialize(
  799. VOID
  800. )
  801. /*++
  802. Routine Description:
  803. Initialize ODBC_STATEMENT lookaside
  804. Arguments:
  805. None
  806. Return Value:
  807. HRESULT
  808. --*/
  809. {
  810. ALLOC_CACHE_CONFIGURATION acConfig;
  811. acConfig.nConcurrency = 1;
  812. acConfig.nThreshold = 100;
  813. acConfig.cbSize = sizeof( ODBC_STATEMENT );
  814. DBG_ASSERT( sm_pachOdbcStatements == NULL );
  815. sm_pachOdbcStatements = new ALLOC_CACHE_HANDLER( "ODBC_STATEMENT",
  816. &acConfig );
  817. if ( sm_pachOdbcStatements == NULL )
  818. {
  819. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  820. }
  821. return NO_ERROR;
  822. }
  823. //static
  824. VOID
  825. ODBC_STATEMENT::Terminate(
  826. VOID
  827. )
  828. /*++
  829. Routine Description:
  830. Terminate ODBC_STATEMENT lookaside
  831. Arguments:
  832. None
  833. Return Value:
  834. None
  835. --*/
  836. {
  837. if ( sm_pachOdbcStatements != NULL )
  838. {
  839. delete sm_pachOdbcStatements;
  840. sm_pachOdbcStatements = NULL;
  841. }
  842. }
  843. # if DBG
  844. VOID
  845. ODBC_STATEMENT::Print( VOID) const
  846. {
  847. DBGPRINTF( ( DBG_CONTEXT,
  848. " Printing ODBC_STATEMENT( %08x)."
  849. " HStmt = %08x. OdbcConn=%08x. RetCode = %d\n",
  850. m_hStmt, m_pOdbcConnection, m_rc));
  851. } // ODBC_STATEMENT::Print()
  852. # endif // DBG
  853. /**************************************************
  854. * Member Functions of class ODBC_CONNECTION
  855. **************************************************/
  856. ODBC_CONNECTION::~ODBC_CONNECTION( VOID)
  857. /*++
  858. This function closes the odbc connection ( if open) and cleans up.
  859. --*/
  860. {
  861. DBG_REQUIRE( SUCCEEDED( Close() ) );
  862. return;
  863. } // ODBC_CONNECTION::~ODBC_CONNECTION()
  864. HRESULT
  865. ODBC_CONNECTION::Open(
  866. IN LPCSTR pszDataSource,
  867. IN LPCSTR pszUserName,
  868. IN LPCSTR pszPassword
  869. )
  870. /*++
  871. This function opens a new odbc connection to given data source
  872. using the user name and password supplied.
  873. Arguments:
  874. pszDataSource - pointer to null-terminated string containing ODBC
  875. data source name
  876. pszUserName - pointer to null-terminated string containing
  877. UserName
  878. pszPassword - pointer to null-terminated string containing
  879. Password
  880. Returns:
  881. HRESULT
  882. --*/
  883. {
  884. HRESULT hr = S_OK;
  885. BOOL fReturn = FALSE;
  886. DBG_ASSERT( pszDataSource != NULL &&
  887. pszUserName != NULL &&
  888. pszPassword != NULL );
  889. //
  890. // Allocate an ODBC environment
  891. //
  892. m_rc = pSQLAllocEnv( &m_henv );
  893. fReturn = Success( m_rc );
  894. IF_DEBUG( ODBC ) {
  895. DBGPRINTF( ( DBG_CONTEXT,
  896. "SQLAllocEnv() returned ErrorCode %d. henv = %08x\n",
  897. m_rc, m_henv));
  898. CheckAndPrintErrorMessage( this, m_rc);
  899. }
  900. if ( fReturn ) {
  901. //
  902. // Establish memory for connection handle within the environment
  903. //
  904. m_rc = pSQLAllocConnect( m_henv, &m_hdbc);
  905. fReturn = Success( m_rc);
  906. IF_DEBUG( ODBC) {
  907. DBGPRINTF( ( DBG_CONTEXT,
  908. "SQLAllocConnect() returns code %d. hdbc = %08x\n",
  909. m_rc, m_hdbc));
  910. CheckAndPrintErrorMessage( this, m_rc);
  911. }
  912. }
  913. if ( fReturn) {
  914. //
  915. // Use Following call to just printout the dynamic values for ODBC
  916. //
  917. // AuxOdbcFunctions( m_henv, m_hdbc);
  918. #if 0
  919. {
  920. STRA str;
  921. STRA strOut;
  922. SWORD swStrOut;
  923. if ( FAILED( str.Append( pszDataSource ) ) ||
  924. FAILED( str.Append( ";UID=" ) ) ||
  925. FAILED( str.Append( pszUserName ) ) ||
  926. FAILED( str.Append( ";PWD=" ) ) ||
  927. FAILED( str.Append( pszPassword ) ) ||
  928. FAILED( str.Append( ";APP=Internet Services") ) ||
  929. FAILED( strOut.Resize( 255 ) ) )
  930. {
  931. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  932. }
  933. m_rc = pSQLDriverConnect( m_hdbc,
  934. NULL,
  935. (UCHAR *) str.QueryStr(),
  936. SQL_NTS,
  937. (UCHAR *) strOut.QueryStr(),
  938. strOut.QuerySize(),
  939. &swStrOut,
  940. SQL_DRIVER_NOPROMPT );
  941. }
  942. #else
  943. {
  944. m_rc = pSQLConnect( m_hdbc,
  945. (UCHAR FAR *) pszDataSource, SQL_NTS,
  946. (UCHAR FAR *) pszUserName, SQL_NTS,
  947. (UCHAR FAR *) pszPassword, SQL_NTS );
  948. }
  949. #endif
  950. fReturn = Success( m_rc);
  951. IF_DEBUG( ODBC) {
  952. DBGPRINTF( ( DBG_CONTEXT,
  953. "SQLConnect( %s, %s, %s) returns code %d.\n",
  954. pszDataSource,
  955. pszUserName,
  956. pszPassword,
  957. m_rc ) );
  958. CheckAndPrintErrorMessage( this, m_rc );
  959. }
  960. }
  961. m_fValid = fReturn;
  962. if ( !fReturn ) {
  963. hr = HRESULT_FROM_WIN32( ERROR_GEN_FAILURE );
  964. }
  965. return hr;
  966. } // ODBC_CONNECTION::Open()
  967. HRESULT
  968. ODBC_CONNECTION::Open(
  969. IN LPCWSTR pwszDataSource,
  970. IN LPCWSTR pwszUserName,
  971. IN LPCWSTR pwszPassword
  972. )
  973. /*++
  974. This function opens a new odbc connection to given data source
  975. using the user name and password supplied.
  976. Arguments:
  977. pwszDataSource - pointer to null-terminated string containing ODBC
  978. data source name
  979. pwszUserName - pointer to null-terminated string containing
  980. UserName
  981. pwszPassword - pointer to null-terminated string containing
  982. Password
  983. Returns:
  984. TRUE on success and FALSE if there is an error.
  985. Note:
  986. Poor me. ODBC Does not take UNICODE strings :(. 2/15/95
  987. So we will explicitly convert parameters to ANSI on stack.
  988. --*/
  989. {
  990. HRESULT hr;
  991. DWORD dwError = NO_ERROR;
  992. STRA strDataSource;
  993. STRA strUserName;
  994. STRA strPassword;
  995. //
  996. // Convert all parameters from UNICODE to ANSI
  997. //
  998. hr = strDataSource.CopyW( pwszDataSource );
  999. if( FAILED( hr ) )
  1000. {
  1001. return hr;
  1002. }
  1003. hr = strUserName.CopyW( pwszUserName );
  1004. if( FAILED( hr ) )
  1005. {
  1006. return hr;
  1007. }
  1008. hr = strPassword.CopyW( pwszPassword );
  1009. if( FAILED( hr ) )
  1010. {
  1011. return hr;
  1012. }
  1013. //
  1014. // Make an ANSI open call.
  1015. //
  1016. hr = Open( strDataSource.QueryStr(),
  1017. strUserName.QueryStr(),
  1018. strPassword.QueryStr() );
  1019. //
  1020. // Zero the password for security reasons.
  1021. //
  1022. memset( strPassword.QueryStr(),
  1023. 0, strPassword.QueryCB() );
  1024. return hr;
  1025. } // ODBC_CONNECTION::Open()
  1026. HRESULT
  1027. ODBC_CONNECTION::Close(
  1028. VOID
  1029. )
  1030. /*++
  1031. This function closes the connection established with the ODBC
  1032. and frees up and dynamic memory used.
  1033. Returns:
  1034. TRUE on success and FALSE if there are any failures.
  1035. Note:
  1036. Intermediate failures are ignored. Normally they should not occur.
  1037. --*/
  1038. {
  1039. BOOL fReturn = TRUE;
  1040. //
  1041. // Disconnect and free the connection.
  1042. //
  1043. if ( m_hdbc != SQL_NULL_HDBC)
  1044. {
  1045. m_rc = pSQLDisconnect( m_hdbc );
  1046. //
  1047. // Disconnect is allowed to fail w/o being fatal so don't set
  1048. // fReturn
  1049. //
  1050. IF_DEBUG( ODBC)
  1051. {
  1052. DBGPRINTF( ( DBG_CONTEXT,
  1053. "Warning: SQLDisconnect() returns code %d.\n",
  1054. m_rc));
  1055. CheckAndPrintErrorMessage( this, m_rc);
  1056. }
  1057. m_rc = pSQLFreeConnect( m_hdbc);
  1058. m_hdbc = SQL_NULL_HDBC;
  1059. fReturn = fReturn && Success( m_rc);
  1060. IF_DEBUG( ODBC)
  1061. {
  1062. DBGPRINTF( ( DBG_CONTEXT,
  1063. "SQLFreeConnect() returns code %d.\n",
  1064. m_rc));
  1065. CheckAndPrintErrorMessage( this, m_rc);
  1066. }
  1067. if( !fReturn )
  1068. {
  1069. return E_FAIL;
  1070. }
  1071. }
  1072. //
  1073. // Free the ODBC environment handle.
  1074. //
  1075. if ( m_henv != SQL_NULL_HENV) {
  1076. m_rc = pSQLFreeEnv( m_henv);
  1077. m_henv = SQL_NULL_HENV;
  1078. fReturn = fReturn && Success( m_rc);
  1079. IF_DEBUG( ODBC)
  1080. {
  1081. DBGPRINTF( ( DBG_CONTEXT,
  1082. "SQLFreeEnv() returns code %d.\n",
  1083. m_rc));
  1084. CheckAndPrintErrorMessage( this, m_rc);
  1085. }
  1086. if( !fReturn )
  1087. {
  1088. return E_FAIL;
  1089. }
  1090. }
  1091. return S_OK;
  1092. } // ODBC_CONNECTION::Close()
  1093. PODBC_STATEMENT
  1094. ODBC_CONNECTION::AllocStatement( VOID)
  1095. /*++
  1096. Description:
  1097. This function allocates a new ODBC statement object and also
  1098. calls SQLAllocStatement to create the state required for
  1099. establishing the statement in the ODBC Manager.
  1100. Arguments:
  1101. None
  1102. Returns:
  1103. TRUE on success and FALSE if there is any failure.
  1104. --*/
  1105. {
  1106. PODBC_STATEMENT pOdbcStmt = NULL;
  1107. HSTMT hstmt = SQL_NULL_HSTMT;
  1108. DBG_ASSERT( Success( m_rc));
  1109. //
  1110. // Allocate a statement handle and associate it with the connection.
  1111. //
  1112. m_rc = pSQLAllocStmt( m_hdbc, &hstmt);
  1113. IF_DEBUG( ODBC) {
  1114. DBGPRINTF( ( DBG_CONTEXT,
  1115. "SqlAllocStmt() returns code %d."
  1116. " New Hstmt is : %08x\n",
  1117. m_rc, hstmt));
  1118. CheckAndPrintErrorMessage( this, m_rc);
  1119. }
  1120. if ( ODBC_CONNECTION::Success( m_rc)) {
  1121. pOdbcStmt = new ODBC_STATEMENT( this, hstmt);
  1122. }
  1123. return ( pOdbcStmt );
  1124. } // ODBC_CONNECTION::AllocStatement()
  1125. HRESULT
  1126. ODBC_CONNECTION::SetConnectOption(
  1127. IN UWORD Option,
  1128. IN SQLULEN Param
  1129. )
  1130. /*++
  1131. Sets various options on this connection
  1132. Arguments:
  1133. Option - Option to set
  1134. Param - Option value (32 bit dword or pointer to null terminated
  1135. string )
  1136. Returns:
  1137. HRESULT. Failures are considered to be soft errors as the problem
  1138. may be the driver doesn't support the option etc.
  1139. Note:
  1140. --*/
  1141. {
  1142. BOOL fReturn = TRUE;
  1143. RETCODE rc;
  1144. if ( m_hdbc != SQL_NULL_HDBC)
  1145. {
  1146. rc = pSQLSetConnectOption( m_hdbc, Option, Param );
  1147. fReturn = Success( rc );
  1148. IF_DEBUG( ODBC )
  1149. {
  1150. DBGPRINTF( ( DBG_CONTEXT,
  1151. "SQLSetConnectOption( %d, %d ) returns code %d.\n",
  1152. Option,
  1153. Param,
  1154. rc ) );
  1155. CheckAndPrintErrorMessage( this, rc);
  1156. }
  1157. }
  1158. else
  1159. {
  1160. DBGPRINTF( ( DBG_CONTEXT,
  1161. "[SetConnectOption] Warning: "
  1162. "Setting option on closed connection\n" ));
  1163. }
  1164. if( fReturn )
  1165. {
  1166. return S_OK;
  1167. }
  1168. return E_FAIL;
  1169. }
  1170. BOOL
  1171. ODBC_CONNECTION::GetLastErrorText(
  1172. OUT STRA * pstrError,
  1173. IN HSTMT hstmt,
  1174. IN RETCODE rc
  1175. ) const
  1176. /*++
  1177. This method returns the textual representation of the last ODBC or
  1178. windows error that occurred. Even though the ODBC methods return
  1179. FALSE on failure, if it was an ODBC call that failed, then
  1180. GetLastError won't return the needed error code. Clients of this
  1181. class should call this method to get a descriptive text string of
  1182. the failure.
  1183. Returns:
  1184. TRUE on success and FALSE if there are any failures.
  1185. Note:
  1186. If this function returns FALSE, then a client should call
  1187. GetLastError for the error code.
  1188. --*/
  1189. {
  1190. BOOL fReturn = TRUE;
  1191. if ( ODBC_CONNECTION::Success( rc)) {
  1192. fReturn = SUCCEEDED(pstrError->LoadString( GetLastError() ));
  1193. }
  1194. else
  1195. {
  1196. CHAR rgchMsg[ SQL_MAX_MESSAGE_LENGTH + 10];
  1197. CHAR achState[30];
  1198. CHAR rgchFullMsg[ sizeof(rgchMsg) + sizeof(achState) + 60];
  1199. SWORD cbMsg;
  1200. LONG lError;
  1201. DWORD dwError;
  1202. //
  1203. // If we're formatting as HTML, we bullet list the items
  1204. //
  1205. pstrError->Reset();
  1206. //
  1207. // Loop to pick up all of the errors
  1208. //
  1209. do {
  1210. cbMsg = SQL_MAX_MESSAGE_LENGTH;
  1211. rc = pSQLError( m_henv,
  1212. m_hdbc,
  1213. hstmt,
  1214. (UCHAR *) achState,
  1215. &lError,
  1216. (UCHAR *) rgchMsg,
  1217. cbMsg,
  1218. &cbMsg );
  1219. if ( ODBC_CONNECTION::Success( rc))
  1220. {
  1221. wsprintfA( rgchFullMsg,
  1222. "[State=%s][Error=%d]%s\n",
  1223. achState, lError, rgchMsg);
  1224. if ( FAILED( pstrError->Append( rgchFullMsg ) ) )
  1225. {
  1226. fReturn = FALSE;
  1227. break;
  1228. }
  1229. }
  1230. else
  1231. {
  1232. //
  1233. // This is indicates there are no more error strings
  1234. // to pick up so we should get out
  1235. //
  1236. if ( rc == SQL_NO_DATA_FOUND )
  1237. {
  1238. //
  1239. // Append the end of unorder list marker
  1240. //
  1241. rc = SQL_SUCCESS;
  1242. break;
  1243. }
  1244. }
  1245. } while ( ODBC_CONNECTION::Success( rc ) );
  1246. if ( !ODBC_CONNECTION::Success( rc ) )
  1247. {
  1248. DBGPRINTF( ( DBG_CONTEXT,
  1249. "[GetLastErrorText] SqlError() returned error %d.\n",
  1250. rc));
  1251. SetLastError( ERROR_GEN_FAILURE );
  1252. fReturn = FALSE;
  1253. }
  1254. }
  1255. return ( fReturn);
  1256. } // ODBC_CONNECTION::GetLastErrorText()
  1257. BOOL
  1258. ODBC_CONNECTION::GetLastErrorTextAsHtml(
  1259. OUT STRA * pstrError,
  1260. IN HSTMT hstmt,
  1261. IN RETCODE rc
  1262. ) const
  1263. /*++
  1264. This method returns the textual representation of the last ODBC or
  1265. windows error that occurred. Even though the ODBC methods return
  1266. FALSE on failure, if it was an ODBC call that failed, then
  1267. GetLastError won't return the needed error code. Clients of this
  1268. class should call this method to get a descriptive text string of
  1269. the failure.
  1270. Returns:
  1271. TRUE on success and FALSE if there are any failures.
  1272. Note:
  1273. If this function returns FALSE, then a client should call
  1274. GetLastError for the error code.
  1275. --*/
  1276. {
  1277. BOOL fReturn = TRUE;
  1278. HRESULT hr;
  1279. if ( ODBC_CONNECTION::Success( rc)) {
  1280. fReturn = SUCCEEDED(pstrError->LoadString( GetLastError()));
  1281. } else {
  1282. CHAR rgchMsg[ SQL_MAX_MESSAGE_LENGTH + 10];
  1283. CHAR achState[30];
  1284. CHAR rgchFullMsg[ sizeof(rgchMsg) + sizeof(achState) + 60];
  1285. SWORD cbMsg;
  1286. LONG lError;
  1287. DWORD dwError;
  1288. //
  1289. // If we're formatting as HTML, we bullet list the items
  1290. //
  1291. if ( FAILED( hr = pstrError->Copy( "<UL>" ) ) )
  1292. {
  1293. DBGPRINTF(( DBG_CONTEXT,
  1294. "Error copying error data, hr = 0x%x.\n",
  1295. hr ));
  1296. return FALSE;
  1297. }
  1298. //
  1299. // Loop to pick up all of the errors
  1300. //
  1301. do {
  1302. cbMsg = SQL_MAX_MESSAGE_LENGTH;
  1303. rc = pSQLError( m_henv,
  1304. m_hdbc,
  1305. hstmt,
  1306. (UCHAR *) achState,
  1307. &lError,
  1308. (UCHAR *) rgchMsg,
  1309. cbMsg,
  1310. &cbMsg );
  1311. if ( ODBC_CONNECTION::Success( rc))
  1312. {
  1313. wsprintfA( rgchFullMsg,
  1314. "<LI>[State=%s][Error=%d]%s\n",
  1315. achState, lError, rgchMsg);
  1316. if ( FAILED( hr = pstrError->Append( rgchFullMsg ) ) )
  1317. {
  1318. DBGPRINTF(( DBG_CONTEXT,
  1319. "Error appending error msg, hr = 0x%x.\n",
  1320. hr ));
  1321. fReturn = FALSE;
  1322. break;
  1323. }
  1324. }
  1325. else
  1326. {
  1327. //
  1328. // This is indicates there are no more error strings
  1329. // to pick up so we should get out
  1330. //
  1331. if ( rc == SQL_NO_DATA_FOUND )
  1332. {
  1333. //
  1334. // Append the end of unorder list marker
  1335. //
  1336. if ( FAILED( hr = pstrError->Append( "</UL>" ) ) )
  1337. {
  1338. DBGPRINTF(( DBG_CONTEXT,
  1339. "Error appending error, hr = 0x%x.\n",
  1340. hr ));
  1341. return FALSE;
  1342. }
  1343. rc = SQL_SUCCESS;
  1344. break;
  1345. }
  1346. }
  1347. } while ( ODBC_CONNECTION::Success( rc ) );
  1348. if ( !ODBC_CONNECTION::Success( rc) )
  1349. {
  1350. DBGPRINTF( ( DBG_CONTEXT,
  1351. "[GetLastErrorText] SqlError() returned error %d.\n",
  1352. rc ) );
  1353. SetLastError( ERROR_GEN_FAILURE );
  1354. fReturn = FALSE;
  1355. }
  1356. }
  1357. return ( fReturn);
  1358. } // ODBC_CONNECTION::GetLastErrorTextAsHtml()
  1359. BOOL
  1360. ODBC_CONNECTION::GetInfo(IN DWORD fInfoType,
  1361. IN PVOID rgbInfoValue,
  1362. IN DWORD cbInfoValueMax,
  1363. IN OUT DWORD * pcbInfoValue)
  1364. /*++
  1365. This function obtains the value of the fInfoType for a specific
  1366. ODBC Connection. It mimicks the SQLGetInfo() and uses it to obtain
  1367. this value. On successful return the pointer rgbInfoValue contains
  1368. the requested value and pcbInfoValue contains the size in bytes of
  1369. data.
  1370. Arguments:
  1371. fInfoType - flag containing the Information Type (name) to be
  1372. fetched.
  1373. rgbInfoValue - pointer to buffer which will contain the return
  1374. data.
  1375. cbInfoValue - size of rgbInfoValue in bytes.
  1376. pcbInfoValue - pointer to location that will contain the size of
  1377. information stored in rgbInfoValue, on successful
  1378. return. If buffer is insufficient, this location
  1379. will contain the required number of bytes.
  1380. Returns:
  1381. TRUE on success and FALSE if there is any failure.
  1382. --*/
  1383. {
  1384. BOOL fReturn = FALSE;
  1385. if ( m_hdbc != SQL_NULL_HDBC)
  1386. {
  1387. RETCODE rc;
  1388. rc = pSQLGetInfo( m_hdbc, (UWORD ) fInfoType,
  1389. (PTR) rgbInfoValue,
  1390. (SWORD) cbInfoValueMax,
  1391. (SWORD FAR *) pcbInfoValue );
  1392. fReturn = Success( rc );
  1393. IF_DEBUG( ODBC)
  1394. {
  1395. DBGPRINTF( ( DBG_CONTEXT,
  1396. "SQLGetInfo( %08x, %d, %08x, %d, %08x) returns %d.\n",
  1397. m_hdbc, fInfoType, rgbInfoValue, cbInfoValueMax,
  1398. pcbInfoValue, rc ) );
  1399. CheckAndPrintErrorMessage( this, rc );
  1400. }
  1401. }
  1402. else
  1403. {
  1404. DBGPRINTF( ( DBG_CONTEXT,
  1405. "[SQLGetInfo] Invalid Connection to ODBC\n"));
  1406. }
  1407. return ( fReturn );
  1408. } // ODBC_CONNECTION::GetInfo()
  1409. DWORD
  1410. ODBC_CONNECTION::DisplaySize(
  1411. SWORD coltype,
  1412. DWORD collen
  1413. )
  1414. {
  1415. DWORD cbSize = MAX_NONCHAR_DATA_LEN;
  1416. //
  1417. // Note that we always set the size to at least four bytes.
  1418. // This prevents any possible problems if the column to be
  1419. // bound is NULLable, which can cause a NULL to be written
  1420. // for the data during a fetch
  1421. //
  1422. switch ( coltype )
  1423. {
  1424. case SQL_CHAR:
  1425. case SQL_VARCHAR:
  1426. case SQL_LONGVARCHAR:
  1427. case SQL_BINARY:
  1428. case SQL_VARBINARY:
  1429. case SQL_LONGVARBINARY:
  1430. cbSize = max(collen + sizeof(CHAR), sizeof(PVOID));
  1431. break;
  1432. default:
  1433. break;
  1434. }
  1435. return ( cbSize);
  1436. } // ODBC_CONNECTION::DisplaySize()
  1437. # if DBG
  1438. VOID
  1439. ODBC_CONNECTION::Print(
  1440. VOID
  1441. ) const
  1442. {
  1443. DBGPRINTF( ( DBG_CONTEXT,
  1444. "Printing ODBC_CONNECTION ( %08x). fValid = %d\n"
  1445. " HENV = %08x. HDBC = %08x. ReturnCode =%d\n",
  1446. this, m_fValid,
  1447. m_henv, m_hdbc, m_rc));
  1448. return;
  1449. } // ODBC_CONNECTION::Print()
  1450. # endif // DBG