home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / directx / dxf / samples / multimedia / directshow / baseclasses / dllentry.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  8.7 KB  |  337 lines

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