Make WinVNC service mode work on Windows Vista and beyond.
Patch by Jochen Tucht, fixes bug 135.



git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@5158 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/release/tigervnc.iss.in b/release/tigervnc.iss.in
index 1976840..a27b971 100644
--- a/release/tigervnc.iss.in
+++ b/release/tigervnc.iss.in
@@ -56,3 +56,112 @@
 Filename: "{app}\winvnc4.exe"; Parameters: "-register"; Tasks: installservice
 Filename: "net"; Parameters: "start winvnc4"; Tasks: startservice
 #endif
+
+#ifdef BUILD_WINVNC
+[Code]
+
+{--- IShellLink ---}
+
+const
+  CLSID_ShellLink = '{00021401-0000-0000-C000-000000000046}';
+  SLDF_RUNAS_USER = $2000;
+
+type
+  IShellLinkW = interface(IUnknown)
+    '{000214F9-0000-0000-C000-000000000046}'
+    procedure Dummy;
+    procedure Dummy2;
+    procedure Dummy3;
+    function GetDescription(pszName: String; cchMaxName: Integer): HResult;
+    function SetDescription(pszName: String): HResult;
+    function GetWorkingDirectory(pszDir: String; cchMaxPath: Integer): HResult;
+    function SetWorkingDirectory(pszDir: String): HResult;
+    function GetArguments(pszArgs: String; cchMaxPath: Integer): HResult;
+    function SetArguments(pszArgs: String): HResult;
+    function GetHotkey(var pwHotkey: Word): HResult;
+    function SetHotkey(wHotkey: Word): HResult;
+    function GetShowCmd(out piShowCmd: Integer): HResult;
+    function SetShowCmd(iShowCmd: Integer): HResult;
+    function GetIconLocation(pszIconPath: String; cchIconPath: Integer;
+      out piIcon: Integer): HResult;
+    function SetIconLocation(pszIconPath: String; iIcon: Integer): HResult;
+    function SetRelativePath(pszPathRel: String; dwReserved: DWORD): HResult;
+    function Resolve(Wnd: HWND; fFlags: DWORD): HResult;
+    function SetPath(pszFile: String): HResult;
+  end;
+
+  IShellLinkDataList = interface(IUnknown)
+    '{45E2B4AE-B1C3-11D0-B92F-00A0C90312E1}'
+    function AddDataBlock(pDataBlock : DWORD) : HResult;
+    function CopyDataBlock(dwSig : DWORD; var ppDataBlock : DWORD) : HResult;
+    function RemoveDataBlock(dwSig : DWORD) : HResult;
+    function GetFlags(var pdwFlags : DWORD) : HResult;
+    function SetFlags(dwFlags : DWORD) : HResult;
+  end;
+
+  IPersist = interface(IUnknown)
+    '{0000010C-0000-0000-C000-000000000046}'
+    function GetClassID(var classID: TGUID): HResult;
+  end;
+
+  IPersistFile = interface(IPersist)
+    '{0000010B-0000-0000-C000-000000000046}'
+    function IsDirty: HResult;
+    function Load(pszFileName: String; dwMode: Longint): HResult;
+    function Save(pszFileName: String; fRemember: BOOL): HResult;
+    function SaveCompleted(pszFileName: String): HResult;
+    function GetCurFile(out pszFileName: String): HResult;
+  end;
+
+var
+  OSVersion: TWindowsVersion;
+
+function InitializeSetup: Boolean;
+begin
+  GetWindowsVersionEx(OSVersion);
+  Result := True;
+end;
+
+procedure SetRunAsUserFlag(Path: String);
+var
+  Obj: IUnknown;
+  SL: IShellLinkW;
+  SDL: IShellLinkDataList;
+  PF: IPersistFile;
+  Flags: DWord;
+begin
+  Obj := CreateComObject(StringToGuid(CLSID_ShellLink));
+  SL := IShellLinkW(Obj);
+  PF := IPersistFile(Obj);
+  SDL := IShellLinkDataList(Obj);
+  Path := ExpandConstant(Path);
+  OleCheck(PF.Load(Path, 0));
+  OleCheck(SDL.GetFlags(Flags));
+  OleCheck(SDL.SetFlags(Flags or SLDF_RUNAS_USER));
+  OleCheck(PF.Save(Path, True));
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+  Flags: DWord;
+begin
+  { Post-install actions on Windows Vista and higher:
+    o Modify Service-Mode start menu commands so they run as administrator.
+    o Set up the SoftwareSASGeneration system policy so as to allow services to simulate Ctrl+Alt+Del. }
+  if (CurStep = ssPostInstall) and (OSVersion.Major >= 6) then begin
+    SetRunAsUserFlag('{group}\VNC Server (Service-Mode)\Configure VNC Service.lnk');
+    SetRunAsUserFlag('{group}\VNC Server (Service-Mode)\Register VNC Service.lnk');
+    SetRunAsUserFlag('{group}\VNC Server (Service-Mode)\Unregister VNC Service.lnk');
+    SetRunAsUserFlag('{group}\VNC Server (Service-Mode)\Start VNC Service.lnk');
+    SetRunAsUserFlag('{group}\VNC Server (Service-Mode)\Stop VNC Service.lnk');
+    if not RegQueryDWordValue(
+      HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',
+      'SoftwareSASGeneration', Flags
+    ) then Flags := 0;
+    RegWriteDWordValue(
+      HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',
+      'SoftwareSASGeneration', Flags or 1
+    );
+  end;
+end;  
+#endif