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.
358 lines
9.7 KiB
358 lines
9.7 KiB
#include "stdafx.h"
|
|
#include "Ctrl.h"
|
|
#include "OldExtension.h"
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* class OldExtension
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
static const GUID guidAysncDestroy = { 0xbfe02331, 0xc17d, 0x45ea, { 0x96, 0x35, 0xa0, 0x7a, 0x90, 0x37, 0xfe, 0x34 } }; // {BFE02331-C17D-45ea-9635-A07A9037FE34}
|
|
MSGID OldExtension::s_msgidAsyncDestroy = 0;
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::~OldExtension
|
|
*
|
|
* ~OldExtension() checks that resources were properly cleaned up before the
|
|
* OldExtension was destroyed.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
OldExtension::~OldExtension()
|
|
{
|
|
//
|
|
// Ensure proper destruction
|
|
//
|
|
|
|
AssertMsg(m_hgadListen == NULL, "Gadget should already be destroyed");
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::Create
|
|
*
|
|
* Create() initializes a new OldExtension and attaches it to the subject Gadget
|
|
* being modified.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HRESULT
|
|
OldExtension::Create(
|
|
IN HGADGET hgadSubject, // Gadget being "extended"
|
|
IN const GUID * pguid, // Unique ID of OldExtension
|
|
IN OUT PRID * pprid, // Short ID for OldExtension
|
|
IN UINT nOptions) // Options
|
|
{
|
|
AssertWritePtr(pprid);
|
|
|
|
|
|
//
|
|
// Do not allow attaching a OldExtension to a Gadget that has already started
|
|
// the destruction process.
|
|
//
|
|
|
|
BOOL fStartDelete;
|
|
if ((!IsStartDelete(hgadSubject, &fStartDelete)) || fStartDelete) {
|
|
return DU_E_STARTDESTROY;
|
|
}
|
|
|
|
|
|
//
|
|
// Setup information necessary for asynchronous destruction.
|
|
//
|
|
|
|
m_fAsyncDestroy = TestFlag(nOptions, oAsyncDestroy);
|
|
if (m_fAsyncDestroy) {
|
|
if (s_msgidAsyncDestroy == 0) {
|
|
s_msgidAsyncDestroy = RegisterGadgetMessage(&guidAysncDestroy);
|
|
if (s_msgidAsyncDestroy == 0) {
|
|
return (HRESULT) GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Determine if this OldExtension is already attached to the Gadget being
|
|
// extended.
|
|
//
|
|
|
|
if (*pprid == 0) {
|
|
*pprid = RegisterGadgetProperty(pguid);
|
|
if (*pprid == 0) {
|
|
return GetLastError();
|
|
}
|
|
}
|
|
PRID prid = *pprid;
|
|
|
|
OldExtension * pbExist;
|
|
if (GetGadgetProperty(hgadSubject, prid, (void **) &pbExist) != 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 OldExtension before attaching the new one. After
|
|
// calling RemoveExisting(), the OldExtension should no longer be
|
|
// attached to the Gadget.
|
|
//
|
|
|
|
pbExist->OnRemoveExisting();
|
|
Assert(!GetGadgetProperty(hgadSubject, prid, (void **) &pbExist));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Setup a listener to be notifyed when the RootGadget is destroyed.
|
|
//
|
|
|
|
HRESULT hr = S_OK;
|
|
m_hgadListen = CreateGadget(NULL, GC_MESSAGE, ListenProc, this);
|
|
if (m_hgadListen == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
m_hgadSubject = hgadSubject;
|
|
m_pridListen = prid;
|
|
|
|
if (!SetGadgetProperty(hgadSubject, prid, this) ||
|
|
(!AddGadgetMessageHandler(hgadSubject, GM_DESTROY, m_hgadListen))) {
|
|
|
|
DeleteObject(m_hgadListen);
|
|
m_hgadListen = NULL;
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
|
|
//
|
|
// Successfully created the OldExtension
|
|
//
|
|
|
|
return S_OK;
|
|
|
|
Error:
|
|
Destroy();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::Destroy
|
|
*
|
|
* Destroy() is called from the derived class to cleanup resources associated
|
|
* with the OldExtension.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::Destroy()
|
|
{
|
|
//
|
|
// Since the OldExtension is being destroyed, need to ensure that it is no
|
|
// longer "attached" to the Gadget being extended
|
|
//
|
|
|
|
if ((m_pridListen != 0) && (m_hgadSubject != NULL)) {
|
|
OldExtension * pb;
|
|
if (GetGadgetProperty(m_hgadSubject, m_pridListen, (void **) &pb)) {
|
|
if (pb == this) {
|
|
RemoveGadgetProperty(m_hgadSubject, m_pridListen);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_hgadListen != NULL) {
|
|
::DeleteHandle(m_hgadListen);
|
|
m_hgadListen = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::DeleteHandle
|
|
*
|
|
* DeleteHandle() starts the destruction process for the OldExtension.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::DeleteHandle()
|
|
{
|
|
if (m_hgadListen != NULL) {
|
|
HGADGET hgad = m_hgadListen;
|
|
m_hgadListen = NULL;
|
|
::DeleteHandle(hgad);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::ListenProc
|
|
*
|
|
* ListenProc() is called on the MessageGadget Listener attached to the
|
|
* RootGadget.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HRESULT
|
|
OldExtension::ListenProc(HGADGET hgadCur, void * pvCur, EventMsg * pmsg)
|
|
{
|
|
UNREFERENCED_PARAMETER(hgadCur);
|
|
OldExtension * pb = (OldExtension *) pvCur;
|
|
|
|
switch (GET_EVENT_DEST(pmsg))
|
|
{
|
|
case GMF_DIRECT:
|
|
if (pmsg->nMsg == GM_DESTROY) {
|
|
GMSG_DESTROY * pmsgD = (GMSG_DESTROY *) pmsg;
|
|
if (pmsgD->nCode == GDESTROY_FINAL) {
|
|
pb->OnDestroyListener();
|
|
return DU_S_PARTIAL;
|
|
}
|
|
} else if (pb->m_fAsyncDestroy && (pmsg->nMsg == s_msgidAsyncDestroy)) {
|
|
pb->OnAsyncDestroy();
|
|
return DU_S_PARTIAL;
|
|
}
|
|
break;
|
|
|
|
case GMF_EVENT:
|
|
if (pmsg->nMsg == GM_DESTROY) {
|
|
if (((GMSG_DESTROY *) pmsg)->nCode == GDESTROY_FINAL) {
|
|
pb->OnDestroySubject();
|
|
return DU_S_PARTIAL;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return DU_S_NOTHANDLED;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::OnRemoveExisting
|
|
*
|
|
* OnRemoveExisting() is called when creating a new OldExtension to remove an
|
|
* existing OldExtension already attached to the subject Gadget.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::OnRemoveExisting()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::OnDestroySubject
|
|
*
|
|
* OnDestroySubject() notifies the derived OldExtension that the subject Gadget
|
|
* being modified has been destroyed.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::OnDestroySubject()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::OnDestroyListener
|
|
*
|
|
* OnDestroyListener() notifies the derived OldExtension that the internal
|
|
* "Listener" Gadget has been destroyed and that the OldExtension should start
|
|
* its destruction process.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::OnDestroyListener()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::OnAsyncDestroy
|
|
*
|
|
* OnAsyncDestroy() is called when the OldExtension receives an asynchronous
|
|
* destruction message that was previously posted. This provides the derived
|
|
* OldExtension an opportunity to start the destruction process without being
|
|
* nested several levels.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::OnAsyncDestroy()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::PostAsyncDestroy
|
|
*
|
|
* PostAsyncDestroy() queues an asynchronous destruction message. This
|
|
* provides the derived OldExtension an opportunity to start the destruction
|
|
* process without being nested several levels.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
void
|
|
OldExtension::PostAsyncDestroy()
|
|
{
|
|
AssertMsg(m_fAsyncDestroy,
|
|
"Must create OldExtension with oAsyncDestroy if want to destroy asynchronously");
|
|
Assert(s_msgidAsyncDestroy != 0);
|
|
AssertMsg(m_hgadListen, "Must still have a valid Listener");
|
|
|
|
EventMsg msg;
|
|
ZeroMemory(&msg, sizeof(msg));
|
|
msg.cbSize = sizeof(msg);
|
|
msg.hgadMsg = m_hgadListen;
|
|
msg.nMsg = s_msgidAsyncDestroy;
|
|
|
|
DUserPostEvent(&msg, 0);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* OldExtension::GetExtension
|
|
*
|
|
* GetExtension() retrieves the OldExtension of a specific type currently
|
|
* attached to the subject Gadget.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
OldExtension *
|
|
OldExtension::GetExtension(HGADGET hgadSubject, PRID prid)
|
|
{
|
|
OldExtension * pbExist;
|
|
if (GetGadgetProperty(hgadSubject, prid, (void **) &pbExist)) {
|
|
AssertMsg(pbExist != NULL, "Attached OldExtension must be valid");
|
|
return pbExist;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|