Visual Basic Shell Programming by J. P. Hamilton Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. If you have any technical questions or error reports, you can send them to booktech@oreilly.com. (Please specify the printing date of your copy.) This page was updated July 17, 2002. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and comments from readers: [1] Example code; Hi all, When reading this great book I found a small (but very serious :)) error in it. This error can cause some menu function in IShellView.UIActivate's implemention not work exactly. In VbShell.odl file (and in VbShell.tbl too, of cause) some constant were declared like that: typedef enum { FCIDM_SHVIEWFIRST = 0x0000, FCIDM_SHVIEWLAST = 0x7fff, FCIDM_BROWSERFIRST = 0xa000, FCIDM_BROWSERLAST = 0xbf00, FCIDM_GLOBALFIRST = 0x8000, FCIDM_GLOBALLAST = 0x9fff, } FCIDM; //#define FCIDM_GLOBALLAST 0x9fff typedef enum { FCIDM_MENU_FILE = (0x9fff+0x0000), FCIDM_MENU_EDIT = (0x9fff+0x0040), FCIDM_MENU_VIEW = (0x9fff+0x0080), FCIDM_MENU_VIEW_SEP_OPTIONS = (0x9fff+0x0081), FCIDM_MENU_TOOLS = (0x9fff+0x00c0), FCIDM_MENU_TOOLS_SEP_GOTO = (0x9fff+0x00c1), FCIDM_MENU_HELP = (0x9fff+0x0100), FCIDM_MENU_FIND = (0x9fff+0x0140), FCIDM_MENU_EXPLORE = (0x9fff+0x0150), FCIDM_MENU_FAVORITES = (0x9fff+0x0170), } FCIDM_MENU; But in Micrisoft's SHLOBJ.H file these constant were declared as follow: #define FCIDM_SHVIEWFIRST 0x0000 #define FCIDM_SHVIEWLAST 0x7fff #define FCIDM_BROWSERFIRST 0xa000 #define FCIDM_BROWSERLAST 0xbf00 #define FCIDM_GLOBALFIRST 0x8000 #define FCIDM_GLOBALLAST 0x9fff // // Global submenu IDs and separator IDs // #define FCIDM_MENU_FILE (FCIDM_GLOBALFIRST+0x0000) #define FCIDM_MENU_EDIT (FCIDM_GLOBALFIRST+0x0040) #define FCIDM_MENU_VIEW (FCIDM_GLOBALFIRST+0x0080) #define FCIDM_MENU_VIEW_SEP_OPTIONS (FCIDM_GLOBALFIRST+0x0081) #define FCIDM_MENU_TOOLS (FCIDM_GLOBALFIRST+0x00c0) #define FCIDM_MENU_TOOLS_SEP_GOTO (FCIDM_GLOBALFIRST+0x00c1) #define FCIDM_MENU_HELP (FCIDM_GLOBALFIRST+0x0100) #define FCIDM_MENU_FIND (FCIDM_GLOBALFIRST+0x0140) #define FCIDM_MENU_EXPLORE (FCIDM_GLOBALFIRST+0x0150) #define FCIDM_MENU_FAVORITES (FCIDM_GLOBALFIRST+0x0170) 0x9fff is FCIDM_GLOBALLAST not FCIDM_GLOBALFIRST, so your must change 0x9fff by 0x8000 and run MAKETLB.BAT again to create new VbShell.tbl file. [1] 1; To all of those who are trying to get the shell examples to work under 2000 / XP without success I suggest having a look at http://www.domaindlx.com/e_morcillo/default.asp (If this is becomes a deed link try search the web for 'Edanmo's VB Page'). This excellent web site has examples that work under Windows ME and XP. (10) Sample code; I've just downloaded the sample code. It's a .zip file dated 8/16/00. I believe it has problems: "Chapter 02\ANIMALS.VBP" in Chapter 2 contains the following lines: class=animal; cow.cls class=cow; ..\cow.cls 1) The animal class should be contained in animal.cls, not cow.cls. 2) COW.CLS does not exist in ..\, rather it exists in .\ 3) The contents of COW.CLS is really the text for ANIMAL.CLS [10] Example 2-1; The Enum "Kingdoms" is declared as "Private" in Animal.cls. But the enum is used as a return type for the Kingdoms function. It mus t be made a "Public" enum. It is correctly declared as "Public" in the downloadable code. [10] Box about half way down; Quote: "This source code is from a class module, Animal.cls, that you should add to a standard VB EXE project named Animals. Set the Instancing property of the class to PublicNotCreatable" In my version of VB6, you can't have a public not creatable class module in a Standard EXE project. Moreover, the downloadable code has the type of project as an ActiveX DLL project. [11] The Web address given in the note on this page for the source code is very vague. "http://vb.oreilly.com," should be: http://examles.oreilly.com/vbshell (12) The first line of the second paragraph reads "The Animal and Cow interfaces are unique." But "Animal" is an interface, "Cow" is a class!! (24) Second paragraph; I believe I have found a bug on page 24, where you have this little code block: Private Sub GetTypeInfoCount() As Long GetTypeInfoCount = 1 End Sub Presumably this should be either Property or Function, not Sub, as I don't suppose too many people have had success returning a result to a Sub call. {25} figure 2-6 Animal Interface diagram; Figure 2-6 diagrams IUnknown sans "Release" (i.e. shows only QueryInterface and Addref). As far as I know, this error is not repeated elsewhere in the text. If a reader used this diagram to create an offset for the vtable swapping technique used throughout the book...boom! [34] 1st paragraph, second sentence; The second sentence of the first paragraph states "A stub project with the appropriate settings is included with the book's downloadable code for this chapter". This sentence is part of chapter 3, but there is no code for chapter 3. The second paragraph (next to the last paragraph) on page 34 also states "The source code that is provided with this chapter in the book's sample code serves as a template for future chapters". This sentence is also part of chapter 3, and there is no code for chapter 3. (35) 2nd Paragraph; The vb shell IDL file is shown here as "vbshell.idl", but is named "vbshell.odl" in downloadable source code examples. The file does match what is listed in Appendix A. [Chapter 4] Chapter 4; I downloaded the exaples file and tested them in Win2K. The example of Chapter 4 just don't work on my system, it register dll properly and then crashes the shell. {CH 4} Downloaded code datahandler.bas; Private Function GetBitmap(ByVal pDataObject As IDataObject, pmedium As STGMEDIUM) As Long ' GetPicture = DV_E_FORMATETC <*****Wrong*************** GetBitmap = DV_E_FORMATETC '< Corrected Dim dataObj As clsDataHandler Dim szType As String Dim lBitmap As Long Set dataObj = pDataObject 'Get Animal type szType = Space(255) GetPrivateProfileString "Animal", _ "Type", _ "Unknown", _ szType, _ Len(szType), _ dataObj.FileName szType = TrimNull(szType) Select Case UCase$(szType) Case "ARMADILLO" lBitmap = IDB_ARMADILLO Case "CAT" lBitmap = IDB_CAT Case "COW" lBitmap = IDB_COW Case "DOG" lBitmap = IDB_DOG Case "FISH" lBitmap = IDB_FISH Case Else Exit Function End Select pmedium.pData = LoadBitmap(App.hInstance, lBitmap) pmedium.TYMED = TYMED_GDI Set pmedium.pUnkForRelease = pDataObject Set dataObj = Nothing 'GetPicture = S_OK <********WRONG**************************** GetBitmap = S_OK '< Corrected End Function [40] 2nd paragraph and Figure 4-2; Under W2000, by default, Reged32, under the described key, doesn't show a "shell" sub-key (only a ShellEx) and so, none of the seven canonical verbs is displayable and none seems to be possibly added. Is there a special setting, a command line option to be applied to Reged32 to make those visible under W2000? Downloaded RadEx but not able to reproduce any effect as described in Ch4 (under W2000). (Nice application of interesting VB techniques, by the way). I assume W2000 is too different and the overall solution for Ch4 just don't work under that OS? [41] Figure 4-3; I altered the 'dllfile' registry entry as described starting on page 40 in the section "Static Context Menus." When I right-click on an icon that represents a DLL, I see neither the "Register" nor the "Unregister" items in the context menu. I "End"ed the explorer.exe process and restarted it but they still don't appear. I rebooted ... still don't appear. I'm using Windows 2000 Professional. Are there shell differences that aren't mentioned in the book? [57] 2nd paragraph; There may be errors compiling the .odl file. http://msdn.microsoft.com/ library/books/inole/S111F.HTM contains a listing of the errors you may encounter. If you get this: "Error generating type library: MKTYPLIB cannot preprocess the file." use this: mktyplib /nocpp vbshell.odl If you get a bar file or error then you need to ensure you have the mktyplib.exe on your machine and my advice is to copy it to the same directory as your batch file. [57] mktyplib line; "Fatal error M0006: unable to pre-process input file" using vs 6, sp4 on Microsoft ME. This, indeed, will be a serious problem UNLESS the user adds all of the appropriate Visual Studio directories to the user's PATH environment variable. For Visual Studio .NET 2003, run a .CMD file with the following line in it: SET PATH=%PATH%;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\Bin;C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE to fix this problem {58} Example 4-4; Not clear that reader should be creating 2 modules: handler.bas & clsContextMenu.cls. {58} Example 4-4; variable m_nFiles is declared as "Public", but in the downloadable code is declared as "Private". In the example should be declared as "Private". {58} Example 4-4; After the line: 'handler.bas should be Option Explicit for consistency with clsContextMenu.cls {60} 3rd paragraph (not counting paragraph in "Pointers" box); First sentence reads "The value of nFiles allows us...." should be "The value of m_nFiles allows us..." {61} Example 4-5; CopyMemory is not declared in the example as DragQueryFile and ReleaseStgMedium were declared in Example 4-4. [86] Last registry key listed (above sidebar); The last registry key shows that under the Shell Extensions\Approved key, a value of {61E9A1D1-5985-BB7C-444553540000} = "RAD file icon handler". Where does that GUID come from ? The RadEx.reg file has the following key in it: ... Shell Extensions\Approved "{B3213FAC-EB84-11D2-9FD9-00550076E06F}" = "RAD file icon handler". The GUID of B3213... is the CLSID of clsIconHandler.cls. {107} 1st paragraph; Erroneously claims that a function can't be called from a pointer in Visual Basic. [149] Listing of Private Function GetBitmap; At the beginning of this function: GetPicture = DV_E_FORMATETC At the end of ths function GetPicture = S_OK In both of these lines, should GetPicture be replaced with GetBitmap? Without this change RadEx.vbp will not compile. {206} The 7th line of Example 11-9 now reads: 'Query view for IShellFolder. Should read: 'Query view for IShellView. The shell wants a pointer to the object that implements the passed-in riid, the IShellView. (208) The first line of Example 11-11 indicates that this code goes in ShellFolder.cls. It actually goes in ShellView.cls. {223} The comment in the GetPidlType function (line 18) of Example 11-20 now reads: 'The "level" of the pidl is stored in bytes 3-6 Should read: 'The "type" of the pidl is stored in bytes 3-6 [223] Example 11-20, GetPidlType function; The function GetPidlType as a return type of PIDLTYPE. PIDLTYPE is defined as an Enum. Enums are Longs in VB. The variable pt is declared as an integer, which, as stated on the previous page, is 2 bytes long. The function reads 4 bytes in this 2 byte variable. pt should be declared as a Long. {231} 2nd, 3rd, 4th paragraph; The descriptions of the parameters for GetUIObjectOf are messed up. The 2nd paragraph starts "The third parameter, apidl", then goes on to describe the 4th parameter, which is a GUID. The 3rd paragraph then starts "the fourth parameter, prgfInOut". That is actually the 5th parameter. The 4th paragraph starts "the fifth parameter, ppvOut". That is actually the 6th parameter. So, there ends up being no actual description of the 3rd parameter. ?242? Sample code from DemoSpace.reg file; The last key in the sample .reg file gives the key path as ".../WindowsNT/ CurrentVersion/ShellExtensions/Approved". Is the "WindowsNT" portion of the key path correct? The other .reg files used a key path of "Windows/ CurrentVersion/ShellExtensions". [303] Project Sample for Chapter 14; I get the following error when compiling the sample project for Chapter 14. Compile Error: Procedure declaration does not match description of event or procedure having the same name. The following procedure header, found in the clsInetSpeak class, is responsible for the compilation error: Private Sub IOleCommandTarget_Exec( _ ByVal pguidCmdGroup As VBShellLib.LPGUID, _ ByVal nCmdID As VBShellLib.DWORD, _ ByVal nCmdExecOpt As VBShellLib.DWORD, _ ByVal pvaIn As VBShellLib.LPVARIANTARG, _ pvaOut As VBShellLib.LPVARIANTARG It should be: Private Sub IOleCommandTarget_Exec( _ ByVal pguidCmdGroup As VBShellLib.LPGUID, _ ByVal nCmdID As VBShellLib.DWORD, _ ByVal nCmdExecOpt As VBShellLib.DWORD, _ pvaIn As Variant, _ pvaOut As Variant) [311] 5th bolded section of code; The following produces 'Automation Error': Set m_pDockingWindowFrame = _ pServiceProvider.QueryService(VarPtr(clsidShellBrowser), _ VarPtr(clsidDockWndFrame)) If I skip this line of code the next error is: Object Variable type not set... m_pDockingWindowFrame.AddToolbar pDockWnd, ByVal StrPtr(szToolbar), 0 [325] All of Appendix A; I was unable to locate an electronic copy of the VBShell library. Is it possible that you could make one available? I am required on this project to provide detailed step-by-step instructions on how to re-create all non-standard libraries from source. (colophon) The animal on the book's cover is by all means a single cell organism and NOT a sea urchin. I first though it was a colony of reprsentatives of the "Actinozoa" class of the phylum "Actinopodea" that belong to the kingdom "Protozoa." But it also could be a single Globigerina foraminifer, which belongs to the "Globigerinidae" family of the "Foraminifera" order, of the "Granulareticulosea" class of the phylum "Rhizopoda" of "Protozoa." Tired yet? There is more... The "Protozoa" kingdom consists of single-cell eukaryotic (=with formed nucleus) organisms - few of them are actually visible with the bare eye. Globigerina foraminifer has a calcium carbonate exoskeleton with mastigia (=wheeps) of exoplasm penetrating the exoskeleton's microscopic holes. Chalk is actually a sedimentary rock made by fossilized "Foraminifera." The Actinozoa are quite like the former - except that they have a silicon oxide exoskeleton of a single spheric compartment. Their silicon exoskeleton allows them to live in great sea depths - where the calcium exoskeleton of the former would dissolve.