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开发者_Go百科/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)
A service should be able to read the HKLM hive. When you create the Registry handle make sure you set the Access setting to KEY_READ (ARegHandle.Access := KEY_READ;) and also when you open the key, open in it with Create as false or OpenReadOnly.
Turns out that the problem has nothing to do with the port not being visible under netstat. I ran another test with a prior build on a Win7 machine and even when netstat doesn't show the port listening either as Administrator or a regular user, then browsers can still bind to the port (why would this be?)
What's actually happening is that MyNetApp.exe is failing to run correctly (only on Win7) since when running under the NT AUTHORITY\SYSTEM account it isn't able to read files in C:\ProgramData\ (%ALLUSERPROFILE%) -- it needs files that my client is placing in subfolders under there.
When I check "Effective Permissions" for the SYSTEM user on these files I'm getting Full Control.
What's going on?
UPDATE: No that's not it either. MyNetApp.exe is being told where it's config files are by reading a string in HKEY_LOCAL_MACHINE\SOFTWARE\MyCompany\MyApp\ which I set during install (to %ALLUSERPROFILE%\MyCompany\MyApp. Seems what it's getting is an empty string, which is breaking it. Why on earth would NT AUTHORITY\SYSTEM not be getting the same string as the one I set in the installer (running with elevated privileges so it can install the service)
精彩评论