use Win32::API; use strict; use warnings; BEGIN { # for static vars. my %CSIDL_Constants = ( # Types are: VF - Virtual Folder| W - From Wine, no MS docs to check against| NT - Avail on NT(+?) only, # Shell32.DLL versions : 4.71 - All IE4.0 | 4.72 - All IE4.01/98 | 5.0 - W2k/Me+ # Look into ShFolder.dll if you have trouble. # http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/reference/functions/shgetspecialfolderpath.asp # Name Value Type Comment/Example Return # ----------------------------------------------------------------------------------------------------------------- DESKTOP => 0x0000, # VF -- Root of namespace INTERNET => 0x0001, # VF -- The internet PROGRAMS => 0x0002, # -- C:\Documents and Settings\username\Start Menu\Programs CONTROLS => 0x0003, # VF -- Icons for control panel PRINTERS => 0x0004, # VF -- Installed Printers PERSONAL => 0x0005, # -- C:\Documents and Settings\username\My Documents FAVORITES => 0x0006, # -- C:\Documents and Settings\username\Favorites STARTUP => 0x0007, # -- C:\Documents and Settings\username\Start Menu\Programs\Startup RECENT => 0x0008, # -- C:\Documents and Settings\username\Recent SENDTO => 0x0009, # -- C:\Documents and Settings\username\SendTo BITBUCKET => 0x000a, # VF -- Recycling bin STARTMENU => 0x000b, # -- C:\Documents and Settings\username\Start Menu MYDOCUMENTS => 0x000c, # W -- ?? MYMUSIC => 0x000d, # -- C:\My Music MYVIDEO => 0x000e, # W -- ?? DESKTOPDIRECTORY => 0x0010, # -- C:\Documents and Settings\username\Desktop DESKTOPDIR => 0x0010, # -- C:\Documents and Settings\username\Desktop DRIVES => 0x0011, # VF -- My Computer NETWORK => 0x0012, # VF -- Root of network namespace hierarchy NETHOOD => 0x0013, # -- C:\Documents and Settings\username\NetHood FONTS => 0x0014, # VF -- C:\WINNT\Fonts TEMPLATES => 0x0015, # -- Document templates COMMON_STARTMENU => 0x0016, # NT -- C:\Documents and Settings\All Users\Start Menu, COMMON_PROGRAMS => 0x0017, # NT -- C:\Documents and Settings\All Users\Start Menu\Programs COMMON_STARTUP => 0x0018, # NT -- C:\Documents and Settings\All Users\Start Menu\Programs\Startup COMMON_DESKTOPDIR => 0x0019, # -- C:\Documents and Settings\All Users\Desktop COMMON_DESKTOPDIRECTORY => 0x0019, # -- C:\Documents and Settings\All Users\Desktop APPDATA => 0x001a, # 4.71 -- C:\Documents and Settings\username\Application Data PRINTHOOD => 0x001b, # -- C:\Documents and Settings\username\PrintHood LOCAL_APPDATA => 0x001c, # 5.0 -- C:\Documents and Settings\username\Local Settings\Application Data ALTSTARTUP => 0x001d, # -- nonlocalized startup group COMMON_ALTSTARTUP => 0x001e, # NT -- All users nonlocalized startup COMMON_FAVORITES => 0x001f, # NT -- Favorite items INTERNET_CACHE => 0x0020, # 4.72 -- C:\Documents and Settings\username\Temporary Internet Files COOKIES => 0x0021, # -- C:\Documents and Settings\username\Cookies HISTORY => 0x0022, # -- Internet History COMMON_APPDATA => 0x0023, # 5.0 -- C:\Documents and Settings\All Users\Application Data WINDOWS => 0x0024, # 5.0 -- %windir% == %SYSTEMROOT% == C:\WINNT SYSTEM => 0x0025, # 5.0 -- C:\WINNT\SYSTEM32 PROGRAM_FILES => 0x0026, # 5.0 -- C:\Program Files MYPICTURES => 0x0027, # 5.0 -- C:\Documents and Settings\username\My Documents\My Pictures PROFILE => 0x0028, # 5.0 -- Users profile folder SYSTEMX86 => 0x0029, # W -- ?? PROGRAM_FILESX86 => 0x002a, # W -- ?? PROGRAM_FILES_COMMON => 0x002b, # 5.0/NT+ -- C:\Program Files\Common PROGRAM_FILES_COMMONX86 => 0x002c, # W -- ?? COMMON_TEMPLATES => 0x002d, # W -- ?? COMMON_DOCUMENTS => 0x002e, # -- C:\Documents and Settings\All Users\Documents COMMON_ADMINTOOLS => 0x002f, # 5.0 -- MMC Admin tools dir for all users. ADMINTOOLS => 0x0030, # 5.0 -- MMC Admin tools directory for user CONNECTIONS => 0x0031, # W -- ?? COMMON_MUSIC => 0x0035, # W -- ?? COMMON_PICTURES => 0x0036, # W -- ?? COMMON_VIDEO => 0x0037, # W -- ?? RESOURCES => 0x0038, # W -- ?? RESOURCES_LOCALIZED => 0x0039, # W -- ?? COMMON_OEM_LINKS => 0x003a, # W -- ?? CDBURN_AREA => 0x003b, # W -- ?? COMPUTERSNEARME => 0x003d, # W -- ?? # FLAG_CREATE 0x8000 # FLAG_DONT_VERIFY 0x4000 # FLAG_MASK 0xff00 # FLAG_NO_ALIAS 0x1000 # FLAG_PER_USER_INIT 0x0800 # FOLDER_MASK 0x00ff ); my $GetWindowsDirectory = Win32::API->new( "KERNEL32", "GetWindowsDirectoryA", [ "P", "N" ], "N" ); # Returns the windows directory, equiv to %windir% but slightly safer sub GetWindowsDirectory { my $buffer = "\0" x 255; $GetWindowsDirectory->Call( $buffer, length $buffer ); $buffer =~ tr/\0//d; return $buffer; }; my $SHGetSpecialFolderPath = Win32::API->new( "SHELL32", "SHGetSpecialFolderPath", [ "P", "P", "I", "I" ], "I" ); # Returns the paths of special windows folders, sub GetSpecialFolderPath { my @csidl = @_; @csidl = keys %CSIDL_Constants unless @csidl; my %ret; foreach (@csidl) { my $buffer = "\0" x 255; # Preinit the buffer my $hWnd = ""; # this isnt used (afaict) #0 for no create my $r = $SHGetSpecialFolderPath->Call( $hWnd, $buffer, $CSIDL_Constants{$_}, 0 ); if ($r) { $buffer =~ tr/\0//d; # remove the \0 chars $ret{$_} = $buffer; # save the result } else { $ret{$_} = undef; } } return %ret if wantarray; return ( @csidl > 1 ) ? \%ret : $ret{ $csidl[0] }; } } # Demo usage # Print out the windir and the special folders... $\ = "\n"; print GetWindowsDirectory(); use Data::Dumper; my %hash = GetSpecialFolderPath(); print Dumper( \%hash );