Inside and Out...

An attempt to understand technology better...

  Home  |   Contact  |   Syndication    |   Login
  160 Posts | 0 Stories | 12 Comments | 181 Trackbacks

News


WinToolZone - Spelunking Microsoft Technologies
I work as a developer on the Common Language Runtime (CLR) team, specifically in the areas of exception handling and CLR hosting.
Disclaimer

The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion. All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.

Tag Cloud


Archives

Post Categories

Image Galleries

Links

Monday, January 07, 2008 #

Stack walking is second nature to debuggers. But if you had more interest in it than just debugging and either:

  • wanted to know what stack walking is about, or
  • wanted to know how stack walking is implemented, or
  • wanted to know how a custom stack walker can be authored for your application

then you might find the article, Authoring a Stack Walker for X86, useful. Its my attempt to help clarify the basics of stack walking and explain key concepts and show how it can be implemented on x86 platform. The article can be read here and its accompanying stack walker implementation source code can be downloaded from here.

Below is an output from the stack walker implementation discussed in the article:


Wednesday, December 26, 2007 #

Advanced Windows Debugging got me hooked onto Detours and that led me to experiment with it a bit more. It resulted in this. Over the past three days, I have been working on using Detours to build a memory leak detection tool. MemAnalysis is finally done (v1, that is) and can track memory allocation and release when done using the following APIs:

  • VirtualAlloc
  • VirtualFree
  • HeapAlloc
  • HeapFree
  • HeapDestroy

Once the application being analyzed exits, MemAnalysis produces a report with details on how many allocations took place, how many of them were freed and how much memory was not released. Below is a sample output:

Total Allocations: 8605
Total Virtual allocations: 1
Freed Virtual allocations: 1
Virtual allocation leaked size: 0 bytes

Total Heap allocations: 8604
Freed Heap allocations: 4189
Heap allocation leaked size: 1965244 bytes
==============================================

2344 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019CDD0h
548 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019D700h
16 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019C718h
308 bytes were leaked; Allocation method: Heap; Handle: 10000h; Address: 00010588h
60 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019C4F0h
24 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 00184830h
1826 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019D700h
2032 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019DE30h
538 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019D700h
104 bytes were leaked; Allocation method: Heap; Handle: 180000h; Address: 0019A600h

It is a free download and can be downloaded from here.

Note: If not already present on your machine, you need to have VC++ 2008 runtimes installed. The X86 version can be downloaded from here and the X64 version is here.


Sunday, December 23, 2007 #

Detours is a very interesting library from Microsoft Research that allows you to intercept Windows API calls that an application makes and redirect them to your code that can then:

  1. do some pre-and-post processing work around the call to the original API, and/or
  2. customize what is returned to the caller of the API

This does not involve accessing original application source code and can be done at runtime!

For an example, check the screenshot below for a sample that intercepts calls to GetVersionEx API by an application and displays the OS version details. The first output is the original OS version information when the application invokes GetVersionEx. The second output is when the application is launched by my wrapper application that enabled GetVersionEx interception and returns the version details specified at the command line:

Output from a Detours API interception

For those interested, you can download the complete sample source code from here.


Saturday, December 22, 2007 #

The book is a must have for every serious Windows developer!


Sunday, December 16, 2007 #

For one of my pet projects I am writing, I was contemplating how to integrate Windows Live Authentication with my standalone application, similar to Windows Live Messenger. Turns out, it is really easy! Below are the three steps that were needed for the integration:

  1. Download the Windows Live Client SDK from here and install it.
  2. Create a new project and add reference to Microsoft.WindowsLive.Id.Client assembly
  3. Write code similar to the one below:
using System;
using Microsoft.WindowsLive.Id.Client;

namespace WLAuthenticate
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            // Attempt user authentication
            Console.WriteLine("Enter your passport email address: ");
            string strPassportEmail = Console.ReadLine();
            if (String.IsNullOrEmpty(strPassportEmail))
            {
                Console.WriteLine("Enter valid address!");
                return;
            }

            // Got the details - attempt to authenticate
            IdentityManager idMgr = null;
            Identity curID = null;

            // Create the identity manager
            idMgr = IdentityManager.CreateInstance("OrganizationName;name@company.com;ClientAuthSample",
                "Windows Live Client Authentication Sample App");

            // and now create the user's identity from it..
            curID = idMgr.CreateIdentity(strPassportEmail);
            bool fAuthenticated = false;

            if (curID != null)
            {
                if (curID.SavedCredentials == CredentialType.UserNameAndPassword)
                {
                    // the credentials are persisted in local store and we can authenticate
                    fAuthenticated = curID.Authenticate(AuthenticationType.Silent);
                }
                else
                {
                    // Credentials not available locally, so show the signin dialog...
                    curID = idMgr.CreateIdentity();

                    // This will prompt for credentials to authenticate...
                    fAuthenticated = curID.Authenticate();
                }

                if (fAuthenticated)
                {
                    Console.WriteLine("Authenticated with Windows Live!");
                    Console.WriteLine("Your username is {0}", curID.UserName);
                    
                    // Close the authentication
                    curID.CloseIdentityHandle();
                }
            }
            
        }
    }
}

Easy, isn't it :) ?

The only thing to be kept in mind is that if the passport authentication details are not persisted on the machine where authentication is attempted, then you will need to invoke Identity.Authenticate method without any arguments. This overload uses COM subsystem to display the Windows Live signin dialog to attempt authentication and requires the calling thread to be in STA mode and thus, tagged with STAThread attribute. Hence, I have set this attribute to the Main method above. Not setting this attribute will result in a ThreadStateException being raised.


Saturday, December 15, 2007 #

One always strives to write exception safe application but there are times when an exception can go unhandled.

In the .NET Framework, the AppDomain class exposes the UnhandledException event that can be used by by the managed application to know when an exception has gone unhandled. In the writeup, AppDomains and Unhandled Exception Notifications, I discuss the specifics of when and how this notification is made, what is the relationship between the thread that had unhandled exception and the AppDomain(s) for which this notification will be done and what should be done during the notification callback.

The source code for the article can be downloaded from here.


Sunday, 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


Thursday, 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);
        }
    }
}

Thursday, March 01, 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);
}

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


Monday, 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


Tuesday, February 13, 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.

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


Wednesday, July 04, 2007 #

Last week I updated PocketMaps to support GPS. Once the GPS receiver is connected to your Windows Mobile device, PocketMaps can:

  • Map your current location on the map
  • Auto-refresh the map as you move to plot your move
  • Display details regarding your current location, like altitude, wind speed, etc.

You can download it from http://www.wintoolzone.com/ListDotNET.aspx?Listtype=1. Below are some screenshots:

Displaying current location's details

Support for GPS - mapping current location, autorefresh to plot your move, etc.


Monday, June 25, 2007 #

I just finished authoring PocketMaps, a .NET CF 2.0 based application for Windows Mobile 5.0 based Pocket PC devices that does address mapping on the device using the Yahoo! Map Image API. You can enter the address as free text, or with city/state/zipcode details or as latitude/longitude combination and PocketMaps will map it for you. Particularly useful when you are on the move and want to know the location of an address. It also lets you save the map image that you can send via email/bluetooth, etc.

Below are some screenshots of the application:

PocketMaps  in the Programs Folder

 

An address mapped by PocketMaps

Support for zooming in/out on the map.

It's free for download and use - download it from http://www.wintoolzone.com/ListDotNET.aspx?Listtype=1.


Saturday, June 09, 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;
} 

Sunday, 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.


Thursday, January 05, 2006 #

[Original Post Date: 9th November 2005]
 
Windows Communication Foundation, formerly codenamed Indigo, is the future of Microsoft distributed computing platform. And to take it to the next level in India, we are having Windows Communication Foundation (WCF) Tour across the month of November. The dates are as below:
 
City
Date
Bangalore
10th November
Pune
15th November
Chennai
17th November
Hyderabad
22nd November
 
In this tour, we will enable the attendee to understand WCF, its relation with service orientation and Microsoft's distributed communication platform commitment and its roadmap. It will help understand the technology better, its interoperability aspects and also understand the best practices to be undertaken today for a smoother migration from existing technologies (ASMX, Remoting, ES, MSMQ) to WCF.

For more details and registration, visit
http://www.microsoft.com/india/msdn/events/.

Thursday, March 29, 2007 #

[Originally posted on 5th June 2006]

I just finished off with TechED 2006 India at Delhi and had sometime at hand today before TechED starts at Pune tomorrow. So, I thought about writing an application I had been waiting to develop.

There are times when we forget our phones at home. However, we continue to get SMS and phone calls on our device while we are at a totally different location. Would it not be great if our phone could email us details of the SMS received and phone calls we missed?

Download NotifyOnEmail which will do just that. It is for PocketPC and requires Windows Mobile 5.0 and .NET Compact Framework 2.0. Screenshot is below:


[Originally posted on 10th July 2006]

WinToolZone.Bluetooth now has authentication support. You can use a BluetoothDevice object (which is used represent a Bluetooth device that has been detected) and use the SendPassKey method to send a pass key for authentication:

.
   1:  bth.Devices[ i ].SendPassKey("123", null);


Also, I have added OnIncomingAuthenticationRequest event handler against a BluetoothDevice object that can be used to setup an event handler, which will be invoked when the Bluetooth device sends an authentication request to the machine running WinToolZone.Bluetooth:

.
   1:  bth.Devices[ i ].OnIncomingAuthenticationRequest += new 
   2:  BluetoothDevice.IncomingAuthenticationRequestHandler(
   3:  Program_OnIncomingAuthenticationRequest);

 

The event handler is implemented as shown below:

.
   1:   static void Program_OnIncomingAuthenticationRequest(
   2:                 BluetoothDevice refDeviceRequestingAuthentication)
   3:   {
   4:    Console.WriteLine("{0} is requesting me to send pass key.", 
   5:      refDeviceRequestingAuthentication.Name);
   6:    
   7:    bool bSentResponse = 
   8:    refDeviceRequestingAuthentication.SendAuthenticationResponse("123", null);
   9:    Console.WriteLine("Sent response: {0}",bSentResponse.ToString());
  10:   }

 

The handler gets as an argument the BluetoothDevice instance representing the device that sent the authentication request. To send the pass key back as part of completing the incoming authentication process, SendAuthenticationResponse method of BluetoothDevice is used.

For a partnership/bonding that has been established with a Bluetooth device, DeleteDeviceAuthentication method has been introduced that should be invoked against the BluetoothDevice instance representing the partnered device to break the partnership.


[Originally posted on 6th July 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:

.
   1:  Bluetooth bth = new Bluetooth();
   2:              
   3:      // EnumRadios(bth);
   4:   
   5:      if (bth.RefreshDevices(false, true, true, true, true, null) == false)
   6:      {
   7:           Console.WriteLine("Unable to enum devices");
   8:           return;
   9:      }
  10:   
  11:      foreach (BluetoothDevice device in bth.Devices)
  12:      {
  13:           Console.WriteLine("Devicename: {0}", device.Name);
  14:           Console.WriteLine("LastSeen: {0}", device.LastSeen.ToString());
  15:           Console.WriteLine("LastUsed: {0}", device.LastUsed.ToString());
  16:           Console.WriteLine("Connected: {0}", device.IsConnected.ToString());
  17:           Console.WriteLine("Remembered: {0}", device.IsRemembered.ToString());
  18:           Console.WriteLine("Authenticated: {0}", device.IsAuthenticated.ToString());
  19:           Console.WriteLine("DeviceClass: {0}", device.DeviceClassID);
  20:           Console.WriteLine("Address: {0}\n", device.Address.ToString());
  21:                  
  22:      }

And below is an output screenshot:

Bluetooth device enumeration output using WinToolZone.Bluetooth

[Originally posted on 5th July 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:

.
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Text;
   4:  using WinToolZone;
   5:   
   6:  namespace BTHCSClient
   7:  {
   8:      class Program
   9:      {
  10:          static void Main(string[] args)
  11:          {
  12:              Bluetooth bth = new Bluetooth();
  13:              if (bth.RefreshRadios())
  14:              {
  15:                  foreach (BluetoothRadio radio in bth.Radios)
  16:                  {
  17:                      Console.WriteLine("RadioName: {0}", radio.Name);
  18:                      Console.WriteLine("Address: {0}", radio.Address.ToString());
  19:                      Console.WriteLine("ManuID: {0}", radio.ManufacturerID);
  20:                      Console.WriteLine("LMPSubversion: {0}", radio.LMPSubversion);
  21:                      Console.WriteLine("DeviceClass: {0}", radio.DeviceClass);
  22:                  }
  23:              }
  24:              else
  25:              {
  26:                  Console.WriteLine("Unable to enumerate BTH radios");
  27:              }
  28:          }
  29:      }
  30:  }

[Originally posted on 31st July 2006]

 

Ever wanted to compose SMS from the ease of desktop instead of the phone? Wanted to be notified on the desktop, while you are working, when a SMS is received and reply to it from there itself?


DesktopSMS, for Windows Mobile 5.0 based SmartPhone and PocketPC devices, will let you do just that! Based upon .NET Framework 2.0, .NET Compact Framework 2.0 and Windows Mobile 5.0, it allows you to compose, receive and reply to SMS while the phone is connected to your machine via ActiveSync. Below are some screenshots of the same:


Main window to send SMS

Likewise, when a SMS is received, a popup comes on your screen that will allow you to reply as well:

Popup on message receipt

You can even select recepients from Microsoft Outlook's Contact folder as message receipient, provided they have mobile phone number specified. It comes with complete documentation and installer.

Download DesktopSMS from http://www.wintoolzone.com/showpage.aspx?url=listdotnet.aspx?Listtype=1


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


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);
}