From 9ef17eada6724eb141da6ec7a8408af683e74023 Mon Sep 17 00:00:00 2001 From: Emanuele Aliberti Date: Sun, 16 May 1999 07:27:35 +0000 Subject: [PATCH] A few system utilities that need fixing svn path=/trunk/; revision=475 --- rosapps/sysutils/chkdsk.c | 423 +++++++++++++++++++++++ rosapps/sysutils/chklib.c | 185 +++++++++++ rosapps/sysutils/config.h | 6 + rosapps/sysutils/fmifs.h | 129 +++++++ rosapps/sysutils/format.c | 646 ++++++++++++++++++++++++++++++++++++ rosapps/sysutils/makefile | 86 +++++ rosapps/sysutils/shutdown.c | 181 ++++++++++ rosapps/sysutils/win32err.c | 70 ++++ rosapps/sysutils/win32err.h | 12 + rosapps/sysutils/wmain.c | 52 +++ 10 files changed, 1790 insertions(+) create mode 100644 rosapps/sysutils/chkdsk.c create mode 100644 rosapps/sysutils/chklib.c create mode 100644 rosapps/sysutils/config.h create mode 100644 rosapps/sysutils/fmifs.h create mode 100644 rosapps/sysutils/format.c create mode 100644 rosapps/sysutils/makefile create mode 100644 rosapps/sysutils/shutdown.c create mode 100644 rosapps/sysutils/win32err.c create mode 100644 rosapps/sysutils/win32err.h create mode 100644 rosapps/sysutils/wmain.c diff --git a/rosapps/sysutils/chkdsk.c b/rosapps/sysutils/chkdsk.c new file mode 100644 index 00000000000..8b70216d587 --- /dev/null +++ b/rosapps/sysutils/chkdsk.c @@ -0,0 +1,423 @@ +//====================================================================== +// +// $Id: chkdsk.c,v 1.1 1999/05/16 07:27:35 ea Exp $ +// +// Chkdskx +// +// Copyright (c) 1998 Mark Russinovich +// Systems Internals +// http://www.sysinternals.com/ +// +// -------------------------------------------------------------------- +// +// This software is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this software; see the file COPYING.LIB. If +// not, write to the Free Software Foundation, Inc., 675 Mass Ave, +// Cambridge, MA 02139, USA. +// +// -------------------------------------------------------------------- +// +// Chkdsk clone that demonstrates the use of the FMIFS file system +// utility library. +// +// 1999 February (Emanuele Aliberti) +// Adapted for ReactOS and lcc-win32. +// +// 1999 April (Emanuele Aliberti) +// Adapted for ReactOS and egcs. +// +//====================================================================== +#define UNICODE +#include +#include +#include "fmifs.h" +#define _UNICODE 1 +#include +#include "config.h" +#include "win32err.h" + +// +// Globals +// +BOOL Error = FALSE; + +// switches +BOOL FixErrors = FALSE; +BOOL SkipClean = FALSE; +BOOL ScanSectors = FALSE; +BOOL Verbose = FALSE; +PWCHAR Drive = NULL; +WCHAR CurrentDirectory[1024]; + +#ifndef FMIFS_IMPORT_DLL +// +// FMIFS function +// +PCHKDSK Chkdsk; +#endif /* ndef FMIFS_IMPORT_DLL */ + + +//-------------------------------------------------------------------- +// +// CtrlCIntercept +// +// Intercepts Ctrl-C's so that the program can't be quit with the +// disk in an inconsistent state. +// +//-------------------------------------------------------------------- +BOOL +WINAPI +CtrlCIntercept( DWORD dwCtrlType ) +{ + // + // Handle the event so that the default handler doesn't + // + return TRUE; +} + + +//---------------------------------------------------------------------- +// +// Usage +// +// Tell the user how to use the program +// +// 19990216 EA Missing printf %s argument +//---------------------------------------------------------------------- +VOID +Usage( PWCHAR ProgramName ) +{ + _tprintf( + L"\ +Usage: %s [drive:] [-F] [-V] [-R] [-C]\n\n\ + [drive:] Specifies the drive to check.\n\ + -F Fixes errors on the disk.\n\ + -V Displays the full path of every file on the disk.\n\ + -R Locates bad sectors and recovers readable information.\n\ + -C Checks the drive only if it is dirty.\n\n", + ProgramName + ); +} + + +//---------------------------------------------------------------------- +// +// ParseCommandLine +// +// Get the switches. +// +//---------------------------------------------------------------------- +int +ParseCommandLine( + int argc, + WCHAR *argv [] + ) +{ + int i; + BOOLEAN gotFix = FALSE; + BOOLEAN gotVerbose = FALSE; + BOOLEAN gotClean = FALSE; + BOOLEAN gotScan = FALSE; + + + for ( i = 1; + (i < argc); + i++ + ) { + switch( argv[i][0] ) + { + case L'-': + case L'/': + + switch( argv[i][1] ) + { + case L'F': + case L'f': + + if( gotFix ) return i; + FixErrors = TRUE; + gotFix = TRUE; + break; + + case L'V': + case L'v': + + if( gotVerbose) return i; + Verbose = TRUE; + gotVerbose = TRUE; + break; + + case L'R': + case L'r': + + if( gotFix ) return i; + ScanSectors = TRUE; + gotFix = TRUE; + break; + + case L'C': + case L'c': + + if( gotClean ) return i; + SkipClean = TRUE; + gotClean = TRUE; + break; + + default: + return i; + } + break; + + default: + + if( Drive ) return i; + if( argv[i][1] != L':' ) return i; + + Drive = argv[i]; + break; + } + } + return 0; +} + + +//---------------------------------------------------------------------- +// +// ChkdskCallback +// +// The file system library will call us back with commands that we +// can interpret. If we wanted to halt the chkdsk we could return FALSE. +// +//---------------------------------------------------------------------- +BOOLEAN +__stdcall +ChkdskCallback( + CALLBACKCOMMAND Command, + DWORD Modifier, + PVOID Argument + ) +{ + PDWORD percent; + PBOOLEAN status; + PTEXTOUTPUT output; + + // + // We get other types of commands, + // but we don't have to pay attention to them + // + switch( Command ) + { + case PROGRESS: + percent = (PDWORD) Argument; + _tprintf(L"%d percent completed.\r", *percent); + break; + + case OUTPUT: + output = (PTEXTOUTPUT) Argument; + fprintf(stdout, "%s", output->Output); + break; + + case DONE: + status = (PBOOLEAN) Argument; + if( *status == TRUE ) { + + _tprintf(L"Chkdsk was unable to complete successfully.\n\n"); + Error = TRUE; + } + break; + } + return TRUE; +} + +#ifndef FMIFS_IMPORT_DLL +//---------------------------------------------------------------------- +// +// LoadFMIFSEntryPoints +// +// Loads FMIFS.DLL and locates the entry point(s) we are going to use +// +// 19990216 EA User wide functions +// +//---------------------------------------------------------------------- +BOOLEAN +LoadFMIFSEntryPoints(VOID) +{ + LoadLibraryW( L"fmifs.dll" ); + + if( !(Chkdsk = + (void *) GetProcAddress( + GetModuleHandleW(L"fmifs.dll"), + "Chkdsk" )) + ) + { + return FALSE; + } + return TRUE; +} +#endif /* ndef FMIFS_IMPORT_DLL */ + + +//---------------------------------------------------------------------- +// +// WMain +// +// Engine. Just get command line switches and fire off a chkdsk. This +// could also be done in a GUI like Explorer does when you select a +// drive and run a check on it. +// +// We do this in UNICODE because the chkdsk command expects PWCHAR +// arguments. +// +//---------------------------------------------------------------------- +int +wmain( int argc, WCHAR *argv[] ) +{ + int badArg; + HANDLE volumeHandle; + WCHAR fileSystem [1024]; + WCHAR volumeName [1024]; + DWORD serialNumber; + DWORD flags, + maxComponent; + + wprintf( + L"\n\ +Chkdskx v1.0 by Mark Russinovich\n\ +Systems Internals - http://www.sysinternals.com/\n\ +ReactOS adaptation 1999 by Emanuele Aliberti\n\n" + ); +#ifndef FMIFS_IMPORT_DLL + // + // Get function pointers + // + if( !LoadFMIFSEntryPoints()) + { + wprintf(L"Could not located FMIFS entry points.\n\n"); + return -1; + } +#endif /* ndef FMIFS_IMPORT_DLL */ + // + // Parse command line + // + if( (badArg = ParseCommandLine( argc, argv ))) + { + wprintf(L"Unknown argument: %s\n", argv[badArg] ); + + Usage(argv[0]); + return -1; + } + + // + // Get the drive's format + // + if( !Drive ) + { + if( !GetCurrentDirectoryW( + sizeof(CurrentDirectory), + CurrentDirectory + ) + ) { + + PrintWin32Error( + L"Could not get current directory", + GetLastError() + ); + return -1; + } + + } else { + + wcscpy( CurrentDirectory, Drive ); + } + CurrentDirectory[2] = L'\\'; + CurrentDirectory[3] = L'\0'; + Drive = CurrentDirectory; + + // + // Determine the drive's file system format, which we need to + // tell chkdsk + // + if( !GetVolumeInformationW( + Drive, + volumeName, + sizeof volumeName, + & serialNumber, + & maxComponent, + & flags, + fileSystem, + sizeof fileSystem + ) + ) { + PrintWin32Error( + L"Could not query volume", + GetLastError() + ); + return -1; + } + + // + // If they want to fix, we need to have access to the drive + // + if ( FixErrors ) + { + swprintf( + volumeName, + L"\\\\.\\%C:", + Drive[0] + ); + volumeHandle = CreateFileW( + volumeName, + GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + 0, + 0 + ); + if( volumeHandle == INVALID_HANDLE_VALUE ) + { + wprintf("Chdskx cannot run because the volume is in use by another process.\n\n"); + return -1; + } + CloseHandle( volumeHandle ); + + // + // Can't let the user break out of a chkdsk that can modify the drive + // + SetConsoleCtrlHandler( CtrlCIntercept, TRUE ); + } + + // + // Just do it + // + wprintf( + "The type of file system is %s.\n", + fileSystem + ); + Chkdsk( + Drive, + fileSystem, + FixErrors, + Verbose, + SkipClean, + ScanSectors, + NULL, + NULL, + ChkdskCallback + ); + + if ( Error ) return -1; + return 0; +} + +/* EOF */ diff --git a/rosapps/sysutils/chklib.c b/rosapps/sysutils/chklib.c new file mode 100644 index 00000000000..7eabbd51064 --- /dev/null +++ b/rosapps/sysutils/chklib.c @@ -0,0 +1,185 @@ +/* $Id: chklib.c,v 1.1 1999/05/16 07:27:35 ea Exp $ + * + * chklib.c + * + * Copyright (C) 1998, 1999 Emanuele Aliberti. + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; see the file COPYING.LIB. If + * not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------- + * Check a PE DLL for loading and get an exported symbol's address + * (relocated). + * + */ +//#define UNICODE +#include +#include +#include +#include +#include "win32err.h" + +#ifdef DISPLAY_VERSION +static +void +DisplayVersion( + HANDLE dll, + PCHAR ModuleName + ) +{ + DWORD Zero; + DWORD Size; + PVOID vi = NULL; + + assert(ModuleName); + Size = GetFileVersionInfoSize( + ModuleName, + & Zero + ); + if (Size == 0) + { + PrintWin32Error( + L"GetFileVersionInfoSize", + GetLastError() + ); + return; + } + vi = (PVOID) LocalAlloc(LMEM_ZEROINIT,Size); + if (!vi) return; + assert(dll != INVALID_HANDLE_VALUE); + if (0 == GetFileVersionInfo( + ModuleName, + (DWORD) dll, + Size, + vi + ) + ) { + PrintWin32Error( + L"GetFileVersionInfo", + GetLastError() + ); + return; + } +/* + VerQueryValue( + vi, + L"\\StringFileInfo\\040904E4\\FileDescription", + & lpBuffer, + & dwBytes + ); +*/ + LocalFree(vi); +} +#endif /* def DISPLAY_VERSION */ + + +static +void +DisplayEntryPoint( + const HANDLE dll, + LPCSTR SymbolName + ) +{ + FARPROC EntryPoint; + + printf( + "[%s]\n", + SymbolName + ); + EntryPoint = GetProcAddress( + dll, + SymbolName + ); + if (!EntryPoint) + { + PrintWin32Error( + L"GetProcAddress", + GetLastError() + ); + return; + } + printf( + "%08X %s\n", + EntryPoint, + SymbolName + ); +} + + +/* --- MAIN --- */ + + +int +main( + int argc, + char * argv [] + ) +{ + HINSTANCE dll; + TCHAR ModuleName [_MAX_PATH]; + + if (argc != 2 && argc != 3) + { + fprintf( + stderr, + "\ +ReactOS System Tools\n\ +Check a Dynamic Link Library (DLL) for loading\n\ +Copyright (c) 1998, 1999 Emanuele Aliberti\n\n\ +usage: %s module [symbol]\n", + argv[0] + ); + exit(EXIT_FAILURE); + } + dll = LoadLibraryA(argv[1]); + if (!dll) + { + UINT LastError; + + LastError = GetLastError(); + PrintWin32Error(L"LoadLibrary",LastError); + fprintf( + stderr, + "%s: loading %s failed (%d).\n", + argv[0], + argv[1], + LastError + ); + exit(EXIT_FAILURE); + } + GetModuleFileName( + (HANDLE) dll, + ModuleName, + sizeof ModuleName + ); + printf( + "%s loaded.\n", + ModuleName + ); +#ifdef DISPLAY_VERSION + DisplayVersion(dll,ModuleName); +#endif + if (argc == 3) DisplayEntryPoint( dll, argv[2] ); + FreeLibrary(dll); + printf( + "%s unloaded.\n", + ModuleName + ); + return EXIT_SUCCESS; +} + +/* EOF */ diff --git a/rosapps/sysutils/config.h b/rosapps/sysutils/config.h new file mode 100644 index 00000000000..ec062df0dff --- /dev/null +++ b/rosapps/sysutils/config.h @@ -0,0 +1,6 @@ +#ifndef _INC_CONFIG_H +#define _INC_CONFIG_H +/* $Id: config.h,v 1.1 1999/05/16 07:27:35 ea Exp $ */ +#define FMIFS_IMPORT_DLL +#define REACTOS_NO_SECURITY_SS +#endif /* ndef _INC_CONFIG_H */ diff --git a/rosapps/sysutils/fmifs.h b/rosapps/sysutils/fmifs.h new file mode 100644 index 00000000000..1d448fabf8b --- /dev/null +++ b/rosapps/sysutils/fmifs.h @@ -0,0 +1,129 @@ +#ifndef _FMIFS_H +#define _FMIFS_H +/* $Id: fmifs.h,v 1.1 1999/05/16 07:27:35 ea Exp $ + * + * fmifs.h + * + * Copyright (c) 1998 Mark Russinovich + * Systems Internals + * http://www.sysinternals.com + * + * Typedefs and definitions for using chkdsk and formatex + * functions exported by the fmifs.dll library. + * + * --- + * + * 1999-02-18 (Emanuele Aliberti) + * Normalized function names. + * + */ +#ifndef _INC_WINDOWS_ +#include +#endif + +/* Output command */ +typedef +struct +{ + DWORD Lines; + PCHAR Output; + +} TEXTOUTPUT, *PTEXTOUTPUT; + + +/* Callback command types */ +typedef +enum +{ + PROGRESS, + DONEWITHSTRUCTURE, + UNKNOWN2, + UNKNOWN3, + UNKNOWN4, + UNKNOWN5, + INSUFFICIENTRIGHTS, + UNKNOWN7, + UNKNOWN8, + UNKNOWN9, + UNKNOWNA, + DONE, + UNKNOWNC, + UNKNOWND, + OUTPUT, + STRUCTUREPROGRESS + +} CALLBACKCOMMAND; + + +/* FMIFS callback definition */ +typedef +BOOL +(STDCALL * PFMIFSCALLBACK) ( + CALLBACKCOMMAND Command, + DWORD SubAction, + PVOID ActionInfo + ); + +/* Chkdsk command in FMIFS */ +VOID +STDCALL +ChkDsk( + PWCHAR DriveRoot, + PWCHAR Format, + BOOL CorrectErrors, + BOOL Verbose, + BOOL CheckOnlyIfDirty, + BOOL ScanDrive, + PVOID Unused2, + PVOID Unused3, + PFMIFSCALLBACK Callback + ); + +/* ChkdskEx command in FMIFS (not in the original) */ +VOID +STDCALL +ChkDskEx( + PWCHAR DriveRoot, + PWCHAR Format, + BOOL CorrectErrors, + BOOL Verbose, + BOOL CheckOnlyIfDirty, + BOOL ScanDrive, + PVOID Unused2, + PVOID Unused3, + PFMIFSCALLBACK Callback + ); + +/* DiskCopy command in FMIFS */ + +VOID +STDCALL +DiskCopy(VOID); + +/* Enable/Disable volume compression */ +BOOL +STDCALL +EnableVolumeCompression( + PWCHAR DriveRoot, + BOOL Enable + ); + +/* Format command in FMIFS */ + +/* media flags */ +#define FMIFS_HARDDISK 0xC +#define FMIFS_FLOPPY 0x8 + +VOID +STDCALL +FormatEx( + PWCHAR DriveRoot, + DWORD MediaFlag, + PWCHAR Format, + PWCHAR Label, + BOOL QuickFormat, + DWORD ClusterSize, + PFMIFSCALLBACK Callback + ); + +#endif /* ndef _FMIFS_H */ diff --git a/rosapps/sysutils/format.c b/rosapps/sysutils/format.c new file mode 100644 index 00000000000..457a79961d4 --- /dev/null +++ b/rosapps/sysutils/format.c @@ -0,0 +1,646 @@ +//====================================================================== +// +// $Id: format.c,v 1.1 1999/05/16 07:27:35 ea Exp $ +// +// Formatx +// +// Copyright (c) 1998 Mark Russinovich +// Systems Internals +// http://www.sysinternals.com/ +// +// This software is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this software; see the file COPYING.LIB. If +// not, write to the Free Software Foundation, Inc., 675 Mass Ave, +// Cambridge, MA 02139, USA. +// +// --------------------------------------------------------------------- +// Format clone that demonstrates the use of the FMIFS file system +// utility library. +// +// 1999 February (Emanuele Aliberti) +// Adapted for ReactOS and lcc-win32. +// +// 1999 April (Emanuele Aliberti) +// Adapted for ReactOS and egcs. +// +//====================================================================== +#define UNICODE 1 +#define _UNICODE 1 +#include +#include +#include "fmifs.h" +//#include +#include "win32err.h" +#include "config.h" + +#define WBUFSIZE(b) (sizeof(b) / sizeof (wchar_t)) + + +// +// Globals +// +BOOL Error = FALSE; + +// switches +BOOL QuickFormat = FALSE; +DWORD ClusterSize = 0; +BOOL CompressDrive = FALSE; +BOOL GotALabel = FALSE; +PWCHAR Label = L""; +PWCHAR Drive = NULL; +PWCHAR Format = L"FAT"; + +WCHAR RootDirectory [MAX_PATH]; +WCHAR LabelString [12]; + +#ifndef FMIFS_IMPORT_DLL +// +// Functions in FMIFS.DLL +// +PFORMATEX FormatEx; +PENABLEVOLUMECOMPRESSION EnableVolumeCompression; +#endif /* ndef FMIFS_IMPORT_DLL */ + +// +// Size array +// +typedef +struct +{ + WCHAR SizeString [16]; + DWORD ClusterSize; + +} SIZEDEFINITION, *PSIZEDEFINITION; + + +SIZEDEFINITION +LegalSizes [] = +{ + { L"512", 512 }, + { L"1024", 1024 }, + { L"2048", 2048 }, + { L"4096", 4096 }, + { L"8192", 8192 }, + { L"16K", 16384 }, + { L"32K", 32768 }, + { L"64K", 65536 }, + { L"128K", 65536 * 2 }, + { L"256K", 65536 * 4 }, + { L"", 0 }, +}; + + +//---------------------------------------------------------------------- +// +// Usage +// +// Tell the user how to use the program +// +// 1990218 EA ProgramName missing in wprintf arg list +// +//---------------------------------------------------------------------- +VOID +Usage( PWCHAR ProgramName ) +{ + wprintf( + L"\ +Usage: %s drive: [-FS:file-system] [-V:label] [-Q] [-A:size] [-C]\n\n\ + [drive:] Specifies the drive to format.\n\ + -FS:file-system Specifies the type of file system (e.g. FAT).\n\ + -V:label Specifies volume label.\n\ + -Q Performs a quick format.\n\ + -A:size Overrides the default allocation unit size. Default settings\n\ + are strongly recommended for general use\n\ + NTFS supports 512, 1024, 2048, 4096, 8192, 16K, 32K, 64K.\n\ + FAT supports 8192, 16K, 32K, 64K, 128K, 256K.\n\ + NTFS compression is not supported for allocation unit sizes\n\ + above 4096.\n\ + -C Files created on the new volume will be compressed by\n\ + default.\n\n", + ProgramName + ); +} + + +//---------------------------------------------------------------------- +// +// ParseCommandLine +// +// Get the switches. +// +// 19990218 EA switch characters '-' and '/' are wide +// +//---------------------------------------------------------------------- +int +ParseCommandLine( + int argc, + WCHAR *argv [] + ) +{ + int i, + j; + BOOLEAN gotFormat = FALSE; + BOOLEAN gotQuick = FALSE; + BOOLEAN gotSize = FALSE; + BOOLEAN gotLabel = FALSE; + BOOLEAN gotCompressed = FALSE; + + + for ( + i = 1; + (i < argc); + i++ + ) { + switch ( argv[i][0] ) + { + + case L'-': + case L'/': + + if( !wcsnicmp( & argv[i][1], L"FS:", 3 )) + { + if( gotFormat) return -1; + Format = & argv[i][4]; + gotFormat = TRUE; + } + else if( !wcsnicmp( & argv[i][1], L"A:", 2 )) + { + if ( gotSize ) return -1; + j = 0; + while ( LegalSizes[j].ClusterSize && + wcsicmp( + LegalSizes[j].SizeString, + & argv[i][3] + ) + ) { + j++; + } + if( !LegalSizes[j].ClusterSize ) return i; + ClusterSize = LegalSizes[j].ClusterSize; + gotSize = TRUE; + } + else if( !wcsnicmp( & argv[i][1], L"V:", 2 )) + { + if( gotLabel ) return -1; + Label = & argv[i][3]; + gotLabel = TRUE; + GotALabel = TRUE; + } + else if ( !wcsicmp( & argv[i][1], L"Q" )) + { + if( gotQuick ) return -1; + QuickFormat = TRUE; + gotQuick = TRUE; + } + else if ( !wcsicmp( & argv[i][1], L"C" )) + { + if( gotCompressed ) return -1; + CompressDrive = TRUE; + gotCompressed = TRUE; + } + else + { + return i; + } + break; + + default: + + if ( Drive ) return i; + if ( argv[i][1] != L':' ) return i; + + Drive = argv[i]; + break; + } + } + return 0; +} + + +//---------------------------------------------------------------------- +// +// FormatExCallback +// +// The file system library will call us back with commands that we +// can interpret. If we wanted to halt the chkdsk we could return FALSE. +// +//---------------------------------------------------------------------- +BOOLEAN +__stdcall +FormatExCallback( + CALLBACKCOMMAND Command, + DWORD Modifier, + PVOID Argument + ) +{ + PDWORD percent; + PTEXTOUTPUT output; + PBOOLEAN status; + //static createStructures = FALSE; + + // + // We get other types of commands, but we don't have to pay attention to them + // + switch ( Command ) + { + case PROGRESS: + percent = (PDWORD) Argument; + wprintf(L"%d percent completed.\r", *percent); + break; + + case OUTPUT: + output = (PTEXTOUTPUT) Argument; + fprintf(stdout, "%s", output->Output); + break; + + case DONE: + status = (PBOOLEAN) Argument; + if ( *status == FALSE ) + { + wprintf(L"FormatEx was unable to complete successfully.\n\n"); + Error = TRUE; + } + break; + } + return TRUE; +} + + +#ifndef FMIFS_IMPORT_DLL +//---------------------------------------------------------------------- +// +// LoadFMIFSEntryPoints +// +// Loads FMIFS.DLL and locates the entry point(s) we are going to use +// +// 19990216 EA ANSI strings in LoadFMIFSEntryPoints should be +// wide strings +// +//---------------------------------------------------------------------- +BOOLEAN +LoadFMIFSEntryPoints(VOID) +{ + LoadLibraryW( L"fmifs.dll" ); + + if ( !(FormatEx = + (void *) GetProcAddress( + GetModuleHandleW( L"fmifs.dll"), + "FormatEx" + ) + ) + ) { + return FALSE; + } + if ( !(EnableVolumeCompression = + (void *) GetProcAddress( + GetModuleHandleW( L"fmifs.dll"), + "EnableVolumeCompression" + ) + ) + ) { + return FALSE; + } + return TRUE; +} +#endif /* ndef FMIFS_IMPORT_DLL */ + + +//---------------------------------------------------------------------- +// +// WMain +// +// Engine. Just get command line switches and fire off a format. This +// could also be done in a GUI like Explorer does when you select a +// drive and run a check on it. +// +// We do this in UNICODE because the chkdsk command expects PWCHAR +// arguments. +// +//---------------------------------------------------------------------- +int +wmain( int argc, WCHAR *argv[] ) +{ + int badArg; + + DWORD media; + DWORD driveType; + + WCHAR fileSystem [1024]; + WCHAR volumeName [1024]; + WCHAR input [1024]; + + DWORD serialNumber; + DWORD flags, + maxComponent; + + ULARGE_INTEGER freeBytesAvailableToCaller, + totalNumberOfBytes, + totalNumberOfFreeBytes; + + + wprintf( L"\ +\nFormatx v1.0 by Mark Russinovich\n\ +Systems Internals - http://www.sysinternals.com\n\ +ReactOs adaptation 1999 by Emanuele Aliberti\n\n" + ); + +#ifndef FMIFS_IMPORT_DLL + // + // Get function pointers + // + if( !LoadFMIFSEntryPoints()) + { + wprintf(L"Could not located FMIFS entry points.\n\n"); + return -1; + } +#endif /* ndef FMIFS_IMPORT_DLL */ + // + // Parse command line + // + if( (badArg = ParseCommandLine( argc, argv ))) + { + wprintf( + L"Unknown argument: %s\n", + argv[badArg] + ); + Usage(argv[0]); + return -1; + } + // + // Get the drive's format + // + if( !Drive ) + { + wprintf(L"Required drive parameter is missing.\n\n"); + Usage( argv[0] ); + return -1; + } + else + { + wcscpy( RootDirectory, Drive ); + } + RootDirectory[2] = L'\\'; + RootDirectory[3] = L'\0'; + // + // See if the drive is removable or not + // + driveType = GetDriveTypeW( RootDirectory ); + if ( driveType != DRIVE_FIXED ) + { + wprintf( + L"Insert a new floppy in drive %C:\nand press Enter when ready...", + RootDirectory[0] + ); + fgetws( + input, + WBUFSIZE(input), + stdin + ); + media = FMIFS_FLOPPY; + } + // + // Determine the drive's file system format + // + if ( !GetVolumeInformationW( + RootDirectory, + volumeName, + WBUFSIZE(volumeName), + & serialNumber, + & maxComponent, + & flags, + fileSystem, + WBUFSIZE(fileSystem) ) + ) { + PrintWin32Error( + L"Could not query volume", + GetLastError() + ); + return -1; + } + if( !GetDiskFreeSpaceExW( + RootDirectory, + & freeBytesAvailableToCaller, + & totalNumberOfBytes, + & totalNumberOfFreeBytes ) + ) + { + PrintWin32Error( + L"Could not query volume size", + GetLastError() + ); + return -1; + } + wprintf( + L"The type of the file system is %s.\n", + fileSystem + ); + // + // Make sure they want to do this + // + if ( driveType == DRIVE_FIXED ) + { + if ( volumeName[0] ) + { + while (1) + { + wprintf( + L"Enter current volume label for drive %C: ", + RootDirectory[0] + ); + fgetws( + input, + WBUFSIZE(input), + stdin + ); + input[ wcslen( input ) - 1 ] = 0; + + if ( !wcsicmp( input, volumeName )) + { + break; + } + wprintf(L"An incorrect volume label was entered for this drive.\n"); + } + } + while ( 1 ) + { + wprintf(L"\nWARNING, ALL DATA ON NON_REMOVABLE DISK\n"); + wprintf(L"DRIVE %C: WILL BE LOST!\n", RootDirectory[0] ); + wprintf(L"Proceed with Format (Y/N)? " ); + fgetws( + input, + WBUFSIZE(input), + stdin + ); + if ( (input[0] == L'Y') || (input[0] == L'y') ) break; + + if ( (input[0] == L'N') || (input[0] == L'n') ) + { + wprintf(L"\n"); + return 0; + } + } + media = FMIFS_HARDDISK; + } + // + // Tell the user we're doing a long format if appropriate + // + if ( !QuickFormat ) + { + if ( totalNumberOfBytes.QuadPart > 1024*1024*10 ) + { + + wprintf( + L"Verifying %dM\n", + (DWORD) (totalNumberOfBytes.QuadPart/(1024*1024)) + ); + } + else + { + wprintf( + L"Verifying %.1fM\n", + ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0) + ); + } + } + else + { + if ( totalNumberOfBytes.QuadPart > 1024*1024*10 ) + { + wprintf( + L"QuickFormatting %dM\n", + (DWORD) (totalNumberOfBytes.QuadPart / (1024 * 1024)) + ); + } + else + { + wprintf( + L"QuickFormatting %.2fM\n", + ((float)(LONGLONG)totalNumberOfBytes.QuadPart) / (float)(1024.0*1024.0) + ); + } + wprintf(L"Creating file system structures.\n"); + } + // + // Format away! + // + FormatEx( + RootDirectory, + media, + Format, + Label, + QuickFormat, + ClusterSize, + FormatExCallback + ); + if ( Error ) return -1; + wprintf(L"Format complete.\n"); + // + // Enable compression if desired + // + if ( CompressDrive ) + { + if( !EnableVolumeCompression( RootDirectory, TRUE )) + { + wprintf(L"Volume does not support compression.\n"); + } + } + // + // Get the label if we don't have it + // + if( !GotALabel ) + { + wprintf(L"Volume Label (11 characters, Enter for none)? " ); + fgetws( + input, + WBUFSIZE(LabelString), + stdin + ); + + input[ wcslen(input) - 1 ] = 0; + if( !SetVolumeLabelW( RootDirectory, input )) + { + PrintWin32Error( + L"Could not label volume", + GetLastError() + ); + return -1; + } + } + if ( !GetVolumeInformationW( + RootDirectory, + volumeName, + WBUFSIZE(volumeName), + & serialNumber, + & maxComponent, + & flags, + fileSystem, + WBUFSIZE(fileSystem) ) + ) { + PrintWin32Error( + L"Could not query volume", + GetLastError() + ); + return -1; + } + // + // Print out some stuff including the formatted size + // + if ( !GetDiskFreeSpaceExW( + RootDirectory, + & freeBytesAvailableToCaller, + & totalNumberOfBytes, + & totalNumberOfFreeBytes ) + ) { + PrintWin32Error( + L"Could not query volume size", + GetLastError() + ); + return -1; + } + wprintf( + L"\n%I64d bytes total disk space.\n", + totalNumberOfBytes.QuadPart + ); + wprintf( + L"%I64d bytes available on disk.\n", + totalNumberOfFreeBytes.QuadPart + ); + // + // Get the drive's serial number + // + if ( !GetVolumeInformationW( + RootDirectory, + volumeName, + WBUFSIZE(volumeName), + & serialNumber, + & maxComponent, + & flags, + fileSystem, + WBUFSIZE(fileSystem) ) + ) { + PrintWin32Error( + L"Could not query volume", + GetLastError() + ); + return -1; + } + wprintf( + L"\nVolume Serial Number is %04X-%04X\n", + serialNumber >> 16, + serialNumber & 0xFFFF + ); + return 0; +} + + +/* EOF */ diff --git a/rosapps/sysutils/makefile b/rosapps/sysutils/makefile new file mode 100644 index 00000000000..8b1ed644bd3 --- /dev/null +++ b/rosapps/sysutils/makefile @@ -0,0 +1,86 @@ +# $Id: makefile,v 1.1 1999/05/16 07:27:35 ea Exp $ +# +# ReactOS System Utilities +# +# 1999-02-16 (Emanuele Aliberti) +# Added chkdskx.c and formatx.c by by Mark Russinovich +# (mark@sysinternals.com) and shutdown.c +# +# 1999-03-03 (Emanuele Aliberti) +# Added login.c and chklib.c +# +# 1999-03-16 (Emanuele Aliberti) +# Added regnav.c +# + +ROSINC=../../reactos/include + +all: chkdsk.exe format.exe \ + chklib.exe shutdown.exe regnav.exe +# login.exe chklib.exe shutdown.exe regnav.exe + +# By Mark Russinovich + +chkdsk.exe: chkdsk.o win32err.o wmain.o + $(CC) chkdsk.o win32err.o wmain.o \ + -o chkdsk.exe \ + -lkernel32 \ + -lcrtdll \ + -lfmifs + $(NM) --numeric-sort chkdsk.exe > chkdsk.sym + +format.exe: format.o win32err.o wmain.o + $(CC) format.o win32err.o wmain.o \ + -o format.exe \ + -lkernel32 \ + -lcrtdll \ + -lfmifs + $(NM) --numeric-sort format.exe > format.sym +#--- + +#login.exe: login.o +# $(CC) login.o \ +# -o login.exe \ +# -lntdll \ +# -Wl,--subsystem native:4.0 +# $(NM) --numeric-sort login.exe > login.sym + +chklib.exe: chklib.o win32err.o + $(CC) chklib.o win32err.o \ + -o chklib.exe \ + -lkernel32 \ + -lcrtdll + $(NM) --numeric-sort chklib.exe > chklib.sym + + +regnav.exe: regnav.o + $(CC) regnav.o \ + -o regnav.exe \ + -lkernel32 \ + -lcrtdll + $(NM) --numeric-sort regnav.exe > regnav.sym + + +shutdown.exe: shutdown.o win32err.o + $(CC) shutdown.o win32err.o \ + -o shutdown.exe \ + -lkernel32 \ + -luser32 \ + -lcrtdll + $(NM) --numeric-sort shutdown.exe > shutdown.sym + +#--- + +CLEAN_FILES = *.o *.exe *.sym + +clean: $(CLEAN_FILES:%=%_clean) + +$(CLEAN_FILES:%=%_clean): %_clean: + - $(RM) $* + +.phony: clean $(CLEAN_FILES:%=%_clean) + + +include ../rules.mak + +# EOF diff --git a/rosapps/sysutils/shutdown.c b/rosapps/sysutils/shutdown.c new file mode 100644 index 00000000000..b5696eebfcc --- /dev/null +++ b/rosapps/sysutils/shutdown.c @@ -0,0 +1,181 @@ +/* $Id: shutdown.c,v 1.1 1999/05/16 07:27:35 ea Exp $ + * + * EAU shutdown.c 1.4.1 + * + * Copyright (C) 1997,1998,1999 Emanuele Aliberti + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; see the file COPYING.LIB. If + * not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------- + * 1999-05-14 (Emanuele Aliberti) + * Released version 1.4.1 under GNU GPL for the ReactOS project. + * -------------------------------------------------------------------- + */ +#define UNICODE +#define _UNICODE +#include +#include +#include +#include +#include "win32err.h" + + +struct _EWX +{ + CHAR mode; + UINT id; +}; + +static +struct _EWX modes[] = +{ + { 'f', EWX_FORCE }, + { 'l', EWX_LOGOFF }, + { 'p', EWX_POWEROFF }, + { 'r', EWX_REBOOT }, + { 's', EWX_SHUTDOWN }, + { 0, 0 } +}; + + +static +UINT +DecodeArg( CHAR * modestr ) +{ + register int i; + + if (modestr[0] != '-' && modestr[0] != '/') + { + return (UINT) -1; + } + for ( i = 0; modes[i].mode; ++i) + { + if (modestr[1] == modes[i].mode) + { + return modes[i].id; + } + } + return (UINT) -1; +} + + + +static +const +char * usage = "\ +Shutdown ver. 1.4.1 (compiled on %s, at %s)\n\ +Copyright (C) 1997-1999 Emanuele Aliberti\n\n\ +usage: %s [-f] [-l] [-p] [-r] [-s]\n\ + f (FORCE) processes are unconditionally terminated\n\ + l (LOGOFF) logs the current user off\n\ + p (POWEROFF) turns off the power, if possibile\n\ + r (REBOOT) reboots the system\n\ + s (SHUTDOWN) shuts down the system to a point at which\n\ + it is safe to turn off the power\n\n\ + Any other letter will print this help message.\n"; + +int +main( + int argc, + char * argv [] + ) +{ + UINT mode; + HANDLE h; + TOKEN_PRIVILEGES tp; + + mode = (argc == 2) + ? DecodeArg(argv[1]) + : DecodeArg("-?"); + if (mode == (UINT) -1) + { + fprintf( + stderr, + usage, + __DATE__, + __TIME__, + argv[0] + ); + return EXIT_SUCCESS; + } + /* + * Get the current process token handle + * so we can get shutdown privilege. + */ + if (FALSE == OpenProcessToken( + GetCurrentProcess(), + (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), + & h + ) + ) { + PrintWin32Error( + L"while opening the process", + GetLastError() + ); + return EXIT_FAILURE; + } + /* + * Get the LUID for shutdown privilege. + */ + if (FALSE == LookupPrivilegeValue( + NULL, + SE_SHUTDOWN_NAME, + & tp.Privileges[0].Luid + ) + ) { + PrintWin32Error( + L"while looking up privileges", + GetLastError() + ); + return EXIT_FAILURE; + } + tp.PrivilegeCount = 1; /* One privilege to seat */ + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + /* + * Get shutdown privilege for this process. + */ + if (FALSE == AdjustTokenPrivileges( + h, + FALSE, + & tp, + 0, + (PTOKEN_PRIVILEGES) NULL, + 0 + ) + ) { + PrintWin32Error( + L"while adjusting shutdown privilege", + GetLastError() + ); + return EXIT_FAILURE; + } + /* Now really exit! */ + if (FALSE == ExitWindowsEx(mode, 0)) + { + PrintWin32Error( + L"ExitWindowsEx", + GetLastError() + ); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + + +/* EOF */ + diff --git a/rosapps/sysutils/win32err.c b/rosapps/sysutils/win32err.c new file mode 100644 index 00000000000..421bdd87f64 --- /dev/null +++ b/rosapps/sysutils/win32err.c @@ -0,0 +1,70 @@ +/* $Id: win32err.c,v 1.1 1999/05/16 07:27:35 ea Exp $ + * + * win32err.c + * + * Copyright (c) 1998 Mark Russinovich + * Systems Internals + * http://www.sysinternals.com/ + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; see the file COPYING.LIB. If + * not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * Print a Win32 error. + * + * 1999 February (Emanuele Aliberti) + * Taken from chkdskx.c and formatx.c by Mark Russinovich + * to be used in all sysutils. + */ +#include +#include + +//---------------------------------------------------------------------- +// +// PrintWin32Error +// +// Takes the win32 error code and prints the text version. +// +//---------------------------------------------------------------------- +void +PrintWin32Error( + PWCHAR Message, + DWORD ErrorCode + ) +{ + LPVOID lpMsgBuf; + + FormatMessageW( + (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM), + NULL, + ErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (PWCHAR) & lpMsgBuf, + 0, + NULL + ); + wprintf( + L"%s: %s\n", + Message, + lpMsgBuf + ); + LocalFree( lpMsgBuf ); +} + + +/* EOF */ diff --git a/rosapps/sysutils/win32err.h b/rosapps/sysutils/win32err.h new file mode 100644 index 00000000000..0b60784587f --- /dev/null +++ b/rosapps/sysutils/win32err.h @@ -0,0 +1,12 @@ +#ifndef _INC_WIN32ERR_H +#define _INC_WIN32ERR_H +/* $Id: win32err.h,v 1.1 1999/05/16 07:27:35 ea Exp $ */ +#ifndef _GNU_H_WINDOWS_H +#include +#endif /* ndef _GNU_H_WINDOWS_H */ +VOID +PrintWin32Error( + PWCHAR Message, + DWORD ErrorCode + ); +#endif /* ndef _INC_WIN32ERR_H */ diff --git a/rosapps/sysutils/wmain.c b/rosapps/sysutils/wmain.c new file mode 100644 index 00000000000..b86dffaf8a5 --- /dev/null +++ b/rosapps/sysutils/wmain.c @@ -0,0 +1,52 @@ +/* $Id: wmain.c,v 1.1 1999/05/16 07:27:35 ea Exp $ + * + * Entry point for programs that use wmain() + */ +#include +#include + +int wmain(int argc,wchar_t *argv[]); + +wchar_t * +a2w( char * a, wchar_t * w ) +{ + wchar_t * ww = w; + while (*a) *w++ = (wchar_t) *a++; + *w = 0; + return ww; +} + +wchar_t * +fgetws(wchar_t *buf, int bufsize, FILE *file) +{ + char * abuf = GlobalAlloc(bufsize,0); + if (!buf)return NULL; + fgets(abuf,bufsize,file); + a2w(abuf,buf); + GlobalFree(abuf); + return buf; +} + +int main(int argc, char *argv[]) +{ + wchar_t ** wargv; + int i; + int ec; + + wargv = (wchar_t **) GlobalAlloc( + sizeof(void*) * argc, + 0 + ); + for(i=0;i