Lost Website

You Are Here

Archive for the ‘Windows’ Category

Getting the handle off any Outlook window

with 2 comments

When embedding some window inside Microsoft Outlook, it is not understandable that at some point you need the handle of some an Outlook window object, an Outlook Inspector or an Explorer. The Outlook Object Model does not expose a method to obtain the handle to a window. This is based on some information from Dmitry Streblechenko.

Yes, but not in VBA: you need to QI the Inspector (or Explorer) object for the IOleWindow interface, then call IOleWindow::GetWindow()

If you work with low-level Microsoft Outlook you will eventually find some information, very often forum posts, answered by Dmitry. You will also quickly learn that he is very often right.

I have written the following code in the very last days I have worked on the EchoTracker. It was part of refactorization I have not had time to finish so this code is UNTESTED. This is based solely on my interpretation of the indication of Dmitry.

/// <summary>
/// Embed the Outlook panel in *any* Outlook explorer. Thanks Dimitry.
/// http://www.pcreview.co.uk/forums/thread-1837879.php
/// </summary>
public static MSOWindow GetOutlookWindow(Outlook.Explorer olExp)
{
  IntPtr olExpUnk = IntPtr.Zero;
  IntPtr oleWinPtr = IntPtr.Zero;
  IntPtr hWnd = IntPtr.Zero;
  Guid oleWinGuid = typeof(IOleWindow).GUID;
  IOleWindow oleWin = null;

  try
  {
    olExpUnk = Marshal.GetIUnknownForObject(olExp);
    oleWinPtr = IntPtr.Zero;

    if (Marshal.QueryInterface(olExpUnk, ref oleWinGuid, out oleWinPtr) != 0)
      throw new Exception("QueryInterface failed.");

    oleWin = (IOleWindow)Marshal.GetObjectForIUnknown(oleWinPtr);
    if (oleWin == null)
      throw new Exception("GetObjectForIUnknown failed.");

    oleWin.GetWindow(out oleWinPtr);
  }
  finally
  {
    if (oleWin != null) Marshal.ReleaseComObject(oleWin);
  }
  return new MSOWindow(hWnd);
}

For this code to hopefully work, you need to have the COM interop declaration for the IOleWindow interface. You can find this information on pinvoke.net.

Please, if you stumble upon that code, and happen to have a need for it, use it, or adapt it to your need, leave a comment on this post. I repeat that this is untested. I have no plan to test it, I don’t have a machine on which I can develop Microsoft Outlook.

Written by François-Denis Gonthier

April 27th, 2010 at 9:01 pm

Getting 2 C# Outlook addins to talk together

without comments

The Outlook Object Model (OOM) exposes the COMAddins collections of COMAddin object which can be used by Outlook plugins to communicate together. The communication needs to be done through a COM interface. C# and the .NET framework makes it very easy.

You first need to make a ComVisible interface which the caller will use to communicate with the callee. The sample we will work with is a simple class that will call System.Windows.Forms.MessageBox.

using System;
using System.Runtime.InteropServices;

namespace MessageBox
{
    [ComVisible(true)]
    public interface IMessageBox
    {
        void MessageBox(String msg);
    }
}

Next you need to make the callee addin. This addin can be made using VTSO or without it. Addin Express would work too. The callee of course needs to implement IMessageBox interface.

[ComVisible(true)]
[ComDefaultInterface(typeof(IMessageBox))]
public partial class ThisAddIn : IMessageBox
{
    public void MessageBox(String msg)
    {
        System.Windows.Forms.MessageBox.Show("MessageBox() call: " + msg);
    }

    protected override object RequestComAddInAutomationService()
    {
        return this;
    }
    /* ... snip ... */
}

This is not the full code of the addin. I have removed the boring part generated by VTSO.

There are 2 important things to notice in the above code. The first is the ComDefaultInterface attribute, which defines which default interface is exposed to COM by the addin. This is important because the ThisAddin class derives from a non-COM-visible class. The page on the NonCOMVisibleBaseClass Managed Debugging Assistant (MDA) has the information on why this is important.

The next important thing is the implementation of the RequestComAddinAutomationService, which return an instance of the COM class to the caller. This is part of the communication protocol between addins. You can make this method return any instance of a COM visible objects. We’ve used the addin class itself to keep things simple.

Finally, the caller code amounts to accessing the COMAddins collection and finding the right object inside it to get the interface.

object msgBoxID = "MessageBox.Addin";
Office.COMAddIns addins = null;
Office.COMAddIn msgBox = null;
IMessageBox imsgBox = null;

try
{
    addins = Application.COMAddIns;
    msgBox = addins.Item(ref msgBoxID);
    imsgBox = (IMessageBox)msgBox.Object;

    // Actually use the other addin interface.
    imsgBox.MessageBox("Hello, this is a selection change.");
}
finally
{
    if (addins != null) Marshal.ReleaseComObject(addins);
    if (msgBox != null) Marshal.ReleaseComObject(msgBox);
}

This code is pretty straightforward. The 2 important things to notice are the ref object parameter to the COMAddin.Item method and the fact that you need to use the ProgID of the callee addin when searching inside the COMAddins collection. I put emphasis on this because I lost some time trying to find the ProgID of the IMessageBox interface. The ProgID of the addin, when using VTSO, is usually the name of the assembly.

This research was done in the context of the development of the Echotracker although it is still way too early to say what feature will be built on top of that.

Written by François-Denis Gonthier

March 26th, 2010 at 9:35 am

C# array marshalling with P/Invoke

with 2 comments

This took me a while to figure out and nobody on the Internet seems to have figured out exactly this particular task.

Working on the Echotracker, I wanted to be able to manipulate an array of string from the JScript runtime inside an embedded web browser. Microsoft script runtimes are able to easily manipulate ActiveX objects, and it is easy in C# to make a object visible to COM so interoperability is generally not a problem.

This interoperability wasn’t so intuitive when the time came to deal with arrays. The offending C# declaration was the following.

string[] GetPhoneNumbers();

This is converted by C# into a SAFEARRAY containing BSTR objects. SAFEARRAY is the native name of VB-style multidimensional arrays and BSTR is, in general, the type used by COM to exchange strings. The declaration is nothing exotic as far as COM is concerned. With the MarshalAs attribute added, the declaration now looks like this.

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)]
string[] GetPhoneNumbers();

This doesn’t work well with JScript. The first I found thing is that JScript array aren’t compatible with VB array. Microsoft provides a VBArray class for that purpose. It is supposed to deal with SAFEARRAY. Using this class sadly adds some semantic complexity to using arrays returned by ActiveX objects because they can only be used through methods such as getItem(), ubound(), lbound() instead of the normal way for JScript arrays.

Secondly, JScript can’t deal with SAFEARRAY(BSTR) object. Using the GetPhoneNumbers() method crash with the error message “VBArray expected”. The problem is that while JScript can deal with SAFEARRAY, it can’t deal with SAFEARRAY of type other than VARIANT. VARIANT is the catch-all, magic datatype introduced by Microsoft for its dynamic, untyped languages like VB and JScript. This is how I came to test the next declaration.

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VARIANT)]
string[] GetPhoneNumbers();

This is also not enough for the array to be accepted by JScript, giving out the same “VBArray expected” error message. The problem is in the way the array is marshaled by C#. This page on MSDN clued me to the solution. The .NET marshaller is converting System.String objects automatically into BSTR objects. In this case, the object type needed is a VARIANT object of subtype VT_BSTR. The declaration alone isn’t enough to make the marshaller convert the string to the proper variant type.

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VARIANT)]
object[] GetPhoneNumbers();

This last declaration makes the .NET marshaller properly convert the strings into VT_BSTR variant object and the array becomes usable by the JScript runtime. In fact, once you know how the .NET runtime converts System.Object arrays, you can do without MarshalAs declaration.

object[] GetPhoneNumbers();

This is, by default, converted into a method returning a SAFEARRAY(VARIANT) object.

The lesson is: leave the .NET COM interop marshaller alone, it probably knows more about COM than you do.

Written by François-Denis Gonthier

March 24th, 2010 at 12:17 pm

Microsoft has 2 contact management API which you shouldn’t use

with 2 comments

This day has not improved the problems I have with developing on Microsoft Windows. I was doing some research for future development of the Echotracker. I was looking at how to access the Windows address book features through an API and found there are only 3 options open to the programmer wanting to access address book features on Windows.

The main API we use to deal with Microsoft Outlook 200x, the Outlook Object Model (OOM), offers no ways to directly access the address book provided by Outlook. This is bad enough by itself because it means that access to the address book must be done through the dreaded, and unsupported with .NET, MAPI.

Microsoft Windows XP, and probably some earlier version, also had the Windows Address Book API. This is a COM API that give access to the default Windows address book.

This API is deprecated and Microsoft explicitly says that programmers should not use it.

New applications should not use these interfaces. These interfaces exist for backward compatibility with legacy applications. These interfaces will be unavailable in the future.

The newer, Windows Vista and up, alternative is the Windows Contacts API, but here is what Microsoft has to say about this API.

New applications should not use these interfaces. These interfaces exist for backward compatibility with legacy applications. These interfaces will be unavailable in the future.

So Microsoft deprecated the old API, which isn’t necessarily unreasonable, but replaced it with an API that they ask programmers not to use. Of course, they don’t provide any of alternative nor rationale for that message.

So where does that leave us? Nowhere. Programmers who wants to use the Windows address book features will use those APIs, deprecated or not and screw around until it works. Technical analyst taking project decision could also say that Windows has no contact management API. I’m not sure which path Microsoft wants people to take regarding that. I’m lost myself.

Written by François-Denis Gonthier

March 18th, 2010 at 2:53 pm

Interfacing with Microsoft products

without comments

I work for Kryptiva, which is a small company creating security and collaboration tools. Our server products are deployed on Ubuntu and Debian Linux, but our client-side products are naturally available on Windows. We host some of our server product ourselves, but some of the server we have are deployed inside client networks, which are usually Microsoft Windows networks.

Creating application for Microsoft Network and for Microsoft Windows desktops meant to had to deal with several Microsoft technologies. This might come as a surprise to readers of Linux technology blog, but I think that not all Microsoft technologies are nightmarish messes to deal with. To the extent to what we have needed to do, Microsoft did not fare as worse or as good than everything else I have dealt with in my programming career.

Microsoft Active Directory is the building block of all Microsoft Windows network. It is an huge database with load of information which can happily be accessed using the open LDAP protocol. Working with Active Directory is something intimidating at first because the data it provides isn’t intuitively interpretable. For a Linux user, it takes a little while to get used to the terminology and the features of a Microsoft Windows network. Once the basics are acquired, it’s actually pretty easy to get Active Directory to return the information ones want. Of course, it has Microsoft-style quirks you have to deal with, but everything is pretty decently documented especially since Microsoft was forced release to their documentation. The people working on Samba 4 would certainly have a lot more to say than me about Active Directory but I honestly can’t say that much bad things about it.

Microsoft is a big company that has to deal with an enormous amount of code and software interfaces internally, but they also need to answer to their clients which all together have a massive quantity of code interfacing with Microsoft code. This means that deprecating age-old API is hard, and can’t always be handled in a very elegant way.

I’m not arguing that API should never be deprecated, but there are good ways and bad ways to deprecated API. The MAPI (Messaging API) is an age-old interface that has been in use for years in Windows to send an receive email messages on Windows machine. It’s badly documented and quirky API but since it’s the core of all messaging applications on Windows, it’s very powerful and difficult to do without it. Sadly, Microsoft does not want people to use their shiny new .NET framework with the old MAPI. They reasons they explain is very vague. To put it simply: it’s not compatible and will crash your program, but we can’t really explain why or when. The alternative they suggest are simply not practical or not as powerful as directly dealing with MAPI.

This brings us to the worse. The interface exposed by Microsoft to plug into Outlook is just bad. It has become a kind of running gag that I have become an world expert in calculating the size of a message attachment in Microsoft Outlook 2003. The makers of the framework we use to develop Outlook plugins have even semi-acknowledged that (see the end of the post). In some context, getting the size of file attached to an email message is very difficult and the only way to get it is through… MAPI. This is why it has been disconcerting to learn that Microsoft doesn’t want programmers to use MAPI in managed (.NET) code. Happily, this has been solved in later Outlook versions and Outlook 2007 exposes the size of attachments in all context. This means the some code using MAPI code with eventually go away, along with support for Outlook 2003. Sadly, Microsoft has more surprise in store for Outlook 2010.

Details about the next Microsoft Outlook release, currently in beta are being documented by Microsoft. In a recent newsletter, the makers of Addin Express linked us with this overview of a change related to the way Outlook 2010 shuts down.

Starting in the Outlook 2010 Beta release, Outlook, by default, does not signal add-ins that it is shutting down.

Most add-ins use these events to release references to Outlook COM objects and clear memory that was allocated during the session.

Thanks Microsoft, but what about network connections? Opened databases? Plain old data files?

I can only guess why Microsoft decided that it is important that Outlook shuts down as quickly as possible but it was apparently deemed more important that data integrity. This is something I find questionable. Microsoft have left a backdoor open for system administrator to revert to the old behavior, but in practice this is not the kind of thing you like to ask system administrator to do. There must be a handful of hackish and unsupported workaround to solve this problem and Outlook programmers around the world will find and document most of them, but I’m pretty sure they could all do without that…

Written by François-Denis Gonthier

January 16th, 2010 at 10:15 pm

Don't dust off your tinfoil hat for Skype just yet…

without comments

So Skype is evil because it’s proprietary?

It’s not hard to find rumors about spyware being deployed with the Skype VOIP software. What is hard to find amongst those rumors are concrete facts. Most of the rumors seems to be unsubstantiated, and some other are based on interpretation on the EULA of Skype. I won’t bother with the later case since legalese is not a language I speak.

This blog is one of the few blog around that take seem to take the matter seriously and brings forward something looking like a real proof that Skype may be stepping over the boundary of user privacy.

For the people who don’t read french, I will summarize the article. The author’s hypothesis is that when a new profile is registered through the Skype desktop client, the software accesses bookmarks stored in the user’s Mozilla Firefox profile. Since it’s not immediately obvious why Skype needs to be doing that, he concludes that the Skype software must be sending that information home for data warehousing, or some other shady practices.

For proof he shows his data that he obtained using the strace command on Linux. strace is a lovely, lovely utility I’ve learned to master in the last few years. It is an utility which shows the system calls that are used by a Linux application. strace is not hard to use but its output can be very voluminous and difficult to decipher. This is not the case here.

…Naaah

The data he obtained looked inoffensive to my eyes just 2 seconds after examining it (I won’t claim I’m the first that saw that: several commenter have pointed it to him).

The blogger singles out several calls to stat64(), which is a system call returns information about a file like its size and last modifications or last access date.

[pid 23964] stat64("home/phil/.mozilla/firefox/bstiq480.default/bookmarkbackups/bookmarks-2008-12-17.json", {st_mode=S_IFREG|0600, st_size=41718, ...}) = 0
[pid 23964] stat64("/home/phil/.mozilla/firefox/bstiq480.default/bookmarkbackups/bookmarks-2008-12-20.json";, {st_mode=S_IFREG|0600, st_size=42052, ...}) = 0

An higher level view of the data shows that Skype actually calls stat64() on all files on the the Mozilla profile of the user, and call open() on the directories he finds, then call getdents() to obtain the list of entries in that directory and so on…. Like any software recursively scanning the filesystem would do. The scan in the profile is stopped at the moment the software finds the user preference file.

This is easily explainable: Skype tries to install a FireFox plugin. It seems the Windows version has an option in the installer to disable that plugin but I have not found the same option in the Skype package.

So, Skype does search inside the user’s Firefox profile, but the only thing he does with the result it obtains is the installation of a plugin for the user’s convenience. It’s not even useful to search the place where it might be sending data since there is no data to send other that what it gathered through its registration wizard.

The final nail can be driven in the coffin on this theory by simple listing all the files opened by Skype during registration. None of the files contain personal information. You can see list of opened files I have extracted from the strace output at the end of this post.

Not evil on an evil operating system either…

Those results have been independently confirmed on Windows by DrFrakenstein, a twitterful, but blogless Code Ninja. He used Process Monitor and confirmed me roughly the same behavior but targeted at Internet Explorer.

So, probably not evil…

I can’t conclude this post by saying that Skype doesn’t include spyware. I simply spent one hour examining very limited data on the activity of the software during registration. Yet, I’m confident enough about my result to keep recommending its use to my family. Use Free alternatives such as Ekiga if you give high important to software freedom. It’s a opinion I respect. Just make sure you have something better that crappy strace analysis before dissing good but proprietary software.

See for yourself…

Here are the data I have obtained by running strace during Skype account creation server.

Since I love some good shell-one-liner action, here is the command that extracts the list of opened files from the strace data.

grep open skype.trace | perl -ne '/\"(.*)\"/ && print $1."\n";' | sort | uniq

Written by fdgonthier

November 3rd, 2009 at 8:00 pm