-
Notifications
You must be signed in to change notification settings - Fork 72
/
EnumKnownFolders.ahk
206 lines (206 loc) · 11 KB
/
EnumKnownFolders.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#NoEnv
KFPROPS := ["Name", "ID", "CSIDL", "LocalizedName", "Category", "Path", "ParsingName", "Parent", "RelativePath"
, "Description", "ToolTip", "Icon", "Security", "Attributes", "Flags", "Type"]
; ---------------------------------------------------------------------------------------------------
KF := EnumKnownFolders()
; ---------------------------------------------------------------------------------------------------
Gui, Main:New
Gui, Font, s10, Lucida Console
Gui, Add, ListView, w1200 r30 Grid vMainLV gMainLVLabel, Index|ID|CSIDL|Name|Localized Name|Category
For I, F In KF
LV_Add("", I, F.ID, F.CSIDL, F.Name, F.LocalizedName, F.Category)
Loop, % LV_GetCount("Column")
LV_ModifyCol(A_Index, "AutoHdr")
LV_ModifyCol(1, "Integer")
Gui, Show, , KnownFolders
; ---------------------------------------------------------------------------------------------------
Gui, Props:New, +OwnerMain
Gui, Font, s10, Lucida Console
Gui, Add, ListView, w1200 r20 Grid vPropsLV, Property|Value
Return
; ---------------------------------------------------------------------------------------------------
MainGuiClose:
ExitApp
; ---------------------------------------------------------------------------------------------------
PropsGuiClose:
PropsGuiEscape:
Gui, Main:-Disabled
Gui, Hide
Return
; ---------------------------------------------------------------------------------------------------
MainLVLabel:
Gui, ListView, MainLV
If (A_GuiEvent = "DoubleClick") && (A_EventInfo = LV_GetNext()) {
Gui, Props:Default
Gui, ListView, PropsLV
LV_Delete()
FolderProps := KF[A_EventInfo]
For I, N In KFPROPS
LV_Add("", N, FolderProps[N])
LV_ModifyCol(1, "AutoHdr")
LV_ModifyCol(2, "AutoHdr")
Gui, Main:+Disabled
Gui, Show, , Properties
}
Return
; ==================================================================================================
EnumKnownFolders() {
Local
Static Categories := ["VIRTUAL", "FIXED", "COMMON", "PERUSER"]
If !(IKFM := IKnownFoldersManager_Create())
Return False
If !IKnownFoldersManager_GetFolderIds(IKFM, KFID, CID)
Return False
KnownFolders := {}
PKNID := KFID ; pointer to the current KNOWNFOLDERID
Loop, %CID% {
If !IKnownFoldersManager_GetFolder(IKFM, PKNID, IKF)
Continue
Properties := {ID: StringFromGUID2(PKNID)}
If IKnownFoldersManager_FolderIdToCsidl(IKFM, PKNID, CSIDL)
Properties.CSIDL := CSIDL
If IKnownFolder_GetFolderDefinition(IKF, KFD) {
Properties.Category := Categories[NumGet(KFD, Offset := 0, "UInt")]
Properties.Name := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
Properties.Description := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
Properties.Parent := StringFromGUID2(&KFD + (Offset += A_PtrSize))
Properties.RelativePath := StrGet(NumGet(KFD, Offset += 16, "UPtr"), "UTF-16")
Properties.ParsingName := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
ToolTip := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
If (SubStr(ToolTip, 1, 1) = "@")
ToolTip := GetMUIString(ToolTip)
Properties.ToolTip := ToolTip
LocalName := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
If (SubStr(LocalName, 1, 1) = "@")
LocalName := GetMUIString(LocalName)
Properties.LocalizedName := LocalName
Properties.Icon := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
Properties.Security := StrGet(NumGet(KFD, Offset += A_PtrSize, "UPtr"), "UTF-16")
Properties.Attributes := Format("0x{:08X}", NumGet(KFD, Offset += A_PtrSize, "UInt"))
Properties.Flags := Format("0x{:08X}", NumGet(KFD, Offset += 4, "UInt"))
Properties.Type := StringFromGUID2(&KFD + (Offset += 4))
FreeKnownFolderDefinitionFields(&KFD)
}
If IKnownFolder_GetPath(IKF, Path)
Properties.Path := Path
KnownFolders[A_Index] := Properties
ObjRelease(IKF)
PKNID += 16 ; switch to the next KNOWNFOLDERID
}
DllCall("Ole32.dll\CoTaskMemFree", "Ptr", KFID)
Return KnownFolders
}
; ======================================================================================================================
; IKnownFoldersManager interface
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-iknownfoldermanager
; ======================================================================================================================
; Creates a IKNOWNFOLDERSMANAGER interface and returns its pointer on success.
; ----------------------------------------------------------------------------------------------------------------------
IKnownFoldersManager_Create() {
Local
Static SCLSID_KnownFoldersManager := "{4DF0C730-DF9D-4AE3-9153-AA6B82E9795A}"
, SIID_IKnownFoldersManager := "{8BE2D872-86AA-4d47-B776-32CCA40C7018}"
If !(IKFM := ComObjCreate(SCLSID_KnownFoldersManager, SIID_IKnownFoldersManager))
Return False
Return IKFM
}
; ----------------------------------------------------------------------------------------------------------------------
; Gets the legacy CSIDL value that is the equivalent of a given KNOWNFOLDERID.
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-iknownfoldermanager-folderidtocsidl
; ----------------------------------------------------------------------------------------------------------------------
IKnownFoldersManager_FolderIdToCsidl(IKFM, PKNID, ByRef CSIDL) {
Local
FolderIdToCsidl := NumGet(NumGet(IKFM + 0, "Uptr"), A_PtrSize * 4, "UPtr")
Return !DllCall(FolderIdToCsidl, "Ptr", IKFM, "Ptr", PKNID, "IntP", CSIDL := 0, "UInt")
}
; ----------------------------------------------------------------------------------------------------------------------
; Gets an array of all registered known folder IDs. This can be used in enumerating all known folders.
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-iknownfoldermanager-getfolderids
; ----------------------------------------------------------------------------------------------------------------------
IKnownFoldersManager_GetFolderIds(IKFM, ByRef KFID, ByRef CID) {
Local
GetFolderIds := NumGet(NumGet(IKFM + 0, "Uptr"), A_PtrSize * 5, "UPtr")
Return !DllCall(GetFolderIds, "Ptr", IKFM, "PtrP", KFID, "IntP", CID, "UInt")
}
; ----------------------------------------------------------------------------------------------------------------------
; Gets an object that represents a known folder identified by its KNOWNFOLDERID.
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-iknownfoldermanager-getfolder
; ----------------------------------------------------------------------------------------------------------------------
IKnownFoldersManager_GetFolder(IKFM, PFolderID, ByRef IKF) {
Local
GetFolder := NumGet(NumGet(IKFM + 0, "Uptr"), A_PtrSize * 6, "UPtr")
Return !DllCall(GetFolder, "Ptr", IKFM, "Ptr", PFolderID, "PtrP", IKF, "UInt")
}
; ----------------------------------------------------------------------------------------------------------------------
; Releases the IKNOWNFOLDERSMANAGER interface.
; ----------------------------------------------------------------------------------------------------------------------
IKnownFoldersManager_Release(IKFM) {
Return ObjRelease(IKFM)
}
; ======================================================================================================================
; IKnownFolder interface
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-iknownfolder
; ======================================================================================================================
; Retrieves a structure that contains the defining elements of a known folder,
; which includes the folder's category, name, path, description, tooltip, icon, and other properties.
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-iknownfolder-getfolderdefinition
; ----------------------------------------------------------------------------------------------------------------------
IKnownFolder_GetFolderDefinition(IKF, ByRef KFD) {
Local
GetFolderDefinition := NumGet(NumGet(IKF + 0, "Uptr"), A_PtrSize * 11, "UPtr")
VarSetCapacity(KFD, 40 + (A_PtrSize * 9), 0)
Return !DllCall(GetFolderDefinition, "Ptr", IKF, "Ptr", &KFD, "UInt")
}
; ----------------------------------------------------------------------------------------------------------------------
; Retrieves the path of a known folder as a string.
; docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-iknownfolder-getpath
; ----------------------------------------------------------------------------------------------------------------------
IKnownFolder_GetPath(IKF, ByRef Path, Flags := 0) {
Local
GetPath := NumGet(NumGet(IKF + 0, "Uptr"), A_PtrSize * 6, "UPtr")
Path := ""
If !(HR := DllCall(GetPath, "Ptr", IKF, "UInt", Flags, "PtrP", KFP, "UInt")) {
Path := StrGet(KFP, "UTF-16")
DllCall("Ole32.dll\CoTaskMemFree", "Ptr", KFP)
}
Return !HR
}
; ======================================================================================================================
; Auxiliary functions
; ======================================================================================================================
ExpandEnvironmentStrings(Str) {
If (Chars := DllCall("ExpandEnvironmentStrings", "Ptr", &Str, "Ptr", 0, "UInt", 0, "Int")) {
VarSetCapacity(Expanded, ++Chars << !!A_IsUnicode, 0)
DllCall("ExpandEnvironmentStrings", "Ptr", &Str, "Str", Expanded, "UInt", Chars, "Int")
Return Expanded
}
Return Str
}
; ======================================================================================================================
FreeKnownFolderDefinitionFields(KFD) {
Static OffSets := [A_PtrSize, A_PtrSize, A_PtrSize + 16, A_PtrSize, A_PtrSize, A_PtrSize, A_PtrSize, A_PtrSize]
Offset := 0
For I, V In Offsets {
Offset += V
DllCall("Ole32.dll\CoTaskMemFree", "Ptr", NumGet(KFD + OffSet, "UPtr"))
}
}
; ======================================================================================================================
GetMUIString(ResPath) {
If InStr(ResPath, "%")
ResPath := ExpandEnvironmentStrings(ResPath)
ResStr := ""
ResSplit := StrSplit(ResPath, [",", ";"], "@-")
HMUI := DllCall("LoadLibraryEx", "Str", ResSplit[1], "Ptr", 0, "UInt", 0x00000020, "UPtr")
If (Size := DllCall("LoadStringW", "Ptr", HMUI, "UInt", ResSplit[2], "PtrP", ResPtr, "Int", 0, "Int"))
ResStr := StrGet(ResPtr, Size, "UTF-16")
DllCall("FreeLibrary", "Ptr", HMUI)
Return (ResStr ? ResStr : ResPath)
}
; ======================================================================================================================
StringFromGUID2(PGUID) {
VarSetCapacity(SGUID, 128, 0)
CC := DllCall("Ole32.dll\StringFromGUID2", "Ptr", PGUID, "Ptr", &SGUID, "Int", 64, "Int")
Return StrGet(&SGUID, CC, "UTF-16")
}
; ======================================================================================================================