Bug 323900 (MONO81218) - [PATCH] Marshalling strings as out parameters doesn't work properly.
Summary: [PATCH] Marshalling strings as out parameters doesn't work properly.
Status: RESOLVED FIXED
Alias: MONO81218
Product: Mono: Runtime
Classification: Mono
Component: interop (show other bugs)
Version: 1.2
Hardware: Other Other
: P3 - Medium : Normal
Target Milestone: ---
Assignee: Mono Bugs
QA Contact: Mono Bugs
URL:
Whiteboard:
Keywords: interop
Depends on:
Blocks:
 
Reported: 2007-03-23 15:25 UTC by Vincent Finn
Modified: 2008-02-27 13:16 UTC (History)
2 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
Visual studio projects to reproduce the bug (5.51 KB, application/octet-stream)
2007-03-23 15:26 UTC, Thomas Wiest
Details
Patch (1.99 KB, patch)
2007-12-13 21:14 UTC, Jonathan Chambers
Details | Diff
Updated patch and tests (4.89 KB, patch)
2007-12-19 04:06 UTC, Jonathan Chambers
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wiest 2007-09-15 20:33:30 UTC


---- Reported by vincent.finn@riverdocs.com 2007-03-23 08:25:56 MST ----

Hi,

I have a function exported from a C++ dll, one of the parameters is an out
parameter, the code in the dll calls CoTaskMemAlloc() to return a string.
The signature is this:
void Execute(wchar_t* pIn, int inLength, wchar_t*& pOut, int* pOutLength)

I am building using Visual Studio 2005 and there are two options to define
this in C#:

[DllImport("C:/interop/release/Controller.dll", EntryPoint = "Execute",
CharSet = CharSet.Unicode)]
private static extern void ExecuteWithIntPtr(
  [MarshalAs(UnmanagedType.LPWStr)] string commandIn, 
  int inLength,
  out IntPtr commandOut, 
  out int outLength);

[DllImport("C:/interop/release/Controller.dll", EntryPoint = "Execute",
CharSet = CharSet.Unicode)]
private static extern void ExecuteWithWStr(
  [MarshalAs(UnmanagedType.LPWStr), In] string commandIn,
  int inLength, 
  [MarshalAs(UnmanagedType.LPWStr), Out] out string commandOut,
  out int outLength);

The second method is easier to use since the marshaller does all the work
and you don't have to free the memory yourself.
Both methods work using the .Net Framework (i.e. run from visual studio
under IIS), only the second method, ExecuteWithIntPtr(), works properly
with mono, ExecuteWithWStr() only returns the first character.

Steps to reproduce the problem:
1. Download the attached file. The first project is the dll, the second is
the web application.
2. Build them using Visual Studio. (The path to Controller.dll is hardcoded
in WebSite1/Default.aspx.cs so this will need to be changed).
3. Run the web site using Visual Studio, when you click the "Test" buttons
the will return the same values.
4. Run the web site using mono XSP 2.0 Web Server, the first test will be
correct, the second will be incorrect.

Actual Results:
The broken version of the function only returns 1 character when run under
mono, the working version returns the original string repeated 101 times.

Expected Results:
Both versions should return the original string repeated 101 times.

How often does this happen? 
This happens every time.



---- Additional Comments From vincent.finn@riverdocs.com 2007-03-23 08:26:52 MST ----

Created an attachment (id=171708)
Visual studio projects to reproduce the bug


Imported an attachment (id=171708)

Unknown bug field "cf_op_sys_details" encountered while moving bug
   <cf_op_sys_details>Xp Sp2</cf_op_sys_details>
Unknown operating system unknown. Setting to default OS "Other".

Comment 1 Marek Habersack 2007-09-17 08:26:36 UTC
-> runtime
Comment 2 Jonathan Chambers 2007-12-13 21:14:27 UTC
Created attachment 187528 [details]
Patch

Patch to marshal strings as out params using correct conversion.
Comment 3 Forgotten User vxPDddArjq 2007-12-14 14:35:15 UTC
The patch seems to remove this part, and doesn't replace it with anything:

-		} else {
-			if (mono_marshal_need_free (t, m->piinfo, spec)) {
-				mono_mb_emit_ldloc (mb, conv_arg);
-				if (conv == MONO_MARSHAL_CONV_STR_BSTR)
-					mono_mb_emit_icall (mb, mono_free_bstr);
-				else
-					mono_mb_emit_icall (mb, mono_marshal_free);
-			}
+
 		}
Comment 4 Jonathan Chambers 2007-12-19 04:06:39 UTC
Created attachment 188162 [details]
Updated patch and tests

I restored the logic I accidentally removed. We now free memory the same as we previously did, and also if the parameter is an out param.
Comment 5 Forgotten User vxPDddArjq 2007-12-19 12:33:59 UTC
This looks ok to check in.
Comment 6 Forgotten User vxPDddArjq 2008-01-17 21:50:43 UTC
Jonathan, could you check this in ?
Comment 7 Forgotten User vxPDddArjq 2008-02-27 13:16:33 UTC
-> FIXED.