Friday, December 18, 2009

Monitoring OutputDebugString on Windows systems from an OSGi component using JNA

Recently I needed to create a small DLL to call some functions on a Windows Mobile device attached to the desktop Windows PC. Inside my DLL I made heavy use of the kernel32.dll OutputDebugString Win32 API to send text to an attached debugger or Debug View. Since I was programming in Java, I would have liked to have all the log messages appear in the Java console and end up in the log file created by slf4j.

How does OutputDebugString work?

Basically it writes its data to a shared memory section of kernel32.dll. Everybody can try to read this memory out at any time. You just need to know how the name of this memory block is and can get a direct memory pointer to it. I will not go into the details of that now, you can lookup the required methods in the MSDN yourself. So at first we need to open the existing filemapping with the name "DBWIN_BUFFER" using CreateFileMapping. Windows allocates 4096 bytes for the shared buffer. We then just map this shared buffer to a real memory location using MapViewOfFile. Using JNA thats pretty easy to do:
HANDLE sharedFile = Kernel32.INSTANCE.CreateFileMapping(W32API.INVALID_HANDLE_VALUE, null, Kernel32.PAGE_READWRITE, 0, 4096, DBWIN_BUFFER_SHARED_FILE);
HANDLE sharedMemory = Kernel32.INSTANCE.MapViewOfFile(this.sharedFile, Kernel32.SECTION_MAP_READ, 0, 0, 4096);
I added those prototypes to the already existing JNA Kernel32 package:
int PAGE_READONLY = 0x02;
int PAGE_READWRITE = 0x04;
int PAGE_WRITECOPY = 0x08;
int PAGE_EXECUTE = 0x10;
int PAGE_EXECUTE_READ = 0x20;
int PAGE_EXECUTE_READWRITE = 0x40;

HANDLE CreateFileMapping(HANDLE hFile, SECURITY_ATTRIBUTES lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, String lpName);

int SECTION_QUERY = 0x0001;
int SECTION_MAP_WRITE = 0x0002;
int SECTION_MAP_READ = 0x0004;
int SECTION_MAP_EXECUTE = 0x0008;
int SECTION_EXTEND_SIZE = 0x0010;

Pointer MapViewOfFile(HANDLE hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);

boolean UnmapViewOfFile(Pointer lpBaseAddress);
Now we basically have everything ready to start reading from that buffer. The first 4 bytes (32-bit DWORD) is the process ID of the process that wrote the text using OutputDebugString. The following bytes are the actual debug message as an ANSI string. Now, to tell kernel32 that we are interested in reading out this memory, we should inform it. Otherwise kernel32 would not write anything to this memory, if nobody is about to read it. For that purpose there is a named Win32 event that we need to signal. Its name is "DBWIN_BUFFER_READY". We create it using those new Kernel32 JNA mappings:
HANDLE CreateEvent(SECURITY_ATTRIBUTES lpEventAttributes, boolean bManualReset, boolean bInitialState, String lpName);

boolean SetEvent(HANDLE hEvent);

boolean PulseEvent(HANDLE hEvent);
Now lets create the mentioned event:
bufferReadyEvent = Kernel32.INSTANCE.CreateEvent(null, false, false, DBWIN_BUFFER_READY_EVENT);
When we signal this event, kernel32 will start to write data into the shared memory if some process calls OutputDebugString. In an infinite loop would could now read the memory out but that would read always the last written text that might not have changed since the last time we checked. Windows helps us to get informed when new text has been written to the shared memory. It signals this with the named event "DBWIN_DATA_READY". Now we can be a very good citizen and use the Win32 WaitForSingleObject to wait for this event to be signaled.
while (run) {
 // Say that we are interested in receiving data ready events
 Kernel32.INSTANCE.SetEvent(this.bufferReadyEvent);

 final int ret = Kernel32.INSTANCE.WaitForSingleObject(this.dataReadyEvent, Kernel32.INFINITE);
 if (!run) {
   break;
 }
 if (ret == 0) { // WAIT_OBJECT_0
   final int pid = this.sharedMemory.getInt(0);
   final String text = this.sharedMemory.getString(4, false);
 }
}

Creating a monitor thread

We can implement this whole functionality as a Thread and hand it in an OSGi LogService to log the catched debug message with the OSGi environment.
package outputdebugstring.monitor.internal;

import org.osgi.service.log.LogService;

import com.sun.jna.Pointer;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.examples.win32.W32API;
import com.sun.jna.examples.win32.W32API.HANDLE;

class OutputDebugStringThread extends Thread {
private static final String DBWIN_BUFFER_SHARED_FILE = "DBWIN_BUFFER"; //$NON-NLS-1$
private static final String DBWIN_DATA_READY_EVENT = "DBWIN_DATA_READY"; //$NON-NLS-1$
private static final String DBWIN_BUFFER_READY_EVENT = "DBWIN_BUFFER_READY"; //$NON-NLS-1$

private final HANDLE bufferReadyEvent;
private final HANDLE dataReadyEvent;
private final HANDLE sharedFile;
private final Pointer sharedMemory;
private final LogService log;
private volatile boolean run = true;

public OutputDebugStringThread(final LogService log) {
 super("OutputDebugString monitor"); //$NON-NLS-1$

 setDaemon(true);

 this.log = log;

 this.bufferReadyEvent = Kernel32.INSTANCE.CreateEvent(null, false, false, DBWIN_BUFFER_READY_EVENT);
 this.dataReadyEvent = Kernel32.INSTANCE.CreateEvent(null, false, false, DBWIN_DATA_READY_EVENT);
 this.sharedFile = Kernel32.INSTANCE.CreateFileMapping(W32API.INVALID_HANDLE_VALUE, null,
     Kernel32.PAGE_READWRITE, 0, 4096, DBWIN_BUFFER_SHARED_FILE);
 this.sharedMemory = Kernel32.INSTANCE.MapViewOfFile(this.sharedFile, Kernel32.SECTION_MAP_READ, 0, 0, 4096);
}

@Override
public void run() {
 try {
   while (this.run) {
     // Say that we are interested in receiving data ready events
     Kernel32.INSTANCE.SetEvent(this.bufferReadyEvent);

     final int ret = Kernel32.INSTANCE.WaitForSingleObject(this.dataReadyEvent, Kernel32.INFINITE);
     if (!this.run) {
       break;
     }
     if (ret == 0) { // WAIT_OBJECT_0
       final int pid = this.sharedMemory.getInt(0);
       final String text = this.sharedMemory.getString(4, false);
       this.log.log(LogService.LOG_DEBUG, String.format("[%d] %s", pid, text)); //$NON-NLS-1$
     }
   }
 } finally {
   if (this.sharedMemory != null) {
     Kernel32.INSTANCE.UnmapViewOfFile(this.sharedMemory);
   }
   if (!W32API.INVALID_HANDLE_VALUE.equals(this.sharedFile)) {
     Kernel32.INSTANCE.CloseHandle(this.sharedFile);
   }
   if (!W32API.INVALID_HANDLE_VALUE.equals(this.bufferReadyEvent)) {
     Kernel32.INSTANCE.CloseHandle(this.bufferReadyEvent);
   }
   if (!W32API.INVALID_HANDLE_VALUE.equals(this.dataReadyEvent)) {
     Kernel32.INSTANCE.CloseHandle(this.dataReadyEvent);
   }
 }
}

/**
* Our very own implementation that simply notifies the thread to stop by sending an event it is waiting for.
*/
@Override
public void interrupt() {
 this.run = false;
 Kernel32.INSTANCE.PulseEvent(this.dataReadyEvent);
}
}
As you can see I have overwritten the interrupt() method of Thread to implement a custom interruption using the volatile variable "run". We then pulse the dataReadyEvent to make the WaitForSingleObject wake up and immediately check the run variable to stop running.

Creating an OSGi component

Now that we have the (almost OGSi independent) thread to catch Windows debug messages we can wrap it in a simple OSGi component that will also give the thread the LogService it needs. A better solution would be however to have the Thread just call a simple Listener method to report the debug message event. That way it would have no dependency on OSGi.

The service component would be as simple as this:

public class MonitorComponent {
private OutputDebugStringThread thread;

protected void deactivate() {
  if (this.thread != null) {
    this.thread.interrupt();
  }
}

protected void bind(final LogService log) {
  this.thread = new OutputDebugStringThread(log);
  this.thread.start();
}
}
And the corresponding DS component XML file
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="outputdebugstring.MonitorComponent">
 <implementation class="outputdebugstring.monitor.internal.MonitorComponent"/>
 <reference bind="bind" cardinality="1..1" interface="org.osgi.service.log.LogService" name="LogService" policy="static"/>
</scr:component>
As you can see we dynamically bind to the OSGi LogService and our component will be only activated when there is at least one LogService available. This saves our component from instantiating itself if there is nothing to log to.

Extensions

The component could also facilitate the OSGi EventAdmin and send an event: event.topic = win32/OutputDebugString ods.pid = the process ID ods.text = the text

Note: It seems that inside the mapped file all texts are stored in the ANSI character set and not in Unicode (UTF-16) even when a process called OutputDebugStringW.

Sourcecode is up at github now.

Thursday, December 17, 2009

Displaying OSGi bundle informations in the Windows Explorer

I am currently working on a small Windows Shell Extension that will help to get a quick overview on all the OSGi bundles in the currently browsed folder.



The following features will be supported:

  • Detail columns for all bundle headers
  • Additional Property sheet for bundle files and unpacked bundle folders
  • Overlay icons to display various informations: if the bundle has Service Components, is a fragment or a normal bundle
  • Tooltips with the most important bundle headers
The extension can already read out the default Bunde-l10n. However there is no support for reading out the l10n matching the current Windows locale yet. In the future I plan to support Windows Search 4 and Vista and allow them to find bundles based on their OSGi manifest. I will upload the extension soon to github and everybody is invited to provide feedback. The source package will include documented classes and unit-tests (using googletest) maybe I will create a small tutorial about this later.

Wednesday, December 16, 2009

Notification Framework

In this series of tutorials I will describe a small, extensible notification framework for JFace/Eclipse applications. I will make heavy use of OSGi services and Eclipse Extensions. So before you continue to read, I suggest you make yourself familiar with those concepts to be able to follow the series.
  1. Basic Notification Service
  2. Notify listeners about notifications
  3. Showing all notifications in a view
  4. Notifications via OSGi EventAdmin
  5. Adding links to notifications
  6. Let the notify console command quote "The Big Lebowski" from the IMDB with links
  7. Declarative colour customization for Notifications
  8. Add preferences which notifications should be shown
  9. Showing notifications after a "copy" command was executed
There is git repository accompanied with this tutorial series. You can clone it directly from git://github.com/pke/Notifications.git

Inspiration

The inspiration for using notifications in my own programs came from Mylyn that shows neat little notifications upon changes in the watched buglists. I was further inspired by the great blog post over at Hexapixel: Creating a Notification Popup Widget. We will use this widget as the base of this tutorial series.

Creating the service

First we create a simple service interface for our NotificationService. Its intentionally simple and does not contain any query methods to enumerate notifications or such. It simply provides a method to show a single notification. But as you will see in the course of this series that's enough to drive a powerful notification system. So the interface will look like this:
public interface NotifyService {
 /**
  * Shows a notification. Re-arranges already visible notifications.
  *
  * @param notification
  */
 void show(Notification notification);
}
For the Notification interface itself we will use JFace's IMessageProvider as a base as it provides already a message text and type for our notification. All that is left is a title. So our Notification interface looks pretty simple too:
interface Notification extends IMessageProvider {
 /**
  * @return the title of this notification or null if none.
  */
 String getTitle();
}
Thats basically all we need for a simple notification. As the base for the implementation of our Notification Service we will use Hexapixel's code for now. That makes the implementation of the NotificationService really simple:
public void show(final Notification notification) {
  if (notification != null) {
    Display.getDefault().asyncExec(new Runnable() {
      public void run() {
        NotificationType type;
        switch (notification.getMessageType()) {
        case IMessageProvider.WARNING:
          type = NotificationType.WARN;
          break;
        case IMessageProvider.ERROR:
          type = NotificationType.ERROR;
          break;
        default:
          type = NotificationType.INFO;
          break;
        }
        NotifierDialog.notify(notification.getTitle(), notification.getMessage(), type);
      }
    });
  }
}
I only modified the original NotifierDialog class so that it no longer requires an active shell for operating. There is one more little thing we also need to do, to actually see the notification on screen. We need a thread that polls the SWT message loop. This is usually done for us when we run inside the Eclipse workbench, but since we are going to test this notification framework in an OSGi environment (for now) we need a thread that polls the SWT message loop for us. The code is also inside the NotificationService component implementation:
Runnable runnable = new Runnable() {
  public void run() {
    while (!Display.getDefault().isDisposed()) {
      if (!Display.getDefault().readAndDispatch()) {
        Display.getDefault().sleep();
      }
    }
  }
};
new Thread(runnable, "SWT").start();

Equinox Console Command to show notifications

Basically we have everything in place now to show notifications programmatically. We can have other components use our notification service to display messages. So we will create a console command for the Equinox OSGi console and implement a simple CommandProvider. It will expose the command "notify" to the Equinox console if you start the OSGi configuration with the "-console" command. The notify command will take at least one parameter, which will be the notifications message. If you specify another parameter, then this will become the notifications title. Otherwise a default title is choosen.
public class NotifyCommand implements CommandProvider {

 NotificationService service;

 protected void activate(ComponentContext context) {
   service = (NotificationService) context.locateService("NotificationService");
 }

 public void _notify(CommandInterpreter ci) {
   final String message = ci.nextArgument();
   if (null == message) {
     ci.println("You need to specify a message");
     return;
   }
   String title = ci.nextArgument();
   if (title == null) {
     title = "Notification";
   }
  
   final String finalTitle = title;
   service.show(new Notification() {
     public String getTitle() {
       return finalTitle;
     }
    
     public String getMessage() {
       return message;
     }

     public int getMessageType() {
       return IMessageProvider.INFORMATION;
     }
   });
 }

 public String getHelp() {
   return "--- Notification ---\n\tnotify message [title]";
 }
}

Create the component definitions

All that is left to make those 2 services run as Declerative Services is to create the required component XML files in /OSGI-INF/. For the NotificationService it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ui.notification.NotificationService">
  <implementation class="ui.notification.internal.NotificationServiceImpl"/>
  <service>
     <provide interface="ui.notification.NotificationService"/>
  </service>
</scr:component>
And for the NotifyCommand it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ui.notification.NotifyCommand">
  <implementation class="ui.notification.command.internal.NotifyCommand"/>
  <service>
     <provide interface="org.eclipse.osgi.framework.console.CommandProvider"/>
  </service>
  <reference cardinality="1..1" interface="ui.notification.NotificationService" name="NotificationService" policy="static"/>
</scr:component>

Run configuration

To run this we create an OSGi run configuration and add the following bundles to it:
  • ui.notification
  • ui.notification.command
  • org.eclipse.osgi
  • org.eclipse.osgi.services
  • org.eclipse.equinox.ds
  • org.eclipse.equinox.util
  • org.eclipse.equinox.common
  • org.eclipse.core.commands
  • org.eclipse.swt
  • org.eclipse.swt.win32.win32.x86
  • org.eclipse.jface
Make sure the org.eclipse.equinox.ds bundle is started, as well as our two ui.notification* bundles. If we start the configuration now, we will be able to type: notify "Hello World" and see a notification coming up at the right bottom of our primary screen as seen in this video: That's all for now. Stay tuned for the next part where we will notify listener services about notifications using the White-Board pattern. Feedback is always welcome, especially about how to poll the SWT message loop in OSGi apps.

Source:

Check out the source code at github or clone directly from git://github.com/pke/Notifications.git

Tuesday, December 15, 2009

Toggle Commands that toggle other contributions

Introduction

This is a follow up to Commands Part 6: Toggle & Radio menu contributions of fellow blogger Prakash G.R.. He described how to use command toggle and radio states. Here I will show you how to drive other contributions in the Eclipse Workbench using a toggle command.

What we want to achieve

I needed to show another toolbar button when a certain toggle command was executed. Imagine something like "Show clock" that will show or hide a little clock in the worbench window status bar. Such contribution can be easily added using a menuContribution for the trim area. First create a toolbar in the trim area and then contribute controls/commands to this toolbar also using the menuContribution extension point. Since we want the clock contribution
<menucontribution locationuri="toolbar:mytoolbar">
<control class="test.ui.clocl.internal.ClockControlContribution" id="test.ui.clock">
<visiblewhen checkenabled="false">
<with variable="activeWorkbenchWindow">
  <test args="test.ui.clock.ToggleCommand"
    forcepluginactivation="true"
    property="org.eclipse.core.commands.toggle"
    value="true"/>
</with>
</visiblewhen>
</control>
</menucontribution>
That will create a toolbar contribution that is only visible when the test.ui.clock.ToggleCommand is in the "true" state, when its checked. Lets define the command:
<command defaulthandler="org.eclipse.core.commands.extender.ToggleCommandHandler" id="test.ui.clock.ToggleCommand" name="Show clock">
<state
class="org.eclipse.ui.handlers.RegistryToggleState:true"
id="org.eclipse.ui.commands.toggleState">
</state>
</command>
How this command works and what the state is you have already read in Prakash's blog entry. The default handler for this command does a little more than the one in the latter mentioned blog entry. It is defined like this:
/**
* Generic command that toggles the executed command and re-evaluates property testers for the
* org.eclipse.core.commands.toggle property.
*
*/
public class ToggleCommandHandler extends AbstractHandler {

public Object execute(final ExecutionEvent event) throws ExecutionException {
HandlerUtil.toggleCommandState(event.getCommand());
final IWorkbenchWindow ww = HandlerUtil.getActiveWorkbenchWindowChecked(event);
final IEvaluationService service = (IEvaluationService) ww.getService(IEvaluationService.class);
if (service != null) {
  service.requestEvaluation("org.eclipse.core.commands.toggle");
}
return null;
}
}

How to toggle the visibility of the clock contribution

The connection between toggling the command and making the clock contribution visible is hidden in a property tester, that the clock contribution uses:
public class CommandsPropertyTester extends PropertyTester {
public static final String NAMESPACE = "org.eclipse.core.commands"; //$NON-NLS-1$
public static final String PROPERTY_BASE = NAMESPACE + '.';
public static final String TOGGLE_PROPERTY_NAME = "toggle"; //$NON-NLS-1$
public static final String TOGGLE_PROPERTY = PROPERTY_BASE + TOGGLE_PROPERTY_NAME;

public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
if (receiver instanceof IServiceLocator && args.length == 1 && args[0] instanceof String) {
  final IServiceLocator locator = (IServiceLocator) receiver;
  if (TOGGLE_PROPERTY_NAME.equals(property)) {
    final String commandId = args[0].toString();
    final ICommandService commandService = (ICommandService)locator.getService(ICommandService.class);
    final Command command = commandService.getCommand(commandId);
    final State state = command.getState(RegistryToggleState.STATE_ID);
    if (state != null) {
      return state.getValue().equals(expectedValue);
    }
  }
}
return false;
}
}
It is defined in plugin.xml like this:
<propertytester
class="org.eclipse.core.commands.extender.internal.CommandsPropertyTester"
id="org.eclipse.core.expressions.testers.CommandsPropertyTester"
namespace="org.eclipse.core.commands"
properties="toggle"
type="org.eclipse.ui.services.IServiceLocator"/>
That means we define a new property for the namespace "org.eclipse.core.command" and the property is named "toggle". It will operate on IServiceLocator variables. Such variable that is an IServiceLocator is the "activeWorkbenchWindow" variable. Now you should understand the visibleWhen expression of the clock contribution. It should be only visible when the toggle for the clock toggle command is "true". The re-evaluation of the property testers is triggered by the generic ToggleCommand.

A little tip at the end

If you put the ToggleCommand and property tester in a seperate bundle for easier re-use in all your projects and other bundles make sure you either start the bundle at the beginning or set the "test" expressions "forcePluginActivation" to true to let the Eclipse expression framework activate the bundle for you. Otherwise the property tester is completly ignored and the clock would be always visible.

Bonus

Since the state of the toggle is preserved in an instance preference value, the visibility of all associated contributions that use the property tester to check for the toggle state of the command is as well. Of course you can also reverse the test expression for your contributions if you have a toggle command that says something like "Hide clock".

Sunday, December 13, 2009

Using JNA to query power status on Windows CE device - with a crash

Introduction

I am using the wonderful JNA library to use the Microsoft Remote API (RAPI) to access Windows Mobile Devices on Windows desktops. It allows you to connect to an attached mobile device using ActiveSync. This works all wonderfully easy thanks to the JNA library. I do not need to write any JNI code anymore. The RAPI offers a method to query the power status of the device which is somewhat limited. It does not return more detailed information about the battery type or voltage. There is a function available in the WinCE devices own libraries (coredll.dll) that allows me to query such informations (GetSystemPowerStatusEx2).

How to call methods directly on the device

To call a method on the device that is not exposed by RAPI itself, you can use the CeRapiInvoke function. So I implemented the following function according to the RAPI specs:
EXTERN_C int __declspec(dllexport) GetPowerInfos(DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, LPVOID pStream) {

 *pcbOutput = sizeof(SYSTEM_POWER_STATUS_EX2);
 *ppOutput = (SYSTEM_POWER_STATUS_EX2*)LocalAlloc(LPTR, *pcbOutput);

 return GetSystemPowerStatusEx2(*ppOutput, *pcbOutput, FALSE);
}
The spec requires to LocalAlloc the memory you return. The caller of CeRapiInvoke must then LocalFree the output memory. Now, you may wonder how that can work?

Memory management in CeRapiInvoke

The way I understand how it works is like this: For the pInput parameter you have to call LocalAlloc on the Windows machine and CeRapiInvoke will copy the content of this memory block into a newly created WindowsCE readable block of memory and hand it over to GetPowerInfos function as pInput. It is of course not the same memory pointer that I handed in on the Win32 side, it just contains the same data as I handed in. CeRapiInvoke also calls LocalFree on the pInput that I handed in. The same way around with the ppOutput parameter. I have to allocate it using LocalAlloc on the WindowsCE device. CeRapiInvoke will then copy the content of my returned buffer into a desktop process accessible block of memory that it allocates with LocalAlloc on the Windows machine. I, the caller of CeRapiInvoke am then responsible for calling LocalFree on the ppOutput that CeRapiInvoke created for me. Thats the theory. Lets see how to get the returned ppOutput into the Java world using JNA.

Calling CeRapiInvoke from Java using JNA

We define this prototype in our JNA library interface for RAPI.
public interface Rapi extends W32API {

    static Rapi instance = (Rapi) Native.loadLibrary("rapi", Rapi.class, DEFAULT_OPTIONS); //$NON-NLS-1$

    HRESULT CeRapiInvoke(String dllPath, String functionName, int cbInput, Pointer pInput, IntByReference outBuffer, PointerByReference outBufferSize, PointerByReference ppIRAPIStream, int dwReserved);
}
We also declare the SYSTEM_POWER_STATUS_EX2 structure:
static class SystemPowerStatusEx extends Structure {
 public SystemPowerStatusEx() {
 }

 protected SystemPowerStatusEx(final Pointer p) {
  super(p);
 }

 public byte ACLineStatus;
 public byte BatteryFlag;
 public byte BatteryLifePercent;
 public byte Reserved1;

 public int BatteryLifeTime;
 public int BatteryFullLifeTime;
 public byte Reserved2;
 public byte BackupBatteryFlag;
 public byte BackupBatteryLifePercent;
 public byte Reserved3;
 public int BackupBatteryLifeTime;

 public int BackupBatteryFullLifeTime;
}

class SystemPowerStateEx2 extends Structure {
 public SystemPowerStateEx2(final Pointer p) {
  super(p);
  read();
 }

 public SystemPowerStatusEx base;

 public int BatteryVoltage;
 public int BatteryCurrent;
 public int BatteryAverageCurrent;
 public int BatteryAverageInterval;
 public int BatterymAHourConsumed;
 public int BatteryTemperature;
 public int BackupBatteryVoltage;
 public byte BatteryChemistry;
}
Now we can call our DLLs exported function:
final PointerByReference outBuffer = new PointerByReference();

try {
 final IntByReference outBufferSize = new IntByReference();
 Rapi.instance.CeRapiInvoke("powerex.dll", "GetPowerInfos", 0, null, outBufferSize, outBuffer, null, 0);
 return new SystemPowerStateEx2(outBuffer.getValue());
} finally {
 Kernel32.INSTANCE.LocalFree(outBuffer.getValue());
}
This code has been simplified and usually contains return value checking and error handling. However it returns the power infos we would suspect. I also ommited the initialization of RAPI here.

The LocalFree crash problem

Calling this in a loop will eventually lead to an Access Violation and a crash of the VM. If I comment out the LocalFree call in the finally block, the program runs for hours. But it then leaks memory of course. I have played with different output parameters, pointer handling and more. Without finding a solution to the crashes. Enabling JNAs own VM crash protected reveals, that it sometimes causes an Access Violation inside the native code. It almost seems like the native code overwrites some memory internally. Most likely inside RAPI itself. However calling the same remote function from a C++ Win32 program in a loop does not cause any memory corruption or crash. I hope someone of the community has maybe an idea whats going on here? If not, you got at least a short introduction on how to use JNA and the Microsoft RAPI ;)

Monday, December 7, 2009

Allow contributions to Forms

Introduction

Each Form has a toolbar associated with it, as you probably already know. You can get it by calling form.getToolBarManager(). Once you got the manager you can add your own contribution items or (legacy) actions to it. But what if you could allow other bundles/developers to add contributions to your forms toolbar too? There exists already an extension point that allows adding of contributions to menus and toolbars. You most likely used it already to customize your popup menus or your RCP applications main menu.

How to implement

The menuConstribution extension point works in conjunction with the IMenuService. This service allows you to put matching contributions into any ContributionManager. It respects the current workbench evaluation state so contributions with expressions are carefully evaluated before they are added to the ContributionManager. The menu service also takes care of enabling the contributions and manages their visibility dynamically. Basically all that you already know from addin contributions to the various Eclipse menus and toolbars. To get the contributions you are interested in, you first have to decide on a menu URI schema that identifies contributions for your form. We should follow the Eclipse Schema and define "form:" as our new schema and the following parameter is the ID of the form. The ID can be anything and you as a programmer decide for each form that you create what its ID should be. A common way I use is, if the form is embedded into a ViewPart, to use the ViewPart.getSite().getId() method. So I would call
menuService.populateContributionManager(toolbarManager, "form:"+getSite().getId());

Cleanup

You have to remember to release the contributions when your form is disposed or otherwise the IMenuService will continue to track your contributions and waste time as well as resources. So be a good contribution citizen and call menuService.releaseContributions(toolbarManager) and also toolbarManager.dispose()to allow it to clean up its resources. I recommend using a DisposeListener on the form to perform the cleanup.

Extension: Allow contributions to any form

Much like you can add contributions to the global popup menu using the "popup:org.eclipse.ui.popup.any" we can define our new "form:org.eclipse.ui.form.any" URI that allows contributions to be added to each forms toolbar.
ContributionHelper.contributeTo(toolbarManager, "form:" + getSite().getId(), "form:org.eclipse.ui.form.any");


  
    
    
  


/**
* Adds menu contributions to a {@link ContributionManager} using the
* {@link IMenuService}.
*
* @param contributionManager
* @param locations
*            The format is the Menu API URI format.
*/
public static void contributeTo(final ContributionManager contributionManager, final String... locations) {
final IMenuService menuService = (IMenuService)PlatformUI.getWorkbench().getService(IMenuService.class);

for (final String location : locations) {
 menuService.populateContributionManager(contributionManager, location);
}
contributionManager.update(false);
}

Thursday, July 23, 2009

How to replace the default JFace message icons

We all know the standard JFace icons very well. They appear in Dialogs, Wizards and Forms.

And in a form they look like this:

Now, there is a quick and easy way to replace them with your own icons if you like.

You just have to create a Fragment bundle and set org.eclipse.jface as its Bundle-Host. In your fragment bundle you include the icons you want to replace in the following folder structure:
Don't forget to add the icons folder and all of its subfolder and content into your build.properties file:
bin.includes = META-INF/,\
             .,\
             OSGI-INF/,\
             icons/
Interesting fact: You can replace the JFace icons with PNGs too. You can just rename them to have the .GIF extensions. The image file loader of SWT does not care about the extension but analyses the content of the file.