mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
Add command-line shutdown/logoff utility
svn path=/trunk/; revision=10028
This commit is contained in:
parent
6d616faf61
commit
8d126dbfc4
6 changed files with 212 additions and 8 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $Id: fiber.c,v 1.3 2004/07/03 17:40:19 navaraf Exp $
|
||||
/* $Id: fiber.c,v 1.4 2004/07/07 22:29:37 gvg Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -426,7 +426,7 @@ int _tmain(int argc, _TCHAR const * const * argv)
|
|||
unsigned nFibers;
|
||||
|
||||
if(argc > 1)
|
||||
nFibers = _tcstoul(argv[1], 0, NULL);
|
||||
nFibers = _tcstoul(argv[1], NULL, 0);
|
||||
else
|
||||
nFibers = FIBERTEST_COUNT;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ include $(PATH_TO_TOP)/rules.mak
|
|||
|
||||
# Console system utilities
|
||||
# cabman cat net objdir partinfo pice ps sc stats
|
||||
UTIL_APPS = cat objdir partinfo pnpdump sc stats tickcount consw rundll32 regsvr32
|
||||
UTIL_APPS = cat objdir partinfo pnpdump sc shutdown stats tickcount consw rundll32 regsvr32
|
||||
|
||||
UTIL_NET_APPS =
|
||||
|
||||
|
|
6
reactos/apps/utils/shutdown/.cvsignore
Normal file
6
reactos/apps/utils/shutdown/.cvsignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.o
|
||||
*.d
|
||||
*.exe
|
||||
*.coff
|
||||
*.sym
|
||||
*.map
|
23
reactos/apps/utils/shutdown/Makefile
Normal file
23
reactos/apps/utils/shutdown/Makefile
Normal file
|
@ -0,0 +1,23 @@
|
|||
# $Id: Makefile,v 1.1 2004/07/07 22:29:37 gvg Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET_NORC = yes
|
||||
|
||||
TARGET_TYPE = program
|
||||
|
||||
TARGET_APPTYPE = console
|
||||
|
||||
TARGET_NAME = shutdown
|
||||
|
||||
TARGET_SDKLIBS = kernel32.a user32.a
|
||||
|
||||
TARGET_OBJECTS = shutdown.o
|
||||
|
||||
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# EOF
|
168
reactos/apps/utils/shutdown/shutdown.c
Normal file
168
reactos/apps/utils/shutdown/shutdown.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/* $Id: shutdown.c,v 1.1 2004/07/07 22:29:37 gvg Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS shutdown/logoff utility
|
||||
* FILE: apps/utils/shutdown/shutdown.c
|
||||
* PURPOSE: Initiate logoff, shutdown or reboot of the system
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
static void
|
||||
PrintUsage(LPCTSTR Cmd)
|
||||
{
|
||||
_ftprintf(stderr, _T("usage: %s [action] [flag]\n"), Cmd);
|
||||
_ftprintf(stderr, _T(" action = \"logoff\", \"reboot\", \"shutdown\" or \"poweroff\"\n"));
|
||||
_ftprintf(stderr, _T(" flag = \"force\"\n"));
|
||||
}
|
||||
|
||||
int
|
||||
_tmain(int argc, TCHAR *argv[])
|
||||
{
|
||||
static struct
|
||||
{
|
||||
TCHAR *Name;
|
||||
UINT ExitType;
|
||||
UINT ExitFlags;
|
||||
}
|
||||
Options[] =
|
||||
{
|
||||
{ _T("logoff"), EWX_LOGOFF, 0 },
|
||||
{ _T("logout"), EWX_LOGOFF, 0 },
|
||||
{ _T("poweroff"), EWX_POWEROFF, 0 },
|
||||
{ _T("powerdown"), EWX_POWEROFF, 0 },
|
||||
{ _T("reboot"), EWX_REBOOT, 0 },
|
||||
{ _T("restart"), EWX_REBOOT, 0 },
|
||||
{ _T("shutdown"), EWX_SHUTDOWN, 0 },
|
||||
{ _T("force"), 0, EWX_FORCE }
|
||||
};
|
||||
UINT ExitType, ExitFlags;
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES npr;
|
||||
TCHAR *Arg;
|
||||
TCHAR BaseName[_MAX_FNAME];
|
||||
unsigned i, j;
|
||||
BOOL HaveType, Matched;
|
||||
|
||||
ExitType = 0;
|
||||
ExitFlags = 0;
|
||||
HaveType = FALSE;
|
||||
|
||||
_tsplitpath(argv[0], NULL, NULL, BaseName, NULL);
|
||||
|
||||
/* Process optional arguments */
|
||||
for (i = 1; i < (unsigned) argc; i++)
|
||||
{
|
||||
/* Allow e.g. "/s" or "-l" for shutdown resp. logoff */
|
||||
Arg = argv[i];
|
||||
if (_T('/') == *Arg || _T('-') == *Arg)
|
||||
{
|
||||
Arg++;
|
||||
}
|
||||
|
||||
/* Search known options */
|
||||
Matched = FALSE;
|
||||
for (j = 0; j < sizeof(Options) / sizeof(Options[0]) && ! Matched; j++)
|
||||
{
|
||||
/* Match if arg starts the same as the option name */
|
||||
if (0 == _tcsnicmp(Options[j].Name, Arg, _tcslen(Arg)))
|
||||
{
|
||||
if (0 != Options[j].ExitType)
|
||||
{
|
||||
/* Can have only 1 type */
|
||||
if (HaveType)
|
||||
{
|
||||
PrintUsage(BaseName);
|
||||
exit(1);
|
||||
}
|
||||
ExitType = Options[j].ExitType;
|
||||
HaveType = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Can have only 1 flag */
|
||||
if (0 != ExitFlags)
|
||||
{
|
||||
PrintUsage(BaseName);
|
||||
exit(1);
|
||||
}
|
||||
ExitFlags |= Options[j].ExitFlags;
|
||||
}
|
||||
Matched = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Was the argument processed? */
|
||||
if (! Matched)
|
||||
{
|
||||
PrintUsage(BaseName);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check command name if user didn't explicitly specify action */
|
||||
if (! HaveType)
|
||||
{
|
||||
for (j = 0; j < sizeof(Options) / sizeof(Options[0]); j++)
|
||||
{
|
||||
if (0 == _tcsicmp(Options[j].Name, BaseName) && 0 != Options[j].ExitType)
|
||||
{
|
||||
ExitType = Options[j].ExitType;
|
||||
HaveType = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Still not sure what to do? */
|
||||
if (! HaveType)
|
||||
{
|
||||
PrintUsage(BaseName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Everyone can logoff, for the other actions you need the appropriate privilege */
|
||||
if (EWX_LOGOFF != ExitType)
|
||||
{
|
||||
/* enable shutdown privilege for current process */
|
||||
if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
|
||||
{
|
||||
_ftprintf(stderr, _T("OpenProcessToken failed with error %d\n"), (int) GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
npr.PrivilegeCount = 1;
|
||||
npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
if (! LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &npr.Privileges[0].Luid))
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
_ftprintf(stderr, _T("LookupPrivilegeValue failed with error %d\n"), (int) GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
if (! AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0)
|
||||
|| ERROR_SUCCESS != GetLastError())
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
if (ERROR_NOT_ALL_ASSIGNED == GetLastError())
|
||||
{
|
||||
_ftprintf(stderr, _T("You are not authorized to shutdown the system\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_ftprintf(stderr, _T("AdjustTokenPrivileges failed with error %d\n"), (int) GetLastError());
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
/* Finally do it */
|
||||
if (! ExitWindowsEx(ExitType | ExitFlags, 0))
|
||||
{
|
||||
_ftprintf(stderr, _T("ExitWindowsEx failed with error %d\n"), (int) GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -29,14 +29,20 @@
|
|||
* DISCLAIMED. This includes but is not limited to warranties of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Revision: 1.10 $
|
||||
* $Author: royce $
|
||||
* $Date: 2003/08/11 00:04:05 $
|
||||
* $Revision: 1.11 $
|
||||
* $Author: gvg $
|
||||
* $Date: 2004/07/07 22:29:37 $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TCHAR_H_
|
||||
#define _TCHAR_H_
|
||||
#ifndef _ROS_TCHAR_H_
|
||||
#define _ROS_TCHAR_H_
|
||||
|
||||
#ifdef __USE_W32API
|
||||
|
||||
#include_next <tchar.h>
|
||||
|
||||
#else /* Not __USE_W32API */
|
||||
|
||||
#include <msvcrt/string.h>
|
||||
|
||||
|
@ -259,3 +265,4 @@ typedef char TCHAR;
|
|||
|
||||
#endif /* Not _TCHAR_H_ */
|
||||
|
||||
#endif /* Not __USE_W32API */
|
||||
|
|
Loading…
Reference in a new issue