Here's the code (in a standard TService in Delphi):
const
ProcessExe = 'MyNetApp.exe';
function RunService: Boolean;
var
StartInfo : TStartupInfo;
ProcInfo : TProcessInformation;
CreateOK : Boolean;
begin
CreateOK := false;
FillChar(StartInfo,SizeOf(TStartupInfo),#0);
FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
StartInfo.cb := SizeOf(TStartupInfo);
CreateOK := CreateProcess(nil, PChar(ProcessEXE),nil,nil,False,
CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
nil, PChar(InstallDir), StartInfo, ProcInfo);
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
Result := CreateOK;
end;
procedure TServicel.ServiceExecute(Sender: TService);
const
IntervalsBetweenRuns = 4; //no of IntTimes between checks
IntTime = 250; //ms
var
Count: SmallInt;
begin
Count := IntervalsBetweenRuns; //first time run immediately
while not Terminated do
begin
Inc(Count);
if Count >= IntervalsBetweenRuns then
begin
Count := 0;
//We check to see if the process is running,
//if not we run it. That's all there is to it.
//if ProcessEXE crashes, this service host will just rerun it
if processExists(ProcessEXE)=0 then
RunService;
end;
Sleep(IntTime);
ServiceThread.ProcessRequests(False);
end;
end;
MyNetApp.exe is a SOCKS5 proxy listening on port 9870. Users configure their browser to this proxy which acts as a secure-tunnel/anonymizer.
All works perfectly fine on 2000/XP/2003, but on Vista/Win7 with UAC the service runs in Session0 under LocalSystem and port 9870 doesn't show up in netstat for the logged-in user or Administrator.
Seems UAC is getting in my way.
Is there something I can do with the SECURITY_ATTRIBUTES or CreateProcess, or is there something I can do with CreateProcessAsUser or impersonation to ensure that a network socket on a service is available to logged-in users on the system (note, this app is for mass deployment, I don't have access to user credentials, and require the user elevate their privileges to install a service on Vista/Win7)