Ok, here is something that should work for you:
[DllImport("C:\\WINNT\\System32\\advapi32.dll")]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out IntPtr phToken);
[DllImport("C:\\WINNT\\System32\\Kernel32.dll")]
public static extern int GetLastError();
[DllImport("kernel32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
const int UF_SCRIPT = 0x0001;
const int UF_ACCOUNTDISABLE = 0x0002;
const int UF_HOMEDIR_REQUIRED = 0x0008;
const int UF_LOCKOUT = 0x0010;
const int UF_PASSWD_NOTREQD = 0x0020;
const int UF_PASSWD_CANT_CHANGE = 0x0040;
const int UF_TEMP_DUPLICATE_ACCOUNT = 0x0100;
const int UF_NORMAL_ACCOUNT = 0x0200;
const int UF_INTERDOMAIN_TRUST_ACCOUNT = 0x0800;
const int UF_WORKSTATION_TRUST_ACCOUNT = 0x1000;
const int UF_SERVER_TRUST_ACCOUNT = 0x2000;
const int UF_DONT_EXPIRE_PASSWD = 0x10000;
const int UF_MNS_LOGON_ACCOUNT = 0x20000;
//get ahold somehow of the user that you want to reset their password for
DirectoryEntry _user = new DirectoryEntry(adPath, adminUsername, adminPassword, AuthenticationTypes.Secure);
/// <summary>
/// Reset the user's password
/// </summary>
/// <param name="reset">(bool) change password at next login</param>
/// <returns>user's password (string)</returns>
public string ResetPassword(bool reset)
{
string sPwd = _user.Properties["sAMAccountName"][0].ToString() + ".tmp"; //static password here
int flags;
if(reset)
{
//first have to remove "Password Never Expires Flag"
flags = (int)_user.Properties["userAccountControl"].Value;
if(Convert.ToBoolean(flags & UF_DONT_EXPIRE_PASSWD))
{
flags = (flags ^ UF_DONT_EXPIRE_PASSWD);
_user.Properties["userAccountControl"].Value = flags;
}
if(_user.Properties.Contains("pwdLastSet"))
_user.Properties["pwdLastSet"].Value = 0;
else
_user.Properties["pwdLastSet"].Add(0);
}
else
{
//clear the change password at next login if it is there
if(_user.Properties.Contains("pwdLastSet"))
_user.Properties["pwdLastSet"].Value = -1;
else
_user.Properties["pwdLastSet"].Add(-1);
//set the password never expires flag.
flags = (int)_user.Properties["userAccountControl"].Value;
if(!Convert.ToBoolean(flags & UF_DONT_EXPIRE_PASSWD))
{
flags = (flags | UF_DONT_EXPIRE_PASSWD);
_user.Properties["userAccountControl"].Value = flags;
}
}
//Change thread context to Admin's **IMPERSONATION CODE STARTS HERE**
IntPtr token = IntPtr.Zero;
string username = ""; //same as in your _user constructor
string domain = ""; //same as in your _user constructor
bool result = LogonUser(username, domain , Config.Settings.AdminPassword, 3, 0, out token);
if(!result)
{
int errCode = GetLastError();
string errMessage = String.Empty;
switch(errCode)
{
case 5:
errMessage = "Access Denied";
break;
case 1326:
errMessage = "Logon failure: unknown user name or bad password.";
break;
}
throw new Exception(String.Format("GetLastError() returned {0}, \"{1}\"", errCode, errMessage));
}
else
{
WindowsIdentity wi = new WindowsIdentity(token);
WindowsImpersonationContext wic = wi.Impersonate();
_user.Invoke("SetPassword", new object[]{sPwd.ToLower()});
_user.CommitChanges();
wic.Undo(); //end impersonation **END IMPERSONATION**
CloseHandle(token);
}
return sPwd.ToLower();
}
Ok, so there is a bit of code here... just declare the DllImports and see how I am using the Impersonation code. I have some more stuff in there because I need it to do a couple more things (like set "Change Password at next Login").
Good luck, it is a little hard to cut & paste into this window, so I hope I did not leave anything out (it is part of much bigger class).