FORMPRST.CPP
// --formprst.cpp------------------------------------------------------------- 
// 
//   Implementation of the FRM class IPersistMessage methods 
// 
// Copyright (C) Microsoft Corp. 1986-1996.  All Rights Reserved. 
// --------------------------------------------------------------------------- 
 
#include "stdafx.h" 
#include "tool.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char BASED_CODE THIS_FILE[] = __FILE__; 
#endif 
 
#define new DEBUG_NEW 
 
#include "formdata.h" 
#include "form.h" 
#include "tooldoc.h" 
#include "toolform.h" 
 
//$--FRM::GetLastError-------------------------------------------------------- 
// 
//  Purpose: 
//      Get the last error 
// 
//  Returns: 
//      HRESULT             NOERROR always. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR FAR * lppMAPIError) 
{ 
    ASSERT(m_cRef > 0); 
 
    if (lppMAPIError) 
        *lppMAPIError = NULL; 
    return NOERROR; 
} 
 
//$--FRM::GetClassID---------------------------------------------------------- 
// 
//  Purpose: 
//      Get the class ID associated with this message. 
// 
//  Returns: 
//      HRESULT             NOERROR always. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::GetClassID(LPCLSID pclsid) // Where to put the class ID. 
{ 
    ASSERT(m_cRef > 0); 
 
    // The form only plays with things of its own class ID, so 
    // this is easy; it's more complicated if code supports multiple 
    // classes, or can do "treat as" operations 
    if (pclsid) 
        *pclsid = m_clsid; 
 
    return NOERROR; 
} 
 
 
//$--FRM::IsDirty------------------------------------------------------------- 
// 
//  Purpose: 
//      Returns whether the object has changed since the last save 
// 
//  Returns: 
//      HRESULT             S_OK if dirty, S_FALSE if not dirty. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::IsDirty(void) 
{ 
    ASSERT(m_cRef > 0); 
     
    return m_fDirty ? NOERROR : ResultFromScode(S_FALSE); 
} 
 
 
//$--FRM::InitNew------------------------------------------------------------- 
// 
//  Purpose: 
//      Create a new message of our message class in the provided pmsg. 
// 
//  Returns: 
//      HRESULT             S_OK, or error value. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::InitNew(LPMAPIMESSAGESITE pmsite, 
             LPMESSAGE pmsg)            // Message to create the new form in. 
{ 
    HRESULT             hr              = NOERROR; 
    SPropValue          prop            = {0}; 
 
    ASSERT(m_cRef > 0); 
 
    // ----- Remember our pointers and such 
    hr = Remember(pmsite,pmsg); 
    if (FAILED(hr)) 
    { 
        return hr; 
    } 
 
    // ----- set our message class 
    prop.ulPropTag  = PR_MESSAGE_CLASS; 
    prop.Value.LPSZ = TEXT(kszFormsMessageName); 
    hr = m_pMessage->SetProps(1, &prop, NULL); 
    if (FAILED(hr) ) 
    { 
        return hr; 
    } 
 
    // ----- remind ourselves that this new message could not have been sent 
    m_fSentMessage = 0; 
    
    ADVISE(OnNewMessage); 
    return hr; 
} 
 
 
//$--FRM::Load---------------------------------------------------------------- 
// 
//  Purpose: 
//      Attaches our object to the provided pmsg. 
// 
//  Returns: 
//      HRESULT             S_OK, or error value. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::Load(LPMAPIMESSAGESITE pmsite, 
          LPMESSAGE pmsg,           // Our message to remember 
          ULONG ulMessageStatus, 
          ULONG ulMessageFlags) 
{ 
    ULONG cProps = 0; 
    const ULONG ctagMax = 10; 
    char rgchTaga[sizeof(SPropTagArray) + (ctagMax * sizeof(ULONG))] = {0}; 
    LPSPropTagArray ptaga = (LPSPropTagArray) rgchTaga; 
    LPSPropValue rgval = NULL; 
    LPSPropValue pval = NULL; 
    HRESULT         hr=S_OK; 
 
    ASSERT(m_cRef > 0); 
 
    // ----- Remember our pointers and such 
    hr = Remember(pmsite,pmsg); 
    if (FAILED(hr)) 
    { 
        return hr; 
    } 
 
    // ----- If this message has been sent we would like to remember that 
    m_fSentMessage = !( ulMessageFlags & MSGFLAG_UNSENT); 
    TRACE1("fSentMessage = %d",(int) m_fSentMessage); 
 
    ptaga->cValues = 0; 
    ptaga->aulPropTag[ptaga->cValues++] = PR_SUBJECT; 
    ptaga->aulPropTag[ptaga->cValues++] = PR_BODY; 
    ptaga->aulPropTag[ptaga->cValues++] = PR_FORMDATA;// Form Specific 
  
    hr = pmsg->GetProps(ptaga, 0, &cProps, &rgval); 
    if (FAILED(hr) ) 
    { 
        return hr; 
    } 
    ASSERT(ptaga->cValues <= ctagMax); 
    ASSERT(cProps == ptaga->cValues); 
    ASSERT(NULL != rgval); 
 
    // ----- set properties to variables 
 
    // point pval at form-specific data 
    pval = rgval + 2; 
 
    POSITION pos = theApp.m_pDocTemplate->GetFirstDocPosition(); 
    ASSERT (pos); 
 
    CToolDoc * pDoc = (CToolDoc*)theApp.m_pDocTemplate->GetNextDoc(pos); 
     
    POSITION posVW = pDoc->GetFirstViewPosition(); 
    ASSERT (posVW); 
 
    CToolForm * pView = (CToolForm*) pDoc->GetNextView (posVW); 
 
    if (NULL != pView) 
{ 
    if (pval->Value.bin.cb == sizeof(pDoc->m_theFormData))  // If the data is valid 
        { 
        memcpy(&(pDoc->m_theFormData), pval->Value.bin.lpb,(int) pval->Value.bin.cb); 
    pval++; // CALLERSNAME 
} 
 
pView->PutDataIntoWindow(); 
} 
 
    ASSERT(rgval); 
    (*lpfnMAPIFreeBuffer)(rgval); 
    ADVISE(OnNewMessage); 
 
    return hr; 
} 
 
 
//$--FRM::Save---------------------------------------------------------------- 
// 
//  Purpose: 
//      Writes out our information to the provided pmsg. Does NOT commit 
//      changes; this is the responsibility of the caller. Puts the form 
//      into no-scribble mode until SaveCompleted is called. 
// 
//  Returns: 
//      HRESULT             S_OK, or error value. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::Save( 
         LPMESSAGE pmsg,    // Message to write our changes to. 
         ULONG fSameAsLoad) // TRUE if this is our home message, FALSE if 
                            // this is a different message. 
{ 
    SPropValue prop = {0}; 
    HRESULT hr = NOERROR; 
 
    ASSERT(m_cRef > 0); 
    ASSERT(m_pMessage); 
 
    // ----- If this is the same pmsg as we got back when we loaded ... 
    if (fSameAsLoad) 
    { 
        pmsg = m_pMessage; 
    } 
 
    // ----- set our message class 
    prop.ulPropTag  = PR_MESSAGE_CLASS; 
    prop.Value.LPSZ = TEXT(kszFormsMessageName); 
    hr = m_pMessage->SetProps(1, &prop, NULL); 
    if (FAILED(hr) ) 
    { 
        return hr; 
    } 
 
    POSITION pos = theApp.m_pDocTemplate->GetFirstDocPosition(); 
    ASSERT (pos); 
 
    CToolDoc * pDoc = (CToolDoc*)theApp.m_pDocTemplate->GetNextDoc(pos); 
     
    if (NULL != pDoc) 
{ 
//This will set the Message body to a specific text value in the form. 
//This will be dependent on the specific form.  The intended use of this 
//is when a receiver or the form does not have access to the form, then 
//he/she will view a text version of the form data.  This is the text 
//version. 
prop.ulPropTag  = PR_BODY; 
prop.Value.lpszA = TEXT("Sorry, no text equivalent of tool form"); 
hr = m_pMessage->SetProps(1, &prop, NULL); 
if (FAILED(hr) ) 
{ 
    return hr; 
} 
 
prop.ulPropTag = PR_SUBJECT; 
prop.Value.LPSZ = TEXT(pDoc->m_theFormData.m_szTopic); 
 
hr = m_pMessage->SetProps(1, &prop, NULL); 
if (FAILED(hr)) 
{ 
   return hr; 
} 
 
    prop.ulPropTag  = PR_FORMDATA; 
    prop.Value.bin.lpb = (unsigned char *) &(pDoc->m_theFormData); 
    prop.Value.bin.cb  = sizeof(pDoc->m_theFormData); 
    hr = m_pMessage->SetProps(1, &prop, NULL); 
if (FAILED(hr)) 
{ 
        return hr; 
    } 
} 
    ADVISE(OnSaved); 
    return hr; 
} 
 
 
//$--FRM::SaveCompleted------------------------------------------------------- 
// 
//  Purpose: 
//      Terminates no-scribble and hands-off modes, returning the object 
//      to its normal storage mode. 
// 
//  Returns: 
//      HRESULT             S_OK, or error value. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::SaveCompleted(LPMESSAGE pmsg)  // Our new home message, if we need to change. 
{ 
    ASSERT(m_cRef > 0); 
 
    // Reset modes 
    m_fDirty = FALSE; 
 
    return NOERROR; 
} 
 
 
//$--FRM::HandsOffMessage----------------------------------------------------- 
// 
//  Purpose: 
//      Releases our reference on the message so that a Save As operation 
//      can occur. 
// 
//  Returns: 
//      HRESULT             S_OK, or error value. 
// --------------------------------------------------------------------------- 
STDMETHODIMP 
FRM::HandsOffMessage(void) 
{ 
    ASSERT(m_cRef > 0); 
    return NOERROR; 
}