|
|
SoftwareShield
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.
- 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"
- Declare a member of the main form of your application
(or some module) of this type, like this:
ISSCProtectorPtr spSSCProt;
- 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").
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;
...
};
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()
In the Main Form header file now declare the necessary
variables to support the sink like this:
CCPSink * m_pSink;
DWORD m_dwCookie;
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.
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);
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;
}
|