/// <summary> /// Calls a method with buffer for a type and gets the result or error. /// </summary> /// <typeparam name="TOut">The return type.</typeparam> /// <typeparam name="TSize">The type of the size result. This is usually <see cref="int" /> or <see cref="uint" />.</typeparam> /// <param name="getSize">Method to get the size of the buffer.</param> /// <param name="method">The lambda or method to call into.</param> /// <param name="result">The resulting value of <typeparamref name="TOut" />.</param> /// <param name="outConverter">An optional method to convert the pointer to the type specified by <typeparamref name="TOut" />. By default, this will marshal the pointer to the structure.</param> /// <param name="bufErr">The optional error <paramref name="method"/> returns when the buffer size is insufficient. If left <see langword="null"/>, then a list of well known errors will be used.</param> /// <returns> /// Resulting error or <see cref="Win32Error.ERROR_SUCCESS" /> on success. /// </returns> public static Win32Error CallMethodWithTypedBuf <TOut, TSize>(SizeFunc <TSize> getSize, PtrFunc <TSize> method, out TOut result, Func <IntPtr, TSize, TOut> outConverter = null, Win32Error?bufErr = null) where TSize : struct, IConvertible { TSize sz = default; result = default; var err = (getSize ?? GetSize)(ref sz); if (err.Failed && (bufErr == null || bufErr.Value != err) && !buffErrs.Contains(err)) { return(err); } using (var buf = new SafeHGlobalHandle(sz.ToInt32(null))) { var ret = method(buf.DangerousGetHandle(), ref sz); result = (outConverter ?? Conv)(buf.DangerousGetHandle(), sz); return(ret); } Win32Error GetSize(ref TSize sz1) => method(IntPtr.Zero, ref sz1); TOut Conv(IntPtr p, TSize s) => p.ToStructure <TOut>(); }
public static Win32Error CallMethodWithTypedBuf <TOut, TSize>(SizeFunc <TSize> getSize, PtrFunc <TSize> method, out TOut result, Func <IntPtr, TSize, TOut> outConverter = null) where TSize : struct, IConvertible { TSize sz = default; result = default; var err = getSize(ref sz); if (err.Failed) { return(err); } var len = sz.ToInt32(null); using (var buf = new SafeHGlobalHandle(len)) { var ret = method(buf.DangerousGetHandle(), ref sz); result = (outConverter ?? Conv)(buf.DangerousGetHandle(), sz); return(ret); } TOut Conv(IntPtr p, TSize s) => p.ToStructure <TOut>(); }