You are here

NSIS header for SHGet(Known)FolderPath function

6 posts / 0 new
Last post
wraithdu
Offline
Last seen: 11 years 5 months ago
Developer
Joined: 2007-06-27 20:22
NSIS header for SHGet(Known)FolderPath function

I finally broke down and started to learn AutoIt3's DllCall function, and NSIS's related System plugin. They're hard Wink

This was all prompted by the problem I was having with Vista and RDTools. I needed a way to correctly retrieve the paths for Windows special folders (SendTo, My Documents, etc). Since I fixed it in AutoIt, I figured I'd do an NSIS version too. NSIS has a lot of these builtin, but it doesn't have them all.

This function retrieves the folder paths according to the Windows API (I'm not sure how NSIS does it natively). Hopefully I've made it easy enough for everyday use.

First, copy and paste this into a text file, and save it into your NSIS Include directory with a name of your choice and the .nsh file extension, for example GetFolderPath.nsh -

/*************************************************************************
*	Copyright Erik Pilsits 2008
**************************************************************************
*	HRESULT SHGetFolderPath(      
*		HWND hwndOwner,
*		int nFolder,
*		HANDLE hToken,
*		DWORD dwFlags,
*		LPTSTR pszPath
*	)
*
*	HRESULT SHGetKnownFolderPath(      
*		REFKNOWNFOLDERID rfid,
*		DWORD dwFlags,
*		HANDLE hToken,
*		PWSTR *ppszPath
*	)
**************************************************************************
*	${SHGetFolderPath} "${CSIDL}|${FLAG}|${FLAG}" "${TYPE}" $var
*
*	$var		[path] - path to folder
*			"fail" - function failed
**************************************************************************
*	VISTA ONLY
*
*	${SHGetKnownFolderPath} "${FOLDERID}" "${FLAG}|${FLAG}|${FLAG}" $var
*
*	$var		[path] - path to folder
*			"fail" - function failed
*************************************************************************/

!include LogicLib.nsh

;**********************************************************************
;* SHGetFolderPath Constants                                          *
;**********************************************************************
!define CSIDL_DESKTOP "0x0000"
!define CSIDL_INTERNET "0x0001"
!define CSIDL_PROGRAMS "0x0002"
!define CSIDL_CONTROLS "0x0003"
!define CSIDL_PRINTERS "0x0004"
!define CSIDL_PERSONAL "0x0005"
!define CSIDL_FAVORITES "0x0006"
!define CSIDL_STARTUP "0x0007"
!define CSIDL_RECENT "0x0008"
!define CSIDL_SENDTO "0x0009"
!define CSIDL_BITBUCKET "0x000A"
!define CSIDL_STARTMENU "0x000B"
!define CSIDL_MYDOCUMENTS "0x000C"
!define CSIDL_MYMUSIC "0x000D"
!define CSIDL_MYVIDEO "0x000E"
!define CSIDL_DIRECTORY "0x0010"
!define CSIDL_DRIVES "0x0011"
!define CSIDL_NETWORK "0x0012"
!define CSIDL_NETHOOD "0x0013"
!define CSIDL_FONTS "0x0014"
!define CSIDL_TEMPLATES "0x0015"
!define CSIDL_COMMON_STARTMENU "0x016"
!define CSIDL_COMMON_PROGRAMS "0x0017"
!define CSIDL_COMMON_STARTUP "0x0018"
!define CSIDL_COMMON_DESKTOPDIRECTORY "0x0019"
!define CSIDL_APPDATA "0x001A"
!define CSIDL_PRINTHOOD "0x001B"
!define CSIDL_LOCAL_APPDATA "0x001C"
!define CSIDL_ALTSTARTUP "0x001D"
!define CSIDL_COMMON_ALTSTARTUP "0x001E"
!define CSIDL_COMMON_FAVORITES "0x001F"
!define CSIDL_INTERNET_CACHE "0x0020"
!define CSIDL_COOKIES "0x0021"
!define CSIDL_HISTORY "0x0022"
!define CSIDL_COMMON_APPDATA "0x0023"
!define CSIDL_WINDOWS "0x0024"
!define CSIDL_SYSTEM "0x0025"
!define CSIDL_PROGRAM_FILES "0x0026"
!define CSIDL_MYPICTURES "0x0027"
!define CSIDL_PROFILE "0x0028"
!define CSIDL_SYSTEMX86 "0x0029"
!define CSIDL_PROGRAM_FILESX86 "0x002A"
!define CSIDL_PROGRAM_FILES_COMMON "0x002B"
!define CSIDL_PROGRAM_FILES_COMMONX86 "0x002C"
!define CSIDL_COMMON_TEMPLATES "0x002D"
!define CSIDL_COMMON_DOCUMENTS "0x002E"
!define CSIDL_COMMON_ADMINTOOLS "0x002F"
!define CSIDL_ADMINTOOLS "0x0030"
!define CSIDL_CONNECTIONS "0x0031"
!define CSIDL_COMMON_MUSIC "0x0035"
!define CSIDL_COMMON_PICTURES "0x0036"
!define CSIDL_COMMON_VIDEO "0x0037"
!define CSIDL_RESOURCES "0x0038"
!define CSIDL_RESOURCES_LOCALIZED "0x0039"
!define CSIDL_COMMON_OEM_LINKS "0x003A"
!define CSIDL_CDBURN_AREA "0x003B"
!define CSIDL_COMPUTERSNEARME "0x003D"

; combine with CSIDL_ value to force folder creation in SHGetFolderPath()
!define CSIDL_FLAG_CREATE "0x8000"
; combine with CSIDL_ value to return an unverified folder path
!define CSIDL_FLAG_DONT_VERIFY "0x4000"
; combine with CSIDL_ value to insure non-alias versions of the pidl
!define CSIDL_FLAG_NO_ALIAS "0x1000"
; combine with CSIDL_ value to indicate per-user init (eg. upgrade)
!define CSIDL_FLAG_PER_USER_INIT "0x0800"
; mask for all possible flag values
!define CSIDL_FLAG_MASK "0xFF00"

; dwFlags values for use with SHGetFolderPath
; current value for user, verify it exists
!define SHGFP_TYPE_CURRENT "0x0000"
; default value
!define SHGFP_TYPE_DEFAULT "0x0001"


;**********************************************************************
;* SHGetKnownFolderPath Constants                                     *
;**********************************************************************
!define FOLDERID_AddNewPrograms "{de61d971-5ebc-4f02-a3a9-6c82895e5c04}"
!define FOLDERID_AdminTools  "{724EF170-A42D-4FEF-9F26-B60E846FBA4F}"
!define FOLDERID_AppUpdates "{a305ce99-f527-492b-8b1a-7e76fa98d6e4}"
!define FOLDERID_CDBurning "{9E52AB10-F80D-49DF-ACB8-4330F5687855}"
!define FOLDERID_ChangeRemovePrograms "{df7266ac-9274-4867-8d55-3bd661de872d}"
!define FOLDERID_CommonAdminTools "{D0384E7D-BAC3-4797-8F14-CBA229B392B5}"
!define FOLDERID_CommonOEMLinks "{C1BAE2D0-10DF-4334-BEDD-7AA20B227A9D}"
!define FOLDERID_CommonPrograms "{0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}"
!define FOLDERID_CommonStartMenu "{A4115719-D62E-491D-AA7C-E74B8BE3B067}"
!define FOLDERID_CommonStartup "{82A5EA35-D9CD-47C5-9629-E15D2F714E6E}"
!define FOLDERID_CommonTemplates "{B94237E7-57AC-4347-9151-B08C6C32D1F7}"
!define FOLDERID_ComputerFolder "{0AC0837C-BBF8-452A-850D-79D08E667CA7}"
!define FOLDERID_ConflictFolder "{4bfefb45-347d-4006-a5be-ac0cb0567192}"
!define FOLDERID_ConnectionsFolder "{6F0CD92B-2E97-45D1-88FF-B0D186B8DEDD}"
!define FOLDERID_Contact "{56784854-C6CB-462b-8169-88E350ACB882}"
!define FOLDERID_ControlPanelFolder "{82A74AEB-AEB4-465C-A014-D097EE346D63}"
!define FOLDERID_Cookies "{2B0F765D-C0E9-4171-908E-08A611B84FF6}"
!define FOLDERID_Desktop "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}"
!define FOLDERID_Documents "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}"
!define FOLDERID_Downloads "{374DE290-123F-4565-9164-39C4925E467B}"
!define FOLDERID_Favorites "{1777F761-68AD-4D8A-87BD-30B759FA33DD}"
!define FOLDERID_Fonts "{FD228CB7-AE11-4AE3-864C-16F3910AB8FE}"
!define FOLDERID_Games "{CAC52C1A-B53D-4edc-92D7-6B2E8AC19434}"
!define FOLDERID_GameTasks "{054FAE61-4DD8-4787-80B6-090220C4B700}"
!define FOLDERID_History "{D9DC8A3B-B784-432E-A781-5A1130A75963}"
!define FOLDERID_InternetCache "{352481E8-33BE-4251-BA85-6007CAEDCF9D}"
!define FOLDERID_InternetFolder "{4D9F7874-4E0C-4904-967B-40B0D20C3E4B}"
!define FOLDERID_Links "{bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968}"
!define FOLDERID_LocalAppData "{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}"
!define FOLDERID_LocalAppDataLow "{A520A1A4-1780-4FF6-BD18-167343C5AF16}"
!define FOLDERID_LocalizedResourcesDir "{2A00375E-224C-49DE-B8D1-440DF7EF3DDC}"
!define FOLDERID_Music "{4BD8D571-6D19-48D3-BE97-422220080E43}"
!define FOLDERID_NetHood "{C5ABBF53-E17F-4121-8900-86626FC2C973}"
!define FOLDERID_NetworkFolder "{D20BEEC4-5CA8-4905-AE3B-BF251EA09B53}"
!define FOLDERID_OriginalImages "{2C36C0AA-5812-4b87-BFD0-4CD0DFB19B39}"
!define FOLDERID_PhotoAlbums "{69D2CF90-FC33-4FB7-9A0C-EBB0F0FCB43C}"
!define FOLDERID_Pictures "{33E28130-4E1E-4676-835A-98395C3BC3BB}"
!define FOLDERID_Playlists "{DE92C1C7-837F-4F69-A3BB-86E631204A23}"
!define FOLDERID_PrintersFolder "{76FC4E2D-D6AD-4519-A663-37BD56068185}"
!define FOLDERID_PrintHood "{9274BD8D-CFD1-41C3-B35E-B13F55A758F4}"
!define FOLDERID_Profile "{5E6C858F-0E22-4760-9AFE-EA3317B67173}"
!define FOLDERID_ProgramData "{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}"
!define FOLDERID_ProgramFiles "{905e63b6-c1bf-494e-b29c-65b732d3d21a}"
!define FOLDERID_ProgramFilesX64 "{6D809377-6AF0-444b-8957-A3773F02200E}"
!define FOLDERID_ProgramFilesX86 "{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}"
!define FOLDERID_ProgramFilesCommon "{F7F1ED05-9F6D-47A2-AAAE-29D317C6F066}"
!define FOLDERID_ProgramFilesCommonX64 "{6365D5A7-0F0D-45E5-87F6-0DA56B6A4F7D}"
!define FOLDERID_ProgramFilesCommonX86 "{DE974D24-D9C6-4D3E-BF91-F4455120B917}"
!define FOLDERID_Programs "{A77F5D77-2E2B-44C3-A6A2-ABA601054A51}"
!define FOLDERID_Public "{DFDF76A2-C82A-4D63-906A-5644AC457385}"
!define FOLDERID_PublicDesktop "{C4AA340D-F20F-4863-AFEF-F87EF2E6BA25}"
!define FOLDERID_PublicDocuments "{ED4824AF-DCE4-45A8-81E2-FC7965083634}"
!define FOLDERID_PublicDownloads "{3D644C9B-1FB8-4f30-9B45-F670235F79C0}"
!define FOLDERID_PublicGameTasks "{DEBF2536-E1A8-4c59-B6A2-414586476AEA}"
!define FOLDERID_PublicMusic "{3214FAB5-9757-4298-BB61-92A9DEAA44FF}"
!define FOLDERID_PublicPictures "{B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5}"
!define FOLDERID_PublicVideos "{2400183A-6185-49FB-A2D8-4A392A602BA3}"
!define FOLDERID_QuickLaunch "{52a4f021-7b75-48a9-9f6b-4b87a210bc8f}"
!define FOLDERID_Recent "{AE50C081-EBD2-438A-8655-8A092E34987A}"
!define FOLDERID_RecycleBinFolder "{B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC}"
!define FOLDERID_ResourceDir "{8AD10C31-2ADB-4296-A8F7-E4701232C972}"
!define FOLDERID_RoamingAppData "{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}"
!define FOLDERID_SampleMusic "{B250C668-F57D-4EE1-A63C-290EE7D1AA1F}"
!define FOLDERID_SamplePictures "{C4900540-2379-4C75-844B-64E6FAF8716B}"
!define FOLDERID_SamplePlaylists "{15CA69B3-30EE-49C1-ACE1-6B5EC372AFB5}"
!define FOLDERID_SampleVideos "{859EAD94-2E85-48AD-A71A-0969CB56A6CD}"
!define FOLDERID_SavedGames "{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}"
!define FOLDERID_SavedSearches "{7d1d3a04-debb-4115-95cf-2f29da2920da}"
!define FOLDERID_SEARCH_CSC "{ee32e446-31ca-4aba-814f-a5ebd2fd6d5e}"
!define FOLDERID_SEARCH_MAPI "{98ec0e18-2098-4d44-8644-66979315a281}"
!define FOLDERID_SearchHome "{190337d1-b8ca-4121-a639-6d472d16972a}"
!define FOLDERID_SendTo "{8983036C-27C0-404B-8F08-102D10DCFD74}"
!define FOLDERID_SidebarDefaultParts "{7B396E54-9EC5-4300-BE0A-2482EBAE1A26}"
!define FOLDERID_SidebarParts "{A75D362E-50FC-4fb7-AC2C-A8BEAA314493}"
!define FOLDERID_StartMenu "{625B53C3-AB48-4EC1-BA1F-A1EF4146FC19}"
!define FOLDERID_Startup "{B97D20BB-F46A-4C97-BA10-5E3608430854}"
!define FOLDERID_SyncManagerFolder "{43668BF8-C14E-49B2-97C9-747784D784B7}"
!define FOLDERID_SyncResultsFolder "{289a9a43-be44-4057-a41b-587a76d7e7f9}"
!define FOLDERID_SyncSetupFolder "{0F214138-B1D3-4a90-BBA9-27CBC0C5389A}"
!define FOLDERID_System "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}"
!define FOLDERID_SystemX86 "{D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27}"
!define FOLDERID_Templates "{A63293E8-664E-48DB-A079-DF759E0509F7}"
!define FOLDERID_TreeProperties "{5b3749ad-b49f-49c1-83eb-15370fbd4882}"
!define FOLDERID_UserProfiles "{0762D272-C50A-4BB0-A382-697DCD729B80}"
!define FOLDERID_UsersFiles "{f3ce0f7c-4901-4acc-8648-d5d44b04ef8f}"
!define FOLDERID_Videos "{18989B1D-99B5-455B-841C-AB7C74E4DDFC}"
!define FOLDERID_Windows "{F38BF404-1D43-42F2-9305-67DE0B28FC23}"

; KF_FLAG_ dwFlags values for use with SHGetKnownFolderPath
; force creation of the specified folder if it does not exist
!define KF_FLAG_CREATE "0x8000"
; specifies not to verify the folder's existence before attempting to retrieve the path or IDList
!define KF_FLAG_DONT_VERIFY "0x4000"
; gets the true system path for the folder, free of any aliased placeholders
!define KF_FLAG_NO_ALIAS "0x1000"
; initializes the folder using its Desktop.ini settings
!define KF_FLAG_INIT "0x0800"
; gets the default path for a known folder that is redirected elsewhere
!define KF_FLAG_DEFAULT_PATH "0x0400"
; gets the folder's default path independent of the current location of its parent
!define KF_FLAG_NOT_PARENT_RELATIVE "0x0200"
; build a simple pointer to an item identifier list (PIDL)
!define KF_FLAG_SIMPLE_IDLIST "0x0100"

!define SHGetFolderPath "!insertmacro _SHGetFolderPath"
!define SHGetKnownFolderPath "!insertmacro _SHGetKnownFolderPath"

!macro _SHGetFolderPath nFolder dwFlags outVar
	Push $0
	
	System::Call "shell32::SHGetFolderPath(in, i ${nFolder}, in, i ${dwFlags}, t .s) i.r0"
	${IfNot} $0 == 0
		Push "fail"
	${EndIf}
	
	Exch
	Pop $0
	Pop ${outVar}
!macroend

!macro _SHGetKnownFolderPath rfid dwFlags outVar
	Push $0
	Push $1
	Push $2
	System::Call "shell32::SHGetKnownFolderPath(g '${rfid}', i ${dwFlags} , in, *i.r1) i.r0"
	${If} $0 == 0
		System::Call 'kernel32::lstrlenW(i $1) i.r2'
		IntOp $2 $2 * 2
		System::Call '*$1(&w$2 .s)'
		System::Call 'ole32::CoTaskMemFree(i $1)'
	${Else}
		Push "fail"
	${EndIf}
	Exch 3
	Pop $0
	Pop $2
	Pop $1
	Pop ${outVar}
!macroend

Usage:

!include GetFolderPath.nsh

${SHGetFolderPath} "${CSIDL}|${FLAG}|${FLAG}" "${TYPE}" $var

Examples:
${SHGetFolderPath} "${CSIDL_SENDTO}" "${SHGFP_TYPE_CURRENT}" $folder
MessageBox MB_OK $folder

or

${SHGetFolderPath} "${CSIDL_SENDTO}|${CSIDL_FLAG_NO_ALIAS}" "${SHGFP_TYPE_CURRENT}" $folder ; used to combine flags
MessageBox MB_OK $folder


${SHGetKnownFolderPath} "${FOLDERID}" "${FLAG}|${FLAG}|${FLAG}" $var

CSIDL reference -

http://vbnet.mvps.org/code/browse/csidlvalues.htm

John T. Haller
John T. Haller's picture
Online
Last seen: 20 min 6 sec ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Nice

I'd suggest updating the macro to add in the variable on the same line so folks don't have to manually pop it off the stack afterwards.

And release it under BSD and post it back to the NSIS folks so it can be used upstream by everyone using NSIS. I'm sure they'd appreciate the contribution. Smile

Sometimes, the impossible can become possible, if you're awesome!

wraithdu
Offline
Last seen: 11 years 5 months ago
Developer
Joined: 2007-06-27 20:22
Thanks, I made the change to

Thanks, I made the change to the macro.

How exactly do I go about releasing under BSD? Do I just zip it with the license doc, or does the license go in the source?

John T. Haller
John T. Haller's picture
Online
Last seen: 20 min 6 sec ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
BSD is short

BSD is really short. You can include it as a comment at the top of the code.

; Copyright (c) 2008, wraithdu
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;     * Redistributions of source code must retain the above copyright
;       notice, this list of conditions and the following disclaimer.
;     * Redistributions in binary form must reproduce the above copyright
;       notice, this list of conditions and the following disclaimer in the
;       documentation and/or other materials provided with the distribution.
;     * Neither the name of the organization nor the
;       names of its contributors may be used to endorse or promote products
;       derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY wraithdu ``AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL wraithdu BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

(Usually better to use your real name, though.)

And then head over to the NSIS site and submit it to the library.

Sometimes, the impossible can become possible, if you're awesome!

ZachHudock
ZachHudock's picture
Offline
Last seen: 1 year 10 months ago
Developer
Joined: 2006-12-06 18:07
Good work. I don't have

Good work. I don't have much use for it personally, but I'm certain it will make things easier for others.

P.S. i like John's suggestion about licensing and sharing with NSIS

The developer formerly known as ZGitRDun8705

wraithdu
Offline
Last seen: 11 years 5 months ago
Developer
Joined: 2007-06-27 20:22
Updated functions / macros a

Updated functions / macros a little, and added the Vista-only SHGetKnownFolderPath().

Log in or register to post comments