Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    SNHookClass & MultiLicense

    SDK Help
    0
    7
    650
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 01/02/2013 at 07:40, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R14 
      Platform:      
      Language(s) :     C++  ;

      ---------
      I'm implementing the SNHookClass to allow the user enter the license for my plugin. What is the
      c4dsn String passed to ~:SNCheck(); when working on a MultiLicense environment?

      I'm asking because

      • I can't test it (don't have a MultiLicense environment lying around..)
      • GeGetSerialInfo() can be called for either retrieving the MutltiLicense or the
        generous license.

      Is it the 11 digits only and I have to manually check for a MultiLicense, or will be it be the 18
      characters long MultiLicense string (12345678912-ABCDEF) ?

      Thank you,
      Niklas

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 01/02/2013 at 08:14, xxxxxxxx wrote:

        Header

        ////////////////////////////////////////////////////////////////  
        // KDZSerial.h  
        ////////////////////////////////////////////////////////////////  
        // Serial Number handling  
        ////////////////////////////////////////////////////////////////  
        // V0.1 2011.04.21 Robert Templeton  
        ////////////////////////////////////////////////////////////////  
          
        // Includes  
        #include "general.h"  
        #include "lib_sn.h"  
          
        // KDZSerial: Serial Number Hook Class  
        class KDZSerial : public SNHookClass  
        {  
         private:  
             // Data  
             char            pcode[6];  
             const String    SNPluginName;  
             // Methods  
             Bool            checkSerial(const String& c4dsn, const String& sn);  
         public:  
             // Data  
             // - mode = 0 (not registered/not demo), 1 (demo), 2 (registered), 3 (C4D demo)  
             UCHAR            mode;  
             LONG            time;  
             // Methods  
             KDZSerial();  
             LONG            SNCheck(const String& c4dsn, const String& sn, LONG regdate, LONG curdate);  
             void            setPluginCode(const char* t_pcode);  
             const String&    GetTitle();  
        };
        
        ////////////////////////////////////////////////////////////////  
        // KDZSerial.cpp  
        ////////////////////////////////////////////////////////////////  
        // Serial Number handling  
        ////////////////////////////////////////////////////////////////  
        // V0.1 2011.04.21 Robert Templeton  
        ////////////////////////////////////////////////////////////////  
          
        // Includes  
        #ifdef MACOS  
          #include "Rijndael_Mac.h"  
        #else  
          #include "Rijndael.h"  
        #endif  
        #include "KDZSerial.h"  
          
        // Size of serial number string  
        #define ENTRY_SIZE                17  
          
        // KDZSerial: Serial Number Hook Class  
        // Methods  
        // - Constructor  
        //*---------------------------------------------------------------------------*  
        KDZSerial::KDZSerial() : SNPluginName(GeLoadString(KDZS_PLUGIN_NAME))  
        //*---------------------------------------------------------------------------*  
        {  
          mode =            0;  
        }  
        // - KDZSerial.setPluginCode  
        //*---------------------------------------------------------------------------*  
        void KDZSerial::setPluginCode(const char* t_pcode)  
        //*---------------------------------------------------------------------------*  
        {  
          memcpy(pcode, t_pcode, 6);  
        }  
        // - KDZSerial.checkSerial  
        //*---------------------------------------------------------------------------*  
        Bool KDZSerial::checkSerial(const String& c4dsn, const String& sn)  
        //*---------------------------------------------------------------------------*  
        {  
          // Key is 11-Digit C4D SN + 5-Char PluginCode + NullTerminator  
          char key[ENTRY_SIZE];  
          c4dsn.GetCString(&key[0], c4dsn.GetCStringLen()+1L, STRINGENCODING_7BIT);  
          memcpy(&key[11], &pcode[0], 6);  
          
          // Encrypt plugin serial no. using AES  
          char dout[ENTRY_SIZE] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";  
          // One block testing  
          CRijndael oRijndael;  
          if (!oRijndael.MakeKey(&key[0], "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16))  
          {  
              return MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), GeLoadString(KDZERR_SNMAKEKEY));  
          }  
          char din[ENTRY_SIZE];  
          memcpy(&din[0], &key[0], ENTRY_SIZE);  
          if (!oRijndael.EncryptBlock(din, dout))  
          {  
              return MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), GeLoadString(KDZERR_SNENCRYPTION));  
          }  
          dout[16] = 0;    // Null-terminate  
          
          UINT    i;  
          UCHAR    val;  
          // Convert to AlphaNumerics for user serial number entry  
          for (i = 0; i != 16; ++i)  
          {  
              val =    (UCHAR)dout[i];  
              // Beyond AlphaNumerics  
              if (val > 122)                    val /= 3;  
              // Below AlphaNumberics  
              if (val < 48)                    val += 48;  
              // Between numerals and UC Alpha  
              if ((val > 57) && (val < 65))    val += 24;  
              // Between UC Alpha and LC Alpha  
              if ((val > 90) && (val < 97))    val += 12;  
              dout[i] =    (char)val;  
          }  
          dout[16] = 0;    // Null-terminate  
          
          sn.GetCString(&key[0], sn.GetCStringLen()+1L, STRINGENCODING_7BIT); //ENTRY_SIZE, St7bit);  
          // Check sn against Encrypted-AlphaNumericized dout  
          for (i = 0; i != 16; ++i)  
          {  
              //GePrint("key["+LongToString(i)+"]=\'"+LongToString(key[i])+"\' == chk["+LongToString(i)+"]=\'"+LongToString(dout[i])+"\'");  
              if (key[i] != dout[i])  
              {  
                  return MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), GeLoadString(KDZERR_SNINVALID));  
              }  
          }  
          return TRUE;  
        }  
        // - SNHookClass.SNCheck  
        //*---------------------------------------------------------------------------*  
        LONG KDZSerial::SNCheck(const String& c4dsn, const String& sn, LONG regdate, LONG curdate)  
        //*---------------------------------------------------------------------------*  
        {  
          if (!sn.Content())    return SN_WRONGNUMBER;  
          
          // Demo mode (30 day trial)  
          if (sn.GetLength() == 4L)  
          {  
              // Case-insensitive serial number 'demo'  
              String    demo =                sn.ToLower();  
              if (demo.Compare("demo"))    return SN_WRONGNUMBER;  
          
              if (!regdate)  
              {  
                  mode =    1;  
                  return SN_OKAY;  
              }  
          
              // Calculate timeout of Demo mode  
              // - elapsed time since registering demo  
              LONG    exptime =        curdate - regdate;  
              // - Number of demo days  
              LONG    expiration =    30L;  
              LONG    timeout =        expiration-exptime;  
              if (timeout < 0L)        return SN_EXPIRED;  
              time =                    timeout;  
              mode =                    1;  
              if (exptime >= (expiration-3L))    return SN_EXPIRE_14 - timeout;  
              return SN_OKAY;  
          }  
          // Registered user  
          else if (sn.GetLength() == 16L)  
          {  
              if (checkSerial(c4dsn, sn))  
              {  
                  mode =    2;  
                  return SN_OKAY;  
              }  
          }  
        #ifdef    C4D_R11  
          // Multi-License Server  
          else  
          {  
              // Check for R11 Multi-License  
              SerialInfo    mlsn;  
              GeGetSerialInfo(SERIALINFO_MULTILICENSE, &mlsn);  
              if (mlsn.nr.Content())  
              {  
                  //--------------------------------------------------------------------------------  
                  // Note that we also need to skip over the extra data added to the front of the  
                  // plugin's license key (11 digits/characters and a dash)...  
                  //--------------------------------------------------------------------------------  
                  String    plug_sn =    sn;  
                  LONG dashPos;  
                  if (plug_sn.FindFirst("-", &dashPos, 0L))  
                  {  
                      plug_sn = plug_sn.SubStr(dashPos+1L, plug_sn.GetLength()-dashPos-1L);  
                      if (checkSerial(mlsn.nr, plug_sn))  
                      {  
                          mode =    2;  
                          return SN_OKAY;  
                      }  
                  }  
              }  
          }  
        #else  
          else    MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), GeLoadString(KDZERR_SNSIZE));  
        #endif  
          
          return SN_WRONGNUMBER;  
        }  
        // - SNHookClass.GetTitle  
        //*---------------------------------------------------------------------------*  
        const String& KDZSerial::GetTitle()  
        //*---------------------------------------------------------------------------*  
        {  
          return SNPluginName;  
        }
        
        ////////////////////////////////////////////////////////////////  
        // Main.cpp  
        ////////////////////////////////////////////////////////////////  
        // SymMorphy  
        ////////////////////////////////////////////////////////////////  
        // V0.1 2011.05.25 Robert Templeton  
        ////////////////////////////////////////////////////////////////  
          
        // Includes  
        #include "KDZSerial.h"  
          
        // - To allow future demo for users who have already demoed a previous version  
        // - Note that it is in the code to avoid user changing ID  
        enum  
        {  
          ID_SYMMORPHY_DEMO        =    1029219  
        };  
          
        static KDZSerial* kdzSerial =    NULL;  
          
        //*---------------------------------------------------------------------------*  
        Bool RegisterKDZSerial()  
        //*---------------------------------------------------------------------------*  
        {  
          kdzSerial =            gNew KDZSerial();  
          if (!kdzSerial)        return MessageSystem::Throw(GeLoadString(KDZERR_MEMORY), "Main.RegisterKDZSerial.kdzSerial");  
          char    pcode[6] =    "symmy";  
          kdzSerial->setPluginCode(&pcode[0]);  
          if (!kdzSerial->Register(ID_SYMMORPHY, SNFLAG_OWN))  
              return kdzSerial->Register(ID_SYMMORPHY_DEMO, SNFLAG_OWN);  
          return TRUE;  
        }  
        //*---------------------------------------------------------------------------*  
        void FreeKDZSerial()  
        //*---------------------------------------------------------------------------*  
        {  
          gDelete(kdzSerial);  
        }  
          
          
        // Plugin Functions ==================================================================================================  
          
        #include "SymMorphyDoc.h"  
          
        // Declare Global Plugin Registrants  
        Bool            RegisterSymMorphyTag();  
        SymMorphyDoc*    RegisterSymMorphyDoc();  
        Bool            RegisterSymMorphySceneHook();  
          
        static SymMorphyDoc*    symmorphydoc =        NULL;  
          
        //*---------------------------------------------------------------------------*  
        Bool PluginStart()  
        //*---------------------------------------------------------------------------*  
        {  
          Bool    network =                                        FALSE;  
        #ifdef    C4D_R12  
          VERSIONTYPE    vtype =        GeGetVersionType();  
          SYSTEMINFO    stype =        GeGetSystemInfo();  
          if ((vtype == VERSIONTYPE_NET_SERVER_3) || (vtype == VERSIONTYPE_NET_SERVER_UNLIMITED) || (vtype == VERSIONTYPE_NET_CLIENT))    network = TRUE;  
          if        (stype & SYSTEMINFO_DEMO)                                                                GePrint("C4D Demo");  
          else if (stype & (SYSTEMINFO_SAVABLEDEMO|SYSTEMINFO_SAVABLEDEMO_ACTIVE))                        GePrint("C4D Savable Demo");  
        #ifdef    C4D_R13  
          else if (stype & (SYSTEMINFO_SAVABLEDEMO|SYSTEMINFO_STUDENT))                                    GePrint("C4D Student Demo");  
        #endif  
          else if (stype & SYSTEMINFO_COMMANDLINE)                                                        GePrint("C4D CommandLine");  
          else if ((vtype == VERSIONTYPE_NET_SERVER_3) || (vtype == VERSIONTYPE_NET_SERVER_UNLIMITED))    GePrint("C4D Server");  
          else if (vtype == VERSIONTYPE_NET_CLIENT)                                                        GePrint("C4D Client");  
          else  
          {  
              // serial number check  
              if (!(kdzSerial && kdzSerial->mode)) return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart:serial check failed!");  
          }  
        #elif defined    C4D_R11  
          LONG    vtype =                                            GeGetVersionType();  
          if ((vtype & VERSION_SERVER) || (vtype & VERSION_NET))    network = TRUE;  
          if        (vtype & VERSION_DEMO)                            GePrint("C4D Demo");  
          else if (vtype & VERSION_SAVABLE)                        GePrint("C4D Savable Demo");  
          else if (vtype & VERSION_SERVER)                        GePrint("C4D Server");  
          else if (vtype & VERSION_NET)                            GePrint("C4D Net");  
          // serial number check  
          else if (!(kdzSerial && kdzSerial->mode))                return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart:serial check failed!");  
        #else  
          LONG    vtype =                                            GeGetVersionType();  
          if ((vtype & VERSION_SERVER) || (vtype & VERSION_NET))    network = TRUE;  
          if (!((vtype & VERSION_DEMO) || network))  
          {  
              // serial number check  
              if (!(kdzSerial && kdzSerial->mode))                return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart:serial check failed!");  
          }  
        #endif  
          
          GePrint(" ");  
          GePrint(GeLoadString(KDZS_PLUGIN_BANNER));  
          GePrint("-- "+GeLoadString(KDZS_PLUGIN_NAME)+GeLoadString(KDZS_PLUGIN_EDITION)+"v"+GeLoadString(KDZS_PLUGIN_VERSION)+" "+GeLoadString(KDZS_PLUGIN_COPYRIGHT));  
          if (kdzSerial)  
          {  
              if        (kdzSerial->mode == 1)                        GePrint("-- Trial: "+LongToString(kdzSerial->time)+" days left");  
              else if (kdzSerial->mode == 2)  
              {  
                  SerialInfo    si;  
                  GeGetSerialInfo(SERIALINFO_CINEMA4D, &si);  
                  GePrint("-- Licensed to: "+si.name);  
              }  
          }  
          GePrint(GeLoadString(KDZS_PLUGIN_BANNER));  
          GePrint(" ");  
          
          // Register hooks and return  
          // - SymMorphy Demo or Registered  
          symmorphydoc =                                            RegisterSymMorphyDoc();  
          if (!symmorphydoc)                                        return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart.RegisterSymMorphyDoc() failed!");  
          if (kdzSerial)  
          {  
              if (!symmorphydoc->Initialize(network, kdzSerial->mode, kdzSerial->time))    return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart.SymMorphyDoc.Initialize() failed!");  
          }  
          // - Cinema 4D Demo  
          else  
          {  
              if (!symmorphydoc->Initialize(network, 3L, 2147483647L))    return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart.SymMorphyDoc.Initialize() failed!");  
          }  
          if (!RegisterSymMorphyTag())                                return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart.RegisterSymMorphyTag() failed!");  
          if (!RegisterSymMorphySceneHook())                            return ErrPrt(GeLoadString(KDZS_PLUGIN_NAME)+".Main.PluginStart.RegisterSymMorphySceneHook() failed!");  
          return TRUE;  
        }  
          
        //*---------------------------------------------------------------------------*  
        void PluginEnd()  
        //*---------------------------------------------------------------------------*  
        {  
        }  
          
        //*---------------------------------------------------------------------------*  
        Bool PluginMessage(LONG id, void* data)  
        //*---------------------------------------------------------------------------*  
        {  
          if        (id == C4DPL_INIT_SYS)  
          {  
              // initialize global resource object  
              if (!resource.Init())    return ErrPrt("Main.PluginMessage.resource.Init() failed!");  
          
              Bool    network =        FALSE;  
              Bool    serial =        TRUE;  
              // initialize and register Serial Number Hook  
        #ifdef    C4D_R12  
              VERSIONTYPE    vtype =        GeGetVersionType();  
              SYSTEMINFO    stype =        GeGetSystemInfo();  
              if        (stype & SYSTEMINFO_DEMO)                                                            { GePrint("C4D Demo");            serial = FALSE; }  
              else if (stype & (SYSTEMINFO_SAVABLEDEMO|SYSTEMINFO_SAVABLEDEMO_ACTIVE))                    { GePrint("C4D Savable Demo");    serial = FALSE; }  
        #ifdef    C4D_R13  
              else if (stype & (SYSTEMINFO_SAVABLEDEMO|SYSTEMINFO_STUDENT))                                { GePrint("C4D Student Demo");    serial = FALSE; }  
        #endif  
              else if (stype & SYSTEMINFO_COMMANDLINE)                                                    { GePrint("C4D CommandLine");    serial = FALSE; }  
              if ((vtype == VERSIONTYPE_NET_SERVER_3) || (vtype == VERSIONTYPE_NET_SERVER_UNLIMITED))        { GePrint("C4D Server");        serial = FALSE; network = TRUE; }  
              else if (vtype == VERSIONTYPE_NET_CLIENT)                                                    { GePrint("C4D Net");            serial = FALSE; network = TRUE; }  
        #elif defined    C4D_R11  
              LONG    vtype = GeGetVersionType();  
              if        (vtype & VERSION_SERVER)    { GePrint("C4D Server");        serial = FALSE; network = TRUE; }  
              else if (vtype & VERSION_NET)        { GePrint("C4D Net");            serial = FALSE; network = TRUE; }  
              else if    (vtype & VERSION_DEMO)        { GePrint("C4D Demo");            serial = FALSE; }  
              else if (vtype & VERSION_SAVABLE)    { GePrint("C4D Savable Demo");    serial = FALSE; }  
        #else  
              LONG    vtype =    GeGetVersionType();  
              if        (vtype & VERSION_SERVER)    { serial = FALSE; network = TRUE; }  
              else if (vtype & VERSION_NET)        { serial = FALSE; network = TRUE; }  
              else if (vtype & VERSION_DEMO)        { serial = FALSE; }  
        #endif  
          
              // Allocate SymMorphy Data Storage  
              if (serial) return RegisterKDZSerial();  
              else        return TRUE;  
          }  
          else if (id == C4DPL_ENDACTIVITY)  
          {  
              FreeKDZSerial();  
              return TRUE;  
          }  
          else if (id == C4DMSG_PRIORITY)        return TRUE;  
          return FALSE;  
        }  
          
        // Return SymMorphyDoc* symmorphydoc - globally accessible  
        //*---------------------------------------------------------------------------*  
        SymMorphyDoc* GetSymMorphyDoc()  
        //*---------------------------------------------------------------------------*  
        {  
          return symmorphydoc;  
        }
        
        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 01/02/2013 at 08:15, xxxxxxxx wrote:

          Giblet has a very informative post here that outlines the required format of the serial number for the Maxon License Server for plugin registration. The post is: "R11 License Server & SNHookClass"

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 05/02/2013 at 15:09, xxxxxxxx wrote:

            @NiklasR:

            Here is the Link to "R11 License Server & SNHookClass", mentioned by Robert.
            Indeed a very informative thread.

            And there is a 5 part tutorial about licensing plugins at the "C4D Programming Blog" that also might be interesting for you to read.
            Even though there is no extra information about a License Server implementation to find.

            @kuroyume0161:

            Thank you Robert for your whole licensing source code(s).
            I already have a working solution for myself but I think I'll take a look at yours too and maybe could get some ideas for improvements of my own.
            E.G. I still wasn't able to implement a time limited demo mode that really would work as expected.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 06/02/2013 at 03:33, xxxxxxxx wrote:

              Great to have another open piece of source code for C4D !
              Thank you! Lets lock what new I can learn from it.

              May be we could start GitHub for all the code? 🙂

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 06/02/2013 at 03:42, xxxxxxxx wrote:

                Thank you very much for the reference, Robert! 🍺

                >>> May be we could start GitHub for all the code? 🙂

                + 1 !!!!!

                I already have some C4D related stuff on my GitHub profile:  https://github.com/NiklasRosenstein

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 06/02/2013 at 04:00, xxxxxxxx wrote:

                  I have some code here:
                  http://code.google.com/p/code-editor-gui/source/browse/

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post