home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / BaseClasses / dllentry.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  9.1 KB  |  333 lines

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