Solved

::FormatMessage Error lookup for OLE-DB

Posted on 2000-05-05
7
351 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
  • 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
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 Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
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…

895 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now