windows-nt/Source/XPSP1/NT/shell/osshell/dskquota/ui/prshtext.cpp
2020-09-26 16:20:57 +08:00

504 lines
15 KiB
C++

///////////////////////////////////////////////////////////////////////////////
/* File: prshtext.cpp
Description: DSKQUOTA property sheet extention implementation.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
07/03/97 Added m_hrInitialization member. BrianAu
01/23/98 Removed m_hrInitialization member. BrianAu
06/25/98 Disabled snapin code with #ifdef POLICY_MMC_SNAPIN. BrianAu
Switching to ADM-file approach to entering policy
data. Keeping snapin code available in case
we decide to switch back at a later time.
*/
///////////////////////////////////////////////////////////////////////////////
#include "pch.h" // PCH
#pragma hdrstop
#include "dskquota.h"
#include "prshtext.h"
#include "guidsp.h"
extern LONG g_cLockThisDll;
DiskQuotaPropSheetExt::DiskQuotaPropSheetExt(
VOID
) : m_cRef(0),
m_dwDlgTemplateID(0),
m_lpfnDlgProc(NULL),
m_hPage(NULL),
m_pQuotaControl(NULL),
m_cOleInitialized(0)
{
DBGTRACE((DM_PRSHTEXT, DL_HIGH, TEXT("DiskQuotaPropSheetExt::DiskQuotaPropSheetExt")));
InterlockedIncrement(&g_cRefThisDll);
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::~DiskQuotaPropSheetExt
Description: Destructor for the property sheet extension class.
Arguments: None.
Returns: Nothing.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
DiskQuotaPropSheetExt::~DiskQuotaPropSheetExt(VOID)
{
DBGTRACE((DM_PRSHTEXT, DL_HIGH, TEXT("DiskQuotaPropSheetExt::~DiskQuotaPropSheetExt")));
if (NULL != m_pQuotaControl)
{
m_pQuotaControl->Release();
m_pQuotaControl = NULL;
}
//
// Call OleUninitialize for each time OleInitialize was called in Initialize().
//
while(0 != m_cOleInitialized--)
{
DBGASSERT((0 <= m_cOleInitialized)); // Make sure we don't go negative.
CoUninitialize();
}
InterlockedDecrement(&g_cRefThisDll);
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::QueryInterface
Description: Returns an interface pointer to the object's IUnknown
and IShellPropSheetExt interfaces.
Arguments:
riid - Reference to requested interface ID.
ppvOut - Address of interface pointer variable to accept interface ptr.
Returns:
NO_ERROR - Success.
E_NOINTERFACE - Requested interface not supported.
E_INVALIDARG - ppvOut argument was NULL.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
DiskQuotaPropSheetExt::QueryInterface(
REFIID riid,
LPVOID *ppvOut
)
{
HRESULT hResult = E_NOINTERFACE;
if (NULL == ppvOut)
return E_INVALIDARG;
*ppvOut = NULL;
if (IID_IUnknown == riid ||
IID_IShellPropSheetExt == riid
#ifdef POLICY_MMC_SNAPIN
|| IID_ISnapInPropSheetExt == riid // This is not a "real" interface.
#endif
)
{
*ppvOut = this;
}
#ifdef POLICY_MMC_SNAPIN
else if (IID_IDiskQuotaPolicy == riid)
{
hResult = CreateDiskQuotaPolicyObject(reinterpret_cast<IDiskQuotaPolicy **>(ppvOut));
}
#endif
if (NULL != *ppvOut)
{
((LPUNKNOWN)*ppvOut)->AddRef();
hResult = NOERROR;
}
return hResult;
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::AddRef
Description: Increments object reference count.
Arguments: None.
Returns: New reference count value.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
DiskQuotaPropSheetExt::AddRef(
VOID
)
{
ULONG ulReturn = m_cRef + 1;
DBGPRINT((DM_COM, DL_HIGH, TEXT("DiskQuotaPropSheetExt::AddRef, 0x%08X %d -> %d\n"),
this, ulReturn - 1, ulReturn));
InterlockedIncrement(&m_cRef);
return ulReturn;
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::Release
Description: Decrements object reference count. If count drops to 0,
object is deleted.
Arguments: None.
Returns: New reference count value.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
DiskQuotaPropSheetExt::Release(
VOID
)
{
ULONG ulReturn = m_cRef - 1;
DBGPRINT((DM_COM, DL_HIGH, TEXT("DiskQuotaPropSheetExt::Release, 0x%08X %d -> %d\n"),
this, ulReturn + 1, ulReturn));
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
ulReturn = 0;
}
return ulReturn;
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::Initialize
Description: Initializes a new property sheet extension object.
Arguments:
idVolume - Reference to a CVolumeID object containing both parsable
and displayable names for the volume. In the case of
normal volumes, this is the same string. In the case
of mounted volumes, it may not be depending on what's
provided by the OS for the mounted volume. Most mounted
volumes have names like "\\?\Volume{ GUID }\".
dwDlgTemplateID - Resource ID for the dialog template to use for the
property sheet.
lpfnDlgProc - Address of dialog's window message procedure.
Returns:
NO_ERROR - Success.
ERROR_ACCESS_DENIED (hr) - Read access denied to the device.
Exceptions: OutOfMemory.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
06/27/98 Replaced volume name arg with CVolumeID arg to BrianAu
support mounted volumes.
*/
///////////////////////////////////////////////////////////////////////////////
HRESULT
DiskQuotaPropSheetExt::Initialize(
const CVolumeID& idVolume,
DWORD dwDlgTemplateID,
DLGPROC lpfnDlgProc
)
{
HRESULT hResult = NO_ERROR;
DBGASSERT((NULL != lpfnDlgProc));
DBGASSERT((0 != dwDlgTemplateID));
m_idVolume = idVolume;
m_dwDlgTemplateID = dwDlgTemplateID;
m_lpfnDlgProc = lpfnDlgProc;
//
// Volume parsing name will be blank for a snap-in prop page since
// it isn't displayed on behalf of any particular volume.
//
if (!m_idVolume.ForParsing().IsEmpty())
{
hResult = CoInitialize(NULL);
if (SUCCEEDED(hResult))
{
IDiskQuotaControl *pqc;
m_cOleInitialized++; // Need to call OleUninitialize once more in dtor.
//
// Validate that we can use quotas by instantiating the quota control
// object. If this fails the user probably doesn't have access
// to manipulate quotas.
//
hResult = GetQuotaController(&pqc);
if (SUCCEEDED(hResult))
{
pqc->Release();
//
// Also release the cached m_pQuotaControl ptr.
// We don't want to hold open a handle to the volume if our
// page is not active.
//
m_pQuotaControl->Release();
m_pQuotaControl = NULL;
}
}
}
return hResult;
}
//
// Get a pointer to the IDiskQuotaControl interface.
// If the cached m_pQuotaControl ptr is non-NULL we merely AddRef this
// and return it to the caller. Otherwise we CoCreate a new controller,
// cache the pointer in m_pQuotaControl and return that.
//
// History:
// Originally we opened the controller in ::Initialize() and cached
// the pointer in m_pQuotaControl. The controller remained alive
// until the prop SHEET was destroyed. This was holding open a handle
// to the volume device which prevented the disk checking function
// on the "Tools" page from accessing the volume. Therefore I
// changed the code so that now we call GetQuotaController whenever
// we want an IDiskQuotaControl pointer. The caller releases that
// ptr when done with it. Whenever the prop page becomes inactive
// we release the cached m_pQuotaControl. This ensures that the
// code has the volume open only when the page is active.
// [brianau - 5/21/99]
//
//
HRESULT
DiskQuotaPropSheetExt::GetQuotaController(
IDiskQuotaControl **ppqc
)
{
HRESULT hr = NOERROR;
*ppqc = NULL;
if (NULL == m_pQuotaControl)
{
//
// No cached ptr. Create a new controller.
//
hr = CoCreateInstance(CLSID_DiskQuotaControl,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDiskQuotaControl,
(LPVOID *)&m_pQuotaControl);
if (SUCCEEDED(hr))
{
hr = m_pQuotaControl->Initialize(m_idVolume.ForParsing(), TRUE);
if (FAILED(hr))
{
m_pQuotaControl->Release();
m_pQuotaControl = NULL;
}
}
}
if (NULL != m_pQuotaControl)
{
//
// Ptr is cached. Merely addref and return it.
//
*ppqc = m_pQuotaControl;
static_cast<IUnknown *>(*ppqc)->AddRef();
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::AddPages
Description: Called by the shell when a page is to be added to the property
sheet.
Arguments:
lpfnAddPage - Address of a callback function provided by the shell
that is to be called if the property page creation succedes.
lParam - Parameter to pass to lpfnAddPage function.
Returns:
NO_ERROR - Success.
E_FAIL - Failed to create or add page.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
08/15/96 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
DiskQuotaPropSheetExt::AddPages(
LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam
)
{
HRESULT hResult = E_FAIL; // Assume failure.
PROPSHEETPAGE psp;
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_USECALLBACK | PSP_USEREFPARENT;
psp.hInstance = g_hInstDll;
psp.pszTemplate = MAKEINTRESOURCE(m_dwDlgTemplateID);
psp.hIcon = NULL;
psp.pszTitle = NULL;
psp.pfnDlgProc = m_lpfnDlgProc;
psp.lParam = (LPARAM)this;
psp.pcRefParent = (UINT *)& g_cRefThisDll;
psp.pfnCallback = (LPFNPSPCALLBACK)PropSheetPageCallback;
m_hPage = CreatePropertySheetPage(&psp);
if (NULL != m_hPage)
{
if (!lpfnAddPage(m_hPage, lParam))
{
DBGERROR((TEXT("PRSHTEXT - Failed to add page.\n")));
DestroyPropertySheetPage(m_hPage);
m_hPage = NULL;
}
}
else
{
DBGERROR((TEXT("PRSHTEXT - CreatePropertySheetPage failed.\n")));
}
if (NULL != m_hPage)
{
//
// Incr ref count to keep the extension object alive.
// The shell will release it as soon as the page is created.
// We'll release it on PSPCB_RELEASE in PropSheetPageCallback.
//
AddRef();
hResult = NO_ERROR;
}
return hResult;
}
///////////////////////////////////////////////////////////////////////////////
/* Function: DiskQuotaPropSheetExt::PropSheetPageCallback
Description: Called by the property sheet code when the property page
is being created and again when it is being destroyed. This gives the
page a chance to act at these critical points. We primarily use it
to call Release() on the page extension which calls the virtual
destructor, ultimately destroying the VolumePropPage or FolderPropPage
object.
Arguments:
hwnd - Always NULL (according to SDK docs).
uMsg - PSPCB_CREATE = Creating page.
PSPCB_RELEASE = Destroying page.
ppsp - Pointer to the PROPSHEETPAGE structure for the page.
Returns:
Return value is ignore when uMsg is PSPCB_RELEASE.
On PSPCB_CREATE, returning 0 instructs the PropertySheet to NOT
display the page. 1 means OK to display page.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
09/12/96 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
UINT CALLBACK
DiskQuotaPropSheetExt::PropSheetPageCallback(
HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp
)
{
UINT uReturn = 1;
DiskQuotaPropSheetExt *pThis = (DiskQuotaPropSheetExt *)ppsp->lParam;
DBGASSERT((NULL != pThis));
switch(uMsg)
{
case PSPCB_CREATE:
//
// uReturn == 0 means Don't create the prop page.
//
uReturn = pThis->OnPropSheetPageCreate(ppsp);
break;
case PSPCB_RELEASE:
//
// uReturn is ignored for this uMsg.
//
pThis->OnPropSheetPageRelease(ppsp);
//
// This will release the extension and call the virtual
// destructor (which will destroy the prop page object).
//
pThis->Release();
break;
}
return uReturn;
}