2
0
Эх сурвалжийг харах

Cleanup and improve the support for {userpf}, {usercf}, and {usersavedgames}.

Martijn Laan 1 жил өмнө
parent
commit
00701e734d

+ 0 - 4
ISHelp/isxfunc.xml

@@ -2959,10 +2959,6 @@ end;</pre></example>
      <description>Reg* - RootKey values (also see the <link topic="registrysection" window="main">[Registry]</link> section documentation)</description>
      <values>HKEY_AUTO, HKEY_AUTO_32, HKEY_AUTO_64,<br />HKEY_CLASSES_ROOT, HKEY_CLASSES_ROOT_32, HKEY_CLASSES_ROOT_64,<br />HKEY_CURRENT_USER, HKEY_CURRENT_USER_32, HKEY_CURRENT_USER_64,<br />HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE_32, HKEY_LOCAL_MACHINE_64,<br />HKEY_USERS, HKEY_USERS_32, HKEY_USERS_64,<br />HKEY_PERFORMANCE_DATA,<br />HKEY_CURRENT_CONFIG, HKEY_CURRENT_CONFIG_32, HKEY_CURRENT_CONFIG_64,<br />HKEY_DYN_DATA,<br />HKA, HKA32, HKA64, HKCR, HKCR32, HKCR64, HKCU, HKCU32, HKCU64, HKLM, HKLM32, HKLM64, HKU, HKU32, HKU64, HKCC, HKCC32, HKCC64</values>
   </enum>
-  <enum>
-     <description>TShellFolderID</description>
-     <values>sfDesktop, sfStartMenu, sfPrograms, sfStartup, sfSendTo, sfFonts, sfAppData, sfDocs, sfTemplates, sfFavorites, sfLocalAppData</values>
-  </enum>
   <enum>
      <description>TSetupMessageID</description>
      <values>Use 'msg' + the message name. Example: <i>SetupMessage(msgSetupAppTitle)</i></values>

+ 4 - 4
Projects/Compile.pas

@@ -2710,8 +2710,8 @@ function TSetupCompiler.CheckConst(const S: String; const MinVersion: TSetupVers
   end;
 
 const
-  UserConsts: array[0..3] of String = (
-    'userpf', 'usercf', 'usersavedgames', 'username');
+  UserConsts: array[0..0] of String = (
+    'username');
   Consts: array[0..42] of String = (
     'src', 'srcexe', 'tmp', 'app', 'win', 'sys', 'sd', 'groupname', 'commonfonts', 'hwnd',
     'commonpf', 'commonpf32', 'commonpf64', 'commoncf', 'commoncf32', 'commoncf64',
@@ -2720,10 +2720,10 @@ const
     'userinfoname', 'userinfoorg', 'userinfoserial', 'uninstallexe',
     'language', 'syswow64', 'sysnative', 'log', 'dotnet11', 'dotnet20', 'dotnet2032',
     'dotnet2064', 'dotnet40', 'dotnet4032', 'dotnet4064');
-  UserShellFolderConsts: array[0..10] of String = (
+  UserShellFolderConsts: array[0..13] of String = (
     'userdesktop', 'userstartmenu', 'userprograms', 'userstartup',
     'userappdata', 'userdocs', 'usertemplates', 'userfavorites', 'usersendto', 'userfonts',
-    'localappdata');
+    'localappdata', 'userpf', 'usercf', 'usersavedgames');
   ShellFolderConsts: array[0..16] of String = (
     'group', 'commondesktop', 'commonstartmenu', 'commonprograms', 'commonstartup',
     'commonappdata', 'commondocs', 'commontemplates',

+ 56 - 61
Projects/Main.pas

@@ -52,6 +52,10 @@ type
     seTask, seDir, seFile, seFileLocation, seIcon, seIni, seRegistry,
     seInstallDelete, seUninstallDelete, seRun, seUninstallRun);
 
+  TShellFolderID = (sfDesktop, sfStartMenu, sfPrograms, sfStartup, sfSendTo,  //these have common and user versions
+    sfFonts, sfAppData, sfDocs, sfTemplates,                                  //
+    sfFavorites, sfLocalAppData, sfUserProgramFiles, sfUserCommonFiles, sfUserSavedGames); //these only have user versions
+
 const
   EntryStrings: array[TEntryType] of Integer = (SetupLanguageEntryStrings,
     SetupCustomMessageEntryStrings, SetupPermissionEntryStrings,
@@ -125,7 +129,7 @@ var
   { 'Constants' }
   SourceDir, TempInstallDir, WinDir, WinSystemDir, WinSysWow64Dir, WinSysNativeDir, SystemDrive,
     ProgramFiles32Dir, CommonFiles32Dir, ProgramFiles64Dir, CommonFiles64Dir,
-    ProgramFilesUserDir, CommonFilesUserDir, SavedGamesUserDir, CmdFilename, SysUserInfoName,
+    CmdFilename, SysUserInfoName,
     SysUserInfoOrg, UninstallExeFilename: String;
 
   { Uninstall 'constants' }
@@ -1021,13 +1025,16 @@ function ExpandIndividualConst(Cnst: String;
   end;
 
 const
-  FolderConsts: array[Boolean, TShellFolderID] of String =
-    (('userdesktop', 'userstartmenu', 'userprograms', 'userstartup',
-      'usersendto', 'commonfonts', 'userappdata', 'userdocs', 'usertemplates',
-      'userfavorites', 'localappdata'),
-     ('commondesktop', 'commonstartmenu', 'commonprograms', 'commonstartup',
-      'usersendto', 'commonfonts', 'commonappdata', 'commondocs', 'commontemplates',
-      'commonfavorites' { not accepted anymore by the compiler }, 'localappdata'));
+  FolderConsts: array[Boolean, TShellFolderID] of String = (
+    { Also see FolderIDs }
+    { User }
+    ('userdesktop', 'userstartmenu', 'userprograms', 'userstartup',
+     'usersendto', 'commonfonts', 'userappdata', 'userdocs', 'usertemplates',
+     'userfavorites', 'localappdata', 'userpf', 'usercf', 'usersavedgames'),
+    { Common }
+    ('commondesktop', 'commonstartmenu', 'commonprograms', 'commonstartup',
+     'usersendto', 'commonfonts', 'commonappdata', 'commondocs', 'commontemplates',
+     'commonfavorites' { not accepted anymore by the compiler }, '', '', '', ''));
   NoUninstallConsts: array[0..6] of String =
     ('src', 'srcexe', 'userinfoname', 'userinfoorg', 'userinfoserial', 'hwnd',
      'wizardhwnd');
@@ -1079,24 +1086,12 @@ begin
   else if Cnst = 'srcexe' then Result := SetupLdrOriginalFilename
   else if Cnst = 'tmp' then Result := TempInstallDir
   else if Cnst = 'sd' then Result := SystemDrive
-  else if Cnst = 'userpf' then begin
-    if ProgramFilesUserDir <> '' then
-      Result := ProgramFilesUserDir
-    else
-      Result := ExpandConst('{localappdata}\Programs'); { supply default, same as Window 7 and newer }
-  end
   else if Cnst = 'commonpf' then begin
     if Is64BitInstallMode then
       Result := ProgramFiles64Dir
     else
       Result := ProgramFiles32Dir;
   end
-  else if Cnst = 'usercf' then begin
-    if CommonFilesUserDir <> '' then
-      Result := CommonFilesUserDir
-    else
-      Result := ExpandConst('{localappdata}\Programs\Common'); { supply default, same as Window 7 and newer }
-  end
   else if Cnst = 'commoncf' then begin
     if Is64BitInstallMode then
       Result := CommonFiles64Dir
@@ -1117,7 +1112,6 @@ begin
     else
       InternalError('Cannot expand "' + OriginalCnst + '" constant on this version of Windows');
   end
-  else if Cnst = 'usersavedgames' then Result := SavedGamesUserDir
   else if Cnst = 'userfonts' then Result := ExpandConst('{localappdata}\Microsoft\Windows\Fonts') { supported by Windows 10 Version 1803 and newer. doesn't have a KNOWNFOLDERID. }
   else if Cnst = 'dao' then Result := ExpandConst('{cf}\Microsoft Shared\DAO')
   else if Cnst = 'cmd' then Result := CmdFilename
@@ -1340,13 +1334,6 @@ procedure InitMainNonSHFolderConsts;
     end;
   end;
 
-const
-  FOLDERID_UserProgramFiles: TGUID = (D1:$5CD7AEE2; D2:$2219; D3:$4A67; D4:($B8,$5D,$6C,$9C,$E1,$56,$60,$CB));
-  FOLDERID_UserProgramFilesCommon: TGUID = (D1:$BCBD3057; D2:$CA5C; D3:$4622; D4:($B4,$2D,$BC,$56,$DB,$0A,$E5,$16));
-  FOLDERID_SavedGames: TGUID = (D1:$4C5C32FF; D2:$BB9D; D3:$43B0; D4:($B5,$B4,$2D,$72,$E5,$4E,$AA,$A4));
-  KF_FLAG_CREATE = $00008000;
-var
-  Path: PWideChar;
 begin
   { Read Windows and Windows System dirs }
   WinDir := GetWinDir;
@@ -1384,34 +1371,6 @@ begin
       InternalError('Failed to get path of 64-bit Common Files directory');
   end;
 
-  { Get dirs which have no CSIDL equivalent and cannot be retrieved using SHGetFolderPath. }
-  if Assigned(SHGetKnownFolderPathFunc) and (WindowsVersion shr 16 >= $0600) then begin
-    var dwFlags: DWORD := 0;
-    if not IsAdminInstallMode then
-      dwFlags := dwFlags or KF_FLAG_CREATE;
-    if SHGetKnownFolderPathFunc(FOLDERID_UserProgramFiles {Windows 7+}, dwFlags, 0, Path) = S_OK then begin
-      try
-        ProgramFilesUserDir := WideCharToString(Path);
-      finally
-        CoTaskMemFree(Path);
-      end;
-    end;
-    if SHGetKnownFolderPathFunc(FOLDERID_UserProgramFilesCommon {Windows 7+}, dwFlags, 0, Path) = S_OK then begin
-      try
-        CommonFilesUserDir := WideCharToString(Path);
-      finally
-        CoTaskMemFree(Path);
-      end;
-    end;
-    if SHGetKnownFolderPathFunc(FOLDERID_SavedGames {Vista+}, dwFlags, 0, Path) = S_OK then begin
-      try
-        SavedGamesUserDir := WideCharToString(Path);
-      finally
-        CoTaskMemFree(Path);
-      end;
-    end;
-  end;
-  
   { Get path of command interpreter }
   if IsNT then
     CmdFilename := AddBackslash(WinSystemDir) + 'cmd.exe'
@@ -1565,6 +1524,8 @@ var
   Res: HRESULT;
   Buf: array[0..MAX_PATH-1] of Char;
 begin
+  { Note: Must pass Create=True or else SHGetFolderPath fails if the
+    specified CSIDL is valid but doesn't currently exist. }
   if Create then
     Folder := Folder or CSIDL_FLAG_CREATE;
 
@@ -1595,6 +1556,27 @@ begin
   end;
 end;
 
+function GetShellFolderByGUID(Folder: TGUID; const Create: Boolean): String;
+begin
+  if Assigned(SHGetKnownFolderPathFunc) and (WindowsVersion shr 16 >= $0600) then begin
+    var dwFlags: DWORD := 0;
+    if Create then
+      dwFlags := dwFlags or KF_FLAG_CREATE;
+    var Path: PWideChar;
+    { Note: Must pass Create=True or else SHGetKnownFolderPath fails if the
+      specified GUID is valid but doesn't currently exist. }
+    var Res := SHGetKnownFolderPathFunc(Folder, dwFlags, 0, Path);
+    if Res = S_OK then begin
+      Result := WideCharToString(Path);
+      CoTaskMemFree(Path);
+    end else begin
+      Result := '';
+      LogFmt('Warning: SHGetKnownFolderPath failed with code 0x%.8x', [Res]);
+    end;
+  end else
+    Result := '';
+end;
+
 function GetShellFolder(const Common: Boolean; const ID: TShellFolderID;
   ReadOnly: Boolean): String;
 const
@@ -1609,21 +1591,34 @@ const
   CSIDL_COMMON_TEMPLATES = $002D;
   CSIDL_COMMON_DOCUMENTS = $002E;
   FolderIDs: array[Boolean, TShellFolderID] of Integer = (
+    { Values must match FolderConsts }
     { User }
     (CSIDL_DESKTOPDIRECTORY, CSIDL_STARTMENU, CSIDL_PROGRAMS, CSIDL_STARTUP,
      CSIDL_SENDTO, CSIDL_FONTS, CSIDL_APPDATA, CSIDL_PERSONAL,
-     CSIDL_TEMPLATES, CSIDL_FAVORITES, CSIDL_LOCAL_APPDATA),
+     CSIDL_TEMPLATES, CSIDL_FAVORITES, CSIDL_LOCAL_APPDATA, 0, 0, 0),
     { Common }
     (CSIDL_COMMON_DESKTOPDIRECTORY, CSIDL_COMMON_STARTMENU, CSIDL_COMMON_PROGRAMS, CSIDL_COMMON_STARTUP,
      CSIDL_SENDTO, CSIDL_FONTS, CSIDL_COMMON_APPDATA, CSIDL_COMMON_DOCUMENTS,
-     CSIDL_COMMON_TEMPLATES, CSIDL_COMMON_FAVORITES, CSIDL_LOCAL_APPDATA));
+     CSIDL_COMMON_TEMPLATES, CSIDL_COMMON_FAVORITES, 0, 0, 0, 0));
+  FOLDERID_UserProgramFiles: TGUID = (D1:$5CD7AEE2; D2:$2219; D3:$4A67; D4:($B8,$5D,$6C,$9C,$E1,$56,$60,$CB));
+  FOLDERID_UserProgramFilesCommon: TGUID = (D1:$BCBD3057; D2:$CA5C; D3:$4622; D4:($B4,$2D,$BC,$56,$DB,$0A,$E5,$16));
+  FOLDERID_SavedGames: TGUID = (D1:$4C5C32FF; D2:$BB9D; D3:$43B0; D4:($B5,$B4,$2D,$72,$E5,$4E,$AA,$A4));
 var
   ShellFolder: String;
 begin
   if not ShellFoldersRead[Common, ID] then begin
-    { Note: Must pass Create=True or else SHGetFolderPath fails if the
-      specified CSIDL is valid but doesn't currently exist. }
-    ShellFolder := GetShellFolderByCSIDL(FolderIDs[Common, ID], not ReadOnly);
+    if ID = sfUserProgramFiles then begin
+      ShellFolder := GetShellFolderByGUID(FOLDERID_UserProgramFiles {Windows 7+}, not ReadOnly);
+      if ShellFolder = '' then
+        ShellFolder := ExpandConst('{localappdata}\Programs'); { supply default, same as Window 7 and newer }
+    end else if ID = sfUserCommonFiles then begin
+      ShellFolder := GetShellFolderByGUID(FOLDERID_UserProgramFilesCommon {Windows 7+}, True);
+      if ShellFolder = '' then
+        ShellFolder := ExpandConst('{localappdata}\Programs\Common'); { supply default, same as Window 7 and newer }
+    end else if ID = sfUserSavedGames then
+      ShellFolder := GetShellFolderByGUID(FOLDERID_SavedGames {Vista+}, True)
+    else
+      ShellFolder := GetShellFolderByCSIDL(FolderIDs[Common, ID], not ReadOnly);
     ShellFolders[Common, ID] := ShellFolder;
     if not ReadOnly or (ShellFolder <> '') then
       ShellFoldersRead[Common, ID] := True;

+ 0 - 1
Projects/ScriptFunc_C.pas

@@ -109,7 +109,6 @@ begin
     'end');
 
   RegisterRealEnum('TMsgBoxType', TypeInfo(TMsgBoxType));
-  RegisterRealEnum('TShellFolderID', TypeInfo(TShellFolderID));
   RegisterRealEnum('TSetupMessageID', TypeInfo(TSetupMessageID));
   RegisterRealEnum('TSetupStep', TypeInfo(TSetupStep));
   RegisterRealEnum('TUninstallStep', TypeInfo(TUninstallStep));

+ 0 - 3
Projects/SetupTypes.pas

@@ -37,9 +37,6 @@ const
   wpFinished = 14;
 
 type
-  TShellFolderID = (sfDesktop, sfStartMenu, sfPrograms, sfStartup, sfSendTo,
-    sfFonts, sfAppData, sfDocs, sfTemplates, sfFavorites, sfLocalAppData);
-
   TInstallOnThisVersionResult = (irInstall, irNotOnThisPlatform,
     irVersionTooLow, irServicePackTooLow, irVerTooHigh);
     

+ 2 - 1
whatsnew.htm

@@ -30,8 +30,9 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
 
 <p><a name="6.2.3"></a><span class="ver">6.2.3-dev </span><span class="date">(?)</span></p>
 <ul>
-  <li>If Setup was starting in administrative install mode it would ask Windows to create any missing <tt>{usercf}</tt>, <tt>{userpf}</tt>, and <tt>{usersavedgames}</tt> folders. It no longer does this because it violates the <a href="https://jrsoftware.org/ishelp/index.php?topic=setup_useduserareaswarning">used user areas warning</a>.</li>
+  <li>During startup Setup would always ask Windows to create any missing <tt>{usercf}</tt>, <tt>{userpf}</tt>, and <tt>{usersavedgames}</tt> folders. It no longer does until the script asks for the folder. Note that scripts running in administrative install mode should not do this because it violates the <a href="https://jrsoftware.org/ishelp/index.php?topic=setup_useduserareaswarning">used user areas warning</a>.</li>
   <li>Added support for IIS group users identifiers (<tt>iisiusrs</tt>) for use in <tt>Permissions</tt> parameters, contributed by Achim Stuy.</li> 
+  <li>Pascal Scripting change: type <tt>TShellFolderID</tt> was removed because it wasn't used by any support function.</a>
   <li>Added official Korean translation.</li>
 </ul>