Click here to Skip to main content
Click here to Skip to main content

Getting a string out of a ref ushort

, 17 Aug 2007
Rate this:
Please Sign up or sign in to vote.
Handling string parameters incorrectly declared as ref ushort

Introduction

The Microsoft PIA for MSHTML is riddled with method signatures that incorrectly declare string parameters as ref ushort, making them unusable.

This article explains how to get and set strings incorrectly declared as ref ushort.

Background

A PIA (primary interop assembly) is the vendor's official rendering of the interfaces of some COM object(s). It's signed and so forth, so you can't alter it. When a PIA contains incorrect declarations of parameters or marshalling hints, it can be nigh impossible to use the incorrectly declared methods.

You can't dodge the problem with typecasting. The strings in question are declared as POLECHAR, which is a pointer to the first element of a null terminated array of unicode characters. A unicode character is 16 bits wide and unsigned, and you need a pointer to it, hence ref ushort.

You could use tlbimp.exe to import the interfaces and then correct them. All you have to do is replace "ref ushort" with "string". But nothing is ever that easy. The webbrowser control uses the Microsoft PIA and C# strong typing treats your declarations and the PIA equivalents as totally different. You can explicitly typecast, but you'll have to typecast everything. This works, but the code is illegible and unmaintainable (I tried).

So, tblimp.exe hasn't exactly got it wrong but there's no way to directly typecast a ref ushort to a string, and we can't alter the interop assembly, and we can't replace it.

All is now lost... or not. Enter the Marshal class.

We get the string like this:

//create a managed string and copy the content of the OLECHAR 
//string pointed at by lpwszBlah into this string
string blah = Marshal.PtrToStringUni((IntPtr)lpwszBlah);

And going the other way (if we change it)...

//lpwszBlah is a pointer, so we return a value by writing it to 
//global memory and putting a pointer to the new value into lpwszBlah 
//but first we free the old buffer
Marshal.FreeHGlobal(lpwszBlah);
lpwszBlah = Marshal.StringToHGlobalUni(blah);

Points of Interest

There are unicode, ANSI and Auto versions of most of the string marshalling methods. Auto selects ANSI or unicode behaviour depending on the underlying platform. In some cases, such as dealing with COM, the string type is platform invariant and the auto versions of these calls will fail on legacy platforms. For exampe, MSHTML uses POLECHAR on all platforms, and Marshal.PtrToStringAuto((IntPtr)lpwszBlah) would incorrectly parse the data as an ANSI string under Windows 9x.

The Marshal class is a point of interest all on its own. How do you think Microsoft does all that wonderful magic conversion? Sure, you hint the process with attributes, but sooner or later the rubber hits the road, and generally Marshal is involved. Microsoft has very thoughtfully made this incredibly handy class directly accessible, and in a departure from tradition even documented it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Peter Wone
Web Developer
Australia Australia
On a personal level (this is a bio, after all) I love gourmet coffee and my wine collection is pretty good. My passion is alpine skiing. On a more technical level, I've been a Delphi/MSSQL hack for donkey's years. VB is a distant memory. It resurfaced as VB.NET but I managed not to get any on me. Java was nice. C# is nicer. Pet peeve: kids today don't appear to know what an RFC is. Or how to spell. My one consolation is that no matter what they get away with at school and on message boards, with a compiler they have to stop their bullsh*t and spell properly.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 17 Aug 2007
Article Copyright 2007 by Peter Wone
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid