#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; }