Microsoft KB Archive/317577

= FIX: Call to managed class method with StringBuilder as in or out parameter may fail =

Article ID: 317577

Article Last Modified on 2/23/2007

-

APPLIES TO


 * Microsoft .NET Framework 1.1
 * Microsoft .NET Framework 1.0
 * Microsoft .NET Framework Class Libraries 1.0

-



This article was previously published under Q317577



SYMPTOMS
When you call a managed method that takes System.Text.StringBuilder as a parameter from an unmanaged client, you may receive an ArgumentOutOfRangeException exception error message.



CAUSE
The unmanaged client calls the Test method of the class and passes a string that is larger than 16 characters.



RESOLUTION
To work around this problem, follow these steps:   Use IntPtr instead of System.Text.StringBuilder to build a modified managed server, as follows: using System; using System.Text; using System.Runtime.InteropServices; namespace Q317577 { public interface ITest{ void Test(ref IntPtr sbString, ref int length); }     public class Class1 : ITest{ public Class1{ }           public void Test(ref IntPtr sbString, ref int length){ Marshal.FreeCoTaskMem(sbString); string str = &quot;changed changed&quot;; length = str.Length; sbString = Marshal.StringToCoTaskMemUni(str); }     } }                      Use Regasm.exe to register the server, as follows:
 * 1) include 
 * 2) include 
 * 3) import &quot;Q317577.tlb&quot; no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[]) {     CoInitialize(NULL); try{ ITestPtr spTest; //wchar_t wszTestString[] = L&quot;This is a test.&quot;; wchar_t wszTestString[] = L&quot;A long long string for test.&quot;; long length = (wcslen(wszTestString) + 1) * sizeof(WCHAR); LPWSTR lpszTestString = (LPWSTR)::CoTaskMemAlloc(length); spTest.CreateInstance(CLSID_Class1); wcscpy((LPWSTR)lpszTestString, wszTestString); spTest->Test((long*)&lpszTestString,&length); MessageBoxW(NULL, (LPWSTR)lpszTestString, L&quot;Results&quot;, 0); ::CoTaskMemFree((LPWSTR)lpszTestString); }     catch(_com_error cerr){ MessageBox(NULL, cerr.Description, &quot;err&quot;, 0); }     CoUninitialize; return 0; }                   

If you are using Visual Studio .NET to build this application, follow these steps:
 * 1) In the IntOpTst Property Pages dialog box, click Configuration Properties, and then click Build. Change the Register for COM Interop value to True.
 * 2) Modify the unmanaged client code to make a call to the managed server.



STATUS
This bug was corrected in .NET Framework 2003|1.1.



MORE INFORMATION
During interoperation, the runtime ignores the size of the input string that is passed in. When an unmanaged client calls the Test method of the class and passes a string that is larger than 16 characters, the method fails with the COR_E_ARGUMENTOUTOFRANGE error code.

Steps to reproduce the behavior
Define a managed class with a method that resembles the following: using System; using System.Text; using System.Runtime.InteropServices; namespace Q317577 {      public interface ITest {       void Test(StringBuilder sbString); }   public class Class1 : ITest {       public Class1 {       }        public void Test(StringBuilder sbString) {                       string str = &quot;changed changed&quot;; sbString.Replace(sbString.ToString, str); }   } } Client code: int _tmain(int argc, _TCHAR* argv[]) {   CoInitialize(NULL); try {       ITestPtr spTest; //wchar_t wszTestString[] = L&quot;This is a test.&quot;; //<- This works wchar_t wszTestString[] = L&quot;A long long string for test.&quot;; long length = (wcslen(wszTestString) + 1) * sizeof(WCHAR); LPWSTR lpszTestString = (LPWSTR)::CoTaskMemAlloc(length); spTest.CreateInstance(CLSID_Class1); wcscpy((LPWSTR)lpszTestString, wszTestString); spTest->Test((LPWSTR)lpszTestString); MessageBoxW(NULL, (LPWSTR)lpszTestString, L&quot;Results&quot;, 0); ::CoTaskMemFree((LPWSTR)lpszTestString); }   catch(_com_error cerr) {       MessageBox(NULL, cerr.Description, &quot;err&quot;, 0); }   CoUninitialize; return 0; } Note The sample code assumes that the Q317577.tlb type library is in the same location as the source file. If this is not true, be sure that you add the path to the type library in the #import statement. When you compile the client from the command line, be sure that you specify the /EHsc compiler option.
 * 1) include 
 * 2) include 
 * 3) import &quot;Q317577.tlb&quot; no_namespace named_guids

Keywords: kbfix kbbug kbcominterop kbnofix KB317577

-

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

© Microsoft Corporation. All rights reserved.