home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / dllentry.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-22  |  8.5 KB  |  317 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11.  
  12. //
  13. // classes used to support dll entrypoints for COM objects.
  14. //
  15. #include <streams.h>
  16. #ifdef DEBUG
  17. #include <tchar.h>
  18. #endif
  19.  
  20. extern CFactoryTemplate g_Templates[];
  21. extern int g_cTemplates;
  22.  
  23. HINSTANCE g_hInst;
  24. DWORD      g_amPlatform;        // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
  25. OSVERSIONINFO g_osInfo;
  26.  
  27. //
  28. // an instance of this is created by the DLLGetClassObject entrypoint
  29. // it uses the CFactoryTemplate object it is given to support the
  30. // IClassFactory interface
  31.  
  32. class CClassFactory : public IClassFactory
  33. {
  34.  
  35. private:
  36.     const CFactoryTemplate * m_pTemplate;
  37.  
  38.     ULONG m_cRef;
  39.  
  40.     static int m_cLocked;
  41. public:
  42.     CClassFactory(const CFactoryTemplate *);
  43.  
  44.     // IUnknown
  45.     STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
  46.     STDMETHODIMP_(ULONG)AddRef();
  47.     STDMETHODIMP_(ULONG)Release();
  48.  
  49.     // IClassFactory
  50.     STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **pv);
  51.     STDMETHODIMP LockServer(BOOL fLock);
  52.  
  53.     // allow DLLGetClassObject to know about global server lock status
  54.     static BOOL IsLocked() {
  55.         return (m_cLocked > 0);
  56.     };
  57. };
  58.  
  59. // process-wide dll locked state
  60. int CClassFactory::m_cLocked = 0;
  61.  
  62. CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
  63. {
  64.     m_cRef = 0;
  65.     m_pTemplate = pTemplate;
  66. }
  67.  
  68.  
  69. STDMETHODIMP
  70. CClassFactory::QueryInterface(REFIID riid,void **ppv)
  71. {
  72.     CheckPointer(ppv,E_POINTER)
  73.     ValidateReadWritePtr(ppv,sizeof(PVOID));
  74.     *ppv = NULL;
  75.  
  76.     // any interface on this object is the object pointer.
  77.     if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
  78.         *ppv = (LPVOID) this;
  79.     // AddRef returned interface pointer
  80.         ((LPUNKNOWN) *ppv)->AddRef();
  81.         return NOERROR;
  82.     }
  83.  
  84.     return ResultFromScode(E_NOINTERFACE);
  85. }
  86.  
  87.  
  88. STDMETHODIMP_(ULONG)
  89. CClassFactory::AddRef()
  90. {
  91.     return ++m_cRef;
  92. }
  93.  
  94. STDMETHODIMP_(ULONG)
  95. CClassFactory::Release()
  96. {
  97.     if (--m_cRef == 0) {
  98.         delete this;
  99.         return 0;
  100.     } else {
  101.         return m_cRef;
  102.     }
  103. }
  104.  
  105. STDMETHODIMP
  106. CClassFactory::CreateInstance(
  107.     LPUNKNOWN pUnkOuter,
  108.     REFIID riid,
  109.     void **pv)
  110. {
  111.     CheckPointer(pv,E_POINTER)
  112.     ValidateReadWritePtr(pv,sizeof(void *));
  113.  
  114.     /* Enforce the normal OLE rules regarding interfaces and delegation */
  115.  
  116.     if (pUnkOuter != NULL) {
  117.         if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
  118.             return ResultFromScode(E_NOINTERFACE);
  119.         }
  120.     }
  121.  
  122.     /* Create the new object through the derived class's create function */
  123.  
  124.     HRESULT hr = NOERROR;
  125.     CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
  126.  
  127.     if (pObj == NULL) {
  128.         return E_OUTOFMEMORY;
  129.     }
  130.  
  131.     /* Delete the object if we got a construction error */
  132.  
  133.     if (FAILED(hr)) {
  134.         delete pObj;
  135.         return hr;
  136.     }
  137.  
  138.     /* Get a reference counted interface on the object */
  139.  
  140.     /* We wrap the non-delegating QI with NDAddRef & NDRelease. */
  141.     /* This protects any outer object from being prematurely    */
  142.     /* released by an inner object that may have to be created  */
  143.     /* in order to supply the requested interface.              */
  144.     pObj->NonDelegatingAddRef();
  145.     hr = pObj->NonDelegatingQueryInterface(riid, pv);
  146.     pObj->NonDelegatingRelease();
  147.     /* Note that if NonDelegatingQueryInterface fails, it will  */
  148.     /* not increment the ref count, so the NonDelegatingRelease */
  149.     /* will drop the ref back to zero and the object will "self-*/
  150.     /* destruct".  Hence we don't need additional tidy-up code  */
  151.     /* to cope with NonDelegatingQueryInterface failing.        */
  152.  
  153.     if (SUCCEEDED(hr)) {
  154.         ASSERT(*pv);
  155.     }
  156.  
  157.     return hr;
  158. }
  159.  
  160. STDMETHODIMP
  161. CClassFactory::LockServer(BOOL fLock)
  162. {
  163.     if (fLock) {
  164.         m_cLocked++;
  165.     } else {
  166.         m_cLocked--;
  167.     }
  168.     return NOERROR;
  169. }
  170.  
  171.  
  172. // --- COM entrypoints -----------------------------------------
  173.  
  174. //called by COM to get the class factory object for a given class
  175. STDAPI
  176. DllGetClassObject(
  177.     REFCLSID rClsID,
  178.     REFIID riid,
  179.     void **pv)
  180. {
  181.     if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
  182.             return E_NOINTERFACE;
  183.     }
  184.  
  185.     // traverse the array of templates looking for one with this
  186.     // class id
  187.     for (int i = 0; i < g_cTemplates; i++) {
  188.         const CFactoryTemplate * pT = &g_Templates[i];
  189.         if (pT->IsClassID(rClsID)) {
  190.  
  191.             // found a template - make a class factory based on this
  192.             // template
  193.  
  194.             *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
  195.             if (*pv == NULL) {
  196.                 return E_OUTOFMEMORY;
  197.             }
  198.             ((LPUNKNOWN)*pv)->AddRef();
  199.             return NOERROR;
  200.         }
  201.     }
  202.     return CLASS_E_CLASSNOTAVAILABLE;
  203. }
  204.  
  205. //
  206. //  Call any initialization routines
  207. //
  208. void
  209. DllInitClasses(BOOL bLoading)
  210. {
  211.     int i;
  212.  
  213.     // traverse the array of templates calling the init routine
  214.     // if they have one
  215.     for (i = 0; i < g_cTemplates; i++) {
  216.         const CFactoryTemplate * pT = &g_Templates[i];
  217.         if (pT->m_lpfnInit != NULL) {
  218.             (*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
  219.         }
  220.     }
  221.  
  222. }
  223.  
  224. // called by COM to determine if this dll can be unloaded
  225. // return ok unless there are outstanding objects or a lock requested
  226. // by IClassFactory::LockServer
  227. //
  228. // CClassFactory has a static function that can tell us about the locks,
  229. // and CCOMObject has a static function that can tell us about the active
  230. // object count
  231. STDAPI
  232. DllCanUnloadNow()
  233. {
  234.     DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
  235.         CClassFactory::IsLocked(),
  236.         CBaseObject::ObjectsActive()));
  237.  
  238.     if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
  239.     return S_FALSE;
  240.     } else {
  241.         return S_OK;
  242.     }
  243. }
  244.  
  245.  
  246. // --- standard WIN32 entrypoints --------------------------------------
  247.  
  248.  
  249. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  250.  
  251. BOOL WINAPI
  252. DllEntryPoint(HINSTANCE hInstance, ULONG ulReason, LPVOID pv)
  253. {
  254.  
  255.     switch (ulReason)
  256.     {
  257.  
  258.     case DLL_PROCESS_ATTACH:
  259.         DisableThreadLibraryCalls(hInstance);
  260.         DbgInitialise(hInstance);
  261.     {
  262.         // The platform identifier is used to work out whether
  263.         // full unicode support is available or not.  Hence the
  264.         // default will be the lowest common denominator - i.e. N/A
  265.             g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails
  266.  
  267.             g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
  268.             if (GetVersionEx(&g_osInfo)) {
  269.             g_amPlatform = g_osInfo.dwPlatformId;
  270.         } else {
  271.         DbgLog((LOG_ERROR, 1, "Failed to get the OS platform, assuming Win95"));
  272.         }
  273.     }
  274.         g_hInst = hInstance;
  275.         DllInitClasses(TRUE);
  276.         break;
  277.  
  278.     case DLL_PROCESS_DETACH:
  279.         DllInitClasses(FALSE);
  280.  
  281. #ifdef DEBUG
  282.         if (CBaseObject::ObjectsActive()) {
  283.             DbgSetModuleLevel(LOG_MEMORY, 2);
  284.             TCHAR szInfo[512];
  285.             extern TCHAR m_ModuleName[];     // Cut down module name
  286.  
  287.             TCHAR FullName[_MAX_PATH];      // Load the full path and module name
  288.             TCHAR *pName;                   // Searches from the end for a backslash
  289.  
  290.             GetModuleFileName(NULL,FullName,_MAX_PATH);
  291.             pName = _tcsrchr(FullName,'\\');
  292.             if (pName == NULL) {
  293.                 pName = FullName;
  294.             } else {
  295.                 pName++;
  296.             }
  297.  
  298.         DWORD cch = wsprintf(szInfo, TEXT("Executable: %s  Pid %x  Tid %x. "),
  299.                 pName, GetCurrentProcessId(), GetCurrentThreadId());
  300.  
  301.             wsprintf(szInfo+cch, TEXT("Module %s, %d objects left active!"),
  302.                      m_ModuleName, CBaseObject::ObjectsActive());
  303.             DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
  304.  
  305.         // If running remotely wait for the Assert to be acknowledged
  306.         // before dumping out the object register
  307.             DbgDumpObjectRegister();
  308.         }
  309.         DbgTerminate();
  310. #endif
  311.         break;
  312.     }
  313.     return TRUE;
  314. }
  315.  
  316.  
  317.