Solved

::FormatMessage Error lookup for OLE-DB

Posted on 2000-05-05
7
368 Views
Last Modified: 2013-12-04
I am using ::FormatMessage(blah, blah, blah, blah....,) to return a text description of the current error (HRESULT) in my DCOM application by pointing it to the system error list. However for OLEDB generated errors, (if my error comes from the database layer) ::FormatMessage return null. I feel there should be a way to extract meaninful text for a bad HRESULT, even if the error comes from the database.
Please help. Any information will be appreciated. Thanks.
0
Comment
Question by:hakeem042997
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 15

Expert Comment

by:NickRepin
ID: 2783273
It is complex enough.

How a Consumer Retrieves an OLE DB Error Object
http://msdn.microsoft.com/library/psdk/dasdk/olpr2fn8.htm

SQLOLEDB Example: Retrieving Error Information
http://msdn.microsoft.com/library/psdk/dasdk/9_ol41pq.htm


My version is based on the example above

#define _SQLERR(descr,iface) \
   { const type_info& t=typeid(*this); \
   SqlDB::LogSqlError(t.name(),__LINE__,descr,p##iface,IID_##iface); }

//********
   hr=pIDBProperties->SetProperties(SZA(PropSet),PropSet);
   if(FAILED(hr)) {
      _SQLERR(L"Unable to set DB properties",IDBProperties)
      pIDBProperties->Release();
      return false;
   }

//*********

void SqlDB::LogSqlError(LPCSTR cname,DWORD line,LPWSTR descr,
   IUnknown* pObjectWithError,
   REFIID IID_InterfaceWithError)
{
   ISupportErrorInfo* pISupportErrorInfo=0;
   if(FAILED(pObjectWithError->QueryInterface(IID_ISupportErrorInfo,
      (void**) &pISupportErrorInfo))) return;

   if(FAILED(pISupportErrorInfo->InterfaceSupportsErrorInfo(
         IID_InterfaceWithError))) {
      pISupportErrorInfo->Release();
      return;
   }

   pISupportErrorInfo->Release();

   IErrorInfo* pIErrorInfoAll=0;
   GetErrorInfo(0,&pIErrorInfoAll);

   if(pIErrorInfoAll) {
      IErrorRecords* pIErrorRecords=0;

      // Test to see if it's a valid OLE DB IErrorInfo interface
      // exposing a list of records.
      if(SUCCEEDED(pIErrorInfoAll->QueryInterface(IID_IErrorRecords,
            (void**) &pIErrorRecords))) {

         ULONG nRecs;
         pIErrorRecords->GetRecordCount(&nRecs);

         // Within each record, retrieve information from each
         // of the defined interfaces.
         for(UINT nRec=0;nRec<nRecs;nRec++) {

            // From IErrorRecords, get the SqlDB and a reference
            // to the ISQLErrorInfo interface.

            ERRORINFO errorinfo;
            pIErrorRecords->GetBasicErrorInfo(nRec,&errorinfo);

             OStr s;
             s<<descr<<L" ("<<cname<<L", "<<line<<L"): "<<
                L"SQLOLE herr="<<hex<<errorinfo.hrError;

            ISQLErrorInfo* pISQLErrorInfo=0;
            ISQLServerErrorInfo* pISQLServerErrorInfo=0;

            pIErrorRecords->GetCustomErrorObject(nRec,
               IID_ISQLErrorInfo,(IUnknown**)&pISQLErrorInfo);

            if(pISQLErrorInfo) {
               BSTR  bstrSQLSTATE=0;
               LONG  lNativeError;
               pISQLErrorInfo->GetSQLInfo(&bstrSQLSTATE,&lNativeError);

               s<<L", native="<<dec<<lNativeError<<L" \""<<
                  SafeStrW(bstrSQLSTATE)<<L"\"";

               SysFreeString(bstrSQLSTATE);

               pISQLErrorInfo->QueryInterface(IID_ISQLServerErrorInfo,
                  (void**) &pISQLServerErrorInfo);

               pISQLErrorInfo->Release();
            }

            if(pISQLServerErrorInfo) {
               SSERRORINFO* pSSErrorInfo=0;
               OLECHAR*     pSSErrorStrings=0;

               pISQLServerErrorInfo->GetErrorInfo(&pSSErrorInfo,
                  &pSSErrorStrings);

               if(pSSErrorInfo)
                  s<<L", err state="<<dec<<int(pSSErrorInfo->bState)<<
                     L" severity="<<dec<<int(pSSErrorInfo->bClass);

               pIMalloc->Free(pSSErrorInfo);
               pIMalloc->Free(pSSErrorStrings);

               pISQLServerErrorInfo->Release();
            }

            IErrorInfo* pIErrorInfoRecord=0;

            if(SUCCEEDED(pIErrorRecords->GetErrorInfo(nRec,
                  GetUserDefaultLCID(),&pIErrorInfoRecord))) {
               BSTR bstrDescription=0;
               BSTR bstrSource=0;
               pIErrorInfoRecord->GetSource(&bstrSource);
               pIErrorInfoRecord->GetDescription(&bstrDescription);

               if(bstrSource) {
                  s<<L", src=\""<<bstrSource<<L"\"";
                  SysFreeString(bstrSource);
               }
               if(bstrDescription) {
                  s<<L", desc=\""<<bstrDescription<<L"\"";
                  SysFreeString(bstrDescription);
               }

               pIErrorInfoRecord->Release();
            }

            _ERROR(LPCTSTR(s),logG)
         } // for

         pIErrorRecords->Release();

      } // if(SUCCEEDED(pIErrorInfoAll->QueryInterface(IID_IErrorRecords
      else {
         BSTR bstrDescription=0;
         BSTR bstrSource=0;
         pIErrorInfoAll->GetSource(&bstrSource);
         pIErrorInfoAll->GetDescription(&bstrDescription);

         if(bstrSource || bstrDescription) {
            _ERROR(descr<<L" ("<<cname<<L", "<<line<<L"): "<<
               L"OLE error, src=\""<<SafeStrW(bstrSource)<<L", desc\""<<
               SafeStrW(bstrDescription)<<L"\"",logG)
            SysFreeString(bstrSource);
            SysFreeString(bstrDescription);
         }
      }
      pIErrorInfoAll->Release();
    }
}

0
 

Author Comment

by:hakeem042997
ID: 2794241
I'm afraid what I'm looking for is a ::FormatMessage(,,,,,) call where the
module point to an oledb or mts dll.

Already, I can copy the bad hresult to an HRPLUS application and it will give me the correct error string that 'am looking for, namely that a bad object context is associated with the application.

How do I do this with FormaMessage?
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2794370
I showed how it must be done.
The code above gives the full description of the error from the data source (SQL server, Oracle etc).
FormatMessage is the wrong way.

0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 

Author Comment

by:hakeem042997
ID: 2796550
Dear NickRepin:

It's interesting that at the point where I handle the error, I get the expected hresult, so I still think ::FormatMessage() will be sufficient. But anyway, I found a solution on MSDN website. Please take a look at the following link:
http://msdn.microsoft.com/library/psdk/certsrv/crtsv_using_8rar.htm 

I feel what I need now is find out what the appropriate dll (module) is that contains OLEDB error information. The microsoft sample uses a dll named ntdsbmsg.dll, only I couldn't locate this dll on my machine.

Thanks for your time.
0
 

Author Comment

by:hakeem042997
ID: 2796991
Dear NickRepin:

It's interesting that at the point where I handle the error, I get the expected hresult, so I still think ::FormatMessage() will be sufficient. But anyway, I found a solution on MSDN website. Please take a look at the following link:
http://msdn.microsoft.com/library/psdk/certsrv/crtsv_using_8rar.htm 

I feel what I need now is find out what the appropriate dll (module) is that contains OLEDB error information. The microsoft sample uses a dll named ntdsbmsg.dll, only I couldn't locate this dll on my machine.

Thanks for your time.
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2797766
This article is related to the Certificate Services, but not to OLE DB.

I gave you the MS article related to OLE DB which shows how OLE DB errors MUST be handled.

I gave you my own code which shows how it must be done.

Sorry, I have nothing more to add to my completely correct answer.
0
 
LVL 15

Accepted Solution

by:
NickRepin earned 300 total points
ID: 2926055
OLE DB can handle many DB providers - Microsoft SQL server, Oracle, Access....

Each of these providers has its own set of error messages.

Moreover, for example, MS SQL server error may come from the database itself ("primary key constraint violation") or from the net-library which provides a communication channel between the server and the client ("connection timeout"). There are several net-libraries for the SQL server - TCP/IP, named pipes, etc. Each of them has its own error messages.

So, the text message for any given error code may contain in several dlls, and only the provider knows in which dll exactly, and the provider passes this info to OLE DB. You may extract the text message using my answer above.
0

Featured Post

 [eBook] Windows Nano Server

Download this FREE eBook and learn all you need to get started with Windows Nano Server, including deployment options, remote management
and troubleshooting tips and tricks

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …

635 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question