October 31, 2025, 05:18:52 AM

News:

IWBasic runs in Windows 11!


How to maintain a list of PIDL's between sessions?

Started by fasecero, September 04, 2010, 04:36:45 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

fasecero

Hello, I need to maintain a list of PIDL's (ITEMIDLIST's) between sessions.
The only way I can do it so far is to create a shortcut (.lnk) on the disk for every PIDL... something like this (extended from shell_COM_example.eba):



' ---------------------------------------------------------------------------------------------
' DECLARATIONS
' ---------------------------------------------------------------------------------------------

$INCLUDE "ishelllink.inc"

CONST CSIDLDESKTOP = 0x0000
CONST CSIDLPROGRAMS = 0x0002
CONST CSIDLCONTROLS = 0x0003
CONST CSIDLPRINTERS = 0x0004
CONST CSIDLPERSONAL = 0x0005
CONST CSIDLFAVORITES = 0x0006
CONST CSIDLSTARTUP = 0x0007
CONST CSIDLRECENT = 0x0008
CONST CSIDLSENDTO = 0x0009
CONST CSIDLBITBUCKET = 0x000a
CONST CSIDLSTARTMENU = 0x000b
CONST CSIDLDESKTOPDIRECTORY = 0x0010
CONST CSIDLDRIVES = 0x0011
CONST CSIDLNETWORK = 0x0012
CONST CSIDLNETHOOD = 0x0013
CONST CSIDLFONTS = 0x0014
CONST CSIDLTEMPLATES = 0x0015
CONST CSIDLCMNSTARTMENU = 0x0016
CONST CSIDLCMNPROGRAMS = 0x0017
CONST CSIDLCMNSTARTUP = 0x0018
CONST CSIDLCMNDESKTOPDIRECTORY = 0x0019
CONST CSIDLAPPDATA = 0x001a
CONST CSIDLPRINTHOOD = 0x001b

CONST CP_ACP = 0
CONST CLSCTX_INPROC_SERVER = 1
$define STGM_READ               0x00000000

DECLARE IMPORT,SHGetSpecialFolderLocation(hwnd as UINT,nFolder as INT,ppITEMIDLIST as POINTER),int
DECLARE IMPORT,SHGetPathFromIDList(pITEMIDLIST:POINTER,PATH:STRING),int
DECLARE IMPORT,CoTaskMemFree(pidl:POINTER)
DECLARE IMPORT,MultiByteToWideChar(codepage as UINT,dwFlags as UINT,lpMBS as STRING,cchMB as INT,lpWCS as POINTER,cchWC as INT)

' ---------------------------------------------------------------------------------------------
' MAIN
' ---------------------------------------------------------------------------------------------

OPENCONSOLE
PRINT "Save and load PIDL's (using shortcuts)..."
PRINT ""

DoExample()

PRINT ""
PRINT "Press any key to close"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE

SUB DoExample()
ISTRING lnkPath[260, 3]
    pointer pidl[3]
   
'Make sure COM is active
CoInitialize(NULL)

'the .lnk target files
lnkPath[0, 0] = GETSTARTPATH + "my_pidl1.lnk"
lnkPath[0, 1] = GETSTARTPATH + "my_pidl2.lnk"
lnkPath[0, 2] = GETSTARTPATH + "my_pidl3.lnk"

' fill the PIDL's with some locations
SHGetSpecialFolderLocation(0, CSIDLPERSONAL, &pidl[0])
SHGetSpecialFolderLocation(0, CSIDLFAVORITES, &pidl[1])
SHGetSpecialFolderLocation(0, CSIDLDESKTOP, &pidl[2])

FOR j = 0 TO 2
'Save PIDL's to file (.lnk)
IF SavePIDL(lnkPath[0, j], pidl[j]) = 0 THEN
CoTaskMemFree(pidl[j])

'Load PIDL's back from the file
pidl[j] = LoadPIDL(lnkPath[0, j])
IF pidl[j] THEN
lnkPath[0, j] = ""

' show to where the PIDL's points to...
' ... cuz the tree PIDL's have physical address
' this is just to check
SHGetPathFromIDList(pidl[j], lnkPath[0, j])
PRINT "PIDL[" + STR$(j) + " ] points to: " + lnkPath[0, j]
CoTaskMemFree(pidl[j])
ENDIF
ENDIF
NEXT j

'Shut down COM
CoUninitialize()
ENDSUB


' ---------------------------------------------------------------------------------------------
' FUNCTIONS
' ---------------------------------------------------------------------------------------------

SUB GetFolderLocation(nFolder:INT),STRING
     ISTRING path[260] = ""
     POINTER pidl = 0
     POINTER ppidl = 0

     ppidl = &pidl
     SHGetSpecialFolderLocation(NULL,nFolder,ppidl)
     SHGetPathFromIDList(pidl,path)
     CoTaskMemFree(pidl)

RETURN path
ENDSUB

SUB SavePIDL(STRING lpszPathLink, pointer pidl),INT
    INT hres = 0
    IShellLinkA psl = NULL
IPersistFile ppf = NULL
WORD wsz[260]

    'Get a pointer to the IShellLink interface.
    hres = CoCreateInstance(_CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, _IID_IShellLinkA, psl)
    if (hres = 0)
'set the PIDL of the IShellLink
psl->SetIDList(*<ITEMIDLIST>pidl)
       'Query IShellLink for the IPersistFile interface for saving the
       'shortcut in persistent storage.
        hres = psl->QueryInterface(_IID_IPersistFile,ppf)
if (hres = 0)
             'Ensure that the string is ANSI unicode.
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,wsz, 260)
             'Save the link by calling IPersistFile->Save.
            hres = ppf->Save(wsz, TRUE)
            ppf->Release()
        endif
        psl->Release()
    endif
    return hres
ENDSUB

SUB LoadPIDL(STRING lpszPathLink), pointer
    INT hres = 0
    IShellLinkA psl = NULL
IPersistFile ppf = NULL
WORD wsz[260]
pointer pidl = 0

    'Get a pointer to the IShellLink interface.
    hres = CoCreateInstance(_CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, _IID_IShellLinkA, psl)
    if (hres = 0)
'set the PIDL of the IShellLink
psl->SetIDList(*<ITEMIDLIST>pidl)
       'Query IShellLink for the IPersistFile interface for saving the
       'shortcut in persistent storage.
        hres = psl->QueryInterface(_IID_IPersistFile,ppf)
if (hres = 0)
             'Ensure that the string is ANSI unicode.
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,wsz, 260)
             'load the link by calling IPersistFile->Load.
            hres = ppf->Load(wsz, STGM_READ)
if (hres = 0) THEN psl->GetIDList(&pidl)
            ppf->Release()
        endif
        psl->Release()
    endif
    return pidl
ENDSUB




But it would be great to save and load all PIDL's from just one single file. Is it possible?

sapero

Fasecero, an ITEMIDLIST is just a memory block allocated by CoTaskMemAlloc, or Alloc method from IMalloc interface. It contains an array of SHITEMID structures (size+string), and it is well explained here.
Give it a try.

fasecero

September 10, 2010, 02:37:02 PM #2 Last Edit: September 10, 2010, 02:41:20 PM by fasecero
Iterating through each SHITEMID I get the total size in bytes, then I save the size (as integer) and after all those bytes.
To read the ITEMIDLIST again, I read the size and with CoTaskMemAlloc(...) I make the allocation again, then I read the bytes.
It works well, thanks Sapero.