<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>.NET Corner</title><link>http://www.dotnetjunkies.com/WebLog/debasish/default.aspx</link><description>.NET, Jeans and ...
(From CAS to "Why by default my progressbar in VS.NET generated installation is not being themed?")</description><dc:language>en-US</dc:language><generator>CommunityServer 1.0 (Build: 1.0.1.50214)</generator><item><title>.NET Code Protectors, Obfuscators And more</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2007/01/23/189061.aspx</link><pubDate>Tue, 23 Jan 2007 14:10:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:189061</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/189061.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=189061</wfw:commentRss><description>&lt;P&gt;Honestly, I'm a frequent user of infamous .NET decompiler - Reflector (&lt;A href="http://www.aisto.com/roeder/dotnet/"&gt;http://www.aisto.com/roeder/dotnet/&lt;/A&gt;). Hacking vanilla .NET assemblies&amp;nbsp;are insanely easy with this tool. Now that I'm writing my own .NET based product (which will be launched soon and I'm pretty much sure that it will be immensely popular in Indian music lovers. I will write a fresh post while launching the tool) my attention is turned into the protection of my own assemblies. After researching a bit I came to conclusion that .NET code protection strategies broadly can be divided into these categories.&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;A. Traditional obfuscators - symbol renaming, control flow obfuscation are generally falls into this category. Visual Studio comes with a community edition of .NET Obfuscator or DotFuscator. But it is not impressive. 9rays, RemoteSoft, Xenocode are some known names in the word of .NET obfuscators.&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;B. Secure IL Stream - Basic strategy is to impose a secure envelope around the .NET assembly to be protected. Another component (which needs to be deployed to the client spaces) attaches itself to the execution engine (EE) of CLR and decodes the secured IL just before handing over to the JIT compiler. This decoding is extremely specific and on-demand based. Effectively, at a time only a few functions' IL remains decoded into the memory. Details can be found at &lt;A href="http://www.secureteam.net/solutionsTechnology.asp"&gt;http://www.secureteam.net/solutionsTechnology.asp&lt;/A&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;C. This is perhaps the most rigorous endeavor to protect .NET assemblies till date. Basic idea is to get some user information (username or user ID or user's Hardware ID - HID or license file) and use this to encrypt/compress the assembly which needs to be secured (often prior to this, there&amp;nbsp;is a Assembly Packing stage where all non-system referenced assemblies of the main executable&amp;nbsp;are packed into a master assembly with suitable entrypoint). Then&amp;nbsp;the binary image is added to a Win32 stub as a Win32 resource. This stub usually has a specific entrypoint which upon loading&amp;nbsp;extracts the special resource (binary image added earlier on the fly) , asks for the user information (username or user ID or user's Hardware ID - HID or license file) , uses this to decrypt/decompress the extracted resource, hosts the CLR (there could be a policy about the loading of the CLR) , create a secure appdomain , loads the decrypted assembly image into the appdomain and starts executing its entrypoint (which is normally the Main method). Symmetric encryption technique is enforced here. The purpose of this entire process is to build up a native-code wall around the .NET assembly to be protected. Naturally Reflector fails badly. To get an example of this technique visit - &lt;A href="http://www.eziriz.com/"&gt;http://www.eziriz.com/&lt;/A&gt;. Now I was pretty impressed by this tool called .NET Reactor. But like any other shareware it is not free and to be true&amp;nbsp;- expensive. I decided it would be a good idea to jump into my new project&amp;nbsp; - .NETCodeProtector - modeled around this strategy. I'm on the way to finish it and I promise I will publish it into the SourceForge along with a relevant post here at DNJ. Anyway I like to share the solution structure of the project -&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/NETCodeProtector/VS_Solution_Explorer_1.gif"&gt;&lt;/P&gt;
&lt;P&gt;1. ClrHostStub : It is the Win32 Stub with CLR hosting code embedded into it.&lt;BR&gt;2. AssemblyPacker: Optionally packs multiple non-system referenced assemblies into a master assembly with suitable entrypoint.&lt;BR&gt;3. PackToStub: This component is used to add the assembly (or packed assembly) into the Win32 stub as a Win32 resource.&lt;BR&gt;&lt;BR&gt;Apart from discussing various .NET code protection strategies, this post also shows how I used to pick up my next project. Well, see you soon. Happy programming.&lt;BR&gt;&lt;BR&gt;Thanks&lt;BR&gt;Debasish Bose&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=189061" width="1" height="1"&gt;</description></item><item><title>WindowsDefender Penetrated</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2007/01/14/187052.aspx</link><pubDate>Sun, 14 Jan 2007 12:37:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:187052</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/187052.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=187052</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Disclaimer: Opinion mentioned in this post is of my personal one, not Microsoft's. Patching to bypass WGA is illegal, so please proceed with your own responsibility. Please don't install pirated copies of Windows. Always buy genuine one.&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Lately, my laptop became infected with so&amp;nbsp; many spywares. It forced me to recall my old friend Microsoft AntiSpyware which is rewritten in Managed C++ and transformed into WindowsDefender. Although I've a MSDN subscription, I was unable to find the download link for it. Normally it is protected under WGA or Windows Genuine Advantage. I don't why the WGA ActiveX(LegitCheckControl.dll) is always redirecting to the 'Unauthorized' page. After I downloaded MGAdiag.exe from &lt;A href="http://go.microsoft.com/fwlink/?linkid=52012"&gt;http://go.microsoft.com/fwlink/?linkid=52012&lt;/A&gt;&amp;nbsp;, the reason became crystal-clear. VLK blocked! Hmmm...&amp;nbsp;Anyway I got the direct link from&amp;nbsp;&lt;A href="http://download.microsoft.com/download/e/d/0/ed099d5e-dc60-4740-8747-1c72f053b800/WindowsDefender.msi"&gt;http://download.microsoft.com/download/e/d/0/ed099d5e-dc60-4740-8747-1c72f053b800/WindowsDefender.msi&lt;/A&gt;. But because of double WGA check, the installation ends prematurely. Now first idea would be to patch LegitCheckControl.dll itself. But it didn't work either. The reason is WGA check library has been embedded into the MSI as a binary module. Following snapshot is found in table 'Binary' at ORCA's dis-assembly &lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/WindowsDefender/Legit_Lib.gif"&gt;&lt;/P&gt;
&lt;P&gt;You can find ORCA at Platform SDK. Now I was inspecting the 'ControlEvent' table and it's column header attracts my attention -&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/WindowsDefender/Hack_Header.gif"&gt;&lt;/P&gt;
&lt;P&gt;The table simply says when you are at 'Dialog', if you press 'Control', a new 'Event' will happen with argument - 'Argument' if&amp;nbsp; 'Condition' is satisfied. Based on this lets judge the following picture -&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/WindowsDefender/Hack_2.gif"&gt;&lt;/P&gt;
&lt;P&gt;The highlighted line says, if ((LegitCheckResult &amp;lt;&amp;gt; "0") &amp;amp;&amp;amp; (LegitCheckResult &amp;lt;&amp;gt; "6")), then if you press Next button, SetupCompleteWGAError dialog will appear which is nothing but the dialog which says that 'You have a counterfeit version of Windows'. The row just above it, have a condition which is just complement of the current one and proceeds towards LicenseAgreement dialog. So to patch it, simply change the 'SetupCompleteWGAError' to 'LicenseAgreement'. This will install WindowsDefender on the system. But as you know, WindowsDefender works in conjunction with Windows Automatic Update (wuaucpl.cpl) which is important to update the spyware signature database. Happy hacking.&lt;/P&gt;
&lt;P&gt;Thanks&lt;BR&gt;Debasish Bose&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=187052" width="1" height="1"&gt;</description></item><item><title>Recreate gacutil - Part 2</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/12/03/164789.aspx</link><pubDate>Sun, 03 Dec 2006 06:16:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:164789</guid><dc:creator>debasish</dc:creator><slash:comments>1</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/164789.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=164789</wfw:commentRss><description>&lt;P&gt;Get the short introductory part 1 &lt;a href="http://dotnetjunkies.com/WebLog/debasish/archive/2006/09/12/146899.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;After the initial inspection was finished, I was pretty much surprised by looking at the existing assembly unGACing code. The code expects full path of the concerned assembly, create a temporary appdomain, inject following class(Util) into the appdomain and get the full qualified name(strong name) for the assembly, then uninstall with the help of IRegister interface.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;internal class&amp;nbsp;Util : MarshalByRefObject&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal&amp;nbsp;string FullAssemblyName(string name)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Assembly.LoadFrom(name).FullName;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT face="Times New Roman"&gt;Crap to say at least. The first thing I did was to learn something about GACed assembly&amp;nbsp;enumeration. If any COM enumeration interface exist, wrap it up in a .NET enumerator or create a custom GAC assembly enumerator from scratch. The second option needs explicit knowledge about GAC folder hierarchy under the hood of %WINDIR%\assembly folder. This would expose my implementation to break often as GAC changes internally. Not to mention 64 bit GAC handling, because in a typical 64 bit box different GACs can exist - GAC_32(32 bit CLR), GAC_64(64 bit CLR), GAC_MSIL(Any CPU) etc. So the first option wins. Fortunately enough there is a relevant COM enumeration interface.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;[SuppressUnmanagedCodeSecurityAttribute()]&lt;BR&gt;&amp;nbsp;[ComImport, Guid("21B8916C-F28E-11D2-A473-00C04F8EF448"), InterfaceType(1)]&lt;BR&gt;&amp;nbsp;internal interface IAssemblyEnum&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int GetNextAssembly([Out] out IApplicationContext ppAppCtx, [Out] out IAssemblyName ppName, uint dwFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int Reset();&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int Clone([Out] out IAssemblyEnum ppEnum);&lt;BR&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;This demands the declarations of the following interfaces - IApplicationContext and IAssemblyName&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;[SuppressUnmanagedCodeSecurityAttribute()]&lt;BR&gt;&amp;nbsp;[ComImport, Guid("7C23FF90-33AF-11D3-95DA-00A024A85B51"), InterfaceType(1)]&lt;BR&gt;&amp;nbsp;internal interface IApplicationContext&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;void SetContextNameObject(IAssemblyName pName);&lt;BR&gt;&amp;nbsp;&amp;nbsp;void GetContextNameObject([Out] out IAssemblyName ppName);&lt;BR&gt;&amp;nbsp;&amp;nbsp;void Set([MarshalAs(UnmanagedType.LPWStr)] string szName, int pvValue, uint cbValue, uint dwFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;void Get([MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] out int pvValue, ref uint pcbValue, uint dwFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;void GetDynamicDirectory([Out] out int wzDynamicDir, ref uint pdwSize);&lt;BR&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;[SuppressUnmanagedCodeSecurityAttribute()]&lt;BR&gt;&amp;nbsp;[ComImport, Guid("CD193BC0-B4BC-11D2-9833-00C04FC31D2E"), InterfaceType(1)]&lt;BR&gt;&amp;nbsp;internal interface IAssemblyName&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int SetProperty(uint PropertyId, IntPtr pvProperty, uint cbProperty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int GetProperty(uint PropertyId, IntPtr pvProperty, ref uint pcbProperty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int Finalize();&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int GetDisplayName(IntPtr szDisplayName, ref uint pccDisplayName, uint dwDisplayFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int BindToObject(object refIID, object pAsmBindSink, IApplicationContext pApplicationContext, [MarshalAs(UnmanagedType.LPWStr)] string szCodeBase, long llFlags, int pvReserved, uint cbReserved, [Out] out int ppv);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int GetName(ref uint lpcwBuffer, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwzName);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int GetVersion([Out] out uint pdwVersionHi, [Out] out uint pdwVersionLow);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int IsEqual(IAssemblyName pName, uint dwCmpFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int Clone([Out] out IAssemblyName pName);&lt;BR&gt;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Times New Roman"&gt;Now the time for .NET wrapper on top of the COM enumeration interface&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;internal abstract class AssemblyCacheEnumerator : IEnumerator&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;protected AssemblyCacheEnumerator(string assemblyName,int cache)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Assembly name passed in may be partial, therefore enumerate matching assemblies&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//for uninstallation of each one.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IAssemblyName fusionName = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int hr = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;//Create the COM enumeration object&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fusion.CreateAssemblyEnum(out this.m_ae, null, fusionName, (uint)cache, 0);&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;bool IEnumerator.MoveNext()&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;IApplicationContext context1 = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return (0 == this.m_ae.GetNextAssembly(out context1, out this.m_anCurrent, 0));&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;void IEnumerator.Reset()&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.m_ae.Reset();&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;// Properties&lt;BR&gt;&amp;nbsp;&amp;nbsp;object IEnumerator.Current&lt;BR&gt;&amp;nbsp;&amp;nbsp;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;get&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return this.m_anCurrent;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;// Fields&lt;BR&gt;&amp;nbsp;&amp;nbsp;private IAssemblyEnum m_ae;&lt;BR&gt;&amp;nbsp;&amp;nbsp;private IAssemblyName m_anCurrent;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Times New Roman"&gt;Now this is a generic assembly cache enumerator not a GAC enumerator. Assembly cache has three subzones - GAC, NGenCache and DownloadCache. &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;[Flags]&lt;BR&gt;&amp;nbsp;internal enum AssemblyCacheFlags&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;NGenCache&amp;nbsp;&amp;nbsp;&amp;nbsp;= 0x1,&lt;BR&gt;&amp;nbsp;&amp;nbsp;GAC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;= 0x2,&lt;BR&gt;&amp;nbsp;&amp;nbsp;DownloadCache&amp;nbsp;&amp;nbsp;= 0x4&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT face="Times New Roman"&gt;For GAC subzone following subclass is defined&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;internal class GacEnumerator : AssemblyCacheEnumerator&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;public GacEnumerator(string assemblyName) : base(assemblyName,(int)AssemblyCacheFlags.GAC)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;It's time for the core Fusion interface -&amp;nbsp; IRegister&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp; [SuppressUnmanagedCodeSecurityAttribute()]&lt;BR&gt;&amp;nbsp; [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]&lt;BR&gt;&amp;nbsp; internal interface IRegister&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [PreserveSig()]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int UninstallAssembly(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, IntPtr pvReserved, out uint&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp; pulDisposition);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [PreserveSig()]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int QueryAssemblyInfo(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, IntPtr pAsmInfo);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [PreserveSig()]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int CreateAssemblyCacheItem(uint dwFlags, IntPtr pvReserved, out /*IRegisterItem*/IntPtr ppAsmItem, [MarshalAs(UnmanagedType.LPWStr)] String pszAssemblyName);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [PreserveSig()]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int CreateAssemblyScavenger(out object ppAsmScavenger);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [PreserveSig()] to be &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int InstallAssembly(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszManifestFilePath, IntPtr pvReserved);&lt;BR&gt;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;And here goes the core Fusion API&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp; [DllImport("Fusion.dll", CharSet=CharSet.Auto)]&lt;BR&gt;&amp;nbsp;&amp;nbsp;internal static extern int CreateAssemblyCache(out IRegister ppAsmCache, uint dwReserved);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The main unGAC function basically creates the assembly cache, create the enumerator, get the strong name for each IAssemblyName references and call UninstallAssembly function on IRegister interface. But there was a small problem. While "partial" assembly name was passed, it was not expanding to all its matches. There has to be something missing. MSDN docs were helpless. Then as a fallback I digged into SSCLI. I found following unmanaged(C++) code at &lt;A href="http://dotnet.di.unipi.it/Content/sscli/docs/doxygen/tools/gac/gac_8cpp-source.html"&gt;http://dotnet.di.unipi.it/Content/sscli/docs/doxygen/tools/gac/gac_8cpp-source.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;//Name passed in may be partial, therefore enumerate matching assemblies&lt;BR&gt;00357&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //and uninstall each one. Uninstall API should be called with full name ref.&lt;BR&gt;00358 &lt;BR&gt;00359&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Create AssemblyName for enum&lt;BR&gt;00360&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((hr = (*g_pfnCreateAssemblyNameObject)(&amp;amp;pEnumName, pszAssemblyName, CANOF_PARSE_DISPLAY_NAME, NULL)))&lt;BR&gt;00361&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;00362&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BSILENT_PRINTF0ARG("Failure removing assembly from cache: ");&lt;BR&gt;00363&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReportError(hr);&lt;BR&gt;00364&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (pCache) pCache-&amp;gt;Release();&lt;BR&gt;00365&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;BR&gt;00366&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;00367&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;00368 &lt;BR&gt;00369&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;00370&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // For zaps, null out the custom string&lt;BR&gt;00371&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (bzapCache)&lt;BR&gt;00372&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;00373&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD dwSize = 0;&lt;BR&gt;00374&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Check if Custom string has been set&lt;BR&gt;00375&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pEnumName-&amp;gt;GetProperty(ASM_NAME_CUSTOM, NULL, &amp;amp;dwSize);&lt;BR&gt;00376 &lt;BR&gt;00377&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!dwSize)&lt;BR&gt;00378&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;00379&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Custom String not set - set to NULL to unset property so lookup is partial&lt;BR&gt;00380&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pEnumName-&amp;gt;SetProperty(ASM_NAME_CUSTOM, NULL, 0);&lt;BR&gt;00381&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;00382&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;00383 &lt;BR&gt;00384&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = (*g_pfnCreateAssemblyEnum)(&amp;amp;pEnum, &lt;BR&gt;00385&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NULL, &lt;BR&gt;00386&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pEnumName,&lt;BR&gt;00387&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bzapCache ? ASM_CACHE_ZAP : ASM_CACHE_GAC, &lt;BR&gt;00388&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NULL);&lt;/FONT&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Note the difference with the AssemblyCacheEnumerator constructor - An extra call to CreateAssemblyNameObject Fusion API which translates to following C# code&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;IAssemblyName fusionName = null;&lt;BR&gt;&amp;nbsp;int hr = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;if (assemblyName != null)&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Create AssemblyName for enumeration&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;EM&gt;hr = Fusion.CreateAssemblyNameObject(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out fusionName,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assemblyName,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0);&lt;BR&gt;&lt;/EM&gt;&lt;/STRONG&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;//Create the COM enumeration object&lt;BR&gt;&amp;nbsp;Fusion.CreateAssemblyEnum(out this.m_ae, null, fusionName, (uint)cache, 0);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The main uninstall function is given below&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;static internal int&amp;nbsp;UnRegFile(string assembly)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IRegister ac = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint n;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int hr = CreateAssemblyCache(out ac, 0);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (hr != 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return hr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IAssemblyName name = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator enumerator = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Create the GAC enumerator&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enumerator = new GacEnumerator(assembly);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string sDisplayName = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (enumerator.MoveNext())&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;//Get the assemblyname from the set of GACed assemblies that matched&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //with the given partial name.If full name is provided this set will&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //contains exactly one element&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name = (IAssemblyName) enumerator.Current;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Get the displayname of the assembly&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sDisplayName = Fusion.GetDisplayName(name,AssemblyNameDisplayFlags.ALL);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;EM&gt;#if VS8&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Here we will count only&amp;nbsp;.NET 2.0&amp;nbsp;assemblies(which has the processorArchitecture &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;EM&gt;attribute as part of&amp;nbsp;assembly strongname.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (sDisplayName.Contains(processorArchitecturex86) ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sDisplayName.Contains(processorArchitecturemsil))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;#endif&lt;BR&gt;&lt;/EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//The following API always expects a full name instead of a partial name&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = ac.UninstallAssembly(0, sDisplayName.ToString(), (IntPtr)0, out n);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (hr != 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;BR&gt;&lt;EM&gt;#if VS8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;#endif&lt;/EM&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Release COM object&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Marshal.ReleaseComObject(name);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return hr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;}&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Times New Roman"&gt;All the DllImport declarations for Fusion APIs are pushed into an internal class called Fusion which also houses the implementation of the GetDisplayName function&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;internal class Fusion&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;[DllImport("Fusion.dll", CharSet=CharSet.Auto)]&lt;BR&gt;&amp;nbsp;&amp;nbsp;public static extern int CreateAssemblyEnum(out IAssemblyEnum ppEnum, IApplicationContext pAppCtx, IAssemblyName pName, uint dwFlags, int pvReserved);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;[DllImportAttribute("Fusion.dll", CharSet = CharSet.Unicode)]&lt;BR&gt;&amp;nbsp;&amp;nbsp;public static extern int CreateAssemblyNameObject(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out IAssemblyName ppEnum,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string szAssemblyName,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // A string representation of the assembly name or of a full assembly reference that&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //is&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;determined by dwFlags. The string representation can be null.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateAssemblyNameObjectFlags dwFlags,&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int pvReserved);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Must be null. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;internal static string GetDisplayName(IAssemblyName aName, AssemblyNameDisplayFlags displayFlags)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;uint uiLen = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;string sDisplayName = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;aName.GetDisplayName(IntPtr.Zero, ref uiLen, (uint)displayFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (uiLen &amp;gt; 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IntPtr ptr1 = IntPtr.Zero;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;byte[] buffer1 = new byte[(uiLen + 1) * 2];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;unsafe&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fixed (byte* numRef1 = buffer1)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ptr1 = new IntPtr((void*) numRef1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aName.GetDisplayName(ptr1, ref uiLen, (uint)displayFlags);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sDisplayName = Marshal.PtrToStringUni(ptr1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return sDisplayName;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Congrats! You've successfully recreated the gacutil utility.&lt;/P&gt;
&lt;P&gt;Re: Although this utility gives you somewhat similar functionality of gacutil, in a typical production deployment MSI should be used. Aaron Stebner has pointed that out here - &lt;BR&gt;&lt;A href="http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx"&gt;http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=164789" width="1" height="1"&gt;</description></item><item><title>Enumerating Sound Recording Devices</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/11/25/160495.aspx</link><pubDate>Sat, 25 Nov 2006 08:54:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:160495</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/160495.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=160495</wfw:commentRss><description>&lt;P&gt;In one of my projects I need to enumerate through all the sound recording devices installed in my system. Now to do so logic is simple.&lt;/P&gt;
&lt;P&gt;int count := Get the count of sound in devices;&lt;BR&gt;for each i in [0, count - 1]&lt;BR&gt;&amp;nbsp; get the device capabilities(i);&lt;BR&gt;&amp;nbsp; print the name(i);&lt;BR&gt;end for&lt;/P&gt;
&lt;P&gt;Retrieving the total count of sound recording devices was the simpler part. Following P/Invoke declaration was enough&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;[&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;DllImport&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;("winmm.dll")]&lt;BR&gt;&lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;static&lt;/FONT&gt; &lt;FONT&gt;extern&lt;/FONT&gt; &lt;FONT&gt;int&lt;/FONT&gt; waveInGetNumDevs();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT&gt;The tough part was to get the device capabilities. The relevant API was&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT&gt;&lt;PRE&gt;&lt;FONT&gt;&lt;B&gt;MMRESULT waveInGetDevCaps(
  UINT_PTR&lt;/B&gt;&lt;I&gt;     uDeviceID&lt;/I&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;B&gt;, 
  LPWAVEINCAPS&lt;/B&gt;&lt;I&gt; pwic&lt;/I&gt;&lt;/FONT&gt;&lt;B&gt;&lt;FONT&gt;,      
  UINT&lt;/FONT&gt;&lt;/B&gt;&lt;FONT&gt;&lt;I&gt;         cbwic      
&lt;/I&gt;&lt;B&gt;);&lt;/B&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Times New Roman"&gt;Although this &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_waveincaps_str.asp"&gt;link &lt;/A&gt;describes the data structure of LPWAVEINCAPS fairly well, the C# declaration was really hard to guess. After a lot of trial &amp;amp; error I finally came accross following signature&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;[&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;StructLayout&lt;/FONT&gt;(&lt;FONT&gt;LayoutKind&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;.Sequential, Pack = 4)]&lt;BR&gt;&lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;sruct&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;WaveInCaps&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;short&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; wMid;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;short&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; wPid;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; vDriverVersion;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;FONT&gt;MarshalAs&lt;/FONT&gt;(&lt;FONT&gt;UnmanagedType&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;.ByValArray, SizeConst = 32)]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;char&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;[] szPname;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;uint&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; dwFormats;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;short&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; wChannels;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;public&lt;/FONT&gt; &lt;FONT&gt;short&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; wReserved1;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT&gt;Keep an eye on the SizeConst=32(MAXPNAMELEN) attribute for the szPname's marsalling requirements. Rest of the story is simple&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; waveInDevicesCount = WaveLib.&lt;FONT&gt;WaveNative&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;.waveInGetNumDevs();&lt;BR&gt;&lt;FONT&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; (waveInDevicesCount &amp;gt; 0)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;for&lt;/FONT&gt; (&lt;FONT&gt;uint&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt; uDeviceID = 0; uDeviceID &amp;lt; waveInDevicesCount; uDeviceID++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveLib.&lt;FONT&gt;WaveInCaps&lt;/FONT&gt; waveInCaps = &lt;FONT&gt;new&lt;/FONT&gt; WaveLib.&lt;FONT&gt;WaveInCaps&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveLib.&lt;FONT&gt;WaveNative&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;.waveInGetDevCaps(uDeviceID,&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT&gt;out&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt; waveInCaps,&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT&gt;Marshal&lt;/FONT&gt;.SizeOf(&lt;FONT&gt;typeof&lt;/FONT&gt;(WaveLib.&lt;FONT&gt;WaveInCaps&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;)));&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cmbWaveInDevices.Items.Add(&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;new&lt;/FONT&gt; &lt;FONT&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;(waveInCaps.szPname));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT face="Times New Roman"&gt;End of quick'n'dirty post&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=160495" width="1" height="1"&gt;</description></item><item><title>Skype, Recording And .NET</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/10/25/151812.aspx</link><pubDate>Wed, 25 Oct 2006 22:26:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:151812</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/151812.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=151812</wfw:commentRss><description>&lt;P&gt;Lately, I've became an absolute fan of Skype. Some time back Yahoo Messanger was failing, saying..."Mixer Device Initialization Fails"...when 5 people or so were trying to have a voice conference call. We tried Skype. It worked instantly. By then I'm interested in what I do best - hacking. This time skype hacking. Some of the meetings I do over skype is really long. It would be nice to have an utility or plugin(++skype may be)&amp;nbsp;which will record the conference session and compress it to mp3/ogg/flac/wma files. By searching I came to know about following tools - &amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;KishKish SAM&lt;BR&gt;&lt;/STRONG&gt;KishKish SAM Skype plug-in records Skype conversations automatically once the incoming Skype call is answered by you. In an Outgoing Skype call you will need to wait until the call is answered by the other party. The voice recording can be stopped or resumed at any time during the call. [$15.95] &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;PowerGramo Recorder for Skype&lt;BR&gt;&lt;/STRONG&gt;PowerGramo Free version is a good option if the Skype conversation involves only two persons. The Skype call can be of any duration and will be recorded in the OGG or WAV format. The por version supports Multiple-call people conference recording. PowerGramo will work on older versions of Skype include Skype 1.1 [Free/$19.95]&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;HotRecorder for VoIP&lt;BR&gt;&lt;/STRONG&gt;Hot Recorder for VoIP is a popular Skype Call recording plugin for the PC. Not just Skype, you can use HotRecorder to record voice conversations from any IM client including Google Talk, AOL AIM, Net2Phone, Yahoo! Messenger or Firefly. The audio recordings can be saved to WAV, OGG or MP3 files. The HotRecorder Voicemail feauture will automatically answer Skype conversations for you. [$14.95] &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Pamela 2.0 Professional&lt;/STRONG&gt;&lt;BR&gt;While the basic version of Pamela is free and supports voice and video answering machine, the Pro version supports skype voice recording and can also record Skypecasts, Skype Video and Skype Chats. You can also make a local playable copy of your Skype Voicemail with Pamela Skype addon. Pamela also generates HTML template code for posting the recorded Skype audio and video calls as podcasts or blog entries. [$24.95]&lt;/P&gt;
&lt;P&gt;Its not doubt that those tools worth have a try and has some nice add-on feature-set. But none is free. So I decided to write my own Skype recorder in my yammi platform - .NET. The only drawback of this nice tool(category: Direct Sound Recorder without a dedicated device driver)&amp;nbsp;is that it's not a plugin. But I will try to convert it to a plugin. It also compresses the conversations into mp3 files.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/SkypeRecorder/SkyRec_Main.gif"&gt;&lt;/P&gt;
&lt;P&gt;Dowload &lt;A href="http://www.raagahacker.com/SkyRec.zip"&gt;SkyRec.zip&lt;/A&gt;. To correctly configure SkyRec, please select proper audio&amp;nbsp;recorder from the Mixer Device Selection. For my case it is SoundMax Digital Audio In. &lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/SkypeRecorder/Mixer_Selection.gif"&gt; &lt;/P&gt;
&lt;P&gt;After that, select the "Stereo Mix" section in the "Recording Control" dialog.&lt;/P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/SkypeRecorder/Recorder_Stereo_Mix.gif"&gt; 
&lt;P&gt;As I said I'll make this open source. Please give me feedback. Either post it it here or "&lt;a href="http://www.dotnetjunkies.com/WebLog/debasish/contact.aspx"&gt;Contact&lt;/A&gt;" section.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=151812" width="1" height="1"&gt;</description></item><item><title>Recreate gacutil</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/09/12/146899.aspx</link><pubDate>Tue, 12 Sep 2006 10:22:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:146899</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/146899.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=146899</wfw:commentRss><description>&lt;P&gt;It is nice to be back at Matrix. The story begins like this -&lt;/P&gt;
&lt;P&gt;Couple of days back we were facing some issues regarding GACing and UnGACing our primary assembly.&amp;nbsp;They(install team) were using some in-house tool called &lt;EM&gt;ourProduct&lt;/EM&gt;Reg.exe for unGACing the primary assembly , let's call it &lt;EM&gt;ourProduct&lt;/EM&gt;Assembly.dll. The commandline tool accepts full qualified filepath of the assembly to be uninstalled(installtion - GACing , seemed doesn't have any issue). Strange. Like below&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;ourProduct&lt;/EM&gt;Reg.exe /u c:\....\&lt;EM&gt;ourProduct&lt;/EM&gt;Assembly.dll&lt;/P&gt;
&lt;P&gt;But the intention was to uninstall all the assemblies given just the filename not the path name. Like&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;ourProduct&lt;/EM&gt;Reg.exe /u &lt;EM&gt;ourProduct&lt;/EM&gt;Assembly&lt;/P&gt;
&lt;P&gt;So this would uninstall all the assemblies named ourProductAssembly irrespective of cultures, version etc. Sounds pretty gacutil-like. So I was looking into it. Suddenly, after one hour, my assignment was revisited. This time the intention was to match more partial names including cultures or versions which were left earlier.Like&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;ourProduct&lt;/EM&gt;Reg.exe /u &lt;EM&gt;ourProduct&lt;/EM&gt;Assembly, Version=1.0.0.1&lt;/P&gt;
&lt;P&gt;This should uninstall(unGAC) all the assemblies with name ourProductAssembly and version 1.0.0.1 irrespective of the cultures. Come home to the world of &lt;EM&gt;gacutil&lt;/EM&gt;. I understood that client shouldn't have entire fatty .NET SDK installed for only this management tools like gacutil.exe. But I was not aware of the reason of not distributing gacutil.exe along with our product. Later I came to know that the SDK license does not allow to distribute the tools outside of the SDK, so&amp;nbsp;client will have to download the entire package. Definitely not an option.&lt;/P&gt;
&lt;P&gt;Find the part 2 &lt;a href="http://dotnetjunkies.com/WebLog/debasish/archive/2006/12/03/164789.aspx"&gt;here&lt;/A&gt;.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=146899" width="1" height="1"&gt;</description></item><item><title>IntPtr, 64 bit Porting and Fun</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/07/25/142644.aspx</link><pubDate>Tue, 25 Jul 2006 20:10:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:142644</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/142644.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=142644</wfw:commentRss><description>Guys I was busy in some HLD for past two weeks or so. I'm back now into my favourite blogspace&amp;nbsp; - DNJ.
Yesterday when our 64 bit porting team is working for the immediate 64 bit release of our product, they came to me for suggestion on a topic which I think worth discussing. While they are happily ported unmanaged C++ code, they were facing some difficulties with porting managed code(which should be easier! right?). In unmanaged C++ world they handled pointer disparity between the platforms...(&lt;a href="http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/07/25/142644.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=142644" width="1" height="1"&gt;</description></item><item><title>BearShare Tips</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/06/25/141144.aspx</link><pubDate>Sun, 25 Jun 2006 14:06:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:141144</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/141144.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=141144</wfw:commentRss><description>&lt;P&gt;Amongst all the P2P file sharing softwares&amp;nbsp;I have came accross so far BearShare is the most&amp;nbsp;efficient one. Unlike some other P2P sharing softwares like Morpheus(hosts of viruses) or LimeWare(terribly slow because of its Java Runtime dependency), BearShare is completely written in C++ and hence very lightweight and efficient. P2P softwares often has a "reputation" of being a trojan horse of various viruses, worms and spywares. This threat is very low for BearShare and if appropriate measure has been taken it could do hardly any harm to your system(for one such measure look at &lt;a href="http://dotnetjunkies.com/WebLog/debasish/archive/2006/04/24/137167.aspx"&gt;this&lt;/A&gt; earlier post of mine&amp;nbsp;regarding BearShare). In this post I will discuss some of the tips and tricks that I've learnt on the way of using BearShare.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tip - 1&lt;BR&gt;&lt;/STRONG&gt;Get the pro version of 5.0.2.3. The serach-space of this version is greater and this also take care of broken downloads. How to get the pro. version. Well you have to pay for it. &lt;A href="http://www.bearshare.com/"&gt;http://www.bearshare.com/&lt;/A&gt;. Another tricky way is to use the BearShare Lite(Free) version itself to search for downloading pro. version. It's analogous to crack SoftIce with SoftIce.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tip - 2&lt;BR&gt;&lt;/STRONG&gt;Be a little selfish. Disable uploading to increase the overall download speed and to&amp;nbsp;secure your system. Do this by going Option &amp;gt; Setup &amp;gt; Upload&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/BearShareTips/Setup_Upload.gif"&gt;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Tip - 3&lt;BR&gt;&lt;/STRONG&gt;Always make sure a file exactly is what it claims to be. Use Bitzi ticket for that. But before going on using that there exists an easier thumb rule for validation. For example if you are searching for "Half-Life 2: Episode 1" game and got a file of size 202,477 bytes you are definitely dealing with a virus or other misleading files unless it points to a valid .torrent file(which are often pretty small) which could be downloaded by any torrent client like BitTorrent. BearShare falls in a Gnutella category and doesn't support downloading through .torrent files.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tip - 4&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/BearShareTips/Bitzi_Validation.gif"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Anytime you suspect about a file, use Bitzi ticket. Bitzi is basically a lookup service which compares a unique SHA1 hashid(that the file presents) with its online database to show details of it. As part of the details you could found the feedback and rating of other users about it. To see the SHA1 hashid of a file unhide the metadata column from "Results" button in the search window(top-left)&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/BearShareTips/SHA1.gif"&gt;&lt;BR&gt;&lt;BR&gt;In one of the Bitzi lookup I found the following feedback/rating &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/BearShareTips/Bitzi_Rating.gif"&gt;&lt;BR&gt;&lt;BR&gt;Clearly One souldn't continue with this download.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Tip - 5&lt;BR&gt;&lt;/STRONG&gt;Instead of validating each search result(which could be vary tiresome) with Bitzi lookup, Use Bitzi search and find out the most recommended version of the file. Once you have found "most recommended" or "best version" file, go to the section in details page of the file which reads "APPLICATION IDENTIFIERS". &lt;BR&gt;&lt;BR&gt;&lt;IMG alt="" src="http://www.raagahacker.com/images/blog/BearShareTips/magnet_app_identifiers.gif"&gt;&lt;BR&gt;There you should have two category of URLs - Magnet and E2DK. We are interested with the first one.&lt;BR&gt;Now if you click on the link, ideally BearShare should capture that and start downloading. But world is far from being ideal. Instead it will show you following messagebox.&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="" src="http://www.raagahacker.com/images/blog/BearShareTips/Invalid_Magnet.gif"&gt;&lt;BR&gt;&lt;BR&gt;To fix this remove all attributes from the magnet URL except sha1(first) and dn(usually the last). So the modified magnet URL looks like&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;magnet:?xt=urn:sha1:ROOFD7DSBLGFZVYMNDMFACGUP7PBGZ74&amp;amp;dn=(PC GAME ITA) The Sims 2 CD1.iso &lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;Put that URL to browser's addressbar and BearShare's URL manager pops up&lt;/P&gt;&lt;IMG alt="" src="http://www.raagahacker.com/images/blog/BearShareTips/magnet_url_fix_download_box.gif"&gt;&lt;BR&gt;&lt;BR&gt;And you know what to do next. By the way my BrainBrush(BB) series on DataStructure will continue. Just I was busy for office-work for a while. Argentina won. Ole-Ole-Oleeeeeeeeeeeeee&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=141144" width="1" height="1"&gt;</description></item><item><title>Binary Tree, C# and Delegates - Part 2</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/31/139364.aspx</link><pubDate>Wed, 31 May 2006 20:33:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:139364</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/139364.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=139364</wfw:commentRss><description>&lt;P&gt;Well the "brain-brush"&amp;nbsp;series continues. One of my favourite binary tree question would be given a preorder and inorder traversal strings write a function to build the tree. Most of the rubbish text books provide non-programmatic solution to this and rest append it as a to-do. Today I will proceed step-by-step to solve this and that too with same ingredients - delegate, generics and C#2.0. Disclaimer still holds: "This is just a fundamental recapitulation of binary tree and data structure as a whole. Geeks excuse me please for this series.&lt;/P&gt;
&lt;P&gt;In the earlier &lt;a href="http://dotnetjunkies.com/WebLog/debasish/archive/2006/05/27/139143.aspx"&gt;post&lt;/A&gt;&amp;nbsp;I discussed the simple data structure of treenode and binary tree. Just to repeat once following is the skeleton of my binary tree class&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class BinaryTree&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //root node&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public TreeNode root;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Algorithms...InOrder etc.&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Now for simplicity lets assume that the binary treenode contains single character data. So instead of embedding our tree-building algo inside this generic BinaryTree class I specialized ot to create a subclass called CharBinaryTree.&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="" src="http://www.raagahacker.com/images/blog/BinaryExpressionTree/WH_BT.gif"&gt;&lt;BR&gt;"Whitehorse" in action. Lets construct the base logic Assume we have following binary tree&lt;/P&gt;&lt;IMG alt="" src="http://www.raagahacker.com/images/blog/BinaryExpressionTree/Sample_BT.gif"&gt; 
&lt;P&gt;Preorder traversal string and Inorder traversal strings are&amp;nbsp;&amp;nbsp;124536&amp;nbsp;and 425163 respectively Lets now back calculate and see how one might can possibly build the tree. Firstly preorder string always helps to get the root right. VLR. Does it ring a bell? But then how to differntiate between&amp;nbsp;left subtree(LT)&amp;nbsp;and right subtree(RT). Well simple. Split the inorder string based on the pivotal root. Left substring is LT and right substring is RT. Now we have to recurse. That's fine. But what are the pivotal indexes for LT and RT. Simple -&amp;nbsp;if you can see&amp;nbsp;dry-run the&amp;nbsp;first recursion frame &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;root := 1, LT := 425, RT := 63&lt;BR&gt;pivot(LT) := pivot+1, pivot(RT) := pivot + len(LT) + 1.&lt;/FONT&gt; &lt;/P&gt;
&lt;P&gt;Naturally&amp;nbsp;these pivotal characters will be the roots of the respective subtrees. Enough said. Let's dump the C# code right now.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private TreeNode MakeTree(string inorderString, int preOrderIndex)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TreeNode p = new TreeNode(' ');&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// terminating condition&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (inorderString.Length == 1)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char.TryParse(inorderString, out p.nodeData);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char pivot = this.preorderString[preOrderIndex];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int rootIndexInorder = inorderString.IndexOf(pivot);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string left&amp;nbsp; = "";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string right = "";&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (rootIndexInorder &amp;gt; 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;left = inorderString.Substring(0, rootIndexInorder);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;right = inorderString.Substring(rootIndexInorder + 1);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p.nodeData = pivot;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (left.Length != 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p.left = MakeTree(left, preOrderIndex + 1);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (right.Length != 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p.right = MakeTree(right, preOrderIndex + left.Length + 1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return p;&lt;BR&gt;}&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This goes the private "workhorse" function as described in my earlier post of the DS-BrainBrush series. Lets see the driver function&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public TreeNode MakeTree(string inorderString, string preorderString)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Couple of pre-checks&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((inorderString.Length == 0) ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(preorderString.Length == 0))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentException("Traversal strings shouldn't be empty");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (inorderString.Length != preorderString.Length)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentException("Traversal strings should have identical length");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Make a copy of traversal strings&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.preorderString = preorderString;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.inorderString = inorderString;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Make a call to "workhorse"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.root = this.MakeTree(this.inorderString, 0);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return this.root;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Everything fits nicely in the "workhorse-driver" model. In the next post of this series I will show how to create a special binary tree called Binary Expression Tree(BET) heavily used in world of lexical analyzer, parser and compilers. See you soon.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=139364" width="1" height="1"&gt;</description></item><item><title>Photos.Blogger.com</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/30/139283.aspx</link><pubDate>Tue, 30 May 2006 16:39:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:139283</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/139283.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=139283</wfw:commentRss><description>&lt;P&gt;This quick post is for just a preview and a short description about&amp;nbsp;a&amp;nbsp;tool I'm building right now. Many bloggers hosts their pages to a thirdparty site like this DNJ or DotNetJunkies , SQLJ etc. In many cases due to restrictions or other reasons some doesn't get access to upload pictures relevant to a specific blog. And no need to tell the importance of screenshots when you are&amp;nbsp;blogging the features of your next crazy invention or experiment. But some blog-host do allow to upload photos but it happens so that you don't like that domain. Earlier my primary .NET blog was hosted by blogspot which is now blogger(Googled). But I always preferred DNJ for obvious reasons. But my account in DNJ initially has no permission to upload images or to use gallery. So I decided to write a small utility that will wrap up blogspot's photo-uploader webpage in a nice, cute C# Winform application and will return the image URLs which I can paste in any of my the DNJ's blog-posts. Initially I used to do it manually but later I devised this small application :-&lt;/P&gt;&lt;A href="http://photos1.blogger.com/blogger/6408/774/1600/Capture1.3.gif"&gt;&lt;IMG alt="" src="http://photos1.blogger.com/blogger/6408/774/320/Capture1.2.png"&gt;&lt;/A&gt; 
&lt;P&gt;Do you like it? Once finished I will publish the full source code here at DNJ. DNJ rocks.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=139283" width="1" height="1"&gt;</description></item><item><title>Binary Tree, C# and Delegates  - Part 1</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/27/139143.aspx</link><pubDate>Sat, 27 May 2006 07:56:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:139143</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/139143.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=139143</wfw:commentRss><description>&lt;P&gt;During the last week I was brushing up my Data Structure fundamentals. It was great to&amp;nbsp;get back&amp;nbsp;the days of C style pointers, link list, binary trees etc. But at the same time I want to play around the anonymous delegates of C# 2.0. Both my wishes were granted...My data structures were based on C# generics. The TreeNode structure and the action delegate were both templatized(i.e. based on Generics&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public delegate void Action&amp;lt;T&amp;gt;(TreeNode&amp;lt;T&amp;gt; p);&lt;BR&gt;public class TreeNode&amp;lt;T&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Data&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public T nodeData;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Self pointers&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public TreeNode&amp;lt;T&amp;gt; left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public TreeNode&amp;lt;T&amp;gt; right;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //More stuff...&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Pretty simple stuff. The task I wanted to implement first is to do a inorder walk down the tree without using recursion. My primary objective in this blog is to resurrect the dying spirit of Data Structure fundamentals ,not to show a new discovery or geeky stuff. Now to do an Inorder walk non-recursively we need a stack. You name it , System.Collections.Generic has it. &lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;//declare a stack&lt;BR&gt;Stack&amp;lt;TreeNode&amp;lt;T&amp;gt;&amp;gt; s = new Stack&amp;lt;TreeNode&amp;lt;T&amp;gt;&amp;gt;();&lt;BR&gt;TreeNode&amp;lt;T&amp;gt; ptr = nodePtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;do&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;while (ptr != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;s.Push(ptr);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ptr = ptr.left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;ptr = s.Pop();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;action(ptr);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;ptr = ptr.right;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;}while (s.Count != 0)&lt;/FONT&gt;;&lt;/P&gt;
&lt;P&gt;Let's give the interface of the function.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private void InOrder(Action&amp;lt;T&amp;gt; action, TreeNode&amp;lt;T&amp;gt; nodePtr)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Another short pointer for the usage of private qualifier. For all(well almost) traversal algorithms&amp;nbsp;of the tree it is always wise to&amp;nbsp;keep two versions. One private&amp;nbsp;method taking a generic&amp;nbsp;TreeNode*(in C)&amp;nbsp;or TreeNode(in C#) and another top level public function calling the private counterpart with the root as a value of the TreeNode* or TreeNode refrence variable. The private function is often called "workhorse.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public void InOrder(Action&amp;lt;T&amp;gt; action)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.InOrder(action, root);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Now the funniest part. The calling&amp;nbsp;portion&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;tree.InOrder(delegate(TreeNode&amp;lt;int&amp;gt; p)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lblPrintTree.Text += p.nodeData.ToString();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;We are injecting&amp;nbsp;our own&amp;nbsp;callback function to the InOrder tree&amp;nbsp;traversal algorithm through the anonymous generic delegate . C#2.0 is cool. Soon I will publish couple of posts in the context of same topic - "Data Structure Fundamentals" brain-brush. See &lt;a href="http://dotnetjunkies.com/WebLog/debasish/archive/2006/05/31/139364.aspx"&gt;part 2&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=139143" width="1" height="1"&gt;</description></item><item><title>SQL Injection Attack, Inference Attack and an E-Commerce Site</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/26/139137.aspx</link><pubDate>Fri, 26 May 2006 20:45:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:139137</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/139137.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=139137</wfw:commentRss><description>&lt;P&gt;If you want to learn real attacking techniques(SQL Injection Attack or Inference Attack) used for hacking real e-commerce sites by real hackers watch this:-&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.rockyh.net/AssemblyHijacking/AssemblyHijacking_media/AssemblyHijacking.wmv"&gt;http://www.rockyh.net/AssemblyHijacking/AssemblyHijacking_media/AssemblyHijacking.wmv&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=139137" width="1" height="1"&gt;</description></item><item><title>AI RoboForm, BHO and C#</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/20/138662.aspx</link><pubDate>Sat, 20 May 2006 20:44:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:138662</guid><dc:creator>debasish</dc:creator><slash:comments>2</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/138662.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=138662</wfw:commentRss><description>&lt;P&gt;Remember the awesome AI RoboForm. Its the smartest of all web form fillers exist on earth. In case you haven't used it you can found it &lt;A href="http://www.roboform.com/"&gt;here&lt;/A&gt;. From&amp;nbsp;password memorization (I'm&amp;nbsp;extremely&amp;nbsp;shaky about trusting any third party software expecially those deals with password, CCs etc.), to secure&amp;nbsp;transfer of user data profile to removable devices&amp;nbsp;by Pass2Go&amp;nbsp;RoboForm has it all. Although its seems easy until I myself went on creating some proof of concept equivalent to this. &lt;BR&gt;To achieve anything closer to this I need to create something called plugin. You must be saying a - 2yr-old kid also know about plugins. What's your point?&amp;nbsp;To be exact&amp;nbsp;I need to create something called BHOs or browser helper objects. These are some browser specific extensibility modules for doing things that the core browser engine not supposed to do. But this same thing can open up a whole new dimension to virus writers and hackers. You know its easy to sit into the lap of Internet Explorer and watch your credit card number and CCV passing by. At certain point of time(most probably around 5.5 release) Microsoft stopped the support for writing IE plugins but the model came back in the name of BHOs. As a part of SP2 patchset of XP, a BHO control manager option has been added to IE. My BHO has to be listed there in order to justify itself as a BHO!&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/RoboFormCracked/Manage_IE_Addons.gif"&gt;&lt;/P&gt;
&lt;P&gt;The first thing you should do to write a BHO in managed language is to recreate the C++/COM interface signature of &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/workshop/components/com/reference/ifaces/iobjectwithsite/iobjectwithsite.asp"&gt;IObjectWithSite&lt;/A&gt;&amp;nbsp;in C#.&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;[ComVisible(true),&lt;BR&gt;&amp;nbsp;InterfaceType(ComInterfaceType.InterfaceIsIUnknown),&lt;BR&gt;&amp;nbsp;Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352") ]&lt;BR&gt;&amp;nbsp;public interface IObjectWithSite&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int SetSite ([MarshalAs(UnmanagedType.IUnknown)]object site);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;[PreserveSig]&lt;BR&gt;&amp;nbsp;&amp;nbsp;int GetSite (ref Guid guid, out IntPtr ppvSite);&lt;BR&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;Now I'm going to implement this interface. To supply the GUID for this class I called up guidgen.exe which could easily be accessed from Tools &amp;gt;&amp;gt; Create GUID&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/RoboFormCracked/Create_GUID.gif"&gt;&lt;/P&gt;
&lt;P&gt;My class implementing the IObjectWithSite interface is following. Now as the same GUID has to be registered with windows registry I made the declaration of it as const string(just like static but accessible from attribute)&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;[ComVisible(true),&lt;BR&gt;&amp;nbsp;ClassInterface(ClassInterfaceType.None),&lt;BR&gt;&amp;nbsp;Guid(SiteWatcherBHO.BHO_GUID)]&lt;BR&gt;&amp;nbsp;public class SiteWatcherBHO : IObjectWithSite&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public const string BHO_GUID = "FFF9DE52-E5A5-4217-B938-DFF5EA95B4CD"; // &amp;lt;&amp;lt; Your GUID goes here&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //SetSite(), GetSite() impl...&lt;BR&gt;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Before implementing meat of our BHO lets set the framework of its registration. While registering the BHO we have to create a subkey at&lt;BR&gt;SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\ with name same as of the generated GUID tagged around the class implementing IObjectWithSite. To simplify the registering process of COM modules(BHOs fall into this category)&amp;nbsp;written as a .NET module Microsoft has provided an utility called RegAsm. One of the interesting switches associated with RegAsm is /codebase. Upon providing this with the commandline, RegAsm automatically searches for a public static method in the assembly which is tagged with the ComRegisterFunction attribute. The benefit is tremendous. You can do any kind of registration work inside the function. As some COM modules require the creation of some special key at some special location this technique proves to be very useful. But if required you can go online, update your online database, call webservice ..anything inside this special method&amp;nbsp;and the fun part is that all this is being done under the cosy corner of .NET. But to be good citizen and play fair you shold pair up your registration function and should provide a static method tagged with ComUnregisterFunction attribute. Reason is simple when your uninstaller calls to unregister the module, depending upon your scenario you should partially or totally undo what you have done in the registration function.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class SiteWatcherBHO : IObjectWithSite&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ComRegisterFunction]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static void RegisterFunction(Type typeToRegister) {}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ComUnregisterFunction]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static void UnregisterFunction(Type typeToRegister) {}&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Below I will show the code I used in my BHO class&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;[ComRegisterFunction]&lt;BR&gt;&amp;nbsp;&amp;nbsp;public static void RegisterBHO(Type t)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\{" + SiteWatcherBHO.BHO_GUID + "}");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch(Exception e)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;#ifdef&amp;nbsp;DEBUG&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Windows.Forms.MessageBox.Show(e.ToString());&lt;BR&gt;#endif&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;See the const declaration of the GUID comes handy here. Another important point is the presence of&amp;nbsp;preprocessor directives. Now in the production release of my CCNumberCollector BHO I'm not supposed to show any messages. Not even a log. Just devour the entire exception like what has been shown here. "Leave no trace" is The mottow for all "underground" guys. Now GetSite() and SetSite() both will be called during the creation and termination of the object we are implementing here(means our BHO object) but each time with a different argument for the site parameter. For SetSite() the site will be non-null while creation and null while termination. Now lets fix the job of our BHO. In this sample BHO I will fillup the username and password of my yahoo mail account and auto-login into it. Saying this I need an appropriate place to do all the fillup stuff. DocumentComplete event is an ideal for such scenario. Now the site object passed at SetSite() is very very precious. Because it is our beloved SHDocVw.WebBrowser instance. Once we have this at our disposal and we added a reference to MSHTML module(through Interop obviously) we can play anything with IE. To generate the Winform equivalent of IE ActiveX you have to use the AxImp tool. For the second task tlbimp is necessary.&lt;/P&gt;
&lt;P&gt;1. aximp c:\windows\system\shdocvw.dll&lt;BR&gt;&lt;BR&gt;2. tlbimp mshtml.tlb&lt;BR&gt;&lt;BR&gt;The code at SetSite() implementation should look something like below&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT face="Courier New"&gt;if (site != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; webBrowser = (WebBrowser)site;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (webBrowser != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; webBrowser.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(webBrowser_DocumentComplete);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (webBrowser != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; webBrowser.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(webBrowser_DocumentComplete);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; webBrowser = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/FONT&gt;&lt;BR&gt;We store the IE web browser instance in a private member of type SHDocVw.WebBrowser. Now what our DocumentComplete event handler does is very simple. If the current URL looks like a yahoo mail, it fills the username and password boxes and auto-login by executing JScript code dynamically on the parent window containing the HTML document. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT face="Courier New"&gt;IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (document != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //See if we are in codeproject&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string url = document.location.href;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (url.IndexOf("mail.yahoo.com") &amp;gt;= 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string sJScript = @"var ctlUserID = document.getElementById('username');&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var ctlPassword = document.getElementById('passwd');&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((ctlUserID != null) &amp;amp;&amp;amp; (ctlPassword != null))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctlUserID.value = &lt;A href="mailto:'debasish.bose@gmail.com'"&gt;'debasish.bose@gmail.com'&lt;/A&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ctlPassword.value = '*******;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}";&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.parentWindow.execScript(sJScript, "JScript");&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sJScript = "login_form.submit();";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.parentWindow.execScript(sJScript, "JScript");&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Hardcoding the password is the crudest method I can imagine right now. It just for demonstration purpose. In reality you should be fetching it into a &lt;A href="http://msdn2.microsoft.com/en-us/library/7kt014s1.aspx"&gt;SecureString&lt;/A&gt; from some encrypted password repository(which may prove useful in building something like a master password or SSO system)&lt;BR&gt;That's it. Now how to capture the CC numbers is upto you. Oh by the way I bought&amp;nbsp;a cute PSP and enjoying every moment with it. My N-Gage is crying like anything.&lt;/P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/RoboFormCracked/My_PSP.gif"&gt; 
&lt;P&gt;Once my "play boy" moments are over, I will start hacking it. Although with current Firmware version hacking seems little impossible at this point, lets be optimistic. Another Monday, another week..damn.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=138662" width="1" height="1"&gt;</description></item><item><title>Electrified !!!</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/14/138402.aspx</link><pubDate>Sun, 14 May 2006 15:47:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:138402</guid><dc:creator>debasish</dc:creator><slash:comments>0</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/138402.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=138402</wfw:commentRss><description>&lt;P&gt;&lt;IMG src="http://www.raagahacker.com/images/blog/GetsRecognized/Capture1.gif"&gt;&lt;/P&gt;
&lt;P&gt;It feels good really good.&amp;nbsp;The last post has been listed &lt;A href="http://jasonhaley.com/blog/archive/2006/05/12/136515.aspx"&gt;here&lt;/A&gt;&amp;nbsp;&amp;nbsp;in "interesting finding" section&amp;nbsp;with my "idol" Don Box. I'm elctrified !!!.&lt;BR&gt;I will post more sane and insane experiments to keep the standards up. Thanks you guys&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=138402" width="1" height="1"&gt;</description></item><item><title>WinDbg , Crash Dump .. Associated Headches</title><link>http://www.dotnetjunkies.com/WebLog/debasish/archive/2006/05/11/138175.aspx</link><pubDate>Thu, 11 May 2006 17:05:00 GMT</pubDate><guid isPermaLink="false">58df7014-fd75-437c-9641-150997716d1c:138175</guid><dc:creator>debasish</dc:creator><slash:comments>1</slash:comments><comments>http://www.dotnetjunkies.com/WebLog/debasish/comments/138175.aspx</comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/debasish/commentrss.aspx?PostID=138175</wfw:commentRss><description>&lt;P&gt;For a long tome I kept myself away from this wonderful but ugly looking tool as I was the die-hard fan of a Compuware(Numega then)&amp;nbsp;masterpiece - SoftIce. Hey I still have it installed inside of&amp;nbsp;a Win98 Virtual Box in my XP host. Though SoftIce has got its new incarnation - &lt;A href="http://www.compuware.com/products/devpartner/default.htm"&gt;DriverStudio&lt;/A&gt;, not the WinDbg. If you haven't downloaded it, get it &lt;A href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx"&gt;Debugging tools for Windows&lt;/A&gt;. But I'm not going to give basics of WinDbg usage here.&amp;nbsp; Nop. But quality articles are galore. One thing I must mention that if your technology stack contains anything .NET, there is a nice WinDbg extension DLL(always keep an eye on software extensibility model) exists at the .NET framework installation folder. It's sos.dll(&lt;U&gt;S&lt;/U&gt;on &lt;U&gt;O&lt;/U&gt;f &lt;U&gt;S&lt;/U&gt;trike). This guy will help to inspect virually anything in .NET world from method table to managed stack&lt;/P&gt;
&lt;P&gt;This encounter with Windbg is actually initiated from requirements at my office. I was analyzing some crash dump generated by our driver library. Boy they are fatty. But still they are smaller than the earlier days. Actually these beasts are tagged as Mini Dump which is much light-weight than the full fledged dumps often called Core Dump. Mini Dumps are very different than their older counterparts in the following way&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Instead of saving the entire process space, only certain sections are saved. There is no point in saving copies of modules such as Kernel32.dll; if the version number is included, it is easy to get a copy from a Windows CD. The actual memory heap of the application is by default not saved in a minidump; it is not required to debug a surprisingly high percentage of crashes. You can save the heap if you need to, however. 
&lt;LI&gt;The minidump save code works to get accurate and full information for modules, including their names, paths, version information, and internal timestamps. 
&lt;LI&gt;The minidump save code also gets the list of threads, their contexts (that is, register sets), and the memory behind their stacks. 
&lt;LI&gt;The whole file is compressed, further reducing its size. A minidump for Notepad is around 6K on Windows XP, almost 300 times smaller than the previous crash dump of the same process. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Now when do we generates dump? Certainly not always. Instead one of these scary moments when your software "sees" end of days at customer premises. Most of the softwares now-a-days&amp;nbsp;employs structure exception handling(SEH) and displays custom user-friendly UI if a fault occurs. But sometimes it is necessary for the developers to analyze what's exactly happened when the fault occurred. Handling the exception is certainly not the answer. Instead with some configuration changes(may be application configuration or infamous&amp;nbsp;Windows Registry backdoor)&amp;nbsp;the "on site" guy enables the dump generation facility&amp;nbsp;and reproduces the fault once more. Following is a vanilla piece of code found somewhere in this context.&lt;/P&gt;
&lt;P&gt;[C#]&lt;BR&gt;&lt;FONT face="Courier New"&gt;&lt;FONT&gt;try&lt;BR&gt;&lt;/FONT&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT&gt;//where fault occurs...&lt;BR&gt;&lt;/FONT&gt;}&lt;BR&gt;&lt;FONT&gt;catch&lt;/FONT&gt;(Exception e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT&gt;if&lt;/FONT&gt; (TraceLevel == TraceLevel.GenerateDump)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DumpGenerator.WriteCrachDump();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Couple of pointers here. First the check inside the exception handler is very important..I repeat..very very important. Here&amp;nbsp;dump is generated as an elevated level of&amp;nbsp;application(or driver)&amp;nbsp;tracing&amp;nbsp;configuration(again done by our beloved "on site" guy). Not always your application(or driver) should inflate the customer disks with fatty DMP files. Another subtle point - I didn't pass the exception object as a parameter to the dump generator function. As this is managed code the exception object will only contain the exception information pertaining to the managed stack. But we need an unmanaged Exception_Pointers struct to pass around. That could be generated within the function with the help of&amp;nbsp; GetLastError() API. Still there is a catch - if you P/Invoke the GetLastError call from C#, always remember that there is chance that CLR will invalidate the error while doing its own stuff when control returns from unmanaged world(where error occurred) to managed world by Interop Marshallar. Look at &lt;A href="http://blogs.msdn.com/adam_nathan/archive/2003/04/25/56643.aspx"&gt;this entry&lt;/A&gt; of Adam Nathan's blog for more detail.&lt;/P&gt;
&lt;P&gt;The most important parameter to the &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/minidumpwritedump.asp"&gt;MiniDumpWrite&lt;/A&gt; function is the first and second.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;typedef struct _MINIDUMP_EXCEPTION_INFORMATION {&lt;BR&gt;&amp;nbsp; DWORD ThreadId;&lt;BR&gt;&amp;nbsp; PEXCEPTION_POINTERS ExceptionPointers;&lt;BR&gt;&amp;nbsp; BOOL ClientPointers;&lt;BR&gt;} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;Naturally the exception pointers parameter is what I was&amp;nbsp;talking about a liitle bit ago and its retrieval by GetLastError or Marshal.GetLastWin32Error. The first parameter identifies the thread which throws the exception. &lt;/P&gt;
&lt;P&gt;Now from here the fun begins. I successfully able to analyze all but one DMP file by inspecting managed and unmanaged stack. But whenever I&amp;nbsp;tried to open the offending DMP file, my WinDbg crashed. Oh God! Who will analyze the dump that WinDbg will generate? Purplexing !&lt;BR&gt;Just before crash I saw a strange output at the WinDbg's console. Something related to invalid thraed id. &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;ERROR: Unable to find system thread 2&lt;BR&gt;ERROR: The thread being debugged has either exited or cannot be accessed&lt;BR&gt;ERROR: Many commands will not work properly&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Now I was performing a suite of test cases while dump was generated. It&amp;nbsp;was utmost important to me to know which process actually generated the dump so that I could narrow down the troubled section. Fortunately there is a tool in the same folder where WinDbg usually resides - &lt;A href="http://support.microsoft.com/kb/315271/"&gt;dumpchk.exe&lt;/A&gt;. With &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;gt;&amp;gt;&amp;nbsp; dumpchk -e "offending_dump_file.dmp"&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;I was instantly presented with&amp;nbsp;enough information to determine the offending test case. But that doesn't solve the problem of WinDbg's unusal crash. Later I found out(through debugging - without dumpchk that even would have been impossible)&amp;nbsp; that when &lt;FONT face="Courier New"&gt;ExceptionPointers &lt;FONT face="Times New Roman"&gt;parameter is not null(means exception actually happened at unmanaged layer of our code) we are pushing the "passed" thread id to this structure before calling the write dump function.Although if you pass null or 0 to this &lt;FONT face="Courier New"&gt;ExceptionPointers &lt;/FONT&gt;&lt;FONT face="Times New Roman"&gt;parameter dump will be generated but its unmanaged stack will be ignored. So to track back how we were passing the thread id to this function, I discovered following code&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;#ifdef&amp;nbsp; DOTNET20&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; threadId = System.Threading.Thread.ManagedThreadId();&lt;BR&gt;#else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; threadId = AppDomain.GetCurrentThreadId();&lt;BR&gt;#endif&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Surely the Appdomain.GetCurrentThreadId API has been deprecated but It does something the newer API doesn't and neither supposed to that.&lt;BR&gt;Managed threads has nothing to do with unmanaged threads. The mapping between managed thread to unmanage thread is tricky. The newer API is just a hash&amp;nbsp; value used to determine a managed threads uniquely. It doesn't corresponds to the unmanaged thread. The mapping between these thraeds of two worlds&amp;nbsp;could be controlled by a CLR host or could be changed by future versions of .NET Fx. Due to this unstability Microsoft recommends that you are not supposed to assume 1:1 correspondence between manage and unmanaged thread while using AppDomain.GetCurrentThreadId() in your code. Although&amp;nbsp;in 2.0 it happens to return the unmanaged id but who knows. Sonner or later this code will definitely break. Check at this blogs about manage and unmanaged threads - &lt;A href="https://blogs.msdn.com/yunjin/archive/2005/08/25/456355.aspx"&gt;1&lt;/A&gt;, &lt;A href="http://blogs.msdn.com/junfeng/archive/2004/02/03/66502.aspx"&gt;2&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;With "not-so-offending" dump files your "!analyze -v" session will be peaceful. It's 3 AM here at India. I'm tired..See you guys.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=138175" width="1" height="1"&gt;</description></item></channel></rss>