2009-11-24 2 views
0

EDIT: Encore un suivi à https://stackoverflow.com/questions/1799742/shouldnt-netusermodalsget-tell-me-what-domain-a-machine-is-part-of-and-whereNetUserModalsGet() renvoie des chaînes de façon incorrecte pour C# .NET

Merci à l'aide de Gonzalo, je suis en mesure de use the NetUserModalsGet() from C#. Mais il y a encore quelques plis: les membres de la chaîne (usrmod1_primary et usrmod2_domain_name) sortent foiré. Voici le code:

[DllImport("netapi32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 
public static extern uint NetUserModalsGet(
    string server, 
    int level, 
    out IntPtr BufPtr 
); 

[DllImport("netapi32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 
public static extern uint NetApiBufferFree(
    IntPtr bufptr 
); 

public struct USER_MODALS_INFO_0 
{ 
    public uint usrmod0_min_passwd_len; 
    public uint usrmod0_max_passwd_age; 
    public uint usrmod0_min_passwd_age; 
    public uint usrmod0_force_logoff; 
    public uint usrmod0_password_hist_len; 
}; 

public struct USER_MODALS_INFO_1 
{ 
    public uint usrmod1_role; 
    public string usrmod1_primary; 
}; 

public struct USER_MODALS_INFO_2 
{ 
    public string usrmod2_domain_name; 
    public uint usrmod2_domain_id; 
}; 

public struct USER_MODALS_INFO_3 
{ 
    public uint usrmod3_lockout_duration; 
    public uint usrmod3_lockout_observation_window; 
    public uint usrmod3_lockout_threshold; 
}; 

... 

uint retVal; 
IntPtr myBuf; 
USER_MODALS_INFO_0 myInfo0 = new USER_MODALS_INFO_0(); 
USER_MODALS_INFO_1 myInfo1 = new USER_MODALS_INFO_1(); 
USER_MODALS_INFO_2 myInfo2 = new USER_MODALS_INFO_2(); 
USER_MODALS_INFO_3 myInfo3 = new USER_MODALS_INFO_3(); 

retVal = NetUserModalsGet("\\\\" + tbHost.Text, 0, out myBuf); 
if (retVal == 0) 
{ 
    myInfo0 = (USER_MODALS_INFO_0)Marshal.PtrToStructure(myBuf, typeof(USER_MODALS_INFO_0)); 
    myResults += String.Format("usrmod0_force_logoff={0}\nusrmod0_max_passwd_age={1}\nusrmod0_min_passwd_age={2}\nusrmod0_min_passwd_len={3}\nusrmod0_password_hist_len={4}\n", 
     myInfo0.usrmod0_force_logoff.ToString("X8"), 
     myInfo0.usrmod0_max_passwd_age.ToString("X8"), 
     myInfo0.usrmod0_min_passwd_age.ToString("X8"), 
     myInfo0.usrmod0_min_passwd_len.ToString("X8"), 
     myInfo0.usrmod0_password_hist_len.ToString("X8") 
     ); 
} 
myResults += String.Format("retVal={0}\n\n", retVal); 
retVal = NetApiBufferFree(myBuf); 

retVal = NetUserModalsGet("\\\\" + tbHost.Text, 1, out myBuf); 
if (retVal == 0) 
{ 
    myInfo1 = (USER_MODALS_INFO_1)Marshal.PtrToStructure(myBuf, typeof(USER_MODALS_INFO_1)); 
    myResults += String.Format("usrmod1_primary={0}\nusrmod1_role={1}\n", 
     myInfo1.usrmod1_primary, 
     myInfo1.usrmod1_role.ToString("X8") 
     ); 
} 
myResults += String.Format("retVal={0}\n\n", retVal); 
retVal = NetApiBufferFree(myBuf); 

retVal = NetUserModalsGet("\\\\" + tbHost.Text, 2, out myBuf); 
if (retVal == 0) 
{ 
    myInfo2 = (USER_MODALS_INFO_2)Marshal.PtrToStructure(myBuf, typeof(USER_MODALS_INFO_2)); 
    myResults += String.Format("usrmod2_domain_id={0}\nusrmod2_domain_name={1}\n", 
     myInfo2.usrmod2_domain_id.ToString("X8"), 
     myInfo2.usrmod2_domain_name 
     ); 
} 
myResults += String.Format("retVal={0}\n\n", retVal); 
retVal = NetApiBufferFree(myBuf); 

retVal = NetUserModalsGet("\\\\" + tbHost.Text, 3, out myBuf); 
if (retVal == 0) 
{ 
    myInfo3 = (USER_MODALS_INFO_3)Marshal.PtrToStructure(myBuf, typeof(USER_MODALS_INFO_3)); 
    myResults += String.Format("usrmod3_lockout_duration={0}\nusrmod3_lockout_observation_window={1}\nusrmod3_lockout_threshold={2}\n", 
     myInfo3.usrmod3_lockout_duration.ToString("X8"), 
     myInfo3.usrmod3_lockout_observation_window.ToString("X8"), 
     myInfo3.usrmod3_lockout_threshold.ToString("X8") 
     ); 
} 
myResults += String.Format("retVal={0}\n\n", retVal); 
retVal = NetApiBufferFree(myBuf); 

Ce que je reçois comme résultat:

usrmod0_force_logoff=FFFFFFFF 
usrmod0_max_passwd_age=00375F00 
usrmod0_min_passwd_age=00000000 
usrmod0_min_passwd_len=00000000 
usrmod0_password_hist_len=00000000 
retVal=0 

usrmod1_primary= 
usrmod1_role=00000003 
retVal=0 

usrmod2_domain_id=08C409B0 
usrmod2_domain_name=M 
retVal=0 

usrmod3_lockout_duration=0000012C 
usrmod3_lockout_observation_window=0000012C 
usrmod3_lockout_threshold=00000000 
retVal=0 

Tout cela, sauf usrmod1_primary et usrmod2_domain_name est logique. La machine testée est un membre d'un domaine, dont le nom commence par un M. Je sens un peu d'Unicode hijinx, mais je ne vois pas ce qui ne va pas.

+1

Je ne connais pas la réponse mais je dirais que votre avatar descend vers la piscine de MonteCarlo. –

+0

Vous obtenez un mod juste pour ça. Vis d'utilité. ;) – JCCyC

Répondre

2

Les chaînes de vos structures sont marshalées en tant que ANSI par défaut, mais les API Net * fonctionnent presque exclusivement avec des chaînes Unicode. Donc, appliquez l'attribut

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 

à USER_MODALS_INFO_1 et _2 et votre devrait être bon.

Quelques autres:

  • Il n'y a aucun point dans la spécification SetLastError = true dans yor DllImport attributs dans ce cas, parce que NetUserModalsGet ne retourne pas d'erreur informations via SetLastError (vous obtenez il en la valeur de retour).

  • USER_MODALS_INFO_2.usrmod2_domain_id est un pointeur et donc mieux modélisé comme un IntPtr (pour la compatibilité x64 ).

+0

Cela fonctionne! Deux choses cependant: (1) Je vais finalement vouloir plonger dans ce à quoi usrmod2_domain_id pointe, mais pas maintenant; (2) Bien que la machine soit membre d'un domaine, elle retourne une chaîne vide dans usrmod1_primary et le nom de la machine elle-même dans usrmod2_domain_name. Je vais probablement poster une autre question à ce sujet. – JCCyC

+0

Question de suivi: http://stackoverflow.com/questions/1799742/shouldnt-netusermodalsget-tell-me-what-domain-a-machine-is-part-of-and-where – JCCyC

Questions connexes