StackOverflowUser
StackOverflowUser

Reputation: 1

Parameters don't match function signature when intercept CoCreateInstanceEx with a VB6 program

I have a weird parameter issue while intercepting the CoCreateInstanceEx function with a VB6 program. According to MSDN docs, the CoCreateInstanceEx signature is:

HRESULT CoCreateInstanceEx(
  [in]      REFCLSID     Clsid,
  [in]      IUnknown     *punkOuter,
  [in]      DWORD        dwClsCtx,
  [in]      COSERVERINFO *pServerInfo,
  [in]      DWORD        dwCount,
  [in, out] MULTI_QI     *pResults
);

The dwCount parameter should be the array length of pResult, but in the hooked HookedCoCreateInstanceEx function, I get dwCount = 4 but the length of pResults is only 1. So I guess maybe the original CoCreateInstanceEx will increase the array size, but after calling the original function with all parameters without modifications, I get hr = 0x80070057 (E_INVALIDARG).

Any ideas of insight MSVBVM6.dll calling to CoCreateInstanceEx?


UPDATE

It's for 32bit, and yes stdcall is used. Here are the codes:

        public class COSERVERINFO : IDisposable
        {
            internal COSERVERINFO(string srvname, IntPtr authinf)
            {
                servername = srvname;
                authinfo = authinf;
            }

    #pragma warning disable 0649
            internal int reserved1;
    #pragma warning restore 0649
            [MarshalAs(UnmanagedType.LPWStr)]
            internal string servername;
            internal IntPtr authinfo;                // COAUTHINFO*
    #pragma warning disable 0649
            internal int reserved2;
    #pragma warning restore 0649
            void IDisposable.Dispose()
            {
                authinfo = IntPtr.Zero;
                GC.SuppressFinalize(this);
            }
            ~COSERVERINFO()
            {
            }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct MULTI_QI : IDisposable
        {
            internal MULTI_QI(IntPtr pid)
            {
                piid = pid;
                pItf = IntPtr.Zero;
                hr = 0;
            }

            internal IntPtr piid;        // 'Guid' can't be marshaled to GUID* here? use IntPtr buffer trick instead
            internal IntPtr pItf;
            internal int hr;

            void IDisposable.Dispose()
            {
                if (pItf != IntPtr.Zero)
                {
                    Marshal.Release(pItf);
                    pItf = IntPtr.Zero;
                }
                if (piid != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(piid);
                    piid = IntPtr.Zero;
                }
                GC.SuppressFinalize(this);

            }
        }

    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
    delegate int CoCreateInstanceExDelegate(
       ref Guid clsid,
       IntPtr punkOuter,
       int dwClsCtx,
       [In, Out] COSERVERINFO pServerInfo,
       int dwCount,
       [In, Out] MULTI_QI[] pResults);

    static IntPtr _originalCoCreateInstanceExPtr;
    static CoCreateInstanceExDelegate _originalCoCreateInstanceEx;

And this is the code for EasyHook IEntryPoint Run method:

        public void Run(RemoteHooking.IContext context)
        {
            _originalCoCreateInstanceExPtr = GetProcAddress(GetModuleHandle("ole32.dll"), "CoCreateInstanceEx");
            _originalCoCreateInstanceEx = Marshal.GetDelegateForFunctionPointer<CoCreateInstanceExDelegate>(_originalCoCreateInstanceExPtr);

            var hook = LocalHook.Create(
                _originalCoCreateInstanceExPtr,
                new CoCreateInstanceExDelegate(HookedCoCreateInstanceEx),
                null);

            hook.ThreadACL.SetExclusiveACL(new int[] { 0 });

            RemoteHooking.WakeUpProcess();

            while (true)
            {
                System.Threading.Thread.Sleep(1000);
            }
        }

I get weird parameters in HookedCoCreateInstanceEx:

    static int HookedCoCreateInstanceEx(
       ref Guid clsid,
       IntPtr punkOuter,
       int dwClsCtx,
       [In, Out] COSERVERINFO pServerInfo,
       int dwCount,
       [In, Out] MULTI_QI[] pResults)
    {
        // Call original CoCreateInstanceEx
        int hr = _originalCoCreateInstanceEx(ref clsid, punkOuter, dwClsCtx, pServerInfo, dwCount, pResults);

        if (hr == 0) // S_OK
        {
            // Do something else
        }

        return hr;
    }

I tried to increase the pResults array size to the length of dwCount, and put the interface identify I need to hook like:

    pResults = new MULTI_QI[dwCount];

    Guid iid = new Guid("322D5097-61CC-4984-9215-791FC75E137E");
    for (int i = 0; i < dwCount; i++)
    {
        pResults[i] = new    MULTI_QI(Marshal.AllocCoTaskMem(Marshal.SizeOf(iid)));
        Marshal.StructureToPtr(iid, pResults[i].piid, false);
    }

I get hr = 0 with this, but apparently this crashed the VB6 program.

Upvotes: -3

Views: 55

Answers (0)

Related Questions