diff --git a/PInvoke/Shared/FunctionHelper.cs b/PInvoke/Shared/FunctionHelper.cs
index 64f3c34e..2590041a 100644
--- a/PInvoke/Shared/FunctionHelper.cs
+++ b/PInvoke/Shared/FunctionHelper.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
-using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
@@ -9,7 +8,7 @@ namespace Vanara.PInvoke
/// Generic functions to help with standard function patterns like getting a string from a method.
public static class FunctionHelper
{
- private static readonly List buffErrs = new List { Win32Error.ERROR_MORE_DATA, Win32Error.ERROR_INSUFFICIENT_BUFFER, Win32Error.ERROR_BUFFER_OVERFLOW };
+ private static readonly List buffErrs = new() { Win32Error.ERROR_MORE_DATA, Win32Error.ERROR_INSUFFICIENT_BUFFER, Win32Error.ERROR_BUFFER_OVERFLOW };
/// Delegate to get the size of memory allocated to a pointer.
/// The type of the size result. This is usually or .
@@ -18,9 +17,7 @@ namespace Vanara.PInvoke
/// Resulting error or on success.
public delegate Win32Error PtrFunc(IntPtr ptr, ref TSize sz) where TSize : struct, IConvertible;
- ///
- /// Delegate that takes and StringBuilder and initial size and returns a result.
- ///
+ /// Delegate that takes and StringBuilder and initial size and returns a result.
/// The type of the size result. This is usually or .
/// The return type.
/// The value.
@@ -28,6 +25,28 @@ namespace Vanara.PInvoke
/// The return value. Often this is an error.
public delegate TRet SBFunc(StringBuilder sb, ref TSize sz) where TSize : struct, IConvertible;
+ /// Delegate that takes and StringBuilder and initial size and returns a result.
+ /// The type of the first parameter.
+ /// The type of the size result. This is usually or .
+ /// The return type.
+ /// The first parameter.
+ /// The value.
+ /// On input, the size of the capacity. On output, the number of characters written.
+ /// The return value. Often this is an error.
+ public delegate TRet SBFunc(T1 arg1, StringBuilder sb, ref TSize sz) where TSize : struct, IConvertible;
+
+ /// Delegate that takes and StringBuilder and initial size and returns a result.
+ /// The type of the first parameter.
+ /// The type of the second parameter.
+ /// The type of the size result. This is usually or .
+ /// The return type.
+ /// The first parameter.
+ /// The second parameter.
+ /// The value.
+ /// On input, the size of the capacity. On output, the number of characters written.
+ /// The return value. Often this is an error.
+ public delegate TRet SBFunc(T1 arg1, T2 arg2, StringBuilder sb, ref TSize sz) where TSize : struct, IConvertible;
+
/// Gets a size and returns an error.
/// The type of the size result. This is usually or .
/// On input, the size of the capacity. On output, the number of characters written.
@@ -39,16 +58,6 @@ namespace Vanara.PInvoke
/// Resulting error or on success.
public static Win32Error BoolToLastErr(bool result) => result ? Win32Error.ERROR_SUCCESS : Win32Error.GetLastError();
- ///
- /// Checks to see if size is not 0 and if the error is requesting a larger buffer.
- ///
- /// The type of the size result. This is usually or .
- /// The error provider return type.
- /// On input, the size of the capacity. On output, the number of characters written.
- /// The error.
- /// true if buffer size is good; otherwise false.
- public static bool ChkGoodBuf(TSize sz, TRet err) where TSize : struct where TRet : IErrorProvider, IConvertible => !sz.Equals(default(TSize)) && buffErrs.ConvertAll(e => (HRESULT)e).Contains(err.ToHRESULT());
-
/// Calls a method with and gets the resulting string or error.
/// The type of the size result. This is usually or .
/// The return type.
@@ -71,8 +80,62 @@ namespace Vanara.PInvoke
var ret = method(sb, ref sz);
result = sb.ToString();
return ret;
+ }
- bool IsNotDef(TSize _sz, TRet _ret) => !_sz.Equals(default(TSize));
+ /// Calls a method with and gets the resulting string or error.
+ /// The type of the first parameter.
+ /// The type of the size result. This is usually or .
+ /// The return type.
+ /// The lambda or method to call into.
+ /// The first parameter.
+ /// The resulting string value.
+ /// An optional method to determine if a valid size was retrieved by .
+ /// The return value of .
+ public static TRet CallMethodWithStrBuf(SBFunc method, T1 arg1, out string result,
+ Func gotGoodSize = null) where TSize : struct, IConvertible
+ {
+ TSize sz = default;
+ var ret0 = method(arg1, null, ref sz);
+ if (!(gotGoodSize ?? IsNotDef)(sz, ret0))
+ {
+ result = null;
+ return ret0;
+ }
+ var len = sz.ToInt32(null) + 1;
+ var sb = new StringBuilder(len, len);
+ sz = (TSize)Convert.ChangeType(len, typeof(TSize));
+ var ret = method(arg1, sb, ref sz);
+ result = sb.ToString();
+ return ret;
+ }
+
+ /// Calls a method with and gets the resulting string or error.
+ /// The type of the first parameter.
+ /// The type of the second parameter.
+ /// The type of the size result. This is usually or .
+ /// The return type.
+ /// The lambda or method to call into.
+ /// The first parameter.
+ /// The second parameter.
+ /// The resulting string value.
+ /// An optional method to determine if a valid size was retrieved by .
+ /// The return value of .
+ public static TRet CallMethodWithStrBuf(SBFunc method, T1 arg1, T2 arg2, out string result,
+ Func gotGoodSize = null) where TSize : struct, IConvertible
+ {
+ TSize sz = default;
+ var ret0 = method(arg1, arg2, null, ref sz);
+ if (!(gotGoodSize ?? IsNotDef)(sz, ret0))
+ {
+ result = null;
+ return ret0;
+ }
+ var len = sz.ToInt32(null) + 1;
+ var sb = new StringBuilder(len, len);
+ sz = (TSize)Convert.ChangeType(len, typeof(TSize));
+ var ret = method(arg1, arg2, sb, ref sz);
+ result = sb.ToString();
+ return ret;
}
/// Calls a method with and gets the resulting string or error.
@@ -91,20 +154,23 @@ namespace Vanara.PInvoke
return ret;
}
- ///
- /// Calls a method with buffer for a type and gets the result or error.
- ///
+ /// Calls a method with buffer for a type and gets the result or error.
/// The return type.
- /// The type of the size result. This is usually or .
+ /// The type of the size result. This is usually or .
/// Method to get the size of the buffer.
/// The lambda or method to call into.
- /// The resulting value of .
- /// An optional method to convert the pointer to the type specified by . By default, this will marshal the pointer to the structure.
- /// The optional error returns when the buffer size is insufficient. If left , then a list of well known errors will be used.
- ///
- /// Resulting error or on success.
- ///
- public static Win32Error CallMethodWithTypedBuf(SizeFunc getSize, PtrFunc method, out TOut result, Func outConverter = null, Win32Error? bufErr = null) where TSize : struct, IConvertible
+ /// The resulting value of .
+ ///
+ /// An optional method to convert the pointer to the type specified by . By default, this will marshal the
+ /// pointer to the structure.
+ ///
+ ///
+ /// The optional error returns when the buffer size is insufficient. If left , then a
+ /// list of well known errors will be used.
+ ///
+ /// Resulting error or on success.
+ public static Win32Error CallMethodWithTypedBuf(SizeFunc getSize, PtrFunc method, out TOut result,
+ Func outConverter = null, Win32Error? bufErr = null) where TSize : struct, IConvertible
{
TSize sz = default;
result = default;
@@ -128,13 +194,49 @@ namespace Vanara.PInvoke
/// The type of the size result. This is usually or .
/// The lambda or method to call into.
/// Method to get the size of the buffer.
- /// An optional method to convert the pointer to the type specified by . By default, this will marshal the pointer to the structure.
- /// The optional error returns when the buffer size is insufficient. If left , then a list of well known errors will be used.
+ ///
+ /// An optional method to convert the pointer to the type specified by . By default, this will marshal the
+ /// pointer to the structure.
+ ///
+ ///
+ /// The optional error returns when the buffer size is insufficient. If left , then a
+ /// list of well known errors will be used.
+ ///
/// The resulting value of .
- public static TOut CallMethodWithTypedBuf(PtrFunc method, SizeFunc getSize = null, Func outConverter = null, Win32Error? bufErr = null) where TSize : struct, IConvertible
+ public static TOut CallMethodWithTypedBuf(PtrFunc method, SizeFunc getSize = null,
+ Func outConverter = null, Win32Error? bufErr = null) where TSize : struct, IConvertible
{
CallMethodWithTypedBuf(getSize, method, out var res, outConverter, bufErr).ThrowIfFailed();
return res;
}
+
+ /// Checks to see if size is not 0 and if the error is requesting a larger buffer.
+ /// The type of the size result. This is usually or .
+ /// The error provider return type.
+ /// On input, the size of the capacity. On output, the number of characters written.
+ /// The error.
+ /// true if buffer size is good; otherwise false.
+ public static bool ChkGoodBuf(TSize sz, TRet err) where TSize : struct where TRet : IErrorProvider, IConvertible =>
+ !sz.Equals(default(TSize)) && buffErrs.ConvertAll(e => (HRESULT)e).Contains(err.ToHRESULT());
+
+ private static bool IsNotDef(TSize _sz, TRet _ret) where TSize : struct, IConvertible => !_sz.Equals(default(TSize));
+
+ /*
+ public delegate TRet P0QI(in Guid iid, out object ppv) where TRet : IErrorProvider, IConvertible;
+ public delegate TRet P1QI(TIn1 p1, in Guid iid, out object ppv) where TRet : IErrorProvider, IConvertible;
+ public delegate TRet P1IQI(in TIn1 p1, in Guid iid, out object ppv) where TIn1 : struct where TRet : IErrorProvider, IConvertible;
+ public delegate TRet P2QI(TIn1 p1, TIn2 p2, in Guid iid, out object ppv) where TRet : IErrorProvider, IConvertible;
+
+ public static TIntf QueryInterface(P0QI f) => f0(typeof(TIntf).GUID, out object ppv).Succeeded ? (TIntf)ppv : throw new InvalidCastException();
+ public static TIntf QueryInterface(P1QI f, TIn1 p1) => QueryInterface(f1, p1, hr => hr.Succeeded);
+ public static TIntf QueryInterface(P1IQI f, in TIn1 p1) where TIn1 : struct => QueryInterface(f1, in p1, hr => hr.Succeeded);
+
+ private void Test()
+ {
+ static HRESULT GetObj(uint f, in Guid iid, out object ppv);
+
+ X x = QueryInterface(GetObj, 3U);
+ }
+ */
}
}
\ No newline at end of file