Reputation: 1
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