FIX: ADO Recordset GetString() Function Throws an Access Violation in Oleaut32.dll

FIX: ADO Recordset GetString() Function Throws an Access Violation in Oleaut32.dll

<script type="text/javascript">function loadTOCNode(){}</script>
Article ID:230276
Last Review:November 4, 2003
Revision:2.0
This article was previously published under Q230276
<script type="text/javascript"> var sectionFilter = "type != 'notice' && type != 'securedata' && type != 'querywords'"; var tocArrow = "/library/images/support/kbgraphics/public/en-us/downarrow.gif"; var depthLimit = 10; var depth3Limit = 10; var depth4Limit = 5; var depth5Limit = 3; var tocEntryMinimum = 1; </script> <script src="http://support.microsoft.com/common/script/gsfx/kbtoc.js?9" type="text/javascript"></script>

SYMPTOMS

<script type="text/javascript">loadTOCNode(1, 'symptoms');</script>
Calling the GetString() function on a _RecordsetPtr object may cause the following error to occur:
Unhandled Exception in <application name> (OLEAUT32.DLL) : 0xC0000005: Access Violation

Back to the top

CAUSE

<script type="text/javascript">loadTOCNode(1, 'cause');</script>
The #import-generated wrapper function GetString() passes an uninitialized BSTR pointer to the ADO raw_GetString() function as an out parameter. The raw_GetString() function incorrectly calls the SysFreeString() function on the parameter if it is not pointing to NULL.

Back to the top

RESOLUTION

<script type="text/javascript">loadTOCNode(1, 'resolution');</script>
This problem was corrected in ADO 2.5.

For earlier versions of ADO, call the raw_GetString directly and pass a BSTR pointer that points to NULL as the output parameter, or create a wrapper function as described in the "More Information" section.

Back to the top

STATUS

<script type="text/javascript">loadTOCNode(1, 'status');</script>
Microsoft has confirmed that this is a problem in the Microsoft products that are listed at the beginning of this article.

This problem was corrected in ADO 2.5.

Back to the top

MORE INFORMATION

<script type="text/javascript">loadTOCNode(1, 'moreinformation');</script>

Steps to Reproduce the Behavior

<script type="text/javascript">loadTOCNode(2, 'moreinformation');</script> These steps use the SQL Server Pubs database:
1. Create a Win32 console application (Simple application) in Visual C++.
2. Paste the following code to replace code generated in the .cpp file:

Note You must change User ID=<username> and Password =<strong password> to the correct values before you run this code. Make sure that User ID has the appropriate permissions to perform this operation on the database.
#include "stdafx.h"
#include <iostream.h>

#import "C:/Program Files/Common Files/System/ado/msado15.dll" no_namespace rename( "EOF", "adoEOF" )

struct InitOle {
InitOle() { ::CoInitialize(NULL); }
~InitOle() { ::CoUninitialize(); }
} _init_InitOle_;

int main(int argc, char* argv[])
{

try {
_ConnectionPtr pCon(__uuidof(Connection));
_RecordsetPtr pRs(__uuidof(Recordset));

pCon->ConnectionString = L"Provider=SQLOLEDB.1; Server=(local);Initial Catalog=pubs; User Id=<username>; Password=<strong password>;";
pCon->Open(L"",L"",L"",-1);

pRs->Open(L"SELECT * FROM authors",pCon.GetInterfacePtr(),adOpenStatic,adLockOptimistic,-1);

_bstr_t btRecordset;
btRecordset = pRs->GetString(adClipString,-1,L",",L"/r/n",L"<NULL>");
cout << (char*) btRecordset << endl;
}
catch (_com_error& e)
{
cout << e.ErrorMessage() << endl;
}

return 0;
}

3. Run the code and observe the results.

Back to the top

Resolution

<script type="text/javascript">loadTOCNode(2, 'moreinformation');</script>
Use ADO 2.5 -or-

Call the raw_GetString() function directly with a BSTR pointer that is initialized to point to NULL.

Use the following code to replace the call to GetString():
		BSTR bstrResult = NULL;
_bstr_t btColDelim(L",");
_bstr_t btRowDelim(L"/r/n");
_bstr_t btNullExp(L"<NULL>");
HRESULT hr = pRs->raw_GetString(adClipString,-1,btColDelim,btRowDelim,btNullExp,&bstrResult);
if (FAILED(hr)) _com_issue_errorex(hr, pRs, __uuidof(pRs));
btRecordset = bstrResult;

-or-
Create an inline function similar to GetString() that calls the raw_GetString function, but initialize the BSTR variable to NULL.

Note: Do not modify the generated .tli file to make the changes directly to the GetString() wrapper implementation because this file is gegenerated at compile time. Instead, use the function below or copy and paste the GetString() function from the .tli file and modify it as follows:
inline _bstr_t GetString2 ( _RecordsetPtr pRs, enum StringFormatEnum StringFormat, long NumRows, _bstr_t ColumnDelimeter, _bstr_t RowDelimeter, _bstr_t NullExpr ) 
{
BSTR _result = NULL;
HRESULT _hr = pRs->raw_GetString(StringFormat, NumRows, ColumnDelimeter, RowDelimeter, NullExpr, &_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, pRs, __uuidof(pRs));
return _bstr_t(_result, false);
}

You can call this function in the main() function as follows:
		btRecordset = GetString2(pRs,adClipString,-1,L",",L"/r/n",L"<NULL>");
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值