Exemple #1
0
        public IntPtr MarshalManagedToNative(object managedObj)
        {
            MyProps t = MyProps.GetTop(m_Index);

            switch (t.GetStage())
            {
            case 0:
            {
                // We are just starting a "Managed calling unmanaged"
                // call.

                // Cast the object back to a PropVariant and save it
                // for use in MarshalNativeToManaged.
                t.m_obj = managedObj as PropVariant;

                // This could happen if (somehow) managedObj isn't a
                // PropVariant.  During normal marshaling, the custom
                // marshaler doesn't get called if the parameter is
                // null.

                // Release any memory currently allocated in the
                // PropVariant.  In theory, the (managed) caller
                // should have done this before making the call that
                // got us here, but .Net programmers don't generally
                // think that way.  To avoid any leaks, do it for them.
                t.m_obj.Clear();

                // Create an appropriately sized buffer (varies from
                // x86 to x64).
                int iSize = GetNativeDataSize();
                t.m_ptr = t.Alloc(iSize);

                // Copy in the (empty) PropVariant.  In theory we could
                // just zero out the first 2 bytes (the VariantType),
                // but since PropVariantClear wipes the whole struct,
                // that's what we do here to be safe.
                Marshal.StructureToPtr(t.m_obj, t.m_ptr, false);

                break;
            }

            case 1:
            {
                if (!System.Object.ReferenceEquals(t.m_obj, managedObj))
                {
                    // If we get here, we have already received a call
                    // to MarshalNativeToManaged where we created a
                    // PropVariant and stored it into t.m_obj.  But
                    // the object we just got passed here isn't the
                    // same one.  Therefore instead of being the second
                    // half of an "Unmanaged calling managed" (as
                    // m_InProcsss led us to believe), this is really
                    // the first half of a nested "Managed calling
                    // unmanaged" (see Recursion in the comments at the
                    // top of this class).  Add another layer.
                    MyProps.AddLayer(m_Index);

                    // Try this call again now that we have fixed
                    // m_CurrentProps.
                    return(MarshalManagedToNative(managedObj));
                }

                // This is (probably) the second half of "Unmanaged
                // calling managed."  However, it could be the first
                // half of a nested usage of PropVariants.  If it is a
                // nested, we'll eventually figure that out in case 2.

                // Copy the data from the managed object into the
                // native pointer that we received in
                // MarshalNativeToManaged.
                Marshal.StructureToPtr(t.m_obj, t.m_ptr, false);

                break;
            }

            case 2:
            {
                // Apparently this is 'part 3' of a 2 part call.  Which
                // means we are doing a nested call.  Normally we would
                // catch the fact that this is a nested call with the
                // ReferenceEquals check above.  However, if the same
                // PropVariant instance is being passed thru again, we
                // end up here.
                // So, add a layer.
                MyProps.SplitLayer(m_Index);

                // Try this call again now that we have fixed
                // m_CurrentProps.
                return(MarshalManagedToNative(managedObj));
            }

            default:
            {
                Environment.FailFast("Something horrible has " +
                                     "happened, probaby due to " +
                                     "marshaling of nested " +
                                     "PropVariant calls.");
                break;
            }
            }
            t.StageComplete();

            return(t.m_ptr);
        }