tags:

views:

436

answers:

2

I'm trying to translate this c++/cli code to c#

#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>

   using namespace System;
   using namespace System::Runtime::InteropServices;

    struct CREDENTIAL    
    {
        DWORD Flags;
        DWORD Type;
        LPSTR TargetName;
        LPSTR Comment;
        Runtime::InteropServices::ComTypes::FILETIME LastWritten;        
        DWORD CredentialBlobSize;
        LPBYTE CredentialBlob;
        DWORD Persist;
        DWORD AttributeCount;
        LPBYTE Attributes;
        LPSTR TargetAlias;
        LPWSTR UserName;
    };

    [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet::Unicode)]
    extern BOOL CredEnumerate(LPCTSTR Filter, DWORD Flags, DWORD* count, CREDENTIAL*** Credentials);

    [DllImport("advapi32.dll")]
    extern VOID CredFree(LPVOID);

        int main( array<System::String^>^argv )
        {
            String^ credentialList = "";
            Int32 count = 0;
            CREDENTIAL** credentialCollection = 0;            

            if( CredEnumerate( _T("WindowsLive:name=*"), 0, (DWORD*)&count, &credentialCollection) )                        
            {
                for( Int32 n = 0; n < count; n++ )
                {
                    credentialList += "\n";
                    credentialList += "Username " + gcnew System::String( credentialCollection[n]->UserName ) + "\n";
                    credentialList += "Password: " + gcnew System::String( (LPWSTR)credentialCollection[n]->CredentialBlob ) + "\n";
                } 

                CredFree( &credentialCollection );
     Console::WriteLine(credentialList);

            }
        Console::ReadLine();
        }

Here's my c# code .. (I am not sure how CredEnumerate does work)

using System;
using System.Runtime.InteropServices;     // DLL support
using System.Collections.Generic;

public struct CREDENTIAL
{
 public UInt32 flags;
 public UInt32 type;
 public string targetName;
 public string comment;
 public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten;
 public UInt32 credentialBlobSize;
 public IntPtr credentialBlob;
 public UInt32 persist;
 public UInt32 attributeCount;
 public IntPtr credAttribute;
 public string targetAlias;
 public string userName;
}

class Test
{        
 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr
 pCredentials);

 static void Main()
 {
  try
  {
   int count = 0;
   IntPtr pCredentials = IntPtr.Zero;
   IntPtr[] credentials = null;
   bool ret = CredEnumerate("WindowsLive:name=*", 0, out count, out pCredentials);
   if (ret != false)
   {

    credentials = new IntPtr[count];
    IntPtr p = pCredentials;
    for (int n = 0; n < count; n++)
    {
     if (Marshal.SizeOf(p) == 4) //32 bit CLR?
      p = new IntPtr(p.ToInt32() + n);
     else
      p = new IntPtr(p.ToInt64() + n);
     credentials[n]  = Marshal.ReadIntPtr(p);
    }

    List<CREDENTIAL> creds = new List<CREDENTIAL>(credentials.Length);
    foreach (var ptr in credentials)
    {
     creds.Add((CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL)));
    }

   }
  }
  catch (Exception x)
  {
      Console.WriteLine(x.ToString());
  }

  Console.ReadLine();
 }
}

I hope someone can help me

A: 

have a look at pinvoke.net it may have an example of how to call CredEnumerate

Ian Ringrose
pinvoke.net doesn't have CredEnumerate api examples
bader
+1  A: 

It's pretty scary code, I have my doubts about the CLI/C++ being right. You should look up the definitions of your structure e.g.

http://msdn.microsoft.com/en-us/library/aa374788%28VS.85%29.aspx

Then clean-up the code properly before posting.

I would be tempted to use the code from this article on credential management

Still, that involves keeping the CLI/C++ which you seem to want to get rid of so I gave fixing it a go.

Now this works on my machine, that I've hacked it together... (note: I've removed your filter so I could test it)

[StructLayout(LayoutKind.Sequential)]
internal struct CREDENTIAL {
    public int Flags;
    public int Type;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string TargetName;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string Comment;
    public long LastWritten;
    public int CredentialBlobSize;
    public IntPtr CredentialBlob;
    public int Persist;
    public int AttributeCount;
    public IntPtr Attributes;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string TargetAlias;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string UserName;
}

Then the reading

try
{
    uint count;
    IntPtr pCredentials = IntPtr.Zero;
    IntPtr[] credentials;
    bool ret = CredEnumerateW("*", 0, out count, out pCredentials);
    if (ret)
    {
        credentials = new IntPtr[count];
        List<CREDENTIAL> creds = new List<CREDENTIAL>(credentials.Length);
        for(int i = 0; i < count; i++) {
            IntPtr structs= Marshal.ReadIntPtr(pCredentials, IntPtr.Size * i);
            CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(structs, typeof(CREDENTIAL));
            creds.Add(c);
        }
    }
}
catch (Exception x)
{
    Console.WriteLine(x.ToString());
}

and

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CredEnumerateW(string filter, uint flag, out uint count, out IntPtr pCredentials);

It doesn't free the structure etc.

Colin Gravill