INF: Sample of SQL-DMO Connection Point Interface

ID: Q156100


The information in this article applies to:
  • Microsoft SQL Server version 6.5


SUMMARY

The sample code in this article shows you how to:

  • Create a connection point interface.


  • Display detailed error information.


  • Access Severity 0 to 10 error messages returned from SQL Server.


It also contains a workaround to the Microsoft Knowledge Base article Q152621, "BUG: SQL-DMO: GetMemUsage Method Returns Empty String."

Before proceeding, make sure you take note of the following:
  • You must implement all methods exposed by the Sink object. These are documented in the "What's New in SQL Server 6.5" portion of Books Online.


  • You must appropriately handle the IUnknown interface methods. This sample uses the default implementations of the IUnknown interface where the last Release deletes the object.



MORE INFORMATION

MAIN.CPP


// 
//   The following code is an example of how to implement the SQL-DMO
//   Server connection point to trap all error messages returned from the
//   SQL Server.
// 
// 
//   Includes:
// 

#include "afx.h"
#include "afxole.h"        //    OLE

#include "stdio.h"         //    Standard I/O header

#include "initguid.h"         //    Only included once to define the GUID and UUID's properly

#include "sqloleid.h"         //    SQL-DMO headers
#include "sqlole.h"

#include "ServerConnectionPoint.h"  //    Server connection point implementation

// 
//   Defines:
// 
#define  _SERVER        ""
#define  _USER          "sa"
#define _PWD            ""
#define  _BAD_COOKIE 99999

// 
//   Function declarations:
// 

BOOL  bInitialize(void);

void  vUninitialize(void);

HRESULT hrDisplayError(HRESULT hRes);
BOOL  bInstallConnectionPointHandler(void);

void  vDoSomeStuff(void);

// 
//   Local variables:
// 

BOOL           bCoInit     =  FALSE;
LPSQLOLESERVER    iSQLServer  =  NULL;
LPCONNECTIONPOINT    iCP      =  NULL;
CSQLServerSink *  pServerSink =  NULL;
DWORD       dwCookie =  _BAD_COOKIE;

// 
//   MAIN ROUTINE
//   ------------
void main(void)
{
   if(bInitialize())
   {
      if(bInstallConnectionPointHandler())
      {
         vDoSomeStuff();
      }
   }

   // 
   //    Perform cleanup operations:
   // 
   vUninitialize();
   printf("\n\nSample run completed...\n\n");
}

// 
//   Initialize - perform all init operations:
// 

BOOL bInitialize(void)
{
   BOOL  bRC   =  FALSE;

   printf("\n...Initializing OLE...");
   if(SUCCEEDED(CoInitialize(NULL)))
   {
      bCoInit = TRUE;

      // 
      //    Create a Server object:
      // 
      printf("\n...Creating SQL Server Object...");
      if(SUCCEEDED(hrDisplayError(CoCreateInstance(CLSID_SQLOLEServer,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        IID_ISQLOLEServer,
                        (LPVOID *)&iSQLServer))))
      {
         bRC = TRUE;
      }
   }
   else
   {
      printf("\nCoInitialize failed.");
      bRC = bCoInit = FALSE;
   }
   return bRC;
 }

// 
//    Uninitialize - perform all shutdown operations:
// 
void vUninitialize(void)
{
   printf("\n...Performing the Unadvice...");
   if((dwCookie != _BAD_COOKIE) && (iCP))
      iCP->Unadvise(dwCookie);

   printf("\n...Cleaning up object memory...");

   // 
   //    Not part of above sequence in case Advise failed and dwCookie was
   //   (0)
   // 
   if(iCP)
      iCP->Release();

   // 
   //    Clean up the server object:
   // 
   if(iSQLServer)
      iSQLServer->Release();

   // 
   //    Shut down OLE:
   // 
   if(bCoInit)
      CoUninitialize();
}

// 
//    Install the connection point handler:
// 

BOOL bInstallConnectionPointHandler(void)
{
   BOOL                 bRC      =  FALSE;
   LPCONNECTIONPOINTCONTAINER       iCPContainer   =  NULL;

   // 
   //    Create an instance of the Server Sink object:
   // 
   pServerSink = new CSQLServerSink;

   if(pServerSink)
   {
      printf("\n...Creating Connection Point Container...");
      if(SUCCEEDED(hrDisplayError(iSQLServer->QueryInterface(IID_IConnectionPointContainer,
            (LPVOID *) &iCPContainer))))
      {
         printf("\n...Finding the SQL Server Sink connection point...");
         if(SUCCEEDED(hrDisplayError(iCPContainer->FindConnectionPoint
             (IID_ISQLOLEServerSink, &iCP))))
         {
            printf("\n...Advising connection point that we are available to
               receive events...");
            if(SUCCEEDED(hrDisplayError(iCP->Advise(pServerSink, &dwCookie))))
            {
               bRC = TRUE;
            }
            else
               dwCookie = _BAD_COOKIE;
         }
         iCPContainer->Release();
      }
   }
   else
   {
      printf("\nAttempt to create server sink object failed due to a memory error.");
   }

   // 
   //    Free memory if necessary:
   // 
   if((pServerSink) && (FALSE == bRC))
   {
      delete pServerSink;
      pServerSink = NULL;
   }
   return bRC;
}

// 
//    Do some things to cause the Sink events to fire:
// 
void vDoSomeStuff(void)
{
   printf("\n...Setting connection options...");
   if(SUCCEEDED(hrDisplayError(iSQLServer->SetLoginTimeout(5))))
   {
      if(SUCCEEDED(hrDisplayError(iSQLServer->SetApplicationName("Server Sink"))))
      {
         if(SUCCEEDED(hrDisplayError(iSQLServer->SetHostName("SQL-DMO"))))
         {
            if(SUCCEEDED(hrDisplayError(iSQLServer->SetNetPacketSize(4096))))
            {
               printf("\n...Attempting to connect...");
               if(SUCCEEDED(hrDisplayError(iSQLServer->Connect(_SERVER,
                      _USER, _PWD))))
               {
                  // 
                  //    Cause a meesage to be fired from SQL Server.
                  // 
                  //    This is one workaround for Q152621 (Bug #15500.)
                  //    You could also use ExecuteWithResultsAndMessages.
                  // 
                  //    You may want to use Sink to capute information
                  //    output from any DBCC command because the standard
                  //    implementation of Database.CheckAllocations uses
                  //    'WITH NO_INFOMSGS'
                  // 
                  hrDisplayError(iSQLServer->ExecuteImmediate("dbcc memusage"));

                  // 
                  //    This will fire the Sink event.
                  // 
                  hrDisplayError(iSQLServer->ExecuteImmediate("raiserror(1204, 1, 1)"));
                  // 
                  //    This will NOT fire the Sink event due to Sev level.
                  // 
                  hrDisplayError(iSQLServer->ExecuteImmediate("raiserror(1204, 11, 1)"));
                  // 
                  //    Close connection.
                  // 
                  hrDisplayError(iSQLServer->DisConnect());
               }
            }
         }
      }
   }
}

// 
//    Display Error Information as a result of an OLE call
// 
HRESULT hrDisplayError(HRESULT hRes)
{
   LPERRORINFO    lpErrorInfo    =  NULL;
   BSTR        bstrDesc;
   BSTR        bstrSource;

   if(FAILED(hRes))
   {
      if(SUCCEEDED(GetErrorInfo(0, &lpErrorInfo)))
      {
         lpErrorInfo->GetDescription(&bstrDesc);
         lpErrorInfo->GetSource(&bstrSource);
         printf("\n\nhrDisplayError: %S\n%S\n", bstrSource, bstrDesc);
         lpErrorInfo->Release();
         SysFreeString(bstrDesc);
         SysFreeString(bstrSource);
      }
      else
         printf("\n\nUnable to obtain detailed error information.");
   }
   return hRes;
} 

ServerConnectionPoint.h


// 
//    SQL-DMO Server Connection Point Interface Declaration and
//    Implementation
// 

#include "windows.h"
#include "stdio.h"

#include "sqloleid.h"      //    SQL-DMO headers
#include "sqlole.h"

class CSQLServerSink : public ISQLOLEServerSink
{
   public:
      CSQLServerSink()
         {
            m_uiRefCount   =  0;
         }
      ~CSQLServerSink()
         {
         }

      // 
      // IUnknown Interface
      // 

      STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj)
         {
            if((riid == IID_IUnknown) || (riid == IID_IASQLOLEServerSink))
            {
               AddRef();
               *ppvObj = this;

               return NOERROR;
            }
            else
               return E_NOINTERFACE;
         }
      STDMETHOD_(ULONG,AddRef) (THIS)
         {
            return ++m_uiRefCount;
         }
      STDMETHOD_(ULONG,Release) (THIS)
         {
            --m_uiRefCount;

            if(0 == m_uiRefCount)
                  delete this;

            return m_uiRefCount;
         }

      // 
      // Sink properties and methods:
      // 
      STDMETHOD(QueryTimeout)(THIS_ SQLOLE_LPCSTR strMessage, LPBOOL pbContinue)
         {
            printf("\nSINK QueryTimeout - %s", strMessage);
            *pbContinue = FALSE;
            return NOERROR;
         }

      // 
      //    Only for designated error messages Sev 10 or less.
      // 
      STDMETHOD(ServerMessage)(THIS_ long lMessageSeverity, long lMessageNumber,
                  long lMessageState, SQLOLE_LPCSTR strMessage)
         {
            printf(  "\nSINK ServerMessage"
                  "\nError: %ld"
                  "\nSev:   %ld"
                  "\nState: %ld"
                  "\n%s\n",
                     lMessageNumber, lMessageSeverity, lMessageState, strMessage);
            return NOERROR;
         }

      STDMETHOD(ConnectionBroken)(THIS_ SQLOLE_LPCSTR strMessage, LPBOOL pbRetry)
         {
            printf("\nSINK ConnectionBroken - %s", strMessage);
            *pbRetry = TRUE;
            return NOERROR;
         }

      STDMETHOD(RemoteLoginFailed)(THIS_ long lMessageSeverity, long lMessageNumber,
                     long lMessageState, SQLOLE_LPCSTR strMessage)
         {
            printf(  "\nSINK RemoteLoginFailed"
                  "\nError: %ld"
                  "\nSev:   %ld"
                  "\nState: %ld"
                  "\n%s\n",
                     lMessageNumber, lMessageSeverity, lMessageState, strMessage);
            return NOERROR;
         }
      // 
      //    Shows actual commands begin sent from SQL-DMO to SQL Server.
      // 
      STDMETHOD(CommandSent)(THIS_ SQLOLE_LPCSTR strSQL)
         {
            printf("\nSINK CommandSent - %s", strSQL);
            return NOERROR;
         }

   private:

      UINT  m_uiRefCount;
}; 

Keywords : kbnetwork SSrvDMO
Version : 6.5
Platform : WINDOWS
Issue type :


Last Reviewed: April 1, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.