FIX: SQLExecute on a Prepared Statement with SQL_NOSCAN_ON Causes Client-Side AV (308401)



The information in this article applies to:

  • Microsoft Data Access Components 2.6
  • Microsoft Data Access Components 2.6 SP1
  • Microsoft Data Access Components 2.7
  • Microsoft ODBC Driver for SQL Server 2000.80.194

This article was previously published under Q308401

SYMPTOMS

When you execute a statement that was prepared with the SQL_ATTR_NOSCAN attribute, you may receive an access violation (AV) as follows:
"Unhandled exception in appname.exe
(SQLSRV32.DLL): 0xC0000005: Access Violation."

RESOLUTION

To resolve this problem, obtain the latest service pack for SQL Server 2000, the latest service pack for MDAC 2.6, or the hotfix referenced below. For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

290211 INF: How to Obtain the Latest SQL Server 2000 Service Pack

For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

300635 INFO: How to Obtain the Latest MDAC 2.6 Service Pack

Hotfix

The English version of this fix should have the following file attributes or later:
   Date          Version         Size            File name     
   -----------------------------------------------------------
   18-SEP-2001   2000.80.447.0    29,252 bytes   Odbcbcp.dll
   18-SEP-2001   2000.80.447.0   471,121 bytes   Sqlsrv32.dll
   18-SEP-2001   2000.80.447.0    90,112 bytes   Sqlsrv32.rll
				

STATUS

Microsoft has confirmed that this is a problem in the Microsoft products that are listed at the beginning of this article. This problem was first corrected in MDAC 2.6 Service Pack 2. This problem was first corrected in Microsoft SQL Server 2000 Service Pack 3.

MORE INFORMATION

Steps to Reproduce Behavior

  1. Create the following tables on SQL Server:
    CREATE TABLE emp4(NAME char(30),  Memo1 text)
    					
  2. Copy the code that follows into a Microsoft Visual C++ console application, and then compile the code. Note that you need to change the data source name, user ID, and password.
    #include <stdio.h>
    #include <string.h>
    #include <windows.h>
    #include <sql.h>
    #include <sqlext.h>
    #include <odbcss.h>
    #define TEXTSIZE    12000
    SQLHENV        henv = SQL_NULL_HENV;
    SQLHDBC        hdbc1 = SQL_NULL_HDBC;     
    SQLHSTMT        hstmt1 = SQL_NULL_HSTMT;
    char * stmt = "INSERT INTO emp4 VALUES('Paul Borm',?)";
    
    int main() {
        RETCODE retcode;
        // SQLBindParameter variables.
        SDWORD        cbTextSize, lbytes;
        // SQLParamData variable.
        PTR            pParmID;
        // SQLPutData variables.
        UCHAR    Data[] = 
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
                "abcdefghijklmnopqrstuvwxyz";
        SDWORD    cbBatch = (SDWORD)sizeof(Data)-1;
         // Allocate the ODBC environment and save handle.
        retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
        // Let ODBC know this is an ODBC 3.0 app.
        retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
                                (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
        // Allocate ODBC connection handle and connect.
        retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
        retcode = SQLConnect(hdbc1, (UCHAR *)"sql32", SQL_NTS,
                   (UCHAR *)"sa", SQL_NTS, (UCHAR *)"mdacsa", SQL_NTS);
        // Allocate statement handle.
        retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
    	retcode = SQLSetStmtAttr(hstmt1,SQL_ATTR_NOSCAN, (SQLPOINTER)SQL_NOSCAN_ON, 0);
    	retcode = SQLPrepare(hstmt1, (UCHAR *)stmt, SQL_NTS);
        // Set parameters based on total data to send.
        lbytes = (SDWORD)TEXTSIZE;
        cbTextSize = SQL_LEN_DATA_AT_EXEC(lbytes);
        // Bind the parameter marker.
        retcode = SQLBindParameter(hstmt1,    // hstmt
                1,                            // ipar
                SQL_PARAM_INPUT,                // fParamType
                SQL_C_CHAR,                    // fCType
                SQL_LONGVARCHAR,                // FSqlType
                lbytes,                        // cbColDef
                0,                            // ibScale
                (VOID *)1,                    // rgbValue
                0,                            // cbValueMax
                &cbTextSize);                // pcbValue
        // Execute the command.
    	retcode = SQLExecute(hstmt1);
        // Check to see if NEED_DATA; if yes, use SQLPutData.
        retcode = SQLParamData(hstmt1, &pParmID);
        if (retcode == SQL_NEED_DATA)
        {
            while (lbytes > cbBatch)
            {
                SQLPutData(hstmt1, Data, cbBatch);
                lbytes -= cbBatch;
            }
            // Put final batch.
            SQLPutData(hstmt1, Data, lbytes); 
        }
        else
        {
               printf("SQLPutData Failed\n\n");
               return(9);
        }
        // Make final SQLParamData call.
        retcode = SQLParamData(hstmt1, &pParmID);
        /* Clean up. */ 
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
        SQLDisconnect(hdbc1);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
        SQLFreeHandle(SQL_HANDLE_ENV, henv);
        return(0);
    
    }
    					

Modification Type:MinorLast Reviewed:9/26/2005
Keywords:kbHotfixServer kbQFE kbSQLServ2000sp3fix kbBug kbfix kbmdac260sp2fix kbSQLServ2000preSP2Fix kbSQLServ2000preSP3fix KB308401