[VB6] Modern Shell Interface Type Library - oleexp.tlb-VBForums
Page 1 of 3 123 LastLast
Results 1 to 40 of 88

Thread: [VB6] Modern Shell Interface Type Library - oleexp.tlb

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    [VB6] Modern Shell Interface Type Library - oleexp.tlb

    OLEEXP : Modern Shell Interfaces
    Current Version: 4.3 (Released 11 Sep 2017)

    About Project


    oleexp is Edanmo's olelib, forked and expanded with more recent content that allows you to access features of the Windows shell that were introduced in Vista or later. It also contains many types and enums that are frequently used when interacting with the shell. It's a very strong foundation for any project.

    Back in the day, E. Morcillo released the very comprehensive interface library olelib.tlb (Edanmo's OLE interfaces & functions). It contained a massive number of interfaces, enums, structs, etc. But after a point it was no longer updated and thus doesn't have any interfaces from Windows Vista or Windows 7. So I set out to bring these interfaces to VB, and quickly realized that so much would have to be duplicated and would then be conflicting, that the only sensible way to approach this would be to fork and expand olelib, particularly since anyone using oleexp would almost certainly be using olelib.

    If an interface isn't included that you would like to use, let me know.

    Installation / Setup Notes


    Installing oleexp
    oleexp.tlb (and oleexmpimp.tlb/mimelib.tlb if you're using them) should be placed in a permanent, common folder all your projects can access. You can register it manually, but I've never had trouble with the registration VB6 performs when you add it for the first time.
    IMPORTANT: oleexp is a common file, and you should only have one copy installed. Do not place multiple copies in the folders of projects that use it. Also, it's a direct replacement for olelib; a project should not have both.

    Setting up oleexp in your project
    oleexp.tlb is added via Project->References. As with any typelib, a sample project may reference a different location, if so, update the location if the References window says it's 'MISSING:'
    oleexpimp.tlb and mimelib.tlb are only required if they're specifically used.
    Explicit declares can be changed via Replace; just replace "As olelib.vartype" (or oleexp3.vartype if upgrading 3.x) with "As oleexp.vartype".
    While some interfaces aren't available on XP (some Win7+), oleexp can still be used; errors only arise if you call an interface unavailable on the current OS.

    Sample Projects (40)


    NEW! [VB6] ucShellBrowse: A modern replacement for Drive/FileList w/ extensive features - A highly customizable UserControl for browsing the file system with all the modern shell features.
    First use: IColumnManager; dozens of others previously demonstrated.

    NEW! [VB6, Vista+] Enumerate, explore, and change all file associations - Use IQueryAssociations to get information about all registered file types.
    IQueryAssociations, IAssocHandler, IEnumAssocHandlers, IOpenControlPanel

    [VB6, Vista] List the Recycle Bin location(s) on a drive - Use folder class IDs to find the official folders.
    IPersist, IKnownFolderManager, IKnownFolder, IEnumShellItems, IShellItem

    [VB6] Dynamic Resize: Use a slider to change ListView icon/thumbnail size on the fly - Smooth and fast resizing without any quality loss.
    IImageList2, IShellItemImageFactory

    [VB6] Exclude file types from Open/Save Dialogs ('all except...'): IShellItemFilter - Instead of selecting which files to show, select which ones to hide.
    IShellItemFilter, IFileOpenDialog, IShellItem

    [VB6, Vista+] Finding and deleting invalid shortcuts with IShellLink and IShellItem Find and remove bad links with IShellLinkW and a new recursive file enumeration/search method using only IShellItem and IEnumShellItems.
    IShellLinkW, IPersistFile, IEnumShellItems, IShellItem, IFileOpenDialog

    [VB6, Vista+] Core Audio - Monitor for disabled/active, default, and property changes - Shows how to use IMMNotificationClient to be notified when audio hardware is added/removed, enabled/disabled, set as default, or had its properties change
    IMMDeviceEnumerator, IMMDevice, IMMNotificationClient, IPropertyStore

    [VB6, Vista+] Core Audio - Change the system default audio device - Uses an undocumented interface to change this much sought-after setting through code.
    IPolicyConfig, IMMDeviceEnumerator, IMMDeviceCollection, IMMDevice

    [VB6] SHBrowseForFolder - Custom filter for shown items: BFFM_IUNKNOWN/IFolderFilter - Shows what to do to actually implement a filter using that weird BFFM_IUNKNOWN message you've seen.
    IFolderFilter, IUnknown, IShellFolder, IShellItem

    [VB6, Vista+] Add the Windows Send To submenu to your popup menu - Uses shell interfaces to implement the Send To menu exactly as Explorer does.
    IShellItem, IShellItemImageFactory, IDataObject, IDropTarget, IEnumShellItems, IShellItemArray, IFileOpenDialog

    [VB6, Vista+] Direct access to the system-wide image thumbnail cache - Uses the LocalThumbnailCache object for advanced access.
    IThumbnailCache, ISharedBitmap, IThumbnailProvider, IShellItem

    [VB6, Vista+] Remember Open/Save state per-dialog instead of per-app (IFileDialog) - The .SetClientGuid method enables automatic saved states per-dialog.
    IFileDialog/IFileOpenDialog, IShellItem

    [VB6] Using IAutoComplete / IAutoComplete2 including autocomplete with custom lists - Shows using autocomplete and IEnumString with oleexp interfaces. Supports custom lists and multiple sources.
    IAutoComplete, IAutoComplete2, IAutoCompleteDropDown, IEnumString, IACList, IACList2, IObjMgr

    [VB6, Vista+] Advanced Thumbnail ListView: Icons, images, videos, framed small images Uses shell interfaces and GDI+ to make a top-tier thumbnail view that handles every type of file.
    IShellItemImageFactory, IExtractImage, IShellItem[2], IShellFolder, IShellIcon, IShellIconOverlay, IParentAndItem, IEnumShellItems, IImageList

    [VB6] Drag drop any format to other apps without custom IDataObject - Drag and drop CF_TEXT, CFSTR_PNG, and more without having to implement IDataObject. Now with sample project.
    IDataObject, IDragSourceHelper2

    [VB6] Register any control as a drop target that shows the Explorer drag image - With IDropTargetHelper, any XP+ app can now show the same drag image as any modern program.
    IDropTarget, IDropTargetHelper

    [VB6, Vista+] Core Audio Basics - Demonstrates the new Core Audio interfaces added in v3.6
    IMMDeviceEnumerator, IMMDeviceCollection, IMMDevice, IAudioEndpointVolume, IAudioEndpointVolumeCallback, ISimpleAudioVolume, IAudioSessionManager2, IAudioSessionControl, IAudioSessionControl2

    [VB6] Code Snippet: View shortcut path w/variables unexpanded: IShellLinkDataList, and
    [VB6] Code Snippet: Make your shortcuts request elevation with IShellLinkDataList - An introduction to the advanced flags and data blocks hidden behind IShellLink.
    IShellLink (IShellLinkW), IShellLinkDataList, IPersistFile

    [VB6] Code Snippet: Get file overlay (e.g. shortcut arrow), inc. customs like DropBox - There's way more to system icon overlays than shortcuts and shares, now you can easily find the other Windows ones and custom ones.
    IShellIconOverlay, IShellFolder

    [VB6] Get extended details about Explorer windows by getting their IFolderView - Get that interface and many more for highly detailed information about open Explorer windows and their items. Changing window settings and selections is also possible.
    IShellWindows, IFolderView, IFolderView2, IShellBrowser, IShellView, IEnumVARIANT, IShellItem, IDispatch

    [VB6, Vista+] List all file properties, locale/unit formatted, by modern PROPERTYKEY - Demonstrates use of the modern PROPERTYKEY/IPropertyStore system, with PROPVARIANT handling made simple. Update includes a new sample project attached displaying a ListView of properties and using IPropertySystem to create a property display management technique.
    See Also: A compact function to retrieve any property by name, which loads a property store directly by file name without IShellItem, and then displays a formatted string for anyone property name.
    IPropertyStore, IPropertyDescription, IPropertySystem, IShellItem2, IShellFolder2

    [VB6, Vista+] SHBrowseForFolder: Handling a choice of Libraries (or Library), Computer, or Network - Some objects aren't valid folders themselves, but contain valid folders, and the user probably expects those objects to be treated like any other parent folder. Shell interfaces to the rescue!
    IShellLibrary, IShellItem, IShellItemArray, IEnumShellItems

    [VB6] Easy image disp/edit; scale/rotate, show animated gifs, conv2JPG, +more; No GDI+/DLL - Shows off oleexp 3.1's new image interfaces, which make dealing with images and imagelists far easier. Scale, rotate, show animated GIFs, transcode to JPG/BMP, get image properties, resize an imagelist, all with mostly single-line calls.
    IShellImageData, IShellImageDataFactory, ITranscodeImage, IImageList, IImageList2, IShellItem, IFileOpenDialog, IShellItem, IShellItemArray, IEnumShellItems, IPersistFile, IExtractImage.

    [VB6] Code Snippet: Get/set/del file zone identifier (Run file from internet? source) - How does Explorer know to ask? Get the basics of Alternative Data Streams and see how to change this one extremely easily thanks to IZoneIdentifier and its coclass PersistentZoneIdentifier.
    IZoneIdentifier, IInternetSecurityManager

    [VB6] Basic unzip without 3rd party DLL or shell32- IStorage-based, and
    [VB6] Create a ZIP file without any DLL depends using IStorage and IDropTarget - Uses IStorage and IStream for basic zip functionality. Creating a Zip uses a neat trick with IDropTarget.
    IStorage, IStream, IEnumSTATSTG, IShellFolder, IDropTarget

    [Vista+] Code Snippet: Get and set the Rating (stars) of a file - Shows a practical example of using IShellItem/IPropertyStore to read/write properties with very few lines of code.
    IPropertyStore, IShellItem2

    [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handler - Don't limit your previews to just images anymore; documents, music, videos, PDFs, Powerpoint/Excel, and lots more have existing or available preview handlers you can access with IPreviewHandler.
    IPreviewHandler, IInitializeWithFile, IInitializeWithStream, IInitializeWithItem, IUnknown

    [VB6, Vista+] Code snippet: KnownFolders made easy with IKnownFolderManager - The KnownFolderManager coclass (a default implementation you can get with the New keyword) greatly simplifies all aspects of working with special folders, their locations, properties, names, and identifiers.
    IKnownFolderManager, IKnownFolder, IShellItem, IShellItemImageFactory

    [VB6, Vista+] Host Windows Explorer on your form: navigation tree and/or folder - Use IExplorerBrowser and INamespaceTreeControl as a simple way (they have default implementations-- you don't even need a ListView, the whole thing is automatically created right on your form) to add a full-fledged Explorer view to your form.
    IExplorerBrowser, IExplorerBrowserEvents, INamespaceTreeControl, INamespaceTreeControlEvents, IDataObject, IShellView, IShellItem

    [VB6] API File Drag from multiple paths w/o native OLE or dragsource, SHDoDragDrop - Create an IDataObject with SHCreateDataObject/SHCreateFileDataObject to initiate a drag operation with very low-level access to all elements of the drag operation. Later comments in the thread show the use of DragDropHelper coclass (IDragSourceHelper, IDragSourceHelper2).
    IDataObject, IDragSourceHelper2

    [VB6] Enhanced Tray Message w/ custom ToolTip icon and feedback, w/o ShellNotifyIcon - Uses the new IUserNotification2 interface (Vista+)
    IUserNotification2

    [VB6] List files by level from a folder in natural sorted order using INamespaceWalk - A unique way of listing files with it's own Windows-managed progress dialog.
    INamespaceWalk, INamespaceWalkCallback, IShellFolder

    [VB6] List/Execute File Handlers: IAssocHandler and IAssocHandlerInvoker (Vista+) - Get names, paths, and icons for all of a file type's handlers, and use it to show your own Open With menu.
    IAssocHandler, IAssocHandlerInvoker, IEnumAssocHandlers

    [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc) - Windows 7 allows you to add an overlay icon, turn the taskbar item into a progress bar, add buttons below the thumbnail, and more. See how to use the new ITaskbarList3 / 4 interface in VB with the TaskbarList object from oleexp.
    ITaskbarList4

    [VB6] Use IFileOperation to replace SHFileOperation for modern Copy/Move box/prompts - Also shows usage of IShellItem; now updated to show the Advise method in action- using a class module to implement an interface to get progress feedback.
    IFileOperation, IFileOperationProgressSink, IShellItem, IShellItemArray, IShellFolder

    [VB6] Using the new IFileDialog interface for customizable Open/Save (TLB, Vista+) - Has the benefit of allowing easy access to events from the dialog, as well as making it very easy to add your own controls.
    IFileDialog2, IFileDialogCustomize, IFileOpenDialog, IFileSaveDialog, IFileDialogEvents, IShellItem, IShellItemArray, IEnumShellItems

    [VB6] Working with Libraries (Win7+) - Uses the IShellLibrary interface to get all folders in a library, add more, get the default save location, get the icon, and even create a new library. Also shows the use of IEnumShellItems and IShellItemArray.
    IShellLibrary, IShellItem, IShellItemArray, IEnumShellItems

    ...more to come soon!

    Add-Ons




    mIID.bas (UPDATED with 4.3) - All IID_'s, usable directly without CLSIDFromString, e.g. SHCreateItemFromIDList(pidl, IID_IShellItem, psi). Strongly recommended for all oleexp projects.

    mPKEY.bas - All PROPERTYKEY's from propkey.h, directly usable.

    mCoreAudio.bas / mDirectShow.bas - IIDs and functions used exclusively by those particular features.


    Included in the ZIP
    oleexp43.zip
    • oleexp.tlb v4.3
    • oleexpimp.tlb - Expanded fork of olelib2.tlb, replaces olelib2.tlb; replace all 'olelib2.<type>' with 'oleexpimp.<type>'
    • All addon modules
    • Full changelog
    oleexp43-source.zip
    • Source for TLBs
    • Originals of modified olelib files
    • Compile shortcuts
    • mimelib.tlb - Original compiled against oleexp; won't work with it otherwise.

    Source distributed separately due to attachment size limits.
    Attached Files Attached Files
    Last edited by fafalone; Oct 8th, 2017 at 12:42 AM. Reason: New Sample

  2. #2

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    (continued from above due to post length limit)
    Upgrading From OLEEXP 3.x To Version 4.0+


    4.0 was a major version upgrade. Along with a large number of new additions, the TLB itself has changed and a few extra steps are needed. To upgrade existing projects from oleexp 3.x (oleexp3.tlb) to oleexp 4.x (oleexp.tlb):
    -The TLB has a new GUID- essentially a new typelib, with the original name of just oleexp.tlb restored. Remove the reference to oleexp3.tlb and add a new reference to oleexp.tlb.
    -Replace all instances of 'oleexp3.<type>' with 'oleexp.<type>. No existing items were modified, so it is safe to run a Replace All with oleexp3 replaced with oleexp
    -Last time I'll switch the name of the TLB! Couldn't stay with 3.x forever and just oleexp makes more sense.
    -oleexpimp.tlb and mimelib.tlb have been compiled against oleexp 4.2; these can simply be overwritten.
    -All sample projects have been updated to use oleexp.tlb 4.0 or newer, reference changed and oleexp3. replaced with oleexp.

    A large number of additions are geared towards writing highly modernized and sophisticated namespace extensions, there will be a major project along these lines in the future.

    Version History


    Note: Versions will becoming more slowly now that oleexp has matured, covering virtually all shell interfaces.

    (oleexp v4.3 - Released 11 Sep 2017)
    -Added interfaces IObjectWithFolderEnumMode, IApplicationDocumentLists, IFilterCondition, IItemFilter.
    -Added interface set IRelatedItem, IIdentityName, IDelegateItem, ICurrentItem, ITransferMediumItem, IUseToBrowseItem, IDisplayItem, IViewStateIdentityItem, and IPreviewItem
    -IContextMenu and IContextMenu2: .InvokeCommand has been changed to a Long, so that both CMINVOKECOMMANDINFO and CMINVOKECOMMANDINFOEX can be used. Use VarPtr(yourcommandinfovar) instead of just yourcommandinfovar.
    -Added all structs, enums, and APIs for Shell Change Notify functions. For flags, Unicode is default- SHCNF_PATH = SHCNFPATHW, SHCNF_PRINTER = SHCNF_PRINTERW.
    -(mIID) All IIDs for new interfaces.
    -(mIID) Added FreeKnownFolderDefinitionFields macro for IKnownFolder type
    -Bug fix: ITransferSource had the last 2 members truncated.
    -Bug fix (mIID): IContextMenu and IContextMenu2 were, unbelievably, not right. How this was overlooked I have no idea. Apologies.
    -Bug fix (mIID): IsEqualIID is now working; it wasn't aliased to IsEqualGUID.

    (oleexp v4.2 - Released 01 Mar 2017)
    -Added interfaces from NETCONLib/Netcon.idl. The existing Windows typelib was very incomplete and used types that would lead to automation errors.
    -Netcon set: IEnumNetConnection, INetConnection, INetConnectionManager, INetSharingManager, [...] See history.txt for full list.
    -Some interfaces with Windows implementations that are never or rarely implemented in VB now have members that are functions instead of subs so the HRESULT's are available. This change was made with IFileOperation, IShellLibrary, IShellLinkDataList, and IExplorerBrowser.
    -Added missing struct members to SHELLEXECUTEINFO that for some reason were in SHELLEXECUTEINFO2. The latter will remain for compatibility.
    -Added enums SE_ERR_x, ASSOCCLASS; structs ASSOCIATIONELEMENT
    -Added additional API declares
    -Added all structs, enums, and APIs for Shell_NotifyIcon
    -Added additional interface for coclass ProgressDialog, IOperationsProgressDialog
    -Added API SHGetSetSettings and related enum SSF_ constants and SHELLSTATE struct
    -Added FILE_FLAG_ values to FILE_ATTRIBUTES enum
    -(mIID) Updated with netcon interface IIDs

    (oleexp v4.11 - 29 Dec 2016)
    -Added interface IPolicyConfig/IPolicyConfigVista with coclass PolicyConfigClient/CPolicyConfigVistaClient; these are undocumented interfaces for managing audio devices. The former is for Windows 7 and higher,
    -(Bug fix) IShellItemFilter.GetItemEnumFlags changed from out to in,out so it can be used with Implements

    (oleexp v4.1 - 01 Dec 2016)
    -Added interfaces IFileSystemBindData and IFileSystemBindData2
    -Added interface IObjectWithFolderEnumMode and related enum FOLDER_ENUM_MODE
    -Added all known string parameters for IBindCtx as of Win10; e.g. STR_BIND_FOLDER_ENUM_MODE. See module BindCtxSTR to view them all.
    -Added enums ASSOC_FILTER and SHIL
    -Added a large number of shell32 APIs that are commonly used with the interfaces in oleexp. For a complete list, see the shell32 module in the Object Browser.
    -Added a few additional APIs to ole32, kernel32 and shlwapi modules as well.
    -(Bug fix) IThumbnailCache.GetThumbnailByID cannot pass user type byval, changed to ByRef. Verified working.
    -(Bug fix) IFolderFilter is primarily used with Implements, but had an out-only parameter. Changed to in,out.

    (oleexp v4.0 - 24 Nov 2016)
    -Added interfaces [...] See history.txt for full list.
    -Added coclass ApplicationAssociationRegistration for IApplicationAssociationRegistration
    -Added coclass ApplicationAssociationRegistrationUI for IApplicationAssociationRegistrationUI
    -Added COMDLG_FILTERSPEC struct (IFileOpenDialog/IFileSaveDialog)
    -Added SysCommands enum (SC_ values; SC_CLOSE, SC_MINIMIZE, etc)
    -FILEOPENDIALOGOPTIONS enum was missing FOS_SUPPORTSTREAMABLEITEMS
    -Bug fix: Some features listed as included in 3.8 weren't in the release posted.
    -(mIID) Added all IIDs for new interfaces
    -(mIID) Added all known other SID_ values

    Older version history can be found in the history.txt file included in the download.

    -------------
    Any and all feedback is welcome. Many thanks to E. Morcillo for the olelib foundation, all the olelib source is all his code.

    Notes


    Copyright/Redistribution
    OLEEXP is open and free. You may distribute the files however you want and release your own projects based on this work, including projects for the Code Bank here, even just about using a particular interface. If you compile a modified version, please use a different GUID and note that it's your own fork as I did with olelib-- but if it's a bugfix-type change you could also just let me know and I'll immediately update the master version here. Project provided as-is.

    File Size
    While oleexp is a large file, when you compile your exe it only takes what is used; the entire TLB isn't compiled into your file, only a few KB in most cases. The same goes for the addons- with mIID, only IIDs that are used get compiled in.

    Coclasses
    A coclass is provided when Windows provides a default implementation of the given interface, and allows instances to be created with the New keyword instead of the CLSID and CoCreateInstance API. For single-interface coclasses (all except DragDropHelper), you need only the name of the coclass: Dim psl As ShellLibrary : Set psl = New ShellLibrary. IShellLibrary, no longer appears anywhere- but it is still present and can be used normally, e.g. if you were using CoCreateInstance that will still work as-is.
    For coclasses with multiple members, you will need to create a specific interface. Only one of the interfaces disappears from view, but it too is still there. Dim pIDSH As IDragSourceHelper[2] : Set pIDSH = New DragDropHelper Dim pIDTH As IDropTargetHelper : Set pIDTH = New DragDropHelper

    Variable Conflicts
    With TLBs, it's possible to have multiple instances of a variable type. For example, if you also had one of the many oleguids.tlb added, you might have two IShellFolder types, so if you have Dim psf As IShellFolder, VB isn't sure which one you mean, and will assign it based on the order in Project->References. Even worse, the high-priority default VB references contain hidden versions of IUnknown and IDispatch, which would take precedence despite being hidden.
    To ensure that your variable is defined as the correct version, declare your variables explicitly:
    Dim pUnk As oleexp.IUnknown
    Dim psf As oleexp.IShellFolder

    and so on, for any interfaces that may be conflicting. It must always be done for IUnknown/IDispatch since they have built-in conflicts, but for other interfaces you should ensure there's not multiple TLBs with a duplicate.



    List of New Interfaces In OLEEXP (as of v4.2)
    IApplicationAssociationRegistration*; coclass ApplicationAssociationRegistration
    IApplicationAssociationRegistrationUI*; coclass ApplicationAssociationRegistrationUI
    IApplicationDestinations
    IApplicationDocumentLists; coclass ApplicationDocumentLists
    IAppPublisher*
    IAssocHandler
    IAssocHandlerInvoker
    IAutoCompleteDropDown
    IBrowserFrameOptions
    IColumnManager*
    ICommDlgBrowser*
    ICommDlgBrowser2*
    ICommDlgBrowser3*
    ICondition*
    ICondition2*
    IConditionFactory; coclass ConditionFactory*
    IConditionFactory2*
    IContextMenu3
    IContextMenuCB
    ICreateObject
    ICustomDestinationsList; coclass DestinationList*
    IDataObjectAsyncCapability‡
    IDefaultExtractIconInit
    IDelegateFolder
    IDragSourceHelperr; coclass DragDropHelper
    IDragSourceHelper2r; coclass DragDropHelper
    IDropTargetHelperr; coclass DragDropHelper
    IEnumAssocHandlers
    IEnumExplorerCommand
    IEnumFullIDList
    IEnumPublishedApps*
    IEnumResources*
    IEnumShellItems
    IExecuteCommand; coclasses ExecuteFolder, ExecuteUnknown, and AppShellVerbHandler
    IExecuteCommandHost
    IExplorerBrowser; coclass ExplorerBrowser
    IExplorerBrowserEvents
    IExplorerCommandProvider
    IExplorerCommandState
    IExplorerPaneVisibility*
    IFileDialog
    IFileDialog2
    IFileDialogControlEvents
    IFileDialogCustomize
    IFileDialogEvents
    IFileIsInUse
    IFileOpenDialog; coclass FileOpenDialog
    IFileOperation; coclass FileOperation
    IFileOperationProgressSink
    IFileSaveDialog; coclass FileSaveDialog
    IFileSystemBindData
    IFileSystemBindData2
    IFolderView2
    IFolderViewOptions
    IFolderViewSettings
    IHomeGroup; coclass HomeGroup
    IImageList; coclass ImageList***
    IImageList2
    IImageRecompress; coclass ImageRecompress
    IInitializeCommand
    IInitializeWithBindCtx
    IInitializeWithFile
    IInitializeWithItem
    IInitializeWithPropertyStore
    IInitializeWithStream
    IInitializeWithWindow
    IKnownFolder
    IKnownFolderManager; coclass KnownFolderManager
    IModalWindow
    INameSpaceTreeControl
    INameSpaceTreeControl2; coclass NamespaceTreeControl
    INameSpaceTreeControlAccessible
    INameSpaceTreeControlCustomDraw
    INameSpaceTreeControlDropHandler
    INameSpaceTreeControlEvents
    INameSpaceTreeControlFolderCapabilities
    INamespaceWalk
    INamespaceWalkCB
    INamespaceWalkCB2
    INewWindowManager
    IObjectArray
    IObjectCollection; coclass EnumerableObjectCollection*
    IObjectWithFolderEnumMode
    IObjectWithPropertyKey
    IObjMgr
    IOperationsProgressDialog
    IPreviewHandler
    IPreviewHandlerFrame*
    IPreviewHandlerVisuals
    IPreviousVersionsInfo; coclass PreviousVersions
    IProgressDialog
    IPropertyChange
    IPropertyChangeArray
    IPropertyDescription
    IPropertyDescription2
    IPropertyDescriptionList
    IPropertyDescriptionRelatedPropertyInfo
    IPropertyDescriptionSearchInfo
    IPropertyEnumType
    IPropertyEnumType2
    IPropertyEnumTypeList
    IPropertyStore
    IPropertyStoreCache
    IPropertyStoreCapabilities
    IPropertyStoreFactory
    IPropertySystem
    IPublishedApp*
    IPublishedApp2*
    IResolveShellLink
    IRichChunk*
    ISearchBoxInfo*
    ISearchFolderItemFactory; coclass SearchFolderItemFactory*
    ISharedBitmap
    IShellApp*
    IShellChangeNotify
    IShellFolderViewCB*
    IShellIconOverlay
    IShellIconOverlayIdentifier*
    IShellImageDataFactory; coclass ShellImageDataFactory
    IShellImageData
    IShellImageDataAbort*
    IShellItem
    IShellItem2
    IShellItemArray
    IShellItemFilter
    IShellItemImageFactory
    IShellItemResources
    IShellLibrary
    IShellLinkDataList
    IShellMenu*
    IShellMenuCallback*
    IShellWindows; coclass ShellWindows
    IStartMenuPinnedList
    IStreamAsync
    ISystemInformation; coclass SystemInformation
    ITaskbarList3
    ITaskbarList4; coclass TaskbarList
    IThumbnailCache; coclass LocalThumbnailCache
    IThumbnailHandlerFactory
    IThumbnailProvider
    IThumbnailSettings
    ITrackShellMenu; coclass TrackShellMenu
    ITranscodeImage; coclass ImageTranscode
    ITransferAdviseSink*
    ITransferDestination*
    ITransferSource*
    IUserNotification2; coclass UserNotification
    IUserNotificationCallback
    IVisualProperties*
    IZoneIdentifier; coclass PersistentZoneIdentifier
    Core Audio
    IActivateAudioInterfaceAsyncOperation
    IActivateAudioInterfaceCompletionHandler
    IAudioAutoGainControl
    IAudioBass
    IAudioCaptureClient
    IAudioChannelConfig
    IAudioClient
    IAudioClient2
    IAudioClient3
    IAudioClock
    IAudioClock2
    IAudioClockAdjustment
    IAudioEndpointFormatControl
    IAudioEndpointLastBufferControl
    IAudioEndpointOffloadStreamMeter
    IAudioEndpointOffloadStreamMute
    IAudioEndpointOffloadStreamVolume
    IAudioEndpointVolume
    IAudioEndpointVolumeCallback
    IAudioEndpointVolumeEx
    IAudioInputSelector
    IAudioLfxControl
    IAudioLoudness
    IAudioMeterInformation
    IAudioMidrange
    IAudioMute
    IAudioOutputSelector
    IAudioPeakMeter
    IAudioRenderClient
    IAudioSessionControl
    IAudioSessionControl2
    IAudioSessionEnumerator
    IAudioSessionEvents
    IAudioSessionManager
    IAudioSessionManager2
    IAudioSessionNotification
    IAudioStreamVolume
    IAudioSystemEffects
    IAudioSystemEffects2
    IAudioTreble
    IAudioVolumeDuckNotification
    IAudioVolumeLevel
    IChannelAudioVolume
    IConnector
    IControlChangeNotify
    IControlInterface
    IDeviceSpecificProperty
    IDeviceTopology
    IHardwareAudioEngineBase
    IKsControl
    IKsFormatSupport
    IKsJackContainerId
    IKsJackDescription
    IKsJackDescription2
    IKsJackSinkInformation
    IMMDevice
    IMMDeviceActivator
    IMMDeviceCollection
    IMMDeviceEnumerator
    IMMEndpoint
    IMMNotificationClient
    IPart
    IPartsList
    IPolicyConfig
    IPerChannelDbLevel
    ISimpleAudioVolume
    ISubunit
    DirectShow
    IAMAnalogVideoDecoder
    IAMAsyncReaderTimestampScaling
    IAMAudioInputMixer
    IAMAudioRendererStats
    IAMBufferNegotiation
    IAMCameraControl
    IAMCertifiedOutputProtection
    IAMChannelInfo
    IAMClockAdjust
    IAMClockSlave
    IAMCollection
    IAMCopyCaptureFileProgress
    IAMCrossbar
    IAMDecoderCaps
    IAMExtendedErrorInfo
    IAMExtendedSeeking
    IAMMediaContent
    IAMMediaContent2
    IAMNetShowConfig
    IAMNetShowExProps
    IAMNetShowPreroll
    IAMNetworkStatus
    IAMStats
    IBaseFilter
    IBasicAudio
    IBasicVideo
    IBasicVideo2
    ICaptureGraphBuilder
    ICaptureGraphBuilder2
    IDeferredCommand
    IEnumFilters
    IEnumMediaTypes
    IEnumPins
    IFileSinkFilter
    IFilterGraph
    IFilterInfo
    IGraphBuilder
    IMediaControl
    IMediaEvent
    IMediaEventEx
    IMediaFilter
    IMediaPosition
    IMediaTypeInfo
    IPin
    IPinInfo
    IQueueCommand
    IReferenceClock
    IRegFilterInfo
    IVideoWindow
    Portable Devices
    IEnumPortableDeviceConnectors**
    IEnumPortableDeviceObjectIDs
    IPortableDevice
    IPortableDeviceCapabilities
    IPortableDeviceConnector**
    IPortableDeviceContent
    IPortableDeviceContent2
    IPortableDeviceDispatchFactory
    IPortableDeviceEventCallback
    IPortableDeviceKeyCollection
    IPortableDeviceManager
    IPortableDeviceProperties
    IPortableDevicePropertiesBulkCallback
    IPortableDevicePropVariantCollection
    IPortableDeviceResources
    IPortableDeviceService
    IPortableDeviceServiceCapabilities
    IPortableDeviceServiceMethodCallback
    IPortableDeviceServiceMethods
    IPortableDeviceServiceOpenCallback
    IPortableDeviceValues
    IPortableDeviceValuesCollection
    Net Connections
    IEnumNetConnection
    IEnumNetSharingEveryConnection
    IEnumNetSharingPortMapping
    IEnumNetSharingPrivateConnection
    IEnumNetSharingPublicConnection
    INetConnection
    INetConnectionConnectUi
    INetConnectionManager, coclass ConnectionManager
    INetConnectionProps
    INetSharingConfiguration
    INetSharingEveryConnectionCollection
    INetSharingManager, coclass NetSharingManager
    INetSharingPortMapping
    INetSharingPortMappingCollection
    INetSharingPortMappingProps
    INetSharingPrivateConnectionCollection
    INetSharingPublicConnectionCollection
    * - Under development; may not bee 100% error free
    *** - Cannot be used with New keyword. IImageList can be created new (if you're making one from scratch instead of system IL) with ImageList_CoCreateInstance API.
    ‡ - IAsyncOperation was renamed to IDataObjectAsyncCapability. Changed some usage details.

    ** - Interface located in oleexpimp.tlb due to GUID conflict


    All related structures and enums are also included.
    Last edited by fafalone; Sep 11th, 2017 at 02:28 PM. Reason: Updated changelog

  3. #3
    Member
    Join Date
    Feb 2015
    Posts
    36

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Good work. Is it possible for you to recompile the TLB's in 64-bit version? I use VB6 but I also support both 32 and 64-bit Office VBA and it would be nice to use these with 64-bit Office. I don't have a version of Visual Studio that comes with a type library editor or compiler so I can't do it myself. Thanks.

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    MORE SECTIONS FROM ABOVE NEEDED TO BE MOVED DOWN; THIS POST IS PART OF THE MAIN PROJECT POST ALONG WITH #1 and #2.

    Interfaces Included From Original OLELIB
    IACList
    IACList2
    IActionProgress
    IActionProgressDialog
    IActiveDesktop
    IAddressBarParser; coclass AddressBarParser
    IAdviseSink
    IAuthenticate
    IAutoComplete
    IAutoComplete2
    IBindCtx
    IBindHost
    IBinding
    IBindProtocol
    IBindStatusCallback
    ICallAddRelease
    ICallGION
    ICallInvoke
    ICallQI
    ICategorizer; multiple coclasses‡
    ICategoryProvider
    ICatInformation
    ICatRegister
    ICDBurn; coclass CDBurn
    IClassFactory
    IClassFactory2
    IColumnProvider
    IConnectionPoint
    IConnectionPointContainer
    IContextMenu
    IContextMenu2
    IContinueCallback
    ICopyHookA
    ICopyHookW
    ICreateErrorInfo
    ICreateTypeInfo
    ICreateTypeInfo2
    ICreateTypeLib
    ICreateTypeLib2
    ICustomDoc
    IDataObject†
    IDeskBand
    IDispatch
    IDocHostShowUI
    IDocHostUIHandler
    IDocHostUIHandler2
    IDockingWindow
    IDockingWindowFrame
    IDockingWindowSite
    IDropSource
    IDropTarget
    IEmptyVolumeCache
    IEmptyVolumeCache2
    IEmptyVolumeCacheCallBack
    IEnumACString
    IEnumCATEGORYINFO
    IEnumConnectionPoints
    IEnumConnections
    IEnumExtraSearch
    IEnumFORMATETC
    IEnumGUID
    IEnumHLITEM
    IEnumIDList†
    IEnumMoniker
    IEnumOleDocumentViews
    IEnumOLEVERB
    IEnumSTATDATA
    IEnumSTATPROPSETSTG
    IEnumSTATPROPSTG
    IEnumSTATSTG
    IEnumSTATURL
    IEnumString
    IEnumUnknown
    IEnumVARIANT
    IErrorInfo
    IErrorLog
    IExtractIconA
    IExtractIconW
    IExtractImage
    IExtractImage2
    IFillLockBytes
    IFolderFilter
    IFolderFilterSite
    IFolderView
    IFolderViewHost; coclass FolderViewHost
    IHlink
    IHlinkBrowseContext
    IHlinkFrame
    IHlinkSite
    IHlinkTarget
    IHttpNegotiate
    IHWEventHandler
    IInputObject
    IInputObjectSite
    IInternetBindInfo
    IInternetHostSecurityManager
    IInternetPriority
    IInternetProtocol
    IInternetProtocolInfo
    IInternetProtocolRoot
    IInternetProtocolSink
    IInternetSecurityManager
    IInternetSecurityMgrSite
    IInternetSession
    IInternetZoneManager
    ILayoutStorage
    ILockBytes
    IMalloc
    IMarshal
    IMoniker
    INetCrawler; coclass NetCrawler
    INewShortcutHookA
    INewShortcutHookW
    IObjectSafety
    IObjectWithSite
    IOleCache
    IOleClientSite
    IOleCommandTarget
    IOleContainer
    IOleControl
    IOleControlSite
    IOleDocument
    IOleDocumentSite
    IOleDocumentView
    IOleInPlaceActiveObject
    IOleInPlaceFrame
    IOleInPlaceObject
    IOleInPlaceSite
    IOleInPlaceUIWindow
    IOleLink
    IOleObject
    IOleWindow
    IParseDisplayName
    IPerPropertyBrowsing
    IPersist
    IPersistFile; coclass ImageProperties
    IPersistFolder
    IPersistFolder2
    IPersistIDList
    IPersistMemory
    IPersistMoniker
    IPersistPropertyBag
    IPersistPropertyBag2
    IPersistStorage
    IPersistStream
    IPersistStreamInit
    IPrint
    IProfferService
    IProgressDialog
    IPropertyBag
    IPropertyBag2
    IPropertyNotifySink
    IPropertySetStorage
    IPropertyStorage
    IPropertyUI; coclass PropertiesUI
    IProvideClassInfo
    IPublishingWizard; coclass PublishingWizard
    IQueryAssociations
    IQueryCancelAutoPlay; coclass QueryCancelAutoPlay
    IQueryContinue
    IQueryInfo
    IRecordInfo
    IRichEditOle
    IRichEditOleCallback
    IRootStorage
    IRunningObjectTable
    ISearchContext
    ISequentialStream
    IServiceProvider
    IShellBrowser†
    IShellExecuteHookA
    IShellExecuteHookW
    IShellExtInit
    IShellFolder2†
    IShellFolder†
    IShellIcon
    IShellLinkA
    IShellLinkW; coclass ShellLinkW
    IShellPropSheetExt
    IShellView2†
    IShellView†
    ISpecifyPropertyPages
    IStorage
    IStream
    ISupportErrorInfo
    ITaskbarList
    ITaskbarList2
    ITextDocument
    ITextFont
    ITextPara
    ITextRange
    ITextSelection
    ITextStoryRanges
    ITypeComp
    ITypeInfo
    ITypeInfo2
    ITypeLib
    ITypeLib2
    IUniformResourceLocatorA
    IUniformResourceLocatorW
    IUnknown
    IUrlHistoryStg
    IUrlHistoryStg2
    IURLSearchHook
    IURLSearchHook2
    IUserEventTimer; coclass UserEventTimer
    IUserEventTimerCallback; coclass UserEventTimerCallback
    IUserNotification
    IViewObject
    IViewObject2
    IWebWizardExtension; coclass WebWizardHost
    IWindowForBindingUI
    IWinInetHttpInfo
    IWinInetInfo
    IWizardExtension
    IWizardSite
    † - Interface specification has been modified from the original version of olelib.

    More Notes


    Implements issues
    Most of the interfaces in this project are not meant to be implemented in class modules. Some of them are, and some of those expect data passed back. Anything given in the typelib as an HRESULT returning function is treated as a Sub in VB, making it impossible to pass a value either way. So to get those values, many things have been changed to LONG. This allows you to receive a value there, but VB does not allow anything other than an HRESULT when you're using Implements to create your own version. All interfaces where your own version is expected, at least in my project, are already all HRESULT's, but if one is not, you can either change it and compile it yourself, or let me know and I can make an Implements-compatible version. Only needing one version would be nice, but VB went out of it's way to break this: the second problem is that sometimes when you're implementing your own version of an interface, some functionality requires that data be returned by the function instead of in one of the arguments.
    To accomplish this, you'll need to swap the implementing sub in the library with a regular function. This is a little more complicated than it sounds.

    First, you need the swapping code (not written by me and reused so many places I can't find the appropriate original attribution):
    Code:
    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal ByteLen As Long)
    Public Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, ByRef lpflOldProtect As Long) As Long
    Public Const PAGE_EXECUTE_READWRITE As Long = &H40&
    
    Public Function SwapVtableEntry(pObj As Long, EntryNumber As Integer, ByVal lpfn As Long) As Long
    
        Dim lOldAddr As Long
        Dim lpVtableHead As Long
        Dim lpfnAddr As Long
        Dim lOldProtect As Long
    
        CopyMemory lpVtableHead, ByVal pObj, 4
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * 4
        CopyMemory lOldAddr, ByVal lpfnAddr, 4
    
        Call VirtualProtect(lpfnAddr, 4, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, 4
        Call VirtualProtect(lpfnAddr, 4, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function
    It's best to put that, and your new function, into a module, unless you're feeling really adventurous.
    To actually do the swap, this goes in the implementing class module:

    Code:
    Private m_pOldFunction As Long
    
    Private Sub Class_Initialize()
    Dim pVTable As ISomeInterface
    Set pVTable = Me
    m_pOldFunction = SwapVtableEntry(ObjPtr(pVTable), 4, AddressOf MyNewFunctionVB)
    End Sub
    
    Private Sub Class_Terminate()
    Dim pVTable As ISomeInterface
    Set pVTable = Me
    m_pOldFunction = SwapVtableEntry(ObjPtr(pVTable), 4, m_pOldFunction)
    End Sub
    The number 4 there, which is the EntryNumber argument, is critically important- it's the ordinal of the function you're replacing. This order is NOT alphabetical order, and not what order it's in in your class module, it's the order in the actual interface definition, and starts at 4 for interfaces that inherit directly from IUnknown, which contains the first 3. Refer to the .odl/.inc source files for the proper order.
    Now we're finally left with the new function itself, which now actually is a function that can return data!

    Code:
    Public Function MyNewFunctionVB(ByVal this As ISomeInterface, ByVal arg1 As Whatever, etc) As Long
    'Handling code here
    End Function
    Any code that was in ISomeInterface_MyNewFunction in the class module will not be executed, but the definition line must remain in place.

    The only bug is, and I've posted a discussion thread in the regular VB6 forum for ideas, is that if you run your program, then exit, and change the code in MyNewFunctionVB, then VB will crash next time the class module is created unless you exit and restart the IDE. Doesn't matter if you've swapped back and destroyed the objects, so for now just restart the IDE if you've run your program then later changed that function's code.

    Using QueryInterface

    The issue came up again for me today when I started using IShellItem2- one of the ways to get that interface by using .QueryInterface from an IShellItem object, which is actually from its parent IUnknown. Due to the way IUnknown was set up in this project, that function isn't visible on IShellItem or any other interface (they all inherit from IUnknown). They can be made visible by changing all the : stdole.IUnknown to just IUnknown, but I'm unsure of the consequences of such a change, and olelib is too massive to confirm there's no side effects.
    But fear not, if you need to access .QueryInterface, use the method in this routine that gets IShellItem2 from IShellItem

    Code:
    Dim psi As IShellItem
    Dim psi2 As IShellItem2
    Dim pUnk As oleexp.IUnknown 'should be explicitly typed since there's another hidden IUnknown in VB and it will cause errors
    
    Call SHCreateShellItem(0, 0, pidl, psi) 'pidl of whatever file/object you're working with, code omitted
    
    Set pUnk = psi
    pUnk.QueryInterface IID_IShellItem2, psi2
    And now you have a ready-to-go IShellItem2. This method is also used, for example, to get an IPropertyStore interface from an IShellLinkW.

    Related Projects


    Undocumented ListView
    The shell's ListView common control has a number of interfaces that expose some cool undocumented features. These interfaces are maintained as a separate typelib called lvundoc.tlb rather than included in oleexp.
    Download ListView Interfaces TypeLib: lvundocsrc.zip
    Includes lvundoc.tlb, source, and template classes for callbacks.

    Current Demos
    UPDATED [VB6, Vista+] Undocumented ListView feature: Footer items - As seen when searching from an Explorer folder, allows a group of buttons at the bottom of a ListView.
    Interfaces: IListViewFooter, IListViewFooterCallback

    [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB) - Allows you to show only a given number of rows per group, with a hyperlink at the bottom the user can click to show the rest.

    [VB6, Vista+] Undocumented ListView feature: Groups in Virtual Mode - Group View officially isn't compatible when the LVS_OWNERDATA style is set, but with a little work it's actually possible.
    Interfaces: IListView, IOwnerDataCallback

    Future Work
    Subitem controls are very complex but offer incredible features. The drive display in My Computer, the Ratings stars, combo boxes, links, subitem label editing... these are all exposed through subitem controls. The type library includes the required interfaces and one closed-source VB project has succeeded, so I will figure it out at some point in the future. In the mean time, the TLB is set up to get started if you want to pursue it on your own.

    Common Controls 6.0/6.1 Definitions TLB
    Download Common Controls TypeLib: tl_comctl6.zip
    Includes CommCtrl.tlb, source, and template classes for ListView interfaces.

    Decided to give my favorite typelib author's CommCtrl.tlb an upgrade as well. In addition to upgrading what was in there for the latest Common Controls version:
    -Added the parts of the included controls that were defined in winuser.h. It made no sense to only include a small portion of the control definitions just because some defs were in another header.
    -The definitions for the ListView control include everything from lvundoc.tlb, including all undocumented messages and interfaces. If you're using this typelib, you do not need to also have lvundoc.

  5. #5

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    @MountainMan:

    I'll try but it looks like a nightmare. midl.exe is complaining about errors in oaidl.idl, which isn't part of the project, which couldn't be found until I copied it into my source folder despite running vcvarsall.bat, and comes straight from the SDK so why on earth would it have errors anyway?

    Code:
    C:\vb6\tl_ole\source>C:\PROGRA~2\MIA713~1\\Windows\v7.0A\Bin\midl.exe /nologo /e
    nv win64 /nocpp /tlb "olelib64.odl" olelib.odl
    64 bit Processing .\olelib.odl
    64 bit Processing .\oaidl.idl
    oaidl.idl(26) : error MIDL2025 : syntax error : expecting an interface name or D
    ispatchInterfaceName or CoclassName or ModuleName or LibraryName or ContractName
     or a type specification near "ifndef"
    oaidl.idl(27) : error MIDL2026 : cannot recover from earlier syntax errors; abor
    ting compilation
    I got the paths problems fixed but the big issue now is the MIDL2003 redefinition problem. It gives that error whenever you define something that's already defined in Windows. Which is everything. If anyone has dealt with this before, let me know.

    Edit: What changes to the code itself would need to be made (what is the problem encountered when trying to use it in 64bit Office), assuming I can overcome the redefinition issue which might not be possible as every solution I've encountered says it's by design and to rename things.

    Edit: So I installed 64-bit office, and definitely need more info about what part of the typlibs won't work. Note that olelib includes API calls, but I've had problems with these everywhere and strongly suggest always using your own declares in a module.
    This is what I tried, and it worked fine with the current versions. Note that IShellItem.GetDisplayname returns a pointer, but VBA doesn't know that thus the LongPtr type isn't needed. If you needed it down the road, there apparently is a CLngPtr() function built in.

    Code:
    Private Sub CommandButton1_Click()
    Dim pidl As Long
    Dim sp As String
    Dim psi As IShellItem
    Dim sb As String
    Dim pstr As Long
    
    sp = "C:\temp\tracks.jpg"
    pidl = ILCreateFromPathW(StrPtr(sp))
    
    'Both of these methods work
    'Call SHCreateShellItem(0&, 0&, pidl, psi)
    Call SHCreateItemFromIDList(pidl, IID_IShellItem, psi)
    
    psi.GetDisplayName SIGDN_FILESYSPATH, pstr
    MsgBox BStrFromLPWStr(pstr)
    
    Call ILFree(pidl)
    
    End Sub
    
    'module
    Public Declare PtrSafe Function SHCreateShellItem Lib "shell32" (ByVal pidlParent As Long, ByVal psfParent As Long, ByVal pidl As Long, ppsi As IShellItem) As Long
    Public Declare PtrSafe Function SHCreateItemFromIDList Lib "shell32" (ByVal pidl As Long, riid As UUID, ppv As Any) As Long
    Public Declare PtrSafe Function SHCreateShellItemArrayFromIDLists Lib "shell32" (ByVal cidl As Long, ByVal rgpidl As Long, ppsiItemArray As IShellItemArray) As Long
    Public Declare PtrSafe Function ILCreateFromPathW Lib "shell32" (ByVal pwszPath As LongPtr) As Long
    Public Declare PtrSafe Sub ILFree Lib "shell32" (ByVal pidl As Long)
    Public Declare PtrSafe Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As LongPtr, Optional ByVal pszStrPtr As Long) As Long
    Public Declare PtrSafe Sub CoTaskMemFree Lib "ole32.dll" (ByVal pv As Long) 
    
    Public Function BStrFromLPWStr(lpWStr As Long, Optional ByVal CleanupLPWStr As Boolean = True) As String
    SysReAllocString VarPtr(BStrFromLPWStr), lpWStr
    If CleanupLPWStr Then CoTaskMemFree lpWStr
    End Function
    
    
    Public Function IID_IShellItem() As UUID
    Static IID As UUID
    If (IID.Data1 = 0) Then Call DEFINE_UUID(IID, &H43826D1E, CInt(&HE718), CInt(&H42EE), &HBC, &H55, &HA1, &HE2, &H61, &HC3, &H7B, &HFE)
    IID_IShellItem = IID
    End Function
    Public Sub DEFINE_UUID(Name As UUID, l As Long, w1 As Integer, w2 As Integer, B0 As Byte, b1 As Byte, b2 As Byte, B3 As Byte, b4 As Byte, b5 As Byte, b6 As Byte, b7 As Byte)
      With Name
        .Data1 = l
        .Data2 = w1
        .Data3 = w2
        .Data4(0) = B0
        .Data4(1) = b1
        .Data4(2) = b2
        .Data4(3) = B3
        .Data4(4) = b4
        .Data4(5) = b5
        .Data4(6) = b6
        .Data4(7) = b7
      End With
    End Sub

  6. #6
    New Member
    Join Date
    Jan 2009
    Posts
    10

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Hallo there,
    I'm trying to use IFileDialog.
    I added a custom button as shown bellow:
    fdc.AddPushButton 1001, "Abandon"
    fdc.MakeProminent 1001 'Moves to by the open button; only checkboxes, buttons, combos, menus can be made prominent
    and I catch the click on it using the FD_ButtonClick event.
    Everything perfect so far. But when the user clicks it I need to return to the calling Form. How is it done? How do I quit the Dialog box just if the user clicked on Cancel button?

    Another question: is it possible to place the Dialog box in the position on the screen I desire?

    Appreciate your reply
    Slobodan Dijaković
    Casa Bustelli
    6864 Arzo
    Switzerland

  7. #7

  8. #8

  9. #9
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    550

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by fafalone View Post
    Major project update to 2.0. Many new interfaces, sample projects, and bugfixes.
    Switching from Edanmo's olelib.tlb to this version, generates 'method or data member not found' error, when using IDataObject.GetData call.

    olelib.tlb {3181A65A-CC39-4CDE-A4DF-2E889E6F1AF1}

    Code causing error.

    Code:
    Dim m_oSource As IDataObject
    Dim tFMT As FORMATETC
    Dim tSTGM As STGMEDIUM
    
     If m_oSource.GetData(tFMT, tSTGM) = S_OK Then
    Doublechecked referenced version and it's from oleexp 2.0RC.zip package.
    Reference=*\G{3181A65A-CC39-4CDE-A4DF-2E889E6F1AF1}#1.5e#0#olelib.tlb#Edanmo's OLE interfaces & functions v1.94 (modified for oleexp)

    Any idea what might cause this?
    Last edited by Tech99; Aug 3rd, 2015 at 07:18 AM.

  10. #10
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    550

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by Tech99 View Post
    Switching from Edanmo's olelib.tlb to this version, generates 'method or data member not found' error, when using IDataObject.GetData call.

    olelib.tlb {3181A65A-CC39-4CDE-A4DF-2E889E6F1AF1}

    Code causing error.

    Code:
    Dim m_oSource As IDataObject
    Dim tFMT As FORMATETC
    Dim tSTGM As STGMEDIUM
    
     If m_oSource.GetData(tFMT, tSTGM) = S_OK Then
    Doublechecked referenced version and it's from oleexp 2.0RC.zip package.
    Reference=*\G{3181A65A-CC39-4CDE-A4DF-2E889E6F1AF1}#1.5e#0#olelib.tlb#Edanmo's OLE interfaces & functions v1.94 (modified for oleexp)

    Any idea what might cause this?
    Edit... variable declaration from integer to long seemed to resolve this.
    Code:
    Private CF_FILECONTENTS As Long 'Integer

  11. #11
    Fanatic Member
    Join Date
    May 2014
    Location
    Preveza Greece
    Posts
    862

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Μaybe mktyplib is better than MIDL2003..I have problem too with Edanmo Idispatch.tlb. I describe the solution here http://www.vbforums.com/showthread.p...an-handle-Word.
    GetIDsOfNames need an array of strings so a Long* (for pointer) and original Idispatch.tlb from Edanmo has LPSTR*
    So maybe there are more problems with that olelib.

    My question is...Can we use IFileDialog Like I use Word.Application? Can I later bind an object from IFileDialog?

  12. #12

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by Tech99 View Post
    Edit... variable declaration from integer to long seemed to resolve this.
    Code:
    Private CF_FILECONTENTS As Long 'Integer
    Yeah that's mentioned in the release notes up top... it was changed because of its use with clipboard formats- and RegisterClipbaordFormat was returning larger values than the (signed) Integer type could hold, so it was changed to a Long. Every change the potentially breaks code is documented, and I'm very careful to only do it when absolutely necessary.

  13. #13

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by georgekar View Post
    Μaybe mktyplib is better than MIDL2003..I have problem too with Edanmo Idispatch.tlb. I describe the solution here http://www.vbforums.com/showthread.p...an-handle-Word.
    GetIDsOfNames need an array of strings so a Long* (for pointer) and original Idispatch.tlb from Edanmo has LPSTR*
    So maybe there are more problems with that olelib.

    My question is...Can we use IFileDialog Like I use Word.Application? Can I later bind an object from IFileDialog?
    If you're talking about passing an array TO a typelib member, it's fairly straightforward, you just change the typelib to expect a LONG and pass a pointer to the first member. If you meant receiving an array... that's a bit more complicated.

    As for late-binding, I haven't really tried it. I'd imagine you probably could with objects that have default implementations like FileOpenDialog, but probably not normal interfaces, though I haven't tried. Why would you really want to?

  14. #14
    Fanatic Member
    Join Date
    May 2014
    Location
    Preveza Greece
    Posts
    862

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    GetIDsOfNames now return an array of long values. As you can see I place an long array to pass names of function in first place and named arguments in other places, and I can get the number of function and the relative numbers of named arguments. I use that in M2000 interpreter.

  15. #15

  16. #16
    Fanatic Member
    Join Date
    May 2014
    Location
    Preveza Greece
    Posts
    862

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    This is a part of mdlIDispatch.cls you can find in the code in M2000 source in sign.
    Code:
            long _stdcall GetIDsOfNames(
                            [in] IID* riid, 
                            [in] long* rgszNames,                previous LPSTR* rgszNames,
                            [in] long cNames, 
                            [in] long lcid, 
                            [in, out] long* rgDispId);
    GetIDsOfNames expected pointers and i do the right think...Why there is a cNames? because from pointers there is no way to know how many items in the array used. So I pass the first item of an array as myptr(0). Inside that array I just put pointers to actual strings. I do a redim to varDISPID so after call I get in first place the number of function and on other places the numbers of relative parameter. The good news is that this method works..
    I make the routine to work with mixed types, some named arguments and some in right place, and for working properly in M2000 language you have to place named arguments as the last arguments.
    This is a line of the example as I post in the link above:
    try ok_doc { method doc, "add", "", DocumentType:=WdNewWebPage as doc1 }
    I call add on object doc (is word.application.documents) and i pass an empty string for the first parameter and a documenttype and I get an object the Document object.
    No any special copymemory done..GetIDsOfNames only read the strings (no conversion needed) and put in the provided array the results.

    With old typelib we have this LPSTR* rgszNames, so we place a string and the system place a pointer to one string, so it works but only for the ProcName not for named arguments. Before I found the solution I think to pass a safearray, but it isn't like this, it is more simple.

    Code:
       ReDim myptr(0 To fixnamearg)
                myptr(0) = StrPtr(pstrProcName)    ' this is the method to call
                For lngLoop = 1 To fixnamearg
                myptr(lngLoop) = StrPtr(pargs2(lngLoop))   'these are the names
                Next lngLoop
                    ReDim varDISPID(0 To fixnamearg)
                lngRet = IDsp.GetIDsOfNames(rIid, myptr(0), fixnamearg + 1, cLid, varDISPID(0))
     DISPID = varDISPID(0)

  17. #17

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    varDISPID() is then filled correctly, so varDISPID(1, 2...etc) would have the correct values?

    cNames is the count of items in the array being passed... why wouldn't you know this value? It's just UBound(myptr) + 1 in the code in your post.

  18. #18

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    On an unrelated note, I've been seriously considering combining olelib and oleexp, such that there's only a single file. So it would be more of a fork of olelib rather than an expansion. Of course all credits for the original would remain. Any objections to this?

  19. #19
    Fanatic Member
    Join Date
    May 2014
    Location
    Preveza Greece
    Posts
    862

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Sorry my English is poor. I know the size of input array. The output array has the same size. The problem for function is that these are not arrays like safe arrays where we found fields that describe the dimension and the size of it. We place the first address and in a variable the length as long items. So cNames is a size both for input and output array. Each array has a long for item, but in first array that long is a pointer to bstr. StrPtr return address of Bstr.
    In old version in typelib we can only provide a string after a convertion to unicode....because vb treat string as ansi, so do a reverse conversion and then put a long as pointer to bstr. There is no way to pass more strings in an array form. So I suspect from cNames that only a buffer of longs passed. Maybe a predefined big buffer can be used for any call to this function.

  20. #20
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,057

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by fafalone View Post
    Using QueryInterface

    The issue came up again for me today when I started using IShellItem2- one of the ways to get that interface by using .QueryInterface from an IShellItem object, which is actually from its parent IUnknown. Due to the way IUnknown was set up in this project, that function isn't visible on IShellItem or any other interface (they all inherit from IUnknown). They can be made visible by changing all the : stdole.IUnknown to just IUnknown, but I'm unsure of the consequences of such a change, and olelib is too massive to confirm there's no side effects.
    But fear not, if you need to access .QueryInterface, use the method in this routine that gets IShellItem2 from IShellItem

    Code:
    Dim psi As IShellItem
    Dim psi2 As IShellItem2
    Dim pUnk As olelib.IUnknown 'should be explicitly typed since there's another hidden IUnknown in VB and it will cause errors
    
    Call SHCreateShellItem(0, 0, pidl, psi) 'pidl of whatever file/object you're working with, code omitted
    
    Set pUnk = psi
    pUnk.QueryInterface IID_IShellItem2, psi2
    And now you have a ready-to-go IShellItem2. This method is also used, for example, to get an IPropertyStore interface from an IShellLinkW.
    Manually invoking IUnknown's QueryInterface method isn't actually necessary in Visual Basic. The Set statement already does it for you.

    Quote Originally Posted by Guy Eddon and Henry Eddon
    QueryInterface: The Visual Basic Way

    . . . If you need access to the other (nondefault) interfaces supported by an object, you can execute a QueryInterface using the Set statement. If needed, the Set statement calls the IUnknown::QueryInterface method to cast the rvalue interface pointer to the type of the lvalue reference. For example, the following code snippet shows two references—MyRef1 and MyRef2. MyRef1 is declared as an IUnknown interface pointer; MyRef2 is a pointer to the IMyInterface interface. When MyRef2 is set to MyRef1, a QueryInterface call that requests the IMyInterface interface pointer from the object pointed to by MyRef1 takes place.

    Code:
    Dim MyRef1 As IUnknown
    Set MyRef1 = New MyObject
    
    Dim MyRef2 As IMyInterface
    Set MyRef2 = MyRef1 ' QueryInterface executed!
    Quote Originally Posted by Jose Mojica
    How Visual Basic COM+ Objects Work Internally

    . . .

    Why does every vtable need to have these three methods? By enforcing this rule, a client may navigate to any lookup table from any starting point. In other words, suppose that I have the following code:

    Code:
    Dim Checking As CChecking
    Set Checking = New CChecking
    
    Call Checking.OrderChecks(100, 132)
    
    Dim Acct As IAccount
    Set Acct = Checking
    
    Call Acct.MakeDeposit(500)
    
    Dim Checking2 As CChecking
    Set Checking2 = Acct
    The code begins by using the default lookup table, then needs to switch to using the IAccount lookup table (or vtable). The line that reads Set Acct = Checking basically calls the QueryInterface function in the default vtable. The resulting vptr is stored in the Acct variable. I can then use that lookup table to switch to any other interface. In the code above I have a second variable to store the default vtable, Checking2. Which interface can I use to switch to the default interface? I can use any other interface, because they all have the QueryInterface method first. In VB you never have to see the QueryInterface method call. However each time you change the interface you are talking to, you are basically telling VB to call QueryInterface on the particular interface to obtain a second vptr.
    These 2 lines of code can therefore be reduced to just 1:

    Code:
    'Set pUnk = psi
    'pUnk.QueryInterface IID_IShellItem2, psi2
    
    Set psi2 = psi
    The code can be simplified even further by taking advantage of the fact that the IShellItem2 interface inherits from IShellItem:

    Code:
    Call SHCreateShellItem(0, 0, pidl, psi2)
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  21. #21

  22. #22

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by georgekar View Post
    Sorry my English is poor. I know the size of input array. The output array has the same size. The problem for function is that these are not arrays like safe arrays where we found fields that describe the dimension and the size of it. We place the first address and in a variable the length as long items. So cNames is a size both for input and output array. Each array has a long for item, but in first array that long is a pointer to bstr. StrPtr return address of Bstr.
    In old version in typelib we can only provide a string after a convertion to unicode....because vb treat string as ansi, so do a reverse conversion and then put a long as pointer to bstr. There is no way to pass more strings in an array form. So I suspect from cNames that only a buffer of longs passed. Maybe a predefined big buffer can be used for any call to this function.
    The output array has the same number of items as the input array, so passed as in your code, the output array is filled for all items?

  23. #23
    Fanatic Member
    Join Date
    May 2014
    Location
    Preveza Greece
    Posts
    862

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    That is the idea when you call a function with 2 named arguments you have 3 names and you get 3 numbers. First number is the number of function and the two others is the real position of the named arguments.

  24. #24

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by Bonnie West View Post
    Manually invoking IUnknown's QueryInterface method isn't actually necessary in Visual Basic. The Set statement already does it for you.
    [...]
    The one problem I've had with this; if you just use the Set statement, and QueryInterface fails (a rare scenario, but one I just encountered*), then you get a Type Mismatch error which would have to go through your error handler or have its own on error resume next statement and then verification that the new object <> nothing. With the QueryInterface method, you can get the HRESULT without an error if it fails, then proceed accordingly.

    *The scenario popped up in using IPreviewHandler. To initialize it, an object may implement IInitializeWithFile, IInitializeWithStream, or IInitializeWithItem. Most only implement one of these, and there's no way to know beforehand (or if there is it's so obscure that every example still uses trial and error). There's sure to be other scenarios or true errors in QueryInterface calls.

  25. #25
    Lively Member
    Join Date
    Aug 2008
    Location
    Denmark
    Posts
    79

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Thanks - this is cool alone and with all the examples excellent!

  26. #26

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    So I figured the most useful place to put it was an addon to this project, but this is of wider interest:

    There's a new attachment called mPKEY.zip that contains mPKEY.bas - a complete VB version of SDK 7.1's propkey.h, containing all the PROPERTYKEY variables. Like the IID module, these are set up to be used directly without conversion in any interface or API that asks for a PROPERTYKEY.

  27. #27
    New Member
    Join Date
    Mar 2015
    Posts
    4

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Hello Fafalone.
    Can you help me please to transform the old IBindStatusCallback_OnProgress Sub in a Function (as it should)?
    More precisely, it seems that all urlmon callback functions are defined by Morcillo as Sub instead of Functions. http://www.tek-tips.com/viewthread.cfm?qid=1626482
    I wan't waste your time, so if you give me basic steps to modify tlb, it's ok.

    Thank you in advance

    gigirex

  28. #28

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    It's not E.M.'s fault; VB requires any Implements interface to use only Subs. (you can see one specific as a function; but you can only do that if you're returning a variable that's the last param and marked as [out]). A few things here and there have been changed to functions in oleexp, but those interfaces aren't used with Implements.

    In situations like this, where other implementations exist that rely on it being a sub, it's highly inadvisable to change the typelib (and in this specific case, impossible, since there are no [out] arguments, so the only thing to return is the HRESULT which VB doesn't allow). What you should do instead is simply swap out the function:

    In a module (bas), put the following, a routine to swap them, and the new function (i'll assume you already have CopyMemory declared, if not add it):
    Code:
    Public Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
    Public Const PAGE_EXECUTE_READWRITE As Long = &H40&
    
    Public Function SwapVtableEntry(pObj As Long, EntryNumber As Integer, ByVal lpfn As Long) As Long
    
        Dim lOldAddr As Long
        Dim lpVtableHead As Long
        Dim lpfnAddr As Long
        Dim lOldProtect As Long
    
        CopyMemory lpVtableHead, ByVal pObj, 4
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * 4
        CopyMemory lOldAddr, ByVal lpfnAddr, 4
    
        Call VirtualProtect(lpfnAddr, 4, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, 4
        Call VirtualProtect(lpfnAddr, 4, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function
    Public Function IBSCBOnProgress(ByVal this As IBindStatusCallback, ByVal ulProgress As Long, ByVal ulProgressMax As Long, ByVal ulStatusCode As BINDSTATUS, ByVal szStatusText As Long) As Long
    'all code for OnProgress goes here
    End Function
    You still need the prototype (Private Sub IBindStatusCallback_OnProgress...) in your class module, but all code should be relocated to the OnProgress in the module. In your class module which contains the 'Implements IBindStatusCallback' statement, add a module level variable:
    Private mOldOP As Long
    then in Class_Initialize, add:
    Code:
    Dim pVTable As IBindStatusCallback
    Set pVTable = Me
    mOldOP = SwapVtableEntry(ObjPtr(pVTable), 7, AddressOf IBSCBOnProgress)
    and in Class_Terminate, add:
    Code:
    Dim pVTable As IBindStatusCallback
    Set pVTable = Me
    mOldOP = SwapVtableEntry(ObjPtr(pVTable), 7, mOldOP)
    And now everything is redirected to the function version. for reference, the '7' is the entry number we're changing, we start at 4 (1-3 are for IUnknown), so that makes OnProgress 7th.

  29. #29
    New Member
    Join Date
    Mar 2015
    Posts
    4

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Woooow Fafalone!
    Really, ignorantly, I supposed that the solution was more simple than that you have skilfully exposed here.
    Thank you very much for the explanation. I'll test it in next days.

    Regards,
    Luigi Stilo

  30. #30

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    It should be easy... it makes no sense at all that VB turns HRESULT-returning function into Subs. So don't feel bad at all about it, everyone is like 'what the heck????' the first they come across it, me included. And full disclosure, somebody else wrote the SwapVtable function; not sure of the original source tho, it's appeared all over code and in books forever.

  31. #31
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,057

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by fafalone View Post
    ... it makes no sense at all that VB turns HRESULT-returning function into Subs.
    It's likely due to VB's goal of hiding as much complexity from the programmer as possible. All programmer-defined methods and properties in object modules (CLS, FRM, CTL, etc.) returns a hidden HRESULT, even Subs (the HRESULT contains the error code raised in the procedure, if any). A Function's programmer-defined return value is actually declared as the last parameter and it is passed ByRef. When VB sees that a TLB-declared Function returns an HRESULT, it treats that as a Sub, unless its last argument is passed ByRef and is given the attributes [out, retval], in which case, it is recognized as a Function.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  32. #32

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    the HRESULT contains the error code raised in the procedure, if any
    You know.. I've seen this before but had always assumed it was just for handling inside VB... if you used the Err.Raise statement inside a class sub (under the circumstances here, where's it's a VB-implemented callback for a COM interface implemented outside of VB), will that return the value specified as the HRESULT to the main interface outside VB?

    Edit: Yes; but it causes a major app error where you'd have to have a custom error handler for the line it gets raised on. So SwapVtable is a better solution.
    Example: INamespaceWalkCB is a callback for an Explorer-implemented NamespaceWalker object. The only way to cancel a directory walk is to return ERROR_CANCELLED as the HRESULT for INamespaceWalkCB_EnterFolder. Using Err.Raise causes a runtime error on the NamespaceWalker.Walk method that initiated the walk. If continued from that line, the walk continues, but it does provide an opportunity to resume on the next line.

  33. #33
    Fanatic Member
    Join Date
    Oct 2008
    Posts
    909

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Where is the download link to get the latest version this oleexp.tlb file? There's a very very very long description of what it can do in the opening thread, but I can't find the download link. It may be buried in the text somewhere, but I didn't manage to find it. Please post the link somewhere where I can find it. I'd really like to try this thing out.

  34. #34
    Fanatic Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    775

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Look at the bottom of the first post in the Attached Files section for the download link.

  35. #35

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    If I add a link at the top then it removes the icons/gray box at the bottom (could add another text link at the bottom too, but can't get the normal box with icons back).. and that I had thought would actually make it harder to find. But unless these manual plain text links are set up, the default download box is always at the bottom of the post.

    Also in case you're looking for a new version of "oleexp.tlb" exactly.. when the version numbers got to 3.0 a few months ago the project was combined with olelib into a single file with a new GUID, so now oleexp3.tlb replaces both olelib.tlb and oleexp.tlb (any variables declared like Dim x As olelib.Type or Dim x As oleexp.Type can be automatically replaced with Dim x As oleexp3.Type)

  36. #36
    Lively Member
    Join Date
    Apr 2009
    Posts
    64

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Hi all,

    I have been trying to make this following code work in Windows 64bit but without any success

    Any help anyone on how to make it work for Windows 64 bit ... Thanks

    Code:
    Public Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
    Public Const PAGE_EXECUTE_READWRITE As Long = &H40&
    
    Public Function SwapVtableEntry(pObj As Long, EntryNumber As Integer, ByVal lpfn As Long) As Long
    
        Dim lOldAddr As Long
        Dim lpVtableHead As Long
        Dim lpfnAddr As Long
        Dim lOldProtect As Long
    
        CopyMemory lpVtableHead, ByVal pObj, 4
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * 4
        CopyMemory lOldAddr, ByVal lpfnAddr, 4
    
        Call VirtualProtect(lpfnAddr, 4, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, 4
        Call VirtualProtect(lpfnAddr, 4, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function

  37. #37
    Member
    Join Date
    Feb 2015
    Posts
    36

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    It depends on whether you mean you want to run a 32-bit program in Windows 64 or whether you want to make a 64-bit program and then run that in 64-bit Windows. If you are using Visual Basic 6 it can't make a 64-bit program so whatever you compile to will be 32-bit, in which case you don't have to make any changes. In the VB6 case, just compile and run the program because it is very common for 32-bit programs like what VB6 makes to run inside of Windows 64.

    The only way I know to make 64-bit code using VB or VBA is to run the code in VBA in a 64-bit version of Microsoft Office (not a 32-bit version running in 64-bit Windows). In this case you need to make the following changes:

    1) You have to change all of the "4" values to "8" because a memory address in Windows 64 is 8 bytes long, not 4 like it is in 32-bit Windows.

    2) Your pointer variables need to change to LongPtr from Long (note that LongPtr does not exist in VB6). It is somewhat confusing because in 32-bit code you use a Long variable to represent a pointer or an actual Long variable so you have to study the code a bit to figure out what are pointers that need to be changed to LongPtr. Note that LongPtr was introduced in Office 2010 and you can use it in 32 or 64 bit Office. In 32-bit Office LongPtr gets converted to Long automatically.

    3) You would have to execute the code below on a 64-bit Office program in VBA. Thee is a requirement if you do that you have to add the word PtrSafe into any Windows API declaration to show that you have thought through the necessary change in the WIndows function call.

    I haven't tested your code but I believe it should look like the following:

    Code:
    Public Declare PtrSafe Function VirtualProtect Lib "kernel32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As LongPtr) As Long
    Public Const PAGE_EXECUTE_READWRITE As Long = &H40&
    
    Public Function SwapVtableEntry(pObj As LongPtr, EntryNumber As Integer, ByVal lpfn As LongPtr) As LongPtr
    
        Dim lOldAddr As LongPtr
        Dim lpVtableHead As LongPtr
        Dim lpfnAddr As LongPtr
        Dim lOldProtect As LongPtr
    
        CopyMemory lpVtableHead, ByVal pObj, 8
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * 8
        CopyMemory lOldAddr, ByVal lpfnAddr, 8
    
        Call VirtualProtect(lpfnAddr, 8, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, 8
        Call VirtualProtect(lpfnAddr, 8, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function
    Now it starts getting interesting if you want to be able to run this code in 32-bit Office (what probably 99.9% of people use up to this point) AND to be able to run in 64-bit Windows without having to change code.

    The way we do that is to use a conditional compilation constant that tells the code compiler which version is trying to compile it and we'll have two sets of code and tell it to only use the code for the type (32 or 64 bit) that is running. I would do this like this:

    Code:
    #If Win64 Then
    Public Declare PtrSafe Function VirtualProtect Lib "kernel32" (ByVal lpAddress As LongPtr, _
       ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As LongPtr) As Long
    Public Const PAGE_EXECUTE_READWRITE As Long = &H40&
    
    Public Function SwapVtableEntry(pObj As LongPtr, EntryNumber As Integer, ByVal lpfn As LongPtr) As LongPtr
    
        Dim lOldAddr As LongPtr
        Dim lpVtableHead As LongPtr
        Dim lpfnAddr As LongPtr
        Dim lOldProtect As LongPtr
    
        CopyMemory lpVtableHead, ByVal pObj, 8
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * 8
        CopyMemory lOldAddr, ByVal lpfnAddr, 8
    
        Call VirtualProtect(lpfnAddr, 8, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, 8
        Call VirtualProtect(lpfnAddr, 8, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function
    
    #Else
    Public Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, _
        ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
    Public Const PAGE_EXECUTE_READWRITE As Long = &H40&
    
    Public Function SwapVtableEntry(pObj As Long, EntryNumber As Integer, ByVal lpfn As Long) As Long
    
        Dim lOldAddr As Long
        Dim lpVtableHead As Long
        Dim lpfnAddr As Long
        Dim lOldProtect As Long
    
        CopyMemory lpVtableHead, ByVal pObj, 4
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * 4
        CopyMemory lOldAddr, ByVal lpfnAddr, 4
    
        Call VirtualProtect(lpfnAddr, 4, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, 4
        Call VirtualProtect(lpfnAddr, 4, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function
    #End If
    There is obviously a lot of code overlap so if you are really adventuresome you could smush stuff together and do the following:

    Code:
    #If Win64 Then
    Public Declare PtrSafe Function VirtualProtect Lib "kernel32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As LongPtr) As Long
    #Else
    Public Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
    #End If
    ' I left the two declarations above the code because it allows you to put other Windows
    '  calls in there if your code has any.
    
    '
    '  Any other code you want to put here.
    '
    
    #If Win64 Then
    Public Function SwapVtableEntry(pObj As LongPtr, EntryNumber As Integer, ByVal lpfn As LongPtr) As LongPtr
    Const BytesPerAddr as Long = 8
    
        Dim lOldAddr As LongPtr
        Dim lpVtableHead As LongPtr
        Dim lpfnAddr As LongPtr
        Dim lOldProtect As LongPtr
    #Else
    Public Function SwapVtableEntry(pObj As Long, EntryNumber As Integer, ByVal lpfn As Long) As Long
    Const BytesPerAddr as Long = 4
    
        Dim lOldAddr As Long
        Dim lpVtableHead As Long
        Dim lpfnAddr As Long
        Dim lOldProtect As Long
    #End If
    
        CopyMemory lpVtableHead, ByVal pObj, BytesPerAddr
        lpfnAddr = lpVtableHead + (EntryNumber - 1) * BytesPerAddr
        CopyMemory lOldAddr, ByVal lpfnAddr, BytesPerAddr
    
        Call VirtualProtect(lpfnAddr, BytesPerAddr, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, lpfn, BytesPerAddr
        Call VirtualProtect(lpfnAddr, BytesPerAddr, lOldProtect, lOldProtect)
    
        SwapVtableEntry = lOldAddr
    
    End Function
    What I did above is much harder to read unless you do this a lot (like I do) so you may be better off not combining the code and using the version above.

  38. #38
    Lively Member
    Join Date
    Apr 2009
    Posts
    64

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Thank you very much Mountainman,

    Based on your answer, I have successfully managed to override the CalculateFull Method of the Excel application object ... The CalculateFull Propery vtable offset happens to be 319 ... See code below :

    Proceedings : Run the HookCOMFunction first in order to hook the CalculateFull Propery and then run the Test macro

    Code:
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, _
    Source As Any, _
    ByVal length As LongPtr _
    )
    
    Private Declare PtrSafe Function VirtualProtect Lib "kernel32" _
    (ByVal lpAddress As LongPtr, ByVal dwSize As LongPtr, _
    ByVal flNewProtect As LongPtr, lpflOldProtect As LongPtr) As Long
    
    
    Private Const PAGE_EXECUTE_READWRITE As Long = &H40&
    Private Const lFuncOffset = 319  'Excel Application.calculateFull Method VTable Offset
    Private pVTable As LongPtr
    Private bHooked As Boolean
    Private lOldAddr As LongPtr
    
    Sub HookCOMFunction()
        Dim lOldAddr As LongPtr
        Dim lpVtableHead As LongPtr
        Dim lpfnAddr As LongPtr
        Dim lOldProtect As LongPtr
        Dim pObj As LongPtr
        pObj = CLngPtr(ObjPtr(Application))
    
        CopyMemory lpVtableHead, ByVal pObj, 8
        lpfnAddr = lpVtableHead + (lFuncOffset) * 8
        CopyMemory lOldAddr, ByVal lpfnAddr, 8
    
        Call VirtualProtect(lpfnAddr, 8, PAGE_EXECUTE_READWRITE, lOldProtect)
        CopyMemory ByVal lpfnAddr, AddressOf OverrideFunction, 8
        Call VirtualProtect(lpfnAddr, 8, lOldProtect, lOldProtect)
    End Sub
    
    
    Private Function OverrideFunction(ByVal voObjPtr As Long, ByVal Param As Long) As Long
        MsgBox "Excel 'CalculateFull' Method has been Hooked !!"
    End Function
    
    
    Sub Test()
        Application.CalculateFull
    End Sub
    The only thing that i haven't managed to do is to restore CalculateFull Property back to its original vtable address ... the following code crashes the excel application :
    Code:
    Sub UnHookComFunction()
        CopyMemory lpfnAddr, ByVal lOldAddr, 8
    End Sub
    Also, (and this is my ultimate goal) is there a way to make this work when executing the CalculateFull Method via the excel user interface (ie via the excel menu) as opposed to the hook only working when the CalculateFull Method is excecuted via code as in the Test macro aboe ?

    Thanks for your help one more time

  39. #39
    Member
    Join Date
    Feb 2015
    Posts
    36

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    I believe the problem is that you hve defined lOldAddr both in your HookCOMFunction procedure and also as a module level variable. When you first determined the value for lOldAddr you are doing it inside of the HookCOMFunction procedure but when that procedure goes out of focus you lose all of the procedure variables including lOldAddr. Normally this would cause a syntax error later when you tried to re-use it to re-set the address because in UnHookComFunction you don't have this variable. However, in this case another variable of the same name exists at the module level and although it has really never been used (i.e., it has a value of 0) your function uses it anyway which I am sure Windows doesn't like. My suggestion is to get rid of the lOldAddr variable in the HookCOMFunction procedure and only use the module-level variable of that name.

    BTW, I also suggest that you don't make all of your passed parameters to be LongPtr. It is true (I think) that in 64-bit Windows all parameters passed to a function or sub are passed as 64-bit values but it can cause you problems later. For example, you are calling the Windows API function VirtualProtect whose 2nd parameter is dwSize. When the Windows documentation shows a variable starting with "dw" it means it is a double word, a 32-bit value. If you pass a LongPtr it will go on the stack as a 64-bit value and VBA will pass the whole value. This means that if somehow you were to put a value larger than a Long to be passed that VBA would just pass it along but the function is really expecting the top 4 bytes to be 0 since it is only going to use the bottom 4 bytes. I prefer to list the parameter in the call as a Long (which is what the function expects) and I will count on VBA to make the top 4 bytes a 0 when it really puts it on the stack as a 64-bit number. That way I feel a lot better than a) I own't ever mess up and give it a value that is out-of-range of what the function wants by being too big and b) when we go to a 129-bit operating system I don't have to go back in and check each variable I am passing to make sure that it is the right size. What you have done though will work; I just think you are setting yourself up for problems down the road.

  40. #40

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    1,776

    Re: [VB6] Modern Shell Interface Type Library - oleexp.tlb

    Quote Originally Posted by RAFAAJ2000 View Post
    Also, (and this is my ultimate goal) is there a way to make this work when executing the CalculateFull Method via the excel user interface (ie via the excel menu) as opposed to the hook only working when the CalculateFull Method is excecuted via code as in the Test macro aboe ?
    Well in principle, you could subclass the process and intercept the menus WM_COMMAND message, but subclassing a 64-bit app might be challenging.

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.