The information in this article applies to:
SUMMARY
The sample code for the book "Inside OLE 2," by Kraig Brockschmidt
(Microsoft Press) was originally written to be compatible with OLE 2.0.
This code has been updated to be compatible with OLE 2.01, and also to fix
some problems in the original code. This article describes the changes that
were made in updating the code.
remove the "if" statement, leaving:
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.
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:
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:
10. CLASSLIB String Allocations Fail with Some CompilersThe 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
to read as follows:
11. CImpIPolyline::WriteToFile() Returns an Incorrect ValueThe 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:
to read as follows:
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 ValueThe 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:
to read as follows:
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 StringThe 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:
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:
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 ProblemThe 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;":
GetData() is in the DataTran source file IDATAOBJ.CPP.
15. Component Cosmo Fails to Release Polyline ObjectThe 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:
to read as follows:
CCosmoDoc::~CCosmoDoc() is in the CoCosmo source file DOCUMENT.CPP.
16. Cosmo Fails to Load When Used with HCosmo HandlerThe 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):
17. Patron Does Not Work with Some Printer DriversThe 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 Software Library. 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:
18. ClassLib Creates Table of Invalid String PointersThe 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:
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 SamplesThe 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:
to read as follows:
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:
to read as follows:
The same changes should be made to the IENUM.CPP files in the following
"Inside OLE 2" sample code directories:
20. Samples GP Fault When Closing Iconized DocumentsThe 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":
MORE INFORMATIONThe following file is available for download from the Microsoft
Download Center. Click the file name below to download the file: Inole2.exeFor more information about how to download files from the Microsoft Download Center, please visit the Download Center at the following Web address http://www.microsoft.com/downloads/search.aspand then click How to use the Microsoft Download Center. 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:
Updated Sample Code AvailableThe 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.DLLIf 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 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:
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:
4. Compiler Errors on IDS_CLOSEProblem: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 5. Linker Fails with CLASSLIB SampleProblem: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.HProblem: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 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:
To match the Windows SDK specifications, both of these functions should
return an int:
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 AsAdditional query words: kbfile gpf gp-fault
Keywords : kbsample kbNTOS351 kbOLE200 kbGrpCom kbDSupport LeTwoOth |
Last Reviewed: December 7, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. |