www.pudn.com > yrsCapture.zip > shellobj.pas
Unit ShellOBJ;
interface
uses
Windows,
Messages,
OLE2,
COMMCTRL,
ShellAPI,
REGSTR;
{=========================================================================== }
{ Object identifiers in the explorer's name space (ItemID and IDList) }
{ All the items that the user can browse with the explorer (such as files, }
{ directories, servers, work-groups, etc.) has an identifier which is unique }
{ among items within the parent folder. Those identifiers are called item }
{ IDs (SHITEMID). Since all its parent folders have their own item IDs, }
{ any items can be uniquely identified by a list of item IDs, which is called }
{ an ID list (ITEMIDLIST). }
{ ID lists are almost always allocated by the task allocator (see some }
{ description below as well as OLE 2.0 SDK) and may be passed across }
{ some of shell interfaces (such as IShellFolder). Each item ID in an ID list }
{ is only meaningful to its parent folder (which has generated it), and all }
{ the clients must treat it as an opaque binary data except the first two }
{ bytes, which indicates the size of the item ID. }
{ When a shell extension -- which implements the IShellFolder interace -- }
{ generates an item ID, it may put any information in it, not only the data }
{ with that it needs to identifies the item, but also some additional }
{ information, which would help implementing some other functions efficiently. }
{ For example, the shell's IShellFolder implementation of file system items }
{ stores the primary (long) name of a file or a directory as the item }
{ identifier, but it also stores its alternative (short) name, size and date }
{ etc. }
{ When an ID list is passed to one of shell APIs (such as SHGetPathFromIDList), }
{ it is always an absolute path -- relative from the root of the name space, }
{ which is the desktop folder. When an ID list is passed to one of IShellFolder }
{ member function, it is always a relative path from the folder (unless it }
{ is explicitly specified). }
const
CLSID_ShellDesktop: TGUID = (
D1:$00021400; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
CLSID_ShellLink: TGUID = (
D1:$00021401; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IContextMenu : TGUID = (
D1:$000214E4; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IShellFolder : TGUID = (
D1:$000214E6; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IShellExtInit : TGUID = (
D1:$000214E8; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IShellPropSheetExt : TGUID = (
D1:$000214E9; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IExtractIcon : TGUID = (
D1:$000214EB; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IShellLink : TGUID = (
D1:$000214EE; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IShellCopyHook : TGUID = (
D1:$000214EF; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IFileViewer : TGUID = (
D1:$000214F0; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IEnumIDList : TGUID = (
D1:$000214F2; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
IID_IFileViewerSite : TGUID = (
D1:$000214F3; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
{ SHITEMID -- Item ID }
type
PSHItemID = ^TSHItemID;
TSHItemID = record { mkid }
cb:word; { Size of the ID (including cb itself) }
abID:array[0..0] of BYTE; { The item ID (variable length) }
end;
{ ITEMIDLIST -- List if item IDs (combined with 0-terminator) }
PItemIDList = ^TItemIDList;
TItemIDList = record { idl }
mkid: TSHITEMID;
end;
{=========================================================================== }
{ Task allocator API }
{ All the shell extensions MUST use the task allocator (see OLE 2.0 }
{ programming guild for its definition) when they allocate or free }
{ memory objects (mostly ITEMIDLIST) that are returned across any }
{ shell interfaces. There are two ways to access the task allocator }
{ from a shell extension depending on whether or not it is linked with }
{ OLE32.DLL or not (virtual; stdcall; abstractly for efficiency). }
{ (1) A shell extension which calls any OLE API (i.e., linked with }
{ OLE32.DLL) should call OLE's task allocator (by retrieving }
{ the task allocator by calling CoGetMalloc API). }
{ (2) A shell extension which does not call any OLE API (i.e., not linked }
{ with OLE32.DLL) should call the shell task allocator API (defined }
{ below), so that the shell can quickly loads it when OLE32.DLL is not }
{ loaded by any application at that point. }
{ Notes: }
{ In next version of Windowso release, SHGetMalloc will be replaced by }
{ the following macro. }
{ #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem) }
{=========================================================================== }
function SHGetMalloc(var ppMalloc: IMALLOC):HResult;
{=========================================================================== }
{ IContextMenu interface }
{ [OverView] }
{ The shell uses the IContextMenu interface in following three cases. }
{ case-1: The shell is loading context menu extensions. }
{ When the user clicks the right mouse button on an item within the shell's }
{ name space (i.g., file, directory, server, work-group, etc.), it creates }
{ the default context menu for its type, then loads context menu extensions }
{ that are registered for that type (and its base type) so that they can }
{ add extra menu items. Those context menu extensions are registered at }
{ HKCR\beginProgIDend\shellex\ContextMenuHandlers. }
{ case-2: The shell is retrieving a context menu of sub-folders in extended }
{ name-space. }
{ When the explorer's name space is extended by name space extensions, }
{ the shell calls their IShellFolder::GetUIObjectOf to get the IContextMenu }
{ objects when it creates context menus for folders under those extended }
{ name spaces. }
{ case-3: The shell is loading non-default drag and drop handler for directories. }
{ When the user performed a non-default drag and drop onto one of file }
{ system folders (i.e., directories), it loads shell extensions that are }
{ registered at HKCR\beginProgIDend\DragDropHandlers. }
{ [Member functions] }
{ IContextMenu::QueryContextMenu }
{ This member function may insert one or more menuitems to the specified }
{ menu (hmenu) at the specified location (indexMenu which is never be -1). }
{ The IDs of those menuitem must be in the specified range (idCmdFirst and }
{ idCmdLast). It returns the maximum menuitem ID offset (ushort) in the }
{ 'code' field (low word) of the scode. }
{ The uFlags specify the context. It may have one or more of following }
{ flags. }
{ CMF_DEFAULTONLY: This flag is passed if the user is invoking the default }
{ action (typically by double-clicking, case 1 and 2 only). Context menu }
{ extensions (case 1) should not add any menu items, and returns NOERROR. }
{ CMF_VERBSONLY: The explorer passes this flag if it is constructing }
{ a context menu for a short-cut object (case 1 and case 2 only). If this }
{ flag is passed, it should not add any menu-items that is not appropriate }
{ from a short-cut. }
{ A good example is the 'Delete' menuitem, which confuses the user }
{ because it is not clear whether it deletes the link source item or the }
{ link itself. }
{ CMF_EXPLORER: The explorer passes this flag if it has the left-side pane }
{ (case 1 and 2 only). Context menu extensions should ignore this flag. }
{ High word (16-bit) are reserved for context specific communications }
{ and the rest of flags (13-bit) are reserved by the system. }
{ IContextMenu::InvokeCommand }
{ This member is called when the user has selected one of menuitems that }
{ are inserted by previous QueryContextMenu member. In this case, the }
{ LOWORD(lpici->lpVerb) contains the menuitem ID offset (menuitem ID - }
{ idCmdFirst). }
{ This member function may also be called programmatically. In such a case, }
{ lpici->lpVerb specifies the canonical name of the command to be invoked, }
{ which is typically retrieved by GetCommandString member previously. }
{ Parameters in lpci: }
{ cbSize -- Specifies the size of this structure (sizeof(*lpci)) }
{ hwnd -- Specifies the owner window for any message/dialog box. }
{ fMask -- Specifies whether or not dwHotkey/hIcon paramter is valid. }
{ lpVerb -- Specifies the command to be invoked. }
{ lpParameters -- Parameters (optional) }
{ lpDirectory -- Working directory (optional) }
{ nShow -- Specifies the flag to be passed to ShowWindow (SW_*). }
{ dwHotKey -- Hot key to be assigned to the app after invoked (optional). }
{ hIcon -- Specifies the icon (optional). }
{ IContextMenu::GetCommandString }
{ This member function is called by the explorer either to get the }
{ canonical (language independent) command name (uFlags == GCS_VERB) or }
{ the help text ((uFlags & GCS_HELPTEXT) != 0) for the specified command. }
{ The retrieved canonical string may be passed to its InvokeCommand }
{ member function to invoke a command programmatically. The explorer }
{ displays the help texts in its status bar; therefore, the length of }
{ the help text should be reasonably short (<40 characters). }
{ Parameters: }
{ idCmd -- Specifies menuitem ID offset (from idCmdFirst) }
{ uFlags -- Either GCS_VERB or GCS_HELPTEXT }
{ pwReserved -- Reserved (must pass NULL when calling, must ignore when called) }
{ pszName -- Specifies the string buffer. }
{ cchMax -- Specifies the size of the string buffer. }
{=========================================================================== }
const
{ QueryContextMenu uFlags }
CMF_NORMAL = $00000000;
CMF_DEFAULTONLY = $00000001;
CMF_VERBSONLY = $00000002;
CMF_EXPLORE = $00000004;
CMF_RESERVED = $ffff0000 { View specific };
{ GetCommandString uFlags }
GCS_VERB =$00000000 { canonical verb };
GCS_HELPTEXT =$00000001 { help text (for status bar) };
GCS_VALIDATE =$00000002 { validate command exists };
CMDSTR_NEWFOLDER = 'NewFolder';
CMDSTR_VIEWLIST = 'ViewList';
CMDSTR_VIEWDETAILS = 'ViewDetails';
CMIC_MASK_HOTKEY = SEE_MASK_HOTKEY;
CMIC_MASK_ICON = SEE_MASK_ICON;
CMIC_MASK_FLAG_NO_UI = SEE_MASK_FLAG_NO_UI;
CMIC_MASK_MODAL =$80000000 (* ; Internal *);
(*!! CMIC_VALID_SEE_FLAGS = SEE_VALID_CMIC_FLAGS; (* ; Internal *)
type
PCMInvokeCommandInfo = ^TCMInvokeCommandInfo;
TCMInvokeCommandInfo = record
cbSize:DWORD; { must be sizeof(CMINVOKECOMMANDINFO) }
fMask:DWORD; { any combination of CMIC_MASK_* }
hwnd:HWND; { might be NULL (indicating no owner window) }
lpVerb:LPCSTR; { either a string of MAKEINTRESOURCE(idOffset) }
lpParameters:LPCSTR; { might be NULL (indicating no parameter) }
lpDirectory:LPCSTR; { might be NULL (indicating no specific directory) }
nShow:integer; { one of SW_ values for ShowWindow() API }
dwHotKey:DWORD;
hIcon:THANDLE;
end;
IContextMenu = class(IUnknown)
function QueryContextMenu(Menu:HMENU; indexMenu:UINT;
idCmdFirst:UINT;idCmdLast:UINT;
uFlags:UINT):HResult; virtual; stdcall; abstract;
function InvokeCommand(lpici: PCMINVOKECOMMANDINFO): HResult; virtual; stdcall; abstract;
function GetCommandString(idCmd:UINT; uType:UINT; var pwReserved:UINT;
pszName:LPSTR; cchMax:UINT):HResult; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ Interface: IShellExtInit }
{ The IShellExtInit interface is used by the explorer to initialize shell }
{ extension objects. The explorer (1) calls CoCreateInstance (or equivalent) }
{ with the registered CLSID and IID_IShellExtInit, (2) calls its Initialize }
{ member, then (3) calls its QueryInterface to a particular interface (such }
{ as IContextMenu or IPropSheetExt and (4) performs the rest of operation. }
{ [Member functions] }
{ IShellExtInit::Initialize }
{ This member function is called when the explorer is initializing either }
{ context menu extension, property sheet extension or non-default drag-drop }
{ extension. }
{ Parameters: (context menu or property sheet extension) }
{ pidlFolder -- Specifies the parent folder }
{ lpdobj -- Spefifies the set of items selected in that folder. }
{ hkeyProgID -- Specifies the type of the focused item in the selection. }
{ Parameters: (non-default drag-and-drop extension) }
{ pidlFolder -- Specifies the target (destination) folder }
{ lpdobj -- Specifies the items that are dropped (see the description }
{ about shell's clipboard below for clipboard formats). }
{ hkeyProgID -- Specifies the folder type. }
{=========================================================================== }
type
IShellExtInit = class(IUnknown)
function Initialize(pidlFolder:PItemIDList;
lpdobj: IDataObject;
hKeyProgID:HKEY):HResult; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ Interface: IShellPropSheetExt }
{ The explorer uses the IShellPropSheetExt to allow property sheet }
{ extensions or control panel extensions to add additional property }
{ sheet pages. }
{ [Member functions] }
{ IShellPropSheetExt::AddPages }
{ The explorer calls this member function when it finds a registered }
{ property sheet extension for a particular type of object. For each }
{ additional page, the extension creates a page object by calling }
{ CreatePropertySheetPage API and calls lpfnAddPage. }
{ Parameters: }
{ lpfnAddPage -- Specifies the callback function. }
{ lParam -- Specifies the opaque handle to be passed to the callback function. }
{ IShellPropSheetExt::ReplacePage }
{ The explorer never calls this member of property sheet extensions. The }
{ explorer calls this member of control panel extensions, so that they }
{ can replace some of default control panel pages (such as a page of }
{ mouse control panel). }
{ Parameters: }
{ uPageID -- Specifies the page to be replaced. }
{ lpfnReplace Specifies the callback function. }
{ lParam -- Specifies the opaque handle to be passed to the callback function. }
{=========================================================================== }
type
IShellPropSheetExt = class(IUnknown)
function AddPages(lpfnAddPage: TFNADDPROPSHEETPAGE; lParam:LPARAM):HResult; virtual; stdcall; abstract;
function ReplacePage(uPageID:UINT;
lpfnReplaceWith:TFNADDPROPSHEETPAGE;
lParam:LPARAM):HResult; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ IExtractIcon interface }
{ This interface is used in two different places in the shell. }
{ Case-1: Icons of sub-folders for the scope-pane of the explorer. }
{ It is used by the explorer to get the 'icon location' of }
{ sub-folders from each shell folders. When the user expands a folder }
{ in the scope pane of the explorer, the explorer does following: }
{ (1) binds to the folder (gets IShellFolder), }
{ (2) enumerates its sub-folders by calling its EnumObjects member, }
{ (3) calls its GetUIObjectOf member to get IExtractIcon interface }
{ for each sub-folders. }
{ In this case, the explorer uses only IExtractIcon::GetIconLocation }
{ member to get the location of the appropriate icon. An icon location }
{ always consists of a file name (typically DLL or EXE) and either an icon }
{ resource or an icon index. }
{ Case-2: Extracting an icon image from a file }
{ It is used by the shell when it extracts an icon image }
{ from a file. When the shell is extracting an icon from a file, }
{ it does following: }
{ (1) creates the icon extraction handler object (by getting its CLSID }
{ under the beginProgIDend\shell\ExtractIconHanler key and calling }
{ CoCreateInstance requesting for IExtractIcon interface). }
{ (2) Calls IExtractIcon::GetIconLocation. }
{ (3) Then, calls IExtractIcon::Extract with the location/index pair. }
{ (4) If (3) returns NOERROR, it uses the returned icon. }
{ (5) Otherwise, it recursively calls this logic with new location }
{ assuming that the location string contains a fully qualified path name. }
{ From extension programmer's point of view, there are only two cases }
{ where they provide implementations of IExtractIcon: }
{ Case-1) providing explorer extensions (i.e., IShellFolder). }
{ Case-2) providing per-instance icons for some types of files. }
{ Because Case-1 is described above, we'll explain only Case-2 here. }
{ When the shell is about display an icon for a file, it does following: }
{ (1) Finds its ProgID and ClassID. }
{ (2) If the file has a ClassID, it gets the icon location string from the }
{ 'DefaultIcon' key under it. The string indicates either per-class }
{ icon (e.g., 'FOOBAR.DLL,2') or per-instance icon (e.g., '%1,1'). }
{ (3) If a per-instance icon is specified, the shell creates an icon }
{ extraction handler object for it, and extracts the icon from it }
{ (which is described above). }
{ It is important to note that the shell calls IExtractIcon::GetIconLocation }
{ first, then calls IExtractIcon::Extract. Most application programs }
{ that support per-instance icons will probably store an icon location }
{ (DLL/EXE name and index/id) rather than an icon image in each file. }
{ In those cases, a programmer needs to implement only the GetIconLocation }
{ member and it Extract member simply returns S_FALSE. They need to }
{ implement Extract member only if they decided to store the icon images }
{ within files themselved or some other database (which is very rare). }
{ [Member functions] }
{ IExtractIcon::GetIconLocation }
{ This function returns an icon location. }
{ Parameters: }
{ uFlags [in] -- Specifies if it is opened or not (GIL_OPENICON or 0) }
{ szIconFile [out] -- Specifies the string buffer buffer for a location name. }
{ cchMax [in] -- Specifies the size of szIconFile (almost always MAX_PATH) }
{ piIndex [out] -- Sepcifies the address of UINT for the index. }
{ pwFlags [out] -- Returns GIL_* flags }
{ Returns: }
{ NOERROR, if it returns a valid location; S_FALSE, if the shell use a }
{ default icon. }
{ Notes: The location may or may not be a path to a file. The caller can }
{ not assume anything unless the subsequent Extract member call returns }
{ S_FALSE. }
{ if the returned location is not a path to a file, GIL_NOTFILENAME should }
{ be set in the returned flags. }
{ IExtractIcon::Extract }
{ This function extracts an icon image from a specified file. }
{ Parameters: }
{ pszFile [in] -- Specifies the icon location (typically a path to a file). }
{ nIconIndex [in] -- Specifies the icon index. }
{ phiconLarge [out] -- Specifies the HICON variable for large icon. }
{ phiconSmall [out] -- Specifies the HICON variable for small icon. }
{ nIconSize [in] -- Specifies the size icon required (size of large icon) }
{ LOWORD is the requested large icon size }
{ HIWORD is the requested small icon size }
{ Returns: }
{ NOERROR, if it extracted the from the file. }
{ S_FALSE, if the caller should extract from the file specified in the }
{ location. }
{=========================================================================== }
{ GetIconLocation() input flags }
const
GIL_OPENICON =$0001 { allows containers to specify an 'open' look };
GIL_FORSHELL =$0002 { icon is to be displayed in a ShellFolder };
{ GetIconLocation() return flags }
GIL_SIMULATEDOC =$0001 { simulate this document icon for this };
GIL_PERINSTANCE =$0002 { icons from this class are per instance (each file has its own) };
GIL_PERCLASS =$0004 { icons from this class per class (shared for all files of this type) };
GIL_NOTFILENAME =$0008 { location is not a filename, must call ::Extract };
GIL_DONTCACHE =$0010 { this icon should not be cached };
type
IExtractIcon = class(IUnknown) { exic }
function GetIconLocation(uFlags:UINT; szIconFile:LPSTR; cchMax:UINT;
var piIndex:integer;
var pwFlags:UINT):HResult; virtual; stdcall; abstract;
function Extract(pszFile:LPCSTR; nIconIndex:UINT; var phiconLarge:HICON;
var phiconSmall:HICON;
nIconSize:UINT):HResult; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ IShellLink Interface }
{=========================================================================== }
const
{ IShellLink::Resolve fFlags }
SLR_NO_UI = $0001;
SLR_ANY_MATCH = $0002;
SLR_UPDATE = $0004;
{ IShellLink::GetPath fFlags }
SLGP_SHORTPATH = $0001;
SLGP_UNCPRIORITY = $0002;
type
IShellLink = class(IUnknown) { sl }
function GetPath(pszFile:LPSTR; cchMaxPath:integer;
var pfd:TWin32FindData;
fFlags:DWORD):HResult; virtual; stdcall; abstract;
function GetIDList(var ppidl:PITEMIDLIST):HResult; virtual; stdcall; abstract;
function SetIDList(pidl:PITEMIDLIST):HResult; virtual; stdcall; abstract;
function GetDescription(pszName:LPSTR; cchMaxName:integer):HResult; virtual; stdcall; abstract;
function SetDescription(pszName:LPSTR):HResult; virtual; stdcall; abstract;
function GetWorkingDirectory(pszDir:LPSTR; cchMaxPath:integer):HResult; virtual; stdcall; abstract;
function SetWorkingDirectory(pszDir:LPSTR):HResult; virtual; stdcall; abstract;
function GetArguments(pszArgs:LPSTR; cchMaxPath:integer):HResult; virtual; stdcall; abstract;
function SetArguments(pszArgs:LPSTR):HResult; virtual; stdcall; abstract;
function GetHotkey(var pwHotkey:word):HResult; virtual; stdcall; abstract;
function SetHotkey(wHotkey:word):HResult; virtual; stdcall; abstract;
function GetShowCmd(var piShowCmd:integer):HResult; virtual; stdcall; abstract;
function SetShowCmd(iShowCmd:integer):HResult; virtual; stdcall; abstract;
function GetIconLocation(pszIconPath:LPSTR; cchIconPath:integer;
var piIcon:integer):HResult; virtual; stdcall; abstract;
function SetIconLocation(pszIconPath:LPSTR; iIcon:integer):HResult; virtual; stdcall; abstract;
function SetRelativePath(pszPathRel:LPSTR; dwReserved:DWORD):HResult; virtual; stdcall; abstract;
function Resolve(Wnd:HWND; fFlags: DWORD):HResult; virtual; stdcall; abstract;
function SetPath(pszFile:LPSTR):HResult; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ ICopyHook Interface }
{ The copy hook is called whenever file system directories are }
{ copy/moved/deleted/renamed via the shell. It is also called by the shell }
{ on changes of status of printers. }
{ Clients register their id under STRREG_SHEX_COPYHOOK for file system hooks }
{ and STRREG_SHEx_PRNCOPYHOOK for printer hooks. }
{ the CopyCallback is called prior to the action, so the hook has the chance }
{ to allow, deny or cancel the operation by returning the falues: }
{ IDYES - means allow the operation }
{ IDNO - means disallow the operation on this file, but continue with }
{ any other operations (eg. batch copy) }
{ IDCANCEL - means disallow the current operation and cancel any pending }
{ operations }
{ arguments to the CopyCallback }
{ hwnd - window to use for any UI }
{ wFunc - what operation is being done }
{ wFlags - and flags (FOF_*) set in the initial call to the file operation }
{ pszSrcFile - name of the source file }
{ dwSrcAttribs - file attributes of the source file }
{ pszDestFile - name of the destiation file (for move and renames) }
{ dwDestAttribs - file attributes of the destination file }
{=========================================================================== }
type
ICopyHook = class(IUnknown) { sl }
function CopyCallback(Wnd:HWND;wFunc:UINT; wFlags:UINT;
pszSrcFile:LPSTR; dwSrcAttribs:DWORD;
pszDestFile:LPSTR; dwDestAttribs:DWORD):UINT; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ IFileViewerSite Interface }
{=========================================================================== }
type
IFileViewerSite = class(IUnknown)
function SetPinnedWindow(Wnd:HWND):HResult; virtual; stdcall; abstract;
function GetPinnedWindow(var Wnd:HWND):HResult; virtual; stdcall; abstract;
end;
{=========================================================================== }
{ IFileViewer Interface }
{ Implemented in a FileViewer component object. Used to tell a }
{ FileViewer to PrintTo or to view, the latter happening though }
{ ShowInitialize and Show. The filename is always given to the }
{ viewer through IPersistFile. }
{=========================================================================== }
type
PFVShowInfo = ^TFVShowInfo;
TFVShowInfo = record
{ Stuff passed into viewer (in) }
cbSize:DWORD; { Size of structure for future expansion... }
hwndOwner:HWND; { who is the owner window. }
iShow:integer; { The show command }
{ Passed in and updated (in/Out) }
dwFlags:DWORD; { flags }
rect:TRECT; { Where to create the window may have defaults }
punkRel:IUNKNOWN; { Relese this interface when window is visible }
{ Stuff that might be returned from viewer (out) }
strNewFile:array[0..MAX_PATH-1] of TOLECHAR; { New File to view. }
end;
{ Define File View Show Info Flags. }
const
FVSIF_RECT =$00000001 { The rect variable has valid data. };
FVSIF_PINNED =$00000002 { We should Initialize pinned };
FVSIF_NEWFAILED =$08000000 { The new file passed back failed };
{ to be viewed. }
FVSIF_NEWFILE =$80000000 { A new file to view has been returned };
FVSIF_CANVIEWIT =$40000000 { The viewer can view it. };
type
IFileViewer = class(IUnknown)
function ShowInitialize(fsi:IFILEVIEWERSITE):HResult; virtual; stdcall; abstract;
function Show(pvsi:PFVSHOWINFO):HResult; virtual; stdcall; abstract;
function PrintTo(pszDriver:LPSTR; fSuppressUI:BOOL):HResult; virtual; stdcall; abstract;
end;
{------------------------------------------------------------------------- }
{ struct STRRET }
{ structure for returning strings from IShellFolder member functions }
{------------------------------------------------------------------------- }
const
STRRET_WSTR =$0000;
STRRET_OFFSET =$0001;
STRRET_CSTR =$0002;
type
PSTRRet = ^TStrRet;
TSTRRET = record
uType:UINT; { One of the STRRET_* values }
case integer of
0:(pOleStr:LPWSTR); { OLESTR that will be freed }
1:(uOffset:UINT); { Offset into SHITEMID (ANSI) }
2:(cStr: array[0..MAX_PATH-1] of char); { Buffer to fill in }
end;
{------------------------------------------------------------------------- }
{ SHGetPathFromIDList }
{ This function assumes the size of the buffer (MAX_PATH). The pidl }
{ should point to a file system object. }
{------------------------------------------------------------------------- }
function SHGetPathFromIDList(pidl:PITEMIDLIST; pszPath:LPSTR):BOOL; stdcall;
{------------------------------------------------------------------------- }
{ SHGetSpecialFolderLocation }
{ Caller should call SHFree to free the returned pidl. }
{------------------------------------------------------------------------- }
{ registry entries for special paths are kept in : }
const
REGSTR_PATH_SPECIAL_FOLDERS = REGSTR_PATH_EXPLORER+'\Shell Folders';
CSIDL_DESKTOP =$0000;
CSIDL_PROGRAMS =$0002;
CSIDL_CONTROLS =$0003;
CSIDL_PRINTERS =$0004;
CSIDL_PERSONAL =$0005;
CSIDL_FAVORITES =$0006;
CSIDL_STARTUP =$0007;
CSIDL_RECENT =$0008;
CSIDL_SENDTO =$0009;
CSIDL_BITBUCKET =$000a;
CSIDL_STARTMENU =$000b;
CSIDL_DESKTOPDIRECTORY =$0010;
CSIDL_DRIVES =$0011;
CSIDL_NETWORK =$0012;
CSIDL_NETHOOD =$0013;
CSIDL_FONTS =$0014;
CSIDL_TEMPLATES =$0015;
function SHGetSpecialFolderLocation(hwndOwner:HWND; nFolder:integer;
var ppidl:PITEMIDLIST):HResult; stdcall;
{------------------------------------------------------------------------- }
{ SHBrowseForFolder API }
{------------------------------------------------------------------------- }
type
BFFCALLBACK = function(Wnd:HWND;uMsg:UINT;lParam,lpData:LPARAM):integer stdcall;
PBrowseInfo = ^TBrowseInfo;
TBrowseInfo = record
hwndOwner:HWND;
pidlRoot:PITEMIDLIST;
pszDisplayName:LPSTR; { Return display name of item selected. }
lpszTitle:LPCSTR; { text to go in the banner over the tree. }
ulFlags:UINT; { Flags that control the return stuff }
lpfn:BFFCALLBACK;
lParam:LPARAM; { extra info that's passed back in callbacks }
iImage:integer; { output var: where to return the Image index. }
end;
const
{ Browsing for directory. }
BIF_RETURNONLYFSDIRS =$0001 { For finding a folder to start document searching };
BIF_DONTGOBELOWDOMAIN =$0002 { For starting the Find Computer };
BIF_STATUSTEXT =$0004;
BIF_RETURNFSANCESTORS =$0008;
BIF_BROWSEFORCOMPUTER =$1000 { Browsing for Computers. };
BIF_BROWSEFORPRINTER =$2000 { Browsing for Printers };
{ message from browser }
BFFM_INITIALIZED = 1;
BFFM_SELCHANGED = 2;
{ messages to browser }
BFFM_SETSTATUSTEXT =(WM_USER + 100);
BFFM_ENABLEOK =(WM_USER + 101);
BFFM_SETSELECTION =(WM_USER + 102);
function SHBrowseForFolder(lpbi:PBROWSEINFO):PItemIDList; stdcall;
{------------------------------------------------------------------------- }
{ SHLoadInProc }
{ When this function is called, the shell calls CoCreateInstance }
{ (or equivalent) with CLSCTX_INPROC_SERVER and the specified CLSID }
{ from within the shell's process and release it immediately. }
{------------------------------------------------------------------------- }
function SHLoadInProc(rclsid:TCLSID):HRESULT; stdcall;
{------------------------------------------------------------------------- }
{ IEnumIDList interface }
{ IShellFolder::EnumObjects member returns an IEnumIDList object. }
{------------------------------------------------------------------------- }
type
IEnumIDList = class(IUnknown)
function Next( celt:ULONG;
var rgelt: PITEMIDLIST;
var pceltFetched:ULONG):HResult; virtual; stdcall; abstract;
function Skip(celt:ULONG):HResult; virtual; stdcall; abstract;
function Reset:HResult; virtual; stdcall; abstract;
function Clone(var ppenum:IEnumIDList):HResult; virtual; stdcall; abstract;
end;
{------------------------------------------------------------------------- }
{ IShellFolder interface }
{ [Member functions] }
{ IShellFolder::BindToObject(pidl, pbc, riid, ppvOut) }
{ This function returns an instance of a sub-folder which is specified }
{ by the IDList (pidl). }
{ IShellFolder::BindToStorage(pidl, pbc, riid, ppvObj) }
{ This function returns a storage instance of a sub-folder which is }
{ specified by the IDList (pidl). The shell never calls this member }
{ function in the first release of Win95. }
{ IShellFolder::CompareIDs(lParam, pidl1, pidl2) }
{ This function compares two IDLists and returns the result. The shell }
{ explorer always passes 0 as lParam, which indicates 'sort by name'. }
{ It should return 0 (as CODE of the scode), if two id indicates the }
{ same object; negative value if pidl1 should be placed before pidl2; }
{ positive value if pidl2 should be placed before pidl1. }
{ IShellFolder::CreateViewObject(hwndOwner, riid, ppvOut) }
{ This function creates a view object of the folder itself. The view }
{ object is a difference instance from the shell folder object. }
{ IShellFolder::GetAttributesOf(cidl, apidl, prgfInOut) }
{ This function returns the attributes of specified objects in that }
{ folder. 'cidl' and 'apidl' specifies objects. 'apidl' contains only }
{ simple IDLists. The explorer initializes *prgfInOut with a set of }
{ flags to be evaluated. The shell folder may optimize the operation }
{ by not returning unspecified flags. }
{ IShellFolder::GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut) }
{ This function creates a UI object to be used for specified objects. }
{ The shell explorer passes either IID_IDataObject (for transfer operation) }
{ or IID_IContextMenu (for context menu operation) as riid. }
{ IShellFolder::GetDisplayNameOf }
{ This function returns the display name of the specified object. }
{ If the ID contains the display name (in the locale character set), }
{ it returns the offset to the name. Otherwise, it returns a pointer }
{ to the display name string (UNICODE), which is allocated by the }
{ task allocator, or fills in a buffer. }
{ IShellFolder::SetNameOf }
{ This function sets the display name of the specified object. }
{ If it changes the ID as well, it returns the new ID which is }
{ alocated by the task allocator. }
{------------------------------------------------------------------------- }
const
{ IShellFolder::GetDisplayNameOf/SetNameOf uFlags }
SHGDN_NORMAL = 0; { default (display purpose) }
SHGDN_INFOLDER = 1; { displayed under a folder (relative) }
SHGDN_FORPARSING = $8000; { for ParseDisplayName or path }
{ IShellFolder::EnumObjects }
SHCONTF_FOLDERS = 32; { for shell browser }
SHCONTF_NONFOLDERS = 64; { for default view }
SHCONTF_INCLUDEHIDDEN = 128; { for hidden/system objects }
{ IShellFolder::GetAttributesOf flags }
SFGAO_CANCOPY = DROPEFFECT_COPY { Objects can be copied };
SFGAO_CANMOVE = DROPEFFECT_MOVE { Objects can be moved };
SFGAO_CANLINK = DROPEFFECT_LINK { Objects can be linked };
SFGAO_CANRENAME =$00000010 { Objects can be renamed };
SFGAO_CANDELETE =$00000020 { Objects can be deleted };
SFGAO_HASPROPSHEET =$00000040 { Objects have property sheets };
SFGAO_DROPTARGET =$00000100 { Objects are drop target };
SFGAO_CAPABILITYMASK =$00000177;
SFGAO_LINK =$00010000 { Shortcut (link) };
SFGAO_SHARE =$00020000 { shared };
SFGAO_READONLY =$00040000 { read-only };
SFGAO_GHOSTED =$00080000 { ghosted icon };
SFGAO_DISPLAYATTRMASK =$000F0000;
SFGAO_FILESYSANCESTOR =$10000000 { It contains file system folder };
SFGAO_FOLDER =$20000000 { It's a folder. };
SFGAO_FILESYSTEM =$40000000 { is a file system thing (file/folder/root) };
SFGAO_HASSUBFOLDER =$80000000 { Expandable in the map pane };
SFGAO_CONTENTSMASK =$80000000;
SFGAO_VALIDATE =$01000000 { invalidate cached information };
SFGAO_REMOVABLE =$02000000 { is this removeable media? };
type
IShellFolder = class(IUnknown)
function ParseDisplayName(hwndOwner:HWND;
pbcReserved:{LPBC}pointer; lpszDisplayName:POLESTR;
var pchEaten:ULONG; var ppidl:PITEMIDLIST;
var dwAttributes:ULONG):HResult; virtual; stdcall; abstract;
function EnumObjects(hwndOwner:HWND; grfFlags:DWORD;
var EnumIDList: IENUMIDLIST):HResult; virtual; stdcall; abstract;
function BindToObject(pidl:PITEMIDLIST; pbcReserved:{LPBC}pointer;
riid:TIID; var ppvOut:pointer):HResult; virtual; stdcall; abstract;
function BindToStorage(pidl:PITEMIDLIST; pbcReserved:{LPBC}pointer;
riid:TIID; var ppvObj:pointer):HResult; virtual; stdcall; abstract;
function CompareIDs(lParam:LPARAM;
pidl1,pidl2: PITEMIDLIST):HResult; virtual; stdcall; abstract;
function CreateViewObject(hwndOwner:HWND; riid:TIID;
var ppvOut: pointer):HResult; virtual; stdcall; abstract;
function GetAttributesOf(cidl:UINT; var apidl: PITEMIDLIST;
var rgfInOut:UINT):HResult; virtual; stdcall; abstract;
function GetUIObjectOf(hwndOwner:HWND; cidl:UINT; var apidl: PITEMIDLIST;
riid:TIID; var prgfInOut:UINT; var ppvOut:pointer):HResult; virtual; stdcall; abstract;
function GetDisplayNameOf(pidl: PITEMIDLIST; uFlags:DWORD;
lpName: PSTRRET):HResult; virtual; stdcall; abstract;
function SetNameOf(hwndOwner:HWND; pidl: PITEMIDLIST;
lpszName:POLEStr; uFlags: DWORD;
var ppidlOut: PITEMIDLIST):HResult; virtual; stdcall; abstract;
end;
{ Helper function which returns a IShellFolder interface to the desktop }
{ folder. This is equivalent to call CoCreateInstance with CLSID_ShellDesktop. }
{ CoCreateInstance(CLSID_Desktop, NULL, }
{ CLSCTX_INPROC, IID_IShellFolder, &pshf); }
function SHGetDesktopFolder(var ppshf: ISHELLFOLDER):HResult; stdcall;
{========================================================================== }
{ Clipboard format which may be supported by IDataObject from system }
{ defined shell folders (such as directories, network, ...). }
{========================================================================== }
const
CFSTR_SHELLIDLIST ='Shell IDList Array' { CF_IDLIST };
CFSTR_SHELLIDLISTOFFSET ='Shell Object Offsets' { CF_OBJECTPOSITIONS };
CFSTR_NETRESOURCES ='Net Resource' { CF_NETRESOURCE };
CFSTR_FILEDESCRIPTOR ='FileGroupDescriptor' { CF_FILEGROUPDESCRIPTOR };
CFSTR_FILECONTENTS ='FileContents' { CF_FILECONTENTS };
CFSTR_FILENAME ='FileName' { CF_FILENAME };
CFSTR_PRINTERGROUP ='PrinterFriendlyName' { CF_PRINTERS };
CFSTR_FILENAMEMAP ='FileNameMap' { CF_FILENAMEMAP };
{ CF_OBJECTPOSITIONS }
DVASPECT_SHORTNAME = 2 { use for CF_HDROP to get short name version };
{ format of CF_NETRESOURCE }
type
PNRESARRAY = ^TNRESARRAY;
TNRESARRAY = record { anr }
cItems:UINT;
nr: array[0..0] of TNETRESOURCE;
end;
{ format of CF_IDLIST }
PIDA = ^TIDA;
TIDA = record
cidl:UINT; { number of relative IDList }
aoffset: array[0..0] of UINT; { [0]: folder IDList, [1]-[cidl]: item IDList }
end;
{ FILEDESCRIPTOR.dwFlags field indicate which fields are to be used }
const
FD_CLSID = $0001;
FD_SIZEPOINT = $0002;
FD_ATTRIBUTES = $0004;
FD_CREATETIME = $0008;
FD_ACCESSTIME = $0010;
FD_WRITESTIME = $0020;
FD_FILESIZE = $0040;
FD_LINKUI = $8000; { 'link' UI is prefered }
type
PFILEDESCRIPTOR = ^TFILEDESCRIPTOR;
TFILEDESCRIPTOR = record { fod }
dwFlags:DWORD;
clsid:TCLSID;
sizel:TSIZE;
pointl:TPOINT;
dwFileAttributes:DWORD;
ftCreationTime:TFILETIME;
ftLastAccessTime:TFILETIME;
ftLastWriteTime:TFILETIME;
nFileSizeHigh:DWORD;
nFileSizeLow:DWORD;
cFileName: array[0..MAX_PATH-1] of CHAR;
end;
{ format of CF_FILEGROUPDESCRIPTOR }
PFILEGROUPDESCRIPTOR = ^TFILEGROUPDESCRIPTOR;
TFILEGROUPDESCRIPTOR = record { fgd }
cItems:UINT;
fgd: array[0..0] of TFILEDESCRIPTOR;
end;
{ format of CF_HDROP and CF_PRINTERS, in the HDROP case the data that follows }
{ is a double null terinated list of file names, for printers they are printer }
{ friendly names }
PDROPFILES = ^TDROPFILES;
TDROPFILES = record
pFiles:DWORD; { offset of file list }
pt:TPOINT; { drop point (client coords) }
fNC:BOOL; { is it on NonClient area }
{ and pt is in screen coords }
fWide:BOOL; { WIDE character switch }
end;
{====== File System Notification APIs =============================== }
const
{ File System Notification flags }
SHCNE_RENAMEITEM =$00000001;
SHCNE_CREATE =$00000002;
SHCNE_DELETE =$00000004;
SHCNE_MKDIR =$00000008;
SHCNE_RMDIR =$00000010;
SHCNE_MEDIAINSERTED =$00000020;
SHCNE_MEDIAREMOVED =$00000040;
SHCNE_DRIVEREMOVED =$00000080;
SHCNE_DRIVEADD =$00000100;
SHCNE_NETSHARE =$00000200;
SHCNE_NETUNSHARE =$00000400;
SHCNE_ATTRIBUTES =$00000800;
SHCNE_UPDATEDIR =$00001000;
SHCNE_UPDATEITEM =$00002000;
SHCNE_SERVERDISCONNECT =$00004000;
SHCNE_UPDATEIMAGE =$00008000;
SHCNE_DRIVEADDGUI =$00010000;
SHCNE_RENAMEFOLDER =$00020000;
SHCNE_FREESPACE =$00040000;
SHCNE_ASSOCCHANGED =$08000000;
SHCNE_DISKEVENTS =$0002381F;
SHCNE_GLOBALEVENTS =$0C0581E0 { Events that dont match pidls first };
SHCNE_ALLEVENTS =$7FFFFFFF;
SHCNE_INTERRUPT =$80000000 { The presence of this flag indicates };
{ that the event was generated by an }
{ interrupt. It is stripped out before }
{ the clients of SHCNNotify_ see it. }
{ Flags }
{ uFlags & SHCNF_TYPE is an ID which indicates what dwItem1 and dwItem2 mean }
SHCNF_IDLIST =$0000 { LPITEMIDLIST };
SHCNF_PATH =$0001 { path name };
SHCNF_PRINTER =$0002 { printer friendly name };
SHCNF_DWORD =$0003 { DWORD };
SHCNF_TYPE =$00FF;
SHCNF_FLUSH =$1000;
SHCNF_FLUSHNOWAIT =$2000;
{ APIs }
procedure SHChangeNotify(wEventId:longint; uFlags:UINT;
dwItem1,dwItem2:pointer); stdcall;
procedure SHAddToRecentDocs(uFlags:UINT; pv:pointer); stdcall;
function SHGetInstanceExplorer(var Unk:IUnknown):HResult; stdcall;
{ SHAddToRecentDocs }
const
SHARD_PIDL =$00000001;
SHARD_PATH =$00000002;
implementation
const Shell32DLL = 'shell32.dll';
function SHGetMalloc(var ppMalloc: IMALLOC):HResult;
begin
Result := CoGetMalloc(MEMCTX_TASK,ppMalloc);
end;
function SHGetPathFromIDList; external Shell32DLL name 'SHGetPathFromIDList';
function SHGetSpecialFolderLocation; external Shell32DLL name 'SHGetSpecialFolderLocation';
function SHBrowseForFolder; external Shell32DLL name 'SHBrowseForFolder';
function SHLoadInProc; external Shell32DLL name 'SHLoadInProc';
function SHGetDesktopFolder; external Shell32DLL name 'SHGetDesktopFolder';
procedure SHChangeNotify; external Shell32DLL name 'SHChangeNotify';
procedure SHAddToRecentDocs; external Shell32DLL name 'SHAddToRecentDocs';
function SHGetInstanceExplorer; external Shell32DLL name 'SHGetInstanceExplorer';
end.