<?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; COM</title>
	<atom:link href="http://blog.delphi-jedi.net/tag/com/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>Is File In Use</title>
		<link>http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/</link>
		<comments>http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/#comments</comments>
		<pubDate>Sun, 14 Nov 2010 19:57:43 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Conversion]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[JWA]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=861</guid>
		<description><![CDATA[In a thread on DelphiPraxis there was a question that comes up several times a year. However, this time I could remember that there is actually an COM API that can solve the problem. The question was about how to find out which process has a lock on a file. The main problem was, in [...]]]></description>
			<content:encoded><![CDATA[<p>In a thread on DelphiPraxis there was a question that comes up several times a year. However, this time I could remember that there is actually an COM API that can solve the problem. The question was about how to find out which process has a lock on a file. The main problem was, in deed, that I could not remember the API&#8217;s name so Assarbad put some effort in retrieving it. Thanks.<span id="more-861"></span></p>
<p>The name of the API is <a href="http://msdn.microsoft.com/en-us/library/bb775874%28VS.85%29.aspx" target="_blank">IFileIsInUse</a>, an interface. It resides in Shobjidl.h, Shobjidl.idl and newly in JwaShlObj.pas. This is the translation:</p>
<pre class="brush:delphi">{$IFDEF WINVISTA_UP}
const
  IID_IFileIsInUse: TGUID = (
    D1:$64a1cbf0; D2:$3a1a; D3:$4461; D4:($91,$58,$37,$69,$69,$69,$39,$50));

type
  {$ALIGN 4}
  tagFILE_USAGE_TYPE = (
    FUT_PLAYING = 0,
    FUT_EDITING = 1,
    FUT_GENERIC = 2
  );
  FILE_USAGE_TYPE = tagFILE_USAGE_TYPE;
  TFileUsageType = FILE_USAGE_TYPE;

const
  OF_CAP_CANSWITCHTO     = $0001;
  OF_CAP_CANCLOSE        = $0002;

type
  IFileIsInUse = interface(IUnknown)
    ['{64a1cbf0-3a1a-4461-9158-376969693950}']
    function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall;
    function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall;
    function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall;
    function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall;
    function CloseFile() : HRESULT; stdcall;
  end;

{$ENDIF WINVISTA_UP}
</pre>
<p>The interface can be used as a client and also can be implemented by a server. A client usually checks if a file has a lock and retrieves a pointer to this interface to access the methods. A server usually holds a lock on a given file and implements the interface to provide the methods to the client. This article will discuss only the client side.<br />
 You see that this API only works if both sides do their jobs. A process that locks a file must also implement this interface and register it, so a client can receive a status information. There is no direct link between a file lock and the process name. If a process holds a lock on a file but does not implement the interface you are on your own again. <br />
 Eventually, this is only a shell helper for the nice Windows Explorer deletion dialog.</p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2010/11/FileInUse-2.png"><img class="alignnone size-full wp-image-869" title="FileInUse Windows Explorer Dialog" src="http://blog.delphi-jedi.net/wp-content/uploads/2010/11/FileInUse-2.png" alt="" width="496" height="293" /></a></p>
<pre class="brush:delphi">  IFileIsInUse = interface(IUnknown)
    function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall;
    function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall;
    function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall;
    function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall;
    function CloseFile() : HRESULT; stdcall;
  end;
</pre>
<p>The methods of the interface are really easy to understand.</p>
<ul>
<li><em>GetAppName </em>retrieves the name of the process that holds the file. It can be any chosen name by the application designer. To get the name use always a PWideChar and don&#8217;t forget to free it with CoTaskMemFree (it uses the interface IMalloc). Don&#8217;t forget to check for the result. If you like exception you can also rewrite the code using <strong>safecall</strong> (convert the function to a procedure then).</li>
<li><em>GetUsage </em>returns the reason why the file is locked. It can be one of the enumeration constant of  TFileUsage. Either it can be playing a video or music or editing a file. If these are not sufficient the value FUT_GENERIC must be used. Maybe there will be more values in future.</li>
<li> <em>GetCapabilities </em>returns a set of flags in a DWORD. They define whether the file can be closed (OF_CAP_CANCLOSE) by calling <em>CloseFile</em> or the we can put the application into foreground (OF_CAP_CANSWITCHTO). Be aware that you should inform the user that you are about to switch the window. Otherwise she could get nervous about her missing application window. Switching the window can be done by <a href="http://msdn.microsoft.com/en-us/library/ms633539%28VS.85%29.aspx" target="_blank"><em>SetForegroundWindow</em></a>. But your application must have a focus (and some other rules, see MSDN SetForegroundWindow) to switch the window; otherwise nothing happens.</li>
<li><em>GetSwitchToHWND</em> returns a window handle of the other process. Only use this handle to switch to the window. You don&#8217;t really know what window is returned here. Don&#8217;t try to close it or anything else because this is just bad behaviour. At all costs, check the return value. Otherwise you don&#8217;t know whether the returned window handle is valid or just an random number. In worst case it is an existing window from your process. Well, COM rules tell us to nullify the out parameters but usually it is better to check.<br />
 Of course, the call is only valid if GetCapabilities returns the bit OF_CAP_CANSWITCHTO.</li>
<li><em>CloseFile</em> implements the server side of closing the file. The call is only valid if <em>GetCapabilities </em>returns the bit OF_CAP_CANCLOSE. Well, this is really nice. However, don&#8217;t trust it! Always recheck the lock on the file instead of continuing blindly.</li>
</ul>
<p>To retrieve an interface on the file you have to lock it first. Either you download and compile the MSDN example <a href="http://msdn.microsoft.com/en-us/library/ee330722(v=VS.85).aspx" target="_blank">IsFileInUse</a> or you open up an application that implements the interface (e.g. a PDF Reader, MS Office).</p>
<p>The next step is to know where the locked files are placed. The location is the running object table, short ROT (ActiveX.GetRunningObjectTable() retrieves it). It is a global* (on machine) table that holds running COM objects. You can implement your own interfaces and put it in this table. Because interfaces can be arbitrary in its structure and reason to be,  they are attached to monikers (<a href="http://msdn.microsoft.com/en-us/library/ms679705%28VS.85%29.aspx" target="_blank">IMoniker</a>) which describe them uniquely. There are several types of monikers like class, item and file moniker (more information provides IMoniker in MSDN). We are interested in the latter only. <br />
 So the whole work is an enumeration over all monikers in the ROT.  Usually there are not that much in there (I got 5 here). Each moniker is checked for its type (IsSystemMoniker) and if it is a file moniker (MKSYS_FILEMONIKER) the path is compared to the input parameter FileName. Honestly, I cannot tell why there is a comparison of the prefix at first followed by a comparison of the moniker itself, sorry. <br />
 The object itself is retrieved from the moniker by GetObject. It may fail with E_ACCESS_DENIED so a check is done using <em>Succeeded</em>. In the end, we can try to retrieve the IFileIsInUse interface. There may be such a file registered but without the implementation of the interface, thus an additional check.</p>
<p>I didn&#8217;t create this whole source by myself. In fact, there is a <a href="http://msdn.microsoft.com/en-us/library/ee330722(v=VS.85).aspx" target="_blank">FileIsInUse example </a>in MSDN that is the base of this article. The original source is located in the docx file in the download. The example FileIsInUse will create a server.</p>
<p><br class="spacer_" /></p>
<pre class="brush:delphi">function GetFileInUseInfo(const FileName : WideString) : IFileIsInUse;
var
  ROT : IRunningObjectTable;
  mFile, enumIndex, Prefix : IMoniker;
  enumMoniker : IEnumMoniker;
  MonikerType : LongInt;
  unkInt  : IInterface;
begin
  result := nil;

  OleCheck(GetRunningObjectTable(0, ROT));
  OleCheck(CreateFileMoniker(PWideChar(FileName), mFile));

  OleCheck(ROT.EnumRunning(enumMoniker));

  while (enumMoniker.Next(1, enumIndex, nil) = S_OK) do
  begin
    OleCheck(enumIndex.IsSystemMoniker(MonikerType));
    if MonikerType = MKSYS_FILEMONIKER then
    begin
      if Succeeded(mFile.CommonPrefixWith(enumIndex, Prefix)) and
         (mFile.IsEqual(Prefix) = S_OK) then
      begin
       if Succeeded(ROT.GetObject(enumIndex, unkInt)) then
        begin
          if Succeeded(unkInt.QueryInterface(IID_IFileIsInUse, result)) then
          begin
            result := unkInt as IFileIsInUse;
            exit;
          end;
        end;
      end;
    end;
  end;
end;
</pre>
<p><br class="spacer_" /></p>
<h3>Conclusion<br class="spacer_" /></h3>
<p>This whole API has some caveats</p>
<ul>
<li>This API relies on a server that registers an interface in the ROT honestly. If an application doesn&#8217;t do the effort, you will be unable to aquire the name of it.</li>
<li>If you lock a file on a shared folder and you want to access the very same file on the local file system, you cannot determine the process if you access the shared folder from localhost. The reason is Windows itself. Windows is the provider of the file to the outer world (even if it is a loopback) so Windows Explorer shows &#8220;System&#8221; as origin. In the ROT you will see the the UNC path instead of the local file system path. Thus the comparison and our function will fail.</li>
<li>*Security: A ROT is not really global. In fact, there are several ROTs in the system. ROTs are divided by a user and then the mandatory integrity control (MIC) or integrity levels (IL) high, medium and propably low (didn&#8217;t check). If you run as a user, your processes get an medium level and as an Administrator you&#8217;ll get an high integrity level. A server that runs with an medium integrity level will only be allowed to register itself into the medium ROT. So it must be started at least once as Administrator to be allowed to create some Registry keys for COM (LOCAL_MACHINE\Classes\AppID\<em>guid</em>). In this way it will be available in all ROTs if it wants. Unfortunately, this is not the end. On a multi user system, every object in a moniker has a security descriptor that tells COM who is allowed to access it. If Alice wants to access an object in the ROT that was created by Bob, Bob has to explicitily grant Alice access to it. By default the security, which allow access to SYSTEM, Administrators and the creator, is copied from the global COM security settings and can be changed either in the registry for an AppID, at process startup or for each registered object by the server. JWSCL provides all of them in JwsclComSecurity.pas (only Subversion trunk and &gt;= 0.9.4). In this way a server can change the settings to, say, allow all authenticated users access to the object. </li>
</ul>
<h3>Downloads</h3>
<p>You can download the example file from the Subversion directly.</p>
<table border="0">
<tbody>
<tr>
<td><a href="tsvn:https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr"><img class="size-full wp-image-387 alignnone" title="tortoisecheckout" src="http://blog.delphi-jedi.net/wp-content/uploads/2007/12/tortoisecheckout.png" alt="Checkout with TortoiseSVN" width="48" height="48" /></a></td>
<td><a href="https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr" target="_blank">https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr</a></td>
</tr>
</tbody>
</table>
<p><br class="spacer_" /></p>
<h3>Sequel</h3>
<p>The next article discusses the the implementation if the interface IFileIsInUse.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ACTRL_ACCESS Diagram</title>
		<link>http://blog.delphi-jedi.net/2010/02/11/actrl_access-diagram/</link>
		<comments>http://blog.delphi-jedi.net/2010/02/11/actrl_access-diagram/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 12:08:22 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=631</guid>
		<description><![CDATA[I had some trouble with this rather complicated COM structure called ACTRL_ACCESS. So I post a diagram to show its design. Otherwise it would be a pity to leave it on my private hard drive. The ACTRL_ACCESS structure is used by the interface method IAccessControl::GetAllAccessRights (and others) which is rather hard to implement yourself because [...]]]></description>
			<content:encoded><![CDATA[<p>I had some trouble with this rather complicated COM structure called ACTRL_ACCESS. So I post a diagram to show its design. Otherwise it would be a pity to leave it on my private hard drive.</p>
<p><span id="more-631"></span></p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/ms693447%28VS.85%29.aspx">ACTRL_ACCESS</a> structure is used by the interface method <a href="http://msdn.microsoft.com/en-us/library/ms688536%28VS.85%29.aspx">IAccessControl::GetAllAccessRights</a> (and others) which is rather hard to implement yourself because the structure must be created in a single block of memory that can be freed by CoTaskMemFree.</p>
<p>So here is how it looks like</p>
<div id="attachment_632" class="wp-caption alignnone" style="width: 427px"><a href="http://blog.delphi-jedi.net/wp-content/uploads/2010/02/IAccessControl_GetAllAccessRights-structures.png"><img class="size-full wp-image-632 " title="IAccessControl_GetAllAccessRights structures" src="http://blog.delphi-jedi.net/wp-content/uploads/2010/02/IAccessControl_GetAllAccessRights-structures.png" alt="ACTRL_ACCESS design diagram" width="417" height="399" /></a><p class="wp-caption-text">ACTRL_ACCESS design diagram</p></div>
<p>Luckily, JWSCL will provide an implementation of IAccessControl so don&#8217;t worry.</p>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/02/11/actrl_access-diagram/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>COM Server tells you sth about opened client connections</title>
		<link>http://blog.delphi-jedi.net/2008/07/01/com-server-tells-you-sth-about-opened-client-connections/</link>
		<comments>http://blog.delphi-jedi.net/2008/07/01/com-server-tells-you-sth-about-opened-client-connections/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 13:59:58 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[COM]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=247</guid>
		<description><![CDATA[If you create a COM Server to serve some clients with COM interfaces (or better their functionality), you maybe get sometimes a dialog box that tells you that there are client connections opened. This happens as soon as you try to close your app. If you want to close it though, you have to explicitly [...]]]></description>
			<content:encoded><![CDATA[<p>If you create a COM Server to serve some clients with COM interfaces (or better their functionality), you maybe get sometimes a dialog box that tells you that there are client connections opened. This happens as soon as you try to close your app. If you want to close it though, you have to explicitly click &#8220;Yes&#8221;.</p>
<p><span id="more-247"></span></p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2008/07/untitled.jpg"><img class="alignnone size-medium wp-image-248" title="untitled" src="http://blog.delphi-jedi.net/wp-content/uploads/2008/07/untitled.jpg" alt="COM Server warning" width="300" height="130" /></a></p>
<p>You can prevent this dialog box by setting the property <em>UIInteractive</em> of <em>TComServer</em> to <strong>true</strong>. The COM Server instance is defined in unit <strong>ComServ</strong> by the instance variable <em>ComServer</em>. It also sets <em>ObjectCount</em> which defines the remaining client COM connections. The dialog pops up if this value is greater than zero. In this way you can easily check yourself the whole circumstance and show a dialog yourself if you need it.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> ComServ,&#8230;;<br />
&#8230;<br />
<span class="me1">ComServer</span>.<span class="me1">UIInteractive</span> := <span class="kw2">false</span>;</div>
<p>Consider what happens if a dialog box appears in your service app. I did some tests in Windows Vista and found out that the dialog box prevented the service process to be terminated although the service shuts down correctly. So I just set <em>UIInteractive</em> to <strong>false</strong> and it worked fine.</p>
<p>Remember: If a service must be shut down it should do it as fast as possible.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/07/01/com-server-tells-you-sth-about-opened-client-connections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Windows Contacts</title>
		<link>http://blog.delphi-jedi.net/2008/04/08/using-windows-contacts/</link>
		<comments>http://blog.delphi-jedi.net/2008/04/08/using-windows-contacts/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 22:17:13 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Registry]]></category>
		<category><![CDATA[WAB]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=103</guid>
		<description><![CDATA[Since Windows Vista, a new API called Windows Contacts (WC) was born. It replaces the Windows Address BookAPI. You can get your personal properties by using the Windows Address Book Editor. It can be opened using &#8220;wab&#8221; in command line. At first you see your personal &#8220;Contacts&#8221; folder. This folder contains your personal contact file. [...]]]></description>
			<content:encoded><![CDATA[<p>Since Windows Vista, a new API called <a href="http://msdn2.microsoft.com/en-us/library/ms735779%28VS.85%29.aspx">Windows Contacts</a> (WC) was born. It replaces the <a href="http://msdn2.microsoft.com/en-us/library/ms629361(VS.85).aspx">Windows Address Book</a>API.</p>
<p>You can get your personal properties by using the Windows Address Book Editor. It can be opened using &#8220;wab&#8221; in command line.<span id="more-103"></span></p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-21.jpg"><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-21-small.jpg" alt="Bild" width="450" height="336" /></a></p>
<p>At first you see your personal &#8220;Contacts&#8221; folder. This folder contains your personal contact file. Its extension is &#8220;.contact&#8221;. A double click on it opens the Address editor as seen below:</p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-20.jpg"><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-20-small.jpg" alt="Bild" width="450" height="366" /></a></p>
<p>&#8220;Web.exe&#8221; can also receive any personal contact file to import it to your personal contacts.</p>
<p>The contact file contains a formatted text in xml syntax. Data is arranged in a tree that is used to retrieve values. When I am writing of a path, I iterate through the tree. Some of the elements contains a collection of the same element type. The reason comes from the fact, that several other contacts can be added to the personal contact. The WC API uses the array brackets to access different contact values.</p>
<p>The following sample path shows you how to obtain the first user&#8217;s name.(Notice that the array starts with one not zero.)</p>
<blockquote><p>NameCollection/Name[1]/GivenName</p></blockquote>
<p>XML (manually formatted):</p>
<div class="dean_ch" style="white-space: wrap;"><span class="sc3"><span class="re1">&lt;c:NameCollection<span class="re2">&gt;</span></span></span><br />
&nbsp; <span class="sc3"><span class="re1">&lt;c:Name</span> <span class="re0">c:ElementID</span>=<span class="st0">&quot;cf809c84-6692-404e-9f57-6f81e130ee11&quot;</span><span class="re2">&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;c:GivenName</span> <span class="re0">c:Version</span>=<span class="st0">&quot;1&quot;</span> <span class="re0">c:ModificationDate</span>=<span class="st0">&quot;2008-03-27T20:29:18Z&quot;</span><span class="re2">&gt;</span></span>TestUser<span class="sc3"><span class="re1">&lt;/c:GivenName<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;c:FormattedName<span class="re2">&gt;</span></span></span>TestUser<span class="sc3"><span class="re1">&lt;/c:FormattedName<span class="re2">&gt;</span></span></span><br />
&nbsp; <span class="sc3"><span class="re1">&lt;/c:Name<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/c:NameCollection<span class="re2">&gt;</span></span></span></div>
<p>This parts can be cut into three parts:</p>
<ol>
<li>NameCollection defines a container for the array</li>
<li>/Name defines an array which contains all contacts</li>
<li>GivenName defines a name property of exact one contact.</li>
</ol>
<p>There are also Value tags:</p>
<blockquote><p>ContactIDCollection/ContactID[1]/Value</p></blockquote>
<p>XML (manually formatted):</p>
<div class="dean_ch" style="white-space: wrap;"><span class="sc3"><span class="re1">&lt;c:ContactIDCollection<span class="re2">&gt;</span></span></span><br />
&nbsp; <span class="sc3"><span class="re1">&lt;c:ContactID</span> <span class="re0">c:ElementID</span>=<span class="st0">&quot;aa8014fe-423c-4e8e-ad9f-4d750a6ba8bb&quot;</span><span class="re2">&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;c:Value<span class="re2">&gt;</span></span></span>5634564e-72356-339-8220-12342f4a4106<span class="sc3"><span class="re1">&lt;/c:Value<span class="re2">&gt;</span></span></span><br />
&nbsp; <span class="sc3"><span class="re1">&lt;/c:ContactID<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/c:ContactIDCollection<span class="re2">&gt;</span></span></span></div>
<p>This path returns the GUID of contact number one.</p>
<p>Many parts of a path are already defined as constants. Have a look at them in <a href="http://msdn2.microsoft.com/en-us/library/ms735869(VS.85).aspx">MSDN</a>.</p>
<p>So how can we read from the personal contact file? Since new API uses COM, we will use the following interfaces</p>
<ul>
<li>IContact</li>
<li>IContactCollection</li>
<li>IContactManager</li>
<li>IContactProperties</li>
<li>IContactPropertyCollection</li>
</ul>
<p>Actually there is no implementation of these interfaces for Delphi. To create your own type library (TLB) do the following steps (in Vista of course):</p>
<ol>
<li>Get Visual Studio 200x</li>
<li>Download and install the latest version <a href="http://www.microsoft.com/downloads/details.aspx?familyid=ff6467e6-5bba-4bf5-b562-9199be864d29&amp;displaylang=en">Windows SDK</a> for Vista for MIDL and IContact.IDL.</li>
<li>Open the Visual Studio Command Prompt (in VS open menu Tools). We need the predefined include path settings.</li>
<li>Add path of midl.exe from the Windows SDK to your path environment. Use this command:
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">set</span> path=%path%;&lt;your path here&gt;\Microsoft SDKs\Windows\v6<span class="nu0">.0</span>\Bin</div>
</li>
<li>Change folder to ;&lt;your path here&gt;\Microsoft SDKs\Windows\v6.0\Include</li>
<li>Backup and open IContact.idl in your favorite text editor.<br />
Find these lines&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">interface IContactPropertyCollection;<br />
interface IContactCollection;</div>
<p>&#8230;and add :</p>
<div class="dean_ch" style="white-space: wrap;">interface IContactProperties;<br />
interface IContactPropertyCollection;</div>
<p>Additionally find this method&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">HRESULT CommitChanges<span class="br0">&#40;</span><span class="br0">&#91;</span>in<span class="br0">&#93;</span> DWORD dwCommitFlags<span class="br0">&#41;</span>;</div>
<p>&#8230;and also add :</p>
<div class="dean_ch" style="white-space: wrap;">HRESULT _DO_NOT_USE1<span class="br0">&#40;</span><span class="br0">&#91;</span>in<span class="br0">&#93;</span> IContactProperties* pC<span class="br0">&#41;</span>;<br />
HRESULT _DO_NOT_USE2<span class="br0">&#40;</span><span class="br0">&#91;</span>in<span class="br0">&#93;</span> IContactPropertyCollection* pC<span class="br0">&#41;</span>;</div>
<p>In this way <em>midl.exe</em> will also create interfaces in the typelibrary for <em>IContactProperties</em> and <em>IContactPropertyCollection</em>.<br />
I could not figure out how to do it in another way. Comments are apreciated.</li>
<li>You should also find all appearances of&#8230;
<div class="dean_ch" style="white-space: wrap;">procedure Next; safecall;</div>
<p>&#8230;and replace them by:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw2">function</span> Next : HRESULT; stdcall;</div>
<p>It is necessary because we need to check for a positive return value (S_FALSE). Delphi does not raise an EOleSysError exception for positive values.</li>
<li>Save your work and start the conversion:<br />
<strong> midl icontact.idl /tlb icontact.tlb</strong></li>
<li>The new tlb file can now be imported using Delphi. To do so, start Delphi as Administrator, open menu &#8220;Components&#8221; and select &#8220;Install components&#8221; and hit the next button until all the components are listed. Click button &#8220;add&#8221; and choose the newly created <em>IContact.tlb</em>. Delphi imports the library and also generates the Delphi type library source code.</li>
</ol>
<p>Did you know?</p>
<blockquote><p>You can also (un)register a TLB file using regtlib.exe from C:\Windows\System32\URTTEMP<br />
Type &#8220;regtlib Icontact.tlb&#8221; to register the library and &#8220;regtlib /u IContact.tlb&#8221; to unregister it.</p></blockquote>
<p><strong>You can find an already generated type library and and Delphi source code at the end of this article.</strong></p>
<p>Using the Windows Contact API is really easy as soon as the Delphi type library unit exists. It implements class factories for IContact and IContactManager. Use the IContact class factory if you want to add your own contacts to the user&#8217;s personal database. If you just want to read data you have to use IContactManager.<br />
Retrieving the current user&#8217;s profile is simple:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span><br />
&nbsp; ContactManager : IContactManager;<br />
&nbsp; Contact : IContact;<br />
<span class="kw1">begin</span><br />
&nbsp; CoInitialize<span class="br0">&#40;</span><span class="kw2">nil</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; ContactManager := CoContactManager.<span class="me1">Create</span>;<br />
&nbsp; ContactManager.<span class="kw3">Initialize</span><span class="br0">&#40;</span><span class="st0">&#8216;Your AppName&#8217;</span>,<span class="st0">&#8216;AppVersion&#8217;</span><span class="br0">&#41;</span>;</div>
<p>These lines creates an empty contact manager. Notice that the method Initialize is necessary for further calls.<br />
Now we have to actually open the current user&#8217;s contact database.</p>
<div class="dean_ch" style="white-space: wrap;">ContactManager.<span class="me1">GetMeContact</span><span class="br0">&#40;</span>Contact<span class="br0">&#41;</span>;</div>
<p>The new interface Contact contains all the user&#8217;s personal data. We can obtain it through a path value as shown in the beginning of this article.<br />
Let us obtain the user&#8217;s name. This task is done by retrieving the property interface IContactProperties using the Contact instance.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span><br />
&nbsp; ContactProp : IContactProperties;<br />
&nbsp; Path,<br />
&nbsp; Name : <span class="kw4">WideString</span>;<br />
&nbsp; wName : <span class="kw4">PWideChar</span>;<br />
&nbsp; Size : <span class="kw4">Cardinal</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; OleCheck<span class="br0">&#40;</span>Contact.<span class="me1">QueryInterface</span><span class="br0">&#40;</span>IID_IContactProperties, ContactProp<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
<p>The new instance ContactProp allows us to access a property through a path.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp;&#8230;<br />
&nbsp; <span class="me1">Path</span> := <span class="st0">&#8216;NameCollection/Name[1]/GivenName&#8217;</span>;<br />
&nbsp; Size := <span class="nu0">0</span>;</p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; ContactProp.<span class="me1">GetString</span><span class="br0">&#40;</span><span class="kw4">PWideChar</span><span class="br0">&#40;</span>Path<span class="br0">&#41;</span>, <span class="nu0">0</span>, <span class="kw2">nil</span>, <span class="nu0">0</span>, Size<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">except</span><br />
&nbsp; &nbsp; <span class="kw3">GetMem</span><span class="br0">&#40;</span>Name, Size*<span class="kw3">sizeof</span><span class="br0">&#40;</span><span class="kw4">WideChar</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; ContactProp.<span class="me1">GetString</span><span class="br0">&#40;</span><span class="kw4">PWideChar</span><span class="br0">&#40;</span>Path<span class="br0">&#41;</span>, <span class="nu0">0</span>, wName, Size, Size<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; Name := <span class="kw4">WideString</span><span class="br0">&#40;</span>wName<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw3">FreeMem</span><span class="br0">&#40;</span>wName<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">end</span>;</div>
<p>The variable <strong>Name</strong> will contain the user&#8217;s name.  In this way we make sure that the right amount of memory is allocated. Notice that the <strong>GetString</strong> actually returns the count of chars and not the count of bytes, so we have to double the size. We always get an exception in <strong>GetString </strong> because Delphi wraps (safecall convetion) the method and automatically raises an exception if the function returns a negative value (E_XXX code). We don&#8217;t distinguish between a memory error which we need to check for the correct size and a real error. So let us implement it in the right way:</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp;&#8230;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; ContactProp.<span class="me1">GetString</span><span class="br0">&#40;</span><span class="kw4">PWideChar</span><span class="br0">&#40;</span>Path<span class="br0">&#41;</span>, <span class="nu0">0</span>, <span class="kw2">nil</span>, <span class="nu0">0</span>, Size<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">except</span><br />
&nbsp; &nbsp; <span class="kw1">on</span> E : EOleSysError <span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ResultCode<span class="br0">&#40;</span>E.<span class="me1">ErrorCode</span><span class="br0">&#41;</span> &lt;&gt; ERROR_INSUFFICIENT_BUFFER<span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">raise</span>;<br />
&nbsp; &nbsp; &nbsp; &#8230;.<br />
&nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; <span class="kw1">end</span>;</div>
<p>In this way all &#8220;real&#8221; errors are catched and reraised.</p>
<p>All the other properties can be obtained in similar ways. However what properties are available at all? The interface IContactPropertyCollection allows us to obtain all available property names and types. IContactProperties implements a method GetPropertyCollection which returns a pointer to a IContactPropertyCollection that contains the requested properties. It is also possible to filter some of them.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">function</span> GetCollection<span class="br0">&#40;</span><span class="kw1">const</span> ContactProp: IContactProperties<span class="br0">&#41;</span> &#8230;<br />
<span class="kw1">var</span><br />
&nbsp; Dummy : <span class="kw4">PWideChar</span>;<br />
&nbsp; Props : IContactPropertyCollection;<br />
&nbsp; H : HRESULT;</p>
<p><span class="kw1">begin</span><br />
&nbsp; Dummy := <span class="kw2">nil</span>;</p>
<p>&nbsp; ContactProp.<span class="me1">GetPropertyCollection</span><span class="br0">&#40;</span>Props, <span class="nu0">0</span>, <span class="kw2">nil</span>, <span class="nu0">0</span>, Dummy, <span class="kw4">Integer</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
<p>The new property collection contains an enumeration method to iterating all available properties. Be aware that you must call Next before you start getting data.</p>
<div class="dean_ch" style="white-space: wrap;">Dummy<br />
ContactProp.<span class="me1">GetPropertyCollection</span><span class="br0">&#40;</span>Props, <span class="nu0">0</span>, <span class="kw2">nil</span>, <span class="nu0">0</span>, Dummy, <span class="kw4">Integer</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
H := Props.<span class="me1">Next</span>;</p>
<p><span class="kw1">while</span> H &lt;&gt; S_FALSE <span class="kw1">do</span><br />
<span class="kw1">begin</span><br />
&nbsp; &#8230;<br />
&nbsp; <span class="me1">H</span> := Props.<span class="me1">Next</span>;<br />
<span class="kw1">end</span>;</div>
<p>In this way we can obtain name, type , version, modification time and ID of a property.  Just use the available methods of IContactPropertyCollection.</p>
<ul>
<li>GetPropertyName</li>
<li>GetPropertyType</li>
<li>GetPropertyVersion</li>
<li>GetPropertyModificationDate</li>
<li>GetPropertyArrayElementID</li>
</ul>
<p>We already coded how to get a string using COM methods. So this code isn&#8217;t new to you. It retrieves the name of the property.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span><br />
&nbsp; PW : <span class="kw4">PWideChar</span>;<br />
&nbsp; Name : <span class="kw4">WideString</span>;<br />
&nbsp; Size : <span class="kw4">Cardinal</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; Size := <span class="nu0">0</span>;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; Props.<span class="me1">GetPropertyName</span><span class="br0">&#40;</span><span class="kw2">nil</span>,<span class="nu0">0</span>, Size<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">except</span><br />
&nbsp; &nbsp; <span class="kw1">on</span> E : EOleSysError <span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ResultCode<span class="br0">&#40;</span>E.<span class="me1">ErrorCode</span><span class="br0">&#41;</span> &lt;&gt; ERROR_INSUFFICIENT_BUFFER<span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">raise</span>;</p>
<p>&nbsp; &nbsp; &nbsp; <span class="kw3">GetMem</span><span class="br0">&#40;</span>PW, <span class="br0">&#40;</span>Size<span class="nu0">+1</span><span class="br0">&#41;</span>*<span class="kw3">sizeof</span><span class="br0">&#40;</span><span class="kw4">WideChar</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; Props.<span class="me1">GetPropertyName</span><span class="br0">&#40;</span>PW, Size, Size<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; Name := <span class="kw4">WideString</span><span class="br0">&#40;</span>PW<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">end</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<p>To make life easier I created a unit that implements the shown code. You can download ContactMisc.pas in the download section of this article. The unit implements the following functions:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">const</span><br />
&nbsp; CGD_DEFAULT = <span class="re0">$<span class="nu0">00000000</span></span>;</p>
<p>&nbsp; CGD_UNKNOWN_PROPERTY = <span class="re0">$<span class="nu0">00000000</span></span>;<br />
&nbsp; CGD_STRING_PROPERTY = <span class="re0">$<span class="nu0">00000001</span></span>;<br />
&nbsp; CGD_DATE_PROPERTY = <span class="re0">$<span class="nu0">00000002</span></span>;<br />
&nbsp; CGD_BINARY_PROPERTY = <span class="re0">$<span class="nu0">00000004</span></span>;<br />
&nbsp; CGD_ARRAY_NODE = <span class="re0">$<span class="nu0">00000008</span></span>;</p>
<p><span class="kw1">type</span> TWideStringArray = <span class="kw1">array</span> <span class="kw1">of</span> <span class="kw4">WideString</span>;</p>
<p><span class="coMULTI">{@Name contains contact information}</span><br />
TContactProperty = <span class="kw1">record</span><br />
&nbsp; <span class="co1">//ID contains the contact&#8217;s guid as a string</span><br />
&nbsp; ID,<br />
&nbsp; <span class="co1">//Name contains the contanct&#8217;s name</span><br />
&nbsp; Name : <span class="kw4">WideString</span>;<br />
&nbsp; <span class="co1">//Type contains contact type</span><br />
&nbsp; Typ,<br />
&nbsp; Version : <span class="kw4">Cardinal</span>;<br />
&nbsp; <span class="kw3">Time</span> : TFileTime;<br />
<span class="kw1">end</span>;</p>
<p>TContactPropertyArray = <span class="kw1">array</span> <span class="kw1">of</span> TContactProperty;</p>
<p><span class="coMULTI">{@Name returns a contact value in binary form.<br />
@param(Contact defines an interface to a contact which is used to retrieve data)<br />
@param(Path defines a path to the value to be retrieved.<br />
Most calls to @Name needs the string &quot;/Value&quot; at the end for success.<br />
For more about possible path values visit:<br />
http://msdn2.microsoft.com/en-us/library/ms735869(VS.85).aspx<br />
)<br />
@param(Mime returns the mime type of binary data)<br />
@return(Returns a memory stream containing the data)<br />
@raises(EPathNotFound will be raised if parameter Path could not be found.)<br />
}</span><br />
<span class="kw1">function</span> GetContactBinaryValue<span class="br0">&#40;</span><span class="kw1">const</span> Contact : IContact;const Path : <span class="kw4">WideString</span>;<br />
out Mime : <span class="kw4">WideString</span><span class="br0">&#41;</span> : TMemoryStream;</p>
<p><span class="coMULTI">{@Name returns an array of available contact properties.<br />
@param(Contact defines an interface to a contact which is used to retrieve data)<br />
}</span><br />
<span class="kw1">function</span> GetUserContactProperties<span class="br0">&#40;</span><span class="kw1">const</span> Contact : IContact<span class="br0">&#41;</span> : TContactPropertyArray;</p>
<p><span class="coMULTI">{@Name returns all available contacts from a contact manager.<br />
@param(Manager defines an interface to a contact manager interface)<br />
@return(Returns a list of IContact interfaces)<br />
}</span><br />
<span class="kw1">function</span> GetContactList<span class="br0">&#40;</span><span class="kw1">const</span> Manager : IContactManager<span class="br0">&#41;</span> : TInterfaceList;</p>
<p><span class="coMULTI">{@Name returns the value of a contact&#8217;s property<br />
@param(Path defines a path to the value to be retrieved.<br />
Most calls to @Name needs the string &quot;/Value&quot; at the end for success.<br />
For more about possible path values visit:<br />
http://msdn2.microsoft.com/en-us/library/ms735869(VS.85).aspx<br />
)<br />
@param(Contact defines an interface to a contact which is used to retrieve data.)<br />
@raises(EPathNotFound will be raised if parameter Path could not be found.)<br />
}</span><br />
<span class="kw1">function</span> GetContactValue<span class="br0">&#40;</span><span class="kw1">const</span> Contact : IContact;const Path : <span class="kw4">WideString</span><span class="br0">&#41;</span> : <span class="kw4">WideString</span>;</div>
<p>Some hints in the end</p>
<ul>
<li> The Windows Contacts API does not allow to open foreign contact profiles. Although IContactManager implements the method Load, it is useless.  Every contact file may contain several contacts. However only one contact belongs to the user. The method Loads expects a contact file name and the user&#8217;s ID (GUID) .    <strong>/GUID:&#8221;xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx&#8221; /PATH:&#8221;&#8230;&#8230;..\xy.contact&#8221;</strong><br />
You cannot retrieve the GUID of a foreign user with the WC API. To do so, you had to parse the contact file manually.</li>
<li>So how does
<div class="dean_ch" style="white-space: wrap;">ContactManager.<span class="me1">GetMeContact</span><span class="br0">&#40;</span>Contact<span class="br0">&#41;</span>;</div>
<p>retrieve the user&#8217;s ID?<br />
The ID is stored in the registry. Look at &#8230;<br />
<strong> HKEY_CURRENT_USER\Software\Microsoft\WAB\Me</strong><br />
&#8230;and you&#8217;ll find the a string that is necessary for the <strong>Load </strong>method of  <em>IContactManager</em>.</li>
<li>The WC API is sensible to the current token. A service may use an impersonated thread to get a foreign user contact.</li>
</ul>
<p>Download:</p>
<p>Download the package <a title="Demonstration of Windows Contacts API and headers" href="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/windowscontacts.zip">here</a>. It contains:</p>
<ul>
<li>IContact.tlb &#8211; type library</li>
<li>Contact_tlb.pas &#8211; delphi type library header</li>
<li>ContactMisc.pas &#8211; IContact tools</li>
<li>Contacts.dpr &#8211; small demonstration</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/04/08/using-windows-contacts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why aren&#8217;t dialogs themed in elevated COM methods.</title>
		<link>http://blog.delphi-jedi.net/2008/03/14/why-arent-dialogs-themed-in-elevated-com-methods/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/14/why-arent-dialogs-themed-in-elevated-com-methods/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 14:07:33 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[callback]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[dialog]]></category>
		<category><![CDATA[DLL]]></category>
		<category><![CDATA[factory]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[mailinglist]]></category>
		<category><![CDATA[manifest]]></category>
		<category><![CDATA[ProcessExplorer]]></category>
		<category><![CDATA[Theme]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/14/why-arent-dialogs-themed-in-elevated-com-methods/</guid>
		<description><![CDATA[I found this question in the borland mailinglist: &#8230; I get my dialog and all runs well &#8211; *except* I&#8217;ve lost theming on this particular dialog. This means the application&#8217;s main windows shows up correctly themed, the progress dialog does not. I&#8217;ve already added the XP manifest to the progress dialog, too, but to no [...]]]></description>
			<content:encoded><![CDATA[<p>I found this question in the <a href="news://newsgroups.borland.com:119/borland.public.delphi.language.delphi.win32">borland mailinglist</a>:</p>
<blockquote><p>&#8230; I get my dialog and all runs well &#8211; *except* I&#8217;ve lost theming<br />
on this particular dialog. This means the application&#8217;s main windows shows<br />
up correctly themed, the progress dialog does not. I&#8217;ve already added the<br />
XP manifest to the progress dialog, too, but to no avail so far.</p></blockquote>
<p>A theme is only applied if an EXE or DLL file has a manifest that explicitly enables theme support. If Windows cannot find this manifest, the process is only shown with the regular window design.</p>
<p><span id="more-47"></span></p>
<p><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-9-1-small.jpg" alt="Bild" height="168" width="225" /><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-12-small.jpg" alt="Bild" height="168" width="225" /></p>
<p>However the Vista elevation is done by creating a COM object and offers its methods through a seperate process. A seperate process is necessary because the same process cannot get assigned the ncessary administrator token. In our case a service in the service container svchost.exe has the task to host the COM object. The contained service is called dllhost.exe (service name: &#8220;COMSysApp&#8221;) and does not run until requested. It does not matter whether the service is deactivated or not because it is started directly by svchost.</p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-6.jpg"><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-6-small.jpg" alt="Bild" height="100" width="450" /></a></p>
<p>The COM method and the dialog will run in the process space of the newly elevated dllhost.exe. And because there is no manifest information in this file you cannot get a themed dialog layout.</p>
<p><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-7.jpg" alt="Bild" height="105" width="215" /></p>
<p>So how can you get a themed dialog anyhow?</p>
<p>The task is done by using the basic principles of COM. COM knowns Callback interfaces and other stuff. By using a Callback interface you can turn around the server &#8211; client principle.</p>
<ol>
<li>Define a well known interface that is implemented by the client only. But also known to the server.</li>
<li>Add a parameter to your elevated COM method that receives a pointer to this interface.</li>
<li>Before calling an elevated method, create the interface and</li>
<li>apply a pointer to the method&#8217;s parameter you added.</li>
<li>Call the method and use the methods in the given callback interface. COM will automatically transfer the method calls to your non-elevated process. In this way you can create themed windows, do window management stuff (progress bar) and eventually close the window.</li>
</ol>
<p>If you prefer to read code instead of text you should study this code excerpts.</p>
<p>Define a callback interface for your client and add it to the server&#8217;s TypeLib. Delphi will generate code for it automatically in a file called &lt;Name&gt;_TLB.pas (TLB Header). Do not create the interface by using the Delphi&#8217;s ActiveX expert. Just add it manually.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">type</span><br />
&nbsp; IMyCallback = <span class="kw1">interface</span><span class="br0">&#40;</span><span class="kw4">IUnknown</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#91;</span>MYCALLBACK_GUID<span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">procedure</span> ACallBackMethod<span class="br0">&#40;</span>DataFromServer : &#8230;<span class="br0">&#41;</span>; <span class="kw1">safecall</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
&nbsp;<span class="co1">//We do not need a CoClass</span></div>
<p><em>IMyCallback </em>interface is known to both the server and the client, because we use the TLB Header in the client and the server. The client will implement and the server will receive a pointer to it and then call the included method <em>ACallBackMethod</em> everytime it wishes to do so.</p>
<p>The server implements a method to allow a callback interface to be passed to it.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">type</span><br />
&nbsp; IServerInt = <span class="kw1">interface</span><span class="br0">&#40;</span>IDispatch<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#91;</span>ISERVERINT_GUID<span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">procedure</span> DoStuffThatNeedsCallBack<span class="br0">&#40;</span><span class="kw1">const</span> Callback: IMyCallback;&#8230;<span class="br0">&#41;</span> <span class="kw1">safecall</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
&nbsp; <span class="co1">//TypeLib editor also declares a CoClass called CoServerInt</span></div>
<p>Of course you have to implement both interfaces: <em>IServerInt</em> and <em>IMyCallback</em>. However <em>IServerInt </em>is implemented on server side and <em>IMyCallback </em>is only implemented on the client side.</p>
<p>On client side (namely your application) write..</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> &#8230;, ComSrv,ComObj;<br />
<span class="kw1">type</span><br />
&nbsp; TMyCallback = <span class="kw1">class</span><span class="br0">&#40;</span>TComObject, IMyCallback<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">procedure</span> ACallBackMethod<span class="br0">&#40;</span>DataFromServer : &#8230;<span class="br0">&#41;</span>; <span class="kw1">safecall</span>;<br />
&nbsp; <span class="kw1">end</span>;</p>
<p>&#8230;</p></div>
<p>Install the COM object anywhere before you&#8217;re going to use it.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp;TComObjectFactory.<span class="me1">Create</span><span class="br0">&#40;</span>ComServer,<br />
&nbsp; &nbsp; &nbsp;TMyCallback, Class_MyCallback,<br />
&nbsp; &nbsp; &nbsp;<span class="st0">&#8216;MyCallback&#8217;</span>, <span class="co1">//Classname</span><br />
&nbsp; &nbsp; &nbsp;<span class="st0">&#8216;Description here&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp;ciMultiInstance<span class="br0">&#41;</span>;</div>
<p>After all implement the callback method&#8230;</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">procedure</span> TMyCallback.<span class="me1">ACallBackMethod</span><span class="br0">&#40;</span>DataFromServer : &#8230;<span class="br0">&#41;</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="co1">//do stuff on the non-elevated client side</span><br />
<span class="kw1">end</span>;</div>
<p>&#8230;and anywhere you like, call the method to use our Callback interface.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span> Server : IServerInt;<br />
&nbsp; &nbsp; Callback : IMyCallback;<br />
<span class="kw1">begin</span><br />
&nbsp; Server := CoServerInt.<span class="me1">Create</span>;<br />
&nbsp; Callback := TMyCallback.<span class="me1">Create</span> <span class="kw1">as</span> IMyCallback;</p>
<p>&nbsp; Server.<span class="me1">DoStuffThatNeedsCallBack</span><span class="br0">&#40;</span>Callback, &#8230;<span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</div>
<p>I&#8217;m using TComObject and TComObjectFactory on the client side , because this way works for  console applications, too. If you need the possibilities of TAutoIntfObject, you will have to write a standalone COM server with TApplication. However this is not necessary here.  The method ACallBackMethod will be run in the client&#8217;s process space rather than the elevated helper process. You can check whether the callback method runs in the correct process (elevated or not?) with the following code.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">procedure</span> TMyCallback.<span class="me1">ACallBackMethod</span><span class="br0">&#40;</span>DataFromServer : &#8230;<span class="br0">&#41;</span>;<br />
<span class="kw1">var</span> Token : TJwSecurityToken;<br />
<span class="kw1">begin</span><br />
&nbsp; &nbsp;Token := TJwSecurityToken.<span class="me1">CreateTokenEffective</span><span class="br0">&#40;</span>TOKEN_QUERY <span class="kw1">or</span> TOKEN_READ<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp;<span class="kw1">if</span> Token.<span class="me1">RunElevation</span> = <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ShowMessage<span class="br0">&#40;</span><span class="st0">&#8216;Process is NOT Elevated: &#8216;</span>+<span class="kw3">IntToStr</span><span class="br0">&#40;</span>GetCurrentProcessId<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ShowMessage<span class="br0">&#40;</span><span class="st0">&#8216;Process is Elevated: &#8216;</span>+<span class="kw3">IntToStr</span><span class="br0">&#40;</span>GetCurrentProcessId<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw1">finally</span><br />
&nbsp; &nbsp; &nbsp;Token.<span class="me1">Free</span>;<br />
&nbsp; &nbsp;<span class="kw1">end</span>;<br />
<span class="kw1">end</span>;</div>
<p><u>Second way, still on the client side:</u><br />
If you already have a form class, you can add the interface to it.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">type</span><br />
&nbsp; TForm1 = <span class="kw1">class</span><span class="br0">&#40;</span>TForm, IMyCallback<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">protected</span><br />
&nbsp; &nbsp; <span class="kw1">procedure</span> ACallBackMethod<span class="br0">&#40;</span>DataFromServer : &#8230;<span class="br0">&#41;</span>; <span class="kw1">safecall</span>;<br />
&nbsp; <span class="kw1">end</span>;</div>
<p>Instead of creating the COM object, you pass a self-pointer to the method parameter.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">procedure</span> TForm1.<span class="me1">OnButtonClick</span><span class="br0">&#40;</span>&#8230;<span class="br0">&#41;</span>;<br />
<span class="kw1">var</span> Server : IServerInt;<br />
&nbsp; &nbsp; Callback : IMyCallback;<br />
<span class="kw1">begin</span><br />
&nbsp; Server := CoServerInt.<span class="me1">Create</span>;</p>
<p>&nbsp; Server.<span class="me1">DoStuffThatNeedsCallBack</span><span class="br0">&#40;</span><span class="kw2">Self</span>, &#8230;<span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</div>
<p>Be aware that in a multi thread environment, you have to make sure that resources in that specific form are accessed only by one thread at a time.</p>
<p>Eventually the server side calls the methods within the callback interface:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> &#8230;, ComSrv,ComObj; </p>
<p><span class="kw1">type</span><br />
&nbsp; TServerIntImpl = <span class="kw1">class</span><span class="br0">&#40;</span>TAutoObject, IServerInt<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">procedure</span> DoStuffThatNeedsCallBack<span class="br0">&#40;</span><span class="kw1">const</span> Callback: IMyCallback;&#8230;<span class="br0">&#41;</span> <span class="kw1">safecall</span>;<br />
&nbsp; <span class="kw1">end</span>;</p>
<p>&#8230;<br />
<span class="kw1">procedure</span> TServerIntImpl.<span class="me1">DoStuffThatNeedsCallBack</span><span class="br0">&#40;</span><span class="kw1">const</span> Callback: IMyCallback;&#8230;<span class="br0">&#41;</span><br />
<span class="kw1">begin</span><br />
&nbsp; &#8230;<br />
&nbsp; <span class="me1">Callback</span>.<span class="me1">ACallBackMethod</span><span class="br0">&#40;</span>&#8230;<span class="br0">&#41;</span>;<br />
<span class="kw1">end</span>;</p>
<p>&#8230;<br />
<span class="kw1">initialization</span><br />
&nbsp; TAutoObjectFactory.<span class="me1">Create</span><span class="br0">&#40;</span>ComServer, TMyCallback,<br />
&nbsp; &nbsp; &nbsp;Class_MyCallback, ciMultiInstance<span class="br0">&#41;</span>;</div>
<p>The callback method will be called in the context of the client. So it will not be elevated. This is because there is no ordinary method call here. COM will pack the function stack and all its parameter into a stream, send it to the client, unpack it and restore a proper function stack to be executed. This happens in the client process of course.<br />
Get more information about COM callbacks <a href="http://www.informit.com/articles/article.aspx?p=130494&amp;seqNum=5" title="Go to external link.">here</a>.</p>
<hr size="2" width="100%" />Aside from the themed dialog problem you never should show window elements in such an elevated method. There is no need to it. All window elements can be displayed by using standard user rights. They do not need Administrator rights; otherwise we had to logon as Administrator.<br />
However you only should do stuff that needs Administrator privileges in these COM methods. The more code you add to the method the more likely a bug may lead to a security risk. So simply call your function that needs Administrator rights, get the results and go back to Standard user rights. There is really no need to display a window with Administrator privilege.<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/14/why-arent-dialogs-themed-in-elevated-com-methods/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Run a program elevated.</title>
		<link>http://blog.delphi-jedi.net/2008/03/13/run-a-program-elevated/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/13/run-a-program-elevated/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 12:53:21 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[certificate]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[DLL]]></category>
		<category><![CDATA[elevated]]></category>
		<category><![CDATA[elevation]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[RunEl]]></category>
		<category><![CDATA[sign]]></category>
		<category><![CDATA[Vista]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/13/run-a-program-elevated/</guid>
		<description><![CDATA[Today I want to introduce a really useful application from the examples in JEDI Windows Security Code Library. In Windows Vista there is no possible way to run a program elevated from the command line. But today there is a cure. I call it RunEl, which stands for Run Elevated. This simple program uses Delphi, [...]]]></description>
			<content:encoded><![CDATA[<p>Today I want to introduce a really useful application from the examples in JEDI Windows Security Code Library. In Windows Vista there is no possible way to run a program elevated from the command line. But today there is a cure. I call it RunEl, which stands for <strong>Run El</strong>evated. This simple program uses Delphi, the JEDI API and JEDI WSCL. It runs only in Windows Vista and Server 2008 with activated UAC. If there is no UAC, it simply starts the requested application.</p>
<p><span id="more-60"></span><br />
If you start the program without any parameter, you&#8217;ll get the help screen.</p>
<blockquote><p>RunEl V1.0 &#8211; Run application elevated<br />
by Christian Wimmer @ 2008<br />
Visit us at http://blog.delphi-jedi.net</p>
<p>RunEl [/INSTALL][/UNINSTALL][/W[D][G]] [AppName] [Parameters]</p>
<p>Parameters:<br />
/INSTALL &#8211; installs the RunElCOM.dll. Needed for parameter /D<br />
RunElCOM.dll must be in the same folder as RunEl.<br />
/UNINSTALL &#8211; uninstalls the RunElCOM.dll.<br />
W &#8211; Wait for called process to be finished.<br />
D &#8211; uses own elevation COM Class. Before using must be setup with /INSTALL .<br />
G &#8211; uses foreground window to display UAC Prompt on.<br />
Parameters W, D and G must be mixed up with only one &#8220;/&#8221;</p></blockquote>
<p>Despite the INSTALL parameter, you do not have to install the program! I implemented two different ways to elevate an application. There is on the one side ShellExecute, which can elevate an application by passing &#8220;runas&#8221; as a parameter. On the other hand, I implemented the usual way by registering a COM DLL. In the last case, you have to register the DLL first. We get back there later.</p>
<p>Let&#8217;s see how we can use it. Open a command line window and type:</p>
<blockquote><p>RunEl cmd</p></blockquote>
<p>This command starts the Windows command line interpreter as an Administrator. You get the UAC prompt, allow the action and a new cmd window is opened. If you disallow the action, RunEl will return an error value through its process return value. This us useful if you want to check the errorlevel in a batch file.</p>
<blockquote><p>Elevation failed. (2147943623) The operation was canceled by the user.</p></blockquote>
<p>If you need to wait for the process to be closed, you can add the <strong>w</strong>ait parameter. This is also mandatory if you want to check your application&#8217;s return value. Because it is clear that we have to wait until the process&#8217; end to get the return value.</p>
<blockquote><p>RunEl /w cmd</p></blockquote>
<p>Sometimes the UAC prompt does not appear and just blinks in the task to get attention. This is because there is no available window. In this case you can specify parameter &#8220;g&#8221;, which uses the foreground window. The UAC prompt will appear again then.</p>
<blockquote><p>RunEl /g cmd</p></blockquote>
<p>Of course you can also combine both parameters. However there must only be one slash.<br />
All these combinations are the same, so it ignores the case-sensitivity and the order of the three options letters.</p>
<blockquote><p>RunEl /wg cmd<br />
RunEl /gw cmd<br />
RunEl /Gw cmd<br />
RunEl /GW cmd</p></blockquote>
<p>The last parameter &#8220;d&#8221; takes the usual way to get elevated privileges. It runs a COM method as the elevated user, creates the process, returns to non-elevated status and then eventually waits for the process or returns immediately.<br />
However you have to install the provided DLL <em>RunElCOM.dll</em> at first. This is done by using RunEl.</p>
<blockquote><p>RunEl /install<br />
The COM DLL was successfully installed.</p></blockquote>
<p>Now you are able to run applications with the &#8220;d&#8221; parameter in the nearly same way as shown above.</p>
<blockquote><p>Run /d cmd<br />
Run /dw cmd<br />
Run /dwg cmd<br />
&#8230;</p></blockquote>
<p>I say nearly because of two issues:</p>
<ol>
<li>You always have to use /d parameter. Otherwise ShellExecute is used</li>
<li>A major problem of ShellExecute is that it ignores the current directory if it is used for elevation. I circumnavigated this problem by using the following command line internally.<br />
<blockquote><p>cmd /C cd /d &lt;current dir&gt; &amp; &lt;your application&gt; &lt;parameters&gt;</p></blockquote>
<p>The disadvantage of this solution is that you do not get the application&#8217;s return value. Cmd is the main process, so we get its return value instead of &lt;your application&gt;.<br />
If you need the correct return value directly, you have to use /d switch.</li>
</ol>
<p>In the end you can uninstall the COM library.</p>
<blockquote><p>runel /uninstall<br />
The COM DLL was successfully uninstalled.</p></blockquote>
<p>If you try to run an application using runel /d you&#8217;ll get the following error message.</p>
<blockquote><p>RunEl /d cmd<br />
Elevation failed. (2148007959) The class is not configured to support Elevated activation.</p></blockquote>
<hr size="2" width="100%" /><u>Statement:</u><br />
I did not sign my application. So you&#8217;ll always get a nasty UAC dialog. But there are several solutions:</p>
<ol>
<li>Do nothing and accept this dialog</li>
<li>Wait until I buy or get the very expensive sign certificate. I tell you that it will last a really long time.</li>
<li>Use your own certificate to sign the file</li>
</ol>
<p><strong><u>Download and Sourecode:</u></strong></p>
<p>You get the newest version of RunEl in the <a href="http://blog.delphi-jedi.net/2008/03/13/download-runel/" title="Go get RunEl.">JWSCL Download section of RunEl</a>.</p>
<p>RunEl is also available through Subversion repository:</p>
<blockquote><p><a href="https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwscl/trunk/examples/runel">https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwscl/trunk/examples/runel</a></p></blockquote>
<p>You can browse the repository or download it with a Subversion client.</p>
<p>Please send bugs to <a href="mailto:mail@delphi-jedi.net">mail@delphi-jedi.net</a> , the <a href="http://sourceforge.net/mail/?group_id=121894" title="Go get more information about our mailinglists.">mailinglist</a> or the <a href="http://sourceforge.net/tracker/?group_id=121894" title="Go to tracker on SF.">forum</a>.</p>
<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/13/run-a-program-elevated/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

