You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
8.3 KiB
303 lines
8.3 KiB
#include "stdafx.h"
|
|
#include "Ctrl.h"
|
|
#include "Extension.h"
|
|
|
|
#if ENABLE_MSGTABLE_API
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* class DuExtension
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
static const GUID guidAysncDestroy = { 0xbfe02331, 0xc17d, 0x45ea, { 0x96, 0x35, 0xa0, 0x7a, 0x90, 0x37, 0xfe, 0x34 } }; // {BFE02331-C17D-45ea-9635-A07A9037FE34}
|
|
MSGID DuExtension::s_msgidAsyncDestroy = 0;
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::~DuExtension
|
|
*
|
|
* ~DuExtension() checks that resources were properly cleaned up before the
|
|
* DuExtension was destroyed.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
DuExtension::~DuExtension()
|
|
{
|
|
//
|
|
// Ensure proper destruction
|
|
//
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
DuExtension::InitClass()
|
|
{
|
|
s_msgidAsyncDestroy = RegisterGadgetMessage(&guidAysncDestroy);
|
|
return s_msgidAsyncDestroy != 0 ? S_OK : (HRESULT) GetLastError();
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::Create
|
|
*
|
|
* Create() initializes a new DuExtension and attaches it to the subject Gadget
|
|
* being modified.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HRESULT
|
|
DuExtension::Create(
|
|
IN Visual * pgvSubject, // Gadget being "extended"
|
|
IN PRID pridExtension, // Short ID for DuExtension
|
|
IN UINT nOptions) // Options
|
|
{
|
|
AssertMsg(pridExtension > 0, "Must have valid PRID");
|
|
|
|
|
|
//
|
|
// Do not allow attaching a DuExtension to a Gadget that has already started
|
|
// the destruction process.
|
|
//
|
|
|
|
HGADGET hgadSubject = DUserCastHandle(pgvSubject);
|
|
|
|
BOOL fStartDelete;
|
|
if ((!IsStartDelete(hgadSubject, &fStartDelete)) || fStartDelete) {
|
|
return DU_E_STARTDESTROY;
|
|
}
|
|
|
|
|
|
//
|
|
// Setup options
|
|
//
|
|
|
|
m_fAsyncDestroy = TestFlag(nOptions, oAsyncDestroy);
|
|
|
|
|
|
//
|
|
// Determine if this DuExtension is already attached to the Gadget being
|
|
// extended.
|
|
//
|
|
|
|
DuExtension * pbExist;
|
|
if (SUCCEEDED(pgvSubject->GetProperty(pridExtension, (void **) &pbExist))) {
|
|
AssertMsg(pbExist != NULL, "Existing Extension must not be NULL");
|
|
if (TestFlag(nOptions, oUseExisting)) {
|
|
return DU_S_ALREADYEXISTS;
|
|
} else {
|
|
//
|
|
// Already attached, but can't use the existing one. We need to
|
|
// remove the existing DuExtension before attaching the new one.
|
|
// After calling RemoveExisting(), the DuExtension should no longer
|
|
// be attached to the Gadget.
|
|
//
|
|
|
|
pbExist->GetStub()->OnRemoveExisting();
|
|
Assert(FAILED(pgvSubject->GetProperty(pridExtension, (void **) &pbExist)));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Setup a listener to be notifyed when the RootGadget is destroyed.
|
|
//
|
|
|
|
HRESULT hr = S_OK;
|
|
m_pgvSubject = pgvSubject;
|
|
m_pridListen = pridExtension;
|
|
|
|
if (FAILED(pgvSubject->SetProperty(pridExtension, this)) ||
|
|
FAILED(pgvSubject->AddHandlerG(GM_DESTROY, GetStub()))) {
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
|
|
//
|
|
// Successfully created the DuExtension
|
|
//
|
|
|
|
return S_OK;
|
|
|
|
Error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::Destroy
|
|
*
|
|
* Destroy() is called from the derived class to cleanup resources associated
|
|
* with the DuExtension.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
DuExtension::Destroy()
|
|
{
|
|
//
|
|
// Since the DuExtension is being destroyed, need to ensure that it is no
|
|
// longer "attached" to the Gadget being extended
|
|
//
|
|
|
|
if ((m_pridListen != 0) && (m_pgvSubject != NULL)) {
|
|
DuExtension * pb;
|
|
if (SUCCEEDED(m_pgvSubject->GetProperty(m_pridListen, (void **) &pb))) {
|
|
if (pb == this) {
|
|
m_pgvSubject->RemoveProperty(m_pridListen);
|
|
}
|
|
}
|
|
}
|
|
|
|
Delete();
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::DeleteHandle
|
|
*
|
|
* DeleteHandle() starts the destruction process for the DuExtension.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
DuExtension::DeleteHandle()
|
|
{
|
|
Delete();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
DuExtension::ApiOnEvent(EventMsg * pmsg)
|
|
{
|
|
switch (GET_EVENT_DEST(pmsg))
|
|
{
|
|
case GMF_DIRECT:
|
|
if (m_fAsyncDestroy && (pmsg->nMsg == s_msgidAsyncDestroy)) {
|
|
GetStub()->OnAsyncDestroy();
|
|
return DU_S_PARTIAL;
|
|
}
|
|
break;
|
|
|
|
case GMF_EVENT:
|
|
if (pmsg->nMsg == GM_DESTROY) {
|
|
if (((GMSG_DESTROY *) pmsg)->nCode == GDESTROY_FINAL) {
|
|
GetStub()->OnDestroySubject();
|
|
return DU_S_PARTIAL;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return SListener::ApiOnEvent(pmsg);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::ApiOnRemoveExisting
|
|
*
|
|
* ApiOnRemoveExisting() is called when creating a new DuExtension to remove
|
|
* an existing DuExtension already attached to the subject Gadget.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HRESULT
|
|
DuExtension::ApiOnRemoveExisting(Extension::OnRemoveExistingMsg *)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::ApiOnDestroySubject
|
|
*
|
|
* ApiOnDestroySubject() notifies the derived DuExtension that the subject
|
|
* Gadget being modified has been destroyed.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HRESULT
|
|
DuExtension::ApiOnDestroySubject(Extension::OnDestroySubjectMsg *)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::ApiOnAsyncDestroy
|
|
*
|
|
* ApiOnAsyncDestroy() is called when the DuExtension receives an asynchronous
|
|
* destruction message that was previously posted. This provides the derived
|
|
* DuExtension an opportunity to start the destruction process without being
|
|
* nested several levels.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HRESULT
|
|
DuExtension::ApiOnAsyncDestroy(Extension::OnAsyncDestroyMsg *)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::PostAsyncDestroy
|
|
*
|
|
* PostAsyncDestroy() queues an asynchronous destruction message. This
|
|
* provides the derived DuExtension an opportunity to start the destruction
|
|
* process without being nested several levels.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
DuExtension::PostAsyncDestroy()
|
|
{
|
|
AssertMsg(m_fAsyncDestroy,
|
|
"Must create DuExtension with oAsyncDestroy if want to destroy asynchronously");
|
|
Assert(s_msgidAsyncDestroy != 0);
|
|
EventMsg msg;
|
|
ZeroMemory(&msg, sizeof(msg));
|
|
msg.cbSize = sizeof(msg);
|
|
msg.hgadMsg = GetHandle();
|
|
msg.nMsg = s_msgidAsyncDestroy;
|
|
|
|
DUserPostEvent(&msg, 0);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DuExtension::GetExtension
|
|
*
|
|
* GetExtension() retrieves the DuExtension of a specific type currently
|
|
* attached to the subject Gadget.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
DuExtension *
|
|
DuExtension::GetExtension(Visual * pgvSubject, PRID prid)
|
|
{
|
|
DuExtension * pbExist;
|
|
if (SUCCEEDED(pgvSubject->GetProperty(prid, (void **) &pbExist))) {
|
|
AssertMsg(pbExist != NULL, "Attached DuExtension must be valid");
|
|
return pbExist;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif // ENABLE_MSGTABLE_API
|