Cool, but what is an IRP?

February 12th, 2007 - Fernando Roberto

My friend Slug, has just read the title of my last post, he laughed and said that most people who read this would ask, “What is an IRP?” Well, thinking about what he said and taking into consideration the a non-simplified explanation DDK reference offers us, I will write a superficial description about IRP, rid my conscience of this weight and be able to sleep again.

Let’s leave the frightening and horrifying DDK diagrams aside to try to see things in a somewhat simpler way. After that, you may refer to the sacred documentation to reinforce the concepts and take any questions about something you have already known what it is, or at least imagined.

Let’s rely on a very practical example. The File Systems drivers for example, NTFS and FAT are implemented as kernel drivers which are called File System Drivers. I imagine that many of you have had the opportunity to open and write to a file.

To start talking to a driver, which we initially make a connection with it, that is done using the CreateFile() function. Contrary to it seems, this function is not restricted to file creation, indeed, the fact of opening a file is a specific way to open the connection to the File System driver (Details about this the next time). The CreateFile function will return to us a handle which will be used to interact with the driver through functions such as ReadFile(), WriteFile() and DeviceIoControl(). By the way, they are not restricted to file operations. When an application calls ReadFile() function, the Win32 subsystem forwards this request to NtReadFile() native API, which in turn, makes the transition to Kernel-Mode and invokes the IoManager, which also in turn, will marshal the request parameters in a structure called IRP (I/O Request Packet).

IoManager sends this packet to the responsible driver, passing through the filters that might be installed on it. An anti-virus driver is a perfect example about the scenario we’re talking about. Anti-virus drivers are implemented as File System Filters. When some application writes to a file, the write IRP gets into the anti-virus before it reaches the File System driver, giving it the opportunity that it needs to check if what is being written contains any known virus signature. For a reading request, the IRP passes through the anti-virus, which installs a CompletionRoutine on it, and thus, it gains access to the IRP’s data when the reading is finished by the target driver.

The IRP is basically divided into two parts, the Header and the Stack Locations. In the IRP Header there is general information, such as status, a pointer to the thread to which the IRP belongs to, user’s buffer addresses, this IRP’s cancellation routine address and so on. In the Stack Locations there are specific request parameters. In case of a file reading, there will be the offset, size and buffer alignment.

Several Stack Locations might exist within an IRP. One for each device belonging to the chain of layers that follow until the IRP reaches the target driver. In other words, there is a Stack Location for the target driver and an additional one for each filter driver installed on it. As the IRP goes down the layers, each driver passes the received parameters from its Stack Location to the one belonging to the next driver using theIoCopyCurrentIrpStackLocationToNext() routine. Once copied, the filter can make the desired changes. If there are no changes being made in the parameters from one layer to another, then the IoSkipCurrentIrpStackLocation() routine you can be used.

The IRPs are going from one layer to another when the filter that received it forwards it to the device in which it is attached, using the IoCallDriver() function. When the IRP gets into the target driver, the driver has basically two options. If the request can be answered immediately, the driver does the desired action and completes the IRP using IoCompleteRequest() routine. But if drivers need to communicate to a device, or even to another driver, the IRP is placed in a queue, it is marked as pending and it will only be finalized when all processing is done.

Returning to our example, when a File System driver receives an writing IRP and depending on many other circumstances, the driver sets the current IRP as pending and creates a new IRP for a volume device representing the partitions, which in turn passes the requests to storage devices. Thus, it is easy to understand that disk drivers know nothing about NTFS or FAT. Storage drivers may have additional storage filters, such as a RAID for disk mirroring among other things. These new IRPs are also created by the IoManager and the whole cycle is redone for each new request.

Watching IRPs

IrpTracker is a tool capable of monitoring IRP’s activities for a particular driver or device. See the figure below where I’m selecting all the devices from Kbdclass driver, which are responsible for reading the keyboard. Notice that my machine has many keyboards. That’s because I’ve been working on anti-key-logger solutions. Selecting all these devices will be easy seeing the IRP’s activities to get the keys you press on the keyboard.

For each key you hit on the keyboard, four lines are issued on the IrpTracker. Each strike key represents two movements, the descent of the key and its release. Each movement is taken with an IRP, which comes with its Completion that means, a line is identified as Call and the other as Comp, representing, respectively, the going IRP and its return. Notice that in this example, the line Comp always comes before the line Call.

Does this mean that the IRP had its completion before being sent to the keyboard driver?

Indeed, the IRP responsible for reading the keyboard gets pended until a key is received. Thus, the system sends an IRP to the driver which waits keyboard events. When this event occurs, the driver receives the key, completes the IRP and the system receives its completion. Soon after, the system launches a new IRP to wait for the next event. Thus, we will always see pair lines, these being the previous Comp IRP and the Call for the next IRP.

If you double click one of these lines, you can see the details of each field in the IRP as shown in the figure below.

I am preparing an evolution driver of Useless.sys, which was used as a starting point in a previous post. The changes will allow it not to be so Useless and be able to demonstrate  the IRPs handling in practice, but it will be for another time.

See you there…

Who owns this IRP? (Process ID)

February 5th, 2007 - Fernando Roberto

There are cases that you need to know which process have launched a given IRP. This is very common in Firewalls or other security programs, which intercept  I/O operations to check in their databases whether a certain process has or not access to a particular resource or service. But how can I know which process an IRP belongs to?

Well, I can start thinking it’s very easy to do. As we know, IoManager gives us the IRPs in the process context that made the request. Thus, knowing the API PsGetCurrentProcessId() we can get the process ID that launched the IRP. See how simple it is:

***     OnDispatchProc
**      A generic name that tells absolutely nothing...
NTSTATUS OnDispatchProc(PDEVICE_OBJECT pDeviceObject,
                        PIRP           pIrp)
    //-f--> I'm thinking it is easy, don't copy.
    HANDLE hProcessID;
    //-f--> Get the current process ID.
    hProcessID = PsGetCurrentProcessId();

Can you see how simple it is to think that everything is right and even being mistaken?

In fact, IoManager delivers the IRPs in the process context of which is doing the I/O. However, what if a third filter got attached to your driver? Yes, it is possible, and when these drivers receive these IRPs, it is not guaranteed that they will transfer them to our driver at the same process context. Suppose we write a driver for a device:

  • An application asks a write operation to the device.
  • IoManager creates and sends the IRP to our driver.
  • A filter attached to our device receives the IRP.
  • The filter performs an asynchronous task, possibly using ExQueueWorkItem().
  • While this task has not being ended up, the filter will mark the IRP as pending and return STATUS_PENDING.
  • The asynchronous operation, in this case, is performed by a system thread and at the end of the task, the filter forwards the IRP to the driver below it that in case, it is our driver.
  • Our driver then receives the IRP in the system context and not in the process context that originated the IRP.

When the filter keeps the IRP pending and returns from the Dispatch function, the thread that originated the IRP goes ahead and will perform other tasks. The original thread can still return to the process that started the whole operation in case the OVERLAPPED structures were used when calling the driver.

The IRP will now be executed in the process context that made a call to IoCallDriver passing the IRP that was pending as a parameter. In our example, the process that will do this is the System process. Using the code above, we obtain the System PID in place of the PID of the process that actually initiated the IRP.

To properly obtain the information we’re looking for, we’ll have to stroll a bit bigger. When every IRP is created, it enters the pending IRP list of the thread that created it. To get this thread from the IRP pointer, we use the field pIrp->Tail.Overlay.Thread. This field has a pointer to the ETHREAD structure, which refers to the thread that created this IRP. To get the process from the thread, we can use the IoThreadToProcess() API. See the excerpt below.

***     OnDispatchProc
**      A generic name that tells absolutely nothing...      
NTSTATUS OnDispatchProc(PDEVICE_OBJECT pDeviceObject,
                        PIRP           pIrp)
    PEPROCESS   pEProcess;
    PETHREAD    pEThread;
    //-f--> Here we get the thread pointer.
    //      The one responsible for creating this IRP.
    pEThread = pIrp->Tail.Overlay.Thread;
    //-f--> Now we get the process that owns
    //      this thread.
    pEProcess = IoThreadToProcess(pEThread);

Okay, see that wonder. Now you have in your hands EPROCESS structure, that according to Microsoft documentation it is an opaque structure used internally by the operating system.

“The EPROCESS structure is an opaque data structure used internally by the operating system.”

Now what can I do with this?

Although I’m sure you’ve thought of something I could do with this structure, I have a better suggestion, and why not saying much more appropriate? Even because there might have children reading this. Despite EPROCESS mean nothing, it can still bring us some useful information. We can get the handle of the process identified by this structure and thus, get additional information from it, such as its PID. See the example below.

//-f--> ZwQueryInformationProcess from
//      Windows NT/2000 Native API Reference
//      ISBN-10: 1578701996 
//      ISBN-13: 978-1578701995
    IN  HANDLE            ProcessHandle,
    IN  PROCESSINFOCLASS  ProcessInformationClass,
    OUT PVOID             ProcessInformation,
    IN  ULONG             ProcessInformationLength,
    OUT PULONG            ReturnLength OPTIONAL
***     MyGetProcessID
**      Get the process ID from its EPROCESS structure.
**      Please, use your imagination to create a better name
**      for this routine.
MyGetProcessID(IN  PEPROCESS    pEProcess,
               OUT PHANDLE      phProcessId)
    NTSTATUS                    nts = STATUS_SUCCESS;
    HANDLE                      hProcess = NULL;
    ULONG                       ulSize;
    //-f--> Zw routines are usually called
    //      from User-Mode, so to call them
    //      from Kernel, we'll need, at least,
    //      to be at PASSIVE_LEVEL.
    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
        //-f--> Initialize the output parameter.
        *phProcessId = 0;
        //-f--> Now we get the handle of the process
        //      identified by this EPROCESS pointer.
        nts = ObOpenObjectByPointer(pEProcess,
        if (!NT_SUCCESS(nts))
        //-f--> To use non-documented API, it is enough to
        //      declare its prototype as it was made in the
        //      beginning os this example
        nts = ZwQueryInformationProcess(hProcess,
        if (NT_SUCCESS(nts))
        //-f--> Everybody is alive so far; now just set the output
        //      parameter with the correct information.
        *phProcessId = (HANDLE)ProcessInfo.UniqueProcessId;
        //-f--> Ops... Something got wrong!
        nts = GetExceptionCode();
    //-f--> Release the process handle that we got.
    //      In this way, your manager will not want to kill you
    //      when, although the processes have finished,
    //      there will still be EPROCESS structures spread in RAM.
    if (hProcess)
    //-f--> And all lived happily ever after.
    //      (including your manager)
    return nts;

You can get extensive information from the process handle. There are even ways to get the full process Path from its handle, but let’s leave that game to the next post.

See you… 🙂

Prog2Svc – A jobless service

February 2nd, 2007 - Fernando Roberto

Nowadays, although contradictory it may seem, creating a service does not require much work. A few clicks on a Visual Studio 2005 Wizard and just it, we will have an application capable of providing ATL COM interfaces and which is indeed a Windows service. In this post, I will talk about a little tool that I’m offering as a toast to those who have the patience to read this Blog.

At the first company I worked for as a programmer, about 11 years ago, I was responsible for maintaining Provectus’s software’s data collector communication network. At first, an MFC program was responsible for interacting with the driver that controls the SS140 board, which was the interface that the PC had to be part of this data collector network. Once the program had stabilized, we modified the software to make it a Windows service.

But what is a Service?

A service is an executable module, which is registered to be executed on the system even if nobody logs on to Windows. Today, many applications and Windows components are implemented as services. A service is not only a common executable registered to get started automatically. A service must provide an interface CallBack routines for the system, in order to respond to commands that start, stop and stay of execution. This interface is not a COM interface as some of you might have guessed. Take a look at the StartServiceCtrlDispatcher function to get an idea of the interface type I am referring to. This is just one of the necessary functions to build a service. Take a walk by reference for details on how to implement a service from the scratch. Services typically run on system account, but it may optionally use a given user account. More details about services, on the MSDN site.

Back to the ’90s, then we needed to make the Supervisor, one of our major programs at Provectus work as a service. Supervisor was a giant program built in Visual Basic 4.0. It was responsible for receiving commands from collector network, and regarding to them, execute Stored Procedures in SQL Server. Visual Basic 4.0 didn’t implement the AddressOf operator, which appeared only in version 5.0. This operator can be used to obtain the pointer to functions written in VB. This allowed such programs registering CallBack routines in the system. Anyway, with this operator, a few pounds of patience and a gun over your head, you could build a service in Visual Basic. We thought about the possibility of rewriting the entire Supervisor in C, so we could then turn it into a service. But luckily someone had an outbreak of sanity and said:

“Why do not you write an empty service that simply calls the Supervisor?”

Yeah, this really works perfectly! This need of having a program behaving as a service is more common than you think, especially when we are talking about business environments. It didn’t take long to some tools that made this possible appear, but nothing prevents me from having my own version.

Prog2Svc program is a service that does right that. Running this program without any parameters, you will receive the message below, which tells what the possible parameters are to be used.

Thus, to register the Windows calculator as a service, we use the following command line. Remember that this is an operation that requires administrative rights, so in the case of Windows Vista, this command should be run from a Command Prompt that was started as an administrator.

Prog2Svc -add Calculadora c:\Windows\System32\calc.exe

After the message of success has been shown, you can already see your new service through the Windows Service Manager. To access the service manager, type “services.msc” without the quotes in the Run… window.

You can start your service either using service manager or using the good old command “net start calculadora” in the Run… window.

When we start the service, we have no sign that it is really working. That’s because calc.exe was executed on another Desktop, but we can confirm its execution using Process Explorer.

The additional -interactive parameter can make your new service interaction with the DesktopNote: Windows Vista deserves special attention here. The -auto parameter sets the service automatic to start when the system is turned on. Finally, the –silent parameter makes the installation being silently done. That is, no success or error message will be displayed. Note: In this case, the success or failure can be verified by the Prog2Svc exit code. Another possibility is the use of environment variables in application path that will run. See this example more completely.

Prog2Svc -add -silent -auto BlocoDeNotas %SystemRoot%\System32\notepad.exe

Removing the service is very simple. See example below. Note that to remove services, we can also count on the silent mode.

Prog2Svc -remove Calculadora
Prog2Svc -remove -silent BlocoDeNotas

How does pseudo-service finishes?

When we ask to stop the service, Prog2Svc program receives a notification via CallBack routine. In that time, we could do a flying kick in the process’s chest, but this wouldn’t be good manners. A routine identifies the process created main window and sends a WM_CLOSE message to this window. After that, 30 seconds are expected for the process to have the opportunity to finish their tasks and deallocate system resources. If this time expires and the process is still running, well, it’s like my friend Thiago always says: “Only violence builds” and the process will be dropped out via TerminateProcess().

If you cannot still imagine how this tool might be useful, think you could create a service that runs the Command Prompt, and thus, you will have a shell running on system account. This would help you to test and find out what you could do with this account privilege.

Prog2Svc -add -interactive SysCmd %SystemRoot%\System32\cmd.exe

To install this program, just put a copy of this executable at the System32 directory. Technically, you could put it into any directory, but remember that the folder where it will be should be accessible by a system account. So, do not put it into directories like “My Documents” or any other personal folder.

As we know that the Internet is not the safest place to get an executable, make sure the program you are downloading has a valid signature.

Have fun!

  • Version:
  • Windows: 2000, XP, 2003, Vista

Prog2Svc.exe – x86 (58.7 KB)
Prog2Svc.exe – x64 (59.2 KB)
Prog2Svc.exe – IA64 (113 KB)

Step into Kernel (SoftIce)

December 23rd, 2006 - Fernando Roberto

Finally back from vacation. It has been nearly six years that I did not take vacations. Traveling, visiting new places and just relaxing were my main tasks during these last 20 days. Back to work, I’ve just arrived at the company and I was amazed by it. I could not believe they sent that old one away. We exchanged glances and obviously I got butterflies in my stomach. I got close enough to be able to smell it. I looked up and down. Simply perfect and it was an injustice to leave it alone. It didn’t take long and it was under my control. I had to prove everything it had to offer. After all, there were so many choices: Coffee, cappuccino, chocolate, tea with or without sugar. But it was all an illusion. “Oh my… that’s was a horrible coffee.” My friends, appearances can be deceiving. How can so beautiful machine make so bad coffee? I confess I miss the old machine. I didn’t mean that coffee was not so good, because the coffee was really horrible! Now I’m looking for alternative ways to keep my addiction. Perhaps there are caffeine patches to sell out there.

Don’t worry, this will no longer be an “Off Topic” post about changing coffee machines and the impact caused by them. In this post, which I had started last year and have just finished it now, I’ll take the steps needed to use SoftICE system debugger.

I still was new in SCUA and I was developing a GINA for our security product. For those who do not know, Gina is one small screen that appears during the Logon in NT platform. GINA is a DLL that is loaded by winlogon.exe process, which has the function of making the user’s interface to perform the login in the computer. The Msgina.dll GINA is the original one, but we can build our own GINA to provide alternative ways of authentication. A practical example of this is the product True Finger sold by SCUA. This product changes the system’s GINA, so that, with a biometric sensor help, it makes the system ask for the user’s fingerprint to logon the system. Debug GINA requires a few atypical steps, since to test it is necessary to do Logon, Logoff and things like that. You can also debug it using the Visual Studio Remote Debug, but at that time, debugging GINA was the need I had to learn how to use SoftICE.

There were two development teams, one for Kernel drivers and the other for applications. I still worked on application staff when in a meeting area, the team introduced me to SoftICE as an alternative to solve the problems about Kernel Debug I was facing. I was using techniques such as log files and MessageBox to debug GINA. You can imagine the MessageBox with the typical messages as “I called the X routine”, “Returning from Y routine.” After I learned how to use SoftICE, it solved many things for me. Specially since other Ginas had to be developed and as, the time passed by, I started to develop kernel drivers.

Most of the application team had a panicked about using SoftICE. A situation very similar to that described in my previous post. They said: “Oh no, using SoftICE is too complicated. I will continue with the MessageBox. If I cannot solve this, then I will use a Kernel Debugger.” I think it was just about getting used to it, SoftICE is not a rocket science and nor difficult to use. I found it amusing when one part of the team was caught trying to solve a particular problem, that kind of strange bug that nobody could find. I went around and asked: “Why don’t you just use SoftICE?”, “No, no, I guess it is not necessary.” they said. Later I also was called to help tracing the problem, and in most of the time I could, I’d picked up the problem that they’d chased for days in half an hour of Debug. I’m not saying I’m super Debug genius, or that they were technically incompetent. I’m saying that it is only a matter of using the right tool. You could dig a tunnel with a teaspoon, but with a shovel things would be much easier.

SoftICE is part of a development package called Driver Studio, which was sold by Compuware. For those who still do not know, Compuware has discontinued SoftICE and we cannot count on a version of this tool for Windows Vista. With SoftICE is possible to debug the kernel using only one machine, but the product still has the resources to do remote debug via serial ports or network adapters. Thus, they are also adopted the names Host for the machine that does the Debug and Target for the machine that will suffer the Debug (Similar to WinDbg). Here we will adopt the Host name for identifying the machine where we have the compiler and the installation type Host SoftICE. We will not do any remote debug on this post.

Very briefly, we can say that SoftICE works as it follows. At the Host machine, it is necessary to create a symbol file known as NMS. This file is copied along with the driver to be tested to the Target machine. In it, we load the symbols and start debugging the driver. We will describe these steps in more details next.

Installing the Host Machine

Installing SoftICE on the development machine is necessary for us to generate the NMS file. Don’t worry; you will not test your driver on your development machine. At least not while you’re sane. During the setup process, you will pass through the typical setup screens until you reach the screen shown above where you select installation type you want. Because we use only installation Host portion, select that option and skip to the next screen. Select only the option “SoftICE Host Components”, so that it appears on screen as below. The remainder of this process is next, next…

Installing the Target Machine

We will use the test machine in a way that it is not necessary to have two machines to do the debug, and so we will explore this feature that is usually used. To do this, select the “Full Instalation” in the first screen, then select only “SoftICE Host Components” items and “SoftICE Target Components” as it is shown below.

In this case, at the end of the register and file copy process, we will have to set some debugger properties. The first group of settings refers to initialization. We will select the Manual startup at this moment. All these settings can be changed after the product is installed. The setup screen should be as shown below.

The next group will be about general settings. In this item, we will change the field “Initialization” to stay with the configuration shown below. These are commands that are executed when the debugger is started. Each command is separated by a semicolon. These commands will make the following changes:

  • LINES 60; Change the total amount of lines to 60
  • WC 30; Change code window size to 30 lines
  • WL 10; Change local variable window size to 10 lines
  • X; And finally, the command that starts the system normal execution

The lack of “X” command will cause the system to become paralyzed at debugger startup time. This gives us the opportunity to put initial breakpoints and later we will be able to continue with the system execution by pressing F5, which is the hot-key for “X” command.

Now let’s set the video configuration. Right now you can ask me: “What do you mean by video configuration? Doesn’t Windows implement an abstraction layer called GDI?”

SoftICE is a system Kernel debugger. GDI is part of the system. How would you debug a video driver if the debugger itself utilizes this driver? The debugger should influence the debugged system as little as possible. It is for this reason that WinDbg need a serial cable and another whole machine to make the Kernel Debug possible. Similarly, SoftICE, once loaded, cannot use any system resource. This includes video drivers, disk, keyboard, mouse and so on. For the SoftICE being able to have a place in the video while debugging the system, it accesses the video memory directly and draws manually its entire interface. That’s why we have to configure the video.

This configuration can be chosen between two main options. The first is the “Universal Video Driver”, where the interface will appear in a window. This “window” is actually the result of writing in video memory that gives the impression of a window. This is not the type of window you’re used to seeing and drag with the mouse or even suffer the action of ALT + TAB. Remember, when SoftICE displays its user interface, the whole system is frozen. The other option is “Full screen”, where SoftICE switches the video to text mode to display its interface.

If you are installing SoftICE on a virtual machine, some steps are required:

  • Do not install tools such as video acceleration like VmTools.
  • Use the standard VGA driver in Windows and configure it so that, it is 640×480 with 16 colors. (Disgusting but necessary)
  • Select the “Full Screen” option in SoftICE.

If these steps are not followed, the machine will freeze when asked, but the debugger screen will not appear. Assuming that we are installing on a real machine, select the video option as shown below.

The remaining is next, next…

Generating the NMS File

On the Host machine, after compiling your driver (if you still don’t know how to do it, read this other post), you must now run the application “SoftICE Symbol Loader” that was already installed. This application does the symbol translation and generates the NMS file. Select Open… from the File menu and point out the driver you will debug. Once opened, the program must place the driver loaded name at the window title. I have numbered the three buttons you need for this operation.

  • Make sure that the second button is pressed. This will make any driver source code be appended to the resulting NMS.
  • Also make sure that the “3” button is released. This will prevent the program for asking for sources that it cannot find.
  • Click on “1” button that will do the symbol translation and the program will generate NMS file at the local directory.

Starting SoftICE

After installing your driver as usual in the Target machine, we will be ready to start the Debug of our driver. Remember that both our sample driver and SoftICE are configured to start manually. To start SoftICE, you can click the “Start SoftICE” icon that was installed in your Start menu or simply run the command “net start ntice” in the “Run…” window. To make sure that the debugger has loaded, press CTRL + D so that the system freezes and the screen is shown as the one below.

No, this is not a CRASH DUMP of your video card that has just exploded. Gentlemen, I am pleased to introduce you the SoftICE. Now can you understand the application staff panic? Don’t worry, it’s ugly but it doesn’t bite you. Pressing F5, the system returns to normal execution.

Now we have to load the NMS file into the debugger. This is easily done simply by double-clicking the NMA file. This file can be in any directory on the machine. The only time that this file is used is when you load it in the debugger. To verify whether the file was successfully loaded by SoftICE, use the “table” command that lists all loaded symbol tables. Several tables can be loaded simultaneously, but only one is active at a time. The “file *” command lists all files of a given table. To open a specific file, enter the file name in front of the command. See example below.

With the file already opened in the code window, press ALT + C to put the cursor into the source code. If this key sequence is not working, press ESC and then ALT + C. Note that you can only walk with the cursor up and down. Attempts to move the cursor sideways causes the command window to gain focus again. Place the cursor on the line you want to insert the breakpoint and press F9. At this time, the line was highlighted as shown in the picture below.

Now let’s press F5 to let the system return to normal operation. At the moment the driver starts, our breakpoint will interrupt this action and the SoftICE interface will be displayed. The highlighted line shows what the next instruction to be executed. Pressing ALT + L, the local variables window gains focus. You can navigate among the variables by moving the cursor up and down. Press ENTER key on the structures that begin with “+”, so that they are expanded. The image below shows register window and then, the local variable window.

I will leave a small table of commands here, but the full reference is in “SoftICE Command Reference” PDF file.

  • F5 : Run
  • F9 : Breakpoint
  • F8 : Step into
  • F10 : Step over
  • F12 : Step out
  • F7 : Run to cursor
  • WL : Local variable window
  • WW : Watch window
  • WD : Memory window
  • F3 : Swap among C source/Assembly/Mixed

Obviously there are numerous details and technical use, but let’s leave that to the documentations that coming with the product.

Wow, what a long post! You thought it would be easy, didn’t you? Until the next time …

Wow!! DDKBuild out of Vista

December 12th, 2006 - Fernando Roberto

About a year ago, I was reading the Windows Internals when I came in the chapter about Wow64, so I thought to myself: “Oh my… That’s a sort of thing that will bring us some issues.”

This week I’ve installed a Vista x64 copy on my computer to do some tests and I attempted to anticipate the problems I would have when it would be released. I almost had no problems. Actually, I had to configure some shortcuts to certain programs with compatibility mode set to Windows XP SP2. This is because these programs showed the message: “This program is not compatible with Windows 6.0”

After installing the Visual Studio 2005, DDK do Windows 2003 Server and DDKBuild, everything was working fine. A project was created, compiled and debugged in Visual Studio without problems. I also compiled a DDK example from the command line and also everything was OK. But at the time I was compiling one of the examples that I’ve already made available at the site using DDKBuild, I got the following error message:

'ddkbuild' is not recognized as an internal or external command

Executing the DDKBuild in a command prompt, it worked fine, but same error was always showing at the Visual Studio. After pooling out some hair, I tried to open the file DDKBuild.cmd from Visual Studio, that is, by selecting Open… from File menu and so on. When I got into the System32 directory, I saw that the file I was looking for was not there as it should be, at least, not for Visual Studio.

It took some time, but the penny dropped. Visual Studio is a 32 bit process and fell in the Wow64 (Windows-on-Windows 64) rules for File System redirection. For those who do not know, to maintain compatibility with the past, 64-bit platforms still use the directory C: \Windows\System32 folder to put the system DLLs, even though they were 64-bits.

But what happens with 32-bit system DLLs? Thirty-two bit processes still need to load these DLLs. When a 32-bit process tries to access the C:\Windows\System32 directory, the access is redirected by Wow64 to C:\Windows\SysWow64  (C:\Windows\System32\SysWow64 For Windows XP x64). Accesses to the registry are also reflected from 32 bits to 64 bits and vice versa. Please, refer to the MSDN site for Wow64 details.

Once the penny has dropped, it is ridiculous to solve the problem. Simply put a copy of DDKBuild.cmd in the C:\Windows\SysWow64 and everyone will live happily ever after.

Walter Oney for Managers

December 11th, 2006 - Fernando Roberto

The fact of writing a little unusual program has some consequences. Some of your friends at work, those ones who sometimes sit beside you, do not understand what you are doing (and vice versa). Others are seen whispering: “Look out! Is that guy the one who programs drivers.” This difficulty other people have to understand what we write, ends up also affecting the managers, directors and so on. Not that they were guilty of this. After all, if they were interested in the technical area at this point, probably they would not be managers, directors or whatever they are. This is not a rule, but at least it worked in companies where I have worked for; the minority of my superiors understood those problem complexities that ended up delaying a product release.

The worst case is when your manager thinks it’s simple to solve things. After all, when he programmed in COBOL, there was no problem he could not solve and you would probably be acting as a lazy guy or simply as a superstar for being able to solve blue screen problems. I particularly think it is beautiful when they ask: “But didn’t you already solve this blue screen problem?”, as there was only one problem what would result in a blue screen.

Well, so I think the recognized authority’s opinion on this could have some influence over those people’s opinions. In the first chapter of his book Programming The Microsoft Windows Driver Model (2nd Edition), Walter Oney gives some tips on how a company could consider driver development to obtain results closer to the expected. I have separated some sections that it follows below.

“The sad truth is that WDM driver programming is pretty hard, and only experienced (and expensive!) programmers are capable of doing it well.”

“Driver programming should start as soon as there is a reasonably firm specification for how the hardware will work. You should expect to modify the specification in light of unpleasant discoveries during driver development…”

“You should also expect driver programming to last longer and cost more that you initially imagine. All software is subject to time and cost overruns. Additional overruns in this kind of programming stem from communication difficulties between the hardware and software people, from ambiguity in specifications and in the DDK documentation…”

“Pay attention early on to how end users will install the driver software. Most vendors of add-on hardware prefer to ship a custom installation program on a CD-ROM, and writting the installer is a lengthy process that can consume en experienced programmer for several weeks…”

“Your driver executable will also probably include the text of messages in a special multilingual message resource, and it would be a good idea to have a trained writer compose that text. (I’m not saying your driver developer can’t do this, but he or she may not be the best choice.)”

“Finally, don’t treat your drivers as unimportant details. Having a good driver with a smooth installation is at least as important as the exterior appearance of the product… So a myopic decision to short-fund driver development could easily have a dramatic, negative effect on your bottom line for years to come. This advice is especially important for hardware manufacturers in developing countries, where managers have a tendency to look for every possible way to cut costs. I suggest that driver development is one place where cost-based decision making is inappropriate.”

Perhaps they will never read this, but for sure it will help us take a deep breath and continue programming. Now, you back to work because you are not getting paid for surfing the Internet! (This is also great) … 😀

Step into Kernel (Serial)

December 1st, 2006 - Fernando Roberto

I earned my first computer when I was 13 years-old, but seven years later, when I started my internship, I discovered that it was possible to debug programs that I used to write. Until then, my debug methods were always things like printing the variable value on screen. All right, in that time I didn’t use to develop complex programs enough to be stuck; over the time, I think I got used to working without the luxury as break-points and so on.

When I was introduced to a debugger, I even paid attention to it. I thought to myself: I can just put a printf and I’ll be OK. I don’t need all this stuff. At that time, we used the CodeView, a 16-bit debugger that runs on DOS which is displayed on the picture below.

It didn’t take long for me starting to depend on the debugger doing the simplest things, like brushing my teeth, for example. In fact, some situations, such as writing code for data collectors, writing firmware for hardware that has no display, situations in which we could not count on a serial port to see what was happening with the software, and the unforgettable situation where I had placed an oscilloscope on a particular processor pin to catch our software life signs, so, situations that we would give an arm to have a simple break-point made me realize that the debugger is really necessary.

The funny thing is that nowadays, in college, most students in my class don’t know how to debug software. I’ve tried to explain to my friends the tremendous advantage of using a debugger, but they end up having the same reaction I had years ago: “No way, Fernando, this is too complicated. Just by looking at the source code we end up finding the mistake”. So, that’s fine for me.

Well, we’re here to debug or to talk? Let us debug the driver generated by the traditional post Getting Started. This time we’ll do according to the tradition. We will need two machines, a Null Modem serial cable and last but not least, a copy of WinDbg. No, not worth reading this sentence again, you didn’t take it wrongly; you’ll really need two machines. I don’t know why some people have a certain resistance to believe in this. Well, I think we have overcome that phase and we can continue with the post.

If you do not have a copy of WinDbg, you can download it for free from the Windows Debugging Tools page at Microsoft site.

Let’s take this picture borrowed from the Windbg Help, which shows how we should set computers to do Kernel debug.

The machine named HOST is where WinDbg will run. This machine is, in most cases, the machine where the driver was developed. Let’s assume that this is the machine where the driver was developed and defer the details about how to set the symbol and source directory to another post. The machine named TARGET is where our driver is loaded by the system. The TARGET machine’s operating system don’t necessarily need to be Checked Build nor it is necessary to install any additional kit to the operating system. All you need is your driver and a serial port. All of the Windows NT platform (Windows NT, Windows 2000, Windows XP, Windows 2003 Server and Windows Vista) already bring their native debugger since its installation. Actually, this is a great feature in the use of WinDbg. Imagine that kind of problem that manifests itself on the client machine. You will not want to install anything aggressive or even that will change the scenario that would make the problem not manifest itself anymore. Believe me, this is not so rare as it seems to be. In these cases, simply enable the Debug mode on the TAGET computer and we’re done.

To enable the Debug mode in the TARGET machine, we need to edit some initialization parameters that are in the Boot.ini file located in the system root folder. This file has its attributes as system file, hidden file and also read-only. You may need to configure Windows Explorer to view these files. Using Windows Explorer, go to the root folder, remove the read-only property from the Boot.ini file, then open this file using a text editor like Notepad, for example. The contents of this file is similar to that shown below.

At Operating Systems section you will need to duplicate the referenced system line you will want to debug. Add to its end the /debugport=com1 /baudrate=115200 parameters that will configure the Debug mode. The first parameter selects the COM port being used, while the second selects communication speed. The serial protocol is not the fastest communication way between machines HOST and TARGET and in some cases is annoying having to wait for interactions between WinDbg and debugee system. There are other media that can be used if your computer does not have an available serial port or if you wish more speed and comfort during the Debug. See more details in the post Serial Killers.

The final result of our Boot.ini file should be something like shown below. I’ll skip the lines beginning that describe the operating system for better visualization putting “…” in their places.

[boot loader]
[operating systems]
multi(0)... /NoExecute=OptIn
multi(0)... /NoExecute=OptIn /debugport=com1 /baudrate=115200

After making these changes, you can save the file and restore the original file attributes on it. In Windows XP and Windows 2003, the same described steps above could be done with the help of a tool named Bootcfg.exe. In Windows Vista, the process is quite different and I will describe it in a future post.

Back on the HOST machine, start WinDbg and select Kernel Debug… from the File menu. You should see a window that sets the communication way. Make it so in a compatible way with what was set in the Boot.ini on the TARGET machine. In this case, we are using COM1 serial port and baud rate of 115200. Clicking on OK will make WinDbg opening the serial port on the HOST machine and it will wait until the TARGET machine be ready. At this point, we get the following messages in WinDbg command window .

While the HOST machine waits, make sure your driver is installed on the TARGET machine and restart it. After that, when system is starting, the system loader is  displaying the options found in the Boot.ini edited by you. Select the option which appears [debugger enabled] as shown below.

After selecting this option, the machines HOST and TARGET should connect each other and the Command window would show a text similar to that shown below.

Microsoft (R) Windows Debugger  Version 6.6.0007.5
Copyright (c) Microsoft Corporation. All rights reserved.
Opened \\.\com1
Waiting to reconnect...
Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.
Symbol search path is: *** Invalid ***
* Symbol loading may be unreliable without a symbol search path.           *
* Use .symfix to have the debugger choose a symbol path.                   *
* After setting your symbol path, use .reload to refresh symbol locations. *
Executable search path is:
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y  argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for
ntkrnlpa.exe -
Windows XP Kernel Version 2600 UP Free x86 compatible
Built by: 2600.xpsp_sp2_gdr.050301-1519
Kernel base = 0x804d7000 PsLoadedModuleList = 0x805531a0

Well, so far we know that the machines are connected. Pressing Ctrl + Break in Windbg, we will make the system freeze in the TARGET machine and the control is passed to the debugger. The debugger is ready to receive your commands when you get a command prompt KD indicated by the letters at Command window bottom left.

Just to make a simple test, type “lm” command and hit enter. This command lists the modules loaded by the system. Note that the Useless driver is not on this list yet. This happens because the driver instance is configured to have its execution started manually, so, the driver has not yet been loaded by the system. Then, select the item Open Source File… from File menu and open Useless.c file. Click on the DriverEntry function name and hit F9. Although there is no visible sign, we put a break-point on this function. The fact of having no visual change is due to the fact that our module has not been loaded yet. We can be sure that the breakpoint is installed listing the breakpoints with the “bl” command.

kd> bl
 0 e f9fb3430     0001 (0001) Useless!DriverEntry

Now we launch the “g” command that will cause the system to return to its normal execution.

Once the system is loaded, we will start the driver through the “net start Useless” command . When the driver starts, the DriverEntry entry point runs and consequently, we have its execution stopped at our breakpoint. The TARGET machine will freeze while the debugger has control over the system. Note that now our module is loaded, the breakpoints are easily identified by lines with red background color.

Well, the first steps have already been done, the commands and details on how to debug the kernel for Windows would be outside the scope of this post. But a good tip on how to obtain tons of details about this subject is the Windows 2000 Kernel Debugging book. The book is not one of my favorites; it gives a good introduction to the subject besides talking about how to use and build Debug Extensions, but does not bring the used techniques by real Kernel Debugging ninja masters. Another excellent information source on this subject is the discussion list Windows Debugger Users List dedicated to Windbg. That’s all without forgetting the Help.

This was an initial post about the subject, wait for future posts where I will give the steps about how to use Windbg with VMware and how to debug Windows Kernel with one machine using SoftIce (God rest his soul).

Have fun… 😉

Off-topic HP 50G

November 28th, 2006 - Fernando Roberto

Finally, the exam period has ended. Now I can return to normal life, reintegrate into the society and why not, write posts. For those who did not know, I’m studying computer engineering at Universidade São Judas Tadeu. Despite my thirty-years-old, I’m still in the third year due to a hectic life that a programmer is suppose to have. I’m sure many of you know exactly what I’m talking about. I had to interrupt my course several times because of lack of money or overwork. Anyway, these past few weeks I was in a rush and I could not compose a decent post. So, you will have to be glad for some funny facts about my new best friend, the HP 50G.

I usually say that a programmer is not a name of a profession, but a name of a disease.”Programmer: A person who suffers for programming”. One of the symptoms that I find most decisive for a programmer their great ability to associate different things with programming, even involuntarily. An example? Easy! When I was studying Industrial Informatics at ETE, there was a teacher who used to speak slowly, about 3 seconds among sentences. He looked like an android. I used to imagine that characteristic was due to the fact the teacher had little RAM, thus took a while to load a new sentence from the HD to be processed by the speech synthesizer. At that time, we said if we had paid attention, we could see a blinking LED in his ear during those breaks. Fortunately, it could be easily solved if there had been a second thread to put the next phrase in RAM as the current phrase was used by the main thread. I do not know what you think about it, but it seems disease for me. :-S

Studying for Computational Numerical Calculus tests and armed with a HP 50G, it was inevitable to program it to automate some steps. The exercises in this subject consist basically of arithmetic, but they are long and full of little rules. Baing a Programming carrier since the age of 13, I have downloaded the manuals and got to work. When an HP is bought, it comes with a “Quick Start” document having 120 pages; but don’t worry, you can download the complete PDF manual having 918 pages in Portuguese.

As it might be expected, I’ve found many sites and tutorials on the subject, even several in Portuguese. The site was a major contributor. On the page about programming you can find a lot of things. And the best thing, it’s all for free.

We can program the HP either in UserRPL or SystemRPL. Programming in SystemRPL gives us a performance gaining of almost 10 times higher than in UserRPL. However, everything in life has a price. The excerpt below was taken from one of the several PDFs I’ve found.

Strange! I could swear I have already read something like that somewhere.

Because I was unable to download a WinDbg version to debug my HP, I decided to program in UserRPL anyway. The language is basically composed of a sequence of keys that were pressed during normal use of the calculator, but we can still use execution blocks, repeating loops (for/while), conditional execution (if, else), sub-programs execution and many other things that I had no patience to read. It’s funny to mix things like IF and ELSE commands that do array operations as if they were as simple as adding one to one.

HP can be programmed on itself, I mean using its own keyboard. But writing on that mini keyboard is similar to play Decathlon on Atari. It works, but you know what will end up happening. Another super uncomfortable thing is trying to understand what is wrong in your program just looking at the source code (which is not indented) on a small LCD screen. One of the facilities is a USB cable that connects the HP to your PC.

To access the stored directories and variables in the calculator, you’ll have to download the software that makes this connection. But if you have an x64 machine (even HP), there will not be drivers available to make this connection. If this is your case, you can use a virtual machine that is running a 32-bit operating system. Wow! That really works!

When connected, it displays a kind of “Explorer” where you can browse the folders and edit variables and programs. With a double-click on the programs, an excellent development environment called “Notepad” opens with its program. Don’t think of indenting your program. When the program is sent to HP, it takes its own indentation, which is not obviously the same as we would like to take.

Well, at least it was interesting to learn more of this. It was really worth spending that money buying something I can program and be able to keep my addiction. But it still does not stop there. If you take a look at the quantity and variety of applications to download from, you will have an idea whatelse it can do besides calculating the matrix determinant. If you’re curious, you can download a calculating emulator on your PC and make a Test Drive.

Kernel + Visual Studio 2005

November 16th, 2006 - Fernando Roberto

Driver or low-level software developer is used to build their projects on the command line, use text editors like Notepad or Norton Editor to code their drivers. It’s like my friend Thiago says: “Knife in the teeth and blood in the eyes”. Using the command TYPE | MORE to see the compilation error files shows how superior human beings we are, technology dominants who don’t under-utilize our brains, don’t need those superfluous tools like graphical interface with syntax coloring, IntelliSence or even auto-complete. We are at the top of the food chain.

If you really believe that, then it is better you leave this post right here. Today I going to defend the use of tools that help, and much, when a driver is coded and it is needed to deal with functions with large number of parameters and endless structures.

Using or not using the Visual Studio to generate drivers is a kind of discussion that tends to be infinite, such as the use of C++ for Kernel Mode development. On the one hand, there are those ones who argue that the environment is almost never perfectly configured to compile drivers. I’ve read posts from real authorities on the subject by talking about how many days were needed to find a bug that was generated by a compiler optimization or even a bad define that was generated by the Wizard. Those who say that use Visual Studio as development environment requires a minimum knowledge of each parameter used in the call to cl.exe; that the ideal is to use the good old Build that parse files SOURCES, DIR and MAKEFILE and be quite sure about the environment set by the DDK shortcuts is correct. On the other hand, there are those ones who do not give up the convenience of having an integrated environment, the facility just about pressing a key to see the detected error file line , the use of syntax coloring, IntelliSence, auto-complete and many other advantages that Visual Studio offers.

I have been doing this for some time and I remember when the DDK started to bring the compiler embedded into the Windows XP kit. The main purpose of this change in the DDK was a trial to separate the driver development environment from application development environment. This link has already created many problems. The Windows NT 4.0 DDK was based on VC 4.2, but with the arrival of VC 5.0 and later VC 6.0, the symbol table format has been changed and WinDbg stopped working. At that time, I used to utilize SoftIce much more than WinDbg to debug drivers. I continued using the Visual Studio without even noticing this problem. I only had symbol problems when Visual Studio came on version 7.0. The VToolsD does not support the new symbol format yet. Conclusion, I still use VC 6.0 to compile VXDs. Actually, it’s not impossible to use VC 7.0 for this, but we won’t able to debug it.

Later, when we did the upgrade from VS2003 to VS2005, the most drastic changes have turned my life become a little bluer. Since this time, I started using the best of both worlds, that is, the assurance of having a properly configured environment and all the tools convenience that the VS2005 editor could offer.

How can we do it? OK, let’s use the project created in post Getting Started as a starting point. Initially we will need to download the file DDKBUILD.CMD from OSR Online and save it in a directory that would be in your machine PATH. That CMD will need the WNETBASE environment variable configured to the DDK installation base directory. This file is a way to make an external build with Visual Studio. To do this, create a Makefile project in Visual Studio as shown below.

After entering in your new project name folder, where it will be created, just click on “OK”. Even without setting up anything, click “Finish” at the next window. After creating the project, add the files in Solution Explorer. Then edit the project properties as it is shown below. Note that in the “Include Search Path” I’m assuming that DDK installation was performed in the C:\WinDDK\3790. This field has no influence over the compilation process; it just tells IntelliSence which directories should be used to serve as sources for its database.

From this point, we can build the project like a User Mode project. The images below do not require comments. I suppose it’s not necessary saying that drivers cannot be debugged using the Visual Studio environment. Remember that Kernel debugging requires special debuggers for that purpose as I mentioned in my last post.

One particularly interesting window that has been added to Visual Studio 2005 is the “Code Definition Window”, displaying where symbols have been defined as you write them in the code window. See the example when I write a call to IoSetCompletionRoutine.

At last, take a look at the options offered by DDKBUILD. You can list your choices by simply opening a command prompt window and running DDKBUILD without any parameter. Note that we can compile drivers also using the PREfast.

That’s it… Have fun! 😉

Serial Killers

October 24th, 2006 - Fernando Roberto

There’s no doubt, they’re really giving up producing serial ports on notebooks and desktops. In this post, I will talk about some problems we encounter when debugging that driver that only reproduces the issue on that machine that has no serial ports. What alternatives do we have with this regard?

This month new computers have arrived here in the company. In these machines, we put some of our products in beta version. For any reason, only on new machines one of our drivers was not working as it should. As the quotes of the programmer’s code of ethics, the blame is on the trainee who did the tests until otherwise could be proved. After several unsuccessful attempts to discover what was happening, I had no doubts, let’s debug it. Avoiding moving the victim to my desk to connect the serial cable, I decided to install SoftIce. But life is a surprise box and we got a nice BSOD when SoftIce was started. Wow! This is rare, but it happens. In these cases, we don’t have much choice; we really have to use Windbg. The PCs we got were Dell Dimension 5150 model. Take a look at its cabinet back in the picture and answer quickly: where is the serial port? That’s it, there is none. By consulting the manufacturer’s Web site, we found that the computer had 8 USB ports but had neither a parallel nor a serial port.

At this moment, we made a circle and talk all together: “Oh God, what do we do now?” Some issues that happen in real machines are also reproduced in virtual ones, especially if the driver you are developing is a filter or a driver that does not deal directly with the hardware. Just for a test, we installed VMware on a new machine and fortunately the problem was reproduced. That’s one of those occasions that we get happy when the problem appears. Thereafter, I just used the old trick about having virtual serial port in a VM and redirect the data stream to a named pipe. This could become a post. 😉

Well, after connecting the debugger, having the break-point set, it did not take long to find the problem, generating a new version, testing, making it to work and live happily ever after. But not always the history is solved with these few steps. Some virtual machines do not support USB devices. Even VMware that offers this feature still does not support human interface devices (HID) like USB keyboards and mice. Not to mention the psychological and esoteric issues involving race conditions and/or a good joint action with Murphy. What can we do in these cases besides sitting and crying?

Fortunately, technology at the service of humanity predicted situations like these. In these cases, we traditionally have two alternatives:

1) Describe the bug you want to delete on a sheet of paper. It is recommended that this description has sections like “Go away strange bug …”. Sew a piece of paper inside a frog’s mouth and positive thinking in solving the problem; throw the frog into a river without seeing where it would fell. After seven days, do a “Rebuild All” in your project (A reboot before the build is recommended). If the problem persists, repeat the steps. Formatting the machine helps to remove bad fluids and scare evil and haunt spirits away that torment your code. Consult a software healer for best results.

2) Use a FireWire card and make a Windbg connection using an IEEE 1394 cable. This option is only available if the machine being debugged is a Windows XP or higher. These cards are installed on your PCI or PCMCIA bus. I did not have any chance of using this connection type to debug a machine, but it is certainly very fast and comfortable, since the data is transmitted at a rate of up to 400Mbps.

Can I use one of those famous serial ports to USB converters that are sold at Santa Ifigenia? Although it’s not required to install a driver on your system, these adapters use drivers to work. All USB stack is mounted to make these devices work. On a machine that is being debugged in Kernel, all the code that deals with serial communication or firewire is hard-coded in the system and it works with fixed standard addresses . These adapters can be used without problems by the debugger machine, but not by the debugee one.

What if I use a PCI multiport serial card? That depends on what I/O addresses and interrupts the card. Normally these cards use different addresses of the standards in order to not to create any compatibility issues with I/O addresses that probably pre-exist on the machine. If the card offers the option of using standard addresses, there is no problem.

Windows Vista will support Kernel Debug via USB 2.0 port, though some conditions are required. USB cable must be special for this purpose, the debugee computer USB interface must support Kernel Debug, and last but not least, the debugger computer USB controller should be Extended Host Controller Interface (EHCI) compliant.

If you are interested in acquiring IEEE 1394, remember that you must have, at least, two interfaces such that there is a link between the debugger and debugee machine. Although I have seen some lost comments on the Internet about FireWire x USB converter cables (for use in debugger machine), as far as I could see, they are electrically impossible to be built. That’s because the entire protocol is different. Whereas USB is a “Master x Slave” protocol, FireWire is “Peer to Peer” one. It would require some intelligent hardware along the way to do all translation.

The company I work for is acquiring these interfaces for PCMCIA FireWire in order to eliminate the problem of debugging customer’s notebook  that is crippled serial ports. I think soon we’ll give up the frog and all. I will make some comparisons with the good old serial cable and give some news on this subject.