BUG: ESQL: AV Using Void * for Fost Variable for Binary Datatype

ID: Q184559


The information in this article applies to:


BUG #: 17889 (SQLBUG_65)
       37106 (SQLBUG_70) 

SYMPTOMS

When using "void *" to map a SQL BINARY column, an access violation (AV) may occur in Sqlakw32.dll.


WORKAROUND

To work around this problem, use the method described in the following article in the Microsoft Knowledge Base:

Q184564 : INF: ESQL: How to Handle Binary Data in ESQL


STATUS

Microsoft has confirmed this to be a problem in Microsoft Embedded SQL for C Programmer's Toolkit version 6.5.



A supported fix is now available, but has not been fully regression- tested and should be applied only to systems experiencing this specific problem. Unless you are severely impacted by this specific problem, Microsoft recommends that you wait for the next Service Pack that contains this fix. Contact Microsoft Technical Support for more information.


MORE INFORMATION

The ESQL documentation states in one section that the SQL binary datatype maps to the void * C datatype. However, using a void * for an input host variable causes an access violation in Sqlakw32.dll.

The hotfix address two issues:

Note: You could have used static ESQL and used an unsigned char array for the input host variable in the cases where the data itself did not contain an embedded 'C' null terminator (0x00), for example, with data that is something like 0x444942420c4242424242, not like 0x444900000c4242424242. If the data contains embedded null, it is truncated at the null (this is by design).

The rest of this article describes the details on how to use 'void *' host variables in static ESQL to map binary data after applying this hotfix:

After the precompiler generates the .c file, you need to edit it and replace the '-1' in the sqlasetv API call with the appropriate size for your void * variable (that you used malloc on). There is no other way of doing this because you have no idea about the size of the memory buffers that had malloc run on them. Therefore, it must be provided by you after nsqlprep precompiles the code. This also comes as a warning message from the precompiler.

The following is the sample code to show how it works:

   EXEC SQL BEGIN DECLARE SECTION;
   void * pColBinary;
   int iId = 0;
   EXEC SQL END DECLARE SECTION;
   .
        .
        .
   pColBinary = malloc(10);
   memcpy(pColBinary,"\x44\x49\x00\x00\x0c\x42\x42\x42\x42\x42",10);

   EXEC SQL
           SELECT Id  INTO :iId
           FROM tblBinary
      WHERE ColBinary =[ASCII 160]:pColBinary;
   if (SQLCODE != 0)
   {
      printf("    SQL Code = %li\n", SQLCODE);
          printf("    SQL Server Message %li: '%Fs'\n", SQLERRD1,
          SQLERRMC);
   }
        else
           printf("The ID is = %d\n", iId);
        .
        .
        .
   free(pColBinary); 

So in the above example, after you precompile the code, you need to search through the .c file it generates and replace -1 with 10 in:

   sqlasetv(2, 0, 444, -1,  (void far *)&pColBinary, (void far *)0, (void far *)0L); 

For output data, using an unsigned char array to map the host variable should work fine in both static and dynamic ESQL, even when data contains embedded null (0x00). There is no need to use the void * host variable.

Additional query words: data type


Keywords          : SSrvESQL_C SSrvProg kbbug6.50 
Version           : WINNT:6.5
Platform          : winnt 
Issue type        : kbbug 

Last Reviewed: April 20, 1999