root/trunk/txlib/txboot.c

Revision 1, 10.2 kB (checked in by jvw, 3 years ago)

Initial check-in for TxWin? version 1.02 sources

Line 
1//
2//                     TxWin, Textmode Windowing Library
3//
4//   Original code Copyright (c) 1995-2005 Fsys Software and Jan van Wijk
5//
6// ==========================================================================
7//
8// This file contains Original Code and/or Modifications of Original Code as
9// defined in and that are subject to the GNU Lesser General Public License.
10// You may not use this file except in compliance with the License.
11// BY USING THIS FILE YOU AGREE TO ALL TERMS AND CONDITIONS OF THE LICENSE.
12// A copy of the License is provided with the Original Code and Modifications,
13// and is also available at http://www.dfsee.com/txwin/lgpl.htm
14//
15// This library is free software; you can redistribute it and/or modify
16// it under the terms of the GNU Lesser General Public License as published
17// by the Free Software Foundation; either version 2.1 of the License,
18// or (at your option) any later version.
19//
20// This library is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23// See the GNU Lesser General Public License for more details.
24//
25// You should have received a copy of the GNU Lesser General Public License
26// along with this library; (lgpl.htm) if not, write to the Free Software
27// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28//
29// Questions on TxWin licensing can be directed to: txwin@fsys.nl
30//
31// ==========================================================================
32//
33// TxLib reboot functions
34//
35// 22-02-2001 JvW Added native NT API reboot
36// 30-08-2004 JvW Added native Linux  reboot
37
38#include <txlib.h>                              // TxLib interface
39
40#if   defined (LINUX)
41
42   #include <signal.h>
43
44#elif defined (DOS32)
45   #define DOS_REVECT_OFF    0x0000             // offset  DOS reboot vector
46   #define DOS_REVECT_SEG    0xffff             // segment DOS reboot vector
47
48#elif defined (WIN32)
49
50#define NTDLL_MODULENAME         "NTDLL.DLL"
51#define NTDLL_SHUTDOWNSYS        "NtShutdownSystem"
52
53typedef enum _SHUTDOWN_ACTION
54{
55   ShutdownNoReboot,
56   ShutdownReboot,
57   ShutdownPowerOff
58} SHUTDOWN_ACTION;
59
60//- Native NT shutdown (bypassing the WIN32 subsystem completely)
61#if defined (__WATCOMC__)
62typedef LONG (_System * NTSDS)(SHUTDOWN_ACTION ParAction);
63#else
64typedef LONG ( * NTSDS)(SHUTDOWN_ACTION ParAction);
65#endif
66#endif
67
68/*****************************************************************************/
69// Perform a shutdown (if possible) followed by a (COLD) boot of the system
70/*****************************************************************************/
71BOOL TxReboot                                   // RET   reboot OK
72(
73   BOOL                flush                    // IN    Flush buffers/FS-data
74)
75{
76   #if   defined (WIN32)
77      HANDLE           hToken;                  // handle to process token
78      TOKEN_PRIVILEGES tkp;                     // ptr to token structure
79      DWORD            Rc;
80      TXLN             ErrMsg;
81   #elif defined (DOS32)
82      union  REGS      regs;
83      struct SREGS     sreg;
84      TXDX_RMINFO      txdx_rmi;
85   #elif defined (LINUX)
86   #else                                        // OS/2 32 bit
87      HFILE            hf;                      // File Handle to DOS.SYS
88      ULONG            dummy;                   // Dummy used in DosOpen
89   #endif
90   FILE               *log;
91
92   ENTER();
93   TxPrint("\nAutomatic reboot ");
94
95   if ((log = TxQueryLogFile( NULL, NULL)) != NULL)
96   {
97      fprintf( log, "\nLogfile being closed automatically, just before forced reboot ...\n");
98      fclose(  log);
99   }
100   #if defined (WIN32)
101      //- Get current process token handle so we can get shutdown privilege.
102      if (OpenProcessToken(GetCurrentProcess(),
103                           TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
104                           &hToken))
105      {
106         //- Get the LUID for shutdown privilege, and get the privilege
107
108         LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
109
110         tkp.PrivilegeCount = 1;                // one privilege to set
111         tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
112
113         AdjustTokenPrivileges( hToken, FALSE, &tkp, 0,
114                               (PTOKEN_PRIVILEGES) NULL, 0);
115
116         if ((Rc = GetLastError()) == ERROR_SUCCESS)
117         {
118            HMODULE    hNTdll;
119            NTSDS      fnShutDown;
120            UINT       OldErrMode;
121
122            OldErrMode = SetErrorMode (SEM_FAILCRITICALERRORS);
123
124            if ((hNTdll = LoadLibrary( NTDLL_MODULENAME)) != 0)
125            {
126               fnShutDown = (NTSDS) GetProcAddress( hNTdll, NTDLL_SHUTDOWNSYS);
127
128               if (fnShutDown != NULL)
129               {
130                  TxPrint("in progress ...\n");
131
132                  //- Note: No-flush is not an option on Windows
133                  TxPrint("Flushing the filesystem, please wait ...\n");
134
135                  (void) (fnShutDown)(ShutdownReboot);
136               }
137               else
138               {
139                  TxPrint("not possible, no NtShutDownSystem entrypoint\n");
140               }
141               FreeLibrary( NTDLL_MODULENAME);
142            }
143            else
144            {
145               TxPrint("not possible, NTDLL not available\n");
146            }
147            SetErrorMode (OldErrMode);
148
149            //- Disable shutdown privilege, just to be nice
150            tkp.Privileges[0].Attributes = 0;
151            AdjustTokenPrivileges( hToken, FALSE, &tkp, 0,
152                                  (PTOKEN_PRIVILEGES) NULL, 0);
153         }
154         else
155         {
156            FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, Rc,
157                          (DWORD) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
158                           ErrMsg, 128, NULL);
159            TxPrint("not possible, probably insufficient rights:\n");
160            TxPrint("AdjustTokenPrivileges error: %s", ErrMsg);
161         }
162      }
163      else
164      {
165         Rc = GetLastError();
166         FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, Rc,
167                       (DWORD) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
168                        ErrMsg, 128, NULL);
169         TxPrint("not possible, probably insufficient rights:\n");
170         TxPrint("OpenProcessToken error: %s", ErrMsg);
171      }
172   #elif defined (DOS32)
173      TxPrint("in progress ...\n");
174
175      if (flush)
176      {
177         TxPrint("Flushing the filesystem, please wait ...\n");
178
179         memset( &regs,  0, sizeof(regs));
180         memset( &sreg,  0, sizeof(sreg));
181         memset( &txdx_rmi, 0, sizeof(txdx_rmi));
182
183         txdx_rmi.eax = 0x0d00;                 // Reset disk, usually hooked
184                                                // by cache-programs ...
185         regs.w.ax    = TXDX_DPMI_RMINT;        // simulate realmode INT
186         regs.h.bl    = 0x21;                   // DOS interrupt 21
187         regs.x.edi   = FP_OFF( &txdx_rmi);     // real mode register struct
188         sreg.es      = FP_SEG( &txdx_rmi);
189
190         txDpmiCall( &regs, &sreg);
191
192         TxSleep( 3000);                        // extra wait 3 seconds, flush
193      }
194
195      memset( &regs,  0, sizeof(regs));
196      memset( &sreg,  0, sizeof(sreg));
197      memset( &txdx_rmi, 0, sizeof(txdx_rmi));
198
199      txdx_rmi.cs  = (short) DOS_REVECT_SEG;    // CS:IP for reboot vector
200      txdx_rmi.ip  = (short) DOS_REVECT_OFF;
201
202      regs.w.ax    = TXDX_DPMI_RMFAR;           // simulate realmode FAR call
203      regs.x.edi   = FP_OFF( &txdx_rmi);        // real mode register struct
204      sreg.es      = FP_SEG( &txdx_rmi);
205
206      txDpmiCall( &regs, &sreg);
207   #elif defined (LINUX)
208      TxPrint("in progress ...\n");
209
210      if (flush)
211      {
212         TxPrint("Flushing the filesystem, please wait ...\n");
213         sync();                                // flush inodes & buffers
214         TxSleep( 1000);                        // allow another second ...
215      }
216      TxPrint( "Attempt automatic system shutdown and reboot ...\n");
217      if (kill( 1, SIGINT) == -1)               // interrupt INIT process
218      {
219         TxPrint( "\nError in 'kill': %s\n", strerror(errno));
220      }
221      if (errno == EPERM)
222      {
223         TxPrint( "\nYou need to have ROOT privileges for shutdown/reboot!\n");
224      }
225      else
226      {
227         TxSleep( 60000);                       // should be down after 60 secs
228      }
229   #else                                        // OS/2 32 bit
230      if (DosOpen("DOS$", &hf, &dummy, 0L,      // DOS.SYS with reboot IOctl
231                   FILE_NORMAL, FILE_OPEN,
232                   OPEN_ACCESS_WRITEONLY |      // must open BEFORE DosShutdown
233                   OPEN_SHARE_DENYNONE   |      // or the Open call will block!
234                   OPEN_FLAGS_FAIL_ON_ERROR,
235                   0L) == NO_ERROR)
236      {
237         TxPrint("in progress ...\n");
238
239         if (flush)
240         {
241            TxPrint("Flushing the filesystem, please wait ...\n");
242            DosShutdown(0L);                    // flush file-systems
243            TxSleep( 1000);                     // allow another second ...
244
245            //- printf NOT guaranteed to reach the screen, but usually does :-)
246            TxPrint( "Attempt automatic system shutdown and reboot ...\n");
247         }
248         DosDevIOCtl( hf, 0xd5, 0xab,           // reboot IOctl
249                      NULL, 0, NULL,
250                      NULL, 0, NULL);
251         DosClose(hf);                          // unreachable code :-)
252
253         if (!flush)                            // without the DosShutDown,
254         {                                      // processing will continue
255            TxSleep( 60000);                    // should be down after 60 secs
256         }
257      }
258      else
259      {
260         TxPrint("not possible!\n");
261         TxPrint("SYS1736: The DOS.SYS device driver cannot be found.\n");
262      }
263   #endif
264   TxPrint( "\nReboot the system manually to complete the function.\n");
265   BRETURN( FALSE);                             // should never get here ...
266}                                               // end 'TxReboot'
267/*---------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the browser.