clsfact.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 12k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * clsfact.cpp - IClassFactory implementation.
  3.  */
  4. /* Headers
  5.  **********/
  6. #include "project.hpp"
  7. #pragma hdrstop
  8. #include "clsfact.h"
  9. #include "ftps.hpp"
  10. #include "inetcpl.h"
  11. #include "inetps.hpp"
  12. /* Types
  13.  ********/
  14. // callback function used by ClassFactory::ClassFactory()
  15. typedef PIUnknown (*NEWOBJECTPROC)(OBJECTDESTROYEDPROC);
  16. DECLARE_STANDARD_TYPES(NEWOBJECTPROC);
  17. // description of class supported by DllGetClassObject()
  18. typedef struct classconstructor
  19. {
  20.    PCCLSID pcclsid;
  21.    NEWOBJECTPROC NewObject;
  22. }
  23. CLASSCONSTRUCTOR;
  24. DECLARE_STANDARD_TYPES(CLASSCONSTRUCTOR);
  25. /* Classes
  26.  **********/
  27. // object class factory
  28. class ClassFactory : public RefCount,
  29.                      public IClassFactory
  30. {
  31. private:
  32.    NEWOBJECTPROC m_NewObject;
  33. public:
  34.    ClassFactory(NEWOBJECTPROC NewObject, OBJECTDESTROYEDPROC ObjectDestroyed);
  35.    ~ClassFactory(void);
  36.    // IClassFactory methods
  37.    HRESULT STDMETHODCALLTYPE CreateInstance(PIUnknown piunkOuter, REFIID riid, PVOID *ppvObject);
  38.    HRESULT STDMETHODCALLTYPE LockServer(BOOL bLock);
  39.    // IUnknown methods
  40.    ULONG STDMETHODCALLTYPE AddRef(void);
  41.    ULONG STDMETHODCALLTYPE Release(void);
  42.    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppvObj);
  43.    // friends
  44. #ifdef DEBUG
  45.    friend BOOL IsValidPCClassFactory(const ClassFactory *pcurlcf);
  46. #endif
  47. };
  48. DECLARE_STANDARD_TYPES(ClassFactory);
  49. /* Module Prototypes
  50.  ********************/
  51. PRIVATE_CODE PIUnknown NewInternetShortcut(OBJECTDESTROYEDPROC ObjectDestroyed);
  52. PRIVATE_CODE PIUnknown NewMIMEHook(OBJECTDESTROYEDPROC ObjectDestroyed);
  53. PRIVATE_CODE PIUnknown NewInternet(OBJECTDESTROYEDPROC ObjectDestroyed);
  54. /* Module Constants
  55.  *******************/
  56. #pragma data_seg(DATA_SEG_READ_ONLY)
  57. PRIVATE_DATA CCLASSCONSTRUCTOR s_cclscnstr[] =
  58. {
  59.    { &CLSID_InternetShortcut,             &NewInternetShortcut },
  60.    { &CLSID_MIMEFileTypesPropSheetHook,   &NewMIMEHook },
  61.    { &CLSID_Internet,                     &NewInternet },
  62. };
  63. #pragma data_seg()
  64. /* Module Variables
  65.  *******************/
  66. #pragma data_seg(DATA_SEG_PER_INSTANCE)
  67. // DLL reference count == number of class factories +
  68. //                        number of URLs +
  69. //                        LockServer() count
  70. PRIVATE_DATA ULONG s_ulcDLLRef   = 0;
  71. #pragma data_seg()
  72. /***************************** Private Functions *****************************/
  73. PRIVATE_CODE HRESULT GetClassConstructor(REFCLSID rclsid,
  74.                                          PNEWOBJECTPROC pNewObject)
  75. {
  76.    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  77.    UINT u;
  78.    ASSERT(IsValidREFCLSID(rclsid));
  79.    ASSERT(IS_VALID_WRITE_PTR(pNewObject, NEWOBJECTPROC));
  80.    *pNewObject = NULL;
  81.    for (u = 0; u < ARRAY_ELEMENTS(s_cclscnstr); u++)
  82.    {
  83.       if (rclsid == *(s_cclscnstr[u].pcclsid))
  84.       {
  85.          *pNewObject = s_cclscnstr[u].NewObject;
  86.          hr = S_OK;
  87.       }
  88.    }
  89.    ASSERT((hr == S_OK &&
  90.            IS_VALID_CODE_PTR(*pNewObject, NEWOBJECTPROC)) ||
  91.           (hr == CLASS_E_CLASSNOTAVAILABLE &&
  92.            ! *pNewObject));
  93.    return(hr);
  94. }
  95. PRIVATE_CODE void STDMETHODCALLTYPE DLLObjectDestroyed(void)
  96. {
  97.    TRACE_OUT(("DLLObjectDestroyed(): Object destroyed."));
  98.    DLLRelease();
  99. }
  100. PRIVATE_CODE PIUnknown NewInternetShortcut(OBJECTDESTROYEDPROC ObjectDestroyed)
  101. {
  102.    ASSERT(! ObjectDestroyed ||
  103.           IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  104.    TRACE_OUT(("NewInternetShortcut(): Creating a new InternetShortcut."));
  105.    return((PIUnknown)(PIUniformResourceLocator)new(InternetShortcut(ObjectDestroyed)));
  106. }
  107. PRIVATE_CODE PIUnknown NewMIMEHook(OBJECTDESTROYEDPROC ObjectDestroyed)
  108. {
  109.    ASSERT(! ObjectDestroyed ||
  110.           IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  111.    TRACE_OUT(("NewMIMEHook(): Creating a new MIMEHook."));
  112.    return((PIUnknown)(PIShellPropSheetExt)new(MIMEHook(ObjectDestroyed)));
  113. }
  114. PRIVATE_CODE PIUnknown NewInternet(OBJECTDESTROYEDPROC ObjectDestroyed)
  115. {
  116.    ASSERT(! ObjectDestroyed ||
  117.           IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  118.    TRACE_OUT(("NewInternet(): Creating a new Internet."));
  119.    return((PIUnknown)(PIShellPropSheetExt)new(Internet(ObjectDestroyed)));
  120. }
  121. #ifdef DEBUG
  122. PRIVATE_CODE BOOL IsValidPCClassFactory(PCClassFactory pccf)
  123. {
  124.    return(IS_VALID_READ_PTR(pccf, CClassFactory) &&
  125.           IS_VALID_CODE_PTR(pccf->m_NewObject, NEWOBJECTPROC) &&
  126.           IS_VALID_STRUCT_PTR((PCRefCount)pccf, CRefCount) &&
  127.           IS_VALID_INTERFACE_PTR((PCIClassFactory)pccf, IClassFactory));
  128. }
  129. #endif
  130. /****************************** Public Functions *****************************/
  131. PUBLIC_CODE ULONG DLLAddRef(void)
  132. {
  133.    ULONG ulcRef;
  134.    ASSERT(s_ulcDLLRef < ULONG_MAX);
  135.    ulcRef = ++s_ulcDLLRef;
  136.    TRACE_OUT(("DLLAddRef(): DLL reference count is now %lu.",
  137.               ulcRef));
  138.    return(ulcRef);
  139. }
  140. PUBLIC_CODE ULONG DLLRelease(void)
  141. {
  142.    ULONG ulcRef;
  143.    if (EVAL(s_ulcDLLRef > 0))
  144.       s_ulcDLLRef--;
  145.    ulcRef = s_ulcDLLRef;
  146.    TRACE_OUT(("DLLRelease(): DLL reference count is now %lu.",
  147.               ulcRef));
  148.    return(ulcRef);
  149. }
  150. PUBLIC_CODE PULONG GetDLLRefCountPtr(void)
  151. {
  152.    return(&s_ulcDLLRef);
  153. }
  154. /********************************** Methods **********************************/
  155. ClassFactory::ClassFactory(NEWOBJECTPROC NewObject,
  156.                            OBJECTDESTROYEDPROC ObjectDestroyed) :
  157.    RefCount(ObjectDestroyed)
  158. {
  159.    DebugEntry(ClassFactory::ClassFactory);
  160.    // Don't validate this until after construction.
  161.    ASSERT(IS_VALID_CODE_PTR(NewObject, NEWOBJECTPROC));
  162.    m_NewObject = NewObject;
  163.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  164.    DebugExitVOID(ClassFactory::ClassFactory);
  165.    return;
  166. }
  167. ClassFactory::~ClassFactory(void)
  168. {
  169.    DebugEntry(ClassFactory::~ClassFactory);
  170.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  171.    m_NewObject = NULL;
  172.    // Don't validate this after destruction.
  173.    DebugExitVOID(ClassFactory::~ClassFactory);
  174.    return;
  175. }
  176. ULONG STDMETHODCALLTYPE ClassFactory::AddRef(void)
  177. {
  178.    ULONG ulcRef;
  179.    DebugEntry(ClassFactory::AddRef);
  180.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  181.    ulcRef = RefCount::AddRef();
  182.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  183.    DebugExitULONG(ClassFactory::AddRef, ulcRef);
  184.    return(ulcRef);
  185. }
  186. ULONG STDMETHODCALLTYPE ClassFactory::Release(void)
  187. {
  188.    ULONG ulcRef;
  189.    DebugEntry(ClassFactory::Release);
  190.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  191.    ulcRef = RefCount::Release();
  192.    DebugExitULONG(ClassFactory::Release, ulcRef);
  193.    return(ulcRef);
  194. }
  195. HRESULT STDMETHODCALLTYPE ClassFactory::QueryInterface(REFIID riid,
  196.                                                        PVOID *ppvObject)
  197. {
  198.    HRESULT hr = S_OK;
  199.    DebugEntry(ClassFactory::QueryInterface);
  200.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  201.    ASSERT(IsValidREFIID(riid));
  202.    ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  203.    if (riid == IID_IClassFactory)
  204.    {
  205.       *ppvObject = (PIClassFactory)this;
  206.       ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
  207.       TRACE_OUT(("ClassFactory::QueryInterface(): Returning IClassFactory."));
  208.    }
  209.    else if (riid == IID_IUnknown)
  210.    {
  211.       *ppvObject = (PIUnknown)this;
  212.       ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  213.       TRACE_OUT(("ClassFactory::QueryInterface(): Returning IUnknown."));
  214.    }
  215.    else
  216.    {
  217.       *ppvObject = NULL;
  218.       hr = E_NOINTERFACE;
  219.       TRACE_OUT(("ClassFactory::QueryInterface(): Called on unknown interface."));
  220.    }
  221.    if (hr == S_OK)
  222.       AddRef();
  223.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  224.    ASSERT(FAILED(hr) ||
  225.           IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  226.    DebugExitHRESULT(ClassFactory::QueryInterface, hr);
  227.    return(hr);
  228. }
  229. HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(PIUnknown piunkOuter,
  230.                                                        REFIID riid,
  231.                                                        PVOID *ppvObject)
  232. {
  233.    HRESULT hr;
  234.    DebugEntry(ClassFactory::CreateInstance);
  235.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  236.    ASSERT(! piunkOuter ||
  237.           IS_VALID_INTERFACE_PTR(piunkOuter, IUnknown));
  238.    ASSERT(IsValidREFIID(riid));
  239.    ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  240.    *ppvObject = NULL;
  241.    if (! piunkOuter)
  242.    {
  243.       PIUnknown piunk;
  244.       piunk = (*m_NewObject)(&DLLObjectDestroyed);
  245.       if (piunk)
  246.       {
  247.          DLLAddRef();
  248.          hr = piunk->QueryInterface(riid, ppvObject);
  249.          // N.b., the Release() method will destroy the object if the
  250.          // QueryInterface() method failed.
  251.          piunk->Release();
  252.       }
  253.       else
  254.          hr = E_OUTOFMEMORY;
  255.    }
  256.    else
  257.    {
  258.       hr = CLASS_E_NOAGGREGATION;
  259.       WARNING_OUT(("ClassFactory::CreateInstance(): Aggregation not supported."));
  260.    }
  261.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  262.    ASSERT(FAILED(hr) ||
  263.           IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  264.    DebugExitHRESULT(ClassFactory::CreateInstance, hr);
  265.    return(hr);
  266. }
  267. HRESULT STDMETHODCALLTYPE ClassFactory::LockServer(BOOL bLock)
  268. {
  269.    HRESULT hr;
  270.    DebugEntry(ClassFactory::LockServer);
  271.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  272.    // bLock may be any value.
  273.    if (bLock)
  274.       DLLAddRef();
  275.    else
  276.       DLLRelease();
  277.    hr = S_OK;
  278.    ASSERT(IS_VALID_STRUCT_PTR(this, CClassFactory));
  279.    DebugExitHRESULT(ClassFactory::LockServer, hr);
  280.    return(hr);
  281. }
  282. /***************************** Exported Functions ****************************/
  283. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PVOID *ppvObject)
  284. {
  285.    HRESULT hr = S_OK;
  286.    NEWOBJECTPROC NewObject;
  287.    DebugEntry(DllGetClassObject);
  288.    ASSERT(IsValidREFCLSID(rclsid));
  289.    ASSERT(IsValidREFIID(riid));
  290.    ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  291.    *ppvObject = NULL;
  292.    hr = GetClassConstructor(rclsid, &NewObject);
  293.    if (hr == S_OK)
  294.    {
  295.       if (riid == IID_IUnknown ||
  296.           riid == IID_IClassFactory)
  297.       {
  298.          PClassFactory pcf;
  299.          pcf = new(ClassFactory(NewObject, &DLLObjectDestroyed));
  300.          if (pcf)
  301.          {
  302.             if (riid == IID_IClassFactory)
  303.             {
  304.                *ppvObject = (PIClassFactory)pcf;
  305.                ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
  306.                TRACE_OUT(("DllGetClassObject(): Returning IClassFactory."));
  307.             }
  308.             else
  309.             {
  310.                ASSERT(riid == IID_IUnknown);
  311.                *ppvObject = (PIUnknown)pcf;
  312.                ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  313.                TRACE_OUT(("DllGetClassObject(): Returning IUnknown."));
  314.             }
  315.             DLLAddRef();
  316.             hr = S_OK;
  317.             TRACE_OUT(("DllGetClassObject(): Created a new class factory."));
  318.          }
  319.          else
  320.             hr = E_OUTOFMEMORY;
  321.       }
  322.       else
  323.       {
  324.          WARNING_OUT(("DllGetClassObject(): Called on unknown interface."));
  325.          hr = E_NOINTERFACE;
  326.       }
  327.    }
  328.    else
  329.       WARNING_OUT(("DllGetClassObject(): Called on unknown class."));
  330.    ASSERT(FAILED(hr) ||
  331.           IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  332.    DebugExitHRESULT(DllGetClassObject, hr);
  333.    return(hr);
  334. }
  335. STDAPI DllCanUnloadNow(void)
  336. {
  337.    HRESULT hr;
  338.    DebugEntry(DllCanUnloadNow);
  339.    hr = (s_ulcDLLRef > 0) ? S_FALSE : S_OK;
  340.     
  341.     if (hr == S_OK) 
  342.         hr = InternetCPLCanUnloadNow();
  343.    TRACE_OUT(("DllCanUnloadNow(): DLL reference count is %lu.",
  344.               s_ulcDLLRef));
  345.    DebugExitHRESULT(DllCanUnloadNow, hr);
  346.    return(hr);
  347. }