2 messaggi dal 13 settembre 2004
Ho costruito un'applicazione per Windows Embedded utilizzando WinForms.
Allo start dell'applicazioen ho bisogno di sincronizzare la data in modalità offline e quindi con un form faccio mettere all'utente la data corrente e poi utilizzo la SetLocalTime (tramite PInvoke) per aggiornare la data di sistema.
La chiamata ritorna una eccezione con codice 5 (Access Denied).
Siccome l'utente corrente non è amministratore locale della macchina uso prima l'AdjustTokenPrivileges per dare al processo il permesso SE_SYSTEMTIME_NAME e poi l'Impersonation per avere i diritti da amministratore.
C'è qualcuno che sa da cosa può dipendere?

Questo è il codice C# della Classe Impersonation:
    class Impersonation
    {
        // obtains user token
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        // closes open handes returned by LogonUser
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        // creates duplicate token handle
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
            int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

        private IntPtr pExistingTokenHandle = new IntPtr(0);
        private IntPtr pDuplicateTokenHandle = new IntPtr(0);

        public Impersonation()
        {
            // initialize tokens
            pExistingTokenHandle = new IntPtr(0);
            pDuplicateTokenHandle = new IntPtr(0);
            pExistingTokenHandle = IntPtr.Zero;
            pDuplicateTokenHandle = IntPtr.Zero;
        }

        public WindowsImpersonationContext ImpersonateUser(string sUsername, string sDomain, string sPassword)
        {
            if (sDomain == "")
                sDomain = System.Environment.MachineName;

            string sResult = null;

            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2;

            // get handle to token
            bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    ref pExistingTokenHandle);

            // did impersonation fail?
            if (false == bImpersonated)
            {
                int nErrorCode = Marshal.GetLastWin32Error();
                throw new Win32Exception(nErrorCode);
            }

            // Get identity before impersonation
            bool bRetVal = DuplicateToken(pExistingTokenHandle,
                (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                    ref pDuplicateTokenHandle);

            // did DuplicateToken fail?
            if (false == bRetVal)
            {
                int nErrorCode = Marshal.GetLastWin32Error();
                // close existing handle
                CloseHandle(pExistingTokenHandle);

                // show the reason why DuplicateToken failed
                MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
            else
            {
                // create new identity using new primary token
                WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
                WindowsImpersonationContext impersonatedUser = newId.Impersonate();

                return impersonatedUser;
            }

        }

        public void CloseHandles()
        {
            if (pExistingTokenHandle != IntPtr.Zero)
                CloseHandle(pExistingTokenHandle);
            if (pDuplicateTokenHandle != IntPtr.Zero)
                CloseHandle(pDuplicateTokenHandle);
        }
    }

    // group type enum
    public enum SECURITY_IMPERSONATION_LEVEL : int
    {
        SecurityAnonymous = 0,
        SecurityIdentification = 1,
        SecurityImpersonation = 2,
        SecurityDelegation = 3
    }


Questo è il codice della mia classe SystemDateTimeUtils:
class SystemDateTimeUtils
    {
        #region pinvokes

        [DllImport("kernel32.dll")]
        private static extern bool SetLocalTime(ref SYSTEMTIME time);

        [DllImport("kernel32.dll")]
        private static extern bool SetSystemTime(ref SYSTEMTIME systime);

        [DllImport("kernel32.dll")]
        private static extern int GetLastError();

        [DllImport("kernel32.dll")]
        private static extern void GetLocalTime(out SYSTEMTIME time);

        [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);

        #endregion

        #region Constants

        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;

        #endregion

        #region SetLocalTime

        public static bool SetLocalTime(DateTime systemTime, out int errorCode)
        {
            AdjustPrivileges();
            SYSTEMTIME time = GetSystemTime(ref systemTime);

            WindowsImpersonationContext newUser = null;
            bool result = false;
            Impersonation imp = new Impersonation();
            try
            {
                newUser = imp.ImpersonateUser(<my_username>, ".", <my_password>);
                result = SetLocalTime(ref time);

                if (result)
                    result = SetLocalTime(ref time);

                if (!result)
                    errorCode = GetLastError();
                else
                    errorCode = 0;
            }
            finally
            {
                imp.CloseHandles();
                if (newUser != null)
                    newUser.Undo();
            }

            return result;
        }

        #endregion

        #region GetSystemTime

        private static SYSTEMTIME GetSystemTime(ref DateTime systemTime)
        {

            SYSTEMTIME time = new SYSTEMTIME();
            time.wDay = (ushort)systemTime.Day;
            time.wDayOfWeek = (ushort)(systemTime.DayOfWeek);
            time.wHour = (ushort)systemTime.Hour;
            time.wMilliseconds = (ushort)systemTime.Millisecond;
            time.wMinute = (ushort)systemTime.Minute;
            time.wMonth = (ushort)systemTime.Month;
            time.wSecond = (ushort)systemTime.Second;
            time.wYear = (ushort)systemTime.Year;
            return time;
        }

        #endregion

        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;
        }


        #region Strutture

        [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct SYSTEMTIME
        {
            public ushort wYear, wMonth, wDayOfWeek, wDay,
                wHour, wMinute, wSecond, wMilliseconds;
        }

        [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;
        }

        #endregion
    }


e questo è il codice della chiamata:

int errorCode = 0;
SystemDateTimeUtils.SetLocalTime(currentDate, out errorCode);
if (errorCode != 0)
    MessageBox.Show("Error setting local system time to desired value: " +
        "error code " + errorCode, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.
In primo piano

I più letti di oggi

Media
In evidenza
MISC