::FormatMessage Error lookup for OLE-DB

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.
hakeem042997Asked:
Who is Participating?
 
NickRepinConnect With a Mentor Commented:
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
 
NickRepinCommented:
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
 
hakeem042997Author Commented:
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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
NickRepinCommented:
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
 
hakeem042997Author Commented:
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
 
hakeem042997Author Commented:
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
 
NickRepinCommented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.