internal static Delegate BindToPInvokeAnsi(FunctionIdentity identity, Type generalDelegate) { if (identity.IsUni) { identity = identity.ToAnsi(); } return(BindToPInvoke(CharSet.Ansi, identity, generalDelegate)); }
// This function is exception-safe and does not throw any exceptions internal static void DefaultLogging(IHookHolderAndCallback hhac, FunctionIdentity identity, string format, params object[] args) { try { DebugLogger.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString("D2") + " " + identity.Function + " " + format, args); } catch (Exception) { } }
/// <summary> /// Basing on signature delegate having DllFunctionAttribute, determines function name, /// dll name and hook category (registry/files/...). /// </summary> private void GetHookAttribs(Type signature, out FunctionIdentity identity, out string category) { DllFunctionAttribute[] attrs = (DllFunctionAttribute[])signature.GetCustomAttributes( typeof(DllFunctionAttribute), false); if (attrs.Length != 1) { throw new ArgumentException("Hook delegate should have single DllFunction attributes"); } identity = attrs[0].Identity; category = attrs[0].Category; }
/// <summary> /// Constructor in addition to just filling the fields with the parameters' values, /// initializes cache of bound delegates. /// </summary> /// <para>For both Ansi and Unicode versions of the same function, the same signature /// delegate is used, but to perform actual call, it is bound using /// <see cref="PInvokeHelper.BindToPInvokeAnsi"/> /// and <see cref="PInvokeHelper.BindToPInvokeUnicode"/>.</para> internal Hook(FunctionIdentity identity, Type signature, Delegate hookHandler, string hookCategory) { signature_ = signature; identity_ = identity; hookHandler_ = hookHandler; hookCategory_ = hookCategory; // Building cache of bound pinvoke delegates ahead of itme to avoid nested calls // which fail: (reg*hook -> Bind -> reg* by .NET -> Bind) PInvokeHelper.BindToPInvokeAnsi(identity, signature); PInvokeHelper.BindToPInvokeUni(identity, signature); }
private void Add(FunctionIdentity identity, Delegate hook, string category) { // The following call checks if function is already in the dict dict_.Add(identity, new Hook(identity, hook.GetType(), hook, category)); if (identity.IsUni) { // For functions accepting string params we add Ansi version too FunctionIdentity ansiId = identity.ToAnsi(); if (!dict_.ContainsKey(ansiId)) { dict_.Add(ansiId, new Hook(ansiId, hook.GetType(), PInvokeHelper.Ansi2UniDecorator(hook), category)); } } }
private static Delegate Bind(FunctionIdentity identity, Type generalDelegate, CharSet charSet) { string suffix = BuildSuffix(identity, charSet); EnsureModuleBuilder(); // Base class specified ONLY to make assembly reference OpenSandbox // before method gets defined so that types are resolved correctly TypeBuilder tb = cachedModuleBuilder_.DefineType( generalDelegate.Name + "PInvoke" + suffix, TypeAttributes.Class, typeof(Win32Api)); MethodInfo method = generalDelegate.GetMethod("Invoke"); ParameterInfo[] parameters = method.GetParameters(); Type[] paramTypes = new Type[parameters.Length]; for (int i = 0; i < paramTypes.Length; ++i) { paramTypes[i] = parameters[i].ParameterType; } MethodBuilder mb = tb.DefinePInvokeMethod( generalDelegate.Name + "PInvoke" + suffix, identity.Dll, identity.Function, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, CallingConventions.Standard, method.ReturnType, paramTypes, CallingConvention.StdCall, charSet); mb.SetImplementationFlags( mb.GetMethodImplementationFlags() | MethodImplAttributes.PreserveSig); for (int i = 0; i < paramTypes.Length; i++) { var parameter = parameters[i]; mb.DefineParameter(i + 1, ParameterAttributes.None, parameter.Name); } Type pinvokeType = tb.CreateType(); return(Delegate.CreateDelegate( // UnmanagedDelegate(generalDelegate, charSet), generalDelegate, pinvokeType.GetMethod(generalDelegate.Name + "PInvoke" + suffix))); }
private static Delegate BindToPInvoke( CharSet charSet, FunctionIdentity identity, Type generalDelegate) { Signature signature = new Signature { Identity = identity, GeneralDelegate = generalDelegate }; lock (boundToPInvoke_) { if (boundToPInvoke_.ContainsKey(signature)) { return(boundToPInvoke_[signature]); } } Delegate bound = Bind(identity, generalDelegate, charSet); lock (boundToPInvoke_) { boundToPInvoke_[signature] = bound; } return(bound); }
/// <summary> /// Adds hook identified by delegate specifying signature and hook handler method, /// DllFunctionAttribute, associated with delegate specifying function name and dll /// name to the container. /// </summary> /// <para>If function also has an Ansi version, it is also added to the container.</para> internal void Add(Delegate hook) { FunctionIdentity identity; string category; GetHookAttribs(hook.GetType(), out identity, out category); // TODO: decouple the hooks container and the strategy // how hooks are added into container if (identity.Dll == Win32Api.Advapi32DllName) { // Registry functions in windows 7 also reside in kernel32.dll, some of system // dlls like oleaut32.dll call kernel32.dll versions FunctionIdentity kernel32Identity = new FunctionIdentity(Win32Api.Kernel32DllName, identity.Function); Add(kernel32Identity, hook, category); // Registry functions in windows 8 also reside in kernelbase.dll, some of system // dlls like combase.dll call kernelbase.dll versions FunctionIdentity kernelBaseIdentity = new FunctionIdentity(Win32Api.KernelBaseDllName, identity.Function); Add(kernelBaseIdentity, hook, category); } Add(identity, hook, category); }
internal static Delegate BindToPInvokeUni(FunctionIdentity identity, Type generalDelegate) { return(BindToPInvoke(CharSet.Unicode, identity, generalDelegate)); }
private static string BuildSuffix(FunctionIdentity identity, CharSet charSet) { string suffix = identity.Dll + "_" + identity.Function + "_" + charSet.ToString(); return(suffix.Replace(".", "_")); }
internal static void NoLogging(IHookHolderAndCallback hhac, FunctionIdentity identity, string format, params object[] args) { }
internal DllFunctionAttribute(string dll, string function, string category) { identity_ = new FunctionIdentity(dll, function); category_ = category; }