FileRegistry.cpp
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:11k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* unixRegistry.cpp - VxCOM Unix disk-based registry class */
  2. /* Copyright (c) 2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01b,03jan02,nel  Remove T2OLE reference.
  7. 01a,02oct01,dsellars  created
  8. */
  9. #if defined (VXDCOM_PLATFORM_SOLARIS) || defined (VXDCOM_PLATFORM_LINUX)
  10. #include <dirent.h>
  11. #include <string>
  12. #include <fstream>
  13. #include <sys/param.h>
  14. #include <dlfcn.h>
  15. #include "comLib.h"
  16. #include "comObjLib.h"
  17. #include "private/comStl.h"
  18. #include "private/comMisc.h"
  19. //////////////////////////////////////////////////////////////////////////
  20. //
  21. // The 'FileRegistry' class implements a 'plug-in' VxCOM registry for
  22. // Unix-based systems, where the coclasses are located in shared
  23. // libraries on disk. Each shared library must export a function
  24. // called DllGetClassObject() which must match the PFN_GETCLASSOBJECT
  25. // signature.
  26. //
  27. // A text-file (with extension .registry) is used to record the CLSIDs
  28. // and map them to shared libraries, which can be anywhere on the
  29. // system. The registration file must be in a directory which is
  30. // mentioned in the environment variable VXCOM_REGISTRY_PATH (which is
  31. // a list of directories, separated by colons, in the usual Unix way).
  32. //
  33. // Each line in the registry file must be of the form:-
  34. //
  35. //  {CLSID}=/path/to/shared/library.so
  36. //
  37. // i.e. the string-form of the CLSID as defined by COM, followed by
  38. // the path to the shared-library itself.
  39. //
  40. class FileRegistry :
  41.     public CComObjectRoot,
  42.     public IRegistry
  43.     {
  44.   public:
  45.     virtual ~FileRegistry ();
  46.     FileRegistry ();
  47.     // IRegistry implementation...
  48.     HRESULT RegisterClass (REFCLSID, void*)
  49.         {
  50.         // Not required for this kind of registry...
  51.         return E_NOTIMPL;
  52.         }
  53.     
  54.     HRESULT IsClassRegistered
  55.         (
  56.         REFCLSID                clsid
  57.         );
  58.     HRESULT CreateInstance
  59.         (
  60.         REFCLSID                clsid,
  61.         IUnknown *              pUnkOuter,
  62.         DWORD                   dwClsContext,
  63.         const char *            hint,
  64.         ULONG                   cMQIs,
  65.         MULTI_QI *              pMQIs
  66.         );
  67.     HRESULT GetClassObject
  68.         (
  69.         REFCLSID                clsid,
  70.         REFIID                  iid,
  71.         DWORD                   dwClsContext,
  72.         const char *            hint,
  73.         IUnknown **             ppClsObj
  74.         );
  75.     HRESULT GetClassID
  76.         (
  77.         DWORD                   dwIndex,
  78.         LPCLSID                 pclsid
  79.         );        
  80.     // Load a .registry file...
  81.     int loadRegistryFile (const string& fileName);
  82.     BEGIN_COM_MAP(FileRegistry)
  83.         COM_INTERFACE_ENTRY(IRegistry)
  84.     END_COM_MAP()
  85.   private:
  86.     // Not implemented
  87.     FileRegistry (const FileRegistry& other);
  88.     FileRegistry& operator= (const FileRegistry& rhs);
  89.     // universal private instance-creation function
  90.     HRESULT instanceCreate
  91.         (
  92.         bool                    classMode,
  93.         REFCLSID                clsid,
  94.         IUnknown *              pUnkOuter,
  95.         DWORD                   dwClsContext,
  96.         const char *            hint,
  97.         ULONG                   cMQIs,
  98.         MULTI_QI *              pMQIs
  99.         );
  100.     // registry entry
  101.     struct entry
  102.         {
  103.         CLSID   clsid;
  104.         string  library;
  105.         entry (REFCLSID cid, const string& lib)
  106.           : clsid (cid), library (lib)
  107.             {}
  108.         entry ()
  109.             {}
  110.         };
  111.     
  112.     typedef STL_MAP(CLSID, entry)       RegMap_t;
  113.     RegMap_t    m_regmap;
  114.     };
  115. typedef CComObject<FileRegistry> FileRegistryClass;
  116. //////////////////////////////////////////////////////////////////////////
  117. //
  118. // theRegistryInstance - returns the single instance of FileRegistryClass
  119. //
  120. static HRESULT theRegistryInstance (FileRegistryClass **ppReg)
  121.     {
  122.     static FileRegistryClass* s_instance = 0;
  123.     if (! s_instance)
  124.         {
  125.         // Create one, add a ref to keep it around forever...
  126.         s_instance = new FileRegistryClass ();
  127.         if (! s_instance)
  128.             return E_FAIL;
  129.         
  130.         s_instance->AddRef ();
  131.         }
  132.     *ppReg = s_instance;
  133.     return S_OK;
  134.     }
  135. //////////////////////////////////////////////////////////////////////////
  136. //
  137. // comFileRegistryInit - initialise the Unix registry component
  138. //
  139. // This function reads all the registry files it can find, and adds
  140. // entries to the one-and-only instance of FileRegistryClass. It then
  141. // puts that registry into the VxCOM registry-list, so that classes
  142. // are accessible to CoCreateInstance() via this mechanism.
  143. //
  144. extern "C" int comFileRegistryInit () 
  145.     {
  146.     IRegistry* pReg;
  147.     FileRegistryClass* pur = 0;
  148.     // Find the one-and-only instance (adds a ref)...
  149.     HRESULT hr = theRegistryInstance (&pur);
  150.     if (FAILED (hr))
  151.         return hr;
  152.     // Get its IRegistry interface...
  153.     hr = pur->QueryInterface (IID_IRegistry, (void**) &pReg);
  154.     if (FAILED (hr))
  155.         return hr;
  156.     // Add it to the VxCOM registry...
  157.     hr = comRegistryAdd ("Unix Registry",
  158.                          CLSCTX_INPROC_SERVER,
  159.                          pReg);
  160.     // Done with the IRegistry interface...
  161.     pReg->Release ();
  162.     // Get path list...
  163.     const char* regPath = getenv ("VXCOM_REGISTRY_PATH");
  164.     if (! regPath)
  165.         return ERROR;
  166.     // Split into dirs...
  167.     string path (regPath);
  168.     size_t prev = 0;
  169.     size_t ix = 0;
  170.     while (ix != string::npos)
  171.         {
  172.         ix = path.find_first_of (':', prev);
  173.         string dirName = path.substr (prev, ix);
  174.         if (ix != string::npos)
  175.             prev = ix + 1;
  176.         if (dirName.length () == 0)
  177.             continue;
  178.         // Now look in this dir for *.registry files...
  179.         cout << "Searching directory " << dirName << endl;
  180.         DIR* dir = opendir (dirName.c_str ());
  181.         if (! dir)
  182.             {
  183.             perror (dirName.c_str ());
  184.             continue;
  185.             }
  186.         struct dirent* pDirent;
  187.         // Load them one by one...
  188.         while ((pDirent = readdir (dir)) != 0)
  189.             {
  190.             const string DOT_REGISTRY = ".registry";
  191.             
  192.             string f = pDirent->d_name;
  193.             if ((f.length () >= DOT_REGISTRY.length ()) &&
  194.                 (f.rfind (DOT_REGISTRY) == (f.length() - DOT_REGISTRY.length ())))
  195.                 {
  196.                 // Found a file...
  197.                 pur->loadRegistryFile (dirName + "/" + f);
  198.                 }
  199.             }
  200.         // Tidy up...
  201.         closedir (dir);
  202.         }
  203.     // Clean up...
  204.     pur->Release ();
  205.     return S_OK;
  206.     }
  207. //////////////////////////////////////////////////////////////////////////
  208. FileRegistry::FileRegistry ()
  209.     {
  210.     }
  211. //////////////////////////////////////////////////////////////////////////
  212. FileRegistry::~FileRegistry ()
  213.     {
  214.     }
  215. //////////////////////////////////////////////////////////////////////////
  216. //
  217. // FileRegistry::loadRegistryFile - load a .registry file
  218. //
  219. int FileRegistry::loadRegistryFile (const string& fileName)
  220.     {
  221.     cout << "Loading registry file " << fileName << endl;
  222.     ifstream str (fileName.c_str ());
  223.     if (! str)
  224.         return -1;
  225.     char buf [MAXPATHLEN + 40];    // big enough for GUID + path
  226.     while (str.getline (buf, sizeof (buf)))
  227.         {
  228.         string line = buf;
  229.         size_t eq = line.find_first_of ('=');
  230.         if (eq == string::npos)
  231.             continue;
  232.         
  233.         string clsid = line.substr (0, eq);
  234.         string shlib = line.substr (eq+1, string::npos);
  235.         
  236.         CLSID classid;
  237.         OLECHAR * pwsz = new OLECHAR [(strlen (clsid.c_str ()) + 1)];
  238. comAsciiToWide (pwsz, clsid.c_str (), (strlen (clsid.c_str ()) + 1));
  239.         HRESULT hr = CLSIDFromString (pwsz, &classid);
  240. delete []pwsz;
  241.         if (FAILED (hr))
  242.             return hr;
  243.         cout << "Registering CLSID " << clsid << endl
  244.              << "  for shared-lib " << shlib << endl;
  245.         m_regmap [classid] = entry (classid, shlib);
  246.         }
  247.     
  248.     return 0;
  249.     }
  250. //////////////////////////////////////////////////////////////////////////
  251. //
  252. // FileRegistry::IsClassRegistered - is class registered here?
  253. //
  254. HRESULT FileRegistry::IsClassRegistered
  255.     (
  256.     REFCLSID                clsid
  257.     )
  258.     {
  259.     RegMap_t::const_iterator i = m_regmap.find (clsid);
  260.     if (i == m_regmap.end ())
  261.         {
  262.         for (i = m_regmap.begin (); i != m_regmap.end (); ++i)
  263.             cout << (*i).first << endl;
  264.         return REGDB_E_CLASSNOTREG;
  265.         }
  266.     return S_OK;
  267.     }
  268. //////////////////////////////////////////////////////////////////////////
  269. //
  270. // FileRegistry::CreateInstance - create an instance of the given class
  271. //
  272. HRESULT FileRegistry::CreateInstance
  273.     (
  274.     REFCLSID                clsid,
  275.     IUnknown *              pUnkOuter,
  276.     DWORD                   dwClsContext,
  277.     const char *            hint,
  278.     ULONG                   cMQIs,
  279.     MULTI_QI *              pMQIs
  280.     )
  281.     {
  282.     IClassFactory* pCF = 0;
  283.     // Get the class-factory...
  284.     HRESULT hr = GetClassObject (clsid,
  285.                                  IID_IClassFactory,
  286.                                  dwClsContext,
  287.                                  hint,
  288.                                  (IUnknown**) &pCF);
  289.     
  290.     // Now get the instance...
  291.     IUnknown *punk = 0;
  292.     hr = pCF->CreateInstance (pUnkOuter, IID_IUnknown, (void**) &punk);
  293.     if (FAILED (hr))
  294.         return hr;
  295.     // Finished with the factory...
  296.     pCF->Release ();
  297.     
  298.     // Ask for all the interfaces...
  299.     for (ULONG i = 0; i < cMQIs; ++i)
  300.         {
  301.         pMQIs[i].hr = punk->QueryInterface (*(pMQIs[i].pIID),
  302.                                             (void**) &pMQIs[i].pItf);
  303.         }
  304.     
  305.     // Release our original ref...
  306.     punk->Release ();
  307.     return hr;
  308.     }
  309. //////////////////////////////////////////////////////////////////////////
  310. //
  311. // FileRegistry::GetClassObject - get the class-factory object
  312. //
  313. HRESULT FileRegistry::GetClassObject
  314.     (
  315.     REFCLSID                clsid,
  316.     REFIID                  iid,
  317.     DWORD                   dwClsContext,
  318.     const char *            hint,
  319.     IUnknown **             ppClsObj
  320.     )
  321.     {
  322.     // Find the reg-entry...
  323.     RegMap_t::const_iterator i = m_regmap.find (clsid);
  324.     if (i == m_regmap.end ())
  325.         return REGDB_E_CLASSNOTREG;
  326.     string fileName = (*i).second.library;
  327.     // Open the shared-lib...
  328.     void* handle = dlopen (fileName.c_str (), RTLD_NOW | RTLD_GLOBAL);
  329.     if (! handle)
  330.         {
  331.         cout << dlerror () << endl;
  332.         return E_UNEXPECTED;
  333.         }
  334.     
  335.     // Find the symbol...
  336.     PFN_GETCLASSOBJECT gco =
  337.         (PFN_GETCLASSOBJECT) dlsym (handle, "DllGetClassObject");
  338.     if (! gco)
  339.         {
  340.         dlclose (handle);
  341.         cout << dlerror () << endl;
  342.         return E_UNEXPECTED;
  343.         }
  344.     // Call the function to get the class-factory...
  345.     return gco (clsid, iid, (void**) ppClsObj);
  346.     }
  347. //////////////////////////////////////////////////////////////////////////
  348. //
  349. // FileRegistry::GetClassID - enumerate class IDs
  350. //
  351. HRESULT FileRegistry::GetClassID
  352.     (
  353.     DWORD                   dwIndex,
  354.     LPCLSID                 pclsid
  355.     )
  356.     {
  357.     RegMap_t::const_iterator iter = m_regmap.begin ();
  358.     for (DWORD i = 0; i < dwIndex; ++i)
  359.         {
  360.         ++iter;
  361.         if (iter == m_regmap.end ())
  362.             return E_FAIL;
  363.         }
  364.     *pclsid = (*iter).first;
  365.         
  366.     return S_OK;
  367.     }
  368. #endif  /* defined SOLARIS || LINUX */