INF: Sample of SQL-DMO Connection Point Interface

Last reviewed: April 9, 1997
Article 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;

};

See also "How to use Connectable Objects in SQL-DMO."


Additional query words:
Keywords : kbnetwork SSrvDMO
Version : 6.5
Platform : WINDOWS


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: April 9, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.