"Mistakes were made."
This page contains the author's errata for D.A.M.E, less typographical errors, transpositions, and the like.
Under certain rare circumstances, the version of Forward As Attachment released in the first edition of the book (fwdasatt version 0.1.2) theoretically can leave a hidden instance of the form running. This will prevent the Exchange client application from closing successfully.
This site contains the source to
version 0.2.2 of Forward As Attachment, which corrects this
flaw. Examine the functions CTargetMessage::CNoteFormWrapper::Resolve,
CTargetMessage::CNoteFormWrapper::Launch, and CTargetMessage::CNoteFormWrapper::~CNoteFormWrapper,
along with the member variable CTargetMessage::CNoteFormWrapper::_fLaunchedOk.
Any code path that fails to activate the created form
successfully explicitly calls IMAPIForm::ShutdownForm
on that form, forcing Exchange to destroy its invisible form.
As an added incentive to update, this version of the sample demonstrates creating an Exchange message-link attachment, per the format described in this unreleased appendix.
If you use my Widgets for Microsoft Exchange, note that any version of Forward As Attachment from 0.2.0 corrects this shortcoming.
The version of Stub Send Form released in the first edition of the book contain a flaw in the code that closes the form after the user issues the send command. The form notifies any registered view advise sinks held by the form that the form has successfully submitted the message; the owners of those advise sinks may then elect to release their reference to the form, theoretically allowing the form's reference count to drop to zero, and initiating a tear-down sequence. While this sequence is difficult to provoke in standard usage, if it strikes, it could cause the form server to crash when dereferencing an invalid pointer value, since it takes place in the middle of a loop through a set of view advise sink pointers.
In the module form.cpp of project sendstub,
emend the definition of function CStubSendForm::CmdSubmit,
preceding the call to _viewnotify.OnSubmitted() with
an internal AddRef(), and following it with a
matching Release(). The resulting sequence should
resemble this fragment:
HRESULT hr = _pmsgsite->SubmitMessage(0);
if (FAILED(hr))
{
_lasterr.Set(hr, _pmsgsite);
_pui->ErrorMessage((IPersistMessage*)this, hr, IDS_WHILE_SENDING);
}
AddRef();
if (SUCCEEDED(hr))
_viewnotify.OnSubmitted();
ShutdownForm(SAVEOPTS_NOSAVE);
Release();
If you want to deliver a more general solution in your own code, keep in mind that any notification could potentially cause the form's clients to release the references that keep the form alive and running.
(Note that the sendstub source contained on this site does not correct this flaw.)
The distributed implementations of the Stub Send Form and Post Form contain a reference leak in their response-form launching code.
In the module form.cpp of projects sendstub and
poststub, emend the definitions of CStubSendForm::DoVerb
and CStubPostForm::DoVerb: instead of following
successful calls to the HrResponseForm member
function by directly clearing the per-verb view context member _pvwctxPerVerb
and calling ShutdownForm, simply set a local flag. Following the
correct release of _pvwctxPerVerb later in the body
of the function, test the local flag and call ShutdownForm as
necessary. The resulting sequences should resemble this fragment:
...
BOOL fTearDown = FALSE; //$ NEW
if (iVerb >= 0)
{
switch (iVerb)
{
...
case EXCHIVERB_REPLYTOSENDER:
hr = HrRespondForm((HWND)hwndParent, prcPosRect);
if (SUCCEEDED(hr))
fTearDown = TRUE; //$ CHANGED
break;
...
}
}
// Restore original view context
if (NULL != _pvwctxPerVerb)
{
_pvwctxPerVerb->Release();
_pvwctxPerVerb = NULL;
}
if (fTearDown) //$ NEW
ShutdownForm(SAVEOPTS_NOSAVE); //$ NEW
...
(Note that the sendstub and poststub sources contained on this site do not correct this flaw.)
Chapter 3, page 115 claims that each database file backing an Exchange Server 4.0 Information Store has a size limit of 2Gb. This should read 16Gb.
The sample file Chap07\Msgopen\Work.cpp does not compile,
thanks to a parameter accidentally removed from a function call.
In the function SimpleMessageOpen in this file,
change the first call to OpenEntry to read as follows:
...
HRESULT hr = pfld->OpenEntry(cbeid, /* unconst */ (ENTRYID*)peid,
(LPIID)&IID_IMessage, MAPI_DEFERRED_ERRORS|MAPI_BEST_ACCESS,
&ulType, (IUnknown**)&pmsg);
...
The same error exists in the version printed at the bottom of p. 432.
As page xiv of D.A.M.E. states,
I developed the sample programs in this book
under version 4.0 of Microsoft Visual C++.
of the compiler.
They do not build successfully under version 5.0.
To fix this, edit the files assert.h and assert.cpp
in each directory,
removing the symbol _CRTAPI1
from the declaration and definition of AssertHelper.
Optionally, you may also remove the obsolete CODE
and DATA statements from each sample's .DEF file.
Last modified: 13 August 1998
Copyright 1997-1998, Ben Goetter. All rights reserved.