home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / prefs / brpref / src / brpref.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  14.8 KB  |  578 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "pch.h"
  20. #include "brpref.h"
  21. #include "pages.h"
  22. #include "brprefid.h"
  23. #include "prefuiid.h"
  24. #include "isppageo.h"
  25. #include <assert.h>
  26.  
  27. // Create a new instance of our derived class and return it.
  28. CComDll *
  29. DLL_ConsumerCreateInstance()
  30. {
  31.     return new CGeneralPrefsDll;
  32. }
  33.  
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Global new/delete operators
  36.  
  37. // Override the global new/delete operators to allocate memory owned by the
  38. // application and not by the DLL; _fmalloc calls GlobalAlloc with GMEM_SHARE
  39. // for DLLs and that means the memory will not be freed until the DLL is
  40. // unloaded. _fmalloc only maintains one heap for a DLL which is shared by
  41. // all applications that use the DLL
  42. #ifndef _WIN32
  43. void *
  44. operator new (size_t size)
  45. {
  46.     return CoTaskMemAlloc(size);
  47. }
  48.  
  49. void
  50. operator delete (void *lpMem)
  51. {
  52.     CoTaskMemFree(lpMem);
  53. }
  54. #endif
  55.  
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CSpecifyPropertyPageObjects
  58.  
  59. // Abstract class that supports aggregation as an inner object
  60. class CCategory : public IUnknown {
  61.     public:
  62.         CCategory();
  63.  
  64.         // IUnknown methods. Doesn't delegate (explicit IUnknown)
  65.         STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj) PURE;
  66.         STDMETHODIMP_(ULONG) AddRef();
  67.         STDMETHODIMP_(ULONG) Release();
  68.  
  69.     public:
  70.         // Abstract nested class that implements ISpecifyPropertyPageObjects
  71.         class CSpecifyPageObjects : public ISpecifyPropertyPageObjects {
  72.             public:
  73.                 CSpecifyPageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter);
  74.  
  75.                 // IUnknown methods. Always delegates to controlling unknown
  76.                 STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
  77.                 STDMETHODIMP_(ULONG) AddRef();
  78.                 STDMETHODIMP_(ULONG) Release();
  79.  
  80.                 // ISpecifyPropertyPageObjects methods
  81.                 STDMETHODIMP GetPageObjects(CAPPAGE FAR* pPages) PURE;
  82.             
  83.             private:
  84.                 CCategory  *m_pBackObj;
  85.                 LPUNKNOWN    m_pUnkOuter;
  86.         };
  87.  
  88.     private:
  89.         ULONG    m_uRef;
  90. };
  91.  
  92. CCategory::CCategory()
  93. {
  94.     m_uRef = 0;
  95. }
  96.  
  97. STDMETHODIMP_(ULONG)
  98. CCategory::AddRef()
  99. {
  100.     return ++m_uRef;
  101. }
  102.  
  103. STDMETHODIMP_(ULONG)
  104. CCategory::Release()
  105. {
  106.     if (--m_uRef == 0) {
  107. #ifdef _DEBUG
  108.         OutputDebugString("Destroying CCategory object.\n");
  109. #endif
  110.         delete this;
  111.         return 0;
  112.     }
  113.  
  114.     return m_uRef;
  115. }
  116.  
  117. CCategory::CSpecifyPageObjects::CSpecifyPageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter)
  118. {
  119.     assert(pBackObj);
  120.  
  121.     // Don't add references to either the back pointer or the controlling unknown
  122.     m_pBackObj = pBackObj;
  123.     m_pUnkOuter = pUnkOuter;
  124.  
  125.     // If we're not being aggregated then pUnkOuter will be NULL. In that case
  126.     // delegate to the object in which we're contained
  127.     if (!m_pUnkOuter)
  128.         m_pUnkOuter = pBackObj;
  129. }
  130.  
  131. STDMETHODIMP
  132. CCategory::CSpecifyPageObjects::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  133. {
  134.     // Delegate to the controlling unknown
  135.     assert(m_pUnkOuter);
  136.     return m_pUnkOuter->QueryInterface(riid, ppvObj);
  137. }
  138.  
  139. STDMETHODIMP_(ULONG)
  140. CCategory::CSpecifyPageObjects::AddRef()
  141. {
  142.     // Delegate to the controlling unknown
  143.     assert(m_pUnkOuter);
  144.     return m_pUnkOuter->AddRef();
  145. }
  146.  
  147. STDMETHODIMP_(ULONG)
  148. CCategory::CSpecifyPageObjects::Release()
  149. {
  150.     // Delegate to the controlling unknown
  151.     assert(m_pUnkOuter);
  152.     return m_pUnkOuter->Release();
  153. }
  154.  
  155. /////////////////////////////////////////////////////////////////////////////
  156. // CAppearanceCategory
  157.  
  158. class CAppearanceCategory : public CCategory {
  159.     public:
  160.         CAppearanceCategory(LPUNKNOWN pUnkOuter);
  161.  
  162.         // IUnknown methods. Doesn't delegate (explicit IUnknown)
  163.         STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
  164.  
  165.     private:
  166.         class CSpecifyAppearancePageObjects : public CCategory::CSpecifyPageObjects {
  167.             public:
  168.                 CSpecifyAppearancePageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter);
  169.  
  170.                 // ISpecifyPropertyPageObjects methods
  171.                 STDMETHODIMP GetPageObjects(CAPPAGE *pPages);
  172.         };
  173.  
  174.         CSpecifyAppearancePageObjects m_innerObj;
  175. };
  176.  
  177. CAppearanceCategory::CAppearanceCategory(LPUNKNOWN pUnkOuter)
  178.     : m_innerObj(this, pUnkOuter)
  179. {
  180. }
  181.  
  182. STDMETHODIMP
  183. CAppearanceCategory::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  184. {
  185.     if (riid == IID_IUnknown) {
  186.         *ppvObj = (LPVOID)this;
  187.         AddRef();
  188.         return NOERROR;
  189.     
  190.     } else if (riid == IID_ISpecifyPropertyPageObjects) {
  191.         *ppvObj = (LPVOID)&m_innerObj;
  192.         m_innerObj.AddRef();
  193.         return NOERROR;
  194.     
  195.     } else {
  196.         *ppvObj = NULL;
  197.         return ResultFromScode(E_NOINTERFACE);
  198.     }
  199. }
  200.  
  201. CAppearanceCategory::CSpecifyAppearancePageObjects::CSpecifyAppearancePageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter)
  202.     : CSpecifyPageObjects(pBackObj, pUnkOuter)
  203. {
  204. }
  205.  
  206. STDMETHODIMP
  207. CAppearanceCategory::CSpecifyAppearancePageObjects::GetPageObjects(CAPPAGE *pPages)
  208. {
  209.     if (!pPages)
  210.         return ResultFromScode(E_POINTER);
  211.  
  212.     pPages->cElems = 3;
  213.     pPages->pElems = (LPPROPERTYPAGE *)CoTaskMemAlloc(pPages->cElems * sizeof(LPPROPERTYPAGE));
  214.     if (!pPages->pElems)
  215.         return ResultFromScode(E_OUTOFMEMORY);
  216.  
  217.     pPages->pElems[0] = new CAppearancePrefs;
  218.     pPages->pElems[1] = new CFontsPrefs;
  219.     pPages->pElems[2] = new CColorsPrefs;
  220.  
  221.     for (ULONG i = 0; i < pPages->cElems; i++)
  222.         pPages->pElems[i]->AddRef();
  223.  
  224.     return NOERROR;
  225. }
  226.  
  227. /////////////////////////////////////////////////////////////////////////////
  228. // CBrowserCategory
  229.  
  230. class CBrowserCategory : public CCategory {
  231.     public:
  232.         CBrowserCategory(LPUNKNOWN pUnkOuter);
  233.  
  234.         // IUnknown methods. Doesn't delegate (explicit IUnknown)
  235.         STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
  236.  
  237.     private:
  238.         class CSpecifyBrowserPageObjects : public CCategory::CSpecifyPageObjects {
  239.             public:
  240.                 CSpecifyBrowserPageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter);
  241.  
  242.                 // ISpecifyPropertyPageObjects methods
  243.                 STDMETHODIMP GetPageObjects(CAPPAGE *pPages);
  244.         };
  245.  
  246.         CSpecifyBrowserPageObjects m_innerObj;
  247. };
  248.  
  249. CBrowserCategory::CBrowserCategory(LPUNKNOWN pUnkOuter)
  250.     : m_innerObj(this, pUnkOuter)
  251. {
  252. }
  253.  
  254. STDMETHODIMP
  255. CBrowserCategory::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  256. {
  257.     if (riid == IID_IUnknown) {
  258.         *ppvObj = (LPVOID)this;
  259.         AddRef();
  260.         return NOERROR;
  261.     
  262.     } else if (riid == IID_ISpecifyPropertyPageObjects) {
  263.         *ppvObj = (LPVOID)&m_innerObj;
  264.         m_innerObj.AddRef();
  265.         return NOERROR;
  266.     
  267.     } else {
  268.         *ppvObj = NULL;
  269.         return ResultFromScode(E_NOINTERFACE);
  270.     }
  271. }
  272.  
  273. CBrowserCategory::CSpecifyBrowserPageObjects::CSpecifyBrowserPageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter)
  274.     : CSpecifyPageObjects(pBackObj, pUnkOuter)
  275. {
  276. }
  277.  
  278. STDMETHODIMP
  279. CBrowserCategory::CSpecifyBrowserPageObjects::GetPageObjects(CAPPAGE *pPages)
  280. {
  281.     if (!pPages)
  282.         return ResultFromScode(E_POINTER);
  283.  
  284.     pPages->cElems = 3;
  285.     pPages->pElems = (LPPROPERTYPAGE *)CoTaskMemAlloc(pPages->cElems * sizeof(LPPROPERTYPAGE));
  286.     if (!pPages->pElems)
  287.         return ResultFromScode(E_OUTOFMEMORY);
  288.  
  289.     pPages->pElems[0] = new CBrowserPrefs;
  290.     pPages->pElems[1] = new CLanguagesPrefs;
  291.     pPages->pElems[2] = new CApplicationsPrefs;
  292.     
  293.     for (ULONG i = 0; i < pPages->cElems; i++)
  294.         pPages->pElems[i]->AddRef();
  295.     
  296.     return NOERROR;
  297. }
  298.  
  299. /////////////////////////////////////////////////////////////////////////////
  300. // CAdvancedCategory
  301.  
  302. class CAdvancedCategory : public CCategory {
  303.     public:
  304.         CAdvancedCategory(LPUNKNOWN pUnkOuter);
  305.  
  306.         // IUnknown methods. Doesn't delegate (explicit IUnknown)
  307.         STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
  308.  
  309.     private:
  310.         class CSpecifyAdvancedPageObjects : public CCategory::CSpecifyPageObjects {
  311.             public:
  312.                 CSpecifyAdvancedPageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter);
  313.  
  314.                 // ISpecifyPropertyPageObjects methods
  315.                 STDMETHODIMP GetPageObjects(CAPPAGE *pPages);
  316.         };
  317.  
  318.         CSpecifyAdvancedPageObjects m_innerObj;
  319. };
  320.  
  321. CAdvancedCategory::CAdvancedCategory(LPUNKNOWN pUnkOuter)
  322.     : m_innerObj(this, pUnkOuter)
  323. {
  324. }
  325.  
  326. STDMETHODIMP
  327. CAdvancedCategory::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  328. {
  329.     if (riid == IID_IUnknown) {
  330.         *ppvObj = (LPVOID)this;
  331.         AddRef();
  332.         return NOERROR;
  333.     
  334.     } else if (riid == IID_ISpecifyPropertyPageObjects) {
  335.         *ppvObj = (LPVOID)&m_innerObj;
  336.         m_innerObj.AddRef();
  337.         return NOERROR;
  338.     
  339.     } else {
  340.         *ppvObj = NULL;
  341.         return ResultFromScode(E_NOINTERFACE);
  342.     }
  343. }
  344.  
  345. CAdvancedCategory::CSpecifyAdvancedPageObjects::CSpecifyAdvancedPageObjects(CCategory *pBackObj, LPUNKNOWN pUnkOuter)
  346.     : CSpecifyPageObjects(pBackObj, pUnkOuter)
  347. {
  348. }
  349.  
  350. STDMETHODIMP
  351. CAdvancedCategory::CSpecifyAdvancedPageObjects::GetPageObjects(CAPPAGE *pPages)
  352. {
  353.     if (!pPages)
  354.         return ResultFromScode(E_POINTER);
  355.  
  356. #ifdef MOZ_MAIL_NEWS
  357.     pPages->cElems = 4;
  358. #else
  359.     pPages->cElems = 3;
  360. #endif /* MOZ_MAIL_NEWS */
  361.     pPages->pElems = (LPPROPERTYPAGE *)CoTaskMemAlloc(pPages->cElems * sizeof(LPPROPERTYPAGE));
  362.     if (!pPages->pElems)
  363.         return ResultFromScode(E_OUTOFMEMORY);
  364.  
  365.     pPages->pElems[0] = new CAdvancedPrefs;
  366.     pPages->pElems[1] = new CCachePrefs;
  367.     pPages->pElems[2] = new CProxiesPrefs;
  368. #ifdef MOZ_MAIL_NEWS   
  369.     pPages->pElems[3] = new CDiskSpacePrefs;
  370. #endif /* MOZ_MAIL_NEWS */
  371.     
  372.     for (ULONG i = 0; i < pPages->cElems; i++)
  373.         pPages->pElems[i]->AddRef();
  374.     
  375.     return NOERROR;
  376. }
  377.  
  378. /////////////////////////////////////////////////////////////////////////////
  379. // Class CPropertyPageFactory
  380.  
  381. // Class factory for our property pages. We use the same C++ class
  382. // to handle all of our CLSIDs
  383. class CPropertyPageFactory : public IClassFactory {
  384.     public:
  385.         CPropertyPageFactory(REFCLSID rClsid);
  386.  
  387.         // *** IUnknown methods ***
  388.         STDMETHODIMP             QueryInterface(REFIID, LPVOID FAR*);
  389.         STDMETHODIMP_(ULONG)     AddRef();
  390.         STDMETHODIMP_(ULONG)     Release();
  391.      
  392.         // *** IClassFactory methods ***
  393.         STDMETHODIMP             CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*);
  394.         STDMETHODIMP             LockServer(BOOL bLock);
  395.  
  396.     private:
  397.         CRefDll    m_refDll;
  398.         ULONG   m_uRef;
  399.         CLSID    m_clsid;
  400. };
  401.  
  402. /////////////////////////////////////////////////////////////////////////////
  403. // CPropertyPageFactory implementation
  404.  
  405. CPropertyPageFactory::CPropertyPageFactory(REFCLSID rClsid)
  406. {
  407.     m_uRef = 0;
  408.     m_clsid = rClsid;
  409. }
  410.  
  411. // *** IUnknown methods ***
  412. STDMETHODIMP CPropertyPageFactory::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  413. {
  414.     *ppvObj = NULL;
  415.  
  416.     if (riid == IID_IUnknown || riid == IID_IClassFactory)
  417.         *ppvObj = (LPVOID)this;
  418.  
  419.     if (*ppvObj) {
  420.         AddRef();
  421.         return NOERROR;
  422.     }
  423.  
  424.     return ResultFromScode(E_NOINTERFACE);
  425. }
  426.  
  427.  
  428. STDMETHODIMP_(ULONG) CPropertyPageFactory::AddRef()
  429. {
  430.     return ++m_uRef;
  431. }
  432.  
  433.  
  434. STDMETHODIMP_(ULONG) CPropertyPageFactory::Release(void)
  435. {
  436.     if (--m_uRef == 0) {
  437. #ifdef _DEBUG
  438.         OutputDebugString("Destroying CPropertyPageFactory class object.\n");
  439. #endif
  440.            delete this;
  441.         return 0;
  442.     }
  443.  
  444.     return m_uRef;
  445. }
  446.  
  447. // *** IClassFactory methods ***
  448. STDMETHODIMP CPropertyPageFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppvObj)
  449. {
  450.     // When requesting aggregation, the outer object must explicitly ask
  451.     // for IUnknown
  452.     if (pUnkOuter && riid != IID_IUnknown)
  453.         return ResultFromScode(CLASS_E_NOAGGREGATION);
  454.  
  455. #ifdef _DEBUG
  456.     OutputDebugString("CPropertyPageFactory::CreateInstance() called.\n");
  457. #endif
  458.     LPUNKNOWN pCategory;
  459.      
  460.     if (m_clsid == CLSID_AppearancePrefs)
  461.         pCategory = new CAppearanceCategory(pUnkOuter);
  462.     else if (m_clsid == CLSID_BrowserPrefs)
  463.         pCategory = new CBrowserCategory(pUnkOuter);
  464.     else if (m_clsid == CLSID_AdvancedPrefs)
  465.         pCategory = new CAdvancedCategory(pUnkOuter);
  466.     
  467.     if (!pCategory)
  468.         return ResultFromScode(E_OUTOFMEMORY);
  469.  
  470.     pCategory->AddRef();
  471.     HRESULT    hRes = pCategory->QueryInterface(riid, ppvObj);
  472.     pCategory->Release();
  473.     return hRes;
  474. }
  475.  
  476.  
  477. STDMETHODIMP CPropertyPageFactory::LockServer(BOOL bLock)
  478. {
  479.     CComDll    *pDll = CProcess::GetProcessDll();
  480.     HRESULT     hres;
  481.  
  482.     assert(pDll);
  483.     hres = CoLockObjectExternal(pDll, bLock, TRUE);
  484.     pDll->Release();
  485.     return hres;
  486. }
  487.  
  488. /////////////////////////////////////////////////////////////////////////////
  489. // CGeneralPrefsDll implementation
  490.  
  491. HRESULT
  492. CGeneralPrefsDll::GetClassObject(REFCLSID rClsid, REFIID riid, LPVOID *ppObj)
  493. {
  494.     HRESULT hres = ResultFromScode(E_UNEXPECTED);
  495.     *ppObj = NULL;
  496.  
  497. #ifdef _DEBUG
  498.     OutputDebugString("CGeneralPrefsDll::GetClassObject() called.\n");
  499. #endif
  500.  
  501.     // See if we have that particular class object.
  502.     if (rClsid == CLSID_AppearancePrefs ||
  503.         rClsid == CLSID_BrowserPrefs ||
  504.         rClsid == CLSID_AdvancedPrefs) {
  505.  
  506.         // Create a class object
  507.         CPropertyPageFactory *pFactory = new CPropertyPageFactory(rClsid);
  508.  
  509.         if (!pFactory)
  510.             return ResultFromScode(E_OUTOFMEMORY);
  511.             
  512.         // Get the desired interface. Note if the QueryInterface fails, the Release
  513.         // will delete the class object
  514.         pFactory->AddRef();
  515.         hres = pFactory->QueryInterface(riid, ppObj);
  516.         pFactory->Release(); 
  517.  
  518.     } else {
  519.         hres = ResultFromScode(CLASS_E_CLASSNOTAVAILABLE);
  520.     }
  521.  
  522.     return hres;
  523. }
  524.  
  525. // Return array of implemented CLSIDs by this DLL. Allocated
  526. // memory freed by caller.
  527. const CLSID **
  528. CGeneralPrefsDll::GetCLSIDs()
  529. {
  530.     const CLSID **ppRetval = (const CLSID **)CoTaskMemAlloc(sizeof(CLSID *) * 4);
  531.  
  532.     if (ppRetval) {
  533.         ppRetval[0] = &CLSID_AppearancePrefs;
  534.         ppRetval[1] = &CLSID_BrowserPrefs;
  535.         ppRetval[2] = &CLSID_AdvancedPrefs;
  536.         ppRetval[3] = NULL;
  537.     }
  538.  
  539.     return ppRetval;
  540. }
  541.  
  542. #ifdef _WIN32
  543. BOOL WINAPI
  544. DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved)
  545. {
  546.     switch (fdwReason) {
  547.         case DLL_PROCESS_ATTACH:
  548.             // The DLL is being loaded for the first time by a given process
  549.             CComDll::m_hInstance = hInstance;
  550.             break;
  551.  
  552.         case DLL_PROCESS_DETACH:
  553.             // The DLL is being unloaded by a given process
  554.             break;
  555.  
  556.         case DLL_THREAD_ATTACH:
  557.             // A thread is being created in a process that has already loaded
  558.             // this DLL
  559.             break;
  560.  
  561.         case DLL_THREAD_DETACH:
  562.             // A thread is exiting cleanly in a process that has already
  563.             // loaded this DLL
  564.             break;
  565.     }
  566.  
  567.     return TRUE;
  568. }
  569. #else
  570. extern "C" int CALLBACK
  571. LibMain(HINSTANCE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR)
  572. {
  573.     CComDll::m_hInstance = hInstance;
  574.     return TRUE;
  575. }
  576. #endif
  577.  
  578.