<?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; Windows</title>
	<atom:link href="http://blog.delphi-jedi.net/tag/windows/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>Using Windows 7 Taskbar-features via components</title>
		<link>http://blog.delphi-jedi.net/2010/08/18/using-windows-7-taskbar-features-via-components/</link>
		<comments>http://blog.delphi-jedi.net/2010/08/18/using-windows-7-taskbar-features-via-components/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 04:39:49 +0000</pubDate>
		<dc:creator>chaosben</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Window]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=770</guid>
		<description><![CDATA[Windows 7 gave us some nice and useful little eye-catchers in the taskbar. Those are available using the Windows shell interfaces ITaskbarList3 and ITaskbarList4. But alas, how can a Delphi developer incorporate these in his applications? You may read on if you ever wanted to&#8230; have this cool progress bar feature in the taskbar. have [...]]]></description>
			<content:encoded><![CDATA[<p>Windows 7 gave us some nice and useful little eye-catchers in the taskbar. Those are available using the Windows shell interfaces <a href="http://msdn.microsoft.com/en-us/library/dd391692%28v=VS.85%29.aspx" target="_blank">ITaskbarList3</a> and <a href="http://msdn.microsoft.com/en-us/library/dd562040%28VS.85%29.aspx">ITaskbarList4</a>. <br />
 But alas, how can a Delphi developer incorporate these in his applications?</p>
<p><span id="more-770"></span>You may read on if you ever wanted to&#8230;</p>
<ol>
<li>have this cool progress bar feature in the taskbar.</li>
<li>have an overlay icon onto your application&#8217;s icon in the taskbar.</li>
<li>multiple tabs for each window or control of your application in the taskbar.</li>
<li>have thumb buttons inside the preview of your form (like the Windows MediaPlayer).</li>
</ol>
<p>You want your application to look like that?</p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2010/08/Screen1.png"><img class="aligncenter size-full wp-image-804" src="http://blog.delphi-jedi.net/wp-content/uploads/2010/08/Screen1.png" alt="" width="421" height="203" /></a></p>
<p>Are you using Windows 7? What a lucky (wo)man you are.</p>
<p>The guys from <a href="http://code.google.com/p/theunknownones/" target="_blank">TheUnknownOnes</a> just released some components to use the new features introduced in Windows 7.  <br />
 Of course, these components are based on the JEDI Windows API. At the moment (until the next release of JWAPI), you&#8217;ll have to checkout the trunk of the JWAPI in order to get the code compiled. <br />
 To get these components, checkout <a href="http://theunknownones.googlecode.com/svn/trunk/Components/TaskBarList/" target="_blank">the source</a> out of their svn repository.</p>
<p>And if you want to discuss something about them in German: use <a href="http://www.delphipraxis.net/153782-taskbarlistcomponents-fuer-windows-7-a.html" target="_blank">this thread</a>.</p>
<p>A first short demo was published <a href="http://vimeo.com/14291783" target="_blank">here</a>. Stay tuned for some more.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/08/18/using-windows-7-taskbar-features-via-components/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TRegistry.DeleteKey and 64bit</title>
		<link>http://blog.delphi-jedi.net/2010/08/17/tregistry-deletekey-and-64bit/</link>
		<comments>http://blog.delphi-jedi.net/2010/08/17/tregistry-deletekey-and-64bit/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 12:51:19 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[64bit]]></category>
		<category><![CDATA[Registry]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=784</guid>
		<description><![CDATA[I got a bug from someone who told me that he had problems with the TRegistry method DeleteKey on his 64bit Windows. It just didn&#8217;t delete a 64bit key* from the registry although he used the KEY_WOW64_64KEY flag in desired access parameter of  TRegistry.Create. At first I thought that it was a problem with the [...]]]></description>
			<content:encoded><![CDATA[<p>I got a bug from someone who told me that he had problems with the TRegistry method <a href="http://docwiki.embarcadero.com/VCL/en/Registry.TRegistry.DeleteKey" target="_blank"><em>DeleteKey</em></a> on his 64bit Windows. It just didn&#8217;t delete a 64bit key* from the registry although he used the KEY_WOW64_64KEY flag in desired access parameter of  TRegistry.Create.</p>
<p><span id="more-784"></span></p>
<p>At first I thought that it was a problem with the OpenKey function of TRegistry. However, this was already confirmed and fixed as a bug in <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=23429" target="_blank">QC# 23429</a>.</p>
<p>Then I wanted to check the real error value of DeleteKey. Of course, it just returns true or false, so I added a call to GetLastError. And it returned 87 (Invalid Parameter). It must be said that using GetLastError in a framework like VCL is always a problem because you don&#8217;t really know how many winapi functions are called subsequent to the actual winapi function. So you may get an error value from another random function. This is one reason I&#8217;m using exceptions in JWSCL, btw.<br />
 A quick step through debugging session (you have to enable debug dcu in project options and rebuild the project) confirmed that the invalid parameter error (87) came from RegDeleteKey. But why 87? The next step was obvious because I had a windows function and thus I would have to read its <a href="http://msdn.microsoft.com/en-us/library/ms724845%28VS.85%29.aspx" target="_blank">MSDN documentation</a>.</p>
<p>It reads:</p>
<div>
<blockquote><p><cite><strong>RegDeleteKey </strong>Function<br />
 Deletes a subkey and its values. Note that key names are not case sensitive. <strong> </strong></cite></p>
<p><strong>64-bit Windows: </strong>On WOW64, 32-bit  applications view a registry tree that is separate from the registry  tree that 64-bit applications view. To enable an application to delete  an entry in the alternate registry view, use the <a id="ctl00_MTCS_main_ctl01" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl01',this);" href="http://msdn.microsoft.com/en-us/library/ms724847%28VS.85%29.aspx"><strong>RegDeleteKeyEx</strong></a> function.</p>
</blockquote>
<p><br class="spacer_" /></p>
<p>So the RegDeleteKey<strong>Ex</strong> function must be used. But don&#8217;t stop reading here and implement it. We can&#8217;t just use this function because MSDN states that this function is only available in XP 64bit or Vista (32 and 64bit). So this gets more complicated and I suggest this way :</p>
<table border="1">
<tbody>
<tr>
<td></td>
<td>XP 32bit</td>
<td>XP 64bit</td>
<td>Vista and newer (32+64)</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left;">RegDeleteKey</td>
<td>√</td>
<td>only 32bit keys</td>
<td>only 32bit keys</td>
</tr>
<tr>
<td>RegDeleteKeyEx</td>
<td>unsupported</td>
<td style="text-align: center;">√</td>
<td style="text-align: center;">√</td>
</tr>
</tbody>
</table>
<p>√ &#8211; will run fine as it is intended.</p>
<ul>
<li>On a 64bit Windows, always call RegDeleteKeyEx. It supports both 32bit and 64bit registry keys.</li>
<li>Otherwise, if you don&#8217;t want to delete 64bit keys:
<ul>
<li>Call RegDeleteKeyEx on Vista or newer, though.</li>
<li>Call RegDeleteKey on XP 32bit. </li>
</ul>
</li>
</ul>
<p>As a conclusion, you cannot use the TRegistry method DeleteKey with 64bit registry keys. Either you have to use your own RegDeleteKeyEx call or just use a derived class of TRegistry. Of course this is only necessary it you want to access 64bit keys&#8230;this article is FYI.</p>
<p>In the end, the question arises to me why RegDeleteKey does not support 64bit registry keys. I couldn&#8217;t find any evidences, so I can only use my brain to think of one:<br />
 Well, the RegDeleteKey function can be really dangerous if a 32bit application, that is not aware of 64bit, erases 64bit keys. This is especially true for &#8220;HKEY_LOCAL_MACHINE\SOFTWARE&#8221; because you may have installed two versions of an application with same name. First you installed a 32bit only application (name it X) you bought several years ago for your 32bit Windows. One day the vendor sends you a 64bit only update that you install (*so happy*). You decide to abandon the 32bit version and call its custom made uninstaller which deletes all of its known keys. Of course, it will also delete the 64bit version. This may be fictional but possible without the breakup of 32bit and 64bit keys in heavily used parts of the registry. So RegDeleteKey will not delete the 64bit keys because that would break 64bit applications. It seems to me that Microsoft experienced it already, before they decided to add 32-64bit registry separation.  Maybe Raymond Chen would say something like this: <em>Believe us, we tried the other way around:  it&#8217;s worse</em>.</p>
<p><br class="spacer_" /></p>
<p>If you are interested in more information, I suggest you to read <a href="http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx" target="_blank">Accessing an Alternate Registry View</a>.</p>
<p>* The key was a subkey from &#8220;HKEY_LOCAL_MACHINE\SOFTWARE&#8221;. In 64bit Windows, a 32bit application (not aware of 64bit) will only see the contents of &#8220;HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node&#8221;.</p>
<h3>Update</h3>
<p>I submitted a bug report to QC: <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=87323" target="_blank">#87323</a></p>
<h3>Links</h3>
<ul>
<li><a href="http://www.delphipraxis.net/127364-registry-deletekey-problem-unter-xp64.html" target="_blank">DelphiPraxis</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/08/17/tregistry-deletekey-and-64bit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Site Recommendation: History of Windows</title>
		<link>http://blog.delphi-jedi.net/2010/03/13/site-recommondation-history-of-windows/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/13/site-recommondation-history-of-windows/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 23:13:27 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[Recommendation]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=697</guid>
		<description><![CDATA[If you are interested in the history of Windows, as I am, you should read the article The Secret Origin of Windows by Tandy Trower the product manager of Windows 1.0. This article gives a deep insight into the journey Tandy and his developers had to endure to bring a product on the market that [...]]]></description>
			<content:encoded><![CDATA[<p>If you are interested in the history of Windows, as I am, you should read the article<a href="http://technologizer.com/2010/03/08/the-secret-origin-of-windows/" target="_blank"> <strong>The Secret Origin of Windows</strong></a> by Tandy Trower the product manager of Windows 1.0. This article gives a deep insight into the journey Tandy and his developers had to endure to bring a product on the market that should change the world (although it took a while).</p>
<p><span id="more-697"></span>Tandy also mentions the competitor Borland with its famous Turbo Pascal (that I also used) and how it got Bill Gates to tremble.</p>
<p><cite>At $50 for the Borland product vs. the Microsoft $400 compiler, it was a bit like comparing a VW to a Porsche. But while Turbo Pascal was lighter weight for serious development, it was almost as quick for programming and debugging as Microsoft’s BASIC interpreters</cite></p>
<p>I wonder if the comment about the speed is true?</p>
<p>And did you know that Microsoft had been using the language Pascal for their projects until they developed C ?</p>
<p>Read more about <a onclick="pageTracker._trackPageview ('/outgoing/http_technologizer_com_2010_03_08_the_secret_origin_of_windows_');" rel="nofollow" href="http://technologizer.com/2010/03/08/the-secret-origin-of-windows/" target="_blank">The Secret Origin of Windows</a></p>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/13/site-recommondation-history-of-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Retrieving File Owner</title>
		<link>http://blog.delphi-jedi.net/2010/03/11/retrieving-file-owner/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/11/retrieving-file-owner/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 13:52:11 +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[file]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=676</guid>
		<description><![CDATA[This article is about how to retrieve the owner of a file. If you are experienced with some of the WinAPI security function this can be pretty easy. There are some problems that needs to be addressed though. The first one is the size of the security items like the SID name of the owner. [...]]]></description>
			<content:encoded><![CDATA[<p>This article is about how to retrieve the owner of a file. If you are experienced with some of the WinAPI security function this can be pretty easy. There are some problems that needs to be addressed though. The first one is the size of the security items like the SID name of the owner. Secondly, there is the possibility that a SID cannot be resolved to a human readable name at all. And thirdly, we need to check all the result values.</p>
<p><span id="more-676"></span></p>
<h2>WinAPI</h2>
<pre class="brush:delphi">
uses
  SysUtils,
  //JwaWindows, //Use either JwaWindows or these JEDI headers:
  JwaWinBase,
  JwaWinType,
  JwaWinNT,
  JwaAclApi,
  JwaAccCtrl,
  JwaWinError,
  JwaSddl;

type
  TOwnerResult = (orNone, orName, orSID);

function GetFileOwner(const FileName: string;
  out Domain, Username: String): TOwnerResult;
var
  pSD: PSecurityDescriptor;
  dwOwnerNameSize, dwDomainNameSize: DWORD;
  pOwnerSID: PSID;
  pszOwnerName, pszDomainName: PChar;
  OwnerType: SID_NAME_USE;
  dwError : DWORD;
begin
  result := orNone;

  pSD := nil;
  dwError := GetNamedSecurityInfo(
     PChar(FileName),//__in       LPTSTR pObjectName,
     SE_FILE_OBJECT,//__in       SE_OBJECT_TYPE ObjectType,
     OWNER_SECURITY_INFORMATION,//__in       SECURITY_INFORMATION SecurityInfo,
     @pOwnerSID,//__out_opt  PSID *ppsidOwner,
     nil,//__out_opt  PSID *ppsidGroup,
     nil,//__out_opt  PACL *ppDacl,
     nil,//__out_opt  PACL *ppSacl,
     pSD//__out_opt  PSECURITY_DESCRIPTOR *ppSecurityDescriptor
   );
  if (dwError <> NOERROR) then
  begin
    SetLastError(dwError);
    RaiseLastOSError;
  end;

  //First get necessary memory size for Owner and Domain
  dwOwnerNameSize  := 0;
  dwDomainNameSize := 0;
  if not LookupAccountSID(nil, pOwnerSID, nil,
    dwOwnerNameSize, nil, dwDomainNameSize, OwnerType) then
  begin
    //Check for SIDs that are unknown on this local system
    if (GetLastError() = ERROR_NONE_MAPPED) then
    begin
      Win32Check(ConvertSidToStringSid(pOwnerSID, pszOwnerName));
      Domain := '';
      Username := pszOwnerName;
      LocalFree(HLOCAL(pszOwnerName));
      result := orSID;
      exit;
    end
    else
    //Any other error exits the function
    if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
      RaiseLastOsError;
  end;

  //Allocate memory for owner and domain
  //Take into account the size of a char type (like WideCHAR)
  GetMem(pszOwnerName, dwOwnerNameSize*sizeof(CHAR));
  try
    GetMem(pszDomainName, dwDomainNameSize*sizeof(CHAR));
    try
      //Retrieve name and domain
      Win32Check(LookupAccountSID(nil, pOwnerSID, pszOwnerName,
        dwOwnerNameSize, pszDomainName, dwDomainNameSize, OwnerType));

      result := orName;

      Domain   := pszDomainName;
      Username := pszOwnerName;
    finally
      FreeMem(pszDomainName);
    end;
  finally
    FreeMem(pszOwnerName);
  end;
end;
</pre>
<p>The function behaves the following:</p>
<ul>
<li>If an WinAPI error occurs the exception EOSError is thrown. You can retrieve the error value from its property Errorcode.</li>
<li>If the user name could be retrieved the result value is <em>orName</em> and both parameter <em>Domain </em>and <em>UserName</em> contain a value. Otherwise the result is orSID and only UserName contains the User Security Identifier (e.g. S-1-5-21-564352346-2735467565-567745764-1001).</li>
</ul>
<h2>JWSCL</h2>
<p>Of course, JWSCL wraps these function calls already. Thus the source size decreases rapidly. See another <a href="http://blog.delphi-jedi.net/2007/10/21/why-jwscl">example here</a>.<br />
In JWSCL it is quite different to implement the function. However the behaviour is equal:</p>
<pre class="brush:delphi">function JwsclGetFileOwner(const FileName: string;
  out Domain, Username: String): TOwnerResult;
var
  F : TJwSecureFileObject;
  Owner : TJwSecurityId;
begin
  F := TJwSecureFileObject.Create(FileName);
  try
    Owner := F.Owner; //Owner is cached/freed by TJwSecureFileObject
    try
      Domain := Owner.GetAccountDomainName();
      Username := Owner.GetAccountName();
      Result := orName;
    except
      on E : EJwsclWinCallFailedException do
      begin
        if E.LastError = ERROR_NONE_MAPPED then
        begin
          Domain := '';
          Username := Owner.StringSID;
          Result := orSID;
        end
        else
          raise;
      end;
    end;
  finally
    F.Free;
  end;
end;
</pre>
<p>In a next version of JWSCL (currently trunk) the exception handling will be a little bit different:</p>
<pre class="brush:delphi">function JwsclGetFileOwner2(const FileName: string;
  out Domain, Username: String): TOwnerResult;
var
  F : TJwSecureFileObject;
  Owner : TJwSecurityId;
begin
  F := TJwSecureFileObject.Create(FileName);
  try
    Owner := F.Owner; //Owner is cached/freed by TJwSecureFileObject
    try
      Domain := Owner.GetAccountDomainName();
      Username := Owner.GetAccountName();
      Result := orName;
    except
      on E : EJwsclSidNotMappedException do //not mapped error is handled differently
      begin
        Domain := '';
        Username := Owner.StringSID;
        Result := orSID;
      end;
    end;
  finally
    F.Free;
  end;
end;
</pre>
<p>If you use JWSCL (Version >= 0.9.2a) and enable the compiler switch <strong>JWSCL_SIDCACHE</strong> in file Include\Jwscl.inc, JWSCL will add a SID cache (for all TJwSecurityID instances globally). In this way LookupAccountSid will be called only once for every unknown SID and thus SIDs that were already translated are retrieved from cache instead.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/11/retrieving-file-owner/feed/</wfw:commentRss>
		<slash:comments>0</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>Version Checking for Delphi (2nd Update)</title>
		<link>http://blog.delphi-jedi.net/2009/08/29/version-checking-for-delphi/</link>
		<comments>http://blog.delphi-jedi.net/2009/08/29/version-checking-for-delphi/#comments</comments>
		<pubDate>Sat, 29 Aug 2009 14:07:23 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=392</guid>
		<description><![CDATA[There is an interesting article about checking the version of the operating system. If you are too lazy to read it then just remember this: Do not check it at all! Well, I changed my mind. You should read it! So go to Yochay Kiriaty&#8217;s Article, read it and then get back her for the [...]]]></description>
			<content:encoded><![CDATA[<p>There is an interesting article about checking the version of the operating system. If you are too lazy to read it then just remember this: Do not check it at all!<br />
 Well, I changed my mind. You should read it! So go to <a href="http://windowsteamblog.com/blogs/developers/archive/2009/08/05/version-checking-just-don-t-do-it.aspx" target="_blank">Yochay Kiriaty&#8217;s</a> Article, read it and then get back her for the Delphi part.</p>
<p><span id="more-392"></span>What have we learned from the article?</p>
<ol>
<li>Avoid version checks at all</li>
<li>Check for functionality</li>
<li>Use the right functions</li>
<li>Learn logic</li>
</ol>
<h3>1. It is always frustrating if an application doesn&#8217;t start because of version checking.</h3>
<p>If you have a Win32API function that is not available on older OS, do not use a version check. If you don&#8217;t dive the internal structures of Window it is very likely that your application will work.</p>
<h3>2. Instead: try to load the function with GetProcAddress. If it fails, well then use something else.</h3>
<p>That is the reason why I tell people to set the DYNAMIC_LINK compiler switch when using any of the JEDI functions. In this case the JEDI API libraries loads a function using <em>GetProcedureAddress </em>(located in JwaWinTypes &#8211; don&#8217;t ask me why it is located there).<br />
 GetProcedureAddress can raise two types of Exception.</p>
<ul>
<li>EJwaLoadLibraryError : If a necessary library could not be found.</li>
<li>EJwaGetProcAddressError : If the function could not be located in the library.</li>
</ul>
<p>So now it is easy to write an exception handler:</p>
<pre class="brush:delphi">try
  API_Call(...);
except
  on E1 : EJwaLoadLibraryError do
    //fail safe library not found
  on E2 : EJwaGetProcAddressError do
   //fail safe function not found
end;</pre>
<p>Well, this code only works if you define DYNAMIC_LINK in your project options. Don&#8217;t forget it! If it is not defined, and you try to run your application on an older Windows, it just won&#8217;t start. Instead you get a nasty error message.</p>
<p>Delphi 2010 comes with a new feature that MS Visual C++ people know as <a href="http://msdn.microsoft.com/en-us/library/151kt790.aspx" target="_blank">Linker support for Delay-loaded DLLs</a>.<br />
 Allen Bauer posted an article about this new feature for Delphi under the strange headline <a href="http://blogs.embarcadero.com/abauer/2009/08/25/38894" target="_blank">Procrastinators Unite… Eventually!</a> You can also think of it as &#8220;Delay loaded functions for Delphi&#8221;.</p>
<pre class="brush:delphi">function NewAPIFunction(Parameter : TParameter): BOOL; stdcall;
  external 'user32.dll' name 'NewAPIFunction' delayed;
...

begin
  NewAPIFunction(Parameter);
end;</pre>
<p>Do you recognize the new word &#8220;delayed&#8221; ? If you try to access the function for the first time, it will be loaded automatically from the library &#8220;user32.dll&#8221;. So we don&#8217;t have to be afraid of running the application on an older Windows version. Unfortunately, we also have to add code that checks for the Windows version.</p>
<pre class="brush:delphi">begin
  if OSVersion > 5.1 then
    NewAPIFunction(Parameter);
end;</pre>
<p><span style="font-size: x-small;">(Don&#8217;t be confused about <em>GreaterThan</em>. There is a </span><span style="font-size: x-small;">bug in the code </span><span style="font-size: x-small;">plugin that prevents the greater sign to be shown correctly.)</span></p>
<p>Haven&#8217;t we learned that it is not good to check for the OS version? Shouldn&#8217;t we check for functionality? Apparently, delay loading in Delphi 2010 wasn&#8217;t created with this idea in mind.<br />
 If we change the library name or the function name to something incorrect, like:</p>
<pre class="brush:delphi">function NewAPIFunction(Parameter : TParameter): BOOL; stdcall;
  external 'user32Bla.dll' name 'NewAPIFunction' delayed;
...

begin
  NewAPIFunction(Parameter);
end;</pre>
<p>&#8230;and call this function, at least, I get a nasty <em>EExternalException </em>with the message &#8220;External Exception C0FB007<strong>E</strong>&#8220;.<br />
 Even using the correct library but an incorrect function name doesn&#8217;t change the exception type, but the message :<br />
 &#8220;External Exception C0FB007<strong>F</strong>&#8220;.</p>
<p>Well, It could have been so nice! And in Update 2 we&#8217;re going to see how&#8230;</p>
<pre class="brush:delphi">function NewAPIFunction(Parameter : TParameter): BOOL; stdcall;
  external 'user32.dll' name 'NewAPIFunction' delayed;
...

begin
  try
    NewAPIFunction(Parameter);
  on E1 : ELoadLibraryError do
    //fail safe library not found
  on E2 : EGetProcAddressError do
   //fail safe function not found
end;</pre>
<p>Instead we need to check:</p>
<pre class="brush:delphi">function NewAPIFunction(Parameter : TParameter): BOOL; stdcall;
  external 'user32.dll' name 'NewAPIFunction' delayed;
...

begin
  try
    NewAPIFunction(Parameter);
  on E : EExternalException do
    //failsafe
end;</pre>
<p>However, I wouldn&#8217;t even be sure that this exception type is always the same. <em>EExternalException </em>is always suspect to me, isn&#8217;t it? So in the end it is all about <em>Exception</em>.</p>
<h2>UPDATE</h2>
<p>I was so short sighted! To the COM people  <em>C0FB007E</em> should look quite familiar. Yeah, it is a <a href="http://en.wikipedia.org/wiki/HRESULT" target="_blank">HRESULT</a> code. It maps to</p>
<p>Severity (ERROR_SEVERITY_ERROR = $C) + Facility Code ($FB) + Code (7E and 7F)</p>
<p>Well $7E is 126 in decimal and can be found in JwaWinError.pas as ERROR_MOD_NOT_FOUND. Same goes for $7F =127 which is ERROR_PROC_NOT_FOUND.</p>
<p>Knowing this we can use:</p>
<pre class="brush:delphi">begin
  try
    NewAPIFunction(Parameter);
  on E : EExternalException do
     RaiseLastOSError(Windows.HResultCode(E.ExceptionRecord.ExceptionCode));
  end;
end;</pre>
<p>This exception should be known to Delphi programmers. And you can add another try except block around to catch the Win32 exception.</p>
<p>The exception EExternalException comes from an internal call to <a href="http://msdn.microsoft.com/en-us/library/ms680552%28VS.85%29.aspx" target="_blank">RaiseException</a>.</p>
<h2>UPDATE2:</h2>
<p>If you read the system.pas file from Delphi 2010 you&#8217;ll find the function SetDliFailureHook. It allows us to get notified when an delayed loading error occured.  So how does it look?</p>
<pre class="brush:delphi">uses
  Windows,
  SysUtils;

type
  ELoadLibraryError = class(EWin32Error);
  EGetProcAddressError = class(EWin32Error);

function DelayedFailureHook(dliNotify: dliNotification; pdli: PDelayLoadInfo): Pointer; stdcall;
begin
  case dliNotify of
    dliNoteStartProcessing: ;
    dliNotePreLoadLibrary: ;
    dliNotePreGetProcAddress: ;
    dliFailLoadLibrary   :
      raise ELoadLibraryError.CreateFmt(
        'Failed to load library "%0:s".'#13#10' Error (%1:d) %2:s',[AnsiString(pdli.szDll),
          pdli.dwLastError, SysErrorMessage(pdli.dwLastError)]);
    dliFailGetProcAddress:
      if pdli.dlp.fImportByName then
        raise EGetProcAddressError.CreateFmt(
            'Failed to load function "%0:s" from "%1:s"'#13#10' Error (%2:d) %3:s',[
           AnsiString(pdli.dlp.szProcName), AnsiString(pdli.szDll),
          pdli.dwLastError, SysErrorMessage(pdli.dwLastError)])
      else
        raise EGetProcAddressError.CreateFmt(
            'Failed to load function #%0:d from "%1:s"'#13#10' Error (%2:d) %3:s',[
           pdli.dlp.dwOrdinal, AnsiString(pdli.szDll),
          pdli.dwLastError, SysErrorMessage(pdli.dwLastError)]);

    dliNoteEndProcessing: ;
  end;
end;

...
begin
  SetDliFailureHook(DelayedFailureHook);

  try
    NewAPIFunction(Parameter);
  on E1 : ELoadLibraryError do
    //fail safe library not found
  on E2 : EGetProcAddressError do
   //fail safe function not found
  end;
end.</pre>
<p>All the other errors we don&#8217;t process are converted to an EExternalException error automatically. You can try it out by removing the case dliFailLoadLibrary or dliFailGetProcAddress.</p>
<p>By the way:</p>
<ol>
<li> The function pointer of NewAPIFunction is not nil. It points to an address that does the magic behind the curtain.</li>
<li>If you wonder why the JEDI Windows API hasn&#8217;t implemented this feature: We are still in pre alpha stage.<br />
 You could help by telling us your experience with this feature.</li>
</ol>
<h3>3. Using the right functions can be a bit problematic. There are a lot of possible functions you can use:</h3>
<ol>
<li>JwaWinBase/Windows contains GetVersion and GetVersionEx</li>
<li>There is also a more complex function called VerifyVersionInfo(Ex)</li>
<li>And Delphi comes with a function of its own in SysUtils :  CheckWin32Version</li>
</ol>
<p>CheckWin32Version is little known to Delphi programmers. Instead they create their own complicated classes and tool functions. But if you just want to check for the major and minor version of the OS, try this:</p>
<pre class="brush:delphi">if CheckWin32Version(5, 1) then</pre>
<p>It checks for Windows XP regardless of a service pack. It is the easiest and safest way to check the OS version. But sometimes you need also to know the service pack or even more.</p>
<p>GetVersion and GetVersionEx can be hard to be used. So Microsoft added support for a more flexible and safe way to check the OS version. VerifyVersionInfo was born.</p>
<p>I have translated Yochay Kiriaty&#8217;s example of VerifyVersionInfo for you.</p>
<pre class="brush:delphi">uses
  JwaWinNT,
  JwaNative,
  JwaWinBase;

function IsWindowsXPorLater : Boolean;
const
  Condition = VER_GREATER_EQUAL;
var
  OSInfo : TOSVersionInfoEx;
  ConditionMask : Int64;
begin
  ZeroMemory(@OsInfo, sizeof(OSInfo));
  OSInfo.dwOSVersionInfoSize := SizeOf(OSInfo);
  OSInfo.dwMajorVersion := 5;
  OSInfo.dwMinorVersion := 1;
  OSInfo.wServicePackMajor := 1;
  OSInfo.wServicePackMinor := 0;

  ConditionMask := 0;
  ConditionMask := VerSetConditionMask(ConditionMask, VER_MAJORVERSION, Condition);
  ConditionMask := VerSetConditionMask(ConditionMask, VER_MINORVERSION, Condition);
  ConditionMask := VerSetConditionMask(ConditionMask, VER_SERVICEPACKMAJOR, Condition);
  ConditionMask := VerSetConditionMask(ConditionMask, VER_SERVICEPACKMINOR, Condition);

  result := VerifyVersionInfo(OSInfo, VER_MAJORVERSION or VER_MINORVERSION or
     VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR,
     ConditionMask);
end;</pre>
<p>I hope more people are going to use this function.</p>
<h3>4. In the end I also want to write something about logic.</h3>
<p>If you wonder why so many applications ceased to work when Windows Vista came out. Well, if you look at this code you should know why (Windows XP: 5.1 -&gt; Vista: 6.0)</p>
<pre class="brush:delphi"> if (MajorVersion >= 5) and (MinorVersion >= 1) then
 begin 'OK'
 end
 else
 begin
 'Sorry. Old Windows version detected'
 end;</pre>
<p>Well, such a (similar) code is (still) used a lot of times. And it seems to work for Windows 2000 and XP. But in Vista MajorVersion was changed to 6 and, because it was the very first release of version 6, MinorVersion was set to zero. So the if condition stopped working on the second condition check. (BTW: This is a reason why Windows 7 is using version 6.1 instead of version 7.0 .)<br />
 Sometimes we need to apply the <a href="http://en.wikipedia.org/wiki/Mathematical_logic">basic rules of logic</a> (read a good book from <a href="http://www.amazon.co.uk/s/ref=nb_ss?url=search-alias%3Dstripbooks&amp;field-keywords=logic&amp;x=19&amp;y=16">Amazon</a>) or check (nearly) all possible values in a table:</p>
<table style="text-align: center;" border="0">
<thead>
<tr class="wp-caption">
<td>MajorVersion</td>
<td>MinorVersion</td>
<td>Condition Result</td>
</tr>
</thead>
<tbody>
<tr>
<td>&#8230;</td>
<td>&#8230;</td>
<td>&#8230;</td>
</tr>
<tr>
<td>4</td>
<td>1</td>
<td>False</td>
</tr>
<tr>
<td>4</td>
<td>2</td>
<td>False</td>
</tr>
<tr>
<td>4</td>
<td>3</td>
<td>False</td>
</tr>
<tr>
<td>5</td>
<td>0</td>
<td>False</td>
</tr>
<tr>
<td>5</td>
<td>1</td>
<td>True</td>
</tr>
<tr>
<td>5</td>
<td>2</td>
<td>True</td>
</tr>
<tr>
<td>5</td>
<td>3</td>
<td>True</td>
</tr>
<tr>
<td>6</td>
<td>0</td>
<td>False</td>
</tr>
<tr>
<td>6</td>
<td>1</td>
<td>True</td>
</tr>
<tr>
<td>7</td>
<td>0</td>
<td>False</td>
</tr>
<tr>
<td>7</td>
<td>1</td>
<td>True</td>
</tr>
</tbody>
</table>
<p>Not all Windows versions in this table really exists. But how could you know that at that time? So make the table as complete as possible. Then you can change the variables <em>Win32MajorVersion </em>and <em>Win32MinorVersion </em>to the test your if condition and run your application. Software engineers also use unit tests to check the <span style="text-decoration: line-through;">correctness</span> efficiency of their functions.</p>
<p>All in all, if the people of the bad applications had used a function like CheckWin32Version, we hadn&#8217;t this article now:</p>
<pre class="brush:delphi">function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;
 begin
 Result := (Win32MajorVersion >AMajor) or
 ((Win32MajorVersion = AMajor) and
 (Win32MinorVersion >= AMinor));
 end;</pre>
<p>But then we couldn&#8217;t blame Microsoft for their bad compatibility. *g*</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2009/08/29/version-checking-for-delphi/feed/</wfw:commentRss>
		<slash:comments>3</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>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>Article about WinAPI programming</title>
		<link>http://blog.delphi-jedi.net/2008/03/11/article-about-winapi-programming/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/11/article-about-winapi-programming/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 12:39:09 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[callback]]></category>
		<category><![CDATA[DLL]]></category>
		<category><![CDATA[dynamic]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[libraries]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/11/article-about-winapi-programming/</guid>
		<description><![CDATA[I found this very old but still good article about how to use the Windows API. These are the subjects: Part I: The Primer Windows API calls are just calls to dynamic link libraries Loading a dynamic link library Dynamic loading at runtime Resource only dynamic link libraries Stack usage and dynamic link libraries Callback [...]]]></description>
			<content:encoded><![CDATA[<p>I found this very old but still good <a href="http://dn.codegear.com/article/10322">article</a> about how to use the Windows API.</p>
<p>These are the subjects:</p>
<ol>
<li>Part I: The Primer</li>
<li>Windows API calls are just calls to dynamic link libraries</li>
<li>Loading a dynamic link library</li>
<li>Dynamic loading at runtime</li>
<li>Resource only dynamic link libraries</li>
<li>Stack usage and dynamic link libraries</li>
<li>Callback functions</li>
<li>The Hook functions</li>
<li>Data storage in dynamic link libraries</li>
<li>Instanced addresses and thunking</li>
<li>Part II: Getting our hands dirty</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/11/article-about-winapi-programming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

