Cook Computing

« April 2002 »

This C++ program compiled with

This C++ program compiled with /clr sums up what I don't like about Managed C++. It runs without complaint even though the buffer overrun is corrupting both allocated memory and unallocated memory, deallocated memory is accessed (admittedly the latter problem is trapped in the debug build but problems often occur only when running in released code), and an unitialized variable is used. A couple of people I've discussed this with are surprised that IL can access unmanaged types so I've included the output from ILDASM below.

void main(void)
{
   char* buff1 = new char[16];
   char* buff2 = new char[16];
   for (int i = 0; i < 33; i++)
     buff1[i] = i;
   delete buff1;
  int x;
   *buff1 = x;
 }

This is no different to what you'd expect with a conventional C++ program, and I should mention that you can also write unsafe code in C# using pointers (it has to be explicitly marked as unsafe), but the ease with which you can use unmanaged types in C++, combined with the temptation to reuse pieces of existing C++ code, suggests to me that many new projects written in Managed C++ code will succumb to using unmanaged types. I think that this will be a mistake because one of the advantages of the managed environment is that you can develop applications which are not subject to problems like these. To quote the Framework SDK docs:

In the core C# language it is simply not possible to have an uninitialized variable, a "dangling"; pointer, or an expression that indexes an array beyond its bounds. Whole categories of bugs that routinely plague C and C++ programs are thus eliminated.

Why throw these advantages away if you are developing new code?

.method public static
int32 modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) 
        main() cil managed
{
  .vtentry 1 : 1
  // Code size       58 (0x3a)
  .maxstack  2
  .locals ([0] int32 i,
           [1] int8 modopt([Microsoft.VisualC]Microsoft.VisualC.NoSignSpecifiedModifier)*
buff1,
           [2] int32 x)
  IL_0000:  ldc.i4.s   16
  IL_0002:  call       void* modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
new(unsigned int32)
  IL_0007:  stloc.1
  IL_0008:  ldc.i4.s   16
  IL_000a:  call       void* modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
new(unsigned int32)
  IL_000f:  pop
  IL_0010:  ldc.i4.0
  IL_0011:  stloc.0
  IL_0012:  ldloc.0
  IL_0013:  ldloc.1
  IL_0014:  add
  IL_0015:  ldloc.0
  IL_0016:  stind.i1
  IL_0017:  ldloc.0
  IL_0018:  ldc.i4.1
  IL_0019:  add
  IL_001a:  stloc.0
  IL_001b:  ldloc.0
  IL_001c:  ldc.i4.s   33
  IL_001e:  blt.s      IL_0012
  IL_0020:  ldloc.1
  IL_0021:  call       void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
delete(void*)
  IL_0026:  ldloc.1
  IL_0027:  ldloc.2
  IL_0028:  stind.i1
  IL_0029:  ldsflda    valuetype $ArrayType$0x52715acd
??_C@_03OHDNLOHO@one?$AA@
  IL_002e:  newobj     instance void [mscorlib]System.String::.ctor(int8*)
  IL_0033:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0038:  ldc.i4.0
  IL_0039:  ret
} // end of method 'Global Functions'::main
Posted by Charles Cook at 08:30 PM. Permalink. View Comments.

I noticed this evening when

I noticed this evening when making a SOAP request to a XML-RPC.NET Remoting server that if the server throws an instance of XmlRpcFaultException (which in the XML-RPC case would be automatically mapped onto a Fault Response) the exception object was not returned to the client - because it could not be serialized. At first I naively assumed that marking the XmlRpcFaultException class with the Serializable attribute would be sufficient. But there is more to it than this.

The problem is that XmlRpcFaultException has System.Exception as one of its base classes and System.Exception derives from ISerializable. If a base class derives from this interface, derived classes also have to implement the ISerializable interface rather than rely on the default serialization provided by the Serializable attribute (though this attribute is still required). Two methods must be implemented: GetObjectData to serialize the object with the data required to persist its state and a deserialization constructor to rehydrate the object from the serialized state. Note that both these methods must invoke the corresponding method on the immediate base class.

The relevant parts of XmlRpcFaultException now look like this:

[Serializable]
public class XmlRpcFaultException : ApplicationException
{
  // deserialization constructor
  protected XmlRpcFaultException(SerializationInfo info,  
                                 StreamingContext context) 
    : base(info, context) 
  {
    m_faultCode = (int)info.GetValue("m_faultCode", typeof(int));
    m_faultString = (String)info.GetValue("m_faultString", 
                                          typeof(string));
  }
  // .... 
  public override
   void GetObjectData(SerializationInfo info, 
                      StreamingContext context)
  {
    info.AddValue("m_faultCode", m_faultCode);
    info.AddValue("m_faultString", m_faultString);
    base.GetObjectData(info, context);
  }
  int m_faultCode;
  string m_faultString;
}
Posted by Charles Cook at 09:21 PM. Permalink. View Comments.

Ingo Rammer describes the work

Ingo Rammer describes the work he and Tomas Restrepo are doing with XML-RPC and formatters:

Ok, but we've been running with a different focus. We're currently in progress of extending the formatter to include the ability to marshal ISerializable and [Serializable] objects in addition to structs for a better compatibility with the general Remoting framework. Tomas is also about to change the serializer to implement IRemotingFormatter - maybe we can merge some code later on!

Yes, the formatter code I've added to XML-RPC.NET just extends the library so that Remoting can be used instead of the existing web service-based approach. Its not designed to reproduce everything that Remoting does with respect to serializing data types, preferring instead to concentrate on maintaining interoperability with other XML-RPC implementations. The use of Remoting with XML-RPC.NET does offer a couple of advantages over the existing implementation: first, it enables you to run an XML-RPC server outside of IIS (as in the StateNameServer example), and second, it enables you to implement an XML-RPC server which can also accept SOAP requests.

I'm looking foward to seeing how Ingo and Tomas solve what looks like a considerably more complex challenge.

Posted by Charles Cook at 07:49 AM. Permalink. View Comments.

I received Ingo Rammer's excellent

I received Ingo Rammer's excellent book Advanced .NET Remoting from Amazon a few days ago and this was the spur I needed to experiment with .NET Remoting. After a couple of long coding sessions this weekend I've released version 0.5.0 of XML-RPC.NET which contains XML-RPC client and server formatter sinks. These enable the .NET remoting infrastructure to be used to implement both XML-RPC clients and servers. In addition, the server-side formatter can be configured so that a server can simultaneously support both XML-RPC and SOAP requests. If the XML-RPC formatter detects an incoming request is a SOAP request, it forwards the request to the default SOAP formatter; otherwise it processes the request as an XML-RPC request.

Some preliminary documentation on .NET Remoting is included on the Samples page. It should be noted that the XML-RPC formatter is not intended to replace SOAP when making calls between .NET clients. The XML-RPC serialization code is designed for use with XML-RPC parameters and is not as comprehensive as the built-in SOAP serialization code, so there wouldn't be much point in using XML-RPC in this scenario.The XML-RPC formatter is instead intended to be used where either client or server is not based on .NET Remoting and XML-RPC is being used, or where a server is required to handle both SOAP and XML-RPC requests.

Posted by Charles Cook at 10:16 PM. Permalink. View Comments.

Yes, this is a sad

Yes, this is a sad situtation IMHO. After 2 years in .NET, I tire of C#'s limitations and I end up choosing MC++ even for new things but I am not the general case-). It is my powertool of choice. Many people see as only used for Interop but it is a very powerful managed language in its own right. [Sam Gentile's Radio Weblog]

This is an example of what is confusing me about Managed C++. Its benefits for Interop are clear but I still can't see what advantages it has for purely managed work. In that environment you have an emasculated version of C++ and some ugly extra syntax. Perhaps if the Managed C++ advocates can explain why they believe it is more powerful than C# for new managed work then things can be made more clear.

Posted by Charles Cook at 07:23 AM. Permalink. View Comments.

Peter Drayton promotes the cause

Peter Drayton promotes the cause of Managed C++. Admittedly I don't have much experience with Managed C++ yet but I can't see what extra power Managed C++ gives you if you're implementing managed code using managed types. As soon as you start coding with traditional C++ features such as MI you have unmanaged types and the extra work to get them to work with managed types. Working with C# just seems easier all round, not having to use header files for example, and does produce assemblies which are pure IL. If people develop new projects in Managed C++ then there's a risk they will be writing new legacy code which will cause problems in the future as .NET is ported to other platforms.

Posted by Charles Cook at 08:49 AM. Permalink. View Comments.

The first thing I've noticed

The first thing I've noticed with COM interop is that if you have managed C++ classes which are holding pointers to COM objects, the final release of the COM objects (in the destructor of the managed classes) occurs after you have called CoUninitialize (as the managed objects are finalized at program termination). Calling GC.Collect before CoUninitialize does result in the final releases happening before CoUninitialize but I just realized that the destructor of the managed classes may be called on a different thread. I remember from the course a couple of weeks ago that GC is a two phase operation - determine which objects are to finalized and then finalize them - and the second phase occurs on a background thread. So which apartment, if any, is the background thread running in? Looks like I have much to learn about COM Interop.

Posted by Charles Cook at 07:22 AM. Permalink. View Comments.

I've started a small project

I've started a small project in Managed C++. Its a library which encapsulates some COM APIs and using Managed C++ seemed the obvious approach to minimising the effort around COM Interop. Its something I've been meaning to do for a while and its fairly limited scope will provide a good introduction to Managed C++. I read someone recently claiming that the majority of managed software development in the near future will involve porting existing C++ code using Managed C++ and I would also guess that is likely to be the case. You can be sure that the added complexity of handling both managed and unmanaged code/types in the same project will cause even worse maintenance nightmares than many C++ projects have already.

Coming from a COM background the old lack of deterministic finalization problem still rears its ugly head and as yet I can't see a solution other than calling GC.Collect fairly frequently. I've done a lot of COM work in situations where the COM objects represent scarce resources and it is essential that an object has final release called on it as soon as a clent is finished with it. IDisposable and the using construct may support a new paradigm for resource management but as yet I'm unconvinced. I can see their use in simple situations but not when passing around references to objects which are consuming resources. I may be wrong - hence the small trial project before getting involved in anything more substantial.

Posted by Charles Cook at 07:19 PM. Permalink. View Comments.

I've been experimenting with the

I've been experimenting with the .NET Framework RealProxy class, seeing if it can be used to generate transparent proxies which can be used in XML-RPC clients. I've posted some sample code on the XMLRPCNET Yahoo group. I have to admit that I've not really learnt much about .NET remoting yet. This is the one topic I thought was missing from the Intensive .NET course last week. An extra day devoted to remoting would have been very useful. I've since order Ingo Rammer's book Advanced .NET Remoting. Based on this description the book sounds interesting.

Posted by Charles Cook at 08:07 AM. Permalink. View Comments.

I've posted another XML-RPC.NET sample

I've posted another XML-RPC.NET sample to the XMLRPCNET Yahoo group. The sample illustrates how the XmlRpcSerializer class can be used to serialize and deserialize XML-RPC requests and responses between the XmlRpcRequest/XmlRpcResponse classes and XML documents in streams.

Posted by Charles Cook at 10:16 PM. Permalink. View Comments.

I found it impossible to

I found it impossible to input the stuff below on CAS as a single entry. Blogger barfed every time I tried. So I had to split it into two entries. Maybe time to evaluate some other blogging tool.

Posted by Charles Cook at 07:04 AM. Permalink. View Comments.

CAS Part II A better

CAS Part II
A better approach would have been to lock down locally running apps by default to a minimal set of permissions, say the default permissions of the Internet Zone minus the ability to connect to a server. This would would have been an unambiguous signal that the days of running untrusted applications is over but does raise the issue of how an application would be given the permissions it requires. One solution would be for Microsoft to provide a managed GUI Permission Manager component which could be invoked by an installer. The installer would supply full details of the components being installed and the permissions they require. The Permission Manager component would then ask the user whether they want to hand out these permissions and then configure the application if the users agrees. The installer could try to display a spoofed version of the Permission Manager component but this would not work because the installer would not have the permissions to configure the app.

This could become quite sophisticated. The installer could ask for different levels of permissions so that a more careful user could restrict more widely what the installed app could do. If the user did not grant the app sufficient permissions then every time the app is run it could invoke the Permission Manager component. In this way the user never has to launch a security tool: either the installer or the application itself launches the Permission Manager which means that whenever the Permission Manager runs it displays information specific to the application, i.e. the user never has to input anything about the app, only to respond to requests for permissions.

It seems a waste to have such a capable approach to Code Access Security and then not use it. Hopefully future versions of .NET and operating systems running .NET will take full advantage of CAS.

Posted by Charles Cook at 06:59 AM. Permalink. View Comments.

CAS Part I Im attending

CAS Part I
Im attending a DevelopMentor course this week Intensive .NET. Today we covered Code Access Security in great depth. Its a great security model for stopping rogue applications from doing things you dont want them to do. Unfortunately the current default for applications running locally from the hard disk on your machine is full trust, whereas on the other hand, Microsoft perversely changed the default for applications running from the Internet in .NET SP 1 so that they have no permissions and cannot run even in the Internet zone sandbox. This is a problem because it is much easier for someone to download such an application to disk, and so run it with full trust, than it is to configure the application to run safely from the Internet.

In the class we discussed the issue of how to install and configure an application so it only has the minimum set of necessary permissions or possibly only those permissions that the user trusts it to run with. Getting a typical user to run the mscorcfg MMC snap-in or even worse the command line program caspol is not realistic. One suggestion was that the application vendor supplies some an installation package which runs with sufficient permissions (for example as unmanaged code) to set the permissions of the application being installed. But this does not really make much sense from a security point of view (even though this is essentially what Microsoft is suggesting you do to give downloadable smart clients permissions).

Posted by Charles Cook at 09:51 PM. Permalink. View Comments.

Version 0.4.3 of XML-RPC.NET is

Version 0.4.3 of XML-RPC.NET is now available. It is an interim release with a few bug fixes, mainly in the serialization/deserialization code.

The sample MathService XML-RPC service is now at: http://www.dev1.eraserver.net/COOKCOMPUTING/math.aspx

Posted by Charles Cook at 09:24 PM. Permalink. View Comments.

aspnet_wp.exe could not be launched

aspnet_wp.exe could not be launched because the username and/or password supplied in the processModel section of the config file are invalid.

Most of the hits on this site are from Google for some variant of the above sentence. I'm mentioning here again to save people searching the site archives.

This Microsoft support article explains the problem I had with configuring ASP.NET. Interesting to note that they suggest changing the account to SYSTEM without mentioning the potential security issues with that account. I chose to use SYSTEM on my dev box but its probably not recommended for a production server (well, a production server should not be a DC anyway).

Posted by Charles Cook at 06:20 PM. Permalink. View Comments.

I just discovered a problem

I just discovered a problem in the deserialization code in XML-RPC.NET. It shows itself when structs are being deserialized. The .NET RTM code included a change to the operation of Type.GetType() which means the deserialization code for arrays of user-defined types now has to pass an assembly-qualified name to GetType().

I'll put out an updated release tomorrow.

Posted by Charles Cook at 06:08 PM. Permalink. View Comments.

The XMLRPCNET group at Yahoo

The XMLRPCNET group at Yahoo is now appearing in the directory. I've posted the first of a series of samples based on some of the publicly used XML-RPC APIs - sample proxy and client code for the Web Bug Simulator API.

Posted by Charles Cook at 10:52 AM. Permalink. View Comments.

Created a Yahoo Group for

Created a Yahoo Group for discussion of XML-RPC.NET issues. The group is XMLRPCNET.

Note: the new group does not seem to have propagated through the Yahoo system yet.

Posted by Charles Cook at 07:54 AM. Permalink. View Comments.