comCoreLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:16k
开发平台:

MultiPlatform

  1. /* comCoreLib.c - core COM support */
  2. /* Copyright (c) 2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01n,10dec01,dbs  diab build
  7. 01m,06dec01,nel  Correct man pages.
  8. 01l,02nov01,nel  SPR#71427. Correct error in comAddRegistry when null
  9.                  terminator wasn't being copied into registry entry.
  10. 01k,09aug01,dbs  check args to comClassObjectGet
  11. 01j,07aug01,dbs  return multiple interfaces during creation
  12. 01i,06aug01,dbs  add registry-show capability
  13. 01h,20jul01,dbs  add self-initialisation
  14. 01g,28jun01,dbs  add interlocked inc/dec funcs
  15. 01f,27jun01,dbs  ensure registry init
  16. 01e,25jun01,dbs  change WIDL vtable macro name to COM_xxx
  17. 01d,22jun01,dbs  add vtable-format symbol
  18. 01c,22jun01,dbs  add const to args for comGuidCmp
  19. 01b,21jun01,nel  Add comGuidCmp function.
  20. 01a,20jun01,dbs  written
  21. */
  22. /*
  23. DESCRIPTION
  24. This library provides basic COM support in VxWorks. It implements an
  25. extensible registry model, and provides functions to create instances
  26. of classes via their class objects. Support for the basic COM
  27. interfaces IUnknown and IClassFactory is present, and it can be used
  28. either from C or C++. The vtable format used for COM interfaces is
  29. defined by the C/C++ compiler and is detailed in comBase.h where each
  30. of the known compilers is enumerated and macros are defined for
  31. generating vtable structures, and filling in vtable instances.
  32. The registration of coclasses is handled by a table of registry
  33. instances within this library. When comCoreLib is asked to create an
  34. instance of a coclass, it searches the table of known registries (each
  35. of which is itself a COM object, exposing the IRegistry interface),
  36. asking each in turn if it has the requested coclass (identified by
  37. CLSID) registered. If so, it will then ask the registry to create an
  38. instance of the coclass.
  39. */
  40. /* includes */
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <stdio.h>
  44. #include "taskLib.h"
  45. #include "comCoreLib.h"
  46. #include "comErr.h"
  47. #include "private/comRegistry.h"
  48. /* defines */
  49. #define COM_CORE_MAX_REGISTRIES 8
  50. #define COM_CORE_LIB_INIT()             
  51.     if (comCoreLibInitFlag == 0)        
  52.         { comCoreLibInit (); }
  53. /* globals */
  54. /* This flag records whether comCoreLib has been initialized. Since it
  55.  * is possible that some of the API functions (particularly the
  56.  * registration functions) may be called during program
  57.  * initialisation, it is important that this library allows those
  58.  * calls to succeed even if its init routine hasn't been called by the
  59.  * normal startup (in VxWorks, at least). Subsequent calls to the init
  60.  * routine simply return OK and carry on as normal.
  61.  */
  62. static int comCoreLibInitFlag = 0;
  63. /* This causes a special symbol, whose name is derived from the vtable
  64.  * format determined by the WIDL_XXX macros in comBase.h, to be
  65.  * declared at this point as a global. In all other modules it will be
  66.  * defined as an external and so will only link if all the modules in
  67.  * the program are compiled with the same vtable format defined.
  68.  */
  69. DECLARE_COM_VTBL_SYMBOL_HERE;
  70. /*
  71.  * This global is here to supply a default for the DCOM priority
  72.  * propagation feature, when building coclasses with WOTL.
  73.  */
  74. int g_defaultServerPriority = 100;
  75. /* Array of reg-entries */
  76. static struct _comCoreRegEntry
  77.     {
  78.     char *              regName;        /* name of registry */
  79.     DWORD               dwClsCtx;       /* inproc/local/remote */
  80.     IRegistry *         pRegistry;      /* registry interface */
  81.     } comCoreRegistries [COM_CORE_MAX_REGISTRIES];
  82. /**************************************************************************
  83. *
  84. * comCoreLibInit - Initialize the comCore library
  85. *
  86. * Initialize the comCore library.
  87. *
  88. * RETURNS: OK if init succeeded, ERROR if not
  89. */
  90. STATUS comCoreLibInit (void)
  91.     {
  92.     if (comCoreLibInitFlag == 0)
  93.         {
  94.         ++comCoreLibInitFlag;
  95.         return comRegistryInit ();
  96.         }
  97.     
  98.     return OK;
  99.     }
  100. /**************************************************************************
  101. *
  102. * comCreateAny - creates an instance of a class or class-object
  103. *
  104. * This function scans the registry table, looking for a registry
  105. * instance with the right class-context (inproc, local or remote) and
  106. * which has the class ID <clsid> registered.
  107. *
  108. * RETURNS: S_OK on success, some other failure code otherwise.
  109. *
  110. * NOMANUAL
  111. */
  112. static HRESULT comCreateAny
  113.     (
  114.     REFCLSID            clsid,          /* class ID */
  115.     IUnknown *          pUnkOuter,      /* aggregating interface */
  116.     DWORD               dwClsCtx,       /* class context */
  117.     const char *        hint,           /* service hint */
  118.     int                 classMode,      /* get class object? */
  119.     ULONG               cMQIs,          /* number of MQIs */
  120.     MULTI_QI *          pMQIs           /* MQI array */
  121.     )
  122.     {
  123.     HRESULT hr = REGDB_E_CLASSNOTREG;
  124.     int i;
  125.     IRegistry * pReg;
  126.     /* Make sure the library is initialized... */
  127.     COM_CORE_LIB_INIT ();
  128.     
  129.     /* Work backwards through the table of known registries, ensuring
  130.      * we catch the most-recently added registry first.
  131.      */
  132.     
  133.     for (i = COM_CORE_MAX_REGISTRIES-1; i >= 0; --i)
  134.         {
  135.         if ((comCoreRegistries[i].pRegistry != NULL) &&
  136.             ((comCoreRegistries[i].dwClsCtx & dwClsCtx) != 0))
  137.             {
  138.             pReg = comCoreRegistries[i].pRegistry;
  139.             /* Is the class registered? */
  140.             hr = IRegistry_IsClassRegistered (pReg, clsid);
  141.             if (SUCCEEDED (hr))
  142.                 {
  143.                 /* Create instance or Class-object? */
  144.                 if (classMode)
  145.                     {
  146.                     hr = IRegistry_GetClassObject (pReg,
  147.                                                    clsid,
  148.                                                    pMQIs[0].pIID,
  149.                                                    dwClsCtx,
  150.                                                    hint,
  151.                                                    &pMQIs[0].pItf);
  152.                     }
  153.                 else
  154.                     {
  155.                     hr = IRegistry_CreateInstance (pReg,
  156.                                                    clsid,
  157.                                                    pUnkOuter,
  158.                                                    dwClsCtx,
  159.                                                    hint,
  160.                                                    cMQIs,
  161.                                                    pMQIs);
  162.                     }
  163.                 /* We can just exit the loop, and return whatever
  164.                  * result came back from the registry...
  165.                  */
  166.                 break;
  167.                 }
  168.             }
  169.         }
  170.     
  171.     return hr;
  172.     }
  173. /**************************************************************************
  174. *
  175. * comInstanceCreate - creates an instance of a coclass
  176. *
  177. * This function returns an instance of the coclass identified by
  178. * <clsid>, asking for the interface <iid>. It may be being aggregated,
  179. * in which case the argument <pUnkOuter> holds the controlling
  180. * IUnknown interface of the aggregating object.
  181. *
  182. * RETURNS: S_OK on success, or an error indication if failure occurs
  183. *          for some reason.
  184. */
  185. HRESULT comInstanceCreate
  186.     (
  187.     REFCLSID            clsid,          /* class ID */
  188.     IUnknown *          pUnkOuter,      /* aggregating interface */
  189.     DWORD               dwClsCtx,       /* class context */
  190.     const char *        hint,           /* service hint */
  191.     ULONG               cMQIs,          /* number of MQIs */
  192.     MULTI_QI *          pMQIs           /* MQI array */
  193.     )
  194.     {
  195.     return comCreateAny (clsid,
  196.                          pUnkOuter,
  197.                          dwClsCtx,
  198.                          hint,
  199.                          FALSE,
  200.                          cMQIs,
  201.                          pMQIs);
  202.     }
  203. /**************************************************************************
  204. *
  205. * comClassObjectGet - returns a class object instance
  206. *
  207. * This function returns the class-object for the coclass identified by
  208. * <clsid>, and asks for the interface <iid> which will usually, but
  209. * not always, be IClassFactory.
  210. *
  211. * RETURNS:
  212. * is
  213. * i E_POINTER
  214. * ppvClsObj doesn't point to a valid piece of memory.
  215. * i E_NOINTERFACE
  216. * The requested interface doesn't exist.
  217. * i S_OK
  218. * On success
  219. * ie
  220. */
  221. HRESULT comClassObjectGet
  222.     (
  223.     REFCLSID            clsid,          /* class ID */
  224.     DWORD               dwClsCtx,       /* class context */
  225.     const char *        hint,           /* service hint */
  226.     REFIID              iid,            /* class-obj IID */
  227.     void **             ppvClsObj       /* resulting interface ptr */
  228.     )
  229.     {
  230.     HRESULT hr;
  231. #ifdef __DCC__
  232.     MULTI_QI mqi[1];
  233.     mqi[0].pIID = iid;
  234.     mqi[0].pItf = NULL;
  235.     mqi[0].hr = S_OK;
  236. #else
  237.     MULTI_QI mqi[] = { { iid, NULL, S_OK } };
  238. #endif
  239.     if (! ppvClsObj)
  240.         return E_POINTER;
  241.     
  242.     hr = comCreateAny (clsid,
  243.                        NULL,
  244.                        dwClsCtx,
  245.                        hint,
  246.                        TRUE,
  247.                        1,
  248.                        mqi);
  249.     if (FAILED (hr))
  250.         return hr;
  251.     if (ppvClsObj)
  252.         *ppvClsObj = mqi[0].pItf;
  253.     else
  254.         hr = E_INVALIDARG;
  255.     return hr;
  256.     }
  257. /**************************************************************************
  258. *
  259. * comRegistryAdd - add a registry instance to the COM core
  260. *
  261. * This function adds a registry instance to the table of all known
  262. * registries in the COM core. If there are no more spaces in the
  263. * registry table, it returns an error, otherwise the registry is added
  264. * to the end of the table.
  265. *
  266. * RETURNS: S_OK if the registry instance was added, or some other error
  267. * code if not.
  268. */
  269. HRESULT comRegistryAdd
  270.     (
  271.     const char *        regName,        /* registry name */
  272.     DWORD               dwClsCtx,       /* class context */
  273.     IRegistry*          pReg            /* registry to add */
  274.     )
  275.     {
  276.     HRESULT hr = REGDB_E_CLASSNOTREG;
  277.     int i;
  278.     
  279.     /* Make sure the library is initialized... */
  280.     COM_CORE_LIB_INIT ();
  281.     
  282.     /* Work forwards through the table of known registries, ensuring
  283.      * we add this registry instance at the end of the table.
  284.      */
  285.     
  286.     for (i = 0; i < COM_CORE_MAX_REGISTRIES; ++i)
  287.         {
  288.         if (comCoreRegistries[i].pRegistry == NULL)
  289.             {
  290.             size_t len;
  291.             
  292.             /* Add a reference-count, and store the info. */
  293.             IUnknown_AddRef (pReg);
  294.             
  295.             len = strlen (regName);
  296.             comCoreRegistries[i].regName = malloc (len + 1);
  297.             strcpy (comCoreRegistries[i].regName, regName);
  298.             
  299.             comCoreRegistries[i].dwClsCtx = dwClsCtx;
  300.             comCoreRegistries[i].pRegistry = pReg;
  301.             /* We can leave now... */
  302.             hr = S_OK;
  303.             break;
  304.             }
  305.         }    
  306.     
  307.     return hr;
  308.     }
  309. /**************************************************************************
  310. *
  311. * comClassRegister - registers a 'get-class-object' function for a CLSID
  312. *
  313. * This function stores an association between the class ID <clsid> and
  314. * the 'get class object' function pointer <pfnGCO> so that instances
  315. * of the coclass can be created. The entry is made in the first known
  316. * registry that can deal with the class context given in <dwClsCtx>.
  317. *
  318. * RETURNS: S_OK if the requested CLSID is found, or REGDB_E_CLASSNOTREG
  319. * if it is not present.
  320. */
  321. HRESULT comClassRegister
  322.     (
  323.     REFCLSID         clsid, /* class ID */
  324.     DWORD               dwClsCtx,       /* class context */
  325.     PFN_GETCLASSOBJECT  pfnGCO,         /* GetClassObject() func */
  326.     VXDCOMPRIORITYSCHEME priScheme,     /* priority scheme */
  327.     int                 priority /* priority assoc. with scheme */
  328.     )
  329.     {
  330.     HRESULT hr = REGDB_E_CLASSNOTREG;
  331.     int i;
  332.     IRegistry * pReg;
  333.     
  334.     /* Make sure the library is initialized... */
  335.     COM_CORE_LIB_INIT ();
  336.     
  337.     /* Work forwards through the table of known registries, looking
  338.      * for the first registry that can deal with this class.
  339.      */
  340.     
  341.     for (i = 0; i < COM_CORE_MAX_REGISTRIES; ++i)
  342.         {
  343.         if ((comCoreRegistries[i].dwClsCtx & dwClsCtx) != 0)
  344.             {
  345.             /* Add to this registry. */
  346.             pReg = comCoreRegistries[i].pRegistry;
  347.             hr = IRegistry_RegisterClass (pReg, clsid, pfnGCO);
  348.             break;
  349.             }
  350.         }
  351.     
  352.     return hr;
  353.     }
  354. /**************************************************************************
  355. *
  356. * comCoreGUID2String - convert GUID to a printable string
  357. *
  358. * Converts a GUID to a printable string.
  359. *
  360. * RETURNS: S_OK
  361. *
  362. */
  363. HRESULT comCoreGUID2String
  364.     (
  365.     const GUID *        pGuid,          /* GUID to print */
  366.     char *              buf             /* GUID_STRING_LEN */
  367.     )
  368.     {
  369.     sprintf (buf,
  370.              "{%8.8X-%4.4X-%4.4X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X}",
  371.              (unsigned int) pGuid->Data1,
  372.              (unsigned short)pGuid->Data2,
  373.              (unsigned short)pGuid->Data3,
  374.              pGuid->Data4[0],
  375.              pGuid->Data4[1], 
  376.              pGuid->Data4[2],
  377.              pGuid->Data4[3], 
  378.              pGuid->Data4[4],
  379.              pGuid->Data4[5], 
  380.              pGuid->Data4[6],
  381.              pGuid->Data4[7]);
  382.     return S_OK;
  383.     }
  384. /**************************************************************************
  385. *
  386. * comCoreRegShow - Displays a human readable version of the registry.
  387. *
  388. * RETURNS: OK
  389. * NOMANUAL
  390. */
  391. STATUS comCoreRegShow (void)
  392.     {
  393.     int i;
  394.     
  395.     /* Make sure the library is initialized... */
  396.     COM_CORE_LIB_INIT ();
  397.     
  398.     /* Work forwards through the table of known registries, getting
  399.      * the CLSIDs out of each one and printing them.
  400.      */
  401.     
  402.     for (i = 0; i < COM_CORE_MAX_REGISTRIES; ++i)
  403.         {
  404.         IRegistry * pReg = comCoreRegistries[i].pRegistry;
  405.         if (pReg != NULL)
  406.             {
  407.             DWORD       ix = 0;
  408.             HRESULT     hr = S_OK;
  409.             CLSID       clsid;
  410.             
  411.             /* Add a ref while we use it... */
  412.             IUnknown_AddRef (pReg);
  413.             /* Print the title... */
  414.             printf ("%s:n", comCoreRegistries[i].regName);
  415.             
  416.             /* Iterate over the CLSIDs... */
  417.             while (hr == S_OK)
  418.                 {
  419.                 char buf [GUID_STRING_LEN];
  420.                 
  421.                 hr = IRegistry_GetClassID (pReg, ix++, &clsid);
  422.                 if (SUCCEEDED (hr))
  423.                     {
  424.                     comCoreGUID2String (&clsid, buf);
  425.                     printf ("%sn", buf);
  426.                     }
  427.                 }
  428.             /* Done - release the registry interface... */
  429.             IUnknown_Release (pReg);
  430.             }
  431.         }
  432.     return OK;
  433.     }
  434. /**************************************************************************
  435. *
  436. * comGuidCmp - compare two GUIDs
  437. *
  438. * This function compares two GUIDs and returns a true/false result.
  439. *
  440. * RETURNS: TRUE if the GUIDs are identical, FALSE otherwise.
  441. *
  442. */
  443. BOOL comGuidCmp
  444.     (
  445.     const GUID * g1, /* Source GUID */
  446.     const GUID * g2 /* GUID to compare to */
  447.     )
  448.     {
  449.     return memcmp (g1, g2, sizeof (GUID)) == 0;
  450.     }
  451. /**************************************************************************
  452. *
  453. * comSafeInc - increments a variable in a task-safe way
  454. *
  455. * This function increments a variable, guaranteeing that no other task
  456. * can simultaneously be modifying its value.
  457. *
  458. * RETURNS: incremented value
  459. */
  460. long comSafeInc
  461.     (
  462.     long *      pVar
  463.     )
  464.     {
  465.     long n;
  466.     
  467.     TASK_LOCK ();
  468.     n = ++(*pVar);
  469.     TASK_UNLOCK ();
  470.     return n;
  471.     }
  472. /**************************************************************************
  473. *
  474. * comSafeDec - decrements a variable in a task-safe way
  475. *
  476. * This function decrements a variable, guaranteeing that no other task
  477. * can simultaneously be modifying its value.
  478. *
  479. * RETURNS: decremented value
  480. */
  481. long comSafeDec
  482.     (
  483.     long *      pVar
  484.     )
  485.     {
  486.     long n;
  487.     
  488.     TASK_LOCK ();
  489.     n = --(*pVar);
  490.     TASK_UNLOCK ();
  491.     return n;
  492.     }