views:

57

answers:

2

EDIT: followup at http://stackoverflow.com/questions/1791377/netusermodalsget-returns-strings-incorrectly-for-c-net

I'm struggling with the DLL declarations for this function:

NET_API_STATUS NetUserModalsGet(
  __in   LPCWSTR servername,
  __in   DWORD level,
  __out  LPBYTE *bufptr
);

(Reference: http://msdn.microsoft.com/en-us/library/aa370656%28VS.85%29.aspx)

I tried this:

private string BArrayToString(byte[] myArray)
{
    string retVal = "";
    if (myArray == null)
        retVal = "Null";
    else
    {
        foreach (byte myByte in myArray)
        {
            retVal += myByte.ToString("X2");
        }
    }
    return retVal;
}

...

[DllImport("netapi32.dll")]
public static extern int NetUserModalsGet(
  string servername,
  int level,
  out byte[] bufptr
);

[DllImport("netapi32.dll")]
public static extern int NetApiBufferFree(
  byte[] bufptr
);

...

int retVal;
byte[] myBuf;

retVal = NetUserModalsGet("\\\\" + tbHost.Text, 0, out myBuf);
myResults.Text += String.Format("retVal={0}\nBuffer={1}\n", retVal, BArrayToString(myBuf));
retVal = NetApiBufferFree(myBuf);

I get a return value of 1231 (Network Location cannot be reached) no matter if I use an IP address or a NetBIOS name of a machine that's undoubtedly online, or even my own. On edit: this happens even if I don't put a "\\" in front of the hostname.

I'm doing things wrong, I know, and let's not even get started on how to declare that blasted return buffer (which can have a number of different lengths, ewww).

+1  A: 

From pinvoke.net (they also have some sample code on how to use it):

   [DllImport("netapi32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    static extern uint NetUserModalsGet(
        string server,
        int level,
        out IntPtr BufPtr);
Gonzalo
Mmmm, gonna try. All that's missing is how to declare the USER_MODALS_INFO_X types. I assume DWORD => int, LPWSTR => string, PSID => int, is that right?
JCCyC
Yes, that is correct.
Gonzalo
It works! Well, for the integers at least. I'm running this against a machine that's a member of a domain, but usrmod1_primary returns an empty string. Any clues?
JCCyC
Ah, and usrmod2_domain_name gets me a single letter "M". The actual domai9n name does begin with M. Unicode shenanigans, I presume.
JCCyC
usrmod1_primary is a unicode string so you should use char instead of byte.
Gonzalo
I'm not using byte anymore, I'm doing it by the book (or so I thought). See: http://stackoverflow.com/questions/1791377/netusermodalsget-returns-strings-incorrectly-for-c-net
JCCyC
A: 

It would be better to use

System.Text.Encoding.ASCII.GetBytes(somestring_param)
and
System.Text.Encoding.ASCII.GetString(byte_array);
instead of your own routine BArrayToString.

Hope this helps, Best regards, Tom.

tommieb75