<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JEDI Windows API &#187; Service</title>
	<atom:link href="http://blog.delphi-jedi.net/tag/service/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.delphi-jedi.net</link>
	<description>Joint Endeavor of Delphi Innovators of Windows Programming</description>
	<lastBuildDate>Wed, 19 Oct 2011 18:52:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Service and application in single EXE? Update</title>
		<link>http://blog.delphi-jedi.net/2008/05/10/service-and-application-in-single-exe/</link>
		<comments>http://blog.delphi-jedi.net/2008/05/10/service-and-application-in-single-exe/#comments</comments>
		<pubDate>Sat, 10 May 2008 19:50:14 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[Service]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=189</guid>
		<description><![CDATA[Creating a binary file that consists of a service and a normal application can be done very simple without using the service manager. Just check for SYSTEM account. It is very unlikely that your app is run as SYSTEM (only RunAsSys does ). uses &#8230;, JwsclToken; begin &#160; if JwIsSystem then &#160; begin &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>Creating a binary file that consists of a service and a normal application can be done very simple without using the service manager. Just check for SYSTEM account. It is very unlikely that your app is run as SYSTEM (only RunAsSys does ).</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> &#8230;, JwsclToken;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="kw1">if</span> JwIsSystem <span class="kw1">then</span><br />
&nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; Application.<span class="kw3">Initialize</span>;<br />
&nbsp; &nbsp; Application.<span class="me1">CreateForm</span><span class="br0">&#40;</span>TMyService, MyService<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; Application.<span class="me1">Run</span>;<br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; <span class="kw1">begin</span><br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<h3>Update</h3>
<p>Mark Robinson suggested (in a comment) to check for a &#8220;service.exe&#8221; parent process. Since I did not find a solution within seconds, I decided to show how it works. Quite in handy came a <a href="http://www.codeproject.com/KB/threads/ParentPID.aspx">CodeProject article</a> about finding a parent process. The code is also available through <a href="http://blog.delphi-jedi.net/wp-content/uploads/2008/05/getparentprocess.zip">download</a>. Use it on your own risk.</p>
<h3><span id="more-189"></span></h3>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">function</span> GetParentProcess<span class="br0">&#40;</span>out ProcessEntry32 : TProcessEntry32W; <span class="kw1">const</span> ProcessID : <span class="kw4">DWORD</span> = <span class="nu0">0</span><span class="br0">&#41;</span> : <span class="kw4">DWORD</span>; <span class="kw1">overload</span>;</p>
<p><span class="kw1">function</span> InternalGetParentProcess<span class="br0">&#40;</span><br />
&nbsp; <span class="kw1">const</span> Condition : <span class="kw4">Boolean</span>;<br />
&nbsp; out ProcessEntry32 : TProcessEntry32W; <span class="kw1">const</span> ProcessID : <span class="kw4">DWORD</span> = <span class="nu0">0</span><span class="br0">&#41;</span> : <span class="kw4">DWORD</span>;<br />
<span class="kw1">var</span><br />
&nbsp; hSnap : <span class="kw4">THandle</span>;<br />
&nbsp; ProcEntry : TProcessEntry32W;<br />
&nbsp; currentID : <span class="kw4">DWORD</span>;<br />
&nbsp; <span class="kw3">Continue</span> : <span class="kw4">Boolean</span>;</p>
<p><span class="kw1">begin</span><br />
&nbsp; hSnap := CreateToolhelp32Snapshot<span class="br0">&#40;</span>TH32CS_SNAPPROCESS, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; result := INVALID_HANDLE_VALUE;</p>
<p>&nbsp; ZeroMemory<span class="br0">&#40;</span>@ProcessEntry32, <span class="kw3">sizeof</span><span class="br0">&#40;</span>ProcessEntry32<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; ProcEntry.<span class="me1">dwSize</span> := <span class="kw3">sizeof</span><span class="br0">&#40;</span>ProcEntry<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw3">Continue</span> := Process32FirstW<span class="br0">&#40;</span>hSnap, ProcEntry<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ProcessID = <span class="kw4">DWORD</span><span class="br0">&#40;</span><span class="nu0">-1</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">or</span> <span class="br0">&#40;</span>ProcessID = <span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; CurrentID := GetCurrentProcessId<br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; CurrentID := ProcessID;</p>
<p>&nbsp; &nbsp; result := INVALID_HANDLE_VALUE;</p>
<p>&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw3">continue</span><span class="br0">&#41;</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> CurrentID = ProcEntry.<span class="me1">th32ProcessID</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result := ProcEntry.<span class="me1">th32ParentProcessID</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> Condition <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; InternalGetParentProcess<span class="br0">&#40;</span><span class="kw2">true</span>, ProcessEntry32, result<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProcessEntry32 := ProcEntry;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;</p>
<p>&nbsp; &nbsp; &nbsp; <span class="kw3">continue</span> := Process32NextW<span class="br0">&#40;</span>hSnap,ProcEntry<span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>result = INVALID_HANDLE_VALUE<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; CloseHandle<span class="br0">&#40;</span>hSnap<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</p>
<p><span class="kw1">begin</span><br />
&nbsp; result := InternalGetParentProcess<span class="br0">&#40;</span><span class="kw2">false</span>, ProcessEntry32, ProcessID<span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</p>
<p><span class="kw1">function</span> GetParentProcess<span class="br0">&#40;</span><span class="kw1">const</span> ProcessID : <span class="kw4">DWORD</span> = <span class="nu0">0</span><span class="br0">&#41;</span> : <span class="kw4">DWORD</span>; <span class="kw1">overload</span>;<br />
<span class="kw1">var</span> ProcessEntry32 : TProcessEntry32W;<br />
<span class="kw1">begin</span><br />
&nbsp; result := GetParentProcess<span class="br0">&#40;</span>ProcessEntry32, ProcessID<span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</p>
<p><span class="kw1">function</span> GetParentProcess<span class="br0">&#40;</span>out ExeName : <span class="kw4">WideString</span>; <span class="kw1">const</span> ProcessID : <span class="kw4">DWORD</span> = <span class="nu0">0</span><span class="br0">&#41;</span> : <span class="kw4">DWORD</span>; <span class="kw1">overload</span>;<br />
<span class="kw1">var</span> ProcessEntry32 : TProcessEntry32W;<br />
<span class="kw1">begin</span><br />
&nbsp; result := GetParentProcess<span class="br0">&#40;</span>ProcessEntry32, ProcessID<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">if</span> result &lt;&gt; INVALID_HANDLE_VALUE <span class="kw1">then</span><br />
&nbsp; &nbsp; ExeName := ProcessEntry32.<span class="me1">szExeFile</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; ExeName := <span class="st0">&#8221;</span>;<br />
<span class="kw1">end</span>;</p>
<p><span class="kw1">var</span> P : <span class="kw4">DWORD</span>;<br />
&nbsp; Name : <span class="kw4">WideString</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; P :=GetParentProcess<span class="br0">&#40;</span>Name<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw3">writeln</span><span class="br0">&#40;</span>P,<span class="st0">&#8216; &#8216;</span>,Name<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw3">readln</span>;<br />
<span class="kw1">end</span>.</div>
<p>There are three versions of GetParentProcess, so you can get more information than usual necessary.<br />
The reason why the first version has an internal function is that we need to iterate the process list twice to get the parent&#8217;s process name.</p>
<p>Finally all you have to do is to check for its name &#8220;services.exe&#8221;.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">if</span> <span class="kw3">CompareText</span><span class="br0">&#40;</span>Name,<span class="st0">&#8216;services.exe&#8217;</span><span class="br0">&#41;</span> <span class="kw1">then</span></div>
<p>However there can be a bad coincidence and another process who started your app is named like that. In this case we should just check for the full path.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">function</span> RetrieveModuleFileName<span class="br0">&#40;</span><span class="kw1">const</span> PID : <span class="kw4">DWORD</span><span class="br0">&#41;</span> : <span class="kw4">WideString</span>;<br />
<span class="kw1">var</span><br />
&nbsp; FileName : <span class="kw1">Array</span><span class="br0">&#91;</span><span class="nu0">0</span>..<span class="me1">MAX_PATH</span><span class="br0">&#93;</span> <span class="kw1">of</span> <span class="kw4">Widechar</span>;<br />
&nbsp; hP : <span class="kw4">THandle</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; hP := OpenProcess<span class="br0">&#40;</span>PROCESS_QUERY_INFORMATION <span class="kw1">or</span> PROCESS_VM_READ, <span class="kw2">false</span>, PID<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">if</span> hP = <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>;</p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> GetModuleFileNameExW<span class="br0">&#40;</span>hP,<span class="nu0">0</span>,FileName, <span class="kw3">sizeof</span><span class="br0">&#40;</span>FileName<span class="br0">&#41;</span><span class="br0">&#41;</span> = <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>;<br />
&nbsp; &nbsp; result := FileName;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; CloseHandle<span class="br0">&#40;</span>hP<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<p>Now we can be sure that it is the correct process.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">function</span> GetSystem32Path : <span class="kw4">WideString</span>;<br />
<span class="kw1">var</span> Path : <span class="kw1">Array</span><span class="br0">&#91;</span><span class="nu0">0</span>..<span class="me1">MAX_PATH</span><span class="br0">&#93;</span> <span class="kw1">of</span> <span class="kw4">Widechar</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; Result := <span class="st0">&#8221;</span>;<br />
&nbsp; <span class="kw1">if</span> SUCCEEDED<span class="br0">&#40;</span>SHGetFolderPathW<span class="br0">&#40;</span><span class="nu0">0</span>,CSIDL_SYSTEM,<span class="nu0">0</span>,SHGFP_TYPE_DEFAULT, @Path<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; result := <span class="kw3">IncludeTrailingBackslash</span><span class="br0">&#40;</span>Path<span class="br0">&#41;</span>; &nbsp;<span class="co1">//Oopps, may convert unicode to ansicode</span><br />
<span class="kw1">end</span>;</p>
<p><span class="kw1">var</span> PID : <span class="kw4">DWORD</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; PID := GetParentProcess<span class="br0">&#40;</span>Name<span class="br0">&#41;</span>;</p>
<p>&nbsp; Path := RetrieveModuleFileName<span class="br0">&#40;</span>P<span class="br0">&#41;</span>;<br />
&nbsp; SysPath := GetSystem32Path+<span class="st0">&#8216;services.exe&#8217;</span>;<br />
&nbsp; <span class="kw1">if</span> <span class="kw3">CompareText</span><span class="br0">&#40;</span>SysPath, Path<span class="br0">&#41;</span> = <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="co1">//OK</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; <span class="co1">//not a service</span><br />
<span class="kw1">end</span>.</div>
<p>We are not at the end. I should mention that your service application can also be in a service pool hosted by the parent process &#8220;svchost.exe&#8221;. In such a case of course, we have to check for &#8220;svchost.exe&#8221; instead of &#8220;services.exe&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/05/10/service-and-application-in-single-exe/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>How to (un-)install and start a service object</title>
		<link>http://blog.delphi-jedi.net/2008/04/05/how-to-un-install-and-start-a-service-object/</link>
		<comments>http://blog.delphi-jedi.net/2008/04/05/how-to-un-install-and-start-a-service-object/#comments</comments>
		<pubDate>Sat, 05 Apr 2008 11:29:43 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Service]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/04/05/how-to-un-install-and-start-a-service-object/</guid>
		<description><![CDATA[Unfortunately Borland didn&#8217;t implement a public register and start function into the class TServiceApplication. So we have to do it ourselves. First we publish the protected RegisterServices function to allow (un-)install our service(s) programmatically. TServiceApplicationEx = class&#40;TServiceApplication&#41; public &#160; procedure RegisterServices&#40;Install, Silent: Boolean&#41;; end; { TServiceApplicationEx } procedure TServiceApplicationEx.RegisterServices&#40;Install, Silent: Boolean&#41;; begin &#160; inherited; end; [...]]]></description>
			<content:encoded><![CDATA[<p>Unfortunately Borland didn&#8217;t implement a public register and start function into the class TServiceApplication. So we have to  do it  ourselves.<br />
First we publish the protected RegisterServices function to allow (un-)install our service(s) programmatically.</p>
<p><span id="more-120"></span></p>
<div class="dean_ch" style="white-space: wrap;">TServiceApplicationEx = <span class="kw1">class</span><span class="br0">&#40;</span>TServiceApplication<span class="br0">&#41;</span><br />
<span class="kw1">public</span><br />
&nbsp; <span class="kw1">procedure</span> RegisterServices<span class="br0">&#40;</span>Install, Silent: <span class="kw4">Boolean</span><span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</p>
<p><span class="coMULTI">{ TServiceApplicationEx }</span><br />
<span class="kw1">procedure</span> TServiceApplicationEx.<span class="me1">RegisterServices</span><span class="br0">&#40;</span>Install, Silent: <span class="kw4">Boolean</span><span class="br0">&#41;</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="kw1">inherited</span>;<br />
<span class="kw1">end</span>;</div>
<p>Of course we need a tool function that starts our service</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> JwaWindows;procedure StartTheService<span class="br0">&#40;</span>Service : TService<span class="br0">&#41;</span>;<br />
<span class="kw1">var</span><br />
&nbsp; hSCM: SC_HANDLE;<br />
&nbsp; hSvc: SC_HANDLE;<br />
&nbsp; args: <span class="kw1">array</span> <span class="kw1">of</span> <span class="kw4">PChar</span>;<br />
&nbsp; i : <span class="kw4">Integer</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; hSCM := OpenSCManager<span class="br0">&#40;</span><span class="kw2">nil</span>, SERVICES_ACTIVE_DATABASEW, SC_MANAGER_CONNECT<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">if</span> hSCM = <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp;<span class="kw3">RaiseLastOSError</span>;</p>
<p><span class="kw1">try</span><br />
&nbsp; &nbsp; hSvc := OpenService<span class="br0">&#40;</span>hSCM, <span class="kw4">PChar</span><span class="br0">&#40;</span>Service.<span class="me1">Name</span><span class="br0">&#41;</span>, SERVICE_START<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> hSvc = <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>; &nbsp; &nbsp;<span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">SetLength</span><span class="br0">&#40;</span>args, <span class="kw3">ParamCount</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; <span class="kw1">for</span> i := <span class="nu0">0</span> <span class="kw1">to</span> ParamCount<span class="nu0">-1</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">GetMem</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span>i<span class="br0">&#93;</span>, <span class="kw3">Length</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="nu0">+1</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="nu0">+2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; StringCchCopy<span class="br0">&#40;</span>args<span class="br0">&#91;</span>i<span class="br0">&#93;</span>, <span class="kw3">Length</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="nu0">+1</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="nu0">+2</span>, <span class="kw4">PChar</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="nu0">+1</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;</p>
<p>&nbsp; &nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> StartServiceA<span class="br0">&#40;</span>hSvc, <span class="kw3">Length</span><span class="br0">&#40;</span>args<span class="br0">&#41;</span>, @args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> i := <span class="nu0">0</span> <span class="kw1">to</span> ParamCount<span class="nu0">-1</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">FreeMem</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; &nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; &nbsp; CloseServiceHandle<span class="br0">&#40;</span>hSvc<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; CloseServiceHandle<span class="br0">&#40;</span>hScm<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<p>Finally we can adjust the main application to install, uninstall or run the service.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">program</span> xy;<br />
<span class="kw1">uses</span> SvcMgr, &#8230;;<br />
<span class="kw1">begin</span><br />
&nbsp; SvcMgr.<span class="me1">Application</span>.<span class="me1">Free</span>;<br />
&nbsp; SvcMgr.<span class="me1">Application</span> := TServiceApplicationEx.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span><span class="br0">&#41;</span>;<br />
&nbsp; SvcMgr.<span class="me1">Application</span>.<span class="kw3">Initialize</span>;<br />
&nbsp; SvcMgr.<span class="me1">Application</span>.<span class="me1">CreateForm</span><span class="br0">&#40;</span>TMyService, MyService<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">if</span> &lt;InstallService&gt; <span class="kw1">then</span><br />
&nbsp; &nbsp; SvcMgr.<span class="me1">Application</span>.<span class="me1">RegisterServices</span><span class="br0">&#40;</span><span class="kw2">true</span>, <span class="kw2">true</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; <span class="kw1">if</span> &lt;DeInstallService&gt; <span class="kw1">then</span><br />
&nbsp; &nbsp; SvcMgr.<span class="me1">Application</span>.<span class="me1">RegisterServices</span><span class="br0">&#40;</span><span class="kw2">false</span>, <span class="kw2">true</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; <span class="kw1">if</span> &lt;StartService&gt; <span class="kw1">then</span><br />
&nbsp; &nbsp; StartService<span class="br0">&#40;</span>MyService<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">and</span> <span class="kw3">exit</span> here<br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; SvcMgr.<span class="me1">Application</span>.<span class="me1">Run</span>;<br />
<span class="kw1">end</span>;</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/04/05/how-to-un-install-and-start-a-service-object/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to get the user&#8217;s token from a service?</title>
		<link>http://blog.delphi-jedi.net/2008/03/31/how-to-get-the-users-token-from-a-service/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/31/how-to-get-the-users-token-from-a-service/#comments</comments>
		<pubDate>Mon, 31 Mar 2008 18:27:28 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[Impersonate]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[Token]]></category>
		<category><![CDATA[WTS]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/31/how-to-get-the-users-token-from-a-service/</guid>
		<description><![CDATA[This simple code excerpt can only be run under SYSTEM account (say in a service). It retrieves the token from the logged on user &#8211; especially the user at the physical console. Or in other words the user data of the person that sits in front of the computer. The main code which does the [...]]]></description>
			<content:encoded><![CDATA[<p>This simple code excerpt can only be run under SYSTEM account (say in a service). It retrieves the token from the logged on user &#8211; especially the user at the physical console. Or in other words the user data of the person that sits in front of the computer. The main code which does the task above can be seen here.</p>
<div class="dean_ch" style="white-space: wrap;">UserToken := TJwSecurityToken.<span class="me1">CreateWTSQueryUserToken</span><span class="br0">&#40;</span>WTS_CURRENT_SESSION<span class="br0">&#41;</span>;</div>
<p><a href="http://jwscldoc.delphi-jedi.net/JwsclToken.TJwSecurityToken.html#CreateWTSQueryUserToken">CreateWTSQueryUserToken</a> is only applicable in Windows XP or newer.  Use <a href="http://jwscldoc.delphi-jedi.net/JwsclToken.TJwSecurityToken.html#CreateWTSQueryUserTokenEx">CreateWTSQueryUserTokenEx</a> if you need Windows 2000  support.<br />
WTS_CURRENT_SESSION (-1)  defines the console session to be retrieved. Any existing session ID (starting from zero (0) )  can be used instead.  If a problems occurs (e.g. session does not exist) you get an exception (see documentation)</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span><br />
&nbsp; JwaWindows,<br />
&nbsp; JwsclToken,<br />
&nbsp; JwsclSid,<br />
&nbsp; JwsclStrings,<br />
&nbsp; SysUtils;</p>
<p>&#8230;<br />
<span class="kw1">var</span><br />
&nbsp; UserToken : TJwSecurityToken;<br />
&nbsp; ConsoleUser : TJwSecurityId;<br />
&nbsp; UserSidString,<br />
&nbsp; UserName : TJwString;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="co1">//erst ab Windows XP</span><br />
&nbsp; UserToken := TJwSecurityToken.<span class="me1">CreateWTSQueryUserToken</span><span class="br0">&#40;</span>WTS_CURRENT_SESSION<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; ConsoleUser := UserToken.<span class="me1">TokenUser</span>;<br />
&nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; UserSidString := ConsoleUser.<span class="me1">StringSID</span>;<br />
&nbsp; &nbsp; &nbsp; UserName := ConsoleUser.<span class="me1">GetAccountName</span><span class="br0">&#40;</span><span class="st0">&#8221;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="co1">//Writeln(UserSidString);</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">//Writeln(UserName);</span><br />
&nbsp; &nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>ConsoleUser<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; &nbsp; <span class="co1">//User personifizieren</span><br />
&nbsp; &nbsp; UserToken.<span class="me1">ImpersonateLoggedOnUser</span>;</p>
<p>&nbsp; &nbsp; ***</p>
<p>&nbsp; &nbsp; UserToken.<span class="me1">RevertToSelf</span>;</p>
<p>&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>UserToken<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<p>***)  Place functions and do stuff here that needs to be run under the user&#8217;s context. Functions like <a href="http://msdn2.microsoft.com/en-us/library/bb762204(VS.85).aspx">SHGetSpecialFolder</a> use the impersonated token to get the (correct) user folder. Additionally all security checks are made with the user&#8217;s token. This comes very handy because a service has (almost) always access to everything (files, reg keys, &#8230;) which means a security hole.</p>
<p><strong>[UPDATE]</strong><br />
Fixed some minor mistakes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/31/how-to-get-the-users-token-from-a-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

