439 lines
11 KiB
C++
439 lines
11 KiB
C++
//+----------------------------------------------------------------------------
|
|
//
|
|
// Windows NT Active Directory Property Page Sample
|
|
//
|
|
// The code contained in this source file is for demonstration purposes only.
|
|
// No warrantee is expressed or implied and Microsoft disclaims all liability
|
|
// for the consequenses of the use of this source code.
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
//
|
|
// File: host.cxx
|
|
//
|
|
// Contents: CDsPropPageHost, the class that exposes IShellExtInit and
|
|
// IShellPropSheetExt
|
|
// Also, the ClassFactory and IUnknown code.
|
|
//
|
|
// History: 8-Sep-97 Eric Brown created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "page.h"
|
|
|
|
CLIPFORMAT g_cfDsObjectNames = 0;
|
|
const CLSID CLSID_SamplePage = { /* cca62184-294f-11d1-bcfe-00c04fd8d5b6 */
|
|
0xcca62184,
|
|
0x294f,
|
|
0x11d1,
|
|
{0xbc, 0xfe, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xb6}
|
|
};
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::CDsPropPageHost
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CDsPropPageHost::CDsPropPageHost() :
|
|
m_pDataObj(NULL),
|
|
m_uRefs(1)
|
|
{
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::~CDsPropPageHost
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CDsPropPageHost::~CDsPropPageHost()
|
|
{
|
|
if (m_pDataObj)
|
|
{
|
|
m_pDataObj->Release();
|
|
}
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::IShellExtInit::Initialize
|
|
//
|
|
// Returns: HRESULTS
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHost::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj,
|
|
HKEY hKeyID)
|
|
{
|
|
if (IsBadReadPtr(pDataObj, sizeof(LPDATAOBJECT)))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (m_pDataObj)
|
|
{
|
|
m_pDataObj->Release();
|
|
m_pDataObj = NULL;
|
|
}
|
|
|
|
// Hang onto the IDataObject we are being passed.
|
|
|
|
m_pDataObj = pDataObj;
|
|
if (m_pDataObj)
|
|
{
|
|
m_pDataObj->AddRef();
|
|
}
|
|
else
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Check to see if we have our clipboard format registered, if not then
|
|
// lets do it.
|
|
|
|
if (!g_cfDsObjectNames)
|
|
{
|
|
g_cfDsObjectNames = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
|
|
}
|
|
if (!g_cfDsObjectNames)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::IShellExtInit::AddPages
|
|
//
|
|
// Returns: HRESULTS
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHost::AddPages(LPFNADDPROPSHEETPAGE pAddPageProc, LPARAM lParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HPROPSHEETPAGE hPage;
|
|
STGMEDIUM ObjMedium = {TYMED_NULL};
|
|
FORMATETC fmte = {g_cfDsObjectNames, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
|
LPDSOBJECTNAMES pDsObjectNames;
|
|
PWSTR pwzObjName;
|
|
PWSTR pwzClass;
|
|
CDsPropPage * PropPage;
|
|
|
|
//
|
|
// Get the path to the DS object from the data object.
|
|
// Note: This call runs on the caller's main thread. The pages' window
|
|
// procs run on a different thread, so don't reference the data object
|
|
// from a winproc unless it is first marshalled on this thread.
|
|
//
|
|
hr = m_pDataObj->GetData(&fmte, &ObjMedium);
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
pDsObjectNames = (LPDSOBJECTNAMES)ObjMedium.hGlobal;
|
|
|
|
if (pDsObjectNames->cItems < 1)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
pwzObjName = (PWSTR)ByteOffset(pDsObjectNames,
|
|
pDsObjectNames->aObjects[0].offsetName);
|
|
pwzClass = (PWSTR)ByteOffset(pDsObjectNames,
|
|
pDsObjectNames->aObjects[0].offsetClass);
|
|
|
|
//
|
|
// NOTIFY_OBJ
|
|
// Create/contact the notification object.
|
|
//
|
|
HWND hNotifyObj;
|
|
|
|
hr = ADsPropCreateNotifyObj(m_pDataObj, pwzObjName, &hNotifyObj);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Create the page.
|
|
//
|
|
PropPage = new CDsPropPage(hNotifyObj);
|
|
|
|
hr = PropPage->Init(pwzObjName, pwzClass);
|
|
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = PropPage->CreatePage(&hPage);
|
|
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Invoke the callback function, which will add the page to the list of
|
|
// pages that will be used to create the property sheet.
|
|
//
|
|
(*pAddPageProc)(hPage, lParam);
|
|
|
|
Cleanup:
|
|
ReleaseStgMedium(&ObjMedium);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::IShellExtInit::ReplacePage
|
|
//
|
|
// Notes: Not used.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHost::ReplacePage(UINT uPageID,
|
|
LPFNADDPROPSHEETPAGE lpfnReplaceWith,
|
|
LPARAM lParam)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::IUnknown::QueryInterface
|
|
//
|
|
// Synopsis: Returns requested interface pointer
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHost::QueryInterface(REFIID riid, void ** ppvObject)
|
|
{
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
*ppvObject = (IUnknown *)(LPSHELLEXTINIT)this;
|
|
}
|
|
else if (IID_IShellExtInit == riid)
|
|
{
|
|
*ppvObject = (LPSHELLEXTINIT)this;
|
|
}
|
|
else if (IID_IShellPropSheetExt == riid)
|
|
{
|
|
*ppvObject = (LPSHELLPROPSHEETEXT)this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObject = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::IUnknown::AddRef
|
|
//
|
|
// Synopsis: increments reference count
|
|
//
|
|
// Returns: the reference count
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CDsPropPageHost::AddRef(void)
|
|
{
|
|
return InterlockedIncrement((long *)&m_uRefs);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHost::IUnknown::Release
|
|
//
|
|
// Synopsis: Decrements the object's reference count and frees it when
|
|
// no longer referenced.
|
|
//
|
|
// Returns: zero if the reference count is zero or non-zero otherwise
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CDsPropPageHost::Release(void)
|
|
{
|
|
unsigned long uTmp;
|
|
if ((uTmp = InterlockedDecrement((long *)&m_uRefs)) == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
return uTmp;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// CDsPropPageHostCF - class factory for the CDsPropPageHost object
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::Create
|
|
//
|
|
// Synopsis: creates a new class factory object
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
IClassFactory *
|
|
CDsPropPageHostCF::Create(void)
|
|
{
|
|
return new CDsPropPageHostCF();
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::CDsPropPageHostCF
|
|
//
|
|
// Synopsis: ctor
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CDsPropPageHostCF::CDsPropPageHostCF() :
|
|
m_uRefs(1)
|
|
{
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::~CDsPropPageHostCF
|
|
//
|
|
// Synopsis: dtor
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CDsPropPageHostCF::~CDsPropPageHostCF(void)
|
|
{
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::IUnknown::QueryInterface
|
|
//
|
|
// Synopsis: Returns requested interface pointer
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHostCF::QueryInterface(REFIID riid, void ** ppvObject)
|
|
{
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
*ppvObject = (IUnknown *)this;
|
|
}
|
|
else if (IsEqualIID(IID_IClassFactory, riid))
|
|
{
|
|
*ppvObject = (IClassFactory *)this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObject = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::IUnknown::AddRef
|
|
//
|
|
// Synopsis: increments reference count
|
|
//
|
|
// Returns: the new reference count
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CDsPropPageHostCF::AddRef(void)
|
|
{
|
|
return InterlockedIncrement((long *)&m_uRefs);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::IUnknown::Release
|
|
//
|
|
// Synopsis: decrement the refcount
|
|
//
|
|
// Returns: the new reference count
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CDsPropPageHostCF::Release(void)
|
|
{
|
|
unsigned long uTmp;
|
|
if ((uTmp = InterlockedDecrement((long *)&m_uRefs)) == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
return uTmp;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::IClassFactory::CreateInstance
|
|
//
|
|
// Synopsis: create an incore instance of the proppage host class object
|
|
//
|
|
// Arguments: [pUnkOuter] - aggregator
|
|
// [riid] - requested interface
|
|
// [ppvObject] - receptor for itf ptr
|
|
//
|
|
// Returns: HRESULTS
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHostCF::CreateInstance(IUnknown *pUnkOuter, REFIID riid,
|
|
void **ppvObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
*ppvObject = NULL;
|
|
|
|
CDsPropPageHost * pPropPage = new CDsPropPageHost();
|
|
if (pPropPage == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pPropPage->QueryInterface(riid, ppvObject);
|
|
if (FAILED(hr))
|
|
{
|
|
pPropPage->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// We got a refcount of one when launched, and the above QI increments it
|
|
// to 2, so call release to take it back to 1.
|
|
//
|
|
pPropPage->Release();
|
|
return hr;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CDsPropPageHostCF::IClassFactory::LockServer
|
|
//
|
|
// Synopsis: Called with fLock set to TRUE to indicate that the server
|
|
// should continue to run even if none of its objects are active
|
|
//
|
|
// Arguments: [fLock] - increment/decrement the instance count
|
|
//
|
|
// Returns: HRESULTS
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CDsPropPageHostCF::LockServer(BOOL fLock)
|
|
{
|
|
CDll::LockServer(fLock);
|
|
return S_OK;
|
|
}
|
|
|