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.