2

I am trying to use the GetSystemWow64Direcory method from my application. The sample from PInvoke.net seems incorrect to me. Don't I have to pin the the array before passing to the unmanaged call?

[DllImport("Kernel32.dll")]
public static extern int GetSystemWow64Directory([In, Out] char[] lpBuffer
    [MarshalAs(UnmanagedType.U4)] uint size);

char[] path = new char[256];

int result = GetSystemWow64Directory(path, (uint)path.Length);
if (result != 0)
    MessageBox.Show(new String(path, 0, result));
pstrjds
  • 16,840
  • 6
  • 52
  • 61
  • It does seem incorrect on the surface, I'd have used a StringBuilder, and it's only an OUT param for the lpBuffer I don't know why they'd use [In] :/ – Lloyd Feb 15 '13 at 15:42
  • @Lloyd: looks like the [StringBuilder is treated in a special](http://msdn.microsoft.com/en-us/magazine/cc164193.aspx#S4) way by the CLR because of it's capacity property – user1416420 Feb 15 '13 at 16:19

3 Answers3

2

No need to pin it - the marshalling will handle it all for you.

It doesn't have to use StringBuilder, but you can (in fact it probably is best to):

public static extern int GetSystemWow64Directory(StringBuilder lpBuffer, uint size);
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 2
    right you are [Marshaling between Managed and Unmanaged Code: Copying and Pinning](http://msdn.microsoft.com/en-us/magazine/cc164193.aspx#S5) – user1416420 Feb 15 '13 at 16:16
  • 1
    "It's not using StringBuilder because you pass in the buffer AND its size." I'm not sure what you meant by this but it doesn't appear, on the face of it, to make sense. – Stephen Martin Feb 15 '13 at 17:49
  • I agree with Stephen. That sentence doesn't make sense and there's no difficulty using StringBuilder here. In fact when using SB to get strings you **always** pass both buffer and size. – David Heffernan Feb 15 '13 at 18:00
  • I should have said "it doesn't *have* to use a StringBuilder". I've clarified my post. – Matthew Watson Feb 16 '13 at 00:54
2

Well, you don't need to pin, the marshaller will take care of that for you.

But, it's a poor p/invoke. My advice is not to trust what you find on pinvoke.net, the quality is very varied. I'd use StringBuilder here.

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern int GetSystemWow64Directory(
    StringBuilder Buffer, 
    int Size
);
....
StringBuilder Buffer = new StringBuilder(260);
int retVal = GetSystemWow64Directory(Buffer, Buffer.Capacity);
if (retVal != 0)
    MessageBox.Show(Buffer.ToString());
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

Objects you pass to native methods are automatically pinned for the duration of the call by the marshaller.

For more details see http://msdn.microsoft.com/en-us/magazine/cc163910.aspx#S2

You only need to manually pin if the object you've passed to native code will be used asynchronously (i.e. after the call passing the object is done executing)

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98