1

I am attempting to invoke an unmanaged DLL and use what it returns for authentication. Could someone help me correct my code to return the correct authentication strings?

I am confused about the struct's, any assistance would be appreciated.

this is my C# code invoking the library

     class Wrapper
{
    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
    public  struct ARSSOUserCredentialsStruct
    {
        /// int
        public int m_nARTCPNum;
        public int m_nARRPCNum;
        /// string*
        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
        public static string m_szARUserName;
        public string m_szARPassword;
        public string m_szARAuthenticationstring;
        public int m_nARNumberOfServers;
        //bool
        public bool m_bARUsingPreferenceServer;
    }
    public struct ARSSOServerInformation
    {

        /// int

        public int m_nARTCPNum;
        public int m_nARRPCNum;

        /// string*
        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
        public string m_szARServerName;

    }


    [System.Runtime.InteropServices.DllImportAttribute("ARSSOInfo.dll", EntryPoint = "ARGetSSOLoginCrendentials")]
    public static extern System.IntPtr ARGetSSOLoginCrendentials(string m_szARUserName);

    public static IntPtr getInfo(string m_szARUserName)
    {
       IntPtr ptr = ARGetSSOLoginCrendentials(m_szARUserName); // should this be IntPtr?
        //return (ARSSOUserCredentialsStruct)(Marshal.PtrToStructure(ptr, typeof(ARSSOUserCredentialsStruct)));   // what should type >

       // var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(m_szARUserName));
        if(ptr != null)
        {
            Marshal.StructureToPtr(m_szARUserName, ptr, false);
            Console.WriteLine("Not null");
            Console.WriteLine();

        }
        else
        {
            Console.WriteLine("null");
            Console.ReadLine();
        }
        return ptr;
    }


    class Program
    {
        static void Main(string[] args)
        {
            getInfo("jp");

        }
    }

}

unmanaged dll code which is being called by C# app:

#include <string.h>
#include <stdafx.h>
struct ARSSOServerInformation
{
    char * m_szARServerName;
    int m_nARTCPNum;
    int m_nARRPCNum;
};
struct ARSSOUserCredentialsStruct
{
    char* m_szARUserName;
    char* m_szARPassword;
    char* m_szARAuthenticationString;
    bool m_bARUsingPreferenceServer;
    int m_nARNumberOfServers;
};

extern "C"
{
    __declspec(dllexport) void
        ARGetSSOLoginCrendentials(ARSSOUserCredentialsStruct
            *pUserCredentialStruct)
    {
        // The required memory for struct ARSSOUserCredentialsStruct is allocated by user tool,
        // This dll just needs to assign values.
        // eg:
        strcpy(pUserCredentialStruct->m_szARUserName, "Demo");
        pUserCredentialStruct->m_nARNumberOfServers = 2;
    }
}//End 'extern "C"

extern "C"
{
    __declspec(dllexport) void
        ARGetSSOServerInformation(ARSSOServerInformation *pServerInfo)
    {
        // The required memory for struct ARSSOServerInformation is allocated by user tool,
        // This dll just needs to assign values.
        // eg:
        strcpy(pServerInfo[0].m_szARServerName, "ServerName1");
        pServerInfo->m_nARTCPNum = 3040; pServerInfo->m_nARRPCNum
            = 390622;
        strcpy(pServerInfo[1].m_szARServerName, "ServerName2");
    }
}//End 'extern "C"
Nipun
  • 2,217
  • 5
  • 23
  • 38
user2190928
  • 319
  • 1
  • 5
  • 21
  • 1
    Possible duplicate of [In C#, how do I invoke a DLL function that returns an unmanaged structure containing a string pointer?](https://stackoverflow.com/questions/356851/in-c-how-do-i-invoke-a-dll-function-that-returns-an-unmanaged-structure-contai) – Cee McSharpface Aug 11 '17 at 12:18
  • dlatikay, I modified code but still lost, the code on post recommended doesn't seem to work without my changes. any ideas on what else to change? – user2190928 Aug 11 '17 at 13:29
  • the `MarshalAsAttribute` always targets just one string right below it. It would have to be added to all string members of the struct. "doesn't seem to work" is not likely to attract fellow developers who could come up with a useful answer here... if your program throws an exception, post it here. if it does not compile, post the error. we need more info. – Cee McSharpface Aug 11 '17 at 13:34
  • dlatikay, IntPtr ARGetSSOLoginCrendentials(m_szARUserName); // should this be IntPtr? return (ARSSOUserCredentialsStruct)(Marshal.(ptr, typeof(ARSSOUserCredentialsStruct))); // what should type be? – user2190928 Aug 11 '17 at 13:58
  • when i have IntPtr ptr = ARGetSSOLoginCrendentials(m_szARUserName); I am getting error can't convert void to IntPtr – user2190928 Aug 11 '17 at 14:13
  • because it is `public static extern *void* ARGetSSOLoginCrendentials`. would have to be `int` as the return type then. but that contradicts the C implementation, where it is void as well. why do you expect it to return an int now? the marshaler is smart enough to dereference the pointer into a scalar value, if it has the correct hints (attributes) to do so. I think your previous version with `string` instead of `char` in the function arguments was correct; `char` in c# is a single byte character. – Cee McSharpface Aug 11 '17 at 14:17
  • the C function will not return anything. it will populate the structure that you pass into it as its only argument. that's fine. just align the types properly, it should work. – Cee McSharpface Aug 11 '17 at 14:19
  • This function is very hard to call reliably from a C program, that never gets better when you pinvoke. The caller has to carefully prepare the struct to provide enough storage for the string. Exactly how much is needed is impossible to discover and the strcpy() in the function will corrupt memory when it is not enough. The pinvoke marshaller has no support for doing this automatically, you'd have to monkey with Marshal.AllocHGlobal(). Just never do this, given how unsafe this is, fix the C code. Breaking this up into multiple functions is a very simple way. – Hans Passant Aug 11 '17 at 14:25
  • so is typeof(ARSSOUserCredentialsStruct))); correct? I get Error CS0029 Cannot implicitly convert type 'rtest.Wrapper.ARSSOUserCredentialsStruct' to 'System.IntPtr' – user2190928 Aug 11 '17 at 14:49
  • think I have almost got it. code updated – user2190928 Aug 11 '17 at 15:52
  • ok well i get error , 'Unable to load DLL 'ARSSOInfo.dll': A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT: 0x8007045A)' i think my logic is wrong, back to the beginning – user2190928 Aug 11 '17 at 16:30

0 Answers0