Nancy Winnick Cluts
Microsoft Developer Network Technology Group
Created: October 20, 1994
Click to open or copy the files in the SHORTCUT sample application for this technical article.
The next version of the Microsoft® Windows® operating system, Windows 95, has a new shell and a way to create shell links (also known as shortcuts) to items or objects in the shell. Shell links provide an easy method for users to access and manipulate objects regardless of the location and name of the object. For example, if a shell link is created to a text file, and if the original text file is subsequently renamed, the original shell link is updated by the shell without needing user intervention (that is, the user does not have to recreate the shell link). This is the second of two articles covering shell links. (The first article, "Using Shell Links in Windows 95," contains background information about shell links and discusses the method used to create and resolve them.) This article provides background information on IShellLink, the interface provided to create and manipulate shell links, and covers how the shell preserves links. A companion sample application for the two articles, SHORTCUT, implements a shell link.
The new shell in the next version of the Microsoft® Windows® operating system, Windows 95, uses an OLE interface to provide developers with functions (commonly known as methods in the object-oriented programming world) to manipulate shell links. An OLE interface provides easy methods for inserting, editing, viewing, and activating linked and embedded objects, and modifying the properties of objects. The interface that the shell defines to expose shell links is the IShellLink interface. This article details the methods exposed by the IShellLink interface and explains the heuristics that the shell uses to preserve a shell link to an object that has been renamed or moved.
The shell employs the use of object identifiers within the shell name space. All objects that are browsable by the shell (such as files, directories, servers, and workgroups) have an identifier that is unique among the objects within the parent folder. These identifiers are referred to as the Item IDs and are defined in the SHLOBJ.H file as SHITEMID. All parent folders also have their own item identifiers and can keep a list of items, known as an ID List (ITEMIDLIST in SHLOBJ.H).
ID Lists are allocated by the shell and may be passed across some of the shell interfaces (that is, IShellFolder). It is important to remember that each item identifier in an ID List is only meaningful within the context of the parent folder.
The IShellLink interface provides a group of methods that other applications can access to provide shell links within the application. These methods are exported via the vtable.
Syntax:
QueryInterface (REFIID riid, LPVOID FAR* ppvObj);
Parameters:
Description:
Returns a pointer to the requested interface, in this case the IShellLink interface, if the interface is supported. Otherwise, it returns an error. Once this pointer is retrieved, the application can use the pointer to gain access to the other functions or methods provided for the interface.
Syntax:
ULONG AddRef (void);
Parameters:
Description:
Increments a reference count for each new copy of an IShellLink interface pointer. The return value for this method is the value of the reference count. Many applications use this value for testing or diagnostic purposes. The reference count is decremented when the Release method is called.
Syntax:
ULONG Release ();
Parameters:
Description:
Decrements the reference count on the IShellLink interface. When the reference count reaches zero, the shell link object will be deleted and the pointer to the object will be invalid. This method returns the current reference count on the IShellLink object.
Syntax:
GetPath(LPSTR pszFile, int cchMaxPath, WIN32_FIND_DATA *pfd, DWORD fFlags);
Parameters:
Description:
Gets the current fully qualified path for the shell link object. The string containing the path is copied into the pszFile parameter. The pfd parameter is a pointer to the WIN32_FIND_DATA structure. This is the same information that is returned when making a call to FindFirstFile and FindNextFile, and includes the file’s attributes, creation time, and so on. The fFlags parameter supports two flags: SLGP_SHORTPATH, which returns the standard short (8.3) filename, and SLGP_UNCPRIORITY, which returns the Universal Naming Convention (UNC) path to the file.
Syntax:
SetPath (LPCSTR pszFile);
Parameter:
Description:
Sets the current path of the shell link object to the path specified by the pszFile parameter. For example, if an application is creating a shell link to a text file, STUFF.TXT, that resides in the C:\STUFF directory, the string passed to the SetPath method would be "C:\STUFF\STUFF.TXT".
Syntax:
GetIDList (LPCITEMIDLIST * ppidl);
Parameter:
Description:
Gets the current ID List for the shell link object.
Syntax:
SetIDList (LPCITEMIDLIST pidl);
Parameter:
Description:
Sets the ID List for the shell link object. This is useful when an application needs to set a shell link to an object that isn't a file, such as to Control Panel, another computer, or a printer.
Syntax:
GetDescription (LPSTR pszName, int cchMaxName);
Parameters:
Description:
Gets the description of the shell link object. The description string is copied into the buffer pointed to by the pszName parameter.
Syntax:
SetDescription (LPCSTR pszName);
Parameter:
Description:
Sets the description for the shell link object to the text provided in the pszName parameter. The description can be anything that the application chooses to provide. The description used by the SHORTCUT sample is simply "Shortcut to <FileName>".
Syntax:
GetWorkingDirectory (LPSTR pszDir, int cchMaxPath);
Parameters:
Description:
Gets the current working directory for the shell link object. The working directory will be copied into the string that is pointed to by the pszDir parameter. If the working directory is larger than the buffer provided, the string will be truncated (that is, the shell will copy, at most, the number of characters specified in the cchMaxPath parameter).
Syntax:
SetWorkingDirectory (LPCSTR pszDir);
Parameter:
Description:
Sets the current working directory for the shell link object to the path listed in the pszDir parameter. The working directory of the object needs to be set only if this is something that the link object requires. For example, if your application were to create a shell link to a Microsoft Word document that used a template or other objects that reside in a special directory, your application could set the working directory via this method.
Syntax:
GetArguments (LPSTR pszArgs, int cchMaxPath);
Parameters:
Description:
Gets the current arguments associated with the shell link object.
Syntax:
SetArguments (LPCSTR pszArgs);
Parameter:
Description:
Sets the arguments for the shell link object. This is useful in a case where you create a link to an application that takes special flags as arguments, such as a compiler.
Syntax:
GetHotkey (WORD *pwHotkey);
Parameter:
Description:
Gets the hot key for the shell link object.
Syntax:
SetHotkey (WORD wHotkey);
Parameter:
Description:
Sets the hot key for the shell link object. This allows you to specify that your shell link should be invoked whenever a special hot key is pressed. For example, you could set up a shell link to a utility that will back up a specific directory whenever the user presses a key combination such as <ALT>+<B>.
Syntax:
GetShowCmd (int *piShowCmd);
Parameters:
Description:
Gets the show command for the shell link object.
Syntax:
SetShowCmd (int iShowCmd);
Parameter:
Description:
Sets the show command for the shell link object. The show command is the show state of the window a la WinMain and can be one of the following:
SW_HIDE | Hide the window. |
SW_MINIMIZE | Minimize the window. |
SW_RESTORE | Activate and display the window. If the window had been previously maximized or minimized, the window will be restored to its original size and position. |
SW_SHOW | Activate the window in its current size and position. |
SW_SHOWMAXIMIZED | Activate and maximize the window. |
SW_SHOWMINIMIZED | Activate and minimize the window. |
SW_SHOWNA | Show the window in its current state, but do not activate it. |
SW_SHOWNOACTIVE | Show the window in its most recent size and position, but do not activate it. |
SW_SHOWNORMAL | Activate and display the window. This style also includes the SW_RESTORE option and will restore the window to its original size and position. |
Syntax:
GetIconLocation (LPSTR pszIconPath, int cchIconPath, int *piIcon);
Parameters:
Description:
Gets the icon location for the shell link object.
Syntax:
SetIconLocation (LPCSTR pszIconPath, int iIcon);
Parameters:
Description:
Sets the location for the shell link icon. If you want to change the icon for the shell link object, use the SetIconLocation method.
Syntax:
Resolve (HWND hwnd, UINT fFlags);
Parameters:
Description:
Resolves a shell link. The system searches for the shell link object and updates the shell link path and its ID List, if necessary. For more detailed information about how the shell resolves links to objects that have been moved or renamed, please refer to the following section, "How Shell Links Are Preserved." If the shell needs to post a dialog box prompting the user for more information, it will use the handle to the window passed in the hwnd parameter as the parent window of the dialog box. The supported flags for this method are:
SLR_NO_UI | Directs to shell not to display a dialog box if it cannot resolve the shell link. |
SLR_UPDATE | When the resolve method is called, the shell marks a link as "dirty" if the object the link points to has changed (date, location, size, and so on). This flag directs the shell to save the link if the link object has been changed. The developer is thus saved the step of calling IPersistFile::IsDirty to determine whether the link has changed. |
One of the nice things that the shell does for you with shell links is automatically attempt to resolve shell links whose targets have been renamed or moved. When a shell link is created, the shell saves information about the link. Most of this information is the same information found in the WIN32_FIND_DATA structure (that is, file attributes, creation time, last access time, last write time, and file size). When the IShellLink::Resolve method is called, the first thing the shell does is to simply get the path associated with the current link via a pointer to its ID List. The shell searches for the link object in that path and, if it finds it, resolves the link.
If the link object is not found, the shell first looks for an object with the same file creation time and attributes in the same directory but with a different name. This will resolve a link to an object that has been renamed.
If the link object is still not found, the system first searches the subdirectories of the current directory. It will continue recursively searching the directory tree looking for a match with either the name or the creation time. If it does not find a match, it will ultimately display a dialog box prompting the user for a location (a browse button). An application can suppress the dialog box by specifying the SLR_NO_UI flag when it calls the Resolve method.
You now should have the information you need to create and manipulate shell links programmatically in your application. The IShellLink interface provides the methods you need. You can use some or all of the methods—it's your choice. The information given here is based upon preliminary information (on a beta operating system, no less) and is subject to change before the final release of Windows 95. It is also worth noting that the IShellLink interface is provided for the Windows 95 shell, and the steps you take here to fully exploit the Windows 95 shell may not be the exact same steps that you would take in exploiting the shell of future operating systems.