Microsoft KB Archive/327109

= BUG: StringBuilder Field in a Structure Cannot Be Marshaled Properly =

Article ID: 327109

Article Last Modified on 2/23/2007

-

APPLIES TO


 * Microsoft .NET Framework 1.0
 * Microsoft .NET Framework 1.1

-



This article was previously published under Q327109



SYMPTOMS
If you marshal a structure that contains a StringBuilder field to an unmanaged function, the StringBuilder field is not marshaled correctly.



RESOLUTION
If you must initialize a buffer to some value before you pass to an unmanaged function, use one of the following workarounds:   Use the StringBuilder class, and apply to ANSI and Unicode strings. For example: StringBuilder buffer = new StringBuilder(&quot;content&quot;, 100); buffer.Append((char)0); buffer.Append('*', buffer.Capacity - 8); //add anything to the end

MyStrStruct mss; mss.buffer = buffer.ToString; mss.size = mss.buffer.Length; Win32.TestStringInStruct(ref mss); // call unmanaged function   Use the Marshal class, and apply only to Unicode strings. For example: IntPtr pMem = Marshal.AllocCoTaskMem(100); String inString = &quot;content&quot;; Marshal.Copy(inString.ToCharArray, 0, pMem, inString.Length); MyStrStruct mss; mss.buffer = pMem; mss.size = 100; Win32.TestStringInStruct(ref mss); // call unmanaged function String outString = Marshal.PtrToStringAuto(mss.buffer); Marshal.FreeCoTaskMem(pMem); 



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.



MORE INFORMATION
To reproduce this problem, use the following code: using System; using System.Runtime.InteropServices; using System.Text;

namespace Test {   [StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO {       public Int32 cb; public StringBuilder lpReserved; public StringBuilder lpDesktop; public StringBuilder lpTitle; public Int32 dwX; public Int32 dwY; public Int32 dwXSize; public Int32 dwYSize; public Int32 dwXCountChars; public Int32 dwYCountChars; public Int32 dwFillAttribute; public Int32 dwFlags; public Int16 wShowWindow; public Int16 cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; }

/*   Original unmanaged structure: typedef struct _STARTUPINFO {        DWORD   cb; LPTSTR lpReserved; LPTSTR lpDesktop; LPTSTR lpTitle; DWORD  dwX; DWORD  dwY; DWORD  dwXSize; DWORD  dwYSize; DWORD  dwXCountChars; DWORD  dwYCountChars; DWORD  dwFillAttribute; DWORD  dwFlags; WORD   wShowWindow; WORD   cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } STARTUPINFO, *LPSTARTUPINFO; */

class TestAPI {       [DllImport(&quot;kernel32.dll&quot;)] public static extern void GetStartupInfo(ref STARTUPINFO lpStartupInfo);

[STAThread] static void Main(string[] args) {           STARTUPINFO startinfo = new STARTUPINFO; startinfo.lpReserved = new StringBuilder(256); startinfo.lpDesktop = new StringBuilder(256); startinfo.lpTitle = new StringBuilder(256); GetStartupInfo(ref startinfo); }   } } If you compile and run this code, you receive a System.TypeLoadException exception, which contains the following information:

Marshaler restriction: StringBuilders can not be used in structure fields. The same effect can usually be achieved by using a String field and preinitializing it to a string with length matching the length of the appropriate buffer.

Keywords: kbbug kbcominterop kbnofix KB327109

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.