Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

::FormatMessage Error lookup for OLE-DB

Posted on 2000-05-05
7
Medium Priority
?
384 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
Veeam Task Manager for Hyper-V

Task Manager for Hyper-V provides critical information that allows you to monitor Hyper-V performance by displaying real-time views of CPU and memory at the individual VM-level, so you can quickly identify which VMs are using host resources.

 

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 600 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

Nothing ever in the clear!

This technical paper will help you implement VMware’s VM encryption as well as implement Veeam encryption which together will achieve the nothing ever in the clear goal. If a bad guy steals VMs, backups or traffic they get nothing.

Question has a verified solution.

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

This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
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…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…

971 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