I was wondering how I could add pinned folder to QuickAccess and did find an easy way but quite poorly documented indeed.
That is done is by sending "pintohome" verb command either in ShellExecute API or in ShellExecuteEx
I choosed the latter one.
But at first I didn't find any good solution for unpinning the folder corresponding to "pintohome" for i.e "unpinfromhome" but nothing such exists.
So I come up with creating a Library Folder and creating a IShellItem pointing to the currently pinned folder via the pidl from it's path.
And by assigning the created IShellItem to HRESULT IShellLibrary::RemoveFolder([in] IShellItem *psiLocation) method you can easily unpin the folder.
So the folder to be pinned MUST physically exist or be a registered virtual folder and it DOES NOT become deleted by unpinning it.
You need Fafalone's TypeLib or other TypeLib that deals with IShellLibrary and IShellItem interfaces.
That is done is by sending "pintohome" verb command either in ShellExecute API or in ShellExecuteEx
I choosed the latter one.
Code:
Public Declare Function ILCreateFromPathW Lib "shell32" (ByVal pszPath As Long) As Long
Public Enum ShellExecuteEx_Flags
SEE_MASK_CLASSKEY = &H3
SEE_MASK_CLASSNAME = &H1
SEE_MASK_CONNECTNETDRV = &H80
SEE_MASK_DOENVSUBST = &H200
SEE_MASK_FLAG_DDEWAIT = &H100
SEE_MASK_FLAG_NO_UI = &H400
SEE_MASK_HOTKEY = &H20
SEE_MASK_ICON = &H10
SEE_MASK_IDLIST = &H4
SEE_MASK_INVOKEIDLIST = &HC
SEE_MASK_NOCLOSEPROCESS = &H40
End Enum
Public Type SHELLEXECUTEINFO
cbSize As Long
fMask As ShellExecuteEx_Flags
hWnd As Long
lpVerb As Long
lpFile As Long
lpParameters As Long
lpDirectory As Long
nShow As Integer
hInstApp As Long
lpIDList As Long
lpClass As Long
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hMonitor As Long
hProcess As Long
End Type
Public Declare Function ShellExecuteEx Lib "shell32.dll" Alias "ShellExecuteExW" (lpSEEI As Any) As Long
Public Const sCLSID_ShellLibrary As String = "{D9B3211D-E57F-4426-AAEF-30A806ADD397}"
Public Declare Function CLSIDFromString Lib "ole32.dll" (ByVal pszCLSID As Long, pguid As Any) As Long
Public Enum CLSCTX
CLSCTX_INPROC_SERVER = &H1
CLSCTX_INPROC_HANDLER = &H2
CLSCTX_LOCAL_SERVER = &H4
CLSCTX_INPROC_SERVER16 = &H8
CLSCTX_REMOTE_SERVER = &H10
CLSCTX_INPROC_HANDLER16 = &H20
CLSCTX_RESERVED1 = &H40
CLSCTX_RESERVED2 = &H80
CLSCTX_RESERVED3 = &H100
CLSCTX_RESERVED4 = &H200
CLSCTX_NO_CODE_DOWNLOAD = &H400
CLSCTX_RESERVED5 = &H800
CLSCTX_NO_CUSTOM_MARSHAL = &H1000
CLSCTX_ENABLE_CODE_DOWNLOAD = &H2000
CLSCTX_NO_FAILURE_LOG = &H4000
CLSCTX_DISABLE_AAA = &H8000
CLSCTX_ENABLE_AAA = &H10000
CLSCTX_FROM_DEFAULT_CONTEXT = &H20000
CLSCTX_ACTIVATE_X86_SERVER = &H40000
CLSCTX_ACTIVATE_32_BIT_SERVER
CLSCTX_ACTIVATE_64_BIT_SERVER = &H80000
CLSCTX_ENABLE_CLOAKING = &H100000
CLSCTX_APPCONTAINER = &H400000
CLSCTX_ACTIVATE_AAA_AS_IU = &H800000
CLSCTX_RESERVED6 = &H1000000
CLSCTX_ACTIVATE_ARM32_SERVER = &H2000000
CLSCTX_ALLOW_LOWER_TRUST_REGISTRATION
CLSCTX_PS_DLL = &H80000000
CLSCTX_SERVER = CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
CLSCTX_ALL = CLSCTX_INPROC_SERVER Or CLSCTX_INPROC_HANDLER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
End Enum
Public Declare Function CoCreateInstance Lib "ole32.dll" (rclsid As Any, ByVal pUnkOuter As Long, ByVal dwClsContext As Long, riid As Any, ppv As Any) As Long
Public Sub DEFINE_UUID(Name As UUID, L As Long, w1 As Integer, w2 As Integer, B0 As Byte, b1 As Byte, b2 As Byte, B3 As Byte, b4 As Byte, b5 As Byte, b6 As Byte, b7 As Byte)
With Name
.Data1 = L: .Data2 = w1: .Data3 = w2: .Data4(0) = B0: .Data4(1) = b1: .Data4(2) = b2: .Data4(3) = B3: .Data4(4) = b4: .Data4(5) = b5: .Data4(6) = b6: .Data4(7) = b7
End With
End Sub
Public Function IID_IShellLibrary() As UUID
'{&H11a66efa, &H382e, &H451a, {&H92, &H34, &H1e, &He, &H12, &Hef, &H30, &H85}}
Static iid As UUID
If (iid.Data1 = 0) Then Call DEFINE_UUID(iid, &H11A66EFA, CInt(&H382E), CInt(&H451A), &H92, &H34, &H1E, &HE, &H12, &HEF, &H30, &H85)
IID_IShellLibrary = iid
End Function
Public Function ShCreateShellLibrary(pISL As IShellLibrary) As Long
Dim CLSID_ShellLibrary As GUID
CLSIDFromString StrPtr(sCLSID_ShellLibrary), CLSID_ShellLibrary
hr = CoCreateInstance(CLSID_ShellLibrary, 0&, CLSCTX_INPROC_SERVER, IID_IShellLibrary, pISL)
ShCreateShellLibrary = hr
End Function
Public Function ShPinToQuickAccessFolder(ByVal sPathOrFile As String) As Long
Dim lpSEIEX As SHELLEXECUTEINFO
Dim lr As Long
Dim pISI As IShellItem2
Dim pISL As IShellLibrary
lpSEIEX.cbSize = LenB(lpSEIEX)
lpSEIEX.fMask = SEE_MASK_NO_CONSOLE Or SEE_MASK_IDLIST
lpSEIEX.lpVerb = StrPtr("pintohome")
lpSEIEX.lpIDList = ILCreateFromPathW(StrPtr(sPathOrFile))
ShCreateShellLibrary pISL
lr = ShellExecuteEx(lpSEIEX)
If lr <> 0 Then
SHCreateShellItem 0, 0, lpSEIEX.lpIDList, pISI
hr = pISL.RemoveFolder(pISI)
pISL.Commit
End If
If lr = 1 Then ShPinToQuickAccessFolder = S_OK Else ShPinToQuickAccessFolder = S_FALSE
Set pISI = Nothing
Set pISL = Nothing
CoTaskMemFree lpSEIEX.lpIDList
End Function
So I come up with creating a Library Folder and creating a IShellItem pointing to the currently pinned folder via the pidl from it's path.
And by assigning the created IShellItem to HRESULT IShellLibrary::RemoveFolder([in] IShellItem *psiLocation) method you can easily unpin the folder.
So the folder to be pinned MUST physically exist or be a registered virtual folder and it DOES NOT become deleted by unpinning it.
You need Fafalone's TypeLib or other TypeLib that deals with IShellLibrary and IShellItem interfaces.