Inside and Out…

An attempt to understand technology better…

Archive for the ‘Development’ Category

Enumerating AppDomains – I

Posted by Gaurav Khanna on June 9, 2007

Surprisingly, enumerating AppDomains is not that straightforward. The System.AppDomain type does not expose functionality to enumerate them at all. The way to enumerate them will be to use the V1 Hosting interface, ICorRuntimeHost and then invoke the EnumDomains and NextDomain methods against it to get the list. If you are using CLR 2.0, you needn’t worry as CLR 2.0 does implement the V1 interfaces as well.

 

Below is the snippet that exemplifies the concept (note: AppDomains will only be enumerated in the current process – I will discuss AppDomain enumeration in remote processes later). You can download the source code (VS Solution) from http://www.wintoolzone.com/ListDotNET.aspx?Listtype=5

 

// EnumAppDomains.cpp : Defines the entry point for the console application.
// 
#include "stdafx.h"
#include <windows.h>
#include "mscoree.h"
#import "C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\mscorlib.tlb" raw_interfaces_only
using namespace mscorlib; 
#define EXITONERROR(hr, mesg) \
if (FAILED(hr)) \
{ \
printf("%s\n", mesg); \
ExitProcess(1); \
} 
#define SUCCESSFUL(hr) (SUCCEEDED(hr) && hr != S_FALSE) 
int _tmain(int argc, _TCHAR* argv[])
{
ICorRuntimeHost * pV1HostPtr = NULL;
HRESULT hr = CorBindToRuntimeEx(NULL,
NULL, 0, 
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(LPVOID *)&pV1HostPtr);
EXITONERROR(hr, "Unable to get ICorRuntimeHost*"); 
// Start the runtime
hr = pV1HostPtr->Start();
EXITONERROR(hr, "Unable to start the runtime"); 
// Enumerate the AppDomains
HDOMAINENUM adEnum;
hr = pV1HostPtr->EnumDomains(&adEnum);
EXITONERROR(hr, "Unable to enumerate AppDomains");
// Loop thru the domains
IUnknown * pDomainUnk = NULL;
hr = pV1HostPtr->NextDomain(adEnum, &pDomainUnk);
while(SUCCESSFUL(hr))
{
// Got the IUnknown* to the AppDomain - convert it to AppDomain pointer
_AppDomain * pCurDomain = NULL;
hr = pDomainUnk->QueryInterface(__uuidof(_AppDomain), (VOID**)&pCurDomain);
if (SUCCESSFUL(hr))
{
// Display the name of the AppDomain
BSTR str;
if (SUCCESSFUL(pCurDomain->get_FriendlyName(&str)))
{
wprintf(L"AppDomain: %s\n",str);
}
else
{
printf("AppDomain: unable to get the name!\n");
}
} 
// Loop onto the next Domain
hr = pV1HostPtr->NextDomain(adEnum, &pDomainUnk);
} 
// Stop the runtime
if (pV1HostPtr)
{
pV1HostPtr->Stop();
}
return 0;
} 
Advertisements

Posted in .NET Framework, CLR, Development | Leave a Comment »

Lessons in Exception Handling

Posted by Gaurav Khanna on May 13, 2007

Working on the CLR’s exception handling subsystem is not just challenging but also gives unique opportunities to understand how the various exception handling subsystems (e.g. SEH, C++ EH, etc) work, and in particular, how they interoperate with one another. It was such case that had me discuss one such issue with Kevin, development lead of the JIT, that he mentions here.

That discussion got me exploring the interoperability aspects of EH further and resulted in the bullets listed below. Incase you are interested, download the PDF version of this article from here and the accompanying source code from here. For those uninitiated to exception handling, Matt Pietrek’s must read article is here.

Now, onto the interoperability aspects of EH.

Note: the following discussion is in context of the x86 platform

  • Catching an exception using __try/__except SEH handler will result in RtlUnwind being called without exception record

    Structured Exception Handling (SEH)
    is built into the Windows OS and it is how the OS processes the exceptions. Compilers offer their own specific ways of setting up a SEH handler. To setup one using Microsoft Visual C++, we use __try/__except keywords. For example:

    __try
    {
    printf(“Calling the /EHSc function\n“);
    InvokeCPPFunction();
    }
    __except (IsForUs(GetExceptionInformation()))
    {
    printf(“In __except\n“);
    }

    If the InvokeCPPFunction throws an exception, the OS will invoke the filter function (the IsForUs function referenced in the braces of __except) and check its return value. The filter function can be passed exception details that can be retrieved using the GetExceptionInformation function and using that information, it can decide whether it wants to process the exception or not.

    If the filter function returns EXCEPTION_CONTINUE_EXECUTION, the OS retries the instruction that created the exception. However, if the return value is EXCEPTION_CONTINUE_SEARCH, it tells the OS that the filter function has declined to process the exception and the OS continues its search for the handler in the SEH handler chain (that is available from FS:0 on x86 machines for each OS thread).

The filter function can also return EXCEPTION_EXECUTE_HANDLER to tell the OS that it wants to handle the exception and the OS proceeds to invoke the funclet within the __except block. But before invoking the funclet, the OS has to unwind the call stack. On x86, the code generated by VC++ compiler does this by invoking RtlUnwind API, with NULL for the third argument – this argument is a pointer to the exception record for the exception being processed. This is done by the compiler by invoking GlobalUnwind (an internal function) after doing some processing. GlobalUnwind makes the call to RtlUnwind as shown below:

@_EH4_GlobalUnwind@4:

70508FB2 push ebp

70508FB3 mov ebp,esp

70508FB5 push ebx

70508FB6 push esi

70508FB7 push edi

70508FB8 push 0

70508FBA push 0

70508FBC push offset ReturnPoint (70508FC7h)

70508FC1 push ecx

70508FC2 call RtlUnwind (70526620h)

The highlighted red line is the one where NULL is pushed for exception record.

What this implies that all SEH handlers that are in the x86 FS:0 chain, prior to the one that agreed to process the exception, will be called by the OS once again to give them a chance to do some cleanup (e.g. release resources) – this is typically known as unwinding of the stack. And since the unwind was initiated with a NULL for the exception record, if your SEH handler relies on checking the exception record for details before deciding to do the cleanup, it can potentially fail (e.g. not end up doing the cleanup)!

  • Corollary Lesson: Don’t throw (and expect to catch correctly) exception across environment boundaries. E.g. throwing a C++ exception and trying to catch it using a SEH handler

    Since a C++ application can have a mix of both C++ exception handling constructs and SEH exception handing constructs, it is easy to commit the mistake of writing code that throws an exception from C++ EH and excepts that to be correctly caught and processed in SEH EH constructs – the focus is on correct processing.

    Let’s extend the previous example. Assume that InvokeCPPFunction is a function in a DLL that was compiled to use C++ EH (using the /EHSc switch) and implemented as shown below:

    class CPPClass2
    {
    public:
    CPPClass2()
    {
    printf(“CPPClass2 constructor\n“);
    }
    ~CPPClass2()
    {
    printf(“CPPClass2 destructor\n“);
    }
    };

    class CPPClass
    {
    public:
    CPPClass()
    {
    printf(“CPPClass constructor\n“);
    }
    void ThrowException()
    {
    CPPClass2 cpp2;
    throw 1;
    }
    ~CPPClass()
    {
    printf(“CPPClass destructor\n“);
    }
    };

    __declspec (dllexport) void InvokeCPPFunction()
    {
    CPPClass cpp;
    cpp.ThrowException();
    }

We have two classes, CPPClass & CPPClass2 that have destructors each. InvokeCPPFunction instantiates CPPClass object, cpp, and invokes the ThrowException method, which in turn, instantiates CPPClass2 object, cpp2, and throws an exception.

As per the C++ semantics, when this exception is caught, the destructors should be invoked as they are expected to do the cleanup for the respective class instance. However, this depends upon who catches the exception.

In our previous example, InvokeCPPFunction was invoked from within __try/__except SEH mechanism. Hence, when ThrowException throws an exception, the OS walks the FS:0 chain to look for a handler that will handle the exception. When the OS comes to our __except block, if the filter funclet returns EXECEPTION_EXECUTE_HANDLER, as per our last discussion, RtlUnwind is invoked with a NULL for the exception record pointer.

When this happens and the unwind call comes to C++ exception handler, the C++ EH does not process the unwind since the exception record is NULL. This is because C++ EH only processes the unwind when the exception code in the exception record has the C++ exception code (0Xe06d7363). Thus, no destructors are invoked and that is not something you want. Below is the output this example:

Hence, it’s important to catch the exception in the environment/EH-context it was thrown in, since that EH-context will know how to process it correctly.

Posted in Development, Exception Handling, Windows, Windows API | Leave a Comment »

[Download] TransNTFS v1.0.0.1 – support for folders, symbolic and hard links and more

Posted by Gaurav Khanna on March 18, 2007

I have updated TransNTFS, my managed implementation for the transactional NTFS APIs that have been introduced with Windows Vista. TransNTFS now also supports the following operations under a transaction:

It comes with complete documentation (as always) and can be downloaded from http://www.wintoolzone.com/ListDotNET.aspx?Listtype=3

Posted in .NET Framework, Development, Downloads, Managed C++, Windows API | Leave a Comment »

[Download] TransNTFS – Managed implementation of Transactional NTFS (TxF) APIs

Posted by Gaurav Khanna on March 15, 2007

Sometime back, I had made a post regarding a native C++ class I had authored for using some of the Transactional NTFS (TxF)APIs introduced in Windows Vista.

Almost two weeks from that post, I just finished my managed implementation, TransNTFS, that enables you to use the TxF APIs from managed code. As always, Managed C++ enabled the implementation with excellent ease. It comes with complete documentation and can be downloaded from http://www.wintoolzone.com/ListDotNET.aspx?Listtype=3.

Below is an example usage of how to copy a file under a transaction:

using System;
using System.Collections.Generic;
using System.Text;
using WinToolZone;
namespace ManagedTransactionCopyDemo
{
class Program
{
static void Main(string[] args)
{
TransNTFS refTC = new TransNTFS();
// Init the transaction
bool fSuccess = refTC.BeginTransaction();
if (fSuccess)
{
fSuccess = refTC.CopyFile("d:\\transcopy.pdb", "d:\\t.pdb", false);
if (fSuccess)
{
fSuccess = refTC.Commit();
if (fSuccess)
{
Console.WriteLine("Copy successful!");
}
else
{
ShowErrorAndExit("Commit failed!", refTC.LastError);
}
}
else
{
ShowErrorAndExit("Copy failed!", refTC.LastError);
}
}
else
{
ShowErrorAndExit("Unable to start the transaction!", refTC.LastError);
}
}
private static void ShowErrorAndExit(string p, int p_2)
{
Console.WriteLine("ERROR: {0}", p);
Console.WriteLine("CODE: {0}", p_2);
System.Environment.Exit(1);
}
}
}

Posted in .NET Framework, Development, Downloads, Windows, Windows API | 1 Comment »

Programming the Transactional NTFS (TxF)

Posted by Gaurav Khanna on March 1, 2007

One of the key new features of Windows Vista is a component called the Kernel Transaction Manager (KTM) that brings inherent support for transactional development in not just the kernel-mode but also for user mode. Infact, NTFS has been enhanced to use and support transactions such that couple of new APIs (e.g. CopyFileTransacted, MoveFileTransacted just to name a few) have surfaced up. You can get more details on Transactional NTFS here.

To demonstrate the power of the new APIs, I wrote a C++ class library (unmanaged), CTransCopy, that allows you to:

  • Copy files under a transaction
  • Move files under a transaction
  • Commit or Rollback the transaction
  • Let you wire up a callback handler for copy/move progress

You can download it from http://www.wintoolzone.com/ListWin32.aspx?Listtype=5. The zipped archive also contains a sample client source code. BTW, since the .LIB file containing the class was compiled using VC++ 2005 compiler, you will need the same to link against it and write an application. You can use VC++ 2005 Express Edition. Below is an example usage of the same:

CTransCopy tcopy;

if (tcopy.IsOSSupported() == FALSE)
{
printf(“This application requires Windows Vista or later.”);
return -1;
}

if (tcopy.Init() == FALSE)
{
printf(“Init failed with error %08X\n”,tcopy.LastError());
return -1;
}

// Setup a callback for progress
tcopy.SetCopyCallback(ProgressCallback);

if (tcopy.CopyFileW(L”D:\\KGK\\Development\\VS\\Windows Vista\\VC\\TransCopy\\debug\\transcopy.pdb”,
L”D:\\transcopy.pdb”,FALSE) == FALSE)
{
printf(“Copy/move failed with error %08X\n”,tcopy.LastError());
tcopy.Rollback();
return -1;
}

if (tcopy.Rollback() == FALSE)
{
printf(“Rollback failed with error %08X\n”,tcopy.LastError());
return -1;
}

if (tcopy.Commit() == FALSE)
{
printf(“Commit failed with error %08X\n”,tcopy.LastError());
return -1;
}

printf(“Copy/move successful!\n”);

The ProgressCallback function is implemented as shown below:

void ProgressCallback(LARGE_INTEGER total, LARGE_INTEGER transferred)
{
double percent = (transferred.QuadPart*100.00)/total.QuadPart;
printf(“%f%% over\n”,percent);
}

Posted in .NET Framework, Development, Downloads, Windows, Windows API | 1 Comment »

Article: Customizing AppDomain Creation

Posted by Gaurav Khanna on February 26, 2007

Did you have a scenario where you wished you could customize the creation of AppDomains? Or, you could control how many AppDomains any code that runs in your application context (e.g. if you are writing a plugin load framework) could create? Or, how about reusing AppDomains for various assemblies?

I have just finished an article on how any of the above scenarios can be accomplished using the System.AppDomainManager type, introduced in .NET Framework 2.0, by intercept AppDomain creation requests.

You can read the article at http://www.wintoolzone.com/articles/Customizing_AppDomain_Creation.aspx and download associated source code from http://www.wintoolzone.com/downloads/Customizing_AppDomain_Creation_src.zip

Posted in .NET Framework, Articles, CLR, Development, Downloads | Leave a Comment »

How the SSCLI [a.k.a. Rotor] managed &quot;new&quot; works

Posted by Gaurav Khanna on February 12, 2007

One of the best ways to understand how the CLR works internally is to have a look at the SSCLI [a.k.a Rotor] source code.

In How the SSCLI [a.k.a. Rotor] managed “new” works, I have used Rotor source code to discuss what happens behind the scenes when you use the managed new operator to instantiate a managed type, discussing implications of object size, how requests from multiple threads are handled, the different validations that are done, when out-of-memory exception is thrown, etc. If you are a managed code developer, you may learn a thing or two that can help you write better code besides understanding how the managed allocation works internally.

Posted in Articles, CLR, Development, Rotor | Leave a Comment »

[WebService] CAPTCHA image generator for spam control

Posted by Gaurav Khanna on July 24, 2006

As part of the revamp efforts of www.wintoolzone.com, I have added the [Web]Services section where I have made available, for free use in your applications, various SOAP based services, built using the .NET Framework.

The first service I have added is a CAPTCHA image generation service. If you are running a website or a blog where you take input from the user in a HTML form, you would know about bots who can spam the form and send invalid details. One of the ways to handle this problem is challenge-response where you throw a challenge to the entity filling up the form and if their response is valid, only then the HTML form’s details are taken for subsequent processing.

One of the ways websites and various blog engines are trying to combat spam is by dynamically generating an image which shall containing a randomly generated text – and then prompting the user to enter the text. Only if there is a match, will the HTML form be processed.

The CAPTCHA image generation service can be used to generate this random text and create an image out of it, which can then be displayed on your webpage for verification. It is Basic Profile 1.1 specification compliant. Its free for use in your applications – you simply need to be registered with WinToolZone.

Complete service documentation is at http://www.wintoolzone.com/showpage.aspx?url=Services/Help/Help_CaptchaGenerator.aspx

Posted in .NET Framework, Development | Leave a Comment »

WinToolZone.Bluetooth – Added device enumeration support

Posted by Gaurav Khanna on July 6, 2006

WinToolZone.Bluetooth, the managed Bluetooth API for the desktop that I am working on, now has the support for enumerating devices as well. The snippet below exemplifies it:

    Bluetooth bth = new Bluetooth();
            
    // EnumRadios(bth);

    if (bth.RefreshDevices(false, true, true, true, true, null) == false)
    {
         Console.WriteLine("Unable to enum devices");
         return;
    }

    foreach (BluetoothDevice device in bth.Devices)
    {
         Console.WriteLine("Devicename: {0}", device.Name);
         Console.WriteLine("LastSeen: {0}", device.LastSeen.ToString());
         Console.WriteLine("LastUsed: {0}", device.LastUsed.ToString());
         Console.WriteLine("Connected: {0}", device.IsConnected.ToString());
         Console.WriteLine("Remembered: {0}", device.IsRemembered.ToString());
         Console.WriteLine("Authenticated: {0}", device.IsAuthenticated.ToString());
         Console.WriteLine("DeviceClass: {0}", device.DeviceClassID);
         Console.WriteLine("Address: {0}\n", device.Address.ToString());
                
    }

And below is an output screenshot:

Bluetooth device enumeration output using WinToolZone.Bluetooth

Technorati : , , , ,
Del.icio.us : , , , ,
Ice Rocket : , , , ,
43 Things : , , , ,

Posted in .NET Framework, Development, Managed C++, Windows API | 1 Comment »

WinToolZone.Bluetooth – Managed Bluetooth API for the desktop

Posted by Gaurav Khanna on July 5, 2006

One of the communication protocols not present in .NET Framework class libraries is Bluetooth. So today, I started to work on my implementation of a managed API for Bluetooth programming – WinToolZone.Bluetooth. I am authoring it using Managed C++ and leveraging the Microsoft Bluetooth stack APIs.

I just completed implementing the support for enumerating the Bluetooth radios on a machine. Below is a C# program that exemplifies how they can be enumerated:

using System;
using System.Collections.Generic;
using System.Text;
using WinToolZone;

namespace BTHCSClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Bluetooth bth = new Bluetooth();
            if (bth.RefreshRadios())
            {
                foreach (BluetoothRadio radio in bth.Radios)
                {
                    Console.WriteLine("RadioName: {0}", radio.Name);
                    Console.WriteLine("Address: {0}", radio.Address.ToString());
                    Console.WriteLine("ManuID: {0}", radio.ManufacturerID);
                    Console.WriteLine("LMPSubversion: {0}", radio.LMPSubversion);
                    Console.WriteLine("DeviceClass: {0}", radio.DeviceClass);
                }
            }
            else
            {
                Console.WriteLine("Unable to enumerate BTH radios");
            }
        }
    }
}

Technorati : , , , , , ,
Del.icio.us : , , , , , ,
Buzznet : , , , , , ,
43 Things : , , , , , ,

Posted in .NET Framework, Development, Distributed Communications, Managed C++ | 1 Comment »