Rebooting a Windows Box Programmatically

It is funny that, to write a programming task as trivial as rebooting a Win32 box, one needs to write some non-trivial code.

You could always choose to just copy the code from some place and forget about it. But, many years ago when I was a beginner to the windows SDK, I found that understanding how this one program worked gave me a lot of insight into the workinga of the Win32 system.

Okay, so we want to write code that reboots a machine. Where do we start? We start by messing with the "access token."

I quote, "An access token contains the security information for a logon session. The system creates an access token when a user logs on, and every process executed on behalf of the user has a copy of the token. The token identifies the user, the user's groups, and the user's privileges. The system uses the token to control access to securable objects and to control the ability of the user to perform various system-related operations on the local computer."

For more information about access control mechanisms, please refer to:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/access_control_model.asp

In short, the access token is an annoying piece of gooey stuff that sticks to all processes that you launch. It is this token that makes you see messages such as "you do not have permission to ....." So, you can start by "adjusting" your access token.

if (!OpenProcessToken(GetCurrentProcess(),
   TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
   {
      printf("OpenProcessToken failed!");
      return 0;
   }

With this call, you have in effect requested permission to enable or disable the privileges in an access token for the current process.

Why do you do this? Well, you guessed it. You need to do this so that you can now "tweak" the acces token. By default, the access token does not contain system shutdown privileges.

But, as with most "system" calls, you need to use some convoluted language to communicate with the API. To adjust access tokens, you need to use the TOKEN_PRIVILEGES structure and retrieve the LUID used on a specified system to locally represent the specified privilege name.

TOKEN_PRIVILEGES tkp;
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
                     &tkp.Privileges[0].Luid);

Now, you have the privilege you want in the language that the system wants. Looks like a piece of cake You now need to set up your TOKEN_PRIVILEGES structure to tell the system that you want to enable the shutdown privilege based on the LUID you just retrieved.

tkp.PrivilegeCount = 1;    // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

Now that you have the LUID and speak the "system" language, your wishes will be respected. So, now you can use this power and do what you have been waiting to do all this time—tweak the access token. You will use AdjustTokenPrivileges for this.

The AdjustTokenPrivileges function enables or disables privileges in the specified access token. Enabling or disabling privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access. You already verified this privilege by using OpenProcessToken.

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
                      (PTOKEN_PRIVILEGES)NULL, 0);

Weirdly enough, this method returns a BOOL. I say weird because the return value is just TRUE/FALSE, but if you had more than one PRIVILEGE that you tried to set, there could be more than two outcomes.

  1. All privileges were successfully set
  2. Some privileges could not be set
  3. The API failed altogether

Agreed, you are setting just one privilege here. But, you are also learning more about the Win32 API on the way. So, instead of relying on the return value, you use the old faithful "GetLastError."

if(GetLastError() != ERROR_SUCCESS)
{
   printf("AdjustTokenPrivileges failed");
   return 0;
}

You are almost there. You tweaked the access token and you are now in control. The actual method that you will use to reboot the machine is pretty straightforward. Here it is:

BOOL b = ExitWindowsEx( EWX_REBOOT|EWX_FORCE,
                        SHTDN_REASON_MINOR_MAINTENANCE |
                        SHTDN_REASON_FLAG_PLANNED);

The ExitWindowsEx function either logs off the current user, shuts down the system, or shuts down and restarts the system.

You Did It!! Wasn't it cool?

Well, as always, you could check the help on each of these APIs and dig deeper into them. This article is meant just to initiate the beginner or the beginner-intermediate developer into a facet of the Win32 API that is not often used. Hopefully, the article served its purpose.



About the Author

Vinayak Raghuvamshi

I am known as the Carpal Tunnel Coder - You probably guessed a lot about me already :-)

Downloads

Comments

  • What if your're not logged in?

    Posted by saddle on 11/20/2005 07:52am

    If the program requiring to shutdowm the PC is running when no-one is logged in, the call to AdjustTokenPrivileges fails (I've tried). How do you get something like the scheduler or screen saver system to have the rights to modify (or even have the tokens) SE_SHUTDOWN_NAME? Thanks, Saddle (In the land of Oz)

    Reply
  • I liked it

    Posted by santoct2002 on 05/27/2005 05:09am

    It is a goodway, it makes tough things looks easy.

    Reply
  • Useful Article

    Posted by Ajay Vijay on 02/19/2005 05:47am

    Coool article with simple explaination. Keep it up! :thumb:

    Reply
  • Nice article

    Posted by nangluc on 12/21/2004 09:32pm

    I read some articles about this, quite weird! But after reading this I see it's not that difficult. Thank you!

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

  • As mobile devices have pushed their way into the enterprise, they have brought cloud apps along with them. This app explosion means account passwords are multiplying, which exposes corporate data and leads to help desk calls from frustrated users. This paper will discover how IT can improve user productivity, gain visibility and control over SaaS and mobile apps, and stop password sprawl. Download this white paper to learn: How you can leverage your existing AD to manage app access. Key capabilities to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds