R
rdilipk
I am posting at the end of this post some code that P/Invoke's
SetSystemTime to set the local system time. This call fails -- i.e
the time is not set and the API returns false. However calling
Marshal.GetLastWin32Error immediately afterwards returns an errorcode
of 0 indicating that the operation somehow executed successfully.
This is a plain vanilla console app written in C#. It runs on vista
and has a manifest embedded in it that has 'requireAdministrator'
privilege level on it. The logged on user belongs to the
administrator group and the UAC is set at "prompt for consent".
What am I missing? (FWIW, I didn't write the P/Invoke signatures
myself. I just lifted them out of various postings on the internet --
is there a mistake in that somewhere)?
It seems similar to what was reported here:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1807068&SiteID=1
/********** CODE ********************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace VistaUACTest
{
class Program
{
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct SystemTime
{
public short year;
public short month;
public short dayOfWeek;
public short day;
public short hour;
public short minute;
public short second;
public short milliseconds;
}
[DllImport("kernel32.dll")]
private static extern bool SetLocalTime(ref SystemTime
systime);
[DllImport("kernel32.dll")]
private static extern bool SetSystemTime(ref SystemTime
systime);
private const int ANYSIZE_ARRAY = 1;
private const string SE_SYSTEMTIME_NAME =
"SeSystemtimePrivilege";
private const int SE_PRIVILEGE_ENABLED = 0x00000002;
private const int TOKEN_QUERY = 0x0008;
private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public int Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst =
ANYSIZE_ARRAY)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool OpenProcessToken(int ProcessHandle,
int DesiredAccess, ref int TokenHandle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetCurrentProcess();
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool LookupPrivilegeValue(string
lpSystemName, string lpName,
[MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool AdjustTokenPrivileges(int
TokenHandle,
int
DisableAllPrivileges,
[MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES NewState,
int
BufferLength,
[MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES PreviousState,
ref
int ReturnLength);
static void Main(string[] args)
{
try
{
// because the docs for SetSystemTime says that the
SE_SYSTEMTIME_NAME privilege is disabled by default
// this call doesn't really help though
AdjustPrivileges();
SystemTime st = new SystemTime();
st.hour = 10;
if (!SetSystemTime(ref st))
{
// the return value says the call failed, however
Marshal.GetLastWin32Error() says the previous P/Invoke operation
// completed successfully (the default ctor of
Win32Exception calls GetLastWin32Error)
throw new Win32Exception();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
}
public static bool AdjustPrivileges()
{
TOKEN_PRIVILEGES tkNew = new TOKEN_PRIVILEGES();
tkNew.Privileges = new LUID_AND_ATTRIBUTES[ANYSIZE_ARRAY];
TOKEN_PRIVILEGES tkOld = new TOKEN_PRIVILEGES();
tkOld.Privileges = new LUID_AND_ATTRIBUTES[ANYSIZE_ARRAY];
LUID luid = new LUID();
int token = -1;
int oldluidSize = 0;
if (LookupPrivilegeValue(null, SE_SYSTEMTIME_NAME, ref
luid))
{
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token))
{
tkNew.PrivilegeCount = 1;
tkNew.Privileges[0].Attributes =
SE_PRIVILEGE_ENABLED;
tkNew.Privileges[0].Luid = luid;
int luidSize =
Marshal.SizeOf(typeof(TOKEN_PRIVILEGES));
if (AdjustTokenPrivileges(token, 0, ref tkNew,
luidSize, ref tkOld, ref oldluidSize))
{
return true;
}
}
}
return false;
}
}
}
/************ CODE ************************/
SetSystemTime to set the local system time. This call fails -- i.e
the time is not set and the API returns false. However calling
Marshal.GetLastWin32Error immediately afterwards returns an errorcode
of 0 indicating that the operation somehow executed successfully.
This is a plain vanilla console app written in C#. It runs on vista
and has a manifest embedded in it that has 'requireAdministrator'
privilege level on it. The logged on user belongs to the
administrator group and the UAC is set at "prompt for consent".
What am I missing? (FWIW, I didn't write the P/Invoke signatures
myself. I just lifted them out of various postings on the internet --
is there a mistake in that somewhere)?
It seems similar to what was reported here:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1807068&SiteID=1
/********** CODE ********************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace VistaUACTest
{
class Program
{
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct SystemTime
{
public short year;
public short month;
public short dayOfWeek;
public short day;
public short hour;
public short minute;
public short second;
public short milliseconds;
}
[DllImport("kernel32.dll")]
private static extern bool SetLocalTime(ref SystemTime
systime);
[DllImport("kernel32.dll")]
private static extern bool SetSystemTime(ref SystemTime
systime);
private const int ANYSIZE_ARRAY = 1;
private const string SE_SYSTEMTIME_NAME =
"SeSystemtimePrivilege";
private const int SE_PRIVILEGE_ENABLED = 0x00000002;
private const int TOKEN_QUERY = 0x0008;
private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public int Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst =
ANYSIZE_ARRAY)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool OpenProcessToken(int ProcessHandle,
int DesiredAccess, ref int TokenHandle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetCurrentProcess();
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool LookupPrivilegeValue(string
lpSystemName, string lpName,
[MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool AdjustTokenPrivileges(int
TokenHandle,
int
DisableAllPrivileges,
[MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES NewState,
int
BufferLength,
[MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES PreviousState,
ref
int ReturnLength);
static void Main(string[] args)
{
try
{
// because the docs for SetSystemTime says that the
SE_SYSTEMTIME_NAME privilege is disabled by default
// this call doesn't really help though
AdjustPrivileges();
SystemTime st = new SystemTime();
st.hour = 10;
if (!SetSystemTime(ref st))
{
// the return value says the call failed, however
Marshal.GetLastWin32Error() says the previous P/Invoke operation
// completed successfully (the default ctor of
Win32Exception calls GetLastWin32Error)
throw new Win32Exception();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
}
public static bool AdjustPrivileges()
{
TOKEN_PRIVILEGES tkNew = new TOKEN_PRIVILEGES();
tkNew.Privileges = new LUID_AND_ATTRIBUTES[ANYSIZE_ARRAY];
TOKEN_PRIVILEGES tkOld = new TOKEN_PRIVILEGES();
tkOld.Privileges = new LUID_AND_ATTRIBUTES[ANYSIZE_ARRAY];
LUID luid = new LUID();
int token = -1;
int oldluidSize = 0;
if (LookupPrivilegeValue(null, SE_SYSTEMTIME_NAME, ref
luid))
{
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token))
{
tkNew.PrivilegeCount = 1;
tkNew.Privileges[0].Attributes =
SE_PRIVILEGE_ENABLED;
tkNew.Privileges[0].Luid = luid;
int luidSize =
Marshal.SizeOf(typeof(TOKEN_PRIVILEGES));
if (AdjustTokenPrivileges(token, 0, ref tkNew,
luidSize, ref tkOld, ref oldluidSize))
{
return true;
}
}
}
return false;
}
}
}
/************ CODE ************************/