GameShield ClientProtector COM Component > Linking To ClientProtector In Your Application > Linking To ClientProtector Using Microsoft Visual C++®

Linking To ClientProtector Using Microsoft Visual C++®


Please be sure you have read Linking To The ClientProtector COM Component In Your Application before you perform this procedure.

If you run into trouble, you may prefer to start with the Sample Code.  There are a set of three complete compile-able MSVC++ programs available.  

The following example was prepared and tested in Microsoft Visual C++ 6.0.

The method we use here involves using a preprocessor directive to import the COM object (which has the added benefit of defining a smart-pointer class we can use). This is fairly easy to use and simplifies a great deal of code and memory management we would have to otherwise prepare ourselves.

  1. Open Microsoft Visual C++. Open a new or existing project to which you want to import the ClientProtector and add the import directive to the header file of your applications main form (or any application module that is appropriate) to import the COM server.  You can include the path information if necessary or copy the server to the project directory. This looks like: #import "SSCProt.dll" no_namespace  

    This import directive (when compiled) will create two header files ("SSCProt.tlh" and "SSCProt.tli"). These headers contain a template class definition for a smart-COM-pointer (of type _com_ptr_t) your application can use. There will be a definition for the COM servers typed interface defined inside.  You may also need to include AfxCtrl if this is not already included like this: 
    #include
    "AfxCtl.h"
  2. Declare a member of the main form of your application (or some module) of this type, like this:
    ISSCProtectorPtr spSSCProt;
  3. In the class wizard (View / Class Wizard) click New Class.  Create a class named CCPSink. Derive from CCmdTarget. Select Automation support radio button. In the Main dialog header file, #include "CPSink.h".  This class will be the sink for the events.  In the CPSink.cpp file include the header of the main form (EG: #include "MainForm.h").
  4. Declare a pointer member in the CPSink class to the applications main form. We do this in order to delegate events back to the main form.  In order to declare this pointer and avoid a circular reference we use a forward class declaration in the CPSink.h file like this:  

    class
    MainForm;
    class
    CCPSink : public CCmdTarget
    {
    ...
    CMainFormDlg * m_pRefMainForm;
    ...
    };

  5. In the CPSink.cpp file, find the interface map - it will probably look like this:

    BEGIN_INTERFACE_MAP(CCPSink, CCmdTarget)
    INTERFACE_PART(CCPSink, IID_ICPSink, Dispatch)
    END_INTERFACE_MAP()


    Change "IID_ICPSink" to "__uuidof(ISSCProtectorEvents)" so it looks like this:

    BEGIN_INTERFACE_MAP(CCPSink, CCmdTarget)
    INTERFACE_PART(CCPSink,
    __uuidof(ISSCProtectorEvents), Dispatch)
    END_INTERFACE_MAP()

  6. In the Main Form header file now declare the necessary variables to support the sink like this:
    CCPSink * m_pSink;
    DWORD m_dwCookie;

  7. In the class wizard, click on the Automation tab, select the CCPSink class in the class name combo box. Click Add Method. Add each event handler you need to respond to. You must enter the event parameters and the event handler name exactly: they are (You can also find these prototypes in the SSCProt.tlh file): 

    void
    OnMissingLicenseFile(LPCTSTR ExpectedFileNamePath, BSTR FAR* ActualFileNamePath)
    void
    OnAttempReleaseCP(LPCTSTR ReleaseCPAuthRequestCode, BSTR FAR* InputActivationCode)
    void
    OnAttemptRecover(LPCTSTR RecoverAuthRequestCode, BSTR FAR* InputActivationCode)
    void
    OnAttemptDeactivate(BOOL FAR* AllowDeactivate)

    These methods you define will be called when the ClientProtector fires the corresponding event.  In the case of this scenario (and our sample code)  we simply use these methods to delegate the function call back to the main form.

  8. Override the OnCreate method of the main form and create the instance for the smart pointer objects you have declared with CreateInstance(). Create the sink object. Connect the events emitted by the COM server to the sink object with AfxConnectionAdvise().

    Don't forget to call CoInitialize() to initialize the MFC COM support as you would normally.

    All that looks like this:
     

    CoInitialize(NULL);  
    //Initialize COM system 
    // lets make sure the ClientProtector COM server is still registered on this machine.


    HRESULT hr = spSSCProt.CreateInstance(_T("SSCProt.SSCprotector"));
    if (! SUCCEEDED(hr))
    {

    // if its not - inform the user of the problem and shut down.

    AfxMessageBox("Unable to connect to the license server. Please contact your vendor.");
    PostQuitMessage(0);

    return
    TRUE;
    }

    m_pSink =
    new CCPSink; // create an instance of the sink object
    m_pSink->m_pRefMainForm =
    this; // add a reference pointer so we can navigate back
    AfxConnectionAdvise(spSSCProt,
    __uuidof(ISSCProtectorEvents), m_pSink->GetIDispatch(FALSE), FALSE, &m_dwCookie);
    char
    * MainLicenseFileName = {"CP30TrialSample.ini"};
    char
    * MainLicenseFilePassword = {"eLiDEs_5_vacanCIes_>_belOnged"};
    char
    * GlobalAuthorizationCodePassword = {"gaggles_|_reaffirm_0_fOodstuff"};
    int
    FingerPrintOptionsCode = 6701175;

    long
    return_code;
    long
    debugFlags = 0;

    spSSCProt->StartUp(MainLicenseFileName,
          MainLicenseFilePassword,
          GlobalAuthorizationCodePassword,
          FingerPrintOptionsCode,
          debugFlags,
          &return_code);

  9. Use the object. Smart pointers manage their own reference counting and memory.  You should however call CoUnitialize() and disconnect the sink with AfxConnectionUnadvise() before you delete the sink object. If you get access violations on shut-down, try placing the CoUninitialize(); call in your applications OnFinalRelease function.  Like this:

    AfxConnectionUnadvise(spSSCProt,
    __uuidof(ISSCProtectorEvents),m_pSink->GetIDispatch(FALSE),FALSE,m_dwCookie);

    CoUninitialize();


    if
    (m_pSink!=NULL)
    {

    delete
    m_pSink; /*the sink destructor must be public or compiler will complain*/
    m_pSink=NULL;
    }

Related Topics