I wrote a test program (attached), and it doesn't work:
CreateDomain failed, hr=80004002
I didn't investigate, but I remember the issue I ran into when I tried to implement this. AppDomain.CreateDomain doesn't return a "real" AppDomain object, it returns a TransparentProxy, and the TransparentProxy doesn't support the _AppDomain interface. The real AppDomain object lives in the newly-created appdomain.
I think you could get the real AppDomain and an IUnknown pointer for it if you used the newly-created MonoDomain, but I suspect the MonoDomain pointer you're getting is also wrong.
Also, I'm not sure it's necessary to lock the RuntimeHost while creating the new AppDomain, it should only be needed when accessing the list.
It might be possible to invoke AppDomain.Id on the new (proxy) object, use mono_domain_get_by_id to get the MonoDomain*, then invoke AppDomain.CurrentDomain to get the real AppDomain object in that domain.
BTW, I think I made a mistake when I added the domains list. We should probably just rely on Mono to keep track of domains (other than the default domain), so we can be aware of domains created by calling AppDomain methods directly.