<?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>words &#187; Win32</title>
	<atom:link href="http://www.curlybrace.com/words/category/technology/win32-technology-2/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.curlybrace.com/words</link>
	<description>by Jeff Fitzsimons</description>
	<lastBuildDate>Tue, 20 Dec 2011 10:21:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>BluetoothAPIs.h Broken in Windows SDK</title>
		<link>http://www.curlybrace.com/words/2011/01/17/bluetoothapis-h-broken-in-windows-sdk/</link>
		<comments>http://www.curlybrace.com/words/2011/01/17/bluetoothapis-h-broken-in-windows-sdk/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 08:54:21 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=1551</guid>
		<description><![CDATA[Summary The Microsoft Windows SDK versions 7.0 and 7.1 appear to have broken BluetoothAPIs.h header files. Details So far, I have uncovered two types of errors in this header file: The use of #pragma deprecate instead of #pragma deprecated, causing &#8230; <a href="http://www.curlybrace.com/words/2011/01/17/bluetoothapis-h-broken-in-windows-sdk/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Summary</h2>
<p>The Microsoft Windows SDK versions 7.0 and 7.1 appear to have broken BluetoothAPIs.h header files.</p>
<h2>Details</h2>
<p>So far, I have uncovered two types of errors in this header file:
<ul>
<li />The use of <tt>#pragma deprecate</tt> instead of <tt>#pragma deprecated</tt>, causing compiler warnings.
<li />Several callback function pointer type definitions omit the <tt>CALLBACK</tt> (<a href="http://msdn.microsoft.com/en-us/library/zxk0tw93(v=vs.80).aspx"><tt>__stdcall</tt></a>) calling convention, causing a crash.
</ul>
<p>The first error simply results in compiler warnings.</p>
<blockquote><pre>warning C4068: unknown pragma</pre>
</blockquote>
<p>The second type of error results in dereferencing of an invalid memory location when using <tt>BluetoothRegisterForAuthenticationEx</tt> and <tt>BluetoothAuthenticateDeviceEx</tt>.  This is because the standard calling convention (<a href="http://msdn.microsoft.com/en-us/library/zkwh89ks(v=vs.80).aspx"><tt>__cdecl</tt></a>) assumes that the caller will clean up the stack.  Since the caller in this case is assuming that the callback function minded its own stack, it immediately pops <tt>ESI</tt>, placing zero into the register:</p>
<blockquote><pre>5EBCFFE2  mov         ecx,dword ptr [ebp-4]
5EBCFFE5  pop         esi
5EBCFFE6  xor         ecx,ebp
5EBCFFE8  pop         ebx
5EBCFFE9  call        @__security_check_cookie@4 (5EBDBBBBh)</pre>
</blockquote>
<p>Later, ntdll.dll dereferences memory at <tt>ESI + 4</tt>, triggering an access violation:</p>
<blockquote><pre>774A8301  test        byte ptr [esi+4],4</pre>
</blockquote>
<blockquote><p>&#8220;Unhandled exception at 0x774a8301 (ntdll.dll) in [Application]: 0xC0000005: Access violation reading location 0&#215;00000004.</p></blockquote>
<h2>Solution</h2>
<p>To the compiler warnings, I replaced all instances of </p>
<blockquote><p><tt>#pragma deprecate</tt></p></blockquote>
<p>with</p>
<blockquote><p><tt>#pragma deprecate<b>d</b></tt></p></blockquote>
<p>To fix the crash bug, I added the <tt>CALLBACK</tt> calling convention keyword to <tt>PFN_AUTHENTICATION_CALLBACK</tt> and <tt>PFN_AUTHENTICATION_CALLBACK_EX</tt>.  They now appear as follows:</p>
<blockquote><p><tt>typedef BOOL (<b>CALLBACK</b> *PFN_AUTHENTICATION_CALLBACK)(LPVOID pvParam, PBLUETOOTH_DEVICE_INFO pDevice);</tt></p></blockquote>
<blockquote><p><tt>typedef BOOL (<b>CALLBACK</b> *PFN_AUTHENTICATION_CALLBACK_EX)(__in_opt LPVOID pvParam, __in PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams);</tt></p></blockquote>
<p>Interestingly, the function pointer type definitions for the attribute-enumeration and device-selection callbacks (<tt>PFN_BLUETOOTH_ENUM_ATTRIBUTES_CALLBACK</tt> and <tt>PFN_DEVICE_CALLBACK</tt>, respectively) are defined correctly, using <tt>CALLBACK</tt> or <tt>WINAPI</tt>.  I suspect that the inconsistency is because someone at Microsoft was using the <tt>/Gz</tt> compiler switch, making <tt>__stdcall</tt> the default calling convention.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2011/01/17/bluetoothapis-h-broken-in-windows-sdk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Demise of CAPICOM</title>
		<link>http://www.curlybrace.com/words/2008/10/15/the-demise-of-capicom/</link>
		<comments>http://www.curlybrace.com/words/2008/10/15/the-demise-of-capicom/#comments</comments>
		<pubDate>Thu, 16 Oct 2008 06:43:01 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[Authenticode]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[CAPICOM]]></category>
		<category><![CDATA[code signing]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=266</guid>
		<description><![CDATA[CAPICOM, a COM-based wrapper for the CryptoAPI library, is deprecated and on its way out. However, Microsoft has no time line for phasing it out, nor have they provided sufficient documentation of alternatives. Many CAPICOM pages contain a confusing, bright-red &#8230; <a href="http://www.curlybrace.com/words/2008/10/15/the-demise-of-capicom/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>CAPICOM, a COM-based wrapper for the CryptoAPI library, is deprecated and on its way out.  However, Microsoft has no time line for phasing it out, nor have they provided sufficient documentation of alternatives.</p>
<p>Many CAPICOM pages contain a confusing, bright-red header along the lines of:</p>
<blockquote><p><span style="color:#FF0000">[The SignedCode object is available for use in the operating systems listed in the Requirements section. Instead, use Platform Invocation Services (PInvoke) to call the Win32 API SignerSignEx, SignerTimeStampEx, and WinVerifyTrust functions to sign content with an Authenticode digital signature. For information about PInvoke, see Platform Invoke Tutorial. The .NET and CryptoAPI via P/Invoke: Part 1 and .NET and CryptoAPI via P/Invoke: Part 2 subsections of Extending .NET Cryptography with CAPICOM and P/Invoke may also be helpful.]</span></p></blockquote>
<p>Note that this alarming paragraph seems to begin by simply telling you that this API is supported on the operating systems listed later.  It does <b>not</b> state that the API will not be available on later OSes, but <i>why</i> place this here otherwise?  The next sentence, beginning with, &#8220;Instead, &#8230;&#8221; seems to be contrasting with something, yet makes absolutely no sense in this context.</p>
<p>Finally, this paragraph instructs us to investigate <a href="http://msdn.microsoft.com/en-us/library/aa387734(VS.85).aspx">SignerSignEx</a>, and <a href="http://msdn.microsoft.com/en-us/library/cc300159(VS.85).aspx">SignerTimeStampEx</a>, which are supplied by the mssign32.dll, have no header file, and absolutely no example code.  This is what I find most irksome, they document each and every function and structure, yet each page says, &#8220;there is no header file, so copy and paste the declaration given here.&#8221;  Well, why not simply provide an mssign.h file on blogs.msdn, or similar?  And why, oh why, is there not a single line of sample code?</p>
<h3>Follow-up</h3>
<p>I have provided a basic header file for mssign32.dll, <a href="http://www.curlybrace.com/words/?p=271">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2008/10/15/the-demise-of-capicom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GnuPG Plugin for vim Under Cygwin</title>
		<link>http://www.curlybrace.com/words/2008/10/04/gnupg-plugin-for-vim-under-cygwin/</link>
		<comments>http://www.curlybrace.com/words/2008/10/04/gnupg-plugin-for-vim-under-cygwin/#comments</comments>
		<pubDate>Sat, 04 Oct 2008 18:50:57 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=137</guid>
		<description><![CDATA[GnuPG, GNU Privacy Guard, is a free system for encrypting files, emails, etc. The GnuPG plugin for vim provides automatic encryption and decryption of files within vim. If you attempt to edit a GnuPG-encrypted file with vim, it will prompt &#8230; <a href="http://www.curlybrace.com/words/2008/10/04/gnupg-plugin-for-vim-under-cygwin/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.gnupg.org/">GnuPG, GNU Privacy Guard</a>, is a free system for encrypting files, emails, etc.  The <a href="http://vim.sourceforge.net/scripts/script.php?script_id=661">GnuPG plugin for vim</a> provides automatic encryption and decryption of files within vim.  If you attempt to edit a GnuPG-encrypted file with vim, it will prompt you for the password, and re-encrypt the file when you&#8217;re done editing.</p>
<p>Download the gnupg plugin for vim from <a href="http://vim.sourceforge.net/scripts/script.php?script_id=661">here</a> and copy it into your user directory directory under <tt>.vim/plugin</tt>.  From the Cygwin bash prompt:</p>
<blockquote><pre class="bash">mkdir ~/.vim/plugin
copy gnupg.vim ~/.vim/plugin</pre>
</blockquote>
<p>Run <tt>vim</tt>, then use the <tt>:scriptnames</tt> command and verify that <tt>gnupg.vim</tt> appears in the list of sourced scripts:</p>
<blockquote><pre class="bash">  1: /cygdrive/c/Users/<i>username</i>/.vim/plugin/gnupg.vim</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2008/10/04/gnupg-plugin-for-vim-under-cygwin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CoCreateInstance Fails With &#8220;Class Not Registered&#8221;</title>
		<link>http://www.curlybrace.com/words/2008/06/17/cocreateinstance-clsctx_inproc_server-failing-with-class-not-registered/</link>
		<comments>http://www.curlybrace.com/words/2008/06/17/cocreateinstance-clsctx_inproc_server-failing-with-class-not-registered/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 00:47:28 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[COM]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=131</guid>
		<description><![CDATA[Recently, I had a problem unique to my test machine. Attempting to call CoCreateInstance on a COM class provided by one of our DLLs resulted in HRESULT 0&#215;80040154, which corresponds to &#8220;Class not registered&#8221;. This was a mystery since regsvr32 &#8230; <a href="http://www.curlybrace.com/words/2008/06/17/cocreateinstance-clsctx_inproc_server-failing-with-class-not-registered/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently, I had a problem unique to my test machine.  Attempting to call CoCreateInstance on a COM class provided by one of our DLLs resulted in HRESULT 0&#215;80040154, which corresponds to &#8220;Class not registered&#8221;.</p>
<p>This was a mystery since regsvr32 appeared to properly register our DLL, and all the obvious registry keys were intact!</p>
<p>After a bit of web searching, I experimented with using CLSCTX_ALL instead of CLSCTX_INPROC_SERVER.  Now, the call succeeded!  But why, since this is a DLL and, therefore, should be considered an in-process COM server?</p>
<p><a href="http://msdn.microsoft.com/en-us/library/ms686615(VS.85).aspx">MSDN documentation</a> states that CLSCTX_ALL is defined as the combination of CLSCTX_INPROC_SERVER, CLSCTX_INPROC_HANDLER, and CLSCTX_LOCAL_SERVER.  I began substituting each one in turn and found that the key was CLSCTX_LOCAL_SERVER.</p>
<p>Stepping through the code in the debugger revealed that the instant the CoCreateInstance call was made, a new instance of dllhost.exe appeared in the process list.  This explained why CLSCTX_INPROC_SERVER would fail, since strictly speaking, the DLL was being hosted in dllhost&#8217;s process space.</p>
<p>Ultimately, the problem turned out to be an artifact from an old COM+ experiment.  There was a COM+ entry corresponding to our COM server in the Component Services panel (Control Panel | Administrative Tools | Component Services, under Component Services | Computers | My Computer | COM+ Applications).  The COM+ entry dictated that the COM server be hosted by proxy by dllhost.exe.  Deleting this COM+ entry and re-running regsvr32 fixed the problem.</p>
<blockquote><p><img src='http://www.curlybrace.com/words/wp-content/uploads/2008/06/componentservices.PNG' alt='Component Services panel in Administrative Tools' /></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2008/06/17/cocreateinstance-clsctx_inproc_server-failing-with-class-not-registered/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SetThreadLocale and SetThreadUILanguage for Localization on Windows XP and Vista</title>
		<link>http://www.curlybrace.com/words/2008/06/10/setthreadlocale-and-setthreaduilanguage-for-localization-on-windows-xp-and-vista/</link>
		<comments>http://www.curlybrace.com/words/2008/06/10/setthreadlocale-and-setthreaduilanguage-for-localization-on-windows-xp-and-vista/#comments</comments>
		<pubDate>Wed, 11 Jun 2008 00:20:48 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=126</guid>
		<description><![CDATA[Simple Localization In classic Windows programming, the quickest way to handle localized resources is to put all languages into the same resource file, then use SetThreadLocale to tell Windows that it should return resources tagged with the specified language identifier. &#8230; <a href="http://www.curlybrace.com/words/2008/06/10/setthreadlocale-and-setthreaduilanguage-for-localization-on-windows-xp-and-vista/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p></p>
<h3>Simple Localization</h3>
<p>In classic Windows programming, the quickest way to handle localized resources is to put all languages into the same resource file, then use <a href="http://msdn.microsoft.com/en-us/library/ms776285.aspx"><tt>SetThreadLocale</tt></a> to tell Windows that it should return resources tagged with the specified <a href="http://msdn.microsoft.com/en-us/library/ms776324(VS.85).aspx">language identifier</a>.  Subsequently, any attempt to load a resource by that thread will cause Windows to prefer resources corresponding to the specified language code.</p>
<h3>Vista Complications</h3>
<p>As of Windows Vista, calling <a href="http://msdn.microsoft.com/en-us/library/ms776285.aspx"><tt>SetThreadLocale</tt></a> will <i>appear</i> to work, but will have no effect.  Your application will continue to use load resources using whatever language identifier is set as the user&#8217;s default.</p>
<p>Under Windows Vista, <a href="http://msdn.microsoft.com/en-us/library/ms776236(VS.85).aspx"><tt>SetThreadUILanguage</tt></a> must be called instead of SetThreadLocale.  This function is in Kernel32.dll.  It appears in Vista, Windows 2008, and some versions of Windows XP.  Under Windows XP, this function will <b>not</b> have the desired effect, and I have no idea what it does under Windows 2008.</p>
<p>Since the function isn&#8217;t available on all systems, you will probably want to use <a href="http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx">GetProcAddress</a> to locate the function, and call it using a function pointer.  However, since the function appears on Windows XP, but does not behave in the desired way, it&#8217;s important to only call it on Windows Vista.</p>
<h3>Resource Storage</h3>
<p>To use the <tt>SetThreadLocale</tt> or <tt>SetThreadUILanguage</tt> methods, the resource file must first be populated with all required languages.  Each translated resource file should be appended to the <tt>.rc</tt> file, each one following an appropriate <a href="http://msdn.microsoft.com/en-us/library/aa381019(VS.85).aspx"><tt>LANGUAGE</tt> statement</a> and corresponding <a href="http://msdn.microsoft.com/en-us/library/ms776324(VS.85).aspx">language identifier</a>.  (note that you could use separate <tt>.rc</tt> files and include them, in which case <a href="http://support.microsoft.com/kb/264156">there are gotchas</a>).</p>
<h3>Is it Vista?</h3>
<p>This function should reliably indicate whether the current OS is Windows Vista.  I use <a href="http://www.finalgear.com/news/2008/06/10/commercial-for-the-new-season-of-top-gear/"><tt>GetVersionEx</tt></a>.   Note that, even though we&#8217;re using an <a href="http://msdn.microsoft.com/en-us/library/ms724833(VS.85).aspx"><tt>OSVERSIONINFOEX</tt></a> structure, we have to cast its pointer so that it appears as a <a href="http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx"><tt>OSVERSIONINFO</tt></a> pointer.  No guarantee of future compatibility is implied:</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">bool IsOSVerWindowsVista()
{
    OSVERSIONINFOEX osver;
    ZeroMemory(&amp;osver, sizeof(osver);
    osver.dwOSVersionInfoSize = sizeof(osver);

    if (!GetVersionEx((OSVERSIONINFO *)&amp;osver))
        return false;

    // dwMajorVersion 6 and dwMinorVersion 0 means Vista or 2k8:
    if ( (osver.dwMajorVersion != 6) || (osver.dwMinorVersion != 0) )
        return false;

    // wProductType of NT_WORKSTATION means it's Vista:
    if (osver.wProductType != VER_NT_WORKSTATION)
        return false;

    return true;
}</pre>
</blockquote>
<h3>Calling SetThreadUILanguage Dynamically</h3>
<p>The trickiest part of using <tt>GetProcAddress</tt> to dynamically call a function at run-time is getting the function pointer declaration correct.  This type definition should work for <tt>SetThreadUILanguage</tt>:</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">typedef LANGID (WINAPI *FP_SetThreadUILanguage)(LANGID LangId);</pre>
</blockquote>
<p>Now, you have a function pointer type called <tt>FP_SetThreadUILanguage</tt> which can be used like any other type.</p>
<p>This function pointer can be used to dynamically call any function within a loaded module (DLL).  <tt>SetThreadUILanguage</tt> lives inside Kernel32.dll.  Since Kernel32.dll is required by all Win32 processes, we can simply use <tt>GetModuleHandle</tt> to find it, we don&#8217;t have to use <tt>LoadLibrary</tt>.  A pointer to <tt>SetThreadUILanguage</tt> can therefore be retrieved like this (unnecessarily verbose code):</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">HMODULE hKernel32 = GetModuleHandle(_T(&quot;Kernel32.dll&quot;));
FARPROC pFn = GetProcAddress(hKernel32, &quot;SetThreadUILanguage&quot;);

FP_SetThreadUILanguage pSetThreadUILanguage = (FP_SetThreadUILanguage)pFn</pre>
</blockquote>
<p>The function can now be called through the function pointer variable:</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">LANGID langid = pSetThreadUILanguage(myLangId);</pre>
</blockquote>
<p><tt>SetThreadUILanguage</tt> returns the <tt>LANGID</tt> which has been set.  If the call was successful, it will return the same <tt>LANGID</tt> that was specified.</p>
<h3>Constructing a Language Identifier</h3>
<p>Use the <tt>MAKELANGID</tt> macro from <tt>Winnt.h</tt>, and supply <tt>LANG_Xxx</tt> constants from same.  For example, Simplified Chinese would require:</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">DWORD dwSimplifiedChinese =
   MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED );</pre>
</blockquote>
<h3>Non-Vista Platforms</h3>
<p>On non-Vista platforms, <tt>SetThreadLocale</tt> can be used.  Instead of a language identifier, it accepts a locale identifier.  To generate the locale identifier, simply pass your language identifier to the <tt>MAKELCID</tt> macro, and supply <tt>SORT_DEFAULT</tt> as the second parameter:</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">SetThreadLocale(MAKELCID(myLangId, SORT_DEFAULT));</pre>
</blockquote>
<p>This example unconditionally sets the thread locale to Simplified Chinese in a single line of code:</p>
<blockquote><pre class="brush: cpp; title: ; notranslate">SetThreadLocale(
   MAKELCID(
      MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
      SORT_DEFAULT));</pre>
</blockquote>
<p><tt>SetThreadLocale</tt> returns <tt>TRUE</tt> on success, <tt>FALSE</tt> on error.</p>
<h3>Reference</h3>
<ul>
<li /><a href="http://msdn.microsoft.com/en-us/library/ms776324(VS.85).aspx">Multiple-Language Resources</a> (MSDN)
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2008/06/10/setthreadlocale-and-setthreaduilanguage-for-localization-on-windows-xp-and-vista/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Underlining Characters in a ToolTip</title>
		<link>http://www.curlybrace.com/words/2008/06/05/placing-underlined-character-into-win32-tooltip/</link>
		<comments>http://www.curlybrace.com/words/2008/06/05/placing-underlined-character-into-win32-tooltip/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 01:02:51 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=122</guid>
		<description><![CDATA[My product, a toolbar for Outlook Express, uses tooltips to display keyboard shortcuts. For some localization work, I needed to display an underlined character within a tooltip. The only hint I could find was a reference to .Net tooltips. Apparently, &#8230; <a href="http://www.curlybrace.com/words/2008/06/05/placing-underlined-character-into-win32-tooltip/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My product, a toolbar for Outlook Express, uses <a href="http://msdn.microsoft.com/en-us/library/bb760246(VS.85).aspx">tooltips</a> to display keyboard shortcuts.  For some localization work, I needed to display an underlined character within a <a href="http://msdn.microsoft.com/en-us/library/bb760246(VS.85).aspx">tooltip</a>.</p>
<p>The only hint I could find was <a href="http://groups.google.com/group/microsoft.public.vb.general.discussion/msg/0f48773dfef470c6?hl=en">a reference to .Net tooltips</a>.</p>
<p>Apparently, in both .Net and Win32 tooltips, a single ampersand will be stripped, a double ampersand will cause the next character to be underlined, and three ampersands will display a single ampersand.</p>
<blockquote>
<table>
<tr>
<th>Input</th>
<td>&nbsp;&nbsp;&nbsp;</td>
<th>Displayed</th>
</tr>
<tr>
<td><tt>&amp;B</tt></td>
<td></td>
<td>B</td>
</tr>
<tr>
<td><tt>&amp;&amp;</tt>B</td>
<td></td>
<td><u>B</u></td>
</tr>
<tr>
<td><tt>&amp;&amp;&amp;B</tt></td>
<td></td>
<td>&amp;B</td>
</tr>
</table>
</blockquote>
<p>Note that this will be affected if the <a href="http://msdn.microsoft.com/en-us/library/bb760248.aspx"><tt>TTS_NOPREFIX</tt></a> flag is set, which prevents ampersands from being stripped.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2008/06/05/placing-underlined-character-into-win32-tooltip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Vista UAC Goofiness</title>
		<link>http://www.curlybrace.com/words/2008/03/18/windows-vista-uac-goofiness/</link>
		<comments>http://www.curlybrace.com/words/2008/03/18/windows-vista-uac-goofiness/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 02:15:43 +0000</pubDate>
		<dc:creator>Jeff Fitzsimons</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[CreateProcess]]></category>
		<category><![CDATA[Setup]]></category>
		<category><![CDATA[ShellExecuteEx]]></category>
		<category><![CDATA[shield icon]]></category>
		<category><![CDATA[UAC]]></category>
		<category><![CDATA[Update]]></category>
		<category><![CDATA[User Access Control]]></category>
		<category><![CDATA[Windows Vista]]></category>

		<guid isPermaLink="false">http://www.curlybrace.com/words/?p=110</guid>
		<description><![CDATA[Windows Vista UAC is not always a predictable beast. Today I found out that if an executable doesn&#8217;t set level="asInvoker" in its manifest, UAC confirmation will kick in if any of the following substrings appear in the filename: setup install &#8230; <a href="http://www.curlybrace.com/words/2008/03/18/windows-vista-uac-goofiness/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Windows Vista UAC is not always a predictable beast.</p>
<p>Today I found out that if an executable doesn&#8217;t set <tt>level="asInvoker"</tt> in its manifest, UAC confirmation will kick in if any of the following substrings appear in the filename:</p>
<ul>
<li>setup</li>
<li>install</li>
<li>update</li>
</ul>
<p>A digital signature does not affect this behavior.</p>
<p>Besides adding &#8220;asInvoker&#8221; to the manifest, another workaround is to rename the executable to remove the trigger word.  For example, renaming <tt>MyProductUpdater.exe</tt> to <tt>MyProductRenewal.exe</tt> will (for now) bypass the UAC logic.</p>
<p>Note that this in no way bypasses the protections of UAC.  Functions which perform some task which requires UAC-approval will simply fail.  This will only be useful if you have an update tool which <b>only</b> updates user-owned resources, since that doesn&#8217;t require UAC-approval.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curlybrace.com/words/2008/03/18/windows-vista-uac-goofiness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

