image
 
image
M023_SpecialDirectories.bas


' ========================================================================================================================
'                                 ____,__,  __,  ____,_,  _,  ____ ____,__, ,____,____,
'                                (-/_|(-|  (-|  (-|_,(-|\ |  (-|__|-/_|( |_/(-|_,(-|__)
'                                _/  |,_|__,_|__,_|__,_| \|,  _|__)/  |,_| \,_|__,_|  \,
'
'                                             Copyright 2011 Allen Baker
'
' ------------------------------------------------------------------------------------------------------------------------
' File:          M023_SpecialDirectories
' Originator:    Allen Baker (2011.03.10 23:21)
' ------------------------------------------------------------------------------------------------------------------------
' $RCSfile$
' $Revision$
' $Date$
' ========================================================================================================================
'
Option Explicit



' ========================================================================================================================
' Description
'    This module provides definitions for finding and using Windows' "special" folders such as "Application Data",
'    "Documents", "Favorites", etc. These URLs provide additional info:
'        http://support.microsoft.com/kb/252652
'        http://msdn.microsoft.com/en-us/library/bb762181(v=VS.85).aspx
'        http://msdn.microsoft.com/en-us/library/bb762494(v=VS.85).aspx
' ========================================================================================================================



' =====================================================================================================================
' @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Constants  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
' =====================================================================================================================



'
' ==============================================================================================
' SHGetFolderPath function return codes
' ----------------------------------------------------------------------------------------------
Private Const cSuccess      As Long = &H0          ' Success

Private Const cDoesNotExist As Long = &H1          ' The Folder is valid, but does not exist
Private Const cInvalidCSIDL As Long = &H80070057   ' Invalid CSIDL Value
'
' ==============================================================================================
' Flags that specify the path to be returned. This value is used in cases where the folder
' associated with a KNOWNFOLDERID (or CSIDL) can be moved, renamed, redirected, or roamed
' across languages by a user or administrator.
'
' The known folder system that underlies SHGetFolderPath allows users or administrators to
' redirect a known folder to a location that suits their needs. This is achieved by calling
' IKnownFolderManager::Redirect, which sets the "current" value of the folder associated with
' the SHGFP_TYPE_CURRENT flag.
'
' The default value of the folder, which is the location of the folder if a user or
' administrator had not redirected it elsewhere, is retrieved by specifying the
' SHGFP_TYPE_DEFAULT flag. This value can be used to implement a "restore defaults" feature for
' a known folder.
'
' For example, the default value (SHGFP_TYPE_DEFAULT) for FOLDERID_Music (CSIDL_MYMUSIC) is
' "C:\Users\user name\Music". If the folder was redirected, the current value
' (SHGFP_TYPE_CURRENT) might be "D:\Music". If the folder has not been redirected, then
' SHGFP_TYPE_DEFAULT and SHGFP_TYPE_CURRENT retrieve the same path.
'
' SHGFP_TYPE_CURRENT - Retrieve the folder's current path.
'
' SHGFP_TYPE_DEFAULT - Retrieve the folder's default path.
' ----------------------------------------------------------------------------------------------
Private Const SHGFP_TYPE_CURRENT = 0
Private Const SHGFP_TYPE_DEFAULT = 1
'
' ==============================================================================================
' the maximum length of a path name in Windows.
' ----------------------------------------------------------------------------------------------
Private Const MAX_PATH = 260
'
' ==============================================================================================
' The source of these CSIDL constants is the MS C/C++ include file shlobj.h
'
' A CSIDL is used in conjunction with one of four Shell functions, SHGetFolderLocation,
' SHGetFolderPath, SHGetSpecialFolderLocation, and SHGetSpecialFolderPath, to retrieve a
' special folder's path or pointer to an item identifier list (PIDL).
'
' Combine CSIDL_FLAG_CREATE with any of the other CSIDLs, except for CSIDL_FLAG_DONT_VERIFY, to
' force the creation of the associated folder. The remaining CSIDLs correspond to either file
' system folders or virtual folders. Where the CSIDL identifies a file system folder, a
' commonly used path is given as an example. Other paths may be used. Some CSIDLs can be mapped
' to an equivalent %VariableName% environment variable. CSIDLs are more reliable, however, and
' should be used if possible.
' ----------------------------------------------------------------------------------------------
Private Const CSIDL_DESKTOP                 As Long = 0
Private Const CSIDL_INTERNET                As Long = 1
Private Const CSIDL_PROGRAMS                As Long = 2
Private Const CSIDL_CONTROLS                As Long = 3
Private Const CSIDL_PRINTERS                As Long = 4
Private Const CSIDL_PERSONAL                As Long = 5
Private Const CSIDL_FAVORITES               As Long = 6
Private Const CSIDL_STARTUP                 As Long = 7
Private Const CSIDL_RECENT                  As Long = 8
Private Const CSIDL_SENDTO                  As Long = 9
Private Const CSIDL_BITBUCKET               As Long = 10
Private Const CSIDL_STARTMENU               As Long = 11
Private Const CSIDL_DESKTOPDIRECTORY        As Long = 16
Private Const CSIDL_DRIVES                  As Long = 17
Private Const CSIDL_NETWORK                 As Long = 18
Private Const CSIDL_NETHOOD                 As Long = 19
Private Const CSIDL_FONTS                   As Long = 20
Private Const CSIDL_TEMPLATES               As Long = 21
Private Const CSIDL_COMMON_STARTMENU        As Long = 22
Private Const CSIDL_COMMON_PROGRAMS         As Long = 23
Private Const CSIDL_COMMON_STARTUP          As Long = 24
Private Const CSIDL_COMMON_DESKTOPDIRECTORY As Long = 25
Private Const CSIDL_APPDATA                 As Long = 26
Private Const CSIDL_PRINTHOOD               As Long = 27
Private Const CSIDL_LOCAL_APPDATA           As Long = 28
Private Const CSIDL_ALTSTARTUP              As Long = 29
Private Const CSIDL_COMMON_ALTSTARTUP       As Long = 30
Private Const CSIDL_COMMON_FAVORITES        As Long = 31
Private Const CSIDL_INTERNET_CACHE          As Long = 32
Private Const CSIDL_COOKIES                 As Long = 33
Private Const CSIDL_HISTORY                 As Long = 34
Private Const CSIDL_COMMON_APPDATA          As Long = 35
Private Const CSIDL_WINDOWS                 As Long = 36
Private Const CSIDL_SYSTEM                  As Long = 37
Private Const CSIDL_PROGRAM_FILES           As Long = 38
Private Const CSIDL_MYPICTURES              As Long = 39
Private Const CSIDL_PROFILE                 As Long = 40
Private Const CSIDL_SYSTEMX86               As Long = 41
Private Const CSIDL_PROGRAM_FILESX86        As Long = 42
Private Const CSIDL_PROGRAM_FILES_COMMON    As Long = 43
Private Const CSIDL_PROGRAM_FILES_COMMONX86 As Long = 44
Private Const CSIDL_COMMON_TEMPLATES        As Long = 45
Private Const CSIDL_COMMON_DOCUMENTS        As Long = 46
Private Const CSIDL_COMMON_ADMINTOOLS       As Long = 47
Private Const CSIDL_ADMINTOOLS              As Long = 48
Private Const CSIDL_CONNECTIONS             As Long = 49
Private Const CSIDL_COMMON_MUSIC            As Long = 53
Private Const CSIDL_COMMON_PICTURES         As Long = 54
Private Const CSIDL_COMMON_VIDEO            As Long = 55
Private Const CSIDL_RESOURCES               As Long = 56
Private Const CSIDL_RESOURCES_LOCALIZED     As Long = 57
Private Const CSIDL_COMMON_OEM_LINKS        As Long = 58
Private Const CSIDL_CDBURN_AREA             As Long = 59
Private Const CSIDL_COMPUTERSNEARME         As Long = 61
Private Const CSIDL_FLAG_DONT_VERIFY        As Long = &H4000
Private Const CSIDL_FLAG_CREATE             As Long = &H8000
Private Const CSIDL_FLAG_MASK               As Long = &HFF00



' =====================================================================================================================
' @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Module Variables  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
' =====================================================================================================================



' =====================================================================================================================
' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Externals  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
' =====================================================================================================================



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function declaration identifies the Win32 API function that gets special directory path names.
' -----------------------------------------------------------------------------------------------------------
Private Declare Function SHGetFolderPath Lib "shfolder" Alias "SHGetFolderPathA" _
   ( _
   ByVal hwndOwner As Long, _
   ByVal nFolder As Long, _
   ByVal hToken As Long, _
   ByVal dwFlags As Long, _
   ByVal pszPath As String _
   ) As Long



' =====================================================================================================================
' @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Public Routines  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
' =====================================================================================================================



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's favorites directory.
'
' return
'    this function returns True if the favorites directory path name can be found.  Otherwise, it returns
'    False.  If this function returns True, then the path name of the favorites directory is stored in the
'    string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the favorites directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function favoritesDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   favoritesDirectory = specialDirectory(CSIDL_FAVORITES, pPath)
   if Not favoritesDirectory Then gMsg(1) = "favoritesDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's common favorites directory.
'
' return
'    this function returns True if the common favorites directory path name can be found.  Otherwise, it
'    returns False.  If this function returns True, then the path name of the common favorites directory is
'    stored in the string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the common favorites directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function commonFavoritesDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   commonFavoritesDirectory = specialDirectory(CSIDL_COMMON_FAVORITES, pPath)
   if Not commonFavoritesDirectory Then gMsg(1) = "commonFavoritesDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's application data directory.
'
' return
'    this function returns True if the application data directory path name can be found.  Otherwise, it
'    returns False.  If this function returns True, then the path name of the application data directory is
'    stored in the string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the application data directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function appdataDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   appdataDirectory = specialDirectory(CSIDL_APPDATA, pPath)
   if Not appdataDirectory Then gMsg(1) = "appdataDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's common application data directory.
'
' return
'    this function returns True if the common application data directory path name can be found.  Otherwise,
'    it returns False.  If this function returns True, then the path name of the common application data
'    directory is stored in the string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the common application data directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function commonAppdataDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   commonAppdataDirectory = specialDirectory(CSIDL_COMMON_APPDATA, pPath)
   if Not commonAppdataDirectory Then gMsg(1) = "commonAppdataDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's local application data directory.
'
' return
'    this function returns True if the local application data directory path name can be found.  Otherwise,
'    it returns False.  If this function returns True, then the path name of the local application data
'    directory is stored in the string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the local application data directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function localAppdataDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   localAppdataDirectory = specialDirectory(CSIDL_LOCAL_APPDATA, pPath)
   if Not localAppdataDirectory Then gMsg(1) = "localAppdataDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's documents directory.
'
' return
'    this function returns True if the documents directory path name can be found.  Otherwise, it returns
'    False.  If this function returns True, then the path name of the documents directory is stored in the
'    string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the documents directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function documentsDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   documentsDirectory = specialDirectory(CSIDL_PERSONAL, pPath)
   if Not documentsDirectory Then gMsg(1) = "documentsDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the current user's common documents directory.
'
' return
'    this function returns True if the common documents directory path name can be found.  Otherwise, it
'    returns False.  If this function returns True, then the path name of the common documents directory is
'    stored in the string pointed to by pPath when the function returns.
'
' param (output)
'    pPath is the string location to which the common documents directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function commonDocumentsDirectory(pPath As String, Optional pCreate As Boolean = False) As Boolean
   commonDocumentsDirectory = specialDirectory(CSIDL_COMMON_DOCUMENTS, pPath)
   if Not commonDocumentsDirectory Then gMsg(1) = "commonDocumentsDirectory:" & gMsg(1)
End Function



' ===========================================================================================================
' ===========================================================================================================
' ===========================================================================================================
' This function gets the path name of the special directory specified by the argument passed in through the
' CSIDL parameter.
'
' return
'    this function returns True if the specified directory path name can be found.  Otherwise, it returns
'    False.  If this function returns True, then the path name of the requestid directory is stored in the
'    string pointed to by pPath when the function returns.
'
' param
'    pDirectoryCSIDL is the CSIDL code that identifies the directory to get the path name of.
' param (output)
'    pPath is the string location to which the special directory path name is written.
' param (Optional)
'    pCreate is a boolean that if set to True will cause the requested directory to be created if it does
'    not already exist.  By default, this parameter is set to False and no directory is created.
' -----------------------------------------------------------------------------------------------------------
Public Function specialDirectory(pDirectoryCSIDL As Long, pPath As String, Optional pCreate As Boolean = False) As Boolean
   Dim retVal As Long
   Dim flag   As Long
   '
   ' ==============================================================================================
   ' make sure the return message string is cleared out so no garbage is accidentally returned.
   ' ----------------------------------------------------------------------------------------------
   gMsg(1) = ""
   '
   ' ==============================================================================================
   ' if the directory doesn't exist the user can request that it be created by setting the
   ' argument passed through the pCreate parameter to True.
   ' ----------------------------------------------------------------------------------------------
   If pCreate Then
      flag = CSIDL_FLAG_CREATE
   Else
      flag = 0
   End If
   '
   ' ==============================================================================================
   ' Fill our string buffer and go get the path name
   ' ----------------------------------------------------------------------------------------------
   pPath = String(MAX_PATH, 0)
   retVal = SHGetFolderPath(0, pDirectoryCSIDL Or flag, 0, SHGFP_TYPE_CURRENT, pPath)
   Select Case retVal
      '
      ' ==============================================================================================
      ' We retrieved the folder successfully All C strings are null terminated, so we need to return
      ' the string upto the first null character
      ' ----------------------------------------------------------------------------------------------
      Case cSuccess
         pPath = Left(pPath, InStr(1, pPath, Chr(0)) - 1)
         specialDirectory = True
      '
      ' ==============================================================================================
      ' The CSIDL in pDirectoryCSIDL is valid, but the folder does not exist.  Use CSIDL_FLAG_CREATE
      ' to have it created automatically
      ' ----------------------------------------------------------------------------------------------
      Case cDoesNotExist
         gMsg(1) = "specialDirectory: Directory does not exist and it's creation was not requested."
         specialDirectory = False
      '
      ' ==============================================================================================
      ' pDirectoryCSIDL is invalid
      ' ----------------------------------------------------------------------------------------------
      Case cInvalidCSIDL
         gMsg(1) = "specialDirectory: Invalid special directory."
         specialDirectory = False
   End Select
End Function