Wednesday, March 17, 2010

Marshal double dereferenced strings in C#

I have been working on some interesting bits and pieces of software that involve the use of C# on Windows Mobile. Specifically, I am using the DMProcessConfigXML() function call to feed an XML provisioning document in to Windows Mobile to change settings on the device.

Today I ran across the need to make full use of the function to query existing settings. To date, I had only pushed data in, I didn't have a need to actually read anything back out.

Where is where it gets fun. The data that is returned is defined as "LPWSTR* ppszwXMLout". Marshaling simple data types in C# isn't terribly hard, but a pointer to a pointer!? Such things are the crazy constructs of a C programmer! After digging around, I found a sample on jaredpar's blog that showed how to marshal a double dereferenced pointer to an integer. I figured getting a string would be similar, except the final step would be to marshal a string, instead of an int. Lucky for me, it really is that simple.

For more on the gory details, I would suggest clicking on the list to jaredpar's blog. He describes the details well, so I won't bother repeating his work. Instead, here is a quick bit of code that shows the difference for dealing with a string instead of an int :


public void queryProxyData()
{
IntPtr outptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
string query = "";

if (DMProcessConfigXML(query, 1, outptr) == 0)
{
// See if we can demarshal that crazy thing!
IntPtr newPtr = (IntPtr)Marshal.PtrToStructure(outptr, typeof(IntPtr));
string xmlData = Marshal.PtrToStringUni(newPtr);
Debug.WriteLine(xmlData);
Marshal.FreeHGlobal(newPtr);
}

Marshal.FreeHGlobal(outptr);
}


Pretty simple, huh? I can safely say this is a much better solution that a previous one that I found!

No comments:

Post a Comment