MORE INFORMATION
The
following file is available for download from the Microsoft Download
Center:
For
additional information about how to download Microsoft Support files, click the
following article number to view the article in the Microsoft Knowledge Base:
119591 How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most
current virus-detection software that was available on the date that the file
was posted. The file is stored on security-enhanced servers that help to
prevent any unauthorized changes to the file.
NOTE: This archive contains subdirectories, be sure to use the -d
command line switch during extraction.
Below is a quick list of the
problems that required changes:
- Compiler Errors on
IViewObject::Draw()Compiler Errors
on OleUIAddVerbMenu()Compiler Errors
on OleStdGetObjectDescriptorFromOleObject()Compiler Errors on IDS_CLOSELinker Fails with CLASSLIB SampleCompiler Errors Referencing GETICON.HIncorrect Prototypes for LibMain() and WEP()Patron GP Faults During Activate AsPatron's Convert To FailsCLASSLIB String Allocations Fail with Some
CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Compiler Errors on
OleUIAddVerbMenu()Compiler Errors on
OleStdGetObjectDescriptorFromOleObject()Compiler Errors on IDS_CLOSELinker Fails with CLASSLIB SampleCompiler Errors Referencing GETICON.HIncorrect Prototypes for LibMain() and WEP()Patron GP Faults During Activate AsPatron's Convert To FailsCLASSLIB String Allocations Fail with Some
CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Compiler Errors on
OleStdGetObjectDescriptorFromOleObject()Compiler Errors on IDS_CLOSELinker Fails with CLASSLIB SampleCompiler Errors Referencing GETICON.HIncorrect Prototypes for LibMain() and WEP()Patron GP Faults During Activate AsPatron's Convert To FailsCLASSLIB String Allocations Fail with Some
CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Compiler Errors on
IDS_CLOSELinker Fails with CLASSLIB
SampleCompiler Errors Referencing
GETICON.HIncorrect Prototypes for
LibMain() and WEP()Patron GP Faults
During Activate AsPatron's Convert
To FailsCLASSLIB String Allocations
Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Linker Fails with CLASSLIB
SampleCompiler Errors Referencing
GETICON.HIncorrect Prototypes for
LibMain() and WEP()Patron GP Faults
During Activate AsPatron's Convert
To FailsCLASSLIB String Allocations
Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Compiler Errors Referencing
GETICON.HIncorrect Prototypes for
LibMain() and WEP()Patron GP Faults
During Activate AsPatron's Convert
To FailsCLASSLIB String Allocations
Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Incorrect Prototypes for
LibMain() and WEP()Patron GP Faults
During Activate AsPatron's Convert
To FailsCLASSLIB String Allocations
Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Patron GP Faults During
Activate AsPatron's Convert To
FailsCLASSLIB String Allocations
Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Patron's Convert To
FailsCLASSLIB String Allocations
Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- CLASSLIB String
Allocations Fail with Some CompilersCImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- CImpIPolyline::WriteToFile() Returns an Incorrect
ValueCImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- CImpIOleObject::GetClientSite() Returns an Incorrect
ValuePolyline Registers a Format
with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Polyline Registers a
Format with an Uninitialized StringDataTran Reference Counting ProblemComponent Cosmo Fails to Release Polyline
ObjectCosmo Fails to Load When Used
with HCosmo HandlerPatron Does Not
Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- DataTran Reference
Counting ProblemComponent Cosmo
Fails to Release Polyline ObjectCosmo Fails to Load When Used with HCosmo
HandlerPatron Does Not Work with
Some Printer DriversClassLib
Creates Table of Invalid String PointersErrors in Enumerator SamplesSamples GP Fault When Closing Iconized
Documents
- Component Cosmo Fails to
Release Polyline ObjectCosmo Fails
to Load When Used with HCosmo HandlerPatron Does Not Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Cosmo Fails to Load When
Used with HCosmo HandlerPatron Does
Not Work with Some Printer DriversClassLib Creates Table of Invalid String
PointersErrors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Patron Does Not Work with
Some Printer DriversClassLib
Creates Table of Invalid String PointersErrors in Enumerator SamplesSamples GP Fault When Closing Iconized
Documents
- ClassLib Creates Table of
Invalid String PointersErrors in
Enumerator SamplesSamples GP Fault
When Closing Iconized Documents
- Errors in Enumerator
SamplesSamples GP Fault When
Closing Iconized Documents
- Samples GP Fault When
Closing Iconized Documents
Updated Sample Code Available
The INOLE2 Download Center sample contains a complete source tree
for updated
Inside OLE 2 sample code. All of the changes described in this article have
already been made to the INOLE2 code.
The easiest way to update all
of the
Inside OLE 2 samples is to get a completely new source tree from INOLE2, and
then rebuild the samples from scratch under OLE 2.01. This article can then be
used as a reference, explaining what changes were made and why there were
necessary.
BOOKUI.DLL
If the original source code to the Inside OLE 2 samples is
updated according to this article, and the samples are then rebuilt to be
compatible with OLE 2.01, it will also be necessary to rebuild an OLE 2.01
version of the OLE2UI library for the samples to use. To do so, build a library
called BOOKUI.DLL according to the instructions in the OLE 2.01 SDK.
Use this new DLL to replace the INOLE2\BUILD\BOOKUI.DLL file included with the
book.
If the samples are rebuilt from the INOLE2 Download Center
sample, it is not necessary to manually rebuild BOOKUI.DLL, because INOLE2
already includes an updated version of BOOKUI.DLL.
1. Compiler Errors on IViewObject::Draw()
Problem:
The prototype for IViewObject::Draw() changed between
OLE 2.0 and OLE 2.01. In 2.0 the lprcBounds and lprcWBounds parameters were
prototyped as "const LPRECTL"; in 2.01 they are prototyped as "LPCRECTL". This
change causes the HCosmo (Chapter 11) and Polyline (Chapters 11 and 16) sample
applications to fail during compilation under 2.01.
Solution:
To correct this error, update all references to
IViewObject::Draw() in the Inside OLE 2 sample code by changing const LPRECTL
to LPCRECTL.
This change will be necessary in the following files:
interfac\iviewobj.cpp
interfac\iviewobj.h
chap11\hcosmo\hcosmo.h
chap11\hcosmo\iviewobj.cpp
chap11\polyline\iviewobj.cpp
chap11\polyline\polyline.h
chap16\polyline\iviewobj.cpp
chap16\polyline\polyline.h
2. Compiler Errors on OleUIAddVerbMenu()
Problem:
The prototype for OleUIAddVerbMenu() changed between
OLE 2.0 and OLE 2.01. The OLE2UI library version OLE 2.01 added an additional
parameter to OleUIAddVerbMenu(). This new parameter is an integer value called
"idVerbMax", and it indicates the largest number the container allows for a
verb menu item identifier. The idVerbMax parameter immediately follows the
idVerbMin parameter.
The Patron sample applications were written for
the OLE 2.0 version of the user interface library, which did not include this
new parameter. Consequently, these samples do not compile with the OLE 2.01
header files. This difference affects the versions of Patron found in Chapters
9, 12, 13, 14, and 15.
Solution:
To correct this problem, perform the following two
steps:
- Build an OLE 2.01 version of BOOKUI.DLL, as described in
problem 1 above.
- Update all calls to OleUIAddVerbMenu() in Patron by passing
"ID_VERBMAX" (already defined in RESOURCE.H) as the idVerbMax parameter. For
example, in the function CPage::FQueryObjectSelected(), change the following
OleUIAddVerbMenu(NULL, NULL, hMenu, MENUPOS_OBJECT
, IDM_VERBMIN, FALSE, 0, &hMenuTemp);
to read as follows:
OleUIAddVerbMenu(NULL, NULL, hMenu, MENUPOS_OBJECT
, IDM_VERBMIN, IDM_VERBMAX, FALSE, 0, &hMenuTemp);
This change will be necessary in the functions
CPage::FQueryObjectSelected() and CTenant::AddVerbMenu() in each of the
following files:
chap09\patron\page.cpp
chap09\patron\tenant.cpp
chap12\patron\page.cpp
chap12\patron\tenant.cpp
chap13\patron\page.cpp
chap13\patron\tenant.cpp
chap14\patron\page.cpp
chap14\patron\tenant.cpp
chap15\patron\page.cpp
chap15\patron\tenant.cpp
3. Compiler Errors on OleStdGetObjectDescriptorFromOleObject()
Problem:
The prototype for
OleStdGetObjectDescriptorFromOleObject() changed between OLE 2.0 and OLE 2.01.
Version 2.01 of the OLE2UI library added an additional parameter to
OleStdGetObjectDescriptorFromOleObject(). This new parameter, "lpSizelHim", is
an LPSIZEL value and points to a structure that indicates the dimensions of the
object. The lpSizelHim parameter was added to the end of the existing parameter
list.
The Patron sample applications were written for the OLE 2.0
version of the user interface library, which did not include this new
parameter. Consequently, these samples do not compile with the OLE 2.01 header
files. This difference affects the versions of Patron in Chapters 9, 12, 13,
14, and 15.
Solution:
To correct this problem, perform the following two
steps:
- Build an OLE 2.01 version of BOOKUI.DLL, as described in
problem 1 above.
- To quickly solve the problem, update all calls to
OleStdGetObjectDescriptorFromOleObject() in Patron by passing NULL as the
lpSizelHim parameter.
- For a more complete solution to the problem, first declare
a local variable: Then replace the code:
stm.hGlobal=OleStdGetObjectDescriptorDataFromOleObject
(m_pIOleObject, NULL, m_fe.dwAspect, ptl);
with the code:
SETSIZEL(szl, (10*(m_rcl.right-m_rcl.left))
, (10 * (m_rcl.bottom-m_rcl.top)));
stm.hGlobal=OleStdGetObjectDescriptorDataFromOleObject
(m_pIOleObject, NULL, m_fe.dwAspect, ptl, &szl);
This code correctly computes the size of the object and then stores
those extents into the object descriptor.
These changes will be
necessary in the function CTenant::CopyEmbeddedObject() in each of the
following files:
chap09\patron\tenant.cpp
chap12\patron\tenant.cpp
chap13\patron\tenant.cpp
chap14\patron\tenant.cpp
chap15\patron\tenant.cpp
These changes will also be necessary in the function
CTenant::CopyLinkedObject(), found in TENANT.CPP in Chapters 12, 13, 14, and
15.
4. Compiler Errors on IDS_CLOSE
Problem:
The OLE2UI.H header file shipped with OLE 2.01 defines
a symbol IDS_CLOSE. This symbol causes a conflict with a symbol of the same
name defined in the Cosmo samples.
This conflict affects the versions
of Cosmo in Chapters 10, 13, 14, and 16. The files affected are COSMO.RC and
RESOURCE.H.
Solution:
To correct the problem, rename IDS_CLOSE in RESOURCE.H
to IDS_CLOSE2, and change the single occurrence of IDS_CLOSE in COSMO.RC to
IDS_CLOSE2 in each chapter. These changes are necessary in the following files:
chap10\cosmo\cosmo.rc
chap10\cosmo\resource.h
chap13\cosmo\cosmo.rc
chap13\cosmo\resource.h
chap14\cosmo\cosmo.rc
chap14\cosmo\resource.h
chap16\cosmo\cosmo.rc
chap16\cosmo\resource.h
5. Linker Fails with CLASSLIB Sample
Problem:
There is an error in the FILES.LST file in the
CLASSLIB directory of the sample code. The first entry in this file,
"cstrtable.obj", is a valid long filename under Windows NT, but the file
created during compilation is actually "cstrtabl.obj" (no "e" on table). This
causes no problems with a 16-bit compiler, because the extra "e" is ignored.
However, it will cause an error with a 32-bit compiler.
Solution:
To solve the problem, remove the "e", thus changing
"cstrtable.obj" to "cstrtabl.obj".
6. Compiler Errors Referencing GETICON.H
Problem:
In OLE 2.0, container applications must include the
file GETICON.H, which is supplied with the OLE Software Development Kit (SDK)
version 2.0. In OLE 2.01, applications no longer need to include GETICON.H,
because the information in that file has been moved to other header files.
Because it is no longer needed, GETICON.H is not included with the OLE 2.01
SDK.
The Patron sample applications of Chapters 14 and 15 were
written for OLE 2.0, so they include GETICON.H. Because this file is no longer
available, these versions of Patron fail to compile with the OLE 2.01
SDK.
Solution:
To correct the problem, comment out or delete the line
"#include <geticon.h>" in TENANT.CPP. This change is necessary in the
following files:
chap14\patron\tenant.cpp
chap15\patron\tenant.cpp
7. Incorrect Prototypes for LibMain() and WEP()
Problem: The LibMain() and WEP() functions in all of the DLL samples are
prototyped incorrectly. These prototypes cause errors when using some compilers
(for example, Borland C++ 4.0); they do not cause problems with other compilers
(for example, Microsoft Visual C++ versions 1.0 and 1.5).
Solution:
The DLL samples in Inside OLE 2 implement the
LibMain() and WEP() functions as follows:
HANDLE FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg
, WORD cbHeapSize, LPSTR lpCmdLine)
{
...
return hInstance;
}
void FAR PASCAL WEP(int bSystemExit)
{
return;
}
To match the Windows SDK specifications, both of these functions should
return an int:
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg
, WORD cbHeapSize, LPSTR lpCmdLine)
{
...
return (int)hInstance;
}
int FAR PASCAL WEP(int bSystemExit)
{
return 0;
}
To solve this problem, make the changes above to all occurrences of
LibMain() and WEP() in the Inside OLE 2 sample code.
8. Patron GP Faults During Activate As
The Patron sample applications from Chapters 14 and 15 support
the OLE 2 Convert dialog box. Choosing Activate As from this dialog box
sometimes causes a GP fault.
Problem:
The problem lies in the way that the CTenant::Close()
function uses the fReopen flag. When Close() determines that there are no
references to the tenant IStorage, it normally resets the internal state of the
tenant to default values. As part of this process, it sets the member
m_pIStorage to NULL. However, if fReopen is TRUE, this assignment to NULL is
skipped.
This can lead to situations where m_pIStorage is non-NULL
but the storage itself has been destroyed. Thus m_pIStorage is an invalid
pointer, and trying to call through it causes a GP fault.
To correct
this problem, ensure that the m_pIStorage variable is set to NULL any time its
reference count is 0 (zero). This correction involves removing a condition in
the CTenant::Close() function, which is found in the Patron source file
TENANT.CPP.
Solution:
To correct this problem, edit the code to
CTenant::Close() as follows:
Where you see the lines
if (!fReopen)
m_pIStorage=NULL;
remove the "if" statement, leaving:
m_pIStorage=NULL;
The fReopen flag was used in an attempt to provide some optimization
when performing Activate As, but this flag is not necessary. The updated Inside
OLE 2 sample code referenced above has removed the flag entirely. This affects
the TENANT.CPP, TENANT.H, and PAGE.CPP source files of the PATRON samples in
Chapters 14 and 15.
9. Patron's Convert To Fails
The Patron sample applications from Chapters 14 and 15 support
the OLE 2 Convert dialog box. When Convert To is chosen from this dialog box,
PATRON fails to perform the conversion properly.
Problem:
The problem is that CPage::FConvertObject() releases
the page's IStorage pointer without committing it. Because Patron uses
transacted storage, this discards all changes, including the conversion that
just happened.
The code in error (listed on Page 817 of Inside OLE 2)
is as follows:
if ((CF_SELECTCONVERTTO & ct.dwFlags)
&& !IsEqualCLSID(ct.clsid, ct.clsidNew))
{
LPSTORAGE pIStorage;
//This should be the only close necessary.
m_pTenantCur->RectGet(&rcl, FALSE);
m_pTenantCur->StorageGet(&pIStorage);
m_pTenantCur->Close(FALSE, FALSE);
hr=OleStdDoConvert(pIStorage, ct.clsidNew);
pIStorage->Release();
This code does not commit the changes to the storage affected by
OleStdDoConvert before releasing pIStorage.
Solution:
To correct this problem, include a call to
pIStorage->Commit() before releasing the storage:
if ((CF_SELECTCONVERTTO & ct.dwFlags)
&& !IsEqualCLSID(ct.clsid, ct.clsidNew))
{
LPSTORAGE pIStorage;
//This should be the only close necessary.
m_pTenantCur->RectGet(&rcl, FALSE);
m_pTenantCur->StorageGet(&pIStorage);
m_pTenantCur->Close(FALSE, FALSE);
hr=OleStdDoConvert(pIStorage, ct.clsidNew);
pIStorage->Commit(STGC_ONLYIFCURRENT);
pIStorage->Release();
...
10. CLASSLIB String Allocations Fail with Some Compilers
The Inside OLE 2 sample code includes a CLASSLIB library.
Compiling the CStringTable class from this library may cause string space
allocation failures with some compilers.
Problem:
The problem is an uninitialized local variable
"cchUsed" in the function CStringTable::FInit(). This routine is found in the
CLASSLIB source file SCSTRTABL.CPP.
Solution:
Initialize cchUsed to zero, for example, change the
line
UINT cchUsed;
to read as follows:
UINT cchUsed=0;
11. CImpIPolyline::WriteToFile() Returns an Incorrect Value
The Polyline sample DLL in Chapter 4 contains a function,
CImpIPolyline::WriteToFile(), which returns an incorrect value.
Problem:
If WriteToFile()'s write operation succeeds, it should
return NOERROR. Instead, it returns POLYLINE_E_WRITEFAILURE.
Solution:
In the code for the CImpIPolyline::WriteToFile()
function, change the lines that read:
return (m_pObj->m_fDirty) ?
NOERROR : ResultFromScode(POLYLINE_E_WRITEFAILURE);
to read as follows:
return (!m_pObj->m_fDirty) ?
NOERROR : ResultFromScode(POLYLINE_E_WRITEFAILURE);
Make this change to the Chapter 4 version of Polyline.
CImpIPolyline::WriteToFile() is in the Polyline source file IPOLYLIN.CPP.
12. CImpIOleObject::GetClientSite() Returns an Incorrect Value
The Cosmo sample applications in Chapters 10, 13, 14 and 16
contain a function, CImpIOleObject::GetClientSite(), that returns an incorrect
value.
Problem:
When GetClientSite() encounters no errors, it should
return NOERROR. Instead, it returns E_NOTIMPL.
Solution:
In the code for CImpIOleObject::GetClientSite(),
change the line that reads:
return ResultFromScode(E_NOTIMPL);
to read as follows:
return NOERROR;
Make this change to the versions of Cosmo in Chapters 10, 13, 14 and
16. CImpIOleObject::GetClientSite() is in the Cosmo source file IOLEOBJ.CPP.
13. Polyline Registers a Format with an Uninitialized String
The Polyline sample DLLs in Chapters 5, 6, 11 and 16 attempt to
register a clipboard format using an uninitialized string. As a result, data
formats do not get properly transferred during clipboard, drag & drop, and
compound document operations.
Problem:
The offending line is:
m_cf=RegisterClipboardFormat(PSZ(IDS_STORAGEFORMAT));
At constructor time, the stringtable referenced by the PSZ macro (this
macro tries to access the member CPolyine::m_pST) has not been initialized, so
m_cf is not set properly.
Solution:
To correct the error, the line of code listed above
that initializes m_cf must be moved into the function CPolyline::FInit().
Specifically, move the line of code to occur after the code that initializes
the stringtable:
if (!m_pST->FInit(IDS_POLYLINEMIN, IDS_POLYLINEMAX))
return FALSE;
m_cf=RegisterClipboardFormat(PSZ(IDS_STORAGEFORMAT));
Make this one-line change to the versions of Polyline in Chapters 5,
11, and 16. CPolyline::FInit() is in the Polyline source file
POLYLINE.CPP.
Correcting this error in the Chapter 6 version of
Polyline requires an extra step. All lines initializing the FORMATETC arrays
m_rgfeGet[0] and m_rgfeSet[0] in which m_cf is stored must also be moved into
CPolyline::FInit(). The most convenient way to make this change is to simply
move all the FORMATETC initialization to the end of FInit(). Note that Polyline
does not use the FORMATETC arrays in Chapters 11 and 16, so this extra step is
not necessary in those chapters.
14. DataTran Reference Counting Problem
The DataTran data transfer object in Chapter 7 has a
reference-counting problem in the function CImpIDataObj::GetData(). As a
result, storage elements in the STGMEDIUM returned by GetData() may become
invalid while they are still in use.
Problem:
GetData() incorrectly fails to call AddRef() on any
IStorage or IStream pointer contained in the STGMEDIUM it returns.
Solution:
To correct this error, add the following lines of code
to GetData(), immediately after the line "*pSTM = pRen->stm;":
/*
* Must remember to AddRef any other objects
* in the STGMEDIUM: storages and streams.
*/
if (TYMED_ISTORAGE==pSTM->tymed)
pSTM->pstg->AddRef();
if (TYMED_ISTREAM==pSTM->tymed)
pSTM->pstm->AddRef();
GetData() is in the DataTran source file IDATAOBJ.CPP.
15. Component Cosmo Fails to Release Polyline Object
The Component Cosmo samples in Chapter 6, 7, 8, 11 and 16 fail to
fully clean up their allocations when closing a document. As a result, files
may not be saved completely and unused code is left in memory.
Problem:
In the function CCosmoDoc::~CCosmoDoc(), CoCosmo
obtains an IDataObject pointer on the Polyline object it maintains in the
document. It then fails to release this pointer, resulting in the problems
listed above.
Solution:
In the code for CCosmoDoc::~CCosmoDoc(), add a call to
IDataObject::Release().
Change the lines:
if (SUCCEEDED(hr))
pIDataObject->DUnadvise(m_dwConn);
to read as follows:
if (SUCCEEDED(hr))
{
pIDataObject->DUnadvise(m_dwConn);
pIDataObject->Release();
}
CCosmoDoc::~CCosmoDoc() is in the CoCosmo source file DOCUMENT.CPP.
16. Cosmo Fails to Load When Used with HCosmo Handler
The Cosmo sample applications in Chapter 10, 13, 14, or 16, when
they are being used in conjunction with the custom object handler HCosmo from
Chapter 11, fail to load and activate a Cosmo object. This problem occurs when
a container application is reloading a Cosmo object from a saved file, and also
when a container application is reactivating a Cosmo object after the object
has been first created and then deactivated.
Problem:
The problem actually lies in HCosmo. HCosmo
incorrectly keeps the object stream open in the object's IStorage. It does this
so that it can perform low-memory saves without having to reopen the
stream.
However, when a process has a stream open and that stream has
a particular IStorage as its parent, the OLE 2 implementation of STORAGE.DLL
does not allow the process to open the stream a second time from the same
parent IStorage. Therefore, when the Cosmo application receives the IStorage
pointer from HCosmo, and attempts to open the same object stream that HCosmo
already has open, the attempt to open the stream fails.
This problem
shows up in HCosmo's implementation of IOleObject::DoVerb(). HCosmo delegates
the DoVerb() call to the default handler, and the default handler attempts to
launch Cosmo. As described above, Cosmo cannot open the object stream, so it
returns an error of STG_E_READFAULT to the default handler, which in turn
returns STG_E_READFAULT to HCosmo.
As noted above, HCosmo keeps the
object stream open so that it can perform low-memory saves without having to
reopen the stream. However, this is not necessary. Because HCosmo never makes
changes to the object, it never has to save anything in a low-memory situation.
Specifically, it never has to save any changes to the storage when its
IPersistStorage::Save() is called with the fSameAsLoad flag set to TRUE.
Because this is the only case where an IPersistStorage implementation should
not attempt to allocate memory, it is totally unnecessary for HCosmo to cache
any pointers to the stream.
Solution:
To correct the problem, make the following five
changes to HCosmo's IPersistStorage implementation (HCosmo's implementation of
IPersistStorage is in the source file IPERSTOR.CPP):
- In CImpIPersistStorage::InitNew(), add the lines below
immediately before the call to WriteClassStg():
m_pObj->m_pIStream->Release();
m_pObj->m_pIStream=NULL;
- In CImpIPersistStorage::Load(), replace the line:
m_pObj->m_pIStream=pIStream;
with the following:
pIStream->Release();
m_pObj->m_pIStream=NULL;
- In CImpIPersistStorage::Save(), remove all the code inside
the "if (fSameAsLoad)" condition (it is unnecessary).
- In CImpIPersistStorage::SaveCompleted(), remove the lines
of code below that occur inside the "if (NULL!=pIStorage)" condition:
hr=pIStorage->OpenStream("CONTENTS", 0, STGM_DIRECT
| STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0
, &pIStream);
if (FAILED(hr))
return hr;
if (NULL!=m_pObj->m_pIStream)
m_pObj->m_pIStream->Release();
m_pObj->m_pIStream=pIStream;
- In CImpIPersistStorage::HandsOffStorage(), remove the
condition and body of code below:
if (NULL!=m_pObj->m_pIStream)
{
m_pObj->m_pIStream->Release();
m_pObj->m_pIStream=NULL;
}
The m_pIStream member of CFigure can then be eliminated
entirely, because it is no longer used in this IPersistStorage implementation.
17. Patron Does Not Work with Some Printer Drivers
The Patron sample applications do not work correctly with certain
printer drivers, including the standard PostScript driver.
One
symptom of failure is getting a blank document window when creating a new
Patron document; that is, no page image appears. Another symptom is getting a
GP fault in the printer driver when attempting to execute the Printer Setup
command from Patron's File menu.
Problem:
The problem is caused by the fact that Patron is not
sensitive to the variable length of the DEVMODE structure returned by the
printer driver. Patron normally obtains the DEVMODE data by calling the Windows
PrintDlg() API; it then copies that data to a private stream in its Compound
File. However, Patron only copies sizeof(DEVMODE) bytes, and therefore loses
any additional driver-specific information that might exist at the end of the
DEVMODE structure.
Some printer drivers, such as the Hewlett-Packard
(HP) LaserJet PCL drivers, use no extra information. Patron works correctly
with these drivers. Other drivers, such as the standard PostScript driver, use
extra information; with these drivers, Patron fails.
Solution:
To correct this problem, change the implementation of
Patron's CPages class so that it works with variable length DEVMODE structures,
and therefore with all printer drivers.
The changes are too extensive
to list in this article; as noted at the top of this article, an updated
version of the Inside OLE 2 sample code source tree is available on the
Microsoft Download Center. The following is a brief overview of the code that
needs to be changed to correct this problem:
The CPages class is
defined in the header file PAGES.H, and implemented in PAGES.CPP. The functions
that need to be updated are:
- CPages::DevmodeSet() and CPages::DevModeGet() in all
chapters
- CPages::ConfigureForDevice() in Chapters 2 and 5
- CPages::DevReadConfig() in all chapters other than 2 and
5
After these changes have been made, the new Patron will be
unable to read files generated by previous versions of Patron. There is no
automatic conversion facility provided in these samples. To convert a file from
the old Patron format to the new Patron format, follow these steps:
- Run an old version of Patron from Chapter 14.
- Run a new version of Patron from Chapter 15 (or, run the
old Chapter 15 Patron and the new Chapter 14 Patron).
- Load the old file into the old Patron.
- Transfer all objects from the old Patron to the new Patron,
using the clipboard or drag-and-drop method.
- Save the new document in the new Patron.
18. ClassLib Creates Table of Invalid String Pointers
The ClassLib sample framework implements a string table class
called CStringTable. In certain situations the implementation of this class can
create a table of invalid string pointers.
Problem:
The function CStringTable::FInit() allocates a block
of memory and loads strings from the application's resources into that memory.
It then initializes a table of far pointers into that memory, one pointer for
each string.
FInit() then reallocates the memory block, in order to
free up any unused space. This reallocation could move the memory block.
Because the far pointers in the pointer array point into the block that has
moved, they all become invalid.
Solution:
To avoid this problem, delete the following lines in
the CStringTable::FInit() function:
//Now reallocate the string memory to however much we used, plus 1
psz=(LPSTR)_frealloc(m_pszStrings, cchUsed+1);
if (NULL!=psz)
m_pszStrings=psz;
This solution wastes a little memory, but is simpler than trying to
recompute all the string pointers; ClassLib is intended to be a simple
example.
CStringTable::FInit() is in ClassLib's CSTRABL.CPP file.
19. Errors in Enumerator Samples
The enumerator samples in
Inside OLE 2 contain two errors. This section describes the errors and the
changes necessary to fix them. The changes are detailed for the IEnumRect
enumerator found in Chapter 3; similar changes are required in all enumerators
in the book's sample code.
Problem 1: If the first parameter to an enumerator's Next() function
(called "celt" in the OLE 2 documentation, "cRects" in the sample) is 1, it is
permissible for the last parameter (called "pceltFetched" in the documentation,
"pdwRects" in the sample) to be NULL. IEnumRect::Next() simply returns FALSE in
this case, which is incorrect.
Solution 1:
To correct this error, change the lines of code in
IEnumRect::New() that read:
if (NULL==pdwRects)
return FALSE;
*pdwRects=0L;
to read as follows:
if (NULL==pdwRects)
{
if (1L!=cRect)
return FALSE;
}
else
*pdwRects=0L;
Problem 2:
IEnumRect::Next() stores an incorrect value into the
out parameter pdwRects.
Solution 2:
To correct this error, change the line of code in
IEnumRect::New() that reads:
*pdwRects=(cRectReturn-cRect);
to read as follows:
if (NULL!=pdwRects)
*pdwRects=cRectReturn;
The same changes should be made to the IENUM.CPP files in the following
Inside OLE 2 sample code directories:
interface
chap03\enumc
chap03\enumcpp
chap06\polyline
chap06\ddataobj
chap06\edataobj
chap07\datatran
20. Samples GP Fault When Closing Iconized Documents
The sample applications may cause a GP fault when closing one or
more iconized documents.
Problem:
The CClient::QueryCloseAllDocuments() function (found
in the ClassLib source file CCLIENT.CPP) can cause this GP fault through
incorrect use of its local variable hPrevClose.
Solution:
To correct this problem, change the code to
CClient::QueryCloseAllDocuments() by adding the two lines below that read
"hPrevClose=NULL":
BOOL CClient::QueryCloseAllDocuments(BOOL fClose)
{
...
for ( ; hWndT; hWndT=GetWindow(hWndT, GW_HWNDNEXT))
{
if (NULL!=hPrevClose)
{
pDoc=(LPCDocument)SendMessage(hPrevClose
, DOCM_PDOCUMENT, 0, 0L);
CloseDocument(pDoc);
hPrevClose=NULL; // ADD THIS LINE
}
...
//Close the last window as necessary.
if (fClose && NULL!=hPrevClose)
{
pDoc=(LPCDocument)SendMessage(hPrevClose, DOCM_PDOCUMENT, 0, 0L);
CloseDocument(pDoc);
hPrevClose=NULL; // ADD THIS LINE
}
...