Bug #10238 Microsoft VB6 DataGrid control causes catastrophic failure
Submitted: 28 Apr 2005 17:27 Modified: 9 Jan 2008 7:17
Reporter: Scott Richardson Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / ODBC Severity:S3 (Non-critical)
Version:3.51 OS:Windows (Windows XP)
Assigned to: CPU Architecture:Any

[28 Apr 2005 17:27] Scott Richardson
Description:
I am using Microsoft's DataGrid control with VB6 to bind directly to an MySQL database table.  When I issue an Refresh call, the control returns with a "Catastrophic failure".  This is VB6's nice way of saying a access violation occurred.

My connection string is:
    Provider=MSDASQL.1;Persist Security Info=False;User ID=root;Extended
    Properties="DATABASE=TSInsert;DSN=MySQL3;OPTION=256;
    PORT=0;SERVER=xfiles2000;UID=root";Initial Catalog=TSInsert

I built a debug version of the 3.51.11 ODBC driver and found that Microsoft's DataGrid control is issuing a call to SQLGetConnectAttr() with a valid hdbc, but the handle has not been connected yet to the database.  So internally to the ODBC driver, the mysql_send_query function attempts to use the macro simple_command, but it crashes because the hdbc->mysql->methods struct member variable is zero.  So the macro causes an access violation.  Clearly the DataView control should not try to call this, BUT the MySQL ODBC driver should be tolerant and return an ODBC error instead of causing an access violation.

Appended Below is the stack trace.

Note that if I remove the "Initial Catalog=TSInsert" text from the connection string, the Microsoft DataGrid control does not make the call that causes the crash.  My application is generic so the user sets the connection string and I have no way of easily knowing to remove this token for specifically MySQL.

Scott Richardson
National Instruments

>	myodbc3.dll!mysql_send_query(st_mysql * mysql=0x0019ffb4, const char * query=0x05afe784, unsigned long length=0x00000011)  Line 2444	C
 	myodbc3.dll!mysql_real_query(st_mysql * mysql=0x0019ffb4, const char * query=0x05afe784, unsigned long length=0x00000011)  Line 2455 + 0x11	C
 	myodbc3.dll!odbc_stmt(tagDBC * dbc=0x0019ffb0, const char * query=0x05afe784)  Line 54 + 0x2d	C
 	myodbc3.dll!reget_current_catalog(tagDBC * dbc=0x0019ffb0)  Line 914 + 0xe	C
 	myodbc3.dll!get_con_attr(void * hdbc=0x0019ffb0, long Attribute=0x0000006d, void * ValuePtr=0x0012d644, long BufferLength=0x00000101, long * StringLengthPtr=0x0012d63c)  Line 480 + 0x9	C
 	myodbc3.dll!SQLGetConnectAttr(void * hdbc=0x0019ffb0, long Attribute=0x0000006d, void * ValuePtr=0x0012d644, long BufferLength=0x00000101, long * StringLengthPtr=0x0012d63c)  Line 906 + 0x19	C
 	odbc32.dll!_ToAnsi_SQLGetConnectAttr@20()  + 0xa6	
 	odbc32.dll!CConnectOptions::SaveDefaultConnAttr()  + 0x694a	
 	odbc32.dll!_SetQueuedAttr@8()  - 0xa1	
 	odbc32.dll!_TraceSQLBrowseConnectW@24()  - 0x15fb8	
 	odbc32.dll!_SQLInternalDriverConnectW@36()  + 0x1a	
 	odbc32.dll!_SQLDriverConnectW@32()  - 0x5cc6	
 	msdasql.dll!CODBCHandle::DriverConnect()  + 0x22	
 	msdasql.dll!CODBCHandle::OHDriverConnect()  + 0x7b	
 	msdasql.dll!CHdbcNode::DriverConnect()  + 0x22	
 	msdasql.dll!CImpIDBInitialize::Initialize()  + 0x125	
 	oledb32.dll!CDBInitialize::DoInitialize()  + 0x33	
 	oledb32.dll!CDBInitialize::Initialize()  + 0x43	
 	oledb32.dll!CDCMPool::CreateResource()  + 0x18e	
 	comsvcs.dll!CHolder::SafeDispenserDriver::CreateResource()  + 0x25	
 	comsvcs.dll!CHolder::AllocResource()  + 0x2bd	
 	oledb32.dll!CDCMPool::DrawResource()  + 0x94	
 	oledb32.dll!CDCMPoolManager::DrawResource()  + 0xa9bf	
 	oledb32.dll!CDPO::Initialize()  + 0xb2	
 	msado15.dll!_ConnectAsync()  + 0x75	
 	msado15.dll!ConnectAsync()  + 0x1b	
 	msado15.dll!CConnection::Open()  - 0xa70b	
 	msadodc.ocx!24e75d05() 	
 	msadodc.ocx!24e75b8c() 	
 	msadodc.ocx!24e760b0() 	
 	msadodc.ocx!24e75568() 	
 	oleaut32.dll!_DispCallFunc@32()  + 0xc3	
 	oleaut32.dll!CTypeInfo2::Invoke()  + 0x20c	
 	msadodc.ocx!24e7f578() 	
 	msadodc.ocx!24e73031() 	
 	MSVBVM60.DLL!OLECTL::Invoke()  + 0x16a	
 	MSVBVM60.DLL!_SafeInvoke@36()  + 0x68	
 	MSVBVM60.DLL!_ExLateId@24()  + 0x64	
 	MSVBVM60.DLL!___vbaLateIdCall()  + 0x1a	
 	DatabaseView.exe!frmDataView::Update()  Line 398 + 0x2c	BASIC

How to repeat:
Create a VB6 app with a DataGrid and ADODC control.  Use the following code:

Private Sub Form_Load()
    Adodc1.CommandType = adCmdTable
    Adodc1.ConnectionString = "Provider=MSDASQL.1;Persist Security Info=False;User ID=root;Extended Properties=""DATABASE=TSInsert;DSN=MySQL3;OPTION=256;PORT=0;SERVER=xfiles2000;UID=root"";Initial Catalog=TSInsert"
    Adodc1.RecordSource = "mytable"
    Set DataGrid1.DataSource = Adodc1
    Adodc1.Refresh
End Sub

Suggested fix:
To validate a possible fix to this problem, I changed the macro...
...from:
  #define simple_command(mysql, command, arg, length, skip_check) \
      (!mysql || !mysql->methods) ? -1 : \
      (*(mysql)->methods->advanced_command)(mysql, command, \
		NullS, 0, arg, length, skip_check)
...to:
  #define simple_command(mysql, command, arg, length, skip_check) \
      (*(mysql)->methods->advanced_command)(mysql, command, \
		NullS, 0, arg, length, skip_check)

...and the catastrophic error no longer occurs and the table is displayed properly. The fix to the MySQL ODBC driver could also be implemented by adding a IsValid() function to all entry points that confirm that a handle is valid and connected to the database.
[2 May 2005 21:39] Scott Richardson
I found another easy way to see this without VB6:
1) Create an empty test.udl text file in a directory
2) Edit the udl file by double clicking on it
3) In the Data Link Properties dialog box, on the Provider, select ODBC
3) In the Data Link Properties dialog box, on the Connection tab,
   a) Select a ODBC data source under the Use Data Source Name combo box
   b) Select a database in the Initial Catalog combo box
4) Test Connection -> Catastrophic Failure Error

If I do not select an initial catalog in the combo box, the error does not occur.

Scott Richardson
[9 Jan 2008 7:17] Jess Balint
Will be fixed with the patch for bug#16653. The problem is trying to get SQL_ATTR_CURRENT_CATALOG before being connected. Many thanks to the original poster for including the the stack dump to confirm this.