PInvoke to get CharArray from ldap_explode_dn

  • Thread starter Thread starter Stefan Buchman
  • Start date Start date
S

Stefan Buchman

Hi All,

I'm attempting to use ldap_explode_dn API call which returns a
character array.

I've been trying to Marshal this value but am unable to get anything
intelligible from it.

I should be getting an array of strings representing a DN.

Any help using this function from C# would be great!

PCHAR* ldap_explode_dn(
PCHAR dn,
ULONG notypes
);


Thanks!


Stefan
 
Stefan Buchman said:
Hi All,

I'm attempting to use ldap_explode_dn API call which returns a
character array.

I've been trying to Marshal this value but am unable to get anything
intelligible from it.

I should be getting an array of strings representing a DN.

Any help using this function from C# would be great!

PCHAR* ldap_explode_dn(
PCHAR dn,
ULONG notypes
);


Thanks!


Stefan

ldap_explode_dn returns an array of characters, not an array of strings.
Please post what you have in C# so far.

Willy.
 
Hi Willy,

I've defined the functions as follows:

[DllImport("wldap32.dll", CharSet=CharSet.Auto)]
static private extern char[] ldap_explode_dn(string dn, int notypes);

[DllImport("wldap32.dll", CharSet=CharSet.Auto)]
static private extern uint ldap_value_free(IntPtr ptr);

But whenever I call the ldap_explode_dn I get junk back. I know they
say it's a char array but if so, how is it going to return an exploded
dn which would consist of OU's and CN's?

Thanks!


Stefan
 
Stefan Buchman said:
Hi Willy,

I've defined the functions as follows:

[DllImport("wldap32.dll", CharSet=CharSet.Auto)]
static private extern char[] ldap_explode_dn(string dn, int notypes);

[DllImport("wldap32.dll", CharSet=CharSet.Auto)]
static private extern uint ldap_value_free(IntPtr ptr);

But whenever I call the ldap_explode_dn I get junk back. I know they
say it's a char array but if so, how is it going to return an exploded
dn which would consist of OU's and CN's?

Thanks!


Stefan

[DllImport("wldap32.dll", CharSet=CharSet.Auto)]
static private extern IntPtr ldap_explode_dn(string dn, int notypes);


....
// returns a pointer to an array of pointers to char[]
IntPtr pptr = ldap_explode_dn("cn=mydom,ou=myou", 0);
IntPtr ptr = Marshal.ReadIntPtr(pptr); // read pointer to char[]
ArrayList exploded = new ArrayList();
do
{
string s = Marshal.PtrToStringAuto(ptr);
exploded.Add(s);
pptr = new IntPtr((int)pptr + IntPtr.Size); //get next pointer
ptr = Marshal.ReadIntPtr(pptr); //get next char[]
} while(ptr != IntPtr.Zero); // loop until char[] == null pointer
....


Willy.
 
Thanks Willy,

That's exactly what I needed. How come it used one pointer to point to
another instead of giving me the char[] pointer to begin with?

Stefan
 
Stefan Buchman said:
Thanks Willy,

That's exactly what I needed. How come it used one pointer to point to
another instead of giving me the char[] pointer to begin with?

Stefan

The function returns a pointer to an array of pointers to a char arrays, but
C has no way to express this, that's why the function is declared as PCHAR*,
that is (semantically) a pointer to a pointer to a char, but in fact it's
just a pointer to a pointer.
The interop marshaler has no idea what this pointer points to, so you can't
use char[] in the DllImport signature. a second problem with this (and all
of the functions returning pointers to pointer) is:
- "who owns the memory allocated by the "thing" pointed to, and
- which allocator was used to allocate the memory.
Again the marshaler has no answers to these questions, however, when you
declare the return as char[], the marshaler assumes that memory was
allocated using CoTaskMemAlloc (which is the marshaler's default) and should
be de-allocated using CoTAskMemFree, both of which are wrong (you have to
call a ldap function to free the buffer, remember!).
In order to solve this whole mess, you have to declare the function as
returning an IntPtr and handle the marshaling yourself like I did in the
sample.


Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top