C++/CLI Interop: COM function always returns null IntPtr - com

I have C++/CLI module which uses COM library. COM library function returns pointer to the object. Signature of the COM function call in C++/CLI is like this
IntPtr p = myCOMObject->GetSettings();
In COM interface same function has the following singnature
virtual HRESULT STDMETHODCALLTYPE GetSettings(
/* [retval][out] */ void *CSettings) = 0;
argument object *CSettings is native C++ object of some other class created in side GetSettings function.
When call this function in C++/CLI. I always Get IntPtr as '0' and no value set to it. I checked with pure C++ code, I get proper object. what could be the reason for this.Am i doing somthing wrong please suggest.

Related

VB.net load dll

I have been attempting to load a DLL using Reflector
Imports System.Reflection
I have a simple DLL file written in c++ using /CLR (this is the entire file)
using namespace System;
namespace ASSEMBLE{
public class REM{
public:
int VALUE(){
return 100;
}
};
};
And inside my VB.net butten click event i have
Dim dllPath As String = "C:\Users\richard\Documents\Visual Studio 2012\Projects\link\link\bin\Release\dlltest.dll"
' load the assembly
Dim assembly1 As System.Reflection.Assembly = Assembly.LoadFrom(dllPath)
' get the type
Dim t As Type = assembly1.GetType("ASSEMBLE.REM")
' create an instance and add it.
Dim c As Object = Activator.CreateInstance(t)
MsgBox(t.InvokeMember("VAULE", BindingFlags.Default Or BindingFlags.InvokeMethod, Nothing, c, {}))
When event triggered (ie. i load the dll) i get the error:
Method 'ASSEMBLE.REM.VALUE' not found
Using:
<DllImport("DLL.dll")> Public Shared Function VALUE() As Integer
End Function
is not an option. I need to load the DLL after runtime.
Your REM class is an unmanaged class, and therefore reflection cannot see its methods. Using the /CLR compile option does not automatically force all classes to be managed. It just allows you to have managed classes in your project.
To allow the call to InvokeMember, you need to make REM a managed class. This can be done by adding ref to the class declaration like so:
public ref class REM{
...
};

Why do libgit2 methods using kernel32.dll's GetProcAddress always return 0?

I have the need to manually handle the loading / unloading of the actual git2.dll, instead of using [DllImport("git2")] in C#. I seem to have issues with creating an IntPtr for reference to the address of methods stored in libgit2.
Here're the good bits from my PluginManager class which are supposed to help facilitate manually loading, marshal/delegate (whenever I get this kink fixed), and unloading libraries.
public class PluginManager {
public const string LIB = "Assets\\Plugins\\git2.dll";
[DllImport( "kernel32.dll", CharSet = CharSet.Ansi )]
public static extern IntPtr LoadLibrary( [In, MarshalAs( UnmanagedType.LPStr )] string lib );
[DllImport( "kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true )]
public static extern IntPtr GetProcAddress( [In] IntPtr reference, [In, MarshalAs( UnmanagedType.LPStr )] string method );
[DllImport( "kernel32.dll" )]
public static extern bool FreeLibrary( [In] IntPtr reference );
}
Here's where I attempt to use them:
//# Working; always non-zero.
IntPtr reference = PluginManager.LoadLibrary( PluginManager.LIB );
//# Should be valid -- LibGit2Sharp.Core.NativeMethods.cs calls this method, too.
//# Always returns IntPtr.Zero.
IntPtr methodReference = PluginManager.GetProcAddress( reference, "git_repository_open" );
Is the library not exposed to this type of loading? I've tried all kinds of methods present in the LibGit2Sharp native hooks, but they always return zero.
It seems that git2.dll has mangled export names, so git_repository_open is actually _git_repository_open#4. After researching some more on why this is happening, it seems that, according to This Post, and several others that I've run into while looking for a fix, that the functions may not be exported using extern "C" or may not be using a .def file.
I did look through some of the libgit2 code, and I saw extern used on a couple functions, but on others I saw no export keyword at all, but they're still being accessed externally from LigGit2Sharp's NativeMethods.cs class.
While all of that is foreign to me, I did find a very useful post about a tool shipped with Visual Studio that allows you to see all exported items, and their names: Dumpbin. With this, I was able to determine the exported names, and used the /OUT:filename flag to save them to a file: PasteBin
With all of the exported names at my disposal, I just have to follow function calls, that I'm actually using, and replace the the methods in NativeMethods.cs to look something like this: LibGit2Sharp Issue #341.

How to convert ISAPI related methods and structures to C#

I have an ISAPI filter written for IIS6. I now need to write a wrapper for IIS7 to wrap the IIS6 filter. I plan to write HTTP module in C# and Pinvoke the unmanaged dll methods.
I need C# representation of the following code,
DWORD WINAPI HttpFilterProc(
PHTTP_FILTER_CONTEXT pfc,
DWORD notificationType,
LPVOID pvNotification
);
typedef struct _HTTP_FILTER_CONTEXT HTTP_FILTER_CONTEXT {
DWORD cbSize;
DWORD Revision;
PVOID ServerContext;
DWORD ulReserved;
BOOL fIsSecurePort;
PVOID pFilterContext;
BOOL GetServerVariable;
BOOL AddResponseHeaders;
BOOL WriteClient;
VOID * AllocMem;
BOOL ServerSupportFunction;
} HTTP_FILTER_CONTEXT, * PHTTP_FILTER_CONTEXT;
I tried using PInvoke Assistant from codeplex but i am not able to make it work.
Has anyone done anything like this before?
Can anyone provide a solution to the above?
Correction: Correct structure added
Building on the code in your answer you need to use the following:
[DllImport(#"XyzISAPI.dll")]
public static extern uint HttpFilterProc(
ref HttpFilterContext pfc,
uint notificationType,
IntPtr pvNotification
);
The native code is passed a pointer to the context struct and passing the struct by ref is the easy way to match that. The final parameter is LPVOID, which is void* and that is plain IntPtr in managed code.
As for HTTP_FILTER_ACCESS_DENIED, define it like this:
[StructLayout(LayoutKind.Sequential)]
public struct HttpFilterAccessDenied
{
IntPtr URL;
IntPtr PhysicalPath;
uint Reason;
}
You can then obtain one of those like this:
HttpFilterAccessDenied hfad = (HttpFilterAccessDenied)Marshal.PtrToStructure(
pvNotification, typeof(HttpFilterAccessDenied));
And then you can get hold of the string values from the struct with Marshal.PtrToStringUni or Marshal.PtrToStringAnsi.

COM - [in] parameter as SAFEARRAY(STRUCT)

I am able to call a COM interface method using SAFEARRAY(BSTR) as input. If I define instead a simple (containing only some BSTR-s fields) STRUCT to pass into the COM I get
"[System.ArgumentException] = {"The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))"
The call to my COM server is not made because as it seems the arguments from client does not match the expected arguments on server: E_INVALIDARG
Here is my declaration in IDL:
typedef enum UserEntityType
{
User,
Group,
IPAddress
} UserEntityType;
[
uuid(4786F77E-BA5F-4806-B224-12AA8601A5B1)
]
typedef struct UserEntity
{
UserEntityType EntityType;
BSTR Value;
} UserEntity;
[id(9)] HRESULT SetUsers([in] SAFEARRAY(UserEntity) input);
The exception is thrown at run-time when a C# 4 client calls SetUsers().
The problem was in the C# client that was using the exe COM server where
SetUsers([in] SAFEARRAY(UserEntity) input)
was defined.
In order to fix this (at least for .NET 4.0) one has to change the following property of the imported COM server: Embed Interop Types = False

Run-Time Check Failure #0 vb.net callback from C dll

I'm writing Add-inn Application A in VB.Net and DLL B in C language.
Application A pass callback method to dll B.
When certain event occur the dll invoke the callback from A.
Whole works fine on my PC but when I move it to Notebook I get an error:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
This is part of C code:
typedef void (__cdecl * OFFICE_PTR)();
void TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3){
switch (dwMessage)
{
case LINE_CALLSTATE:
switch (dwParam1)
{
case LINECALLSTATE_OFFERING:
if(dwInstance!=NULL)
{
try
{
OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
vbFunc( );//Critical moment
}
catch(...)
{
MessageBox (NULL, L"( (OFFICE_PTR)dwInstance )(&sCallNr)",L"ERROR",MB_OK);
}
}
break;
};
break;
}
}
Where dwInstance is a address of application A callback method
This is part of VB.Net code:
Public Class TapiPlugin
Public Delegate Sub P_Fun()
Private Declare Function startSpy _
Lib "TAPIClient.dll" _
(ByVal pFun As P_Fun) As IntPtr
Public Shared Sub simpleTest()
MsgBox("Plugin sub simpleTest")
End Sub
Public Sub onStart()
Dim pBSTR As IntPtr
pBSTR = startSpy(AddressOf simpleTest)
MsgBox(Marshal.PtrToStringAuto(pBSTR))
Marshal.FreeBSTR(pBSTR)
End Sub
End Class
The Error occur when I try call 'vbFunc( )'. I would be grateful for any help. :D
If the calling convention is cdecl, then you need to declare your delegate like this:
<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Sub P_Fun()
You can only do this in .NET 2.0 and after, as the attribute was not introduced before then (and the interop layer was not changed to acknowledge it before that).
If the calling convention is indeed stdcall then the delegate can remain as is. You said it is stdcall, but I have doubts, since the exception is explicitly telling you that there might be a mismatch in calling conventions.
Do the two computers have different pointer sizes perhaps? Maybe one is a 64 bit machine and the other only 32?
typedef void (__cdecl * OFFICE_PTR)();
void TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
...){
...
OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
vbFunc( );//Critical moment
The DWORD type is not really valid for passing pointer types. You should be using INT_PTR I guess.
I thing it is not a reason to check it out I passed the callback as global pointer of type OFFICE_PTR and i get the same result. On PC it work fine on Notebook it crash :(
A have to apologies for a mistake I wrote that the def look like:
typedef void (__cdecl * OFFICE_PTR)();
but for real it looks like
typedef void (__stdcall * OFFICE_PTR)();