<?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; Process</title>
	<atom:link href="http://blog.delphi-jedi.net/tag/process/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>Restrict access to process</title>
		<link>http://blog.delphi-jedi.net/2008/11/08/restrict-access-to-process/</link>
		<comments>http://blog.delphi-jedi.net/2008/11/08/restrict-access-to-process/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 21:58:11 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[DACL]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[Process]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=271</guid>
		<description><![CDATA[The following code is really simple. It restricts access to the current process. In this way no other process can open the process handle and for example terminate this process. uses &#160; JwaWindows, &#160; JwsclSecureObjects, &#160; JwsclDescriptor, &#160; JwsclToken, &#160; JwsclTypes, &#160; JwsclAcl, &#160; JwsclKnownSid; var &#160; SD : TJwSecurityDescriptor; &#160; hProcess : TJwProcessHandle; begin [...]]]></description>
			<content:encoded><![CDATA[<p>The following code is really simple. It restricts access to the current process. In this way no other process can open the process handle and for example terminate this process.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span><br />
&nbsp; JwaWindows,<br />
&nbsp; JwsclSecureObjects,<br />
&nbsp; JwsclDescriptor,<br />
&nbsp; JwsclToken,<br />
&nbsp; JwsclTypes,<br />
&nbsp; JwsclAcl,<br />
&nbsp; JwsclKnownSid;</p>
<p><span class="kw1">var</span><br />
&nbsp; SD : TJwSecurityDescriptor;<br />
&nbsp; hProcess : TJwProcessHandle;<br />
<span class="kw1">begin</span><br />
&nbsp; JwInitWellKnownSIDs;</p>
<p>&nbsp; hProcess := OpenProcess<span class="br0">&#40;</span>READ_CONTROL <span class="kw1">or</span> WRITE_DAC, <span class="kw2">false</span>, GetCurrentProcessId<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">if</span> hProcess &lt;&gt; <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; SD := TJwSecureGeneralObject.<span class="me1">GetSecurityInfo</span><span class="br0">&#40;</span>hProcess,SE_KERNEL_OBJECT, <span class="br0">&#91;</span>siDaclSecurityInformation<span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; SD.<span class="me1">DACL</span>.<span class="me1">Clear</span>;<br />
&nbsp; &nbsp; &nbsp; SD.<span class="me1">DACL</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_ALL, JwLocalSystemSID<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; <span class="co1">//allow read access to the current user</span><br />
&nbsp; &nbsp; &nbsp; SD.<span class="me1">DACL</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_READ, JwSecurityProcessUserSID<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; TJwSecureGeneralObject.<span class="me1">SetSecurityInfo</span><span class="br0">&#40;</span>hProcess, SE_KERNEL_OBJECT, <span class="br0">&#91;</span>siDaclSecurityInformation<span class="br0">&#93;</span>, SD<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; &nbsp; SD.<span class="me1">Free</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>hProcess<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<p>However there are some problems:</p>
<ol>
<li>This code does not prevent the user from reverting the process DACL to the original state. An owner of the process can always change the DACL even if she is not listed in it. So the code just prevents a beginner from closing the application forcefully.</li>
<li>Any user with the DEBUG privilege can open the process with full access using <em>OpenProcess</em>. The taskmanager uses this way to terminate a process &#8211; if TaskManager is started with administrative rights.</li>
</ol>
<p>The only way to prevent a restricted user from terminating the application is to run the process with a foreign account (e.g. CreateProcessAsUser) and make sure that the user is not listed in the DACL. However if this user gets the DEBUG privilege the game is over.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/11/08/restrict-access-to-process/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>CreateProcess in full glory</title>
		<link>http://blog.delphi-jedi.net/2008/04/11/createprocess-in-full-glory/</link>
		<comments>http://blog.delphi-jedi.net/2008/04/11/createprocess-in-full-glory/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 11:11:40 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Process]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=114</guid>
		<description><![CDATA[CreateProcess is a little tricky to use. Thus I write the full example code here so you don&#8217;t have to worry. uses SysUtils, JwaWindows, JwsclStrings; procedure StartApp&#40;const App, Parameters, CurDir : TJwString&#41;; var &#160; StartupInfo: {$IFDEF UNICODE}TStartupInfoW{$ELSE}TStartupInfoA{$ENDIF}; &#160; ProcInfo : TProcessInformation; &#160; pEnv : Pointer; &#160; pCurDir, &#160; pCmdLine : TJwPChar; begin &#160; ZeroMemory&#40;@StartupInfo, sizeof&#40;StartupInfo&#41;&#41;; [...]]]></description>
			<content:encoded><![CDATA[<p>CreateProcess is a little tricky to use. Thus I write the full example code here so you don&#8217;t have to worry.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> SysUtils, JwaWindows, JwsclStrings;</p>
<p><span class="kw1">procedure</span> StartApp<span class="br0">&#40;</span><span class="kw1">const</span> App, Parameters, CurDir : TJwString<span class="br0">&#41;</span>;<br />
<span class="kw1">var</span><br />
&nbsp; StartupInfo: <span class="coMULTI">{$IFDEF UNICODE}</span>TStartupInfoW<span class="coMULTI">{$ELSE}</span>TStartupInfoA<span class="coMULTI">{$ENDIF}</span>;<br />
&nbsp; ProcInfo : TProcessInformation;<br />
&nbsp; pEnv : <span class="kw4">Pointer</span>; </p>
<p>&nbsp; pCurDir,<br />
&nbsp; pCmdLine : TJwPChar;<br />
<span class="kw1">begin</span><br />
&nbsp; ZeroMemory<span class="br0">&#40;</span>@StartupInfo, <span class="kw3">sizeof</span><span class="br0">&#40;</span>StartupInfo<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; StartupInfo.<span class="me1">cb</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:= <span class="kw3">SizeOf</span><span class="br0">&#40;</span>StartupInfo<span class="br0">&#41;</span>;<br />
&nbsp; StartupInfo.<span class="me1">lpDesktop</span> &nbsp; := <span class="st0">&#8216;winsta0\default&#8217;</span>;</p>
<p>&nbsp; CreateEnvironmentBlock<span class="br0">&#40;</span>@pEnv, <span class="nu0">0</span>, <span class="kw2">true</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">Length</span><span class="br0">&#40;</span>Parameters<span class="br0">&#41;</span> &gt; <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; pCmdLine := TJwPChar<span class="br0">&#40;</span><span class="st0">&#8216;&quot;&#8217;</span>+App+<span class="st0">&#8216;&quot; &#8216;</span> + Parameters<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; pCmdLine := TJwPChar<span class="br0">&#40;</span><span class="st0">&#8216;&quot;&#8217;</span>+App+<span class="st0">&#8216;&quot; &#8216;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; pCurDir := <span class="kw2">Nil</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">Length</span><span class="br0">&#40;</span>CurDir<span class="br0">&#41;</span> &gt; <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; pCurDir := TJwPChar<span class="br0">&#40;</span>CurDir<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp;<span class="kw1">if</span> <span class="kw1">not</span><br />
<span class="coMULTI">{$IFDEF UNICODE}</span>CreateProcessW<span class="coMULTI">{$ELSE}</span>CreateProcessA<span class="coMULTI">{$ENDIF}</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; TJwPChar<span class="br0">&#40;</span>App<span class="br0">&#41;</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPCTSTR lpApplicationName,</span><br />
&nbsp; &nbsp; pCmdLine, <span class="co1">//__inout_opt &nbsp;LPTSTR lpCommandLine,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPSECURITY_ATTRIBUTES lpProcessAttributes,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPSECURITY_ATTRIBUTES lpThreadAttributes,</span><br />
&nbsp; &nbsp; <span class="kw2">true</span>,<span class="co1">//__in &nbsp; &nbsp; &nbsp; &nbsp; BOOL bInheritHandles,</span><br />
&nbsp; &nbsp; CREATE_NEW_CONSOLE <span class="kw1">or</span> CREATE_UNICODE_ENVIRONMENT,<span class="co1">//__in &nbsp; &nbsp; &nbsp; &nbsp; DWORD dwCreationFlags,</span><br />
&nbsp; &nbsp; pEnv,<span class="co1">//__in_opt &nbsp; &nbsp; LPVOID lpEnvironment,</span><br />
&nbsp; &nbsp; pCurDir,<span class="co1">//__in_opt &nbsp; &nbsp; LPCTSTR lpCurrentDirectory,</span><br />
&nbsp; &nbsp; StartupInfo,<span class="co1">//__in &nbsp; &nbsp; &nbsp; &nbsp; LPSTARTUPINFO lpStartupInfo,</span><br />
&nbsp; &nbsp; ProcInfo,<span class="co1">//__out &nbsp; &nbsp; &nbsp; &nbsp;LPPROCESS_INFORMATION lpProcessInformation</span><br />
&nbsp; <span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp;<span class="kw3">raiseLastOsError</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; DestroyEnvironmentBlock<span class="br0">&#40;</span>pEnv<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
&nbsp; CloseHandle<span class="br0">&#40;</span>ProcInfo.<span class="me1">hProcess</span><span class="br0">&#41;</span>;<br />
&nbsp; CloseHandle<span class="br0">&#40;</span>ProcInfo.<span class="me1">hThread</span><span class="br0">&#41;</span>;<br />
&#8230;</div>
<p>Here some explanations:</p>
<ul>
<li>What is a <em>TJwString</em> and <em>TJwPchar</em>?<br />
These types are declared in the <strong>JWSCL </strong>unit <em>JwsclStrings</em> and define a <em>String</em> or <em>WideString</em> and its C counterparts <em>PChar</em> or <em>PWideCha</em>r. It depends on the compiler directive <strong>UNICODE</strong> whether they become the ansi or unicode version. Define <strong>UNICODE</strong> in your project options and rebuilt your project to use the unicode version.<br />
The same  reason applies to this line.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="coMULTI">{$IFDEF UNICODE}</span>CreateProcessW<span class="coMULTI">{$ELSE}</span>CreateProcessA<span class="coMULTI">{$ENDIF}</span></div>
<p>Here we use either the unicode or ansicode version of <strong>CreateProcess</strong>.</li>
<li>
<div class="dean_ch" style="white-space: wrap;">ZeroMemory<span class="br0">&#40;</span>@StartupInfo, <span class="kw3">sizeof</span><span class="br0">&#40;</span>StartupInfo<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
<p>Is it really necessary to fill this block with zeroes?<br />
Yes, it is. <strong>CreateProcess</strong> uses values that are not zero as input and thus may fail if the values are incorrect.</li>
<li>
<div class="dean_ch" style="white-space: wrap;">StartupInfo.<span class="me1">cb</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:= <span class="kw3">SizeOf</span><span class="br0">&#40;</span>StartupInfo<span class="br0">&#41;</span>;</div>
<p>What is the member <em>cb</em> for?<br />
The size member of this structures defines which version is used. In future if new members are added, <strong>CreateProcess</strong> can determine which version (with or without the new members) is used and thus ignore the new member&#8217;s values (they aren&#8217;t there anyway).</li>
<li>
<div class="dean_ch" style="white-space: wrap;">StartupInfo.<span class="me1">lpDesktop</span> &nbsp; := <span class="st0">&#8216;winsta0\default&#8217;</span>;</div>
<p>What does this line do?<br />
The <em>lpDesktop</em> member defines on which windowstation (here: &#8220;winsta0&#8243;) and desktop (here: &#8220;default&#8221;) the new application is shown. The value &#8220;winsta0\default&#8221; is a default value and should be sufficient for 99% of all cases. However Windows versions older than <strong>Vista</strong> come with a bug that does not show the application on &#8220;winsta0\defaul&#8221; if not specified. This bug only occurs in some rare occasions and is fixed in <strong>Vista</strong> and <strong>Server 2008.</strong></li>
<li>What is <strong>CreateEnvironmentBlock </strong>for?<br />
<strong>CreateEnvironmentBlock </strong>creates all the command variables for the user you can see when you type &#8220;set&#8221; into command prompt (cmd.exe).</li>
<li>Why do you repeat the applications path in the command line parameters?
<div class="dean_ch" style="white-space: wrap;">pCmdLine := TJwPChar<span class="br0">&#40;</span><span class="st0">&#8216;&quot;&#8217;</span>+App+<span class="st0">&#8216;&quot; &#8216;</span> + Parameters<span class="br0">&#41;</span>;</div>
<p>It is standard in C world to repeat the application path as the first (zero based) parameter. So we have to add the app name in front of the remaining parameters. Otherwise the first parameter would be recognized as the application path and thus be ignored. In this case <strong>ParamStr</strong>(0)<strong> </strong>returns application path though but <strong>ParamStr</strong>(1) returns the second parameter. Example: pCmdLine = &#8217;1 2 3&#8242;; In this example <strong>ParamStr</strong>(0) would be the path to exe. <strong>ParamStr</strong>(1) would be &#8220;2&#8243; and not &#8220;1&#8243; because &#8220;1&#8243; is considered as the path to exe. <strong>ParamStr</strong>(0) uses <strong>GetModuleFileName</strong> as an exception.</p>
<div class="dean_ch" style="white-space: wrap;">pCmdLine := TJwPChar<span class="br0">&#40;</span><span class="st0">&#8216;&quot;&#8217;</span>+App+<span class="st0">&#8216;&quot; &#8216;</span><span class="br0">&#41;</span>;</div>
<p>If no additional parameters are specified we just add the application name as the first parameter.</li>
<li>Why do we use a <em>P(Wide)Char</em> (TJwPChar resolves to this depending on compiler directive <strong>UNICODE</strong>)  and set it to <strong>nil</strong> if <em>Parameters</em> or <em>CurDir</em> are empty?<br />
The reason is CreateProcess. If those pointers aren&#8217;t nil, the function consider them as input and does not ignore them. So if you empty the input parameters, CreateProcess considers an empty current directory string as input and tries to use it. Of course the operation fails and thus CreateProcess returns an error.</li>
<li>Does <strong>CloseHandle</strong> kill the newly created process?<br />
No, it does not. CreateProcess returns two handles so you could control the process or thread. However closing an application needs more action than just closing a handle. The handle however should be closed because it consumes memory in your process. So if you don&#8217;t need them, close it.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/04/11/createprocess-in-full-glory/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to get the threads of a process?</title>
		<link>http://blog.delphi-jedi.net/2008/03/19/how-to-get-the-threads-of-a-process/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/19/how-to-get-the-threads-of-a-process/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 15:00:25 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[Thread]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/19/how-to-get-the-threads-of-a-process/</guid>
		<description><![CDATA[Yesterday, I described how to get the process of a window. Today I show you how to obtain the threads of a process. There are two ways to retrieve all the threads of a foreign process. Use the Tool Help Library. There is also a sample about enumerating threads. So I am not going to [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday, I described <a href="http://blog.delphi-jedi.net/2008/03/18/how-to-get-the-process-of-a-window/">how to get the process of a window</a>. Today I show you how to obtain the threads of a process.</p>
<p>There are two ways to retrieve all the threads of a foreign process.</p>
<ol>
<li>Use the <a href="http://msdn2.microsoft.com/en-us/library/ms686728(VS.85).aspx">Tool Help Library</a>. There is also a <a href="http://msdn2.microsoft.com/en-us/library/ms686852(VS.85).aspx">sample</a> about enumerating threads. So I am not going to to show you code in Delphi. The sample is simple enough to understand and convert.<br />
But these functions are necessary.</p>
<ul>
<li><a href="http://msdn2.microsoft.com/en-us/library/ms682489%28VS.85%29.aspx" target="_top">CreateToolhelp32Snapshot</a></li>
<li><a href="http://msdn2.microsoft.com/en-us/library/ms686728%28VS.85%29.aspx" class="tocSelected" target="_top">Thread32First</a></li>
<li><a href="http://msdn2.microsoft.com/en-us/library/ms686731%28VS.85%29.aspx" target="_top">Thread32Next</a></li>
</ul>
<p>The Tool Help Library declarations are defined in JwaTLHelp32.pas or JwaWindows.pas</li>
<li>Use Performance Data Helper as described in a <a href="http://www.codeproject.com/KB/system/ntenumthreads.aspx?display=Print">CodeProject article</a>.<br />
The PDH declarations are defined in JwaPdh.pas, JwaPdhMsg.pas or JwaWindows.pas</li>
</ol>
<p><strong>Tell me how you liked this blog entry by adding a comment.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/19/how-to-get-the-threads-of-a-process/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to use VCL and SetThreadDesktop</title>
		<link>http://blog.delphi-jedi.net/2008/03/19/how-to-use-vcl-and-setthreaddesktop/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/19/how-to-use-vcl-and-setthreaddesktop/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 09:00:49 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[Thread]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/19/how-to-use-vcl-and-setthreaddesktop/</guid>
		<description><![CDATA[It is impossible to use SetThreadDesktop and the VCL at the same time because a thread can only show windows on one desktop at a time. However VCL is not written for the use with multiple threads, so there is no way to show Delphi forms of same process on two different desktops. SetThreadDesktop describes [...]]]></description>
			<content:encoded><![CDATA[<p>It is impossible to use <a href="http://msdn2.microsoft.com/en-us/library/ms686250(vs.85).aspx">SetThreadDesktop</a> and the <strong>VCL </strong>at the same time because a thread can only show windows on one desktop at a time.  However <strong>VCL </strong>is not written for the use with multiple threads, so there is no way to show <strong>Delphi </strong>forms of same process on two different desktops. <em>SetThreadDesktop </em>describes this issue as followed.</p>
<blockquote><p>The  <strong>SetThreadDesktop</strong> function will fail if the calling thread has any windows or hooks on its current desktop (unless the <em>hDesktop</em> parameter is a handle to the current desktop).</p></blockquote>
<p><u>Though there is a  workaround</u> to make <strong>VCL </strong>work with <em>SetThreadDesktop </em>and <a href="http://msdn2.microsoft.com/en-us/library/ms686347(VS.85).aspx">SwitchDesktop</a>. The <em>Application </em>variable defined in unit <em>Forms </em>must be freed and then renewed. Here is the correct order :</p>
<ol>
<li>Close all your forms so the Application is going to quit.</li>
<li>Free the Application instance in your DPR file.
<div class="dean_ch" style="white-space: wrap;">Application.<span class="me1">Run</span>;<br />
Application.<span class="me1">Free</span>;</div>
</li>
<li>Then call <em>SetThreadDesktop </em>and <em>SwitchDesktop</em></li>
<li>Recreate the application object &#8211; now on the new desktop:
<div class="dean_ch" style="white-space: wrap;">Application := TApplication.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span><span class="br0">&#41;</span>;<br />
Application.<span class="kw3">Initialize</span>;</div>
</li>
<li>Call all the usual stuff that has to be done to show your forms</li>
</ol>
<p>&#8230;follow the same way as described to get back to the original desktop and forms (in this order!). However this has to be done in the  main project file (DPR) (except you&#8217;re going to source it out) because you cannot just free <em>Application</em> in the event method of a button click. You have to shutdown your application (not your process) and continue right after :</p>
<div class="dean_ch" style="white-space: wrap;">Application.<span class="me1">Free</span>;</div>
<p>In this way the process does not shut down and you can use <strong>VCL </strong>on one desktop at a time.</p>
<p><u>A second possibility</u> is to use <strong>VCL </strong>on one desktop and <strong>NonVCL</strong> on the other. However in this way you have to create a new thread and use your own message loop (located in the new thread).  Then you can call <em>SetThreadDesktop </em>in this thread and show the <strong>NonVCL</strong> windows.</p>
<p><u>A third possibility</u> is to execute another or the same application with <a href="http://msdn2.microsoft.com/en-us/library/ms682425.aspx"><em>CreateProcess</em></a>. This function allows you to specify the target desktop name for the new process in <em>lpDesktop </em>of the <em><a href="http://msdn2.microsoft.com/en-us/library/ms686331(VS.85).aspx">TProcessInformation</a></em> structure.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> JwaWindows;</p>
<p><span class="kw1">var</span><br />
&nbsp; StartupInfo: TStartupInfo;<br />
&nbsp; ProcInfo : TProcessInformation;<br />
<span class="kw1">begin</span><br />
&nbsp; StartupInfo.<span class="me1">cb</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:= <span class="kw3">SizeOf</span><span class="br0">&#40;</span>StartupInfo<span class="br0">&#41;</span>;<br />
&nbsp; StartupInfo.<span class="me1">lpDesktop</span> &nbsp; := <span class="st0">&#8216;winsta0\default&#8217;</span>;</p>
<p>&nbsp; CreateProcess<span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;appname.exe&#8217;</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPCTSTR lpApplicationName,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__inout_opt &nbsp;LPTSTR lpCommandLine,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPSECURITY_ATTRIBUTES lpProcessAttributes,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPSECURITY_ATTRIBUTES lpThreadAttributes,</span><br />
&nbsp; &nbsp; <span class="kw2">true</span>,<span class="co1">//__in &nbsp; &nbsp; &nbsp; &nbsp; BOOL bInheritHandles,</span><br />
&nbsp; &nbsp; CREATE_NEW_CONSOLE,<span class="co1">//__in &nbsp; &nbsp; &nbsp; &nbsp; DWORD dwCreationFlags,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPVOID lpEnvironment,</span><br />
&nbsp; &nbsp; <span class="kw2">nil</span>,<span class="co1">//__in_opt &nbsp; &nbsp; LPCTSTR lpCurrentDirectory,</span><br />
&nbsp; &nbsp; StartInfo,<span class="co1">//__in &nbsp; &nbsp; &nbsp; &nbsp; LPSTARTUPINFO lpStartupInfo,</span><br />
&nbsp; &nbsp; ProcInfo,<span class="co1">//__out &nbsp; &nbsp; &nbsp; &nbsp;LPPROCESS_INFORMATION lpProcessInformation</span><br />
&nbsp; <span class="br0">&#41;</span>;<br />
&nbsp; CloseHandle<span class="br0">&#40;</span>ProcInfo.<span class="me1">hProcess</span><span class="br0">&#41;</span>;<br />
&nbsp; CloseHandle<span class="br0">&#40;</span>ProcInfo.<span class="me1">hThread</span><span class="br0">&#41;</span>;<br />
&#8230;</div>
<hr size="2" width="100%" /><u><strong>JWSCL</strong></u><br />
Did you know that there is already a desktop class that provides all necessary function to administer desktops? Yes, there is! It is called <a href="http://jwscldoc.delphi-jedi.net/JwsclDesktops.TJwSecurityDesktop.html">TJwSecurityDesktop</a> and resides in unit <a href="http://jwscldoc.delphi-jedi.net/JwsclDesktops.html" class="bold">JwsclDesktops</a>.<br />
<hr size="2" width="100%" /><strong>Tell me how you liked this blog entry by adding a comment.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/19/how-to-use-vcl-and-setthreaddesktop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to get the process of a window?</title>
		<link>http://blog.delphi-jedi.net/2008/03/18/how-to-get-the-process-of-a-window/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/18/how-to-get-the-process-of-a-window/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 18:00:35 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[ID]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[Thread]]></category>
		<category><![CDATA[Window]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/18/how-to-get-the-process-of-a-window/</guid>
		<description><![CDATA[This answer is very easy &#8211; just use GetWindowThreadProcessId JWA declares it as followed: function GetWindowThreadProcessId&#40;hWnd: HWND; lpdwProcessId: LPDWORD&#41;: DWORD; stdcall; The function returns an identifier (not a handle) and also may set lpdwProcessId to the identifier (again not a handle!) if it is not nil. Be aware that identifiers aren&#8217;t handles, so you must [...]]]></description>
			<content:encoded><![CDATA[<p>This answer is very easy &#8211; just use <a href="http://msdn2.microsoft.com/en-us/library/ms633522(VS.85).aspx">GetWindowThreadProcessId</a></p>
<p>JWA declares it as followed:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">function</span> GetWindowThreadProcessId<span class="br0">&#40;</span>hWnd: HWND; lpdwProcessId: LPDWORD<span class="br0">&#41;</span>: <span class="kw4">DWORD</span>; <span class="kw1">stdcall</span>;</div>
<p>The function returns an identifier (not a handle) and also may set lpdwProcessId to the identifier (again not a handle!) if it is not nil. Be aware that identifiers aren&#8217;t handles, so you must not close them by using CloseHandle. Identifiers are only numbers that makes an object distinguishable from other objects of the same type.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> JwaWindows;</p>
<p><span class="kw1">var</span> ProcessID,<br />
&nbsp;ThreadID &nbsp;: <span class="kw4">DWORD</span>;<br />
&nbsp;WndHandle : HWND;</p>
<p><span class="kw1">begin</span><br />
&nbsp; WndHandle := FindWindow<span class="br0">&#40;</span>&#8230;<span class="br0">&#41;</span>;<br />
&nbsp; ThreadID := GetWindowThreadProcessId<span class="br0">&#40;</span>WndHandle, @ProcessID<span class="br0">&#41;</span>;<br />
&#8230;</div>
<p><strong>Tell me how you liked this blog entry by adding a comment.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/18/how-to-get-the-process-of-a-window/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>You cannot make your application undestroyable.</title>
		<link>http://blog.delphi-jedi.net/2008/03/17/you-cant-make-your-application-undestroyable/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/17/you-cant-make-your-application-undestroyable/#comments</comments>
		<pubDate>Mon, 17 Mar 2008 22:24:57 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[KillProcess]]></category>
		<category><![CDATA[Laptop]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[TerminateProcess]]></category>
		<category><![CDATA[user]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/17/you-cant-make-your-application-undestroyable/</guid>
		<description><![CDATA[The people from Microsoft decided that the user has to be in full control over the computer. So there is no assured way to make a program user resistant. She can always use TerminateProcess to forcibly kill the process. uses JwaWindows; function KillProcess&#40;const ProcessID : DWord&#41;: Boolean; var &#160; hProcess: HANDLE; begin &#160; hProcess := [...]]]></description>
			<content:encoded><![CDATA[<p>The people from Microsoft decided that the user has to be in full control over the computer. So there is no assured way to make a program user resistant. She can always use <a href="http://msdn2.microsoft.com/en-us/library/ms686714.aspx" title="Go to MSDN.">TerminateProcess</a> to forcibly kill the process.</p>
<p><span id="more-76"></span></p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> JwaWindows;</p>
<p><span class="kw1">function</span> KillProcess<span class="br0">&#40;</span><span class="kw1">const</span> ProcessID : <span class="kw4">DWord</span><span class="br0">&#41;</span>: <span class="kw4">Boolean</span>;<br />
<span class="kw1">var</span><br />
&nbsp; hProcess: HANDLE;<br />
<span class="kw1">begin</span><br />
&nbsp; hProcess := OpenProcess<span class="br0">&#40;</span>PROCESS_TERMINATE, &nbsp;<span class="kw2">False</span>, ProcessID<span class="br0">&#41;</span>;<br />
&nbsp; Result := TerminateProcess<span class="br0">&#40;</span>hProcess, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</div>
<p>Because nobody reads the remarks section of <a href="http://msdn2.microsoft.com/en-us/library/ms686714.aspx" title="Go to MSDN.">TerminateProcess</a>, I cite it here.</p>
<blockquote><p>The  <strong>TerminateProcess</strong> function is used to unconditionally cause a process to exit. The state of global data maintained by dynamic-link libraries (DLLs) may be compromised if <strong>TerminateProcess</strong> is used rather than  <a href="http://msdn2.microsoft.com/en-us/library/ms682658%28VS.85%29.aspx" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl06',this);" id="ctl00_rs1_mainContentContainer_ctl06"><strong>ExitProcess</strong></a>.</p>
<p><strong>TerminateProcess</strong> initiates termination and returns immediately. This stops execution of all threads within the process and requests cancellation of all pending I/O. The terminated process cannot exit until all pending I/O has been completed or canceled.</p></blockquote>
<p><strong>And remind this little sentence.</strong></p>
<blockquote><p>A process cannot prevent itself from being terminated.</p></blockquote>
<p>However there are some reasons <u>not to make your application undestroyable</u>.</p>
<ol>
<li>The users don&#8217;t want it.</li>
<li>The work does not pay off. The user is going to close the app anyway.</li>
<li>Some people complain about apps that do not close when Windows is shutting down.</li>
<li>It&#8217;s also said that there were laptops which didn&#8217;t shutdown. The users put them into their bags and didn&#8217;t realize that the machine overheated eventually.</li>
<li>Vista closes your application in the end you have no veto.</li>
</ol>
<p><strong>Tell me how you liked this blog entry by adding a comment.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/17/you-cant-make-your-application-undestroyable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The case of the unexplained&#8230;</title>
		<link>http://blog.delphi-jedi.net/2008/03/16/the-case-of-the-unexplained/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/16/the-case-of-the-unexplained/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 17:51:24 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[Handle]]></category>
		<category><![CDATA[Kernel Microsoft]]></category>
		<category><![CDATA[Process]]></category>
		<category><![CDATA[ProcessExplorer]]></category>
		<category><![CDATA[Russinovich]]></category>
		<category><![CDATA[Thread]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/16/the-case-of-the-unexplained/</guid>
		<description><![CDATA[As you maybe already have noted, I use the ProcessExplorer of Mark Russinovich a lot. It is a very powerful tool, that can help you finding out what&#8217;s going on in your Windows system&#8230; Processes Threads Properties Handles Kernel Bluescreens (WinDbg) and many more If you are interested in getting an introduction into the great [...]]]></description>
			<content:encoded><![CDATA[<p>As you maybe already have noted, I use the <a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx">ProcessExplorer</a> of Mark Russinovich a lot. It is a very powerful tool, that can help you finding out what&#8217;s going on in your Windows system&#8230;</p>
<ul>
<li>
<div>Processes</div>
</li>
<li>
<div>Threads</div>
</li>
<li>
<div>Properties</div>
</li>
<li>
<div>Handles</div>
</li>
<li>
<div>Kernel</div>
</li>
<li>Bluescreens (WinDbg)</li>
<li>
<div>and many more</div>
</li>
</ul>
<p>If you are interested in getting an introduction into the great application, you should watch this video. Mark presents his tool with many examples from his own experiences.</p>
<p><a href="http://www.microsoft.com/emea/spotlight/sessionh.aspx?videoid=722">http://www.microsoft.com/emea/spotlight/sessionh.aspx?videoid=722</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/16/the-case-of-the-unexplained/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

