none
Any suggestions on why I'm unable to SetLocalTime() under Windows 7 with standard Windows user and how I can work around this?

    Question

  • System setup: Windows 7, UAC turned off, (non-administrator) standard user account.
    Note: The solution I'm looking for needs to be accomplished programaticaly and due to FDA restrictions, we are unable to simply use a Windows system administrator account.

    Problem: Calls to SetLocalTime() fail (ie. GetLastError() returns 1314 - ERROR_PRIVILEGE_NOT_HELD). 

    I've manually created an local administrator account which I am attempting to temporarily switch to (via LogonUser()) in the hopes of gaining enough privileges to complete the SetLocalTime call but this approach doesn't seem to succeed.  Based on researching this, my understanding is that even though I'm logging in as a local admin, the token I get back (from LogonUser(...)) won't have higher privileges than the standard non-admin user which I'm currently logged in under.

    I've researched the internet and almost pulled all my hair out...there are a number of people experiencing the same\similar problem but no solutions that I've found.


    I've also attempted to use:
           OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hLogonUserToken);
    instead of the LogonUser(....), in order to set the TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY parameters but that still resulted in the SetLocalTime returning 1314 in GetLastError.

    Thanks for your time, help and any suggestions.

    Here is my code:
    .
    .
    .
    LogonUser(L"adminUserName", L".", L"adminPassword", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hLogonUserToken);

    TOKEN_PRIVILEGES TokenPriv;
    TokenPriv.PrivilegeCount = 1;
    TokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &(TokenPriv.Privileges[0].Luid)))
    {
         bRet = AdjustTokenPrivileges(hLogonUserToken, FALSE, &TokenPriv, sizeof(TokenPriv), NULL, NULL);
         if (!bRet)
         {
               // Error....
         }

         // Duplicate the token.
         bRet = DuplicateTokenEx(hLogonUserToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hToken );
          if (!bRet)
         {
               // Error...
         }

       // Impersonate the elevated user.
       bRet = ImpersonateLoggedOnUser(hToken);
       if (!bRet)
       {
           // Error....
       }
                 
       bRet = SetLocalTime(&stNewCurrDateTime);
       if (!bRet)
       {
            DWORD dwErr = GetLastError();    // ERROR_PRIVILEGE_NOT_HELD
       }
      
       bRet = RevertToSelf();
       if (!bRet)
       {
           // Error....  
       }
    }

    // gcr pedalhed
    • Moved by Wesley Yao Monday, December 21, 2009 9:29 AM sdk question (From:Visual C++ Language)
    Thursday, December 17, 2009 3:31 PM

All replies

  • Hi,

    I had exactly the same issue with a piece of code I was writing C#.

    Simple, Microsoft decided in the infinite wisdom, that if you are Administrator under Vista and Win7, that you AREN'T Administrator.

    If you are debugging your app under VS, make sure you run VS from the start 'As Administrator'.

    If you are running the app straight from exdplorer, make sure you execute 'As administrator'.

    Yes, even if you login as administrator, with the correct password etc etc. you STILL aren't administrator! Madness.

    Spitz
    Saturday, February 13, 2010 10:39 AM
  • @Anonymous

    You say madness but it seems you miss the whole point of this feature. But well, I guess that kind of thing is normal for a lot of Windows users, who think that having full control of their system is best but then bash Microsoft for making Windows so insecure when they use it exclusively with Administrative users.

    @Floria

    What are you trying to accomplish? You are trying to set the System time. This is a global setting which affects everything with the computer, so the question is why?
    There is probably a better way of doing what you want without the need for switching the system time. It is possible to work out differences manually without needing to set the system time. In .Net there is the whole DateTime struct and time related structures to do this.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    Saturday, February 13, 2010 1:18 PM
  • I am Unix programmer, so know all about access permissions and NOT being logged in a root. My point is very simple. If I AM administrator, (and I do need to be from time to time) AND I know the admin password, and I have access to my console keyboard, then I expect administrator access, not a half way house. If I login as root on a Unix system (which is rare) then I expect to BE root, not have a screen come up every time I run something saying, 'Are you sure you want to do this?'.

    This all comes about presicely BECAUSE Microsoft's OS began life as a single user OS where you were always admin. That meant every time you ran an executable you ran as root, which meant any old nasty virus and script could do whatever it liked to your unsuspecting user. Microsoft have been living with that legacy for 20 years. Unix does not suffer anything like the attacks that Windows does because it was built on the solid ground of user access control. Apple makes great sway by the claim they are 'virus free' and that's why.

    Back to where I was. I have a windows box which is paired with an embedded unix system. The unix system is a piece of hardware that has an NTP client emdedded on it and has absolute precision time encodded. When I boot the two machines from battery, I want them both to agree on the time. The unix box is guaranteed to have correct time. The obvious solution is to read that time and set my time to it. I could use windows built in ntp time client also, but they would be out of sync for up to an hour whilst it re-sync's. This is a hardware system and on boot I want clocks agreeing.

    So I want a program to boot and set time! My code is C# and I want to set the time. Give me another way to do that and I'll be glad to use a C# call.
    Monday, February 15, 2010 5:54 PM
  • @Anonymous:

    Microsoft has a HUGE amount of users, and most of them are just above monkeys when it comes to using a PC.  I don't know about training monkeys, but I bet is not the simplest thing to do.  The truth is that people are used to the fact that their user accounts are administrators, and changing this for them IS madness.  This has nothing to do with the fact that Windows comes from a single-user platform.  It is a matter of supporting the majority of the users, while providing a more secure computing environment.

    Can Microsoft change this?  Or are Microsoft developers simply incompetent?  Yes, they can change it.  No, they are not incompetent; actually they are close to brilliant most of the time.  It is a matter of appealing to the majority, and the majority says "let me be an administrator, but make my system secure".  Our job as developers is simple:  Follow the rules.  Do you want to synchronize the Windows PC time on boot?  Provide credentials.  Are you bothered by the Credentials UI prompt?  Make your code a Windows Service and make it run as SYSTEM.  Is not like Microsoft doesn't give you ways to do things.  There are ways.  You are just not following the rules.
    MCP
    Sunday, February 21, 2010 5:57 AM
  • Has anyone found a solution to this yet? 

    I don't need sub-second accuary on the time and I am not always guaranteed to have network connections when I am setting times so I also have a GPS connection that I can be using to set the time and this does not work well as a system service. 

     

    Tuesday, May 11, 2010 10:15 AM
  • Crescens2k

    Setting the System time is one of the things I need to accomplish via my applications UI.  Among other things are network specific settings etc that are tied to the machine my user will be using.  Hence, I want them to go through my application to make these changes and not through Windows.  The point is, is that because changing the system time can affect ALL users on the Windows operating system, Microsoft has decided to make it difficult (if not impossible) for it to be done through coding. 

    So, I need to do this otherwise I wouldn't be asking.  There isn't a "workaround" (ie. the user can double click the clock on the task bar and change the time) because my application is running in the system shell and the user doesn't have access to Window directly.

     

    any suggestions?

     

    Thanks in advance.

    Friday, May 21, 2010 5:38 PM
  • Well, your only choice then is to either force your UI to run with Admin privileges all the time or use the recommended practice of having your application ask for privileges when you go to set the time.

    The way you would do the second is to put all your time update code into a seperate executable and then use ShellExecute or ShellExecuteEx with the runas verb. This will get your UI to prompt for privilages to run and then the executable will run with Admin privilages. There is also a way to do it with COM but that would mean you have to write a COM server.

    I think the only time this would fail is if the Group Policy has been changed so there is no standard user prompting for an Admin password.


    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://c2kblog.blogspot.com/
    Saturday, May 22, 2010 1:13 PM