<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>C++ Hard'n'Fast</title>
        <link>http://geekswithblogs.net/willemf/category/3176.aspx</link>
        <description>C++/ATL/STL/MFC and other ancient technologies</description>
        <language>en-ZA</language>
        <copyright>Willem Fourie</copyright>
        <managingEditor>willemf@bware.biz</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>Win32 XP Key Recovery Utility</title>
            <link>http://geekswithblogs.net/willemf/archive/2006/05/31/80203.aspx</link>
            <description>&lt;P&gt;Following my prior post:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://geekswithblogs.net/willemf/archive/2006/04/23/76125.aspx" target=_blank&gt;Recover your XP product key from the registry using C#&lt;/A&gt;,&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I have had many requests to provide the same code in unmanaged C++ - so here goes:&lt;/P&gt;
&lt;P&gt;
&lt;TABLE cellPadding=16 bgColor=#dddddd border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;PRE&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// KeyDecoder.h&lt;/FONT&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;FONT face="Courier New" color=black size=2&gt;&lt;FONT color=#0000ff&gt;#pragma once
#ifndef byte
typedef unsigned char&lt;/FONT&gt; byte;
&lt;FONT color=#0000ff&gt;#endif&lt;/FONT&gt; &lt;FONT color=green&gt;// byte&lt;/FONT&gt;
&lt;FONT color=blue&gt;class&lt;/FONT&gt; KeyDecoder
{
&lt;FONT color=blue&gt;public&lt;/FONT&gt;:
  &lt;FONT color=#0000ff&gt;enum&lt;/FONT&gt; Key { XP, Office10, Office11 };
  &lt;FONT color=blue&gt;static&lt;/FONT&gt; &lt;FONT color=blue&gt;int&lt;/FONT&gt; DecodeProductKey(KeyDecoder::Key key, &lt;FONT color=blue&gt;char&lt;/FONT&gt;* pDecodedKey);
&lt;FONT color=blue&gt;protected&lt;/FONT&gt;:
  &lt;FONT color=blue&gt;static&lt;/FONT&gt; byte* GetRegistryDigitalProductId(KeyDecoder::Key key);
  &lt;FONT color=blue&gt;static&lt;/FONT&gt; &lt;FONT color=blue&gt;char&lt;/FONT&gt;* DecodeProductKey(byte* digitalProductId);
};&lt;/FONT&gt;&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;and:&lt;/P&gt;
&lt;P&gt;
&lt;TABLE cellPadding=16 bgColor=#dddddd border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;PRE&gt;&lt;FONT face="Courier New" color=#008000&gt;// KeyDecoder.cpp&lt;/FONT&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;#include &lt;/FONT&gt;&lt;FONT face="Courier New" color=black size=2&gt;"StdAfx.h"
&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;#include &lt;/FONT&gt;&lt;FONT face="Courier New" color=black size=2&gt;"keydecoder.h"
&lt;FONT color=blue&gt;int&lt;/FONT&gt; KeyDecoder::DecodeProductKey(KeyDecoder::Key key, &lt;FONT color=blue&gt;char&lt;/FONT&gt;* pKey)
{
  byte* pEncodedPID = GetRegistryDigitalProductId(key);
  &lt;FONT color=blue&gt;int&lt;/FONT&gt; keyLen = 0;
  &lt;FONT color=blue&gt;if&lt;/FONT&gt;(pEncodedPID)
  {
    &lt;FONT color=blue&gt;char&lt;/FONT&gt;* pDecodedPID = DecodeProductKey(pEncodedPID);
    &lt;FONT color=blue&gt;if&lt;/FONT&gt;(pDecodedPID)
    {
      keyLen = (&lt;FONT color=blue&gt;int&lt;/FONT&gt;)::strlen(pDecodedPID);
      &lt;FONT color=blue&gt;if&lt;/FONT&gt;(pKey)
      {
        ::strcpy(pKey, pDecodedPID);
      }
      &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;delete&lt;/FONT&gt;&lt;FONT face="Courier New" color=black size=2&gt;[] pDecodedPID;
    }
  }
  &lt;FONT color=blue&gt;return&lt;/FONT&gt; keyLen + 1;
}
&lt;FONT color=blue&gt;char&lt;/FONT&gt;* KeyDecoder::DecodeProductKey(byte* digitalProductId)
{
  &lt;FONT color=green&gt;// Offset of first byte of encoded product key in &lt;/FONT&gt;
  &lt;FONT color=green&gt;//  'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.&lt;/FONT&gt;
  &lt;FONT color=blue&gt;const&lt;/FONT&gt; &lt;FONT color=blue&gt;int&lt;/FONT&gt; keyStartIndex = 52;
  &lt;FONT color=green&gt;// Offset of last byte of encoded product key in &lt;/FONT&gt;
  &lt;FONT color=green&gt;//  'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.&lt;/FONT&gt;
  &lt;FONT color=blue&gt;const&lt;/FONT&gt; &lt;FONT color=blue&gt;int&lt;/FONT&gt; keyEndIndex = keyStartIndex + 15;
  &lt;FONT color=green&gt;// Possible alpha-numeric characters in product key.&lt;/FONT&gt;
  &lt;FONT color=blue&gt;char&lt;/FONT&gt; digits[] = 
  {
    'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 
    'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
  };
  &lt;FONT color=green&gt;// Length of decoded product key&lt;/FONT&gt;
  &lt;FONT color=blue&gt;const&lt;/FONT&gt; &lt;FONT color=blue&gt;int&lt;/FONT&gt; decodeLength = 29;
  &lt;FONT color=green&gt;// Length of decoded product key in byte-form.&lt;/FONT&gt;
  &lt;FONT color=green&gt;// Each byte represents 2 chars.&lt;/FONT&gt;
  &lt;FONT color=blue&gt;const&lt;/FONT&gt; &lt;FONT color=blue&gt;int&lt;/FONT&gt; decodeStringLength = 15;
  &lt;FONT color=green&gt;// Array of containing the decoded product key.&lt;/FONT&gt;
  &lt;FONT color=blue&gt;char&lt;/FONT&gt;* pDecodedChars = &lt;FONT color=blue&gt;new&lt;/FONT&gt; &lt;FONT color=blue&gt;char&lt;/FONT&gt;[decodeLength + 1];
  ::memset(pDecodedChars, 0, decodeLength + 1); 
  &lt;FONT color=green&gt;// Extract byte 52 to 67 inclusive.&lt;/FONT&gt;
  byte hexPid[keyEndIndex - keyStartIndex + 1];
  &lt;FONT color=blue&gt;for&lt;/FONT&gt; (&lt;FONT color=blue&gt;int&lt;/FONT&gt; i = keyStartIndex; i &amp;lt;= keyEndIndex; i++)
  {
    hexPid[i - keyStartIndex] = digitalProductId[i];
  }
  &lt;FONT color=blue&gt;for&lt;/FONT&gt; (&lt;FONT color=blue&gt;int&lt;/FONT&gt; i = decodeLength - 1; i &amp;gt;= 0; i--)
  {
    &lt;FONT color=green&gt;// Every sixth char is a separator.&lt;/FONT&gt;
    &lt;FONT color=blue&gt;if&lt;/FONT&gt; ((i + 1) % 6 == 0)
    {
      *(pDecodedChars + i) = '-';
    }
    &lt;FONT color=blue&gt;else&lt;/FONT&gt;
    {
      &lt;FONT color=green&gt;// Do the actual decoding.&lt;/FONT&gt;
      &lt;FONT color=blue&gt;int&lt;/FONT&gt; digitMapIndex = 0;
      &lt;FONT color=blue&gt;for&lt;/FONT&gt; (&lt;FONT color=blue&gt;int&lt;/FONT&gt; j = decodeStringLength - 1; j &amp;gt;= 0; j--)
      {
        &lt;FONT color=blue&gt;int&lt;/FONT&gt; byteValue = (digitMapIndex &amp;lt;&amp;lt; 8) | hexPid[j];
        hexPid[j] = (byte)(byteValue / 24);
        digitMapIndex = byteValue % 24;
        *(pDecodedChars + i) = digits[digitMapIndex];
      }
    }
  }
  &lt;FONT color=blue&gt;return&lt;/FONT&gt; pDecodedChars;
}
byte* KeyDecoder::GetRegistryDigitalProductId(KeyDecoder::Key key)
{
  HKEY hKey = 0;
  LONG lResult = 0L;
  &lt;FONT color=blue&gt;const&lt;/FONT&gt; &lt;FONT color=blue&gt;char&lt;/FONT&gt;* pPIDName = "DigitalProductId";
  byte* pPID = 0;
  &lt;FONT color=blue&gt;switch&lt;/FONT&gt;(key)
  {
    &lt;FONT color=blue&gt;case&lt;/FONT&gt; KeyDecoder::Key::XP:
      lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
        0, KEY_QUERY_VALUE, &amp;amp;hKey);
      &lt;FONT color=blue&gt;break&lt;/FONT&gt;;
    &lt;FONT color=blue&gt;case&lt;/FONT&gt; KeyDecoder::Key::Office10:
      &lt;FONT color=blue&gt;break&lt;/FONT&gt;;
    &lt;FONT color=blue&gt;case&lt;/FONT&gt; KeyDecoder::Key::Office11:
      &lt;FONT color=blue&gt;break&lt;/FONT&gt;;
  }
  &lt;FONT color=blue&gt;if&lt;/FONT&gt;(lResult == ERROR_SUCCESS)
  {
    DWORD cbData = 0;
    DWORD dwType = 0;
    lResult = ::RegQueryValueEx(hKey, pPIDName, 0, &amp;amp;dwType, 0, &amp;amp;cbData);
    &lt;FONT color=blue&gt;if&lt;/FONT&gt;(lResult == ERROR_SUCCESS)
    {
      pPID = &lt;FONT color=blue&gt;new&lt;/FONT&gt; byte[cbData];
      lResult = ::RegQueryValueEx(hKey, pPIDName, 0, &amp;amp;dwType, pPID, &amp;amp;cbData);
      &lt;FONT color=blue&gt;if&lt;/FONT&gt;(lResult != ERROR_SUCCESS)
      {
        &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;delete&lt;/FONT&gt;&lt;FONT face="Courier New" color=black size=2&gt;[] pPID;
        pPID = 0;
      }
    }
  }
  &lt;FONT color=blue&gt;if&lt;/FONT&gt;(hKey)
  {
    ::RegCloseKey(hKey);
  }
  &lt;FONT color=blue&gt;return&lt;/FONT&gt; pPID;
}&lt;/FONT&gt;&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;This provides the same functionality as the C# code in the prior post.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;XPKey&lt;/B&gt; is a standard Win32 console application that pops up a message box containing the decoded XP product key. It also copies the product key to the clipboard. You can download the executable here:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://www.bware.biz/DotNet/Tools/XPKey/xpkey.exe"&gt;Download XPKey Console Application&lt;/A&gt;,&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;and the VC source-code and project file here:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://www.bware.biz/DotNet/Tools/XPKey/xpkey.zip"&gt;Download XPKey Source Code&lt;/A&gt;.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The C++ application is provided for VS2003, but should convert without problems to VS2005. It uses only standard Win32 calls - no MFC/ATL/STL etc.&lt;/P&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=80203"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=80203" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/willemf/aggbug/80203.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Willem Fourie</dc:creator>
            <guid>http://geekswithblogs.net/willemf/archive/2006/05/31/80203.aspx</guid>
            <pubDate>Wed, 31 May 2006 13:08:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/willemf/comments/80203.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/willemf/archive/2006/05/31/80203.aspx#feedback</comments>
            <slash:comments>12</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/willemf/comments/commentRss/80203.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/willemf/services/trackbacks/80203.aspx</trackback:ping>
        </item>
        <item>
            <title>Integrating fingerprint and RFID readers in AD/AM applications</title>
            <link>http://geekswithblogs.net/willemf/archive/2005/10/30/58565.aspx</link>
            <description>&lt;P&gt;An interesting adventure - if anyone is interested in how to do this contact me. We used the following devices:&lt;/P&gt;
&lt;LI&gt;SAGEM MSO-series fingerprint reader 
&lt;LI&gt;pcPRox RFID reader 
&lt;LI&gt;ADAM primarily, with some AD integration to hold the fingerprint-minutae data 
&lt;P&gt;What made this interesting was writing the application entirely in 'Unmanaged' C++ and integrating the SAGEM SDK (MorphoSmart API) and the pcProxlib API SDK. Both these APIs are provided as native C++ DLLs and ultimately drove our decision to go the complete C++ route. Some useful techniques&amp;nbsp;for using the ADSI ('ADs...') calls and the various AD/AM COM objects was (painfully) learnt.&lt;/P&gt;
&lt;P&gt;We are currently building a C#-interop wrapper for the various SDKs to make life a lot easier...&lt;/P&gt;&lt;/LI&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=58565"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=58565" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/willemf/aggbug/58565.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Willem Fourie</dc:creator>
            <guid>http://geekswithblogs.net/willemf/archive/2005/10/30/58565.aspx</guid>
            <pubDate>Mon, 31 Oct 2005 00:35:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/willemf/comments/58565.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/willemf/archive/2005/10/30/58565.aspx#feedback</comments>
            <slash:comments>9</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/willemf/comments/commentRss/58565.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/willemf/services/trackbacks/58565.aspx</trackback:ping>
        </item>
        <item>
            <title>User input idle detection in MFC applications</title>
            <link>http://geekswithblogs.net/willemf/archive/2005/10/30/58564.aspx</link>
            <description>&lt;P&gt;&lt;FONT face=Verdana size=2&gt;We needed to write an application that would automatically execute a time-out action, the time-out being a prescribed length of time that has expired without any user input occurring during that period.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Not as easy as it sounds.&amp;nbsp; One way to do it is to setup a set of system-hooks using the message hook APIs provided by Win32.&amp;nbsp; I personally did not like this approach for the following reasons:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;Using system-hooks is intrusive and reduces overall system performance. &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;Its more work, because the hooks provide callbacks for all the windows/processes running and they would have to be filtered. &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;There may be security and credentials constraints setting system-wide hooks while running the application as a user with certain permissions.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I discovered a little gem: the Win32 (user.lib)&lt;/FONT&gt; &lt;FONT face="Courier New" color=#000080 size=2&gt;GetLastInputInfo&lt;/FONT&gt; &lt;FONT face=Verdana size=2&gt;function which returns a data structure containing the system tick-count when the last user input was detected. User input is defined as any captured mouse event or application keyboard event.&amp;nbsp; One problem with this very easy to use function is that if specific inputs have to recognized, eg only mouse events, this function cannot be used.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;The following code-excerpt provides a means of detecting an application user-input idle timeout.&amp;nbsp; The example is an MFC application, and uses a timer event to periodically poll for the last user input time:&lt;FONT color=#0000ff&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;void CMyWindow::OnTimer(UINT nIDEvent)&lt;/FONT&gt;&lt;/FONT&gt; 
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;{ &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // timer event for polling for user-idle timeout.&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;(nIDEvent == TIMEOUT_TIMER_ID) &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the last input event info.&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LASTINPUTINFO li; &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; li.cbSize = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff&gt;sizeof&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;(LASTINPUTINFO); &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ::GetLastInputInfo(&amp;amp;li); &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Calculate the time elapsed in seconds.&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD te = ::GetTickCount(); &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; elapsed = (te - li.dwTime) / 1000; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Test against a preset timeout period in&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // seconds.&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;(Application()-&amp;gt;TimeOut() &amp;lt; elapsed) &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Call a function or set an application flag&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // that can be acted on outside this function.&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnTimeout(); &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .. &lt;/FONT&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;} &lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;BTW, this API is only available in WIN 2000 onwards - correct your &lt;FONT color=#000080&gt;stdafx.h&lt;/FONT&gt; file as follows, to ensure correct compilation and linking:&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;
&lt;DL&gt;
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;#define&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; WINVER 0x0500&lt;/FONT&gt;&lt;FONT color=#0000ff&gt; 
&lt;DT&gt;&lt;FONT face="Courier New" size=2&gt;#define&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; _WIN32_WINNT 0x0500&lt;/FONT&gt;&lt;/DT&gt;&lt;/DL&gt;&lt;/DT&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=58564"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=58564" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/willemf/aggbug/58564.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Willem Fourie</dc:creator>
            <guid>http://geekswithblogs.net/willemf/archive/2005/10/30/58564.aspx</guid>
            <pubDate>Mon, 31 Oct 2005 00:29:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/willemf/comments/58564.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/willemf/archive/2005/10/30/58564.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/willemf/comments/commentRss/58564.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/willemf/services/trackbacks/58564.aspx</trackback:ping>
        </item>
    </channel>
</rss>