Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncOpen method can not use callback #6

Open
takuya-takeuchi opened this issue Aug 15, 2018 · 9 comments
Open

AsyncOpen method can not use callback #6

takuya-takeuchi opened this issue Aug 15, 2018 · 9 comments
Assignees
Labels
bug Something isn't working
Milestone

Comments

@takuya-takeuchi
Copy link
Owner

Just after call AsyncOpenFramework method with WINBIO_ASYNC_NOTIFY_CALLBACK, library throw exception with E_OUTOFMEMORY

@takuya-takeuchi takuya-takeuchi added the bug Something isn't working label Aug 15, 2018
@takuya-takeuchi takuya-takeuchi added this to the 1.0 milestone Aug 15, 2018
@takuya-takeuchi takuya-takeuchi self-assigned this Aug 15, 2018
@takuya-takeuchi
Copy link
Owner Author

After turned on Enable native code debugging, IDE show the following dialog

image

@takuya-takeuchi
Copy link
Owner Author

takuya-takeuchi commented Aug 18, 2018

In unmanaged application, despite Win32 sample is x86 or x64, it works fine.

image

@takuya-takeuchi
Copy link
Owner Author

C++/CLI console apps also works fine.

#include "stdafx.h"

using namespace System;

void CALLBACK WINBIO_ASYNC_COMPLETION_CALLBACK(PWINBIO_ASYNC_RESULT AsyncResult)
{
}

int main(array<System::String ^> ^args)
{
	WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod = WINBIO_ASYNC_NOTIFY_CALLBACK;
	HWND  TargetWindow = NULL;
	UINT  MessageCode = 0;
	PVOID UserData = NULL;
	BOOL  AsynchronousOpen = TRUE;
	WINBIO_FRAMEWORK_HANDLE FrameworkHandle;
	HRESULT hr = WinBioAsyncOpenFramework(
		NotificationMethod,
		TargetWindow,
		MessageCode,
		WINBIO_ASYNC_COMPLETION_CALLBACK,
		UserData,
		AsynchronousOpen,
		&FrameworkHandle
	);
	
	return 0;
}

@takuya-takeuchi
Copy link
Owner Author

Create C++/CLI library which call AsyncOpenFramework and C$ console app which call C++/CLI library, then it works fine.

#include "stdafx.h"

#include "ClassLibrary1.h"


namespace ClassLibrary1 {
	
	void CALLBACK WINBIO_ASYNC_COMPLETION_CALLBACK(PWINBIO_ASYNC_RESULT AsyncResult)
	{
	}

	HRESULT Class1::Test()
	{
		WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod = WINBIO_ASYNC_NOTIFY_CALLBACK;
		HWND  TargetWindow = NULL;
		UINT  MessageCode = 0;
		PVOID UserData = NULL;
		BOOL  AsynchronousOpen = TRUE;
		WINBIO_FRAMEWORK_HANDLE FrameworkHandle;
		HRESULT hr = WinBioAsyncOpenFramework(
			NotificationMethod,
			TargetWindow,
			MessageCode,
			WINBIO_ASYNC_COMPLETION_CALLBACK,
			UserData,
			AsynchronousOpen,
			&FrameworkHandle
		);

		return hr;
	}
}
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new ClassLibrary1.Class1();
            var ret = test.Test();
            Console.WriteLine(ret);
        }
    }
}

@takuya-takeuchi
Copy link
Owner Author

Minimum C# apps does not work.

using System;
using System.Runtime.InteropServices;

using BOOL = System.Int32;
using HRESULT = System.Int32;
using HWND = System.IntPtr;
using PVOID = System.IntPtr;
using UINT = System.UInt32;

using WINBIO_FRAMEWORK_HANDLE = System.UInt32;

namespace ConsoleApp2
{
    class Program
    {

        private const string DllName = "Winbio.dll";

        public enum WINBIO_ASYNC_NOTIFICATION_METHOD
        {

            WINBIO_ASYNC_NOTIFY_NONE = 0,

            WINBIO_ASYNC_NOTIFY_CALLBACK,

            WINBIO_ASYNC_NOTIFY_MESSAGE,

            WINBIO_ASYNC_NOTIFY_MAXIMUM_VALUE

        }

        public delegate void WINBIO_ASYNC_COMPLETION_CALLBACK([In] IntPtr AsyncResult);

        [DllImport(DllName)]
        public static extern HRESULT WinBioAsyncOpenFramework([In]  WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod,
                                                              [In]  HWND TargetWindow,
                                                              [In]  UINT MessageCode,
                                                              [In]  WINBIO_ASYNC_COMPLETION_CALLBACK CallbackRoutine,
                                                              [In]  PVOID UserData,
                                                              [In]  BOOL AsynchronousOpen,
                                                              [Out] out WINBIO_FRAMEWORK_HANDLE FrameworkHandle);
        
        private static void AsyncCompletedCallback(IntPtr asyncResult)
        {
        }

        static void Main(string[] args)
        {
            var NotificationMethod = WINBIO_ASYNC_NOTIFICATION_METHOD.WINBIO_ASYNC_NOTIFY_CALLBACK;
            IntPtr TargetWindow = IntPtr.Zero;
            UINT MessageCode = 0;
            PVOID UserData = IntPtr.Zero;
            var AsynchronousOpen = 1;
            var hr = WinBioAsyncOpenFramework(NotificationMethod,
                                              TargetWindow,
                                              0,
                                              AsyncCompletedCallback,
                                              UserData,
                                              AsynchronousOpen,
                                              out var h);
            Console.WriteLine(hr);
        }
    }
}

@takuya-takeuchi
Copy link
Owner Author

Win32 with dynamic call looks like p/invoke by using LoadLibrary.
It does not link any Windows Biometric Framework library.
It works fine.

#include "stdafx.h"

#include "windows.h"
#include "WinBio.h"

typedef HRESULT(WINAPI *WINBIOASYNCOPENFRAMEWORK)
(
	_In_ WINBIO_ASYNC_NOTIFICATION_METHOD,
	_In_opt_ HWND,
	_In_opt_ UINT,
	_In_opt_ PWINBIO_ASYNC_COMPLETION_CALLBACK,
	_In_opt_ PVOID,
	_In_ BOOL,
	_Out_opt_ WINBIO_FRAMEWORK_HANDLE *
);

void CALLBACK WINBIO_ASYNC_COMPLETION_CALLBACK(PWINBIO_ASYNC_RESULT AsyncResult)
{
}

int main()
{
	HMODULE hModule = LoadLibrary(_T("WinBio.dll"));
	WINBIOASYNCOPENFRAMEWORK pFunc = (WINBIOASYNCOPENFRAMEWORK)GetProcAddress(hModule, "WinBioAsyncOpenFramework");

	WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod = WINBIO_ASYNC_NOTIFY_CALLBACK;
	HWND  TargetWindow = NULL;
	UINT  MessageCode = 0;
	PVOID UserData = NULL;
	BOOL  AsynchronousOpen = TRUE;
	WINBIO_FRAMEWORK_HANDLE FrameworkHandle;
	HRESULT hr = pFunc(
		NotificationMethod,
		TargetWindow,
		MessageCode,
		WINBIO_ASYNC_COMPLETION_CALLBACK,
		UserData,
		AsynchronousOpen,
		&FrameworkHandle
	);

    return 0;
}

@takuya-takeuchi takuya-takeuchi changed the title AsyncOpen method can not use callback 💣 AsyncOpen method can not use callback Aug 19, 2018
@takuya-takeuchi takuya-takeuchi changed the title 💣 AsyncOpen method can not use callback AsyncOpen method can not use callback Aug 19, 2018
@takuya-takeuchi
Copy link
Owner Author

C# + LoadLibrary. It does not work.

using System;
using System.Runtime.InteropServices;

using BOOL = System.Int32;
using HRESULT = System.Int32;
using HWND = System.IntPtr;
using PVOID = System.IntPtr;
using UINT = System.UInt32;

using WINBIO_FRAMEWORK_HANDLE = System.UInt32;

namespace ConsoleApp4
{
    class Program
    {

        private const string DllName = "Winbio.dll";

        public enum WINBIO_ASYNC_NOTIFICATION_METHOD
        {

            WINBIO_ASYNC_NOTIFY_NONE = 0,

            WINBIO_ASYNC_NOTIFY_CALLBACK,

            WINBIO_ASYNC_NOTIFY_MESSAGE,

            WINBIO_ASYNC_NOTIFY_MAXIMUM_VALUE

        }

        [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32", SetLastError = true)]
        internal static extern bool FreeLibrary(IntPtr hModule);

        [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)]
        internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

        public delegate void WINBIO_ASYNC_COMPLETION_CALLBACK([In] IntPtr AsyncResult);

        public delegate HRESULT WinBioAsyncOpenFramework([In]  WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod,
                                                         [In]  HWND TargetWindow,
                                                         [In]  UINT MessageCode,
                                                         [In]  WINBIO_ASYNC_COMPLETION_CALLBACK CallbackRoutine,
                                                         [In]  PVOID UserData,
                                                         [In]  BOOL AsynchronousOpen,
                                                         [Out] out WINBIO_FRAMEWORK_HANDLE FrameworkHandle);

        private static void AsyncCompletedCallback(IntPtr asyncResult)
        {
        }

        static void Main(string[] args)
        {
            IntPtr handle = LoadLibrary(DllName);
            IntPtr funcPtr = GetProcAddress(handle, nameof(WinBioAsyncOpenFramework));

            WinBioAsyncOpenFramework func = (WinBioAsyncOpenFramework)Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(WinBioAsyncOpenFramework));

            var NotificationMethod = WINBIO_ASYNC_NOTIFICATION_METHOD.WINBIO_ASYNC_NOTIFY_CALLBACK;
            IntPtr TargetWindow = IntPtr.Zero;
            UINT MessageCode = 0;
            PVOID UserData = IntPtr.Zero;
            var AsynchronousOpen = 1;
            var hr = func(NotificationMethod,
                          TargetWindow,
                          0,
                          AsyncCompletedCallback,
                          UserData,
                          AsynchronousOpen,
                          out var h);

            Console.WriteLine(hr);
        }
    }
}

@takuya-takeuchi
Copy link
Owner Author

C++/CLI and C#, but pass the delegate pointer defined in managed to C++/CLI side.
It does not work

#include "stdafx.h"

#include "ClassLibrary1.h"


namespace ClassLibrary1 {
	
	void CALLBACK WINBIO_ASYNC_COMPLETION_CALLBACK(PWINBIO_ASYNC_RESULT AsyncResult)
	{
	}

	HRESULT Class1::Test()
	{
		WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod = WINBIO_ASYNC_NOTIFY_CALLBACK;
		HWND  TargetWindow = NULL;
		UINT  MessageCode = 0;
		PVOID UserData = NULL;
		BOOL  AsynchronousOpen = TRUE;
		WINBIO_FRAMEWORK_HANDLE FrameworkHandle;
		HRESULT hr = WinBioAsyncOpenFramework(
			NotificationMethod,
			TargetWindow,
			MessageCode,
			WINBIO_ASYNC_COMPLETION_CALLBACK,
			UserData,
			AsynchronousOpen,
			&FrameworkHandle
		);

		return hr;
	}
	HRESULT Class1::Test2(void* func)
	{
		WINBIO_ASYNC_NOTIFICATION_METHOD NotificationMethod = WINBIO_ASYNC_NOTIFY_CALLBACK;
		HWND  TargetWindow = NULL;
		UINT  MessageCode = 0;
		PVOID UserData = NULL;
		BOOL  AsynchronousOpen = TRUE;
		WINBIO_FRAMEWORK_HANDLE FrameworkHandle;
		HRESULT hr = WinBioAsyncOpenFramework(
			NotificationMethod,
			TargetWindow,
			MessageCode,
			(PWINBIO_ASYNC_COMPLETION_CALLBACK)func,
			UserData,
			AsynchronousOpen,
			&FrameworkHandle
		);

		return hr;
	}
}
using System;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    class Program
    {
        public delegate void WINBIO_ASYNC_COMPLETION_CALLBACK([In] IntPtr AsyncResult);

        private static void AsyncCompletedCallback(IntPtr asyncResult)
        {
        }

        static unsafe void Main(string[] args)
        {
            var test = new ClassLibrary1.Class1();
            var ret = test.Test();
            Console.WriteLine(ret);

            var ptr = Marshal.GetFunctionPointerForDelegate<WINBIO_ASYNC_COMPLETION_CALLBACK>(AsyncCompletedCallback);
            ret = test.Test2((void*)ptr);
            Console.WriteLine(ret);
        }
    }
}

@takuya-takeuchi
Copy link
Owner Author

takuya-takeuchi commented Aug 19, 2018

App Constitution Result
Win32 OK
Win32 (by LoadLibrary) OK
C++/CLI app OK
C++/CLI (defined here) +C# app (.NET Framework) OK
C++/CLI (defined here) +C# app (.NET Framework, pass the delegate pointer) NG
C# app (.NET Framework) NG
C# app (by LoadLibrary) (.NET Framework) NG
C# app (.NET Core) NG

So

  • It does not matter whether application is unmanaged or managed.
  • The unmanaged definition works fine.
  • P/invoke definition may have something wrong.
    • The definition of delegate looks like to be wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant