home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Internet 2000 May / MICD_2000_05.iso / CBuilder5 / INSTALL / DATA1.CAB / Program_Built_Files / Include / Atl / atlmod.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-01  |  25.3 KB  |  910 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // ATLMOD.H - Helper classes (based on ATL) used by CBuilder ActiveX Servers
  3. //
  4. // $Revision:   1.25.1.11  $
  5. // $Date:   21 Jan 2000 15:56:52  $
  6. //
  7. // Copyright (c) 1999, 2000 Borland International
  8. /////////////////////////////////////////////////////////////////////////////
  9.  
  10. #if !defined(_ATLMOD_H)
  11. #define _ATLMOD_H
  12.  
  13. #pragma option push -VF
  14.  
  15. // These are required due to RTL differences between VC++ and BCB
  16. //
  17. #define _ATL_NO_FORCE_LIBS
  18. #define _ATL_NO_DEBUG_CRT
  19.  
  20. // Defines _ASSERTE et al.
  21. //
  22. #include <utilcls.h>
  23.  
  24. // ATL's Base header
  25. //
  26. #if !defined(__ATLBASE_H)
  27.   #include <atl\atlbase.h>
  28. #endif
  29.  
  30. #include <objbase.h>
  31. #include <cguid.h>
  32. #include <dir.h>
  33.  
  34. // Local Servers are assumed to be VCL-based
  35. //
  36. #if !defined(__DLL__)
  37. #define USING_VCL
  38. #endif
  39.  
  40. #if defined(USING_VCL)
  41. #include <comconst.hpp>
  42. #include <sysutils.hpp>
  43. #endif
  44.  
  45. // Enumerations for Instancing, ThreadingModel etc...
  46. //
  47. enum ObjectInstancing
  48. {
  49.   ioInternalInstance,       // Object is *NOT* exposed to Clients via CoCreateInstance
  50.   ioSingleInstance,         //
  51.   ioMultiInstance,          //
  52.   oiAmbientInstancing       // Determine based on definition of _ATL_xxxx_THREADED macro
  53. };
  54.  
  55. enum ObjectThreadingModel
  56. {
  57.   otSingle,                 //
  58.   otApartment,
  59.   otFree,
  60.   otBoth,
  61.   otNeutral,
  62.   otAmbientThreadModel      // Use global settings based on _ATL_xxxx_INSTANCING
  63. };
  64.  
  65. // Default MiscStatus Flags of Object
  66. //
  67. const DWORD dwDefaultControlMiscFlags = OLEMISC_RECOMPOSEONRESIZE | OLEMISC_CANTLINKINSIDE |
  68.                                         OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE |
  69.                                         OLEMISC_SETCLIENTSITEFIRST;
  70.  
  71. // Declares routine that provide static accessors to various OBJECT attributes
  72. //
  73. #define DECLARE_OLEMISC_FLAGS(flags)  static DWORD   _GetObjectMiscStatus(){ return flags; }
  74. #define DECLARE_PROGID(progid)        static LPCTSTR GetProgID()           { return progid;}
  75. #define DECLARE_DESCRIPTION(desc)     static LPCTSTR GetDescription()      { return desc;  }
  76. #define DECLARE_THREADING_MODEL(thrd) static ObjectThreadingModel GetThreadModel() { return thrd; }
  77.  
  78. // Declares tables of Verbs (Actions) support by object
  79. //
  80. #define BEGIN_VERB_MAP()            \
  81. static const OLEVERB* _GetVerbs()   \
  82. {                                   \
  83.   static const OLEVERB  _verbs[]=   \
  84.   {
  85.  
  86. #define VERB_ENTRY_EX(verbId, verbString, mfFlags, verbAttrib)  \
  87.       {verbId, verbString, mfFlags, verbAttrib },
  88.  
  89. #define VERB_ENTRY(verbId, verbString)  \
  90.          VERB_ENTRY_EX(verbId, verbString, 0 /* No MF_xxxx Flags */, OLEVERBATTRIB_ONCONTAINERMENU)
  91.  
  92. #define END_VERB_MAP()  \
  93.       { 0, 0, 0, 0 }    \
  94.   };                    \
  95.   return _verbs;        \
  96. };
  97.  
  98.  
  99.  
  100. // TATLModule enhances ATL's CComModule (i.e. T is assumed to be CComModule or a
  101. //                                       CComModule-derived class)
  102. // It is designed to support both in-process and out-of-process servers and handle
  103. // some VCL requirements (if USING_VCL is defined)
  104. //
  105. template <class T = CComModule>
  106. class TATLModule: public T
  107. {
  108. public:
  109.   TATLModule();
  110.  
  111. #if defined(USING_VCL)
  112.   // Used by Local Servers using VCL
  113.   //
  114.   TATLModule(TProcedure InitProcedure);
  115. #endif
  116.  
  117.  ~TATLModule();
  118.  
  119. #if defined(USING_VCL)
  120.   LONG        Unlock();
  121. #endif
  122.   // Data members of TATLModule<T>
  123.   //
  124.   DWORD       m_ThreadID;             // Thread identifier of module
  125.   bool        m_bRun;                 // Flags whether to run server
  126.   bool        m_bExe;                 // Flags Local server
  127.   bool        m_bAutomationServer;    // Flags module's for Automation Server
  128.   TInitOle*    m_InitOle;              // Object to initialize OLE
  129.  
  130. #if defined(USING_VCL)
  131.   // Routine used to initialize/cleandup .EXE server using VCL
  132.   //
  133.   static  void __fastcall InitATLServer();
  134.   static  bool __fastcall AutomationTerminateProc();
  135.   static  TProcedure      SaveInitProc;   // Holds system's old InitProcedure
  136.  
  137.   void    DoFileAndObjectRegistration();
  138. #endif
  139. };
  140.  
  141.  
  142. // Constructor used by In-Proc servers (and Out-of-proc servers not using VCL)
  143. //
  144. template <class T>
  145. TATLModule<T>::TATLModule() : m_ThreadID(0), m_bRun(true), m_bExe(false), m_bAutomationServer(false)
  146. {
  147.   m_InitOle = new TInitOle;
  148.   // Could ensure OLE was properly initialized
  149.   /*
  150.   _ASSERTE(!!m_InitOle);
  151.   */
  152. }
  153.  
  154.  
  155. // Constructor used by Out-of-proc servers using VCL
  156. //
  157. #if defined(USING_VCL)
  158.  
  159. template <class T>
  160. TATLModule<T>::TATLModule(TProcedure initProcedure): m_ThreadID(0), m_bRun(true),
  161.                                                      m_bExe(true), m_bAutomationServer(false)
  162. {
  163.   // Could ensure OLE was properly initialized
  164.   /*
  165.   _ASSERTE(!!m_InitOle);
  166.   */
  167.  
  168.   // Have default Initialization Procedure if none was specified
  169.   //
  170.   if (!initProcedure)
  171.     initProcedure = TATLModule<T>::InitATLServer;
  172.  
  173.   // Plug in our Initialization procedure
  174.   //
  175.   if (m_bExe && initProcedure)
  176.   {
  177.     SaveInitProc = TProcedure(System::InitProc);
  178.     System::InitProc = initProcedure;
  179.   }
  180. }
  181.  
  182. #endif  // USING_VCL
  183.  
  184.  
  185. // If we're a running out-of-proc server, we revoke registered objects
  186. //
  187. template <class T>
  188. TATLModule<T>::~TATLModule()
  189. {
  190.   if (m_bRun && m_bExe)
  191.   {
  192.     RevokeClassObjects();
  193.   }
  194.  
  195.   if (!(m_bExe)) {
  196.     delete m_InitOle;
  197.   }
  198. }
  199.  
  200. #if defined(USING_VCL)
  201.  
  202. // Performs registration based on switches passed to application
  203. // Invoked only for local servers
  204. //
  205. template <class T>
  206. void TATLModule<T>::DoFileAndObjectRegistration()
  207. {
  208.   TSysCharSet DelimSet;
  209.   DelimSet << '/' << '-';
  210.  
  211.   if (FindCmdLineSwitch("REGSERVER", DelimSet, true))
  212.   {
  213.     RegisterServer(TRUE);
  214.     m_bRun = false;
  215.   }
  216.   else if (FindCmdLineSwitch("UNREGSERVER", DelimSet, true))
  217.   {
  218.     UnregisterServer();
  219.     m_bRun = false;
  220.   }
  221.   else if (!(FindCmdLineSwitch("AUTOMATION", DelimSet, true) ||
  222.              FindCmdLineSwitch("EMBEDDING", DelimSet, true)))
  223.   {
  224.     RegisterServer(TRUE);
  225.   }
  226.  
  227.   if (m_bRun)
  228.   {
  229. #ifdef _ATL_SINGLEUSE_INSTANCING
  230.       RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE);
  231. #else
  232.       RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
  233. #endif
  234.   }
  235.   else
  236.     exit(EXIT_SUCCESS);
  237. }
  238.  
  239. #endif  // USING_VCL
  240.  
  241.  
  242. #if defined(USING_VCL)
  243. // Override's CComModule's Unlock to post a WM_QUIT message for out-of-proc servers
  244. //
  245. template <class T>
  246. LONG TATLModule<T>::Unlock()
  247. {
  248.   LONG result = T::Unlock();
  249.   if ((result == 0) && m_bExe)
  250.   {
  251.     // If this EXE was launched by OLE (as an Automation Server), then terminate.
  252.     //
  253.     TSysCharSet DelimSet;
  254.     DelimSet << '/' << '-';
  255.     if (FindCmdLineSwitch("AUTOMATION", DelimSet, true))
  256.       ::PostThreadMessage(m_ThreadID, WM_QUIT, 0, 0);
  257.   }
  258.   return result;
  259. }
  260. #endif
  261.  
  262. // _Module is assumed to be a reference to a TComModule
  263. // User may define _Module to be a ref. to an instance of a class derived
  264. // from TComModule.
  265. //
  266. typedef TATLModule<CComModule> TComModule;
  267. extern TComModule &_Module;
  268.  
  269.  
  270. #if defined(USING_VCL)
  271.  
  272. // Variable used to store original System's InitProc
  273. //
  274. template <class T>
  275. TProcedure TATLModule<T>::SaveInitProc = 0;
  276.  
  277. // To be defined in the Project's source
  278. //
  279. extern _ATL_OBJMAP_ENTRY ObjectMap[];
  280.  
  281. // Routine used to initialize EXE ATL Servers that use VCL
  282. // This routine is set as System's InitProc - allowing us to initialize a
  283. // variables before chaining off to the original InitProcedure...
  284. //
  285. //
  286. template <class T>
  287. void __fastcall TATLModule<T>::InitATLServer()
  288. {
  289.   // Invoke previous InitProcedure in the chain
  290.   //
  291.   if (SaveInitProc)
  292.     SaveInitProc();
  293.  
  294.   _Module.Init(ObjectMap, Sysinit::HInstance);
  295.   _Module.m_ThreadID = ::GetCurrentThreadId();
  296.   _Module.m_bAutomationServer = true;
  297.   _Module.DoFileAndObjectRegistration();
  298.   AddTerminateProc(AutomationTerminateProc);
  299. }
  300.  
  301.  
  302. // AutomationTerminateProc
  303. //
  304. // Verifies if a Server was launched with the /Automation switch and warns
  305. // user of attempt to unload Server currently being automated.
  306. //
  307.  
  308. template <class T>
  309. bool __fastcall TATLModule<T>::AutomationTerminateProc()
  310. {
  311.  
  312.   if (_Module.GetLockCount() > 0)
  313.   {
  314.     return ::MessageBoxA(0, (Comconst_SNoCloseActiveServer1 + Comconst_SNoCloseActiveServer2).c_str(),
  315.                          Comconst_SAutomationWarning.c_str(),
  316.                          MB_YESNO|MB_TASKMODAL|MB_ICONWARNING|MB_DEFBUTTON2) == IDYES;
  317.   }
  318.   else
  319.     // if there are no outstanding lock, it's OK to terminate
  320.     //
  321.     return true;
  322. }
  323.  
  324. #endif  // USING_VCL
  325.  
  326. // BCC32's paranoid about operator ambiguities
  327. //
  328. #if defined(__BORLANDC__)
  329. #pragma option push -w-prc
  330. #endif
  331.  
  332. #if !defined(__ATLCOM_H__)
  333.   #include <atl\atlcom.h>
  334. #endif
  335. #include   <shellapi.h>
  336. #if !defined(__ATLCTL_H__)
  337.   #include <atl\atlctl.h>
  338. #endif
  339.  
  340. #if defined(__BORLANDC__)
  341. #pragma option pop
  342. #endif
  343.  
  344. class TFakeRegistrarType
  345. {
  346. public:
  347.   DECLARE_THREADING_MODEL(otAmbientThreadModel);
  348. };
  349.  
  350. // Provides basic registry support (Add, delete and nuke a key)
  351. //
  352. template <class T>
  353. class TRegistrarBaseT
  354. {
  355. public:
  356.   // Helpers to create/delete registry keys
  357.   //
  358.   static HRESULT  CreateRegKey(LPCTSTR Key, LPCTSTR ValueName, LPCTSTR Value);
  359.   static HRESULT  DeleteRegKey(LPCTSTR Key);
  360.   static HRESULT  NukeRegKey(LPCTSTR Key);
  361.  
  362.   // Converts a GUID to string
  363.   //
  364.   static HRESULT GUIDToString(const GUID& guid, TAPtr<TCHAR>& gstr);
  365. };
  366.  
  367. // Creates a Registry Key
  368. //
  369. template <class T>
  370. HRESULT TRegistrarBaseT<T>::CreateRegKey(LPCTSTR keyStr, LPCTSTR ValueName, LPCTSTR Value)
  371. {
  372.   CRegKey key;
  373.   HRESULT status = key.Create(HKEY_CLASSES_ROOT, keyStr);
  374.  
  375.   if (status == ERROR_SUCCESS)
  376.   {
  377.     status = key.SetValue(Value, ValueName);
  378.  
  379. #if defined(SHOW_CREATEREGKEY_VALUES)
  380.     TCHAR dbgMsg[_MAX_PATH*3];
  381.     wsprintf(dbgMsg, _T("%s=%s [%s]"), keyStr, ValueName, Value);
  382.     ::MessageBox(0, dbgMsg, keyStr, MB_OK);
  383. #endif
  384.   }
  385.   return status;
  386. }
  387.  
  388. // Deletes a Registry Key
  389. // NOTE: A quirk of Windows is that under Win95, ::RegDeleteKey also deletes all descendants
  390. //       whereas under NT the subkey to be deleted must not have subkeys.
  391. //
  392. template <class T>
  393. HRESULT TRegistrarBaseT<T>::DeleteRegKey(LPCTSTR keyStr)
  394. {
  395.   return ::RegDeleteKey(HKEY_CLASSES_ROOT, keyStr);
  396. }
  397.  
  398. // Delete a Registry Key and all subkeys
  399. //
  400. template <class T>
  401. HRESULT TRegistrarBaseT<T>::NukeRegKey(LPCTSTR keyStr)
  402. {
  403.   // Open the Key
  404.   //
  405.   CRegKey key;
  406.   key.Attach(HKEY_CLASSES_ROOT);
  407.   return key.RecurseDeleteKey(keyStr);
  408. }
  409.  
  410. // Convert GUID to String
  411. //
  412. template <class T>
  413. HRESULT TRegistrarBaseT<T>::GUIDToString(const GUID& guid, TAPtr<TCHAR>& gstr)
  414. {
  415.   LPOLESTR wstr;
  416.   HRESULT hr = ::StringFromCLSID(guid, &wstr);
  417.   if (hr != S_OK)
  418.     return hr;
  419. #if !defined(UNICODE) && !defined(_UNICODE)
  420.   gstr = WideToAnsi(wstr);
  421. #else
  422.   gstr = strnewdup(wstr);
  423. #endif
  424.   ::CoTaskMemFree(wstr);
  425.   return hr;
  426. }
  427.  
  428.  
  429.  
  430. // TComServerRegistrar class performs registration for a COM server.
  431. // An instance of this class is typically created via the
  432. // DECLARE_COMSERVER_REGISTRY macro.
  433. //
  434. template <class T>
  435. class TComServerRegistrarT : TRegistrarBaseT<T>
  436. {
  437. public:
  438.   TComServerRegistrarT();
  439.   TComServerRegistrarT(const CLSID& clsid, LPCTSTR progID, LPCTSTR description);
  440.  ~TComServerRegistrarT();
  441.  
  442.   // Virtual method overriden by various Registrars to carry our Registration tasks
  443.   //
  444.   virtual HRESULT UpdateRegistry(bool Register);
  445.  
  446. protected:
  447.   LPCTSTR                 m_ProgID;           // Programmatic Identifier
  448.   CLSID                   m_ClassID;          // GUID of Object to be registered
  449.   TAPtr<TCHAR>            m_Description;      // Description of CoClass
  450.   TAPtr<TCHAR>            m_ClassIDstr;       // {xxxxxxxx-xxxx-... }
  451.   TAPtr<TCHAR>            m_ClassKey;         // CLSID\{xxxxxxxx-xxxx}
  452.   TAPtr<TCHAR>            m_ServerType;       // LocalServer32 or InprocServer32
  453.   TAPtr<TCHAR>            m_ModuleName;       // Full path to server
  454.  
  455.   // Helper routine to initialize some data members of class
  456.   //
  457.   void                    Init();
  458. };
  459.  
  460. // CBuilder3 compatible registrar type
  461. //
  462. typedef TComServerRegistrarT<TFakeRegistrarType> TComServerRegistrar;
  463.  
  464.  
  465. template <class T>
  466. TComServerRegistrarT<T>::TComServerRegistrarT() : m_ClassID(0), m_ProgID(0)
  467. {
  468.   Init();
  469. }
  470.  
  471. template <class T>
  472. TComServerRegistrarT<T>::TComServerRegistrarT(const CLSID& clsid, LPCTSTR progID, LPCTSTR description) :
  473.                                              m_ClassID(clsid),
  474.                                              m_ProgID(progID),
  475.                                              m_Description((description && *description) ?
  476.                                                            TStringConverter<TCHAR>::strnewdup(description) : 0)
  477. {
  478.   Init();
  479. }
  480.  
  481. template <class T>
  482. TComServerRegistrarT<T>::~TComServerRegistrarT()
  483. {}
  484.  
  485.  
  486. // Initialize variables required for registering server
  487. //
  488. template <class T> void
  489. TComServerRegistrarT<T>::Init()
  490. {
  491.   // Retrieve name of this module
  492.   //
  493.   TAPtr<TCHAR> longModuleName = new TCHAR[_MAX_PATH];
  494.   ::GetModuleFileName(_Module.m_hInst, longModuleName, _MAX_PATH);
  495.  
  496.   // Determine whether there are spaces in the module path/name
  497.   //
  498.   bool hasSpace = false;
  499.   for (int i=0; longModuleName[i]; i++)
  500.     if (isspace(longModuleName[i]))
  501.     {
  502.       hasSpace = true;
  503.       break;
  504.     }
  505.  
  506.   // Convert to shortpath (NT4's CreateProcess bug) if there's a space
  507.   //
  508.   if (hasSpace)
  509.   {
  510.     m_ModuleName = new TCHAR[_MAX_PATH];
  511.     ::GetShortPathName(longModuleName, m_ModuleName, _MAX_PATH);
  512.   }
  513.   else
  514.     // Transfer ownership of buffer;
  515.     //
  516.     m_ModuleName = longModuleName;
  517.  
  518.   // Create string of CLSID
  519.   //
  520.   GUIDToString(m_ClassID, m_ClassIDstr);
  521.  
  522.   // CLSID\{xxxxx-xxx-xx-xx} key
  523.   //
  524.   m_ClassKey = new TCHAR[_MAX_PATH];
  525.   lstrcpy(m_ClassKey, _T("CLSID\\"));
  526.   lstrcat(m_ClassKey, m_ClassIDstr);
  527.  
  528.   // Create string for server type
  529.   //
  530.   if (_Module.m_bExe)
  531.     m_ServerType = strnewdup(_T("\\LocalServer32"));
  532.   else
  533.     m_ServerType = strnewdup(_T("\\InprocServer32"));
  534. }
  535.  
  536. template <class T>
  537. bool IsEqual(T t1, T t2)
  538. {
  539.   return t1 == t2;
  540. }
  541.  
  542. // Perform actual (Un)Registration
  543. //
  544. template <class T> HRESULT
  545. TComServerRegistrarT<T>::UpdateRegistry(bool bRegister)
  546. {
  547.   if (bRegister)
  548.   {
  549.     static TCHAR szAutomation[] = _T(" /Automation");
  550.  
  551.     // Create registry entries
  552.     //
  553.     CreateRegKey(m_ClassKey, _T(""), m_Description);
  554.  
  555.     // ClassKey\ServerType
  556.     //
  557.     TAPtr<TCHAR> key(new TCHAR[_MAX_PATH]);
  558.     lstrcpy(key, m_ClassKey);
  559.     lstrcat(key, m_ServerType);
  560.  
  561.     // Copy over module name
  562.     //
  563.     TAPtr<TCHAR> mod(new TCHAR[_MAX_PATH + sizeof(szAutomation)]);
  564.     lstrcpy(mod, m_ModuleName);
  565.  
  566.     // Make sure we have /Automation on EXE Automation Servers
  567.     //
  568.     if (_Module.m_bExe && _Module.m_bAutomationServer)
  569.       lstrcat(mod, szAutomation);
  570.  
  571.     // Register ClassKey\ServerType
  572.     //
  573.     CreateRegKey(key, _T(""), mod);
  574.  
  575.     // Store Threading Model
  576.     // Ambient relies on defines (a la CBuilder3)
  577.     //
  578.     LPCTSTR szThrdMdl = _T("ThreadingModel");
  579.     if (IsEqual(T::GetThreadModel(), otAmbientThreadModel))
  580.     {
  581. #if   defined(_ATL_SINGLE_THREADED)
  582.       CreateRegKey(key, szThrdMdl, _T("Single"));
  583. #elif defined(_ATL_BOTH_THREADED)
  584.       CreateRegKey(key, szThrdMdl, _T("Both"));
  585. #elif defined(_ATL_APARTMENT_THREADED)
  586.       CreateRegKey(key, szThrdMdl, _T("Apartment"));
  587. #elif defined(_ATL_NEUTRAL_THREADED)
  588.       if (IsComPlusPlatform<int>()) CreateRegKey(key, szThrdMdl, _T("Neutral"))
  589.       else CreateRegKey(key, szThrdMdl, _T("Apartment"));
  590. #elif defined(_ATL_FREE_THREADED)           // NOTE: Check _ATL_FREE_THREADED last
  591.                                             //       because ATLBASE.H defines it for BOTH
  592.       CreateRegKey(key, szThrdMdl, _T("Free"));
  593. #else
  594.       CreateRegKey(key, _T("NoThreadingModel"), _T(""));
  595. #endif
  596.     }
  597.     else if (IsEqual(T::GetThreadModel(), otSingle))
  598.     {
  599.       CreateRegKey(key, szThrdMdl, _T("Single"));
  600.     }
  601.     else if (IsEqual(T::GetThreadModel(), otFree))
  602.     {
  603.       CreateRegKey(key, szThrdMdl, _T("Free"));
  604.     }
  605.     else if (IsEqual(T::GetThreadModel(), otBoth))
  606.     {
  607.       CreateRegKey(key, szThrdMdl, _T("Both"));
  608.     }
  609.     else if (IsEqual(T::GetThreadModel(), otNeutral))
  610.     {
  611.       if (IsComPlusPlatform<int>()) CreateRegKey(key, szThrdMdl, _T("Neutral"));
  612.       else CreateRegKey(key, szThrdMdl, _T("Apartment")); 
  613.     }
  614.     else /* if (T::GetThreadModel() == otApartment)  (Default case) */
  615.     {
  616.       CreateRegKey(key, szThrdMdl, _T("Apartment"));
  617.     }
  618.  
  619.     // Register CLSID/ProgID
  620.     //
  621.     if (m_ProgID && *m_ProgID)
  622.     {
  623.       CreateRegKey(m_ProgID, _T(""), m_Description);
  624.  
  625.       TAPtr<TCHAR> buff(new TCHAR[_MAX_PATH]);
  626.       lstrcpy(buff, m_ProgID);
  627.       lstrcat(buff, _T("\\CLSID"));
  628.       CreateRegKey(buff, _T(""), m_ClassIDstr);
  629.  
  630.       lstrcpy(buff, m_ClassKey);
  631.       lstrcat(buff, _T("\\ProgID"));
  632.       CreateRegKey(buff, _T(""), m_ProgID);
  633.     }
  634.   }
  635.   else
  636.   {
  637.     // Remove registry entries
  638.     //
  639.     NukeRegKey(m_ClassKey);
  640.     if (m_ProgID && *m_ProgID)
  641.       NukeRegKey(m_ProgID);
  642.   }
  643.   return S_OK;
  644. }
  645.  
  646.  
  647. // TTypedComServerRegistrar class performs registration for a COM server
  648. // which contains a type library (i.e., an automation server).
  649. // An instance of this class is typically created via the
  650. // DECLARE_TYPED_COMSERVER_REGISTRY macro.
  651. //
  652. template <class T>
  653. class TTypedComServerRegistrarT : public TComServerRegistrarT<T>
  654. {
  655. public:
  656.   TTypedComServerRegistrarT(): TComServerRegistrarT<T>() {}
  657.  
  658.   TTypedComServerRegistrarT(const CLSID& clsid,
  659.                             LPCTSTR progid,
  660.                             LPCTSTR description = 0) : TComServerRegistrarT<T>(clsid, progid, description)
  661.   {}
  662.  
  663.   // Overriden to perform additional Registration tasks
  664.   //
  665.   virtual HRESULT UpdateRegistry(bool Register);
  666. };
  667.  
  668.  
  669. // CBuilder3 compatible registrar type
  670. //
  671. typedef TTypedComServerRegistrarT<TFakeRegistrarType> TTypedComServerRegistrar;
  672.  
  673.  
  674. // Registers (or Unregisters) Server with TypeLibrary
  675. //
  676. template <class T>
  677. HRESULT TTypedComServerRegistrarT<T>::UpdateRegistry(bool Register)
  678. {
  679.   // Load the Module's type library (assumes TypeLibrary is part of module)
  680.   //
  681.   TComInterface<ITypeLib> pTypeLib;
  682.   HRESULT hres = ::LoadTypeLib(TOleString(m_ModuleName), &pTypeLib);
  683.   if (hres != S_OK)
  684.     return hres;
  685.  
  686.   // Retrieve ITypeInfo
  687.   //
  688.   TComInterface<ITypeInfo> pTypeInfo;
  689.   hres = pTypeLib->GetTypeInfoOfGuid(m_ClassID, &pTypeInfo);
  690.   if (!SUCCEEDED(hres))
  691.     return hres;
  692.  
  693.   // Get description
  694.   //
  695.   if (!m_Description)
  696.   {
  697.     BSTR description;
  698.     hres = pTypeInfo->GetDocumentation(MEMBERID_NIL, NULL,
  699.                                        &description, NULL, NULL);
  700.     if (SUCCEEDED(hres))
  701.     {
  702. #if !defined(UNICODE) && !defined(_UNICODE)
  703.       m_Description = WideToAnsi(description);
  704. #else
  705.       m_Description = strnewdup(description);
  706. #endif
  707.       ::SysFreeString(description);
  708.     }
  709.   }
  710.  
  711.   // Obtain TLIBATTR for this type library
  712.   //
  713.   TLIBATTR *pTypeAttr = 0;
  714.   hres = pTypeLib->GetLibAttr(&pTypeAttr);
  715.   if (!SUCCEEDED(hres))
  716.     return hres;
  717.  
  718.   // Get type library version number and GUID from TLIBATTR
  719.   //
  720.   WORD wMajor = pTypeAttr->wMajorVerNum;
  721.   WORD wMinor = pTypeAttr->wMinorVerNum;
  722.   GUID libID  = pTypeAttr->guid;
  723.  
  724.   pTypeLib->ReleaseTLibAttr(pTypeAttr);
  725.   pTypeAttr = 0;
  726.  
  727.   if (Register)
  728.   {
  729.     // Make registry entries
  730.     // Call base first when registering
  731.     //
  732.     hres = TComServerRegistrarT<T>::UpdateRegistry(Register);
  733.  
  734.     // Create TypeLibrary keys
  735.     //
  736.     TCHAR versionVal[128];
  737.     wsprintf(versionVal, _T("%d.%d"), int(wMajor), int(wMinor));
  738.  
  739.     TAPtr<TCHAR> key(new TCHAR[_MAX_PATH]);
  740.     lstrcpy(key, m_ClassKey);
  741.     lstrcat(key, _T("\\Version"));
  742.     CreateRegKey(key, _T(""), versionVal);
  743.  
  744.     TAPtr<TCHAR> libidstr;
  745.     GUIDToString(libID, libidstr);
  746.  
  747.     lstrcpy(key, m_ClassKey);
  748.     lstrcat(key, _T("\\Typelib"));
  749.     CreateRegKey(key, _T(""), libidstr);
  750.  
  751.     hres = ::RegisterTypeLib(pTypeLib, TOleString(m_ModuleName), 0);
  752.   }
  753.   else
  754.   {
  755.     // Call base to unregister
  756.     // NOTE: Base class nukes everything under \\CLSID\\<clsid>
  757.     //
  758.     hres = TComServerRegistrarT<T>::UpdateRegistry(Register);
  759.   }
  760.   return hres;
  761. }
  762.  
  763.  
  764. // TRemoteDataModuleRegistrar
  765. //
  766. class TRemoteDataModuleRegistrar : public TTypedComServerRegistrar
  767. {
  768. private:
  769.   HRESULT doRegisterPooled();
  770.   HRESULT doUnRegisterPooled();
  771.   HRESULT doRegister();
  772.   HRESULT doUnRegister();
  773. public:
  774.   bool RegisterPooled;
  775.   bool EnableSocket;
  776.   bool EnableWeb;
  777.   bool Singleton;
  778.   int Timeout;
  779.   int MaxObjects;
  780.   TRemoteDataModuleRegistrar() : TTypedComServerRegistrar() {}
  781.  
  782.   TRemoteDataModuleRegistrar(const CLSID& clsid, LPCTSTR progID, LPCTSTR description = 0):
  783.   TTypedComServerRegistrar(clsid, progID, description)
  784.   {}
  785.  
  786.   virtual HRESULT UpdateRegistry(bool);
  787. };
  788.  
  789.  
  790. // TAxControlRegistrar class performs registration for an ActiveX control.
  791. // An instance of this class is typically created via the
  792. // DECLARE_ACTIVEXCONTROL_FACTORY macro.
  793. //
  794. class TAxControlRegistrar: public TTypedComServerRegistrar
  795. {
  796. public:
  797.   TAxControlRegistrar(): m_BitmapID(0), m_MiscFlags(dwDefaultControlMiscFlags), m_Verbs(0)
  798.   {}
  799.  
  800.   TAxControlRegistrar(const CLSID& clsid,                           // CLSID of Object
  801.                       LPCTSTR progid,                               // ProgId of Object
  802.                       int bitmapID,                                 // Index of ToolboxBitmap32 res.
  803.                       DWORD miscFlags = dwDefaultControlMiscFlags,  // Object MISC_xxx flags
  804.                       const OLEVERB *verbs = 0) :                   // Array of Verbs
  805.                                                 m_BitmapID(bitmapID),
  806.                                                 m_MiscFlags(miscFlags),
  807.                                                 m_Verbs(verbs),
  808.                                                 TTypedComServerRegistrar(clsid, progid, 0)
  809.   {}
  810.  
  811.   // Overriden to perform additional Registration tasks
  812.   //
  813.   virtual HRESULT UpdateRegistry(bool Register);
  814.  
  815. protected:
  816.   int             m_BitmapID;     // Index of ToolboxBitmap32 Resource
  817.   DWORD           m_MiscFlags;    // Inf. about Control's Designer's/behavior's aspect
  818.   const OLEVERB*  m_Verbs;        // Array of OLEVERBs support be Control
  819. };
  820.  
  821.  
  822. // Automation Object Macros
  823. //
  824.  
  825. // Macro to provide IAppServer support
  826. #define  RDMOBJECT_COM_INTERFACE_ENTRIES(intf) \
  827.       COM_INTERFACE_ENTRY(intf)                \
  828.       COM_INTERFACE_ENTRY2(IAppServer, intf)   \
  829.       COM_INTERFACE_ENTRY2(IDispatch, intf)     
  830.   
  831. //Macro for standard IDispatch Support
  832. #define  AUTOOBJECT_COM_INTERFACE_ENTRIES(intf) \
  833.       COM_INTERFACE_ENTRY(intf)                 \
  834.       COM_INTERFACE_ENTRY2(IDispatch, intf)
  835.  
  836. // Entry of the default dispatch interface of a COCLASS
  837. //
  838. #define   COM_INTERFACE_ENTRY_OF_DEF_DISPINTF(intf) \
  839.       COM_INTERFACE_ENTRY(intf)                     \
  840.       COM_INTERFACE_ENTRY2(IDispatch, intf)
  841.  
  842. // Macro defining base class of an Automation Object implementation class.
  843. // NOTE: This macro uses the ambient Threading model setting
  844. //
  845. #define AUTOOBJECT_IMPL(cppClass, CoClass, intf)  \
  846.   public CComObjectRootEx<CComObjectThreadModel>, \
  847.   public CComCoClass<cppClass, &CLSID_##CoClass>, \
  848.   public IDispatchImpl<intf, &IID_##intf, LIBID_OF_##CoClass >
  849.  
  850.  
  851. // The DUALINTERFACE macros are inserted by the CodeManager if you insert additional interfaces
  852. // to your CoClass.
  853. //
  854. #define DUALINTERFACE_IMPL(coclass, intf) \
  855.    public IDispatchImpl<intf, &IID_##intf, LIBID_OF_##coclass>
  856.  
  857. #define DUALINTERFACE_ENTRY(i) \
  858.    COM_INTERFACE_ENTRY(i)
  859.  
  860.  
  861. #define UPDATE_REGISTRY_METHOD(code) \
  862. static HRESULT WINAPI UpdateRegistry(BOOL bRegister)  \
  863. { \
  864.   HRESULT hres; \
  865.   try \
  866.   { \
  867.    code \
  868.   } \
  869.   catch (Exception& e) \
  870.   { \
  871.    hres = Error(e.Message.c_str()); \
  872.   } \
  873.   return hres; \
  874. }
  875.  
  876. #define DECLARE_COMSERVER_REGISTRY(progid, desc)                \
  877.    UPDATE_REGISTRY_METHOD(                                      \
  878.       TComServerRegistrar CSR(GetObjectCLSID(), progid, desc);  \
  879.       hres = CSR.UpdateRegistry(bRegister);)
  880.  
  881. #define DECLARE_TYPED_COMSERVER_REGISTRY(progid)                \
  882.    UPDATE_REGISTRY_METHOD(                                      \
  883.     TTypedComServerRegistrar TCSR(GetObjectCLSID(), progid);    \
  884.     hres = TCSR.UpdateRegistry(bRegister);)
  885.  
  886. #define DECLARE_VCL_CONTROL_PERSISTENCE(CppClass, VclClass) \
  887.     HRESULT IPersistStreamInit_Save(LPSTREAM pstrm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap) \
  888.              { \
  889.              HRESULT retval = S_OK; \
  890.              typedef TVclComControl<CppClass, VclClass> VclComBase;  \
  891.              if (VclComBase* convert = dynamic_cast<VclComBase*>(this)) \
  892.                 retval = convert->IPersistStreamInit_SaveVCL(pstrm, fClearDirty, pMap);   \
  893.          else retval = S_FALSE; \
  894.              return retval; \
  895.              } \
  896.     HRESULT IPersistStreamInit_Load(LPSTREAM pstrm, ATL_PROPMAP_ENTRY *pMap)  \
  897.              { \
  898.              HRESULT retval = S_OK; \
  899.              typedef TVclComControl<CppClass, VclClass> VclComBase; \
  900.              if (VclComBase* convert = dynamic_cast<VclComBase*>(this)) \
  901.                 retval = convert->IPersistStreamInit_LoadVCL(pstrm, pMap); \
  902.          else retval = S_FALSE; \
  903.              return retval; \
  904.              }
  905.  
  906. #pragma option pop
  907. #endif // _ATL_MOD
  908.  
  909.  
  910.