Quantcast
Viewing all articles
Browse latest Browse all 1449

How to pin/unpin from QuickAccessFolder the easy way

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.

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

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.
Attached Images
Image may be NSFW.
Clik here to view.
 

Viewing all articles
Browse latest Browse all 1449

Trending Articles