Namespace extensions - the undocumented Windows Shell (original) (raw)

Index

Functions

Structures

SHCreateShellFolderViewEx callback messages

SHShellFolderView_Message messages

Shell Messages

Macros

Interfaces


This article explains how you can easily create a namespace extension with lots of features without doing lots of work by using some undocumented shell functions. The most noticeable function is SHCreateShellFolderViewEx, which creates the view for you and creates all interfaces you need for displaying the contents of your folder. You can modify the behaviour of the folder by implementing a callback function. This is how Microsoft implements its own namespace extensions.

Introduction to the windows shell

The windows shell is built around COM interfaces. The browser ("explorer") calls interfaces that are implemented by a number of DLL's and these DLL's can call back into the interfaces of the browser. You can extend the behaviour of the browser by plugging in your own DLL that implements the needed interfaces.

The householding of the DLL's is maintained in the registry, as is usual for COM objects.

The shell namespace

The shell namespace is a collection of folders that contain items. These items can in turn be folders, generating a tree structure. This ressembles the directory tree structure that is found in a file system, but should not be confused with it.

The top of the shell namespace tree is the Desktop folder. This folder contains "my computer", which in turn contains the drives on your computer. The part of the shell namespace that represents a drive looks almost the same as the directory structure on that drive, but is not exactly the same. The drive can contain additional items and existing items may look very different in the shell namespace.

Shell extensions

The DLL's that are plugged into the shell are called shell extensions. There are several kinds of shell extensions:

  1. A context menu extension puts extra items in the context menu that is viewed in the browser.
  2. A property sheet extension displays extra property pages in the property sheets that are viewed in the browser.
  3. A namespace extension adds extra folders to the namespace.

Pidls

Every item in a folder is identified by an identifier, just like every file or directory on a drive is identified by a filename. This identifier is called a Pidl.

For someone who uses the shell to browse the namespace, a pidl is just an opaque structure that gets passed around without having any meaning.

Someone who implements a part of the namespace assigns a meaning to the pidls for his part of the namespace. The pidl is a variable-sized structure that can contain anything the implementor wants to put in. The pidl usually caches all information that is frequently needed. In a directory structure, the pidl contains the long and short filename and some other stuff.

Structure of a pidl

A item id consists of 2 parts: the length and the data. The length comes first and is the total length of the item (including the length part itself). The data is opaque to the user and only has meaning to the implementor of the namespace.

Multiple item ids are concatenated to form a pidl. A pidl is a series of concatenated item ids, ending with an id with length 0.

Absolute and relative pidls

A filename can be absolute or relative: An absulute filename is fully qualified (e.g. "c:\winnt\system32\shell32.dll"). A relative filename is relative to the directory in which it resides.

The same goes for a pidl. A pidl can be absolute or relative. The root for an absolute pidl is the desktop. A relative pidl is relative to a specific folder in the namespace.

Designing your pidls

If you implement your own namespace extension, you will have to design your own pidls.

The easiest way to assign a meaning to your pidls is by defining a struct that contains all the information you need.

You must be able to determine if a pidl that is passed to you is really a valid pidl. You can do this by starting the pidl with a signature (a few bytes that are always the same).

The pidl should contain all information that will frequently be needed and that takes some time to find out. You should always store the name and all texts that are stored in the different columns in the details view, unless you can derive them easily.

Your pidl should contain one field that uniquely identifies the item. This can be a handle, an ID,...

You will be the only one who decides wether two pidls are for the same item. You will do that through your IShellFolder's CompareIDs. Return 0 for pidls that represent the same object, and 1 or -1 for pidls that represent different objects (even if you don't care how they are sorted).

Allocating and freeing pidls

All pidls should always be allocated and freeed by the Shell Allocater.

You can retrieve the Shell Allocator by calling SHGetMalloc.

Shortcuts for allocating and freeing pidls are provided by the functions SHAlloc and ILFree.

Pidl functions

SHAlloc

WINSHELLAPI LPVOID WINAPI SHAlloc(UINT cb);

Description

Allocates cb bytes of memory using the Shell Allocator

Parameters

Return value

A pointer to the block of memory that was allocated

ILFree

WINSHELLAPI void WINAPI ILFree(LPITEMIDLIST pidl);

Description

Frees a pidl using the Shell Allocator

Parameters

Remarks

I have no idea why there is both a SHfree function and an ILFree function. They are probably exactly the same.

ILClone

WINSHELLAPI LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl);

Description

Creates a copy of the passed in pidl

Parameters

Return value

A pointer to the newly created copy of the pidl

Remarks

The new pidl is allocated using the Shell Allocator. You should free it by calling ILFree.

ILAppendID

WINSHELLAPI LPITEMIDLIST WINAPI ILAppendID(LPITEMIDLIST pidl, LPCITEMIDLIST item,BOOL bEnd);

Description

Appends a new item identifier to an existing pidl

Parameters

Remarks

This function destroys the passed in complex pidl.

ILCloneFirst

WINSHELLAPI LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl);

Description

Creates a new pidl that contains the first item id of a complex pidl

Parameters

Return value

A newly created pidl that contains the first item id of the passed in complex pidl

Remarks

The new pidl is allocated with the Shell Allocator. You should free it by calling ILFree.

ILCombine

WINSHELLAPI LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl, LPCITEMIDLIST pidlsub);

Description

Concatenates two complex pidls

Parameters

Return value

The newly created pidl

Remarks

The passed in pidls are not destroyed. The newly created pidl is allocated using the Shell Allocator. You should free it by calling ILFree. This function is useful if you have a relative pidl of an item and the absolute pidl of its parent folder. The function returns the absolute pidl of the item.

ILCreateFromPath

Remarks

I didn't find out the exact signature of this function yet.

ILFindChild

WINSHELLAPI LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);

Description

Compares the elements of a complex pidl

Parameters

Return value

If at least the first item id is the same, returns the location of the first item id in pidl2 that doesn't match pidl1. NULL if pidl2 is shorter than pidl1

Remarks

I never tested this function. The signature and description may not be correct.

ILFindLastID

WINSHELLAPI LPITEMIDLIST WINAPI ILFindLastID)(LPCITEMIDLIST pidl);

Description

Finds the position of the last item id in a pidl

Parameters

Return value

A pointer to the last item id in the passed in pidl

Remarks

You can call ILClone(ILFindLastID(pidl)) to create a relative pidl out of an absolute pidl.

ILGetDisplayName

Remarks

I didn't find out the exact signature of this function yet.

ILGetNext

WINSHELLAPI LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl);

Description

This function finds the location of the second item id in a complex pidl

Parameters

Return value

The position of the next item id in the pidl The pidl itself is the first item id, the next one is the second.

Remarks

You can use ILClone(ILFindNextID(pidl)) to obtain a pidl of an item that is relative to the first parent folder. This can be very useful if you were passed a complex pidl in you IShellFolder implementation. You can split off the first item id, bind a new shell folder to this id and the,n pass this new folder the remainder of the pidl.

ILGetSize

WINSHELLAPI UINT WINAPI ILGetSize(LPCITEMIDLIST pidl);

Description

Calculates the full size of a pidl

Parameters

Return value

The total size of the passed in pidl in bytes, including the zero terminator

ILGlobalClone

Remarks

I didn't find out the exact signature of this function yet.

ILGlobalFree

Remarks

I didn't find out the exact signature of this function yet.

ILIsEqual

WINSHELLAPI BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);

Description

Tests two pidls for equality

Paramaters

Return value

Zero if the two pidls are different, nonzero if the pidls are equal

ILIsParent

Remarks

I didn't find out the exact signature of this function yet.

ILLoadFromStream

Remarks

I didn't find out the exact signature of this function yet.

ILRemoveLastID

WINSHELLAPI BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl);

Description

Removes the last item identifier from a complex pidl

Parameters

Return value

Nonzero if successful, zero otherwise

Remarks

This function modifies the passed in pidl by setting the last item id's byte count to zero.
To create a new pidl without the last item id, you would have to call ILRemoveLastID(ILClone(pidl)).

ILSaveToStream

Remarks

I didn't find out the exact signature of this function yet.

Object model

The shell is browsed by a Shell Browser object, which is implemented by the browser, usually Windows Explorer. This browser traverses the namespace.

The namespace is made up of Shell Folders. A Shell Folder is an object that represents a virtual folder, i.e. a filesystem directory or a namespace extension folder. The items of a Shell Folder are enumerated by an Item Enumerator. This object simply enumerates the pidls of objects.

The contents of a Shell Folder are viewed by a Shell View. The Shell View is a window that usually displays a list of items. A group of items (e.g. the items that are selected in a Shell View) is represented by a UI Object.

The Shell Browser

The Shell Browser is the application that browses the namespace (Windows Explorer). The Shell Browser implements the interface IShellBrwoser. You will never implement this interface yourself.

Shell Folders

Shell Folders represent folders in the namespace. They create new Shell Folders for their items and they create UI Objects. They provide information on their items. A Shell Folder implements a namespace extension.

Interfaces implemented by Shell Folders

A shell folder should implement IShellFolder, IPersistFolder, IDropTarget, IExtractIcon and ["#IShellDetails">IShellDetails](<span).

The IShellFolder interface is used for getting information on items in a folder and as a factory for creating Item Enumerators, Shell Views and UI Objects. Most IShellFolder methods take pidls as parameters. These pidls are always relative to the Shell Folder.

The IPersistfolder interface is only used to pass the shell folder its own absolute pidl.

The IDropTarget interface is a standard OLE interface that is used for drag and drop.

The IExtractIcon interface is used to get the icon for an item.

The ["#IShellDetails">IShellDetails](<span) interface is used for communication with the Shell View. It provides some extra information about how to display items in a multi-column list: the titles for the columns and the details to fill in in these columns.

All these interfaces are well documented, except ["#IShellDetails">IShellDetails](<span). This interface is described later.

Item Enumerators

An item enumerator makes it possible to enumerate all items in a Shell Folder.

An Item Enumerator implements IEnumIDList. This is a common IEnumXXX interface. This interface is well documented.

User Interface Objects (UI objects)

UI Objects handle user interaction with items. They implement shell extensions other than namespace extensions.

Possible UI objects are context menu handlers, property sheet handlers, infotip handlers.

UI Objects must be able to handle multiple selection.

Interfaces implemented by UI Objects

UI Objects implement some are all of the following interfaces:
IObjectWithSite, IExternalConnection, IShellExtInit, IDataSource, IContextMenu, IShellPropSheetExt and IQueryInfo.

IObjectWithSite is a standard OLE interface that is used for setting up communication between an object and the container in which it resides. In this case the container is the Shell Browser. You can omit thhis interface.

IExternalConnection is used for maintaining strong locks on an object. This interface is needed because the object may be marshalled to another proces (e.g. during drag and drop).
You can omit this interface. In that case, OLE will provide a default interface for you.

IShellExtInit is implemented by property sheet handlers and context menu handlers. These should always implement the interface. The IShellExtInit interface only has one method Initialize, which is used for setting the context of the shell extension.

IDataSource is a standard OLE interface. It is used mainly for drag and drop and for copy and paste. You can think of the IDataSource interface as a way of serializing the set of items.
If your namespace extension has more than one folder, you can implement your own clip formats. The IDataSource interface is too complex to be fully covered here.

Besides its obvious usage as a source of information for displaying a context menu, the IContextMenu interface is used for some other purposes: When the user presses a standard button in the toolbar, IContextMenu::InvokeCommand will be invoked with a verb. This verb will be a word like cut, copy, paste, delete or properties.

The IContextMenu interface is also used to add items to the main menu of the browser's window. When QueryContextMenu is called, you should add commands to the menu that have identifiers of the form idCmdFirst + SOME_CONSTANT. When InvokeCommand is called, the identifier SOME_CONSTANT will be passed.

The IShellPropSheetExt interface is used for displaying property pages.

The IQueryInfo interface is used for displaying info tips when the mouse is moved over an item.

All these interfaces are well documented.

Shell Views

Shell views are the windows that display a shell folder's contents. Shell views implement IShellView and some additional interfaces. Instead of implementing this object yourself, you should call ["#SHCreateShellFolderViewEx">SHCreateShellFolderViewEx](<span). This function creates the Shell View for you.

Interface IShellDetails

Besides the IUnknown functions, the IShellDetails interface has two functions: GetDetailsOf and ColumnClick.

HRESULT STDMETHODCALLTYPE GetDetailsOf(LPCITEMIDLIST pidl, UINT col, ["#SHColInfo">SHColInfo](<span) *data);

Description

If pidl equals NULL, this function retrieves information about a column in the Shell View. Otherwise, it retrieves the information to display in a particular column of the view for a given pidl.

Parameters

Return value

Return S_OK if you filled in the details, E_FAIL otherwise.
If pidl equals NULL, you should return S_OK for all columns that you support and E_FAIL for an index that is too large. This is how the Shell View will know how many columns to display.

HRESULT STDMETHODCALLTYPE ColumnClick(UINT col);

Description

This function is called when the user clicks the title of a column.

Parameters

Remarks

You should send a SFVM_REARRANGE message to the owner of the view window.
You can use the function SHShellFolderView_Message to send the meassage. The window handle of the owner of the view window is passed to you in IShellFolder::CreateViewObject. This is the time to save this handle.
The lparam that you should pass to SHShellFolderView_Message is the index of the column that was clicked (i.e. the col parameter).
After calling SHSHellFolderView_Message, IShellFolder::CompareIDs will be called with an lParam that equals the index of the column that was clicked. This is contrary to the Microsoft documentation, which states that this lParam will always be zero and should be ignored.

Function SHCreateShellFolderViewEx

The function

WINSHELLAPI HRESULT WINAPI SHCreateShellFolderViewEx(["#SHELLVIEWDATA">LPSHELLVIEWDATA](<span) psvcbi, LPVOID *ppv);

Description

This is the most interesting function I discovered. This function enables you to use the same mechanism as Microsoft for displaying the contents of your namespace extensions.

This function creates the Shell View for you, including the most important interfaces like IShellView.

This function makes sure you will handle everything the way you should. It provides an easy interface for otherwise difficult tasks like changing the toolbar.

When calling this function, you pass a callback function that gets called to handle all kinds of events, enabling you to customize the shell view.

Parameters

Remarks

Call this function from your IShellFolder's CreateViewObject when riid is IID_IShellView.

The SHELLVIEWDATA structure

typedef struct _SHELLVIEWDATA { DWORD dwSize; LPSHELLFOLDER pShellFolder; DWORD dwUserParam; LPCITEMIDLIST pidl; DWORD dwEventId; SHELLVIEWPROC pCallBack; DWORD viewmode;
} SHELLVIEWDATA, * LPSHELLVIEWDATA;

Members:

The callback function

HRESULT CALLBACK SHELLVIEWPROC(DWORD dwUserParam, LPSHELLFOLDER psf, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

Description

This is the prototype of a function you should implement yourself. You pass a pointer to this function in SHCreateShellFolderViewEx.

Parameters

Remarks

This is the function that enables you to modify the behavior of the shell view. You can add toolbar buttons, change the menu and react on several events, all from within this function. This function is typically a large switch on uMsg. Te values for uMsg and the corresponding wParam and lParam are described below. The uMsg values all have a name that starts with SFVCB_.

SFVCB_INVOKECOMMAND

Description

This message is sent when the user presses one of the toolbar buttons that you added.

wParam

The wParam value is the command id that you assigned to this toolbar button. Maybe you should use LOWORD(wParam).

SFVCB_GETTOOLBARTIP

Description

This message is sent either when a tooltip is needed for a toolbar button or when a text label is needed if the toolbar displays text labels beneath the buttons.

LOWORD(wParam)

This is the command ID, like in SFVCB_INVOKECOMMAND.

lParam

lParam is a pointer to a unicode buffer that will receive the text string.

HIWORD(wParam)

This is the length of the buffer in unicode characters.

Remarks

You will typically call Lo <NOBR>adStringW(hInstance, ID_YOUR_COMMAND, (LPSTR)lParam, HIWORD(wParam))</NOBR> to react on this message.

SFVCB_GETTOOLBARINFO

Description

This message allows you to change the toolbar. It is sent when the list view is first shown.

lParam

Pointer to a <SFVCB%5FTOOLBARINFO> structure to be filled in.

Remarks

If you return S_OK, you will get a SFVCB_ADDTOOLBARITEMS message that allows you to provide the details of the buttons.

SFVCB_ADDTOOLBARITEMS

Description

This message is sent if you return S_OK to the SFVCB_GETTOOLBARINFO message. It is sent once to fill in details for all buttons.

LOWORD(wParam)

This is a constant you should add to your command IDs, much like in IContextMenu. When the user presses a toolbar button, you will receive the ID you filled in minus this constant.

lParam

Pointer to an array of SFVCB_TOOLBARBUTTONINFO structures. The size of the array is equal to the number of buttons that was supplied in SFVCB_GETTOOLBARINFO.

SFVCB_INITMENUPOPUP

Description

I don't know the exact meaning of this message.

SFVCB_SELECTIONCHANGED

Description

This message is sent when the selection changes in the list view.

lParam

Pointer to a SFVCB_SELECTINFO structure.

Remarks

If the user selects/deselects multiple items at a time (e.g. using Shift), the message will be sent for every item.

SFVCB_DRAWMENUITEM

Description

I don't know the exact meaning of this message.

SFVCB_MEASUREMENUITEM

Description

I don't know the exact meaning of this message.

SFVCB_EXITMENULOOP

Description

I don't know the exact meaning of this message.

SFVCB_VIEWRELEASE

Description

I don't know the exact meaning of this message.

SFVCB_GETNAMELENGTH

Description

I don't know the exact meaning of this message. The message is sent when beginning label edit.

SFVCB_CHANGENOTIFY

Description

This message is sent when SHChangeNotify is called for one of the items in the shell folder that is represented by this view.

wParam

Pointer to an array of the two pidls that were passed to SHChangeNotify.

lParam

The dwEventID that represents the event (e.g. SHCNE_RENAMEITEM)

SFVCB_WINDOWCREATED

Description

This message is sent when the window is created

wParam

The HWND of the newly created window

SFVCB_WINDOWCLOSING

Description

I don't know the exact meaning of this message.

SFVCB_LISTREFRESHED

Description

I don't know the exact meaning of this message.

SFVCB_WINDOWFOCUSED

Description

This message is sent to inform you that the list view has received the focus.

SFVCB_REGISTERCOPYHOOK

Description

I don't know the exact meaning of this message.

SFVCB_COPYHOOKCALLBACK

Description

I don't know the exact meaning of this message.

SFVCB_GETDETAILSOF

Description

This message is sent to if you don't implement IShellDetails.

lParam

Pointer to a SFVCB_COLUMNINFOSTRUCT structure. The STRRET has to be filled in.

wParam

The column for which the info is requested.

Remarks

The pidl in the SFVCB_COLUMNINFOSTRUCT structure will be NULL to request the title of a column.

SFVCB_COLUMNCLICK

Description

This message is sent if you don't implement IShellDetails.

wParam

The index of the column that was clicked

Remarks

The default implementation would be SHShellFolderView_Message(hWndCabinet, SFVM_REARRANGE, wParam) where hWndCabinet is the window handle that was passes in IShellFolder::GetViewObjectOf.

SFVCB_GETCHANGENOTIFYPIDL

Description

Use this message to change the pidl to watch for change notifications. This is only useful of you will call SHChangeNotify with another pidl than the one specified in SHCreateShellFolderViewEx.

lParam

Pointer to a complex pidl to be filled in

Remarks

It seems that specifying a NULL pidl is just the same as failing the message. You will probably never use this one.

SFVCB_COLUMNCLICK2

Description

The same as SFVCB_COLUMNCLICK, but called when you do implement IShellDetails.

Used structs

SHColInfo

typedef struct { DWORD fJustify; INT nWidth; STRRET text; } SHColInfo, *PSHCOLINFO;

SFVCB_COLUMNINFOSTRUCT

typedef struct tag_SFVCB_COLUMNINFOSTRUCT { LPCITEMIDLIST pidl; SHColInfo sci; } SFVCB_COLUMNINFOSTRUCT, *LPSFVCB_COLUMNINFOSTRUCT;

SFVCB_TOOLBARINFO

typedef struct tag_SFVCB_TOOLBARINFO { DWORD dwNumItems; DWORD dwPos; } SFVCB_TOOLBARINFO;

SFVCB_TOOLBARBUTTONINFO

typedef struct tag_SFVCB_TOOLBARBUTTONINFO { DWORD dwBitmap; DWORD dwCommand; DWORD dwFlags; DWORD reserved1; DWORD reserved2; } SFVCB_TOOLBARBUTTONINFO;

SFVCB_SELECTINFO

typedef struct tag_SFVCB_SELECTINFO { DWORD reserved; DWORD dwFLAGS; LPITEMIDLIST pidl; } SFVCB_SELECTINFO;

The function SHShellFolderView_Message

The function

WINSHELLAPI int WINAPI SHShellFolderView_Message(HWND hwndCabinet, UINT uMsg, LPARAM lParam);

Description

This function can be used to send some special messages to the cabinet window. These messages have mostly to do with gatherring information about items and changing some attributes of some items.

Parameters

Return value

The return value depends on the message.

Remarks

You will need to call this function to enable sorting on a specified column. You use SFVM_REARRANGE for that.

SFVM_REARRANGE

This message indicates that the user has clicked a column in the header of the list control. The list needs to be rearranged.

lParam

The index of the column on which to sort (starting at 0). This value will be passes to IShellFolder::CompareIDs.

SFVM_GETARRANGECOLUMN

To be done.

SFVM_ADDOBJECT

To be done.

SFVM_GETITEMCOUNT

Description

Used to retrieve the number of items in the list.

Return value

The number of items in the list

SFVM_GETITEMPIDL

To be done.

SFVM_REMOVEOBJECT

Description

Use this message to remove an item from the list.

lParam

lParam is a relative pidl of the object to remove. You can specify NULL to remove all items.

SFVM_UPDATEOBJECT

To be done.

SFVM_SETREDRAW

To be done.

SFVM_GETSELECTEDOBJECTS

Description

Use this message to retrieve an array of pidls for all selected objects.

lParam

lParam is actually of type (LPITEMID **). It is a pointer to a pointer that receives the address of an array of pidls. Use SFVM_GETSELECTEDCOUNT to learn the size of this array.

SFVM_ISDROPONSOURCE

To be done.

SFVM_MOVEICONS

To be done.

SFVM_GETDRAGPOINT

To be done.

SFVM_GETDROPPOINT

To be done.

SFVM_SETOBJECTPOS

To be done.

SFVM_ISDROPONBACKGROUND

To be done.

SFVM_CUTOBJECTS

To be done.

SFVM_TOGGLEAUTOARRANGE

To be done.

SFVM_LINEUPICONS

To be done.

SFVM_GETAUTOARRANGE

To be done.

SFVM_GETSELECTEDCOUNT

Description

This message can be used to learn how many items are selected in the list.

Return value

The number of selected items

SFVM_GETITEMSPACING

To be done.

SFVM_REFRESHOBJECT

To be done.

SFVM_SETCLIPBOARDPOINTS

To be done.

Shell messages

There are some undocumented messages that can be sent to a cabinet window. This is again the window that is passed as hwndOwner in IShellFolder::CreateViewObject.

CWM_SETPATH

wParam

A combination of one or more of the flags CSP_HANDLE and CSP_REPOST. CSP_REPOST indicates the message should not be handled immediately.

lParam

If CSP_HANDLE is specified, lParam is a HGLOBAL that contains a string. This memory will be freed when the message is handled.
Otherwise, lParam points to a string.

CWM_WANTIDLE

Macro

This message can be sent using the following macro:
FileCabinet_WantIdle(_hwnd, _user, _lpidlproc)

Description

Use this message if you created a window using SHCreateShellFolderViewEx and you want to do idle processing in your window.

wParam

wParam (the _user in the macro) is a user-defined value that will be passed to the idle proc.

lParam

lParam (the _lpidlproc in the macro) is the idle proc that should be called. This function is of the type FCIDLEPROC.

Return value

non-zero if successful, zero otherwise

CWM_GETSETCURRENTINFO

Macro

FileCabinet_GetSetCurrentInfo(_hwnd, _bSet, _lpfs)

Description

This message is used to retrieve or change the current folder settings.

wParam

wParam is the _bSet in the macro. If it is zero, the settings are being retrieved. Otherwise, they are being set.

lParam

lParam is the _lpfs in the macro. It points to a FOLDERSETTINGS structure that contains the values to set or receives the current values, depending on wParam.

CWM_SELECTITEM

Macro

FileCabinet_SelectItem(_hwnd, _bSel, _lpidl)

Description

Use this message to select/deselect an item.

wParam

wParam is the _bSel in the macro. If it is zero, the item is selected. Otherwise, the item is deselected.

lParam

lParam is the _lpidl in the macro. It is the pidl of the item to select/deselect. Use NULL to select/deselect all items.

CWM_STOPWAITING

Macro

FileCabinet_StopWaiting(_hwnd)

Remarks

One source defines the same message as CWM_SELECTITEMSTR. I don't know which one is right.

CWM_GETISHELLBROWSER

Macro

FileCabinet_GetIShellBrowser(_hwnd)

Description

Returns an IShellBrowser interface pointer of the shell browser that created the window.

Remarks

The returned IShellFolder interface is not AddRef'ed, so you should not call Release on the interface. This message is sent frequently by all microsoft namespace extensions and is the most important one. This message is described in the Microsoft Knowledge Base article Q157247.

CWM_TESTPATH

To be done.

CWM_STATECHANGE

To be done.

CWM_GETPATH

To be done.

FCIDLEPROC

typedef BOOL (CALLBACK *FCIDLEPROC)(void FAR *lpsv, UINT uID);

Description

This is the idle proc that will be called if you send CWM_WANTIDLE.

Paramaeters

Return value

Return non-zero if you want to continue idle time processing. The function will be called again.
Return zero if your idle-time processing has finished.

Remarks

you should make this function as short as possible. To perform multiple tasks, process one atomic task in every call and return non-zero until all jobs are finished.

Some helper functions

ShlExtInit

void ShlExtInit()

Description

Performs dynamic binding to the shell32 functions.

ShlExtUninit

void ShlExtUninit()

Description

Cleans up the dynamic binding that was set up by ShlExtInit.

ILCreate

LPITEMIDLIST ILCreate(LPVOID pData, DWORD dwLen)

Description

Allocates and initializes a simple pidl

Parameters

Return value

The newly created pidl

ILGetCount

int ILGetCount(LPCITEMIDLIST pidl)

Description

calculates teh number of item IDs in a complex pidl

Parameters

Return value

The number of item IDs that make up this complex pidl

PrintInterfaceName

void PrintInterfaceName(REFIID riid)

Description

Sends the name of an interface to the debugger
Useful to trace QueryInterface calls

Parameters

IsInterfaceSupported

BOOL IsInterfaceSupported(IUnknown *punk, REFIID riid)

Description

Determines wether an object supports a given interface

Parameters

Return value

Non-zero if the interface is supported, zero otherwise.

PrintSupportedInterfaces

void PrintSupportedInterfaces(IUnknown *punk)

Description

Sends the names of all interfaces of an object to the debugger.
When you receive an interface while debugging, this function can come in very handy.

Parameters

Implementing "View as Web Page"

You don't have to do anything in your code to implement a web view. You only have to create your web page and link your class id to it in the registry.

The web page

You should base your web page on the web pages that are created by Microsoft. On windows NT, you can find them in the directory winnt\web. A typical example is folder.htt, the web page for a normal folder. Just copy this web page and edit it to suit your needs.
There is one little problem: Microsoft changed the look of these web pages with every release of Windows, so you would have to provide separate web pages for all operating system versions.

Registry enteries

Explorer will rely on the class id that is returned by your IPersistFolder's GetClassID. As you know (and is very well documented), all information about your class is gathered in HKEY_CLASSES_ROOT\CLSID\{yourclassid}. There should already be a subkey shellex. In this shellex, you should create a subkey ExtShellFolderView, which again contains a subkey {5984FFE0-28D4-11CF-AE66-08002B2E1262}. In this subkey, you create an entry with the name PersistMoniker. It's value should be the full path of your web page.

References

Most of this stuff wasn't invented by me. You can find more information on the following locations:

You should also take a look at the shlext.h header file. It contains some information that is not included on this page.

Feedback

If you use the information on this page, you will probably discover things that are still missing here. You can see that there are lots of "to be done" bits. It is important to make that information available, so that you make the life of other developers a little easier. Please send me all your comments, sugestions and discoveries by email or leave comments on the codeproject site. All new discoveries will be available on my home page as soon as possible, and major updates will be posted on the codeproject site.